Move the video size and rate abbreviations system from libavformat to libavcodec
[libav.git] / output_example.c
CommitLineData
8de65d4f
FB
1/*
2 * Libavformat API example: Output a media file in any supported
3 * libavformat format. The default codecs are used.
115329f1 4 *
8de65d4f 5 * Copyright (c) 2003 Fabrice Bellard
115329f1 6 *
8de65d4f
FB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
115329f1 13 *
8de65d4f
FB
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
115329f1 16 *
8de65d4f
FB
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
115329f1 23 * THE SOFTWARE.
8de65d4f
FB
24 */
25#include <stdlib.h>
26#include <stdio.h>
af547ce5 27#include <string.h>
8de65d4f
FB
28#include <math.h>
29
264cb2b8 30#ifndef M_PI
a40de112 31#define M_PI 3.14159265358979323846
264cb2b8
MN
32#endif
33
8de65d4f 34#include "avformat.h"
03ae87a3 35#include "swscale.h"
8de65d4f 36
364a9607
DB
37#undef exit
38
8de65d4f 39/* 5 seconds stream duration */
cb0c448a
FB
40#define STREAM_DURATION 5.0
41#define STREAM_FRAME_RATE 25 /* 25 images/s */
42#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
002c01a6 43#define STREAM_PIX_FMT PIX_FMT_YUV420P /* default pix_fmt */
8de65d4f 44
03ae87a3
LA
45static int sws_flags = SWS_BICUBIC;
46
8de65d4f
FB
47/**************************************************************/
48/* audio output */
49
e70fcf07 50float t, tincr, tincr2;
8de65d4f
FB
51int16_t *samples;
52uint8_t *audio_outbuf;
53int audio_outbuf_size;
54int audio_input_frame_size;
55
115329f1 56/*
8de65d4f
FB
57 * add an audio output stream
58 */
ceaf1909 59static AVStream *add_audio_stream(AVFormatContext *oc, int codec_id)
8de65d4f 60{
8de65d4f
FB
61 AVCodecContext *c;
62 AVStream *st;
63
64 st = av_new_stream(oc, 1);
65 if (!st) {
66 fprintf(stderr, "Could not alloc stream\n");
67 exit(1);
68 }
69
01f4895c 70 c = st->codec;
e70fcf07 71 c->codec_id = codec_id;
8de65d4f
FB
72 c->codec_type = CODEC_TYPE_AUDIO;
73
74 /* put sample parameters */
75 c->bit_rate = 64000;
76 c->sample_rate = 44100;
77 c->channels = 2;
e70fcf07
FB
78 return st;
79}
80
ceaf1909 81static void open_audio(AVFormatContext *oc, AVStream *st)
e70fcf07
FB
82{
83 AVCodecContext *c;
84 AVCodec *codec;
85
01f4895c 86 c = st->codec;
e70fcf07
FB
87
88 /* find the audio encoder */
89 codec = avcodec_find_encoder(c->codec_id);
90 if (!codec) {
91 fprintf(stderr, "codec not found\n");
92 exit(1);
93 }
8de65d4f
FB
94
95 /* open it */
96 if (avcodec_open(c, codec) < 0) {
97 fprintf(stderr, "could not open codec\n");
98 exit(1);
99 }
100
101 /* init signal generator */
102 t = 0;
e70fcf07
FB
103 tincr = 2 * M_PI * 110.0 / c->sample_rate;
104 /* increment frequency by 110 Hz per second */
105 tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
8de65d4f
FB
106
107 audio_outbuf_size = 10000;
5d915e82 108 audio_outbuf = av_malloc(audio_outbuf_size);
8de65d4f
FB
109
110 /* ugly hack for PCM codecs (will be removed ASAP with new PCM
111 support to compute the input frame size in samples */
112 if (c->frame_size <= 1) {
113 audio_input_frame_size = audio_outbuf_size / c->channels;
01f4895c 114 switch(st->codec->codec_id) {
8de65d4f
FB
115 case CODEC_ID_PCM_S16LE:
116 case CODEC_ID_PCM_S16BE:
117 case CODEC_ID_PCM_U16LE:
118 case CODEC_ID_PCM_U16BE:
119 audio_input_frame_size >>= 1;
120 break;
121 default:
122 break;
123 }
124 } else {
125 audio_input_frame_size = c->frame_size;
126 }
5d915e82 127 samples = av_malloc(audio_input_frame_size * 2 * c->channels);
8de65d4f
FB
128}
129
cb750e33
FB
130/* prepare a 16 bit dummy audio frame of 'frame_size' samples and
131 'nb_channels' channels */
ceaf1909 132static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels)
cb750e33
FB
133{
134 int j, i, v;
135 int16_t *q;
136
137 q = samples;
138 for(j=0;j<frame_size;j++) {
139 v = (int)(sin(t) * 10000);
140 for(i = 0; i < nb_channels; i++)
141 *q++ = v;
142 t += tincr;
143 tincr += tincr2;
144 }
145}
146
ceaf1909 147static void write_audio_frame(AVFormatContext *oc, AVStream *st)
8de65d4f 148{
8de65d4f 149 AVCodecContext *c;
e928649b
MN
150 AVPacket pkt;
151 av_init_packet(&pkt);
115329f1 152
01f4895c 153 c = st->codec;
8de65d4f 154
cb750e33
FB
155 get_audio_frame(samples, audio_input_frame_size, c->channels);
156
e928649b
MN
157 pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
158
002c01a6 159 pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
e928649b
MN
160 pkt.flags |= PKT_FLAG_KEY;
161 pkt.stream_index= st->index;
162 pkt.data= audio_outbuf;
8de65d4f
FB
163
164 /* write the compressed frame in the media file */
e928649b 165 if (av_write_frame(oc, &pkt) != 0) {
8de65d4f
FB
166 fprintf(stderr, "Error while writing audio frame\n");
167 exit(1);
168 }
169}
170
ceaf1909 171static void close_audio(AVFormatContext *oc, AVStream *st)
e70fcf07 172{
01f4895c 173 avcodec_close(st->codec);
115329f1 174
e70fcf07
FB
175 av_free(samples);
176 av_free(audio_outbuf);
177}
178
8de65d4f
FB
179/**************************************************************/
180/* video output */
181
e70fcf07 182AVFrame *picture, *tmp_picture;
8de65d4f
FB
183uint8_t *video_outbuf;
184int frame_count, video_outbuf_size;
185
186/* add a video output stream */
ceaf1909 187static AVStream *add_video_stream(AVFormatContext *oc, int codec_id)
8de65d4f 188{
8de65d4f
FB
189 AVCodecContext *c;
190 AVStream *st;
8de65d4f
FB
191
192 st = av_new_stream(oc, 0);
193 if (!st) {
194 fprintf(stderr, "Could not alloc stream\n");
195 exit(1);
196 }
115329f1 197
01f4895c 198 c = st->codec;
e70fcf07 199 c->codec_id = codec_id;
8de65d4f
FB
200 c->codec_type = CODEC_TYPE_VIDEO;
201
202 /* put sample parameters */
203 c->bit_rate = 400000;
204 /* resolution must be a multiple of two */
115329f1 205 c->width = 352;
8de65d4f 206 c->height = 288;
5b28c8c3
MN
207 /* time base: this is the fundamental unit of time (in seconds) in terms
208 of which frame timestamps are represented. for fixed-fps content,
209 timebase should be 1/framerate and timestamp increments should be
210 identically 1. */
115329f1 211 c->time_base.den = STREAM_FRAME_RATE;
c0df9d75 212 c->time_base.num = 1;
cb0c448a 213 c->gop_size = 12; /* emit one intra frame every twelve frames at most */
002c01a6 214 c->pix_fmt = STREAM_PIX_FMT;
85e33747 215 if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
cb0c448a
FB
216 /* just for testing, we also add B frames */
217 c->max_b_frames = 2;
218 }
85e33747 219 if (c->codec_id == CODEC_ID_MPEG1VIDEO){
115329f1
DB
220 /* needed to avoid using macroblocks in which some coeffs overflow
221 this doesnt happen with normal video, it just happens here as the
85e33747
MN
222 motion of the chroma plane doesnt match the luma plane */
223 c->mb_decision=2;
224 }
0afd2a92 225 // some formats want stream headers to be separate
af547ce5
MN
226 if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp"))
227 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
115329f1 228
e70fcf07
FB
229 return st;
230}
231
ceaf1909 232static AVFrame *alloc_picture(int pix_fmt, int width, int height)
e70fcf07
FB
233{
234 AVFrame *picture;
235 uint8_t *picture_buf;
236 int size;
115329f1 237
e70fcf07
FB
238 picture = avcodec_alloc_frame();
239 if (!picture)
240 return NULL;
241 size = avpicture_get_size(pix_fmt, width, height);
5d915e82 242 picture_buf = av_malloc(size);
e70fcf07
FB
243 if (!picture_buf) {
244 av_free(picture);
245 return NULL;
246 }
115329f1 247 avpicture_fill((AVPicture *)picture, picture_buf,
e70fcf07
FB
248 pix_fmt, width, height);
249 return picture;
250}
115329f1 251
ceaf1909 252static void open_video(AVFormatContext *oc, AVStream *st)
e70fcf07
FB
253{
254 AVCodec *codec;
255 AVCodecContext *c;
256
01f4895c 257 c = st->codec;
e70fcf07
FB
258
259 /* find the video encoder */
260 codec = avcodec_find_encoder(c->codec_id);
261 if (!codec) {
262 fprintf(stderr, "codec not found\n");
263 exit(1);
264 }
265
266 /* open the codec */
8de65d4f
FB
267 if (avcodec_open(c, codec) < 0) {
268 fprintf(stderr, "could not open codec\n");
269 exit(1);
270 }
271
e70fcf07
FB
272 video_outbuf = NULL;
273 if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
274 /* allocate output buffer */
275 /* XXX: API change will be done */
5d915e82
RP
276 /* buffers passed into lav* can be allocated any way you prefer,
277 as long as they're aligned enough for the architecture, and
278 they're freed appropriately (such as using av_free for buffers
279 allocated with av_malloc) */
e70fcf07 280 video_outbuf_size = 200000;
5d915e82 281 video_outbuf = av_malloc(video_outbuf_size);
e70fcf07 282 }
8de65d4f 283
e70fcf07
FB
284 /* allocate the encoded raw picture */
285 picture = alloc_picture(c->pix_fmt, c->width, c->height);
286 if (!picture) {
287 fprintf(stderr, "Could not allocate picture\n");
288 exit(1);
289 }
8de65d4f 290
e70fcf07
FB
291 /* if the output format is not YUV420P, then a temporary YUV420P
292 picture is needed too. It is then converted to the required
293 output format */
294 tmp_picture = NULL;
295 if (c->pix_fmt != PIX_FMT_YUV420P) {
296 tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
297 if (!tmp_picture) {
298 fprintf(stderr, "Could not allocate temporary picture\n");
299 exit(1);
300 }
301 }
302}
8de65d4f 303
e70fcf07 304/* prepare a dummy image */
ceaf1909 305static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
8de65d4f 306{
e70fcf07
FB
307 int x, y, i;
308
309 i = frame_index;
8de65d4f 310
8de65d4f 311 /* Y */
e70fcf07
FB
312 for(y=0;y<height;y++) {
313 for(x=0;x<width;x++) {
314 pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
8de65d4f
FB
315 }
316 }
115329f1 317
8de65d4f 318 /* Cb and Cr */
e70fcf07
FB
319 for(y=0;y<height/2;y++) {
320 for(x=0;x<width/2;x++) {
321 pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
322 pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
8de65d4f
FB
323 }
324 }
e70fcf07 325}
8de65d4f 326
ceaf1909 327static void write_video_frame(AVFormatContext *oc, AVStream *st)
e70fcf07
FB
328{
329 int out_size, ret;
330 AVCodecContext *c;
03ae87a3 331 static struct SwsContext *img_convert_ctx;
115329f1 332
01f4895c 333 c = st->codec;
115329f1 334
cb0c448a
FB
335 if (frame_count >= STREAM_NB_FRAMES) {
336 /* no more frame to compress. The codec has a latency of a few
337 frames if using B frames, so we get the last frames by
002c01a6 338 passing the same picture again */
e70fcf07 339 } else {
cb0c448a
FB
340 if (c->pix_fmt != PIX_FMT_YUV420P) {
341 /* as we only generate a YUV420P picture, we must convert it
342 to the codec pixel format if needed */
03ae87a3
LA
343 if (img_convert_ctx == NULL) {
344 img_convert_ctx = sws_getContext(c->width, c->height,
345 PIX_FMT_YUV420P,
346 c->width, c->height,
347 c->pix_fmt,
348 sws_flags, NULL, NULL, NULL);
349 if (img_convert_ctx == NULL) {
350 fprintf(stderr, "Cannot initialize the conversion context\n");
351 exit(1);
352 }
353 }
cb0c448a 354 fill_yuv_image(tmp_picture, frame_count, c->width, c->height);
03ae87a3
LA
355 sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize,
356 0, c->height, picture->data, picture->linesize);
cb0c448a
FB
357 } else {
358 fill_yuv_image(picture, frame_count, c->width, c->height);
359 }
e70fcf07
FB
360 }
361
115329f1 362
e70fcf07
FB
363 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
364 /* raw video case. The API will change slightly in the near
365 futur for that */
e928649b
MN
366 AVPacket pkt;
367 av_init_packet(&pkt);
115329f1 368
e928649b
MN
369 pkt.flags |= PKT_FLAG_KEY;
370 pkt.stream_index= st->index;
002c01a6 371 pkt.data= (uint8_t *)picture;
e928649b 372 pkt.size= sizeof(AVPicture);
115329f1 373
e928649b 374 ret = av_write_frame(oc, &pkt);
e70fcf07
FB
375 } else {
376 /* encode the image */
002c01a6 377 out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
cb0c448a 378 /* if zero size, it means the image was buffered */
b5bc8591 379 if (out_size > 0) {
e928649b
MN
380 AVPacket pkt;
381 av_init_packet(&pkt);
115329f1 382
002c01a6 383 pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
e928649b
MN
384 if(c->coded_frame->key_frame)
385 pkt.flags |= PKT_FLAG_KEY;
386 pkt.stream_index= st->index;
387 pkt.data= video_outbuf;
388 pkt.size= out_size;
115329f1 389
cb0c448a 390 /* write the compressed frame in the media file */
e928649b 391 ret = av_write_frame(oc, &pkt);
cb0c448a
FB
392 } else {
393 ret = 0;
394 }
e70fcf07
FB
395 }
396 if (ret != 0) {
8de65d4f
FB
397 fprintf(stderr, "Error while writing video frame\n");
398 exit(1);
399 }
e70fcf07
FB
400 frame_count++;
401}
402
ceaf1909 403static void close_video(AVFormatContext *oc, AVStream *st)
e70fcf07 404{
01f4895c 405 avcodec_close(st->codec);
e70fcf07
FB
406 av_free(picture->data[0]);
407 av_free(picture);
408 if (tmp_picture) {
409 av_free(tmp_picture->data[0]);
410 av_free(tmp_picture);
411 }
412 av_free(video_outbuf);
8de65d4f
FB
413}
414
415/**************************************************************/
416/* media file output */
417
418int main(int argc, char **argv)
419{
420 const char *filename;
421 AVOutputFormat *fmt;
422 AVFormatContext *oc;
e70fcf07 423 AVStream *audio_st, *video_st;
8de65d4f 424 double audio_pts, video_pts;
e70fcf07
FB
425 int i;
426
8de65d4f
FB
427 /* initialize libavcodec, and register all codecs and formats */
428 av_register_all();
115329f1 429
8de65d4f
FB
430 if (argc != 2) {
431 printf("usage: %s output_file\n"
e70fcf07
FB
432 "API example program to output a media file with libavformat.\n"
433 "The output format is automatically guessed according to the file extension.\n"
434 "Raw images can also be output by using '%%d' in the filename\n"
8de65d4f
FB
435 "\n", argv[0]);
436 exit(1);
437 }
115329f1 438
8de65d4f
FB
439 filename = argv[1];
440
441 /* auto detect the output format from the name. default is
442 mpeg. */
443 fmt = guess_format(NULL, filename, NULL);
444 if (!fmt) {
445 printf("Could not deduce output format from file extension: using MPEG.\n");
446 fmt = guess_format("mpeg", NULL, NULL);
447 }
448 if (!fmt) {
449 fprintf(stderr, "Could not find suitable output format\n");
450 exit(1);
451 }
115329f1 452
8de65d4f 453 /* allocate the output media context */
bc874dae 454 oc = av_alloc_format_context();
8de65d4f
FB
455 if (!oc) {
456 fprintf(stderr, "Memory error\n");
457 exit(1);
458 }
459 oc->oformat = fmt;
e70fcf07 460 snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
8de65d4f
FB
461
462 /* add the audio and video streams using the default format codecs
463 and initialize the codecs */
464 video_st = NULL;
465 audio_st = NULL;
466 if (fmt->video_codec != CODEC_ID_NONE) {
467 video_st = add_video_stream(oc, fmt->video_codec);
468 }
469 if (fmt->audio_codec != CODEC_ID_NONE) {
470 audio_st = add_audio_stream(oc, fmt->audio_codec);
471 }
472
e70fcf07
FB
473 /* set the output parameters (must be done even if no
474 parameters). */
475 if (av_set_parameters(oc, NULL) < 0) {
476 fprintf(stderr, "Invalid output format parameters\n");
477 exit(1);
478 }
479
8de65d4f
FB
480 dump_format(oc, 0, filename, 1);
481
e70fcf07
FB
482 /* now that all the parameters are set, we can open the audio and
483 video codecs and allocate the necessary encode buffers */
484 if (video_st)
485 open_video(oc, video_st);
486 if (audio_st)
487 open_audio(oc, audio_st);
488
8de65d4f
FB
489 /* open the output file, if needed */
490 if (!(fmt->flags & AVFMT_NOFILE)) {
491 if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
492 fprintf(stderr, "Could not open '%s'\n", filename);
493 exit(1);
494 }
495 }
115329f1 496
8de65d4f
FB
497 /* write the stream header, if any */
498 av_write_header(oc);
115329f1 499
8de65d4f
FB
500 for(;;) {
501 /* compute current audio and video time */
502 if (audio_st)
e06d3d55 503 audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
8de65d4f
FB
504 else
505 audio_pts = 0.0;
115329f1 506
8de65d4f 507 if (video_st)
e06d3d55 508 video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
8de65d4f
FB
509 else
510 video_pts = 0.0;
511
115329f1 512 if ((!audio_st || audio_pts >= STREAM_DURATION) &&
8de65d4f
FB
513 (!video_st || video_pts >= STREAM_DURATION))
514 break;
115329f1 515
8de65d4f 516 /* write interleaved audio and video frames */
e70fcf07 517 if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
8de65d4f
FB
518 write_audio_frame(oc, audio_st);
519 } else {
520 write_video_frame(oc, video_st);
521 }
522 }
523
524 /* close each codec */
e70fcf07
FB
525 if (video_st)
526 close_video(oc, video_st);
527 if (audio_st)
528 close_audio(oc, audio_st);
8de65d4f
FB
529
530 /* write the trailer, if any */
531 av_write_trailer(oc);
115329f1 532
e70fcf07
FB
533 /* free the streams */
534 for(i = 0; i < oc->nb_streams; i++) {
8720de5b 535 av_freep(&oc->streams[i]->codec);
e70fcf07
FB
536 av_freep(&oc->streams[i]);
537 }
538
8de65d4f
FB
539 if (!(fmt->flags & AVFMT_NOFILE)) {
540 /* close the output file */
541 url_fclose(&oc->pb);
542 }
543
544 /* free the stream */
545 av_free(oc);
546
547 return 0;
548}