]> git.sesse.net Git - ffmpeg/commitdiff
Merge commit '9897d9f4e074cdc6c7f2409885ddefe300f18dc7'
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>
Mon, 11 Apr 2016 13:06:43 +0000 (14:06 +0100)
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>
Mon, 11 Apr 2016 13:06:43 +0000 (14:06 +0100)
* commit '9897d9f4e074cdc6c7f2409885ddefe300f18dc7':
  examples/output: convert to codecpar

Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
1  2 
doc/examples/muxing.c

index d4dac5cd692fb4167450ab296aa70bf86ccdb40b,cc2cbb1bae3e308ffdb61972f29ac73a80dceed6..2fbc89bb02dd849c97b129de1758544391d732e0
@@@ -104,80 -86,57 +105,85 @@@ static void add_stream(OutputStream *os
          exit(1);
      }
  
-     ost->st = avformat_new_stream(oc, *codec);
+     ost->st = avformat_new_stream(oc, NULL);
      if (!ost->st) {
 -        fprintf(stderr, "Could not alloc stream\n");
 +        fprintf(stderr, "Could not allocate stream\n");
          exit(1);
      }
 -
 -    c = avcodec_alloc_context3(codec);
 +    ost->st->id = oc->nb_streams-1;
-     c = ost->st->codec;
++    c = avcodec_alloc_context3(*codec);
+     if (!c) {
+         fprintf(stderr, "Could not alloc an encoding context\n");
+         exit(1);
+     }
+     ost->enc = c;
  
 -    /* put sample parameters */
 -    c->sample_fmt     = codec->sample_fmts           ? codec->sample_fmts[0]           : AV_SAMPLE_FMT_S16;
 -    c->sample_rate    = codec->supported_samplerates ? codec->supported_samplerates[0] : 44100;
 -    c->channel_layout = codec->channel_layouts       ? codec->channel_layouts[0]       : AV_CH_LAYOUT_STEREO;
 -    c->channels       = av_get_channel_layout_nb_channels(c->channel_layout);
 -    c->bit_rate       = 64000;
 +    switch ((*codec)->type) {
 +    case AVMEDIA_TYPE_AUDIO:
 +        c->sample_fmt  = (*codec)->sample_fmts ?
 +            (*codec)->sample_fmts[0] : AV_SAMPLE_FMT_FLTP;
 +        c->bit_rate    = 64000;
 +        c->sample_rate = 44100;
 +        if ((*codec)->supported_samplerates) {
 +            c->sample_rate = (*codec)->supported_samplerates[0];
 +            for (i = 0; (*codec)->supported_samplerates[i]; i++) {
 +                if ((*codec)->supported_samplerates[i] == 44100)
 +                    c->sample_rate = 44100;
 +            }
 +        }
 +        c->channels        = av_get_channel_layout_nb_channels(c->channel_layout);
 +        c->channel_layout = AV_CH_LAYOUT_STEREO;
 +        if ((*codec)->channel_layouts) {
 +            c->channel_layout = (*codec)->channel_layouts[0];
 +            for (i = 0; (*codec)->channel_layouts[i]; i++) {
 +                if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO)
 +                    c->channel_layout = AV_CH_LAYOUT_STEREO;
 +            }
 +        }
 +        c->channels        = av_get_channel_layout_nb_channels(c->channel_layout);
 +        ost->st->time_base = (AVRational){ 1, c->sample_rate };
 +        break;
 +
 +    case AVMEDIA_TYPE_VIDEO:
 +        c->codec_id = codec_id;
 +
 +        c->bit_rate = 400000;
 +        /* Resolution must be a multiple of two. */
 +        c->width    = 352;
 +        c->height   = 288;
 +        /* timebase: This is the fundamental unit of time (in seconds) in terms
 +         * of which frame timestamps are represented. For fixed-fps content,
 +         * timebase should be 1/framerate and timestamp increments should be
 +         * identical to 1. */
 +        ost->st->time_base = (AVRational){ 1, STREAM_FRAME_RATE };
 +        c->time_base       = ost->st->time_base;
 +
 +        c->gop_size      = 12; /* emit one intra frame every twelve frames at most */
 +        c->pix_fmt       = STREAM_PIX_FMT;
 +        if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
 +            /* just for testing, we also add B frames */
 +            c->max_b_frames = 2;
 +        }
 +        if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
 +            /* Needed to avoid using macroblocks in which some coeffs overflow.
 +             * This does not happen with normal video, it just happens here as
 +             * the motion of the chroma plane does not match the luma plane. */
 +            c->mb_decision = 2;
 +        }
 +    break;
  
 -    ost->st->time_base = (AVRational){ 1, c->sample_rate };
 +    default:
 +        break;
 +    }
  
 -    // some formats want stream headers to be separate
 +    /* Some formats want stream headers to be separate. */
      if (oc->oformat->flags & AVFMT_GLOBALHEADER)
          c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 -
 -    /* initialize sample format conversion;
 -     * to simplify the code, we always pass the data through lavr, even
 -     * if the encoder supports the generated format directly -- the price is
 -     * some extra data copying;
 -     */
 -    ost->avr = avresample_alloc_context();
 -    if (!ost->avr) {
 -        fprintf(stderr, "Error allocating the resampling context\n");
 -        exit(1);
 -    }
 -
 -    av_opt_set_int(ost->avr, "in_sample_fmt",      AV_SAMPLE_FMT_S16,   0);
 -    av_opt_set_int(ost->avr, "in_sample_rate",     44100,               0);
 -    av_opt_set_int(ost->avr, "in_channel_layout",  AV_CH_LAYOUT_STEREO, 0);
 -    av_opt_set_int(ost->avr, "out_sample_fmt",     c->sample_fmt,       0);
 -    av_opt_set_int(ost->avr, "out_sample_rate",    c->sample_rate,      0);
 -    av_opt_set_int(ost->avr, "out_channel_layout", c->channel_layout,   0);
 -
 -    ret = avresample_open(ost->avr);
 -    if (ret < 0) {
 -        fprintf(stderr, "Error opening the resampling context\n");
 -        exit(1);
 -    }
  }
  
 +/**************************************************************/
 +/* audio output */
 +
  static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt,
                                    uint64_t channel_layout,
                                    int sample_rate, int nb_samples)
      return frame;
  }
  
 -static void open_audio(AVFormatContext *oc, OutputStream *ost)
 +static void open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
  {
      AVCodecContext *c;
 -    int nb_samples, ret;
 +    int nb_samples;
 +    int ret;
 +    AVDictionary *opt = NULL;
  
-     c = ost->st->codec;
+     c = ost->enc;
  
      /* open it */
 -    if (avcodec_open2(c, NULL, NULL) < 0) {
 -        fprintf(stderr, "could not open codec\n");
 +    av_dict_copy(&opt, opt_arg, 0);
 +    ret = avcodec_open2(c, codec, &opt);
 +    av_dict_free(&opt);
 +    if (ret < 0) {
 +        fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret));
          exit(1);
      }
  
  
      ost->frame     = alloc_audio_frame(c->sample_fmt, c->channel_layout,
                                         c->sample_rate, nb_samples);
 -    ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, AV_CH_LAYOUT_STEREO,
 -                                       44100, nb_samples);
 +    ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout,
 +                                       c->sample_rate, nb_samples);
  
