-----Original Message----- From: Libav-user [mailto:[email protected]] 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 <[email protected]> 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 [email protected] http://ffmpeg.org/mailman/listinfo/libav-user _______________________________________________ Libav-user mailing list [email protected] http://ffmpeg.org/mailman/listinfo/libav-user
