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.
27 * @example libavformat/output-example.c
28 * Output a media file in any supported libavformat format.
29 * The default codecs are used.
37 #include "libavutil/mathematics.h"
38 #include "libavformat/avformat.h"
39 #include "libswscale/swscale.h"
41 /* 5 seconds stream duration */
42 #define STREAM_DURATION 5.0
43 #define STREAM_FRAME_RATE 25 /* 25 images/s */
44 #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
45 #define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
47 static int sws_flags
= SWS_BICUBIC
;
49 /**************************************************************/
52 static float t
, tincr
, tincr2
;
53 static int16_t *samples
;
54 static int audio_input_frame_size
;
57 * add an audio output stream
59 static AVStream
*add_audio_stream(AVFormatContext
*oc
, enum AVCodecID codec_id
)
65 /* find the audio encoder */
66 codec
= avcodec_find_encoder(codec_id
);
68 fprintf(stderr
, "codec not found\n");
72 st
= avformat_new_stream(oc
, codec
);
74 fprintf(stderr
, "Could not alloc stream\n");
80 /* put sample parameters */
81 c
->sample_fmt
= AV_SAMPLE_FMT_S16
;
83 c
->sample_rate
= 44100;
86 // some formats want stream headers to be separate
87 if (oc
->oformat
->flags
& AVFMT_GLOBALHEADER
)
88 c
->flags
|= CODEC_FLAG_GLOBAL_HEADER
;
93 static void open_audio(AVFormatContext
*oc
, AVStream
*st
)
100 if (avcodec_open2(c
, NULL
, NULL
) < 0) {
101 fprintf(stderr
, "could not open codec\n");
105 /* init signal generator */
107 tincr
= 2 * M_PI
* 110.0 / c
->sample_rate
;
108 /* increment frequency by 110 Hz per second */
109 tincr2
= 2 * M_PI
* 110.0 / c
->sample_rate
/ c
->sample_rate
;
111 if (c
->codec
->capabilities
& CODEC_CAP_VARIABLE_FRAME_SIZE
)
112 audio_input_frame_size
= 10000;
114 audio_input_frame_size
= c
->frame_size
;
115 samples
= av_malloc(audio_input_frame_size
*
116 av_get_bytes_per_sample(c
->sample_fmt
) *
120 /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
121 * 'nb_channels' channels. */
122 static void get_audio_frame(int16_t *samples
, int frame_size
, int nb_channels
)
128 for (j
= 0; j
< frame_size
; j
++) {
129 v
= (int)(sin(t
) * 10000);
130 for (i
= 0; i
< nb_channels
; i
++)
137 static void write_audio_frame(AVFormatContext
*oc
, AVStream
*st
)
140 AVPacket pkt
= { 0 }; // data and size must be 0;
141 AVFrame
*frame
= avcodec_alloc_frame();
144 av_init_packet(&pkt
);
147 get_audio_frame(samples
, audio_input_frame_size
, c
->channels
);
148 frame
->nb_samples
= audio_input_frame_size
;
149 avcodec_fill_audio_frame(frame
, c
->channels
, c
->sample_fmt
,
151 audio_input_frame_size
*
152 av_get_bytes_per_sample(c
->sample_fmt
) *
155 avcodec_encode_audio2(c
, &pkt
, frame
, &got_packet
);
159 pkt
.stream_index
= st
->index
;
161 /* Write the compressed frame to the media file. */
162 if (av_interleaved_write_frame(oc
, &pkt
) != 0) {
163 fprintf(stderr
, "Error while writing audio frame\n");
166 avcodec_free_frame(&frame
);
169 static void close_audio(AVFormatContext
*oc
, AVStream
*st
)
171 avcodec_close(st
->codec
);
176 /**************************************************************/
179 static AVFrame
*picture
, *tmp_picture
;
180 static uint8_t *video_outbuf
;
181 static int frame_count
, video_outbuf_size
;
183 /* Add a video output stream. */
184 static AVStream
*add_video_stream(AVFormatContext
*oc
, enum AVCodecID codec_id
)
190 /* find the video encoder */
191 codec
= avcodec_find_encoder(codec_id
);
193 fprintf(stderr
, "codec not found\n");
197 st
= avformat_new_stream(oc
, codec
);
199 fprintf(stderr
, "Could not alloc stream\n");
205 /* Put sample parameters. */
206 c
->bit_rate
= 400000;
207 /* Resolution must be a multiple of two. */
210 /* timebase: This is the fundamental unit of time (in seconds) in terms
211 * of which frame timestamps are represented. For fixed-fps content,
212 * timebase should be 1/framerate and timestamp increments should be
214 c
->time_base
.den
= STREAM_FRAME_RATE
;
215 c
->time_base
.num
= 1;
216 c
->gop_size
= 12; /* emit one intra frame every twelve frames at most */
217 c
->pix_fmt
= STREAM_PIX_FMT
;
218 if (c
->codec_id
== AV_CODEC_ID_MPEG2VIDEO
) {
219 /* just for testing, we also add B frames */
222 if (c
->codec_id
== AV_CODEC_ID_MPEG1VIDEO
) {
223 /* Needed to avoid using macroblocks in which some coeffs overflow.
224 * This does not happen with normal video, it just happens here as
225 * the motion of the chroma plane does not match the luma plane. */
228 /* Some formats want stream headers to be separate. */
229 if (oc
->oformat
->flags
& AVFMT_GLOBALHEADER
)
230 c
->flags
|= CODEC_FLAG_GLOBAL_HEADER
;
235 static AVFrame
*alloc_picture(enum AVPixelFormat pix_fmt
, int width
, int height
)
238 uint8_t *picture_buf
;
241 picture
= avcodec_alloc_frame();
244 size
= avpicture_get_size(pix_fmt
, width
, height
);
245 picture_buf
= av_malloc(size
);
250 avpicture_fill((AVPicture
*)picture
, picture_buf
,
251 pix_fmt
, width
, height
);
255 static void open_video(AVFormatContext
*oc
, AVStream
*st
)
262 if (avcodec_open2(c
, NULL
, NULL
) < 0) {
263 fprintf(stderr
, "could not open codec\n");
268 if (!(oc
->oformat
->flags
& AVFMT_RAWPICTURE
)) {
269 /* Allocate output buffer. */
270 /* XXX: API change will be done. */
271 /* Buffers passed into lav* can be allocated any way you prefer,
272 * as long as they're aligned enough for the architecture, and
273 * they're freed appropriately (such as using av_free for buffers
274 * allocated with av_malloc). */
275 video_outbuf_size
= 200000;
276 video_outbuf
= av_malloc(video_outbuf_size
);
279 /* Allocate the encoded raw picture. */
280 picture
= 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
290 if (c
->pix_fmt
!= AV_PIX_FMT_YUV420P
) {
291 tmp_picture
= alloc_picture(AV_PIX_FMT_YUV420P
, c
->width
, c
->height
);
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
)
308 for (y
= 0; y
< height
; y
++)
309 for (x
= 0; x
< width
; x
++)
310 pict
->data
[0][y
* pict
->linesize
[0] + x
] = x
+ y
+ i
* 3;
313 for (y
= 0; y
< height
/ 2; y
++) {
314 for (x
= 0; x
< width
/ 2; x
++) {
315 pict
->data
[1][y
* pict
->linesize
[1] + x
] = 128 + y
+ i
* 2;
316 pict
->data
[2][y
* pict
->linesize
[2] + x
] = 64 + x
+ i
* 5;
321 static void write_video_frame(AVFormatContext
*oc
, AVStream
*st
)
325 static struct SwsContext
*img_convert_ctx
;
329 if (frame_count
>= STREAM_NB_FRAMES
) {
330 /* No more frames to compress. The codec has a latency of a few
331 * frames if using B-frames, so we get the last frames by
332 * passing the same picture again. */
334 if (c
->pix_fmt
!= AV_PIX_FMT_YUV420P
) {
335 /* as we only generate a YUV420P picture, we must convert it
336 * to the codec pixel format if needed */
337 if (img_convert_ctx
== NULL
) {
338 img_convert_ctx
= sws_getContext(c
->width
, c
->height
,
342 sws_flags
, NULL
, NULL
, NULL
);
343 if (img_convert_ctx
== NULL
) {
345 "Cannot initialize the conversion context\n");
349 fill_yuv_image(tmp_picture
, frame_count
, c
->width
, c
->height
);
350 sws_scale(img_convert_ctx
, tmp_picture
->data
, tmp_picture
->linesize
,
351 0, c
->height
, picture
->data
, picture
->linesize
);
353 fill_yuv_image(picture
, frame_count
, c
->width
, c
->height
);
357 if (oc
->oformat
->flags
& AVFMT_RAWPICTURE
) {
358 /* Raw video case - the API will change slightly in the near
359 * future for that. */
361 av_init_packet(&pkt
);
363 pkt
.flags
|= AV_PKT_FLAG_KEY
;
364 pkt
.stream_index
= st
->index
;
365 pkt
.data
= (uint8_t *)picture
;
366 pkt
.size
= sizeof(AVPicture
);
368 ret
= av_interleaved_write_frame(oc
, &pkt
);
370 /* encode the image */
371 out_size
= avcodec_encode_video(c
, video_outbuf
,
372 video_outbuf_size
, picture
);
373 /* If size is zero, it means the image was buffered. */
376 av_init_packet(&pkt
);
378 if (c
->coded_frame
->pts
!= AV_NOPTS_VALUE
)
379 pkt
.pts
= av_rescale_q(c
->coded_frame
->pts
,
380 c
->time_base
, st
->time_base
);
381 if (c
->coded_frame
->key_frame
)
382 pkt
.flags
|= AV_PKT_FLAG_KEY
;
383 pkt
.stream_index
= st
->index
;
384 pkt
.data
= video_outbuf
;
387 /* Write the compressed frame to the media file. */
388 ret
= av_interleaved_write_frame(oc
, &pkt
);
394 fprintf(stderr
, "Error while writing video frame\n");
400 static void close_video(AVFormatContext
*oc
, AVStream
*st
)
402 avcodec_close(st
->codec
);
403 av_free(picture
->data
[0]);
406 av_free(tmp_picture
->data
[0]);
407 av_free(tmp_picture
);
409 av_free(video_outbuf
);
412 /**************************************************************/
413 /* media file output */
415 int main(int argc
, char **argv
)
417 const char *filename
;
420 AVStream
*audio_st
, *video_st
;
421 double audio_pts
, video_pts
;
424 /* Initialize libavcodec, and register all codecs and formats. */
428 printf("usage: %s output_file\n"
429 "API example program to output a media file with libavformat.\n"
430 "The output format is automatically guessed according to the file extension.\n"
431 "Raw images can also be output by using '%%d' in the filename\n"
438 /* Autodetect the output format from the name. default is MPEG. */
439 fmt
= av_guess_format(NULL
, filename
, NULL
);
441 printf("Could not deduce output format from file extension: using MPEG.\n");
442 fmt
= av_guess_format("mpeg", NULL
, NULL
);
445 fprintf(stderr
, "Could not find suitable output format\n");
449 /* Allocate the output media context. */
450 oc
= avformat_alloc_context();
452 fprintf(stderr
, "Memory error\n");
456 snprintf(oc
->filename
, sizeof(oc
->filename
), "%s", filename
);
458 /* Add the audio and video streams using the default format codecs
459 * and initialize the codecs. */
462 if (fmt
->video_codec
!= AV_CODEC_ID_NONE
) {
463 video_st
= add_video_stream(oc
, fmt
->video_codec
);
465 if (fmt
->audio_codec
!= AV_CODEC_ID_NONE
) {
466 audio_st
= add_audio_stream(oc
, fmt
->audio_codec
);
469 /* Now that all the parameters are set, we can open the audio and
470 * video codecs and allocate the necessary encode buffers. */
472 open_video(oc
, video_st
);
474 open_audio(oc
, audio_st
);
476 av_dump_format(oc
, 0, filename
, 1);
478 /* open the output file, if needed */
479 if (!(fmt
->flags
& AVFMT_NOFILE
)) {
480 if (avio_open(&oc
->pb
, filename
, AVIO_FLAG_WRITE
) < 0) {
481 fprintf(stderr
, "Could not open '%s'\n", filename
);
486 /* Write the stream header, if any. */
487 avformat_write_header(oc
, NULL
);
490 /* Compute current audio and video time. */
492 audio_pts
= (double)audio_st
->pts
.val
* audio_st
->time_base
.num
/ audio_st
->time_base
.den
;
497 video_pts
= (double)video_st
->pts
.val
* video_st
->time_base
.num
/
498 video_st
->time_base
.den
;
502 if ((!audio_st
|| audio_pts
>= STREAM_DURATION
) &&
503 (!video_st
|| video_pts
>= STREAM_DURATION
))
506 /* write interleaved audio and video frames */
507 if (!video_st
|| (video_st
&& audio_st
&& audio_pts
< video_pts
)) {
508 write_audio_frame(oc
, audio_st
);
510 write_video_frame(oc
, video_st
);
514 /* Write the trailer, if any. The trailer must be written before you
515 * close the CodecContexts open when you wrote the header; otherwise
516 * av_write_trailer() may try to use memory that was freed on
517 * av_codec_close(). */
518 av_write_trailer(oc
);
520 /* Close each codec. */
522 close_video(oc
, video_st
);
524 close_audio(oc
, audio_st
);
526 /* Free the streams. */
527 for (i
= 0; i
< oc
->nb_streams
; i
++) {
528 av_freep(&oc
->streams
[i
]->codec
);
529 av_freep(&oc
->streams
[i
]);
532 if (!(fmt
->flags
& AVFMT_NOFILE
))
533 /* Close the output file. */
536 /* free the stream */