Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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
  25.  * libavformat API example.
  26.  *
  27.  * Output a media file in any supported libavformat format. The default
  28.  * codecs are used.
  29.  * @example muxing.c
  30.  */
  31.  
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <math.h>
  36.  
  37. #include <libavutil/avassert.h>
  38. #include <libavutil/channel_layout.h>
  39. #include <libavutil/opt.h>
  40. #include <libavutil/mathematics.h>
  41. #include <libavutil/timestamp.h>
  42. #include <libavformat/avformat.h>
  43. #include <libswscale/swscale.h>
  44. #include <libswresample/swresample.h>
  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
  53. typedef struct OutputStream {
  54.     AVStream *st;
  55.  
  56.     /* pts of the next frame that will be generated */
  57.     int64_t next_pts;
  58.     int samples_count;
  59.  
  60.     AVFrame *frame;
  61.     AVFrame *tmp_frame;
  62.  
  63.     float t, tincr, tincr2;
  64.  
  65.     struct SwsContext *sws_ctx;
  66.     struct SwrContext *swr_ctx;
  67. } OutputStream;
  68.  
  69. static void log_packet(const AVFormatContext *fmt_ctx, const AVPacket *pkt)
  70. {
  71.     AVRational *time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;
  72.  
  73.     printf("pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
  74.            av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),
  75.            av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),
  76.            av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),
  77.            pkt->stream_index);
  78. }
  79.  
  80. static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
  81. {
  82.     /* rescale output packet timestamp values from codec to stream timebase */
  83.     av_packet_rescale_ts(pkt, *time_base, st->time_base);
  84.     pkt->stream_index = st->index;
  85.  
  86.     /* Write the compressed frame to the media file. */
  87.     log_packet(fmt_ctx, pkt);
  88.     return av_interleaved_write_frame(fmt_ctx, pkt);
  89. }
  90.  
  91. /* Add an output stream. */
  92. static void add_stream(OutputStream *ost, AVFormatContext *oc,
  93.                        AVCodec **codec,
  94.                        enum AVCodecID codec_id)
  95. {
  96.     AVCodecContext *c;
  97.     int i;
  98.  
  99.     /* find the encoder */
  100.     *codec = avcodec_find_encoder(codec_id);
  101.     if (!(*codec)) {
  102.         fprintf(stderr, "Could not find encoder for '%s'\n",
  103.                 avcodec_get_name(codec_id));
  104.         exit(1);
  105.     }
  106.  
  107.     ost->st = avformat_new_stream(oc, *codec);
  108.     if (!ost->st) {
  109.         fprintf(stderr, "Could not allocate stream\n");
  110.         exit(1);
  111.     }
  112.     ost->st->id = oc->nb_streams-1;
  113.     c = ost->st->codec;
  114.  
  115.     switch ((*codec)->type) {
  116.     case AVMEDIA_TYPE_AUDIO:
  117.         c->sample_fmt  = (*codec)->sample_fmts ?
  118.             (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
  119.         c->bit_rate    = 64000;
  120.         c->sample_rate = 44100;
  121.         if ((*codec)->supported_samplerates) {
  122.             c->sample_rate = (*codec)->supported_samplerates[0];
  123.             for (i = 0; (*codec)->supported_samplerates[i]; i++) {
  124.                 if ((*codec)->supported_samplerates[i] == 44100)
  125.                     c->sample_rate = 44100;
  126.             }
  127.         }
  128.         c->channels        = av_get_channel_layout_nb_channels(c->channel_layout);
  129.         c->channel_layout = AV_CH_LAYOUT_STEREO;
  130.         if ((*codec)->channel_layouts) {
  131.             c->channel_layout = (*codec)->channel_layouts[0];
  132.             for (i = 0; (*codec)->channel_layouts[i]; i++) {
  133.                 if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO)
  134.                     c->channel_layout = AV_CH_LAYOUT_STEREO;
  135.             }
  136.         }
  137.         c->channels        = av_get_channel_layout_nb_channels(c->channel_layout);
  138.         ost->st->time_base = (AVRational){ 1, c->sample_rate };
  139.         break;
  140.  
  141.     case AVMEDIA_TYPE_VIDEO:
  142.         c->codec_id = codec_id;
  143.  
  144.         c->bit_rate = 400000;
  145.         /* Resolution must be a multiple of two. */
  146.         c->width    = 352;
  147.         c->height   = 288;
  148.         /* timebase: This is the fundamental unit of time (in seconds) in terms
  149.          * of which frame timestamps are represented. For fixed-fps content,
  150.          * timebase should be 1/framerate and timestamp increments should be
  151.          * identical to 1. */
  152.         ost->st->time_base = (AVRational){ 1, STREAM_FRAME_RATE };
  153.         c->time_base       = ost->st->time_base;
  154.  
  155.         c->gop_size      = 12; /* emit one intra frame every twelve frames at most */
  156.         c->pix_fmt       = STREAM_PIX_FMT;
  157.         if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
  158.             /* just for testing, we also add B frames */
  159.             c->max_b_frames = 2;
  160.         }
  161.         if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
  162.             /* Needed to avoid using macroblocks in which some coeffs overflow.
  163.              * This does not happen with normal video, it just happens here as
  164.              * the motion of the chroma plane does not match the luma plane. */
  165.             c->mb_decision = 2;
  166.         }
  167.     break;
  168.  
  169.     default:
  170.         break;
  171.     }
  172.  
  173.     /* Some formats want stream headers to be separate. */
  174.     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
  175.         c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
  176. }
  177.  
  178. /**************************************************************/
  179. /* audio output */
  180.  
  181. static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt,
  182.                                   uint64_t channel_layout,
  183.                                   int sample_rate, int nb_samples)
  184. {
  185.     AVFrame *frame = av_frame_alloc();
  186.     int ret;
  187.  
  188.     if (!frame) {
  189.         fprintf(stderr, "Error allocating an audio frame\n");
  190.         exit(1);
  191.     }
  192.  
  193.     frame->format = sample_fmt;
  194.     frame->channel_layout = channel_layout;
  195.     frame->sample_rate = sample_rate;
  196.     frame->nb_samples = nb_samples;
  197.  
  198.     if (nb_samples) {
  199.         ret = av_frame_get_buffer(frame, 0);
  200.         if (ret < 0) {
  201.             fprintf(stderr, "Error allocating an audio buffer\n");
  202.             exit(1);
  203.         }
  204.     }
  205.  
  206.     return frame;
  207. }
  208.  
  209. static void open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
  210. {
  211.     AVCodecContext *c;
  212.     int nb_samples;
  213.     int ret;
  214.     AVDictionary *opt = NULL;
  215.  
  216.     c = ost->st->codec;
  217.  
  218.     /* open it */
  219.     av_dict_copy(&opt, opt_arg, 0);
  220.     ret = avcodec_open2(c, codec, &opt);
  221.     av_dict_free(&opt);
  222.     if (ret < 0) {
  223.         fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret));
  224.         exit(1);
  225.     }
  226.  
  227.     /* init signal generator */
  228.     ost->t     = 0;
  229.     ost->tincr = 2 * M_PI * 110.0 / c->sample_rate;
  230.     /* increment frequency by 110 Hz per second */
  231.     ost->tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
  232.  
  233.     if (c->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)
  234.         nb_samples = 10000;
  235.     else
  236.         nb_samples = c->frame_size;
  237.  
  238.     ost->frame     = alloc_audio_frame(c->sample_fmt, c->channel_layout,
  239.                                        c->sample_rate, nb_samples);
  240.     ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout,
  241.                                        c->sample_rate, nb_samples);
  242.  
  243.     /* create resampler context */
  244.         ost->swr_ctx = swr_alloc();
  245.         if (!ost->swr_ctx) {
  246.             fprintf(stderr, "Could not allocate resampler context\n");
  247.             exit(1);
  248.         }
  249.  
  250.         /* set options */
  251.         av_opt_set_int       (ost->swr_ctx, "in_channel_count",   c->channels,       0);
  252.         av_opt_set_int       (ost->swr_ctx, "in_sample_rate",     c->sample_rate,    0);
  253.         av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt",      AV_SAMPLE_FMT_S16, 0);
  254.         av_opt_set_int       (ost->swr_ctx, "out_channel_count",  c->channels,       0);
  255.         av_opt_set_int       (ost->swr_ctx, "out_sample_rate",    c->sample_rate,    0);
  256.         av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt",     c->sample_fmt,     0);
  257.  
  258.         /* initialize the resampling context */
  259.         if ((ret = swr_init(ost->swr_ctx)) < 0) {
  260.             fprintf(stderr, "Failed to initialize the resampling context\n");
  261.             exit(1);
  262.         }
  263. }
  264.  
  265. /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
  266.  * 'nb_channels' channels. */
  267. static AVFrame *get_audio_frame(OutputStream *ost)
  268. {
  269.     AVFrame *frame = ost->tmp_frame;
  270.     int j, i, v;
  271.     int16_t *q = (int16_t*)frame->data[0];
  272.  
  273.     /* check if we want to generate more frames */
  274.     if (av_compare_ts(ost->next_pts, ost->st->codec->time_base,
  275.                       STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
  276.         return NULL;
  277.  
  278.     for (j = 0; j <frame->nb_samples; j++) {
  279.         v = (int)(sin(ost->t) * 10000);
  280.         for (i = 0; i < ost->st->codec->channels; i++)
  281.             *q++ = v;
  282.         ost->t     += ost->tincr;
  283.         ost->tincr += ost->tincr2;
  284.     }
  285.  
  286.     frame->pts = ost->next_pts;
  287.     ost->next_pts  += frame->nb_samples;
  288.  
  289.     return frame;
  290. }
  291.  
  292. /*
  293.  * encode one audio frame and send it to the muxer
  294.  * return 1 when encoding is finished, 0 otherwise
  295.  */
  296. static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
  297. {
  298.     AVCodecContext *c;
  299.     AVPacket pkt = { 0 }; // data and size must be 0;
  300.     AVFrame *frame;
  301.     int ret;
  302.     int got_packet;
  303.     int dst_nb_samples;
  304.  
  305.     av_init_packet(&pkt);
  306.     c = ost->st->codec;
  307.  
  308.     frame = get_audio_frame(ost);
  309.  
  310.     if (frame) {
  311.         /* convert samples from native format to destination codec format, using the resampler */
  312.             /* compute destination number of samples */
  313.             dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
  314.                                             c->sample_rate, c->sample_rate, AV_ROUND_UP);
  315.             av_assert0(dst_nb_samples == frame->nb_samples);
  316.  
  317.         /* when we pass a frame to the encoder, it may keep a reference to it
  318.          * internally;
  319.          * make sure we do not overwrite it here
  320.          */
  321.         ret = av_frame_make_writable(ost->frame);
  322.         if (ret < 0)
  323.             exit(1);
  324.  
  325.             /* convert to destination format */
  326.             ret = swr_convert(ost->swr_ctx,
  327.                               ost->frame->data, dst_nb_samples,
  328.                               (const uint8_t **)frame->data, frame->nb_samples);
  329.             if (ret < 0) {
  330.                 fprintf(stderr, "Error while converting\n");
  331.                 exit(1);
  332.             }
  333.             frame = ost->frame;
  334.  
  335.         frame->pts = av_rescale_q(ost->samples_count, (AVRational){1, c->sample_rate}, c->time_base);
  336.         ost->samples_count += dst_nb_samples;
  337.     }
  338.  
  339.     ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
  340.     if (ret < 0) {
  341.         fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
  342.         exit(1);
  343.     }
  344.  
  345.     if (got_packet) {
  346.         ret = write_frame(oc, &c->time_base, ost->st, &pkt);
  347.         if (ret < 0) {
  348.             fprintf(stderr, "Error while writing audio frame: %s\n",
  349.                     av_err2str(ret));
  350.             exit(1);
  351.         }
  352.     }
  353.  
  354.     return (frame || got_packet) ? 0 : 1;
  355. }
  356.  
  357. /**************************************************************/
  358. /* video output */
  359.  
  360. static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, int width, int height)
  361. {
  362.     AVFrame *picture;
  363.     int ret;
  364.  
  365.     picture = av_frame_alloc();
  366.     if (!picture)
  367.         return NULL;
  368.  
  369.     picture->format = pix_fmt;
  370.     picture->width  = width;
  371.     picture->height = height;
  372.  
  373.     /* allocate the buffers for the frame data */
  374.     ret = av_frame_get_buffer(picture, 32);
  375.     if (ret < 0) {
  376.         fprintf(stderr, "Could not allocate frame data.\n");
  377.         exit(1);
  378.     }
  379.  
  380.     return picture;
  381. }
  382.  
  383. static void open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
  384. {
  385.     int ret;
  386.     AVCodecContext *c = ost->st->codec;
  387.     AVDictionary *opt = NULL;
  388.  
  389.     av_dict_copy(&opt, opt_arg, 0);
  390.  
  391.     /* open the codec */
  392.     ret = avcodec_open2(c, codec, &opt);
  393.     av_dict_free(&opt);
  394.     if (ret < 0) {
  395.         fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));
  396.         exit(1);
  397.     }
  398.  
  399.     /* allocate and init a re-usable frame */
  400.     ost->frame = alloc_picture(c->pix_fmt, c->width, c->height);
  401.     if (!ost->frame) {
  402.         fprintf(stderr, "Could not allocate video frame\n");
  403.         exit(1);
  404.     }
  405.  
  406.     /* If the output format is not YUV420P, then a temporary YUV420P
  407.      * picture is needed too. It is then converted to the required
  408.      * output format. */
  409.     ost->tmp_frame = NULL;
  410.     if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
  411.         ost->tmp_frame = alloc_picture(AV_PIX_FMT_YUV420P, c->width, c->height);
  412.         if (!ost->tmp_frame) {
  413.             fprintf(stderr, "Could not allocate temporary picture\n");
  414.             exit(1);
  415.         }
  416.     }
  417. }
  418.  
  419. /* Prepare a dummy image. */
  420. static void fill_yuv_image(AVFrame *pict, int frame_index,
  421.                            int width, int height)
  422. {
  423.     int x, y, i, ret;
  424.  
  425.     /* when we pass a frame to the encoder, it may keep a reference to it
  426.      * internally;
  427.      * make sure we do not overwrite it here
  428.      */
  429.     ret = av_frame_make_writable(pict);
  430.     if (ret < 0)
  431.         exit(1);
  432.  
  433.     i = frame_index;
  434.  
  435.     /* Y */
  436.     for (y = 0; y < height; y++)
  437.         for (x = 0; x < width; x++)
  438.             pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
  439.  
  440.     /* Cb and Cr */
  441.     for (y = 0; y < height / 2; y++) {
  442.         for (x = 0; x < width / 2; x++) {
  443.             pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
  444.             pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
  445.         }
  446.     }
  447. }
  448.  
  449. static AVFrame *get_video_frame(OutputStream *ost)
  450. {
  451.     AVCodecContext *c = ost->st->codec;
  452.  
  453.     /* check if we want to generate more frames */
  454.     if (av_compare_ts(ost->next_pts, ost->st->codec->time_base,
  455.                       STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
  456.         return NULL;
  457.  
  458.     if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
  459.         /* as we only generate a YUV420P picture, we must convert it
  460.          * to the codec pixel format if needed */
  461.         if (!ost->sws_ctx) {
  462.             ost->sws_ctx = sws_getContext(c->width, c->height,
  463.                                           AV_PIX_FMT_YUV420P,
  464.                                           c->width, c->height,
  465.                                           c->pix_fmt,
  466.                                           SCALE_FLAGS, NULL, NULL, NULL);
  467.             if (!ost->sws_ctx) {
  468.                 fprintf(stderr,
  469.                         "Could not initialize the conversion context\n");
  470.                 exit(1);
  471.             }
  472.         }
  473.         fill_yuv_image(ost->tmp_frame, ost->next_pts, c->width, c->height);
  474.         sws_scale(ost->sws_ctx,
  475.                   (const uint8_t * const *)ost->tmp_frame->data, ost->tmp_frame->linesize,
  476.                   0, c->height, ost->frame->data, ost->frame->linesize);
  477.     } else {
  478.         fill_yuv_image(ost->frame, ost->next_pts, c->width, c->height);
  479.     }
  480.  
  481.     ost->frame->pts = ost->next_pts++;
  482.  
  483.     return ost->frame;
  484. }
  485.  
  486. /*
  487.  * encode one video frame and send it to the muxer
  488.  * return 1 when encoding is finished, 0 otherwise
  489.  */
  490. static int write_video_frame(AVFormatContext *oc, OutputStream *ost)
  491. {
  492.     int ret;
  493.     AVCodecContext *c;
  494.     AVFrame *frame;
  495.     int got_packet = 0;
  496.  
  497.     c = ost->st->codec;
  498.  
  499.     frame = get_video_frame(ost);
  500.  
  501.     if (oc->oformat->flags & AVFMT_RAWPICTURE) {
  502.         /* a hack to avoid data copy with some raw video muxers */
  503.         AVPacket pkt;
  504.         av_init_packet(&pkt);
  505.  
  506.         if (!frame)
  507.             return 1;
  508.  
  509.         pkt.flags        |= AV_PKT_FLAG_KEY;
  510.         pkt.stream_index  = ost->st->index;
  511.         pkt.data          = (uint8_t *)frame;
  512.         pkt.size          = sizeof(AVPicture);
  513.  
  514.         pkt.pts = pkt.dts = frame->pts;
  515.         av_packet_rescale_ts(&pkt, c->time_base, ost->st->time_base);
  516.  
  517.         ret = av_interleaved_write_frame(oc, &pkt);
  518.     } else {
  519.         AVPacket pkt = { 0 };
  520.         av_init_packet(&pkt);
  521.  
  522.         /* encode the image */
  523.         ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
  524.         if (ret < 0) {
  525.             fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
  526.             exit(1);
  527.         }
  528.  
  529.         if (got_packet) {
  530.             ret = write_frame(oc, &c->time_base, ost->st, &pkt);
  531.         } else {
  532.             ret = 0;
  533.         }
  534.     }
  535.  
  536.     if (ret < 0) {
  537.         fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));
  538.         exit(1);
  539.     }
  540.  
  541.     return (frame || got_packet) ? 0 : 1;
  542. }
  543.  
  544. static void close_stream(AVFormatContext *oc, OutputStream *ost)
  545. {
  546.     avcodec_close(ost->st->codec);
  547.     av_frame_free(&ost->frame);
  548.     av_frame_free(&ost->tmp_frame);
  549.     sws_freeContext(ost->sws_ctx);
  550.     swr_free(&ost->swr_ctx);
  551. }
  552.  
  553. /**************************************************************/
  554. /* media file output */
  555.  
  556. int main(int argc, char **argv)
  557. {
  558.     OutputStream video_st = { 0 }, audio_st = { 0 };
  559.     const char *filename;
  560.     AVOutputFormat *fmt;
  561.     AVFormatContext *oc;
  562.     AVCodec *audio_codec, *video_codec;
  563.     int ret;
  564.     int have_video = 0, have_audio = 0;
  565.     int encode_video = 0, encode_audio = 0;
  566.     AVDictionary *opt = NULL;
  567.  
  568.     /* Initialize libavcodec, and register all codecs and formats. */
  569.     av_register_all();
  570.  
  571.     if (argc < 2) {
  572.         printf("usage: %s output_file\n"
  573.                "API example program to output a media file with libavformat.\n"
  574.                "This program generates a synthetic audio and video stream, encodes and\n"
  575.                "muxes them into a file named output_file.\n"
  576.                "The output format is automatically guessed according to the file extension.\n"
  577.                "Raw images can also be output by using '%%d' in the filename.\n"
  578.                "\n", argv[0]);
  579.         return 1;
  580.     }
  581.  
  582.     filename = argv[1];
  583.     if (argc > 3 && !strcmp(argv[2], "-flags")) {
  584.         av_dict_set(&opt, argv[2]+1, argv[3], 0);
  585.     }
  586.  
  587.     /* allocate the output media context */
  588.     avformat_alloc_output_context2(&oc, NULL, NULL, filename);
  589.     if (!oc) {
  590.         printf("Could not deduce output format from file extension: using MPEG.\n");
  591.         avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
  592.     }
  593.     if (!oc)
  594.         return 1;
  595.  
  596.     fmt = oc->oformat;
  597.  
  598.     /* Add the audio and video streams using the default format codecs
  599.      * and initialize the codecs. */
  600.     if (fmt->video_codec != AV_CODEC_ID_NONE) {
  601.         add_stream(&video_st, oc, &video_codec, fmt->video_codec);
  602.         have_video = 1;
  603.         encode_video = 1;
  604.     }
  605.     if (fmt->audio_codec != AV_CODEC_ID_NONE) {
  606.         add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec);
  607.         have_audio = 1;
  608.         encode_audio = 1;
  609.     }
  610.  
  611.     /* Now that all the parameters are set, we can open the audio and
  612.      * video codecs and allocate the necessary encode buffers. */
  613.     if (have_video)
  614.         open_video(oc, video_codec, &video_st, opt);
  615.  
  616.     if (have_audio)
  617.         open_audio(oc, audio_codec, &audio_st, opt);
  618.  
  619.     av_dump_format(oc, 0, filename, 1);
  620.  
  621.     /* open the output file, if needed */
  622.     if (!(fmt->flags & AVFMT_NOFILE)) {
  623.         ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
  624.         if (ret < 0) {
  625.             fprintf(stderr, "Could not open '%s': %s\n", filename,
  626.                     av_err2str(ret));
  627.             return 1;
  628.         }
  629.     }
  630.  
  631.     /* Write the stream header, if any. */
  632.     ret = avformat_write_header(oc, &opt);
  633.     if (ret < 0) {
  634.         fprintf(stderr, "Error occurred when opening output file: %s\n",
  635.                 av_err2str(ret));
  636.         return 1;
  637.     }
  638.  
  639.     while (encode_video || encode_audio) {
  640.         /* select the stream to encode */
  641.         if (encode_video &&
  642.             (!encode_audio || av_compare_ts(video_st.next_pts, video_st.st->codec->time_base,
  643.                                             audio_st.next_pts, audio_st.st->codec->time_base) <= 0)) {
  644.             encode_video = !write_video_frame(oc, &video_st);
  645.         } else {
  646.             encode_audio = !write_audio_frame(oc, &audio_st);
  647.         }
  648.     }
  649.  
  650.     /* Write the trailer, if any. The trailer must be written before you
  651.      * close the CodecContexts open when you wrote the header; otherwise
  652.      * av_write_trailer() may try to use memory that was freed on
  653.      * av_codec_close(). */
  654.     av_write_trailer(oc);
  655.  
  656.     /* Close each codec. */
  657.     if (have_video)
  658.         close_stream(oc, &video_st);
  659.     if (have_audio)
  660.         close_stream(oc, &audio_st);
  661.  
  662.     if (!(fmt->flags & AVFMT_NOFILE))
  663.         /* Close the output file. */
  664.         avio_closep(&oc->pb);
  665.  
  666.     /* free the stream */
  667.     avformat_free_context(oc);
  668.  
  669.     return 0;
  670. }
  671.