1 /*
2 * Copyright (c) 2003 Fabrice Bellard
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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
20 * THE SOFTWARE.
21 */
22
23 /**
24 * @file libavformat muxing API usage example
25 * @example mux.c
26 *
27 * Generate a synthetic audio and video signal and mux them to a media file in
28 * any supported libavformat format. The default codecs are used.
29 */
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <math.h>
35
45
46 #define STREAM_DURATION 10.0
47 #define STREAM_FRAME_RATE 25 /* 25 images/s */
48 #define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
49
50 #define SCALE_FLAGS SWS_BICUBIC
51
52 // a wrapper around a single output AVStream
56
57 /* pts of the next frame that will be generated */
60
63
65
67
71
73 {
75
76 printf(
"pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
81 }
82
85 {
87
88 // send the frame to the encoder
91 fprintf(stderr, "Error sending a frame to the encoder: %s\n",
93 exit(1);
94 }
95
99 break;
101 fprintf(stderr,
"Error encoding a frame: %s\n",
av_err2str(
ret));
102 exit(1);
103 }
104
105 /* rescale output packet timestamp values from codec to stream timebase */
108
109 /* Write the compressed frame to the media file. */
112 /* pkt is now blank (av_interleaved_write_frame() takes ownership of
113 * its contents and resets pkt), so that no unreferencing is necessary.
114 * This would be different if one used av_write_frame(). */
116 fprintf(stderr,
"Error while writing output packet: %s\n",
av_err2str(
ret));
117 exit(1);
118 }
119 }
120
122 }
123
124 /* Add an output stream. */
128 {
131
132 /* find the encoder */
134 if (!(*codec)) {
135 fprintf(stderr, "Could not find encoder for '%s'\n",
137 exit(1);
138 }
139
142 fprintf(stderr, "Could not allocate AVPacket\n");
143 exit(1);
144 }
145
148 fprintf(stderr, "Could not allocate stream\n");
149 exit(1);
150 }
154 fprintf(stderr, "Could not alloc an encoding context\n");
155 exit(1);
156 }
158
159 switch ((*codec)->type) {
161 c->sample_fmt = (*codec)->sample_fmts ?
164 c->sample_rate = 44100;
165 if ((*codec)->supported_samplerates) {
166 c->sample_rate = (*codec)->supported_samplerates[0];
167 for (
i = 0; (*codec)->supported_samplerates[
i];
i++) {
168 if ((*codec)->supported_samplerates[
i] == 44100)
169 c->sample_rate = 44100;
170 }
171 }
174 break;
175
178
179 c->bit_rate = 400000;
180 /* Resolution must be a multiple of two. */
183 /* timebase: This is the fundamental unit of time (in seconds) in terms
184 * of which frame timestamps are represented. For fixed-fps content,
185 * timebase should be 1/framerate and timestamp increments should be
186 * identical to 1. */
189
190 c->gop_size = 12;
/* emit one intra frame every twelve frames at most */
193 /* just for testing, we also add B-frames */
195 }
197 /* Needed to avoid using macroblocks in which some coeffs overflow.
198 * This does not happen with normal video, it just happens here as
199 * the motion of the chroma plane does not match the luma plane. */
201 }
202 break;
203
204 default:
205 break;
206 }
207
208 /* Some formats want stream headers to be separate. */
211 }
212
213 /**************************************************************/
214 /* audio output */
215
218 int sample_rate, int nb_samples)
219 {
222 fprintf(stderr, "Error allocating an audio frame\n");
223 exit(1);
224 }
225
226 frame->format = sample_fmt;
228 frame->sample_rate = sample_rate;
229 frame->nb_samples = nb_samples;
230
231 if (nb_samples) {
233 fprintf(stderr, "Error allocating an audio buffer\n");
234 exit(1);
235 }
236 }
237
239 }
240
243 {
245 int nb_samples;
248
250
251 /* open it */
256 fprintf(stderr,
"Could not open audio codec: %s\n",
av_err2str(
ret));
257 exit(1);
258 }
259
260 /* init signal generator */
262 ost->tincr = 2 *
M_PI * 110.0 /
c->sample_rate;
263 /* increment frequency by 110 Hz per second */
264 ost->tincr2 = 2 *
M_PI * 110.0 /
c->sample_rate /
c->sample_rate;
265
267 nb_samples = 10000;
268 else
269 nb_samples =
c->frame_size;
270
272 c->sample_rate, nb_samples);
274 c->sample_rate, nb_samples);
275
276 /* copy the stream parameters to the muxer */
279 fprintf(stderr, "Could not copy the stream parameters\n");
280 exit(1);
281 }
282
283 /* create resampler context */
286 fprintf(stderr, "Could not allocate resampler context\n");
287 exit(1);
288 }
289
290 /* set options */
297
298 /* initialize the resampling context */
300 fprintf(stderr, "Failed to initialize the resampling context\n");
301 exit(1);
302 }
303 }
304
305 /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
306 * 'nb_channels' channels. */
308 {
311 int16_t *q = (int16_t*)
frame->data[0];
312
313 /* check if we want to generate more frames */
317
318 for (j = 0; j <
frame->nb_samples; j++) {
319 v = (int)(sin(
ost->t) * 10000);
320 for (
i = 0;
i <
ost->enc->ch_layout.nb_channels;
i++)
321 *q++ = v;
323 ost->tincr +=
ost->tincr2;
324 }
325
328
330 }
331
332 /*
333 * encode one audio frame and send it to the muxer
334 * return 1 when encoding is finished, 0 otherwise
335 */
337 {
341 int dst_nb_samples;
342
344
346
348 /* convert samples from native format to destination codec format, using the resampler */
349 /* compute destination number of samples */
352
353 /* when we pass a frame to the encoder, it may keep a reference to it
354 * internally;
355 * make sure we do not overwrite it here
356 */
359 exit(1);
360
361 /* convert to destination format */
363 ost->frame->data, dst_nb_samples,
364 (
const uint8_t **)
frame->data,
frame->nb_samples);
366 fprintf(stderr, "Error while converting\n");
367 exit(1);
368 }
370
372 ost->samples_count += dst_nb_samples;
373 }
374
376 }
377
378 /**************************************************************/
379 /* video output */
380
382 {
385
389
393
394 /* allocate the buffers for the frame data */
397 fprintf(stderr, "Could not allocate frame data.\n");
398 exit(1);
399 }
400
402 }
403
406 {
410
412
413 /* open the codec */
417 fprintf(stderr,
"Could not open video codec: %s\n",
av_err2str(
ret));
418 exit(1);
419 }
420
421 /* allocate and init a reusable frame */
424 fprintf(stderr, "Could not allocate video frame\n");
425 exit(1);
426 }
427
428 /* If the output format is not YUV420P, then a temporary YUV420P
429 * picture is needed too. It is then converted to the required
430 * output format. */
434 if (!
ost->tmp_frame) {
435 fprintf(stderr, "Could not allocate temporary video frame\n");
436 exit(1);
437 }
438 }
439
440 /* copy the stream parameters to the muxer */
443 fprintf(stderr, "Could not copy the stream parameters\n");
444 exit(1);
445 }
446 }
447
448 /* Prepare a dummy image. */
451 {
453
455
456 /* Y */
457 for (y = 0; y <
height; y++)
458 for (x = 0; x <
width; x++)
460
461 /* Cb and Cr */
463 for (x = 0; x <
width / 2; x++) {
466 }
467 }
468 }
469
471 {
473
474 /* check if we want to generate more frames */
478
479 /* when we pass a frame to the encoder, it may keep a reference to it
480 * internally; make sure we do not overwrite it here */
482 exit(1);
483
485 /* as we only generate a YUV420P picture, we must convert it
486 * to the codec pixel format if needed */
494 fprintf(stderr,
495 "Could not initialize the conversion context\n");
496 exit(1);
497 }
498 }
500 sws_scale(
ost->sws_ctx, (
const uint8_t *
const *)
ost->tmp_frame->data,
501 ost->tmp_frame->linesize, 0,
c->height,
ost->frame->data,
502 ost->frame->linesize);
503 } else {
505 }
506
507 ost->frame->pts =
ost->next_pts++;
508
510 }
511
512 /*
513 * encode one video frame and send it to the muxer
514 * return 1 when encoding is finished, 0 otherwise
515 */
517 {
519 }
520
522 {
529 }
530
531 /**************************************************************/
532 /* media file output */
533
534 int main(
int argc,
char **argv)
535 {
538 const char *filename;
540 const AVCodec *audio_codec, *video_codec;
542 int have_video = 0, have_audio = 0;
543 int encode_video = 0, encode_audio = 0;
546
547 if (argc < 2) {
548 printf(
"usage: %s output_file\n"
549 "API example program to output a media file with libavformat.\n"
550 "This program generates a synthetic audio and video stream, encodes and\n"
551 "muxes them into a file named output_file.\n"
552 "The output format is automatically guessed according to the file extension.\n"
553 "Raw images can also be output by using '%%d' in the filename.\n"
554 "\n", argv[0]);
555 return 1;
556 }
557
558 filename = argv[1];
559 for (
i = 2;
i+1 < argc;
i+=2) {
560 if (!strcmp(argv[
i],
"-flags") || !strcmp(argv[
i],
"-fflags"))
562 }
563
564 /* allocate the output media context */
566 if (!oc) {
567 printf(
"Could not deduce output format from file extension: using MPEG.\n");
569 }
570 if (!oc)
571 return 1;
572
574
575 /* Add the audio and video streams using the default format codecs
576 * and initialize the codecs. */
579 have_video = 1;
580 encode_video = 1;
581 }
584 have_audio = 1;
585 encode_audio = 1;
586 }
587
588 /* Now that all the parameters are set, we can open the audio and
589 * video codecs and allocate the necessary encode buffers. */
590 if (have_video)
592
593 if (have_audio)
595
597
598 /* open the output file, if needed */
602 fprintf(stderr, "Could not open '%s': %s\n", filename,
604 return 1;
605 }
606 }
607
608 /* Write the stream header, if any. */
611 fprintf(stderr, "Error occurred when opening output file: %s\n",
613 return 1;
614 }
615
616 while (encode_video || encode_audio) {
617 /* select the stream to encode */
618 if (encode_video &&
622 } else {
624 }
625 }
626
628
629 /* Close each codec. */
630 if (have_video)
632 if (have_audio)
634
636 /* Close the output file. */
638
639 /* free the stream */
641
642 return 0;
643 }