2 * Copyright (c) 2003 Fabrice Bellard
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * libavformat API example.
28 * Output a media file in any supported libavformat format. The default
37 #include "libavutil/channel_layout.h"
38 #include "libavutil/mathematics.h"
39 #include "libavformat/avformat.h"
40 #include "libswscale/swscale.h"
42 /* 5 seconds stream duration */
43 #define STREAM_DURATION 5.0
44 #define STREAM_FRAME_RATE 25 /* 25 images/s */
45 #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
46 #define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
48 static int sws_flags = SWS_BICUBIC;
50 // a wrapper around a single output AVStream
51 typedef struct OutputStream {
57 float t, tincr, tincr2;
58 int audio_input_frame_size;
61 /**************************************************************/
65 * add an audio output stream
67 static void add_audio_stream(OutputStream *ost, AVFormatContext *oc,
68 enum AVCodecID codec_id)
73 /* find the audio encoder */
74 codec = avcodec_find_encoder(codec_id);
76 fprintf(stderr, "codec not found\n");
80 ost->st = avformat_new_stream(oc, codec);
82 fprintf(stderr, "Could not alloc stream\n");
88 /* put sample parameters */
89 c->sample_fmt = AV_SAMPLE_FMT_S16;
91 c->sample_rate = 44100;
93 c->channel_layout = AV_CH_LAYOUT_STEREO;
95 // some formats want stream headers to be separate
96 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
97 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
100 static void open_audio(AVFormatContext *oc, OutputStream *ost)
107 if (avcodec_open2(c, NULL, NULL) < 0) {
108 fprintf(stderr, "could not open codec\n");
112 /* init signal generator */
114 ost->tincr = 2 * M_PI * 110.0 / c->sample_rate;
115 /* increment frequency by 110 Hz per second */
116 ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
118 if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
119 ost->audio_input_frame_size = 10000;
121 ost->audio_input_frame_size = c->frame_size;
124 /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
125 * 'nb_channels' channels. */
126 static void get_audio_frame(OutputStream *ost, AVFrame *frame, int nb_channels)
129 int16_t *q = (int16_t*)frame->data[0];
131 /* when we pass a frame to the encoder, it may keep a reference to it
133 * make sure we do not overwrite it here
135 ret = av_frame_make_writable(frame);
139 for (j = 0; j < frame->nb_samples; j++) {
140 v = (int)(sin(ost->t) * 10000);
141 for (i = 0; i < nb_channels; i++)
143 ost->t += ost->tincr;
144 ost->tincr += ost->tincr2;
148 static void write_audio_frame(AVFormatContext *oc, OutputStream *ost)
151 AVPacket pkt = { 0 }; // data and size must be 0;
152 AVFrame *frame = av_frame_alloc();
155 av_init_packet(&pkt);
158 frame->sample_rate = c->sample_rate;
159 frame->nb_samples = ost->audio_input_frame_size;
160 frame->format = AV_SAMPLE_FMT_S16;
161 frame->channel_layout = c->channel_layout;
162 ret = av_frame_get_buffer(frame, 0);
164 fprintf(stderr, "Could not allocate an audio frame.\n");
168 get_audio_frame(ost, frame, c->channels);
170 avcodec_encode_audio2(c, &pkt, frame, &got_packet);
174 pkt.stream_index = ost->st->index;
176 /* Write the compressed frame to the media file. */
177 if (av_interleaved_write_frame(oc, &pkt) != 0) {
178 fprintf(stderr, "Error while writing audio frame\n");
181 av_frame_free(&frame);
184 static void close_audio(AVFormatContext *oc, OutputStream *ost)
186 avcodec_close(ost->st->codec);
189 /**************************************************************/
192 static int frame_count;
194 /* Add a video output stream. */
195 static void add_video_stream(OutputStream *ost, AVFormatContext *oc,
196 enum AVCodecID codec_id)
201 /* find the video encoder */
202 codec = avcodec_find_encoder(codec_id);
204 fprintf(stderr, "codec not found\n");
208 ost->st = avformat_new_stream(oc, codec);
210 fprintf(stderr, "Could not alloc stream\n");
216 /* Put sample parameters. */
217 c->bit_rate = 400000;
218 /* Resolution must be a multiple of two. */
221 /* timebase: This is the fundamental unit of time (in seconds) in terms
222 * of which frame timestamps are represented. For fixed-fps content,
223 * timebase should be 1/framerate and timestamp increments should be
225 c->time_base.den = STREAM_FRAME_RATE;
226 c->time_base.num = 1;
227 c->gop_size = 12; /* emit one intra frame every twelve frames at most */
228 c->pix_fmt = STREAM_PIX_FMT;
229 if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
230 /* just for testing, we also add B frames */
233 if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
234 /* Needed to avoid using macroblocks in which some coeffs overflow.
235 * This does not happen with normal video, it just happens here as
236 * the motion of the chroma plane does not match the luma plane. */
239 /* Some formats want stream headers to be separate. */
240 if (oc->oformat->flags & AVFMT_GLOBALHEADER)
241 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
244 static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
249 picture = av_frame_alloc();
253 picture->format = pix_fmt;
254 picture->width = width;
255 picture->height = height;
257 /* allocate the buffers for the frame data */
258 ret = av_frame_get_buffer(picture, 32);
260 fprintf(stderr, "Could not allocate frame data.\n");
267 static void open_video(AVFormatContext *oc, OutputStream *ost)
274 if (avcodec_open2(c, NULL, NULL) < 0) {
275 fprintf(stderr, "could not open codec\n");
279 /* Allocate the encoded raw picture. */
280 ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);
282 fprintf(stderr, "Could not allocate picture\n");
286 /* If the output format is not YUV420P, then a temporary YUV420P
287 * picture is needed too. It is then converted to the required
289 ost->tmp_frame = NULL;
290 if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
291 ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);
292 if (!ost->tmp_frame) {
293 fprintf(stderr, "Could not allocate temporary picture\n");
299 /* Prepare a dummy image. */
300 static void fill_yuv_image(AVFrame *pict, int frame_index,
301 int width, int height)
305 /* when we pass a frame to the encoder, it may keep a reference to it
307 * make sure we do not overwrite it here
309 ret = av_frame_make_writable(pict);
316 for (y = 0; y < height; y++)
317 for (x = 0; x < width; x++)
318 pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
321 for (y = 0; y < height / 2; y++) {
322 for (x = 0; x < width / 2; x++) {
323 pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
324 pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
329 static void write_video_frame(AVFormatContext *oc, OutputStream *ost)
333 static struct SwsContext *img_convert_ctx;
337 if (frame_count >= STREAM_NB_FRAMES) {
338 /* No more frames to compress. The codec has a latency of a few
339 * frames if using B-frames, so we get the last frames by
340 * passing the same picture again. */
342 if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
343 /* as we only generate a YUV420P picture, we must convert it
344 * to the codec pixel format if needed */
345 if (img_convert_ctx == NULL) {
346 img_convert_ctx = sws_getContext(c->width, c->height,
350 sws_flags, NULL, NULL, NULL);
351 if (img_convert_ctx == NULL) {
353 "Cannot initialize the conversion context\n");
357 fill_yuv_image(ost->tmp_frame, frame_count, c->width, c->height);
358 sws_scale(img_convert_ctx, ost->tmp_frame->data, ost->tmp_frame->linesize,
359 0, c->height, ost->frame->data, ost->frame->linesize);
361 fill_yuv_image(ost->frame, frame_count, c->width, c->height);
365 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
366 /* Raw video case - the API will change slightly in the near
367 * future for that. */
369 av_init_packet(&pkt);
371 pkt.flags |= AV_PKT_FLAG_KEY;
372 pkt.stream_index = ost->st->index;
373 pkt.data = (uint8_t *)ost->frame;
374 pkt.size = sizeof(AVPicture);
376 ret = av_interleaved_write_frame(oc, &pkt);
378 AVPacket pkt = { 0 };
380 av_init_packet(&pkt);
382 /* encode the image */
383 ret = avcodec_encode_video2(c, &pkt, ost->frame, &got_packet);
384 /* If size is zero, it means the image was buffered. */
385 if (!ret && got_packet && pkt.size) {
386 av_packet_rescale_ts(&pkt, c->time_base, ost->st->time_base);
387 pkt.stream_index = ost->st->index;
389 /* Write the compressed frame to the media file. */
390 ret = av_interleaved_write_frame(oc, &pkt);
396 fprintf(stderr, "Error while writing video frame\n");
402 static void close_video(AVFormatContext *oc, OutputStream *ost)
404 avcodec_close(ost->st->codec);
405 av_frame_free(&ost->frame);
406 av_frame_free(&ost->tmp_frame);
409 /**************************************************************/
410 /* media file output */
412 int main(int argc, char **argv)
414 OutputStream video_st, audio_st;
415 const char *filename;
418 double audio_pts, video_pts;
419 int have_video = 0, have_audio = 0;
422 /* Initialize libavcodec, and register all codecs and formats. */
426 printf("usage: %s output_file\n"
427 "API example program to output a media file with libavformat.\n"
428 "The output format is automatically guessed according to the file extension.\n"
429 "Raw images can also be output by using '%%d' in the filename\n"
436 /* Autodetect the output format from the name. default is MPEG. */
437 fmt = av_guess_format(NULL, filename, NULL);
439 printf("Could not deduce output format from file extension: using MPEG.\n");
440 fmt = av_guess_format("mpeg", NULL, NULL);
443 fprintf(stderr, "Could not find suitable output format\n");
447 /* Allocate the output media context. */
448 oc = avformat_alloc_context();
450 fprintf(stderr, "Memory error\n");
454 snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
456 /* Add the audio and video streams using the default format codecs
457 * and initialize the codecs. */
458 if (fmt->video_codec != AV_CODEC_ID_NONE) {
459 add_video_stream(&video_st, oc, fmt->video_codec);
462 if (fmt->audio_codec != AV_CODEC_ID_NONE) {
463 add_audio_stream(&audio_st, oc, fmt->audio_codec);
467 /* Now that all the parameters are set, we can open the audio and
468 * video codecs and allocate the necessary encode buffers. */
470 open_video(oc, &video_st);
472 open_audio(oc, &audio_st);
474 av_dump_format(oc, 0, filename, 1);
476 /* open the output file, if needed */
477 if (!(fmt->flags & AVFMT_NOFILE)) {
478 if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) {
479 fprintf(stderr, "Could not open '%s'\n", filename);
484 /* Write the stream header, if any. */
485 avformat_write_header(oc, NULL);
488 /* Compute current audio and video time. */
490 audio_pts = (double)audio_st.st->pts.val * audio_st.st->time_base.num / audio_st.st->time_base.den;
495 video_pts = (double)video_st.st->pts.val * video_st.st->time_base.num /
496 video_st.st->time_base.den;
500 if ((!have_audio || audio_pts >= STREAM_DURATION) &&
501 (!have_video || video_pts >= STREAM_DURATION))
504 /* write interleaved audio and video frames */
505 if (!have_video || (have_video && have_audio && audio_pts < video_pts)) {
506 write_audio_frame(oc, &audio_st);
508 write_video_frame(oc, &video_st);
512 /* Write the trailer, if any. The trailer must be written before you
513 * close the CodecContexts open when you wrote the header; otherwise
514 * av_write_trailer() may try to use memory that was freed on
515 * av_codec_close(). */
516 av_write_trailer(oc);
518 /* Close each codec. */
520 close_video(oc, &video_st);
522 close_audio(oc, &audio_st);
524 /* Free the streams. */
525 for (i = 0; i < oc->nb_streams; i++) {
526 av_freep(&oc->streams[i]->codec);
527 av_freep(&oc->streams[i]);
530 if (!(fmt->flags & AVFMT_NOFILE))
531 /* Close the output file. */
534 /* free the stream */