+     /* copy the stream parameters to the muxer */
+     ret = avcodec_parameters_from_context(ost->st->codecpar, c);
+     if (ret < 0) {
+         fprintf(stderr, "Could not copy the stream parameters\n");
+         exit(1);
+     }
++
 +    /* create resampler context */
 +        ost->swr_ctx = swr_alloc();
 +        if (!ost->swr_ctx) {
 +            fprintf(stderr, "Could not allocate resampler context\n");
 +            exit(1);
 +        }
 +
 +        /* set options */
 +        av_opt_set_int       (ost->swr_ctx, "in_channel_count",   c->channels,       0);
 +        av_opt_set_int       (ost->swr_ctx, "in_sample_rate",     c->sample_rate,    0);
 +        av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt",      AV_SAMPLE_FMT_S16, 0);
 +        av_opt_set_int       (ost->swr_ctx, "out_channel_count",  c->channels,       0);
 +        av_opt_set_int       (ost->swr_ctx, "out_sample_rate",    c->sample_rate,    0);
 +        av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt",     c->sample_fmt,     0);
 +
 +        /* initialize the resampling context */
 +        if ((ret = swr_init(ost->swr_ctx)) < 0) {
 +            fprintf(stderr, "Failed to initialize the resampling context\n");
 +            exit(1);
 +        }
  }
  
  /* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
@@@ -275,9 -215,10 +288,9 @@@ static AVFrame *get_audio_frame(OutputS
                        STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
          return NULL;
  
 -
 -    for (j = 0; j < frame->nb_samples; j++) {
 +    for (j = 0; j <frame->nb_samples; j++) {
          v = (int)(sin(ost->t) * 10000);
-         for (i = 0; i < ost->st->codec->channels; i++)
+         for (i = 0; i < ost->enc->channels; i++)
              *q++ = v;
          ost->t     += ost->tincr;
          ost->tincr += ost->tincr2;
   * encode one audio frame and send it to the muxer
   * return 1 when encoding is finished, 0 otherwise
   */
 -static int process_audio_stream(AVFormatContext *oc, OutputStream *ost)
 +static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
  {
 +    AVCodecContext *c;
 +    AVPacket pkt = { 0 }; // data and size must be 0;
      AVFrame *frame;
 -    int got_output = 0;
      int ret;
-     c = ost->st->codec;
 +    int got_packet;
 +    int dst_nb_samples;
 +
 +    av_init_packet(&pkt);
++    c = ost->enc;
  
      frame = get_audio_frame(ost);
 -    got_output |= !!frame;
  
 -    /* feed the data to lavr */
      if (frame) {
 -        ret = avresample_convert(ost->avr, NULL, 0, 0,
 -                                 frame->extended_data, frame->linesize[0],
 -                                 frame->nb_samples);
 -        if (ret < 0) {
 -            fprintf(stderr, "Error feeding audio data to the resampler\n");
 -            exit(1);
 -        }
 -    }
 +        /* convert samples from native format to destination codec format, using the resampler */
 +            /* compute destination number of samples */
 +            dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
 +                                            c->sample_rate, c->sample_rate, AV_ROUND_UP);
 +            av_assert0(dst_nb_samples == frame->nb_samples);
  
 -    while ((frame && avresample_available(ost->avr) >= ost->frame->nb_samples) ||
 -           (!frame && avresample_get_out_samples(ost->avr, 0))) {
          /* when we pass a frame to the encoder, it may keep a reference to it
           * internally;
           * make sure we do not overwrite it here
@@@ -380,19 -402,16 +393,19 @@@ static AVFrame *alloc_picture(enum AVPi
      return picture;
  }
  
 -static void open_video(AVFormatContext *oc, OutputStream *ost)
 +static void open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
  {
 -    AVCodecContext *c;
      int ret;
-     AVCodecContext *c = ost->st->codec;
++    AVCodecContext *c = ost->enc;
 +    AVDictionary *opt = NULL;
  
 -    c = ost->enc;
 +    av_dict_copy(&opt, opt_arg, 0);
  
      /* open the codec */
 -    if (avcodec_open2(c, NULL, NULL) < 0) {
 -        fprintf(stderr, "could not open codec\n");
 +    ret = avcodec_open2(c, codec, &opt);
 +    av_dict_free(&opt);
 +    if (ret < 0) {
 +        fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));
          exit(1);
      }
  
@@@ -492,10 -517,10 +512,10 @@@ static int write_video_frame(AVFormatCo
      int ret;
      AVCodecContext *c;
      AVFrame *frame;
 -    AVPacket pkt   = { 0 };
      int got_packet = 0;
 +    AVPacket pkt = { 0 };
  
-     c = ost->st->codec;
+     c = ost->enc;
  
      frame = get_video_frame(ost);
  
@@@ -620,11 -640,11 +640,11 @@@ int main(int argc, char **argv
      while (encode_video || encode_audio) {
          /* select the stream to encode */
          if (encode_video &&
-             (!encode_audio || av_compare_ts(video_st.next_pts, video_st.st->codec->time_base,
-                                             audio_st.next_pts, audio_st.st->codec->time_base) <= 0)) {
+             (!encode_audio || av_compare_ts(video_st.next_pts, video_st.enc->time_base,
+                                             audio_st.next_pts, audio_st.enc->time_base) <= 0)) {
              encode_video = !write_video_frame(oc, &video_st);
          } else {
 -            encode_audio = !process_audio_stream(oc, &audio_st);
 +            encode_audio = !write_audio_frame(oc, &audio_st);
          }
      }