[Libav-user] Bitrate parameter ignored when writing videos

Masneri, Stefano stefano.masneri at brain.mpg.de
Thu Aug 11 10:08:22 EEST 2016


-----Original Message-----
From: Libav-user [mailto:libav-user-bounces at ffmpeg.org] On Behalf Of Paul B Mahol
Sent: Mittwoch, 10. August 2016 18:25
To: This list is about using libavcodec, libavformat, libavutil, libavdevice and libavfilter.
Subject: Re: [Libav-user] Bitrate parameter ignored when writing videos

>>On 8/10/16, Masneri, Stefano <stefano.masneri at brain.mpg.de> wrote:
>> I am trying to write an .mp4 video with a specified bitrate and 
>> gopsize set to 1.
>> Apparently libavcodec ignores the settings I provide and creates a 
>> video with a much higher bitrate
>>
>> Here's the code I use to setup the output video:
>>
>>   m_pcVideoSt->codec->gop_size = m_iGopSize; /* emit one intra frame 
>> every m_iGopSize frames at most */
>>  m_pcVideoSt->codec->pix_fmt = AV_PIX_FMT_YUV420P; /* default pix_fmt */
>>   m_pcVideoSt->codec->max_b_frames = 1;
>>   AVDictionary* pcOpts = nullptr;
>>   int res1 = av_dict_set(&pcOpts, "b", "20k", 0);
>>   int res = avcodec_open2(m_pcVideoSt->codec, codec, &pcOpts);
>>
>> m_pcVideoSt is of type AVStream*
>>
>> This is the output of ffprobe ran on the video I wrote:
>>
>> Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'testGray.mp4':
>>   Metadata:
>>     major_brand     : isom
>>     minor_version   : 512
>>     compatible_brands: isomiso2avc1mp41
>>     encoder         : Lavf56.40.101
>>   Duration: 00:00:20.00, start: 0.000000, bitrate: 8905 kb/s
>>     Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 
>> 720x576, 8904 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default)
>>     Metadata:
>>       handler_name    : VideoHandler
>>
>> When watching the video, it seems that the quality is low for the 
>> first few frames, but then the quality gets much better (explaining 
>> the 8905Kb/s bitrate).
>> Any idea on what I am missing?

>Above I do not see relevant code that calls encoder.

Yes, I was trying to keep the code to a minimum. Here's what I do to initialize my Video Writer class. Any suggestions will be appreciated

//init 
  avcodec_register_all();
  av_register_all();

  //guess format (mpeg as default)
  AVOutputFormat* outFmt = nullptr;
  outFmt = av_guess_format(NULL, m_pcFilename.c_str(), NULL);
  if (!outFmt)
  {
    outFmt = av_guess_format("mpeg", NULL, NULL);
    if (!outFmt) //paranoia
    {
      return -1;
    }
  }
  //get codecID
  AVCodecID codecID = outFmt->video_codec;

  //AVFormatContext memory allocation
  avformat_alloc_output_context2(&m_pcOC, outFmt, NULL, NULL);
  if (!m_pcOC)
  {
    return -1;
  }
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
  strncpy_s(m_pcOC->filename, sizeof(m_pcOC->filename), m_pcFilename.c_str(), sizeof(m_pcOC->filename));
#else
  strncpy(m_pcOC->filename, m_pcFilename.c_str(), m_pcFilename.size());
#endif
  //define video stream
  m_pcVideoSt = avformat_new_stream(m_pcOC, NULL);
  AVCodec* codec = nullptr;
  codec = avcodec_find_encoder(codecID);
  avcodec_get_context_defaults3(m_pcVideoSt->codec, codec);

  // set some required values for codec
  m_pcVideoSt->codec->codec_id = codecID;
  m_pcVideoSt->codec->codec_type = AVMEDIA_TYPE_VIDEO;
  //m_pcVideoSt->codec->bit_rate = 10;
  m_pcVideoSt->codec->bit_rate_tolerance = 20000;
  m_pcVideoSt->codec->width = m_iOutCols;
  m_pcVideoSt->codec->height = m_iOutRows;
  /* time base: 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
  identically 1. */
  if (dFps > 29 && dFps < 30) //29.97
  {
    m_pcVideoSt->codec->time_base.den = 30000;
    m_pcVideoSt->codec->time_base.den = 1001;
    m_pcVideoSt->time_base.den = 30000;
    m_pcVideoSt->time_base.num = 1001;
    m_pcOC->streams[0]->time_base.den = 30000;
    m_pcOC->streams[0]->time_base.num = 1001;
  }
  else
  {
    m_pcVideoSt->codec->time_base.den = static_cast<int>(dFps);
    m_pcVideoSt->codec->time_base.num = 1;
    m_pcVideoSt->time_base.den = static_cast<int>(dFps);
    m_pcVideoSt->time_base.num = 1;
    m_pcOC->streams[0]->time_base.den = static_cast<int>(dFps);
    m_pcOC->streams[0]->time_base.num = 1;
  }
  m_pcVideoSt->codec->gop_size = m_iGopSize; /* emit one intra frame every m_iGopSize frames at most */
  m_pcVideoSt->codec->pix_fmt = AV_PIX_FMT_YUV420P; /* default pix_fmt */
  m_pcVideoSt->codec->max_b_frames = 1;
  // needed for x264 to work
  if (m_pcVideoSt->codec->codec_id == AV_CODEC_ID_H264)
  {
    av_opt_set(m_pcVideoSt->codec->priv_data, "b", bitrate.c_str(), AV_OPT_SEARCH_CHILDREN);
  }

  // some formats want stream headers to be separate
  if (m_pcOC->oformat->flags & AVFMT_GLOBALHEADER)
  {
    m_pcVideoSt->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  }

  /* open the codec */
  AVDictionary* pcOpts = nullptr;
  int res1 = av_dict_set(&pcOpts, "b", bitrate.c_str(), 0);
  int res = avcodec_open2(m_pcVideoSt->codec, codec, &pcOpts);
  if (res < 0)
  {
    return -1;
  }

  /* allocate the encoded raw picture */
  m_pcPicture = allocPicture(m_pcVideoSt->codec->pix_fmt, m_pcVideoSt->codec->width, m_pcVideoSt->codec->height);

  if (!m_pcPicture)
  {
    std::cout << "ERROR: Cannot allocate memory for AVFrame structures" << std::endl;
    return -1;
  }

  /* init the sws contexts */
  m_pcColCvtCtx = sws_getCachedContext(m_pcColCvtCtx, m_iInputCols, m_iInputRows,
    AV_PIX_FMT_YUV420P, m_iInputCols, m_iInputRows, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);

  m_pcOutCtx = sws_getCachedContext(m_pcOutCtx, m_iInputCols, m_iInputRows,
    srcFmt, m_iOutCols, m_iOutRows, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

  /* open the output file, if needed */
  if (!(m_pcOC->oformat->flags & AVFMT_NOFILE))
  {
    if (avio_open(&m_pcOC->pb, m_pcFilename.c_str(), AVIO_FLAG_WRITE) < 0)
    {
      return -1;
    }
  }

  /* write the stream header, if any */
  avformat_write_header(m_pcOC, NULL);

  av_dict_free(&pcOpts);
  m_bIsInited = true;

  return 0;
_______________________________________________
Libav-user mailing list
Libav-user at ffmpeg.org
http://ffmpeg.org/mailman/listinfo/libav-user


More information about the Libav-user mailing list