ffmpeg libx264 AVCodecContext 设置
Posted
技术标签:
【中文标题】ffmpeg libx264 AVCodecContext 设置【英文标题】:ffmpeg libx264 AVCodecContext settings 【发布时间】:2012-02-28 16:32:49 【问题描述】:我正在使用最近的 Windows(2011 年 1 月)ffmpeg 版本并尝试在 H264 中录制视频。使用以下设置可以在 MPEG4 中正常录制:
c->codec_id = CODEC_ID_MPEG4;
c->codec_type = AVMEDIA_TYPE_VIDEO;
c->width = VIDEO_WIDTH;
c->height = VIDEO_HEIGHT;
c->bit_rate = c->width * c->height * 4;
c->time_base.den = FRAME_RATE;
c->time_base.num = 1;
c->gop_size = 12;
c->pix_fmt = PIX_FMT_YUV420P;
只需将 CODEC Id 更改为 H264 就会导致 avcodec_open() 失败 (-1)。我找到了可能的设置列表How to encode h.264 with libavcodec/x264?。我已经尝试了这些,没有设置 pix_fmt,avcodec_open() 仍然失败,但如果我另外设置 c->pix_fmt = PIX_FMT_YUV420P;然后我得到一个除以零的异常。
然后我在这里看到一些帖子说我不应该设置任何内容(除了 code_id、codec_type、width、height 以及可能的 bit_rate 和 pix_fmt),因为库现在自己选择了最佳设置。我尝试了各种组合,仍然 avcode_open() 失败。
有人对当前的操作或某些设置有什么建议吗?
谢谢。
这是一组 H264 设置,它们给出了我描述的问题:
static AVStream* AddVideoStream(AVFormatContext *pOutputFmtCtx,
int frameWidth, int frameHeight, int fps)
AVCodecContext* ctx;
AVStream* stream;
stream = av_new_stream(pOutputFmtCtx, 0);
if (!stream)
return NULL;
ctx = stream->codec;
ctx->codec_id = pOutputFmtCtx->oformat->video_codec; //CODEC_ID_H264
ctx->codec_type = AVMEDIA_TYPE_VIDEO;
ctx->width = frameWidth; //704
ctx->height = frameHeight; //576
ctx->bit_rate = frameWidth * frameHeight * 4;
ctx->coder_type = 1; // coder = 1
ctx->flags|=CODEC_FLAG_LOOP_FILTER; // flags=+loop
ctx->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1
ctx->partitions|=X264_PART_I8X8+X264_PART_I4X4+X264_PART_P8X8+X264_PART_B8X8; // partitions=+parti8x8+parti4x4+partp8x8+partb8x8
ctx->me_method=ME_HEX; // me_method=hex
ctx->me_subpel_quality = 7; // subq=7
ctx->me_range = 16; // me_range=16
ctx->gop_size = 250; // g=250
ctx->keyint_min = 25; // keyint_min=25
ctx->scenechange_threshold = 40; // sc_threshold=40
ctx->i_quant_factor = 0.71; // i_qfactor=0.71
ctx->b_frame_strategy = 1; // b_strategy=1
ctx->qcompress = 0.6; // qcomp=0.6
ctx->qmin = 10; // qmin=10
ctx->qmax = 51; // qmax=51
ctx->max_qdiff = 4; // qdiff=4
ctx->max_b_frames = 3; // bf=3
ctx->refs = 3; // refs=3
ctx->directpred = 1; // directpred=1
ctx->trellis = 1; // trellis=1
ctx->flags2|=CODEC_FLAG2_BPYRAMID+CODEC_FLAG2_MIXED_REFS+CODEC_FLAG2_WPRED+CODEC_FLAG2_8X8DCT+CODEC_FLAG2_FASTPSKIP; // flags2=+bpyramid+mixed_refs+wpred+dct8x8+fastpskip
ctx->weighted_p_pred = 2; // wpredp=2
// libx264-main.ffpreset preset
ctx->flags2|=CODEC_FLAG2_8X8DCT;
ctx->flags2^=CODEC_FLAG2_8X8DCT; // flags2=-dct8x8
// if set this get divide by 0 error on avcodec_open()
// if don't set it get -1 error on avcodec_open()
//ctx->pix_fmt = PIX_FMT_YUV420P;
return stream;
【问题讨论】:
您确定 h.264 编解码器包含在 ffmpeg 构建中吗? 我正在使用ffmpeg.zeranoe.com/builds 构建。他们说它是用 --enable-libx264 构建的。 请发布您的CODEC_ID_H264代码 将 avcodeccontext avrational 设置为正确的值。 我有完全相同的问题: - 从ffmpeg.zeranoe.com/builds 下载的源代码 - avcodec_open() 为 CODEC_ID_H264 返回 -1 - avcodec_open() 非常适用于 CODEC_ID_MPEG2VIDEO - ffmpeg.zeranoe.com/builds 表明库是用 --enable-libx264 构建的 那么,你找到解决方案了吗? 【参考方案1】:根据我的经验,在初始化编解码器时,您应该尽可能少地给 FFMPEG 提供信息。这可能看起来违反直觉,但这意味着 FFMPEG 将使用它的默认设置,这比您自己的猜测更有可能起作用。看看我会在下面包括什么:
AVStream *stream;
m_video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
stream = avformat_new_stream(_outputCodec, m_video_codec);
ctx = stream->codec;
ctx->codec_id = m_fmt->video_codec;
ctx->bit_rate = m_AVIMOV_BPS; //Bits Per Second
ctx->width = m_AVIMOV_WIDTH; //Note Resolution must be a multiple of 2!!
ctx->height = m_AVIMOV_HEIGHT; //Note Resolution must be a multiple of 2!!
ctx->time_base.den = m_AVIMOV_FPS; //Frames per second
ctx->time_base.num = 1;
ctx->gop_size = m_AVIMOV_GOB; // Intra frames per x P frames
ctx->pix_fmt = AV_PIX_FMT_YUV420P;//Do not change this, H264 needs YUV format not RGB
与之前的答案一样,这里是 FFMPEG 库将 RGB 帧编码为 H264 视频的工作示例:
http://www.imc-store.com.au/Articles.asp?ID=276
对您的代码的额外思考:
你有没有像下面这样注册过?
avcodec_register_all();
av_register_all();
如果您没有在代码开头附近调用这两个函数,您对 FFMPEG 的后续调用将会失败,并且您很可能会出现段错误。
看看链接的例子,我在 VC++2010 上测试过,效果很好。
【讨论】:
以上是关于ffmpeg libx264 AVCodecContext 设置的主要内容,如果未能解决你的问题,请参考以下文章
Android FFMPeg——FFMpeg+libx264编译
ffmpeg缺少 libx264依赖时的安装方法 (linux 下)
ffmpeg/libx264 C API:从短 MP4 末尾丢弃的帧