title: FFmpeg not honoring bitrate for different containers?
body: <p>I am attempting to encode a <strong>mp4</strong> video file into a <strong>flv</strong> video. Here is what I am doing:</p>
  
  <pre><code>#include &lt;stdlib.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;string.h&gt;
  #include &lt;math.h&gt;
  #include &lt;libavcodec/avcodec.h&gt;
  #include &lt;libavformat/avformat.h&gt;
  
  #define STREAM_FRAME_RATE 30 /* 30 images/s */
  #define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
  /**************************************************************/
  /* Add an output stream. */
  static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,
          enum AVCodecID codec_id) {
      AVCodecContext *c;
      AVStream *st;
      /* find the encoder */
      *codec = avcodec_find_encoder(codec_id);
      if (!(*codec)) {
          fprintf(stderr, "Could not find encoder for '%s'\n",
                  avcodec_get_name(codec_id));
          exit(1);
      }
      st = avformat_new_stream(oc, *codec);
      if (!st) {
          fprintf(stderr, "Could not allocate stream\n");
          exit(1);
      }
      st-&gt;id = oc-&gt;nb_streams - 1;
      c = st-&gt;codec;
      switch ((*codec)-&gt;type) {
      case AVMEDIA_TYPE_VIDEO:
          //avcodec_get_context_defaults3(c, *codec);
          c-&gt;codec_id = codec_id;
          c-&gt;bit_rate = 150 * 1000; //2314000;;
          //c-&gt;rc_max_rate = 150*1000;
          //c-&gt;rc_buffer_size = 150*1000;
          /* Resolution must be a multiple of two. */
          c-&gt;width = 1280;
          c-&gt;height = 720;
          /* 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. */
          c-&gt;time_base.den = STREAM_FRAME_RATE;
          c-&gt;time_base.num = 1;
          c-&gt;gop_size = 12; /* emit one intra frame every twelve frames at most */
          c-&gt;pix_fmt = STREAM_PIX_FMT;
          if (c-&gt;codec_id == AV_CODEC_ID_MPEG2VIDEO) {
              /* just for testing, we also add B frames */
              c-&gt;max_b_frames = 2;
          }
          if (c-&gt;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-&gt;mb_decision = 2;
          }
          break;
      default:
          break;
      }
      /* Some formats want stream headers to be separate. */
      if (oc-&gt;oformat-&gt;flags &amp; AVFMT_GLOBALHEADER)
          c-&gt;flags |= CODEC_FLAG_GLOBAL_HEADER;
      return st;
  }
  /**************************************************************/
  /* video output */
  static AVFrame *frame;
  static AVPicture src_picture, dst_picture;
  static int frame_count;
  static void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st) {
      int ret;
      AVCodecContext *c = st-&gt;codec;
      /* open the codec */
      ret = avcodec_open2(c, codec, NULL);
      if (ret &lt; 0) {
          fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));
          exit(1);
      }
      /* allocate and init a re-usable frame */
      frame = avcodec_alloc_frame();
      if (!frame) {
          fprintf(stderr, "Could not allocate video frame\n");
          exit(1);
      }
      /* Allocate the encoded raw picture. */
      ret = avpicture_alloc(&amp;dst_picture, c-&gt;pix_fmt, c-&gt;width, c-&gt;height);
      if (ret &lt; 0) {
          fprintf(stderr, "Could not allocate picture: %s\n", av_err2str(ret));
          exit(1);
      }
      /* If the output format is not YUV420P, then a temporary YUV420P
       * picture is needed too. It is then converted to the required
       * output format. */
      if (c-&gt;pix_fmt != AV_PIX_FMT_YUV420P) {
          ret = avpicture_alloc(&amp;src_picture, AV_PIX_FMT_YUV420P, c-&gt;width,
                  c-&gt;height);
          if (ret &lt; 0) {
              fprintf(stderr, "Could not allocate temporary picture: %s\n",
                      av_err2str(ret));
              exit(1);
          }
      }
      /* copy data and linesize picture pointers to frame */
      *((AVPicture *) frame) = dst_picture;
  }
  static void close_video(AVFormatContext *oc, AVStream *st) {
      avcodec_close(st-&gt;codec);
      av_free(src_picture.data[0]);
      av_free(dst_picture.data[0]);
      av_free(frame);
  }
  
  int main(int argc, char *argv[]) {
      AVFormatContext *pFormatCtx = NULL;
      int i, videoStream;
      AVCodecContext *pCodecCtx = NULL;
      AVCodec *pCodec;
      AVFrame *pFrame;
      AVPacket packet;
      int frameFinished;
  
      const char *filename;
      AVOutputFormat *fmt;
      AVFormatContext *oc;
      AVStream *video_st;
      AVCodec *video_codec;
      int ret;
  
      // Register all formats, codecs and network
      av_register_all();
      avcodec_register_all();
      avformat_network_init();
  
      // Open video file
      if (avformat_open_input(&amp;pFormatCtx, "input_file.mp4", NULL, NULL) != 0)
          return -1; // Couldn't open file
  
      // Retrieve stream information
      if (avformat_find_stream_info(pFormatCtx, NULL) &lt; 0)
          return -1; // Couldn't find stream information
  
      // Dump information about file onto standard error
      av_dump_format(pFormatCtx, 0, "input_file.mp4", 0);
  
      // Find the first video stream
      videoStream = -1;
      for (i = 0; i &lt; pFormatCtx-&gt;nb_streams; i++)
          if (pFormatCtx-&gt;streams[i]-&gt;codec-&gt;codec_type == AVMEDIA_TYPE_VIDEO) {
              videoStream = i;
              break;
          }
      if (videoStream == -1)
          return -1; // Didn't find a video stream
  
      // Get a pointer to the codec context for the video stream
      pCodecCtx = pFormatCtx-&gt;streams[videoStream]-&gt;codec;
  
      // Find the decoder for the video stream
      pCodec = avcodec_find_decoder(pCodecCtx-&gt;codec_id);
      if (pCodec == NULL) {
          fprintf(stderr, "Unsupported codec!\n");
          return -1; // Codec not found
      }
      // Open codec
      if (avcodec_open2(pCodecCtx, pCodec, NULL) &lt; 0)
          return -1; // Could not open codec
  
      // Allocate video frame
      pFrame = avcodec_alloc_frame();
  
      // setup mux
      filename = "output_file.flv";
      fmt = av_guess_format("flv", filename, NULL);
      if (fmt == NULL) {
          printf("Could not guess format.\n");
          return -1;
      }
      // allocate the output media context
      oc = avformat_alloc_context();
      if (oc == NULL) {
          printf("could not allocate context.\n");
          return -1;
      }
      oc-&gt;oformat = fmt;
  
      // Add the video streams using the default format codecs
      // and initialize the codecs.
      video_st = NULL;
      if (fmt-&gt;video_codec != AV_CODEC_ID_NONE) {
          video_st = add_stream(oc, &amp;video_codec, fmt-&gt;video_codec);
      }
      // Now that all the parameters are set, we can open the
      // video codec and allocate the necessary encode buffers.
      if (video_st)
          open_video(oc, video_codec, video_st);
  
      /* open the output file, if needed */
      if (!(fmt-&gt;flags &amp; AVFMT_NOFILE)) {
          ret = avio_open(&amp;oc-&gt;pb, filename, AVIO_FLAG_WRITE);
          if (ret &lt; 0) {
              fprintf(stderr, "Could not open '%s': %s\n", filename,
                      av_err2str(ret));
              return 1;
          }
      }
  
      // dump output format
      av_dump_format(oc, 0, filename, 1);
  
      // Write the stream header, if any.
      ret = avformat_write_header(oc, NULL);
      if (ret &lt; 0) {
          fprintf(stderr, "Error occurred when opening output file: %s\n",
                  av_err2str(ret));
          return 1;
      }
  
      // Read frames, decode, and re-encode
      while (av_read_frame(pFormatCtx, &amp;packet) &gt;= 0) {
          // Is this a packet from the video stream?
          if (packet.stream_index == videoStream) {
              // Decode video frame
              avcodec_decode_video2(pCodecCtx, pFrame, &amp;frameFinished, &amp;packet);
  
              // Did we get a video frame?
              if (frameFinished) {
  
                  AVFrame* newFrame = avcodec_alloc_frame(); // Initialize a new frame
                  int size = avpicture_get_size(video_st-&gt;codec-&gt;pix_fmt,
                          video_st-&gt;codec-&gt;width, video_st-&gt;codec-&gt;height);
                  uint8_t* picture_buf = av_malloc(size);
  
                  avpicture_fill((AVPicture *) newFrame, picture_buf,
                          video_st-&gt;codec-&gt;pix_fmt, video_st-&gt;codec-&gt;width,
                          video_st-&gt;codec-&gt;height);
  
                  // Copy only the frame content without any other disturbing
                  av_picture_copy((AVPicture*) newFrame, (AVPicture*) pFrame,
                          video_st-&gt;codec-&gt;pix_fmt, video_st-&gt;codec-&gt;width,
                          video_st-&gt;codec-&gt;height);
  
                  // encode the image
                  AVPacket pkt;
                  int got_output;
                  av_init_packet(&amp;pkt);
                  pkt.data = NULL; // packet data will be allocated by the encoder
                  pkt.size = 0;
  
                  /* Setting newFrame-&gt;pts this way produces the error 'non-strictly-monotonic PTS' */
                  //if(newFrame-&gt;pts != AV_NOPTS_VALUE)
                  //newFrame-&gt;pts = av_rescale_q(newFrame-&gt;pts, video_st-&gt;time_base, video_st-&gt;codec-&gt;time_base);
  
                  // Setting newFrame-&gt;pts this does not produce 'non-strictly-monotonic PTS'
                  newFrame-&gt;pts = frame_count;
  
                  ret = avcodec_encode_video2(video_st-&gt;codec, &amp;pkt, newFrame, &amp;got_output);
                  if (ret &lt; 0) {
                      fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
                      exit(1);
                  }
  
                  if (got_output) {
                      if (video_st-&gt;codec-&gt;coded_frame-&gt;key_frame)
                      pkt.flags |= AV_PKT_FLAG_KEY;
                      pkt.stream_index = video_st-&gt;index;
  
                      if (pkt.pts != AV_NOPTS_VALUE)
                          pkt.pts = av_rescale_q(pkt.pts,
                                  video_st-&gt;codec-&gt;time_base,
                                  video_st-&gt;time_base);
                      if (pkt.dts != AV_NOPTS_VALUE)
                          pkt.dts = av_rescale_q(pkt.dts,
                                  video_st-&gt;codec-&gt;time_base,
                                  video_st-&gt;time_base);
  
                      // Write the compressed frame to the media file.
                      ret = av_interleaved_write_frame(oc, &amp;pkt);
                  } else {
                      ret = 0;
                  }
                  if (ret != 0) {
                      fprintf(stderr, "Error while writing video frame: %s\n",
                              av_err2str(ret));
                      exit(1);
                  }
  
                  fprintf(stderr, "encoded frame #%d\n", frame_count);
                  frame_count++;
                  av_free(picture_buf);
                  av_free_packet(&amp;pkt);
              }
          }
  
          // Free the packet that was allocated by av_read_frame
          av_free_packet(&amp;packet);
      }
  
      /* Write the trailer, if any. The trailer must be written before you
       * close the CodecContexts open when you wrote the header; otherwise
       * av_write_trailer() may try to use memory that was freed on
       * av_codec_close(). */
      av_write_trailer(oc);
  
      /* Close video encoder (codec). */
      if (video_st)
          close_video(oc, video_st);
      // Free the streams.
      for (i = 0; i &lt; oc-&gt;nb_streams; i++) {
          av_freep(&amp;oc-&gt;streams[i]-&gt;codec);
          av_freep(&amp;oc-&gt;streams[i]);
      }
      if (!(fmt-&gt;flags &amp; AVFMT_NOFILE))
          /* Close the output file. */
          avio_close(oc-&gt;pb);
      /* free the stream */
      av_free(oc);
  
      // Free the YUV frame holding decoded frame
      av_free(pFrame);
  
      // Close the decoder (codec)
      avcodec_close(pCodecCtx);
  
      // Close the input video file
      avformat_close_input(&amp;pFormatCtx);
  
      return 0;
  }
  </code></pre>
  
  <p>If I change the output format to an <strong>mp4, mov, or f4v</strong> by changing:</p>
  
  <pre><code>// setup mux (FLV OUTPUT)
  filename = "output_file.flv";
  fmt = av_guess_format("flv", filename, NULL);
  if (fmt == NULL) {
      printf("Could not guess format.\n");
      return -1;
  }
  </code></pre>
  
  <p>to</p>
  
  <pre><code>// setup mux (MP4 OUTPUT)
  filename = "output_file.mp4";
  fmt = av_guess_format("mp4", filename, NULL);
  if (fmt == NULL) {
      printf("Could not guess format.\n");
      return -1;
  }
  </code></pre>
  
  <p>Then the bitrate is honored. Here is the output of running with a <strong>mp4</strong> output</p>
  
  <pre><code>Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input_file.mp4':
    Metadata:
      major_brand     : mp42
      minor_version   : 0
      compatible_brands: isomavc1mp42
      creation_time   : 2010-02-09 19:11:10
    Duration: 00:04:31.80, start: 0.000000, bitrate: 2314 kb/s
      Stream #0:0(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s
      Metadata:
        creation_time   : 2010-02-09 19:11:10
        handler_name    : (C) 2007 Google Inc. v08.13.2007.
      Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 2186 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc
      Metadata:
        creation_time   : 2010-02-09 19:11:10
        handler_name    : (C) 2007 Google Inc. v08.13.2007.
  [libx264 @ 02268b80] using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE4.2 AVX
  [libx264 @ 02268b80] profile High, level 3.1
  [libx264 @ 02268b80] 264 - core 129 r2230 1cffe9f - H.264/MPEG-4 AVC codec - Copyleft 2003-2012 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deb
  lock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chro
  ma_qp_offset=-2 threads=12 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1
   b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=12 keyint_min=1 scenecut=40 intra_refresh=0 rc_lookahead=12 rc=abr mbtree=1 bitrate=150 ratetol=1.0 qco
  mp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
  Output #0, mp4, to 'output_file.mp4':
      Stream #0:0: Video: h264, yuv420p, 1280x720, q=-1--1, 150 kb/s, 90k tbn, 30 tbc
  encoded frame #0
  encoded frame #1
  encoded frame #2
  encoded frame #3
  .
  .
  .
  encoded frame #8142
  encoded frame #8143
  encoded frame #8144
  encoded frame #8145
  [libx264 @ 02174240] frame I:771   Avg QP:47.71  size:  2739
  [libx264 @ 02174240] frame P:5083  Avg QP:50.05  size:   833
  [libx264 @ 02174240] frame B:2264  Avg QP:48.16  size:    91
  [libx264 @ 02174240] consecutive B-frames: 59.6%  6.4%  9.0% 24.9%
  [libx264 @ 02174240] mb I  I16..4: 34.0% 65.8%  0.2%
  [libx264 @ 02174240] mb P  I16..4:  6.8%  3.0%  0.0%  P16..4:  8.5%  0.4%  1.7%  0.0%  0.0%    skip:79.6%
  [libx264 @ 02174240] mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  1.8%  0.0%  0.0%  direct: 0.0%  skip:98.2%  L0:23.6% L1:76.4% BI: 0.0%
  [libx264 @ 02174240] final ratefactor: 57.62
  [libx264 @ 02174240] 8x8 transform intra:52.1% inter:98.5%
  [libx264 @ 02174240] coded y,uvDC,uvAC intra: 3.1% 14.0% 0.2% inter: 0.1% 0.4% 0.0%
  [libx264 @ 02174240] i16 v,h,dc,p: 69% 23%  4%  4%
  [libx264 @ 02174240] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 23%  6% 68%  1%  1%  1%  1%  0%  0%
  [libx264 @ 02174240] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 41% 18% 18%  4%  4%  5%  3%  3%  3%
  [libx264 @ 02174240] i8c dc,h,v,p: 98%  1%  1%  0%
  [libx264 @ 02174240] Weighted P-Frames: Y:2.1% UV:1.2%
  [libx264 @ 02174240] ref P L0: 72.4%  0.8% 19.1%  7.6%  0.1%
  [libx264 @ 02174240] ref B L0: 89.8%  9.1%  1.2%
  [libx264 @ 02174240] ref B L1: 96.2%  3.8%
  [libx264 @ 02174240] kb/s:193.62
  </code></pre>
  
  <p>The final file size of <strong>output_file.mp4</strong> is about <strong>6.5MB</strong> and using ffplay, I notice that bitrate was honored. Of course the quality itself shows.</p>
  
  <p>Here is the output of running with a <strong>flv</strong> output:</p>
  
  <pre><code>Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'input_file.mp4':
    Metadata:
      major_brand     : mp42
      minor_version   : 0
      compatible_brands: isomavc1mp42
      creation_time   : 2010-02-09 19:11:10
    Duration: 00:04:31.80, start: 0.000000, bitrate: 2314 kb/s
      Stream #0:0(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s
      Metadata:
        creation_time   : 2010-02-09 19:11:10
        handler_name    : (C) 2007 Google Inc. v08.13.2007.
      Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 2186 kb/s, 30 fps, 30 tbr, 30k tbn, 60 tbc
      Metadata:
        creation_time   : 2010-02-09 19:11:10
        handler_name    : (C) 2007 Google Inc. v08.13.2007.
  Output #0, flv, to 'output_file.flv':
      Stream #0:0: Video: flv1, yuv420p, 1280x720, q=2-31, 150 kb/s, 90k tbn, 30 tbc
  encoded frame #0
  encoded frame #1
  encoded frame #2
  encoded frame #3
  .
  .
  .
  encoded frame #8142
  encoded frame #8143
  encoded frame #8144
  encoded frame #8145
  </code></pre>
  
  <p>I noticed that the bitrate is honored as long as the container is a mp4, mov, f4v, or something similar. If I try flv, wmv, or other different containers, then the bitrate is not honored. Also, the bitrate that is automatically set for wmv is different from that of flv. I am not sure what I am doing wrong. I suspect it has to do with the <strong>pts</strong>, however, I cannot find a solution :(.</p>