/*
* Copyright (c) 2003 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @file
* libavformat API example.
*
* Output a media file in any supported libavformat format.
* The default codecs are used.
* @example doc/examples/muxing.c
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
/* 5 seconds stream duration */
#define STREAM_DURATION 200.0
#define STREAM_FRAME_RATE 25 /* 25 images/s */
#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
/* Add an output stream. */
{
/* find the encoder */
if (!(*codec)) {
fprintf(stderr, "Could not find encoder for '%s'\n",
exit(1);
}
if (!st) {
fprintf(stderr, "Could not allocate stream\n");
exit(1);
}
switch ((*codec)->type) {
break;
/* Resolution must be a multiple of two. */
/* timebase: This is the fundamental unit of time (in seconds) in terms
* of which frame timestamps are represented. For fixed-fps content,
* timebase should be 1/framerate and timestamp increments should be
* identical to 1. */
c->
gop_size = 12;
/* emit one intra frame every twelve frames at most */
/* just for testing, we also add B frames */
}
/* Needed to avoid using macroblocks in which some coeffs overflow.
* This does not happen with normal video, it just happens here as
* the motion of the chroma plane does not match the luma plane. */
}
break;
default:
break;
}
/* Some formats want stream headers to be separate. */
return st;
}
/**************************************************************/
/* audio output */
{
/* open it */
if (ret < 0) {
fprintf(stderr,
"Could not open audio codec: %s\n",
av_err2str(ret));
exit(1);
}
/* init signal generator */
/* increment frequency by 110 Hz per second */
if (ret < 0) {
fprintf(stderr, "Could not allocate source samples\n");
exit(1);
}
/* create resampler context */
if (!swr_ctx) {
fprintf(stderr, "Could not allocate resampler context\n");
exit(1);
}
/* set options */
/* initialize the resampling context */
fprintf(stderr, "Failed to initialize the resampling context\n");
exit(1);
}
}
/* compute the number of converted samples: buffering is avoided
* ensuring that the output buffer will contain at least all the
* converted input samples */
if (ret < 0) {
fprintf(stderr, "Could not allocate destination samples\n");
exit(1);
}
}
/* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
* 'nb_channels' channels. */
{
int16_t *q;
q = samples;
v = (int)(sin(
t) * 10000);
*q++ = v;
}
}
{
int got_packet,
ret, dst_nb_samples;
/* convert samples from native format to destination codec format, using the resampler */
if (swr_ctx) {
/* compute destination number of samples */
if (ret < 0)
exit(1);
}
/* convert to destination format */
if (ret < 0) {
fprintf(stderr, "Error while converting\n");
exit(1);
}
} else {
}
if (ret < 0) {
fprintf(stderr,
"Error encoding audio frame: %s\n",
av_err2str(ret));
exit(1);
}
if (!got_packet)
return;
/* Write the compressed frame to the media file. */
if (ret != 0) {
fprintf(stderr, "Error while writing audio frame: %s\n",
exit(1);
}
}
{
}
/**************************************************************/
/* video output */
{
/* open the codec */
if (ret < 0) {
fprintf(stderr,
"Could not open video codec: %s\n",
av_err2str(ret));
exit(1);
}
/* allocate and init a re-usable frame */
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
/* Allocate the encoded raw picture. */
if (ret < 0) {
fprintf(stderr,
"Could not allocate picture: %s\n",
av_err2str(ret));
exit(1);
}
/* If the output format is not YUV420P, then a temporary YUV420P
* picture is needed too. It is then converted to the required
* output format. */
if (ret < 0) {
fprintf(stderr, "Could not allocate temporary picture: %s\n",
exit(1);
}
}
/* copy data and linesize picture pointers to frame */
}
/* Prepare a dummy image. */
{
i = frame_index;
/* Y */
for (x = 0; x <
width; x++)
/* Cb and Cr */
for (y = 0; y < height / 2; y++) {
for (x = 0; x < width / 2; x++) {
}
}
}
{
/* No more frames to compress. The codec has a latency of a few
* frames if using B-frames, so we get the last frames by
* passing the same picture again. */
} else {
/* as we only generate a YUV420P picture, we must convert it
* to the codec pixel format if needed */
if (!sws_ctx) {
if (!sws_ctx) {
fprintf(stderr,
"Could not initialize the conversion context\n");
exit(1);
}
}
} else {
}
}
/* Raw video case - directly store the picture in the packet */
} else {
int got_packet;
/* encode the image */
if (ret < 0) {
fprintf(stderr,
"Error encoding video frame: %s\n",
av_err2str(ret));
exit(1);
}
/* If size is zero, it means the image was buffered. */
if (!ret && got_packet && pkt.
size) {
/* Write the compressed frame to the media file. */
} else {
ret = 0;
}
}
if (ret != 0) {
fprintf(stderr,
"Error while writing video frame: %s\n",
av_err2str(ret));
exit(1);
}
frame_count++;
}
{
}
/**************************************************************/
/* media file output */
int main(
int argc,
char **argv)
{
const char *filename;
AVCodec *audio_codec, *video_codec;
double audio_time, video_time;
/* Initialize libavcodec, and register all codecs and formats. */
if (argc != 2) {
printf("usage: %s output_file\n"
"API example program to output a media file with libavformat.\n"
"This program generates a synthetic audio and video stream, encodes and\n"
"muxes them into a file named output_file.\n"
"The output format is automatically guessed according to the file extension.\n"
"Raw images can also be output by using '%%d' in the filename.\n"
"\n", argv[0]);
return 1;
}
filename = argv[1];
/* allocate the output media context */
if (!oc) {
printf("Could not deduce output format from file extension: using MPEG.\n");
}
if (!oc) {
return 1;
}
/* Add the audio and video streams using the default format codecs
* and initialize the codecs. */
video_st = NULL;
audio_st = NULL;
}
}
/* Now that all the parameters are set, we can open the audio and
* video codecs and allocate the necessary encode buffers. */
if (video_st)
if (audio_st)
/* open the output file, if needed */
if (ret < 0) {
fprintf(stderr, "Could not open '%s': %s\n", filename,
return 1;
}
}
/* Write the stream header, if any. */
if (ret < 0) {
fprintf(stderr, "Error occurred when opening output file: %s\n",
return 1;
}
if (frame)
for (;;) {
/* Compute current audio and video time. */
break;
/* write interleaved audio and video frames */
if (!video_st || (video_st && audio_st && audio_time < video_time)) {
} else {
}
}
/* Write the trailer, if any. The trailer must be written before you
* close the CodecContexts open when you wrote the header; otherwise
* av_write_trailer() may try to use memory that was freed on
* av_codec_close(). */
/* Close each codec. */
if (video_st)
if (audio_st)
/* Close the output file. */
/* free the stream */
return 0;
}