[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