如何设置 libavcodec 在编码 MPEG-2 4:2:2 配置文件时使用 4:2:2 色度?

发布于 2024-08-25 16:28:54 字数 2440 浏览 12 评论 0原文

我有一个使用 libavcodec (ffmpeg) 的项目。我使用它以 4:2:2 配置文件、主级别对 MPEG-2 视频进行编码。我在 AVCodecContext 中选择了像素格式 PIX_FMT_YUV422P,但是我得到的视频输出所有颜色都是错误的,在我看来,编码器错误地读取了缓冲区,就好像它认为它是 4:2:0 色度一样比 4:2:2。这是我的编解码器设置:

// 
// AVFormatContext* _avFormatContext previously defined as mpeg2video
//

//
// Set up the video stream for output
//
AVVideoStream* _avVideoStream = av_new_stream(_avFormatContext, 0);
if (!_avVideoStream)
{
    err = ccErrWFFFmpegUnableToAllocateStream;
    goto bail;
}
_avCodecContext = _avVideoStream->codec;
_avCodecContext->codec_id = CODEC_ID_MPEG2VIDEO;
_avCodecContext->codec_type = CODEC_TYPE_VIDEO;

//
// Set up required parameters
//
_avCodecContext->rc_max_rate = _avCodecContext->rc_min_rate = _avCodecContext->bit_rate = src->_avCodecContext->bit_rate;
_avCodecContext->flags = CODEC_FLAG_INTERLACED_DCT;
_avCodecContext->flags2 = CODEC_FLAG2_INTRA_VLC | CODEC_FLAG2_NON_LINEAR_QUANT;
_avCodecContext->qmin = 1;
_avCodecContext->qmax = 1;
_avCodecContext->rc_buffer_size = _avCodecContext->rc_initial_buffer_occupancy = 2000000;
_avCodecContext->rc_buffer_aggressivity = 0.25;
_avCodecContext->profile = 0;
_avCodecContext->level = 5;
_avCodecContext->width = f->GetWidth(); // f is a private Frame class with width, height properties etc.
_avCodecContext->height = f->GetHeight();
_avCodecContext->time_base.den = 25;
_avCodecContext->time_base.num = 1;
_avCodecContext->gop_size = 12;
_avCodecContext->max_b_frames = 2;
_avCodecContext->pix_fmt = PIX_FMT_YUV422P;

if (_avFormatContext->oformat->flags & AVFMT_GLOBALHEADER)
{
    _avCodecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
}

if (av_set_parameters(_avFormatContext, NULL) < 0)
{
    err = ccErrWFFFmpegUnableToSetParameters;
    goto bail;
}

//
// Set up video codec for encoding
//
AVCodec* _avCodec = avcodec_find_encoder(_avCodecContext->codec_id);
if (!_avCodec)
{
    err = ccErrWFFFmpegUnableToFindCodecForOutput;
    goto bail;
}
if (avcodec_open(_avCodecContext, _avCodec) < 0)
{
    err = ccErrWFFFmpegUnableToOpenCodecForOutput;
    goto bail;
}

可以在 http://ftp 上看到生成的视频帧的屏幕截图。 Limeboy.com/images/screen_grab.png(输入是标准颜色条)。

我已经通过在过程中的各个点将调试帧输出为 TGA 格式进行了检查,并且我可以确认在 libavcodec 对帧进行编码之前一切都很好。

非常感谢任何帮助!

干杯, 麦克风。

I have a project using libavcodec (ffmpeg). I'm using it to encode MPEG-2 video at 4:2:2 Profile, Main Level. I have the pixel format PIX_FMT_YUV422P selected in the AVCodecContext, however the video output I'm getting has all the colours wrong, and looks to me like the encoder is incorrectly reading the buffers as though it thinks it is 4:2:0 chroma rather than 4:2:2. Here's my codec setup:

// 
// AVFormatContext* _avFormatContext previously defined as mpeg2video
//

//
// Set up the video stream for output
//
AVVideoStream* _avVideoStream = av_new_stream(_avFormatContext, 0);
if (!_avVideoStream)
{
    err = ccErrWFFFmpegUnableToAllocateStream;
    goto bail;
}
_avCodecContext = _avVideoStream->codec;
_avCodecContext->codec_id = CODEC_ID_MPEG2VIDEO;
_avCodecContext->codec_type = CODEC_TYPE_VIDEO;

//
// Set up required parameters
//
_avCodecContext->rc_max_rate = _avCodecContext->rc_min_rate = _avCodecContext->bit_rate = src->_avCodecContext->bit_rate;
_avCodecContext->flags = CODEC_FLAG_INTERLACED_DCT;
_avCodecContext->flags2 = CODEC_FLAG2_INTRA_VLC | CODEC_FLAG2_NON_LINEAR_QUANT;
_avCodecContext->qmin = 1;
_avCodecContext->qmax = 1;
_avCodecContext->rc_buffer_size = _avCodecContext->rc_initial_buffer_occupancy = 2000000;
_avCodecContext->rc_buffer_aggressivity = 0.25;
_avCodecContext->profile = 0;
_avCodecContext->level = 5;
_avCodecContext->width = f->GetWidth(); // f is a private Frame class with width, height properties etc.
_avCodecContext->height = f->GetHeight();
_avCodecContext->time_base.den = 25;
_avCodecContext->time_base.num = 1;
_avCodecContext->gop_size = 12;
_avCodecContext->max_b_frames = 2;
_avCodecContext->pix_fmt = PIX_FMT_YUV422P;

if (_avFormatContext->oformat->flags & AVFMT_GLOBALHEADER)
{
    _avCodecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
}

if (av_set_parameters(_avFormatContext, NULL) < 0)
{
    err = ccErrWFFFmpegUnableToSetParameters;
    goto bail;
}

//
// Set up video codec for encoding
//
AVCodec* _avCodec = avcodec_find_encoder(_avCodecContext->codec_id);
if (!_avCodec)
{
    err = ccErrWFFFmpegUnableToFindCodecForOutput;
    goto bail;
}
if (avcodec_open(_avCodecContext, _avCodec) < 0)
{
    err = ccErrWFFFmpegUnableToOpenCodecForOutput;
    goto bail;
}

A screengrab of the resulting video frame can be seen at http://ftp.limeboy.com/images/screen_grab.png (the input was standard colour bars).

I've checked by outputting debug frames to TGA format at various points in the process, and I can confirm that it is all fine and dandy up until the point that libavcodec encodes the frame.

Any assistance most appreciated!

Cheers,
Mike.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

離人涙 2024-09-01 16:28:54

好吧,这很尴尬。

其实我的设置方式是正确的。查看 ffmpeg 的源代码,似乎要使其编码 4:2:2 配置文件和 4:2:2 色度,您所需要做的就是将传入像素格式设置为 PIX_FMT_YUV422P。

问题的原因是什么?我在虚拟机中的 VLC 上观看视频文件,该虚拟机在某个阶段已将其视频分辨率从 32 位更改为 16 位。

这是正确的! IT 改变了它。我没有改变它——是它改变了它!就其本身而言,你听到我的声音!

如果有人浪费时间去追寻这个不存在的问题,我深表歉意。

OK, this is embarrassing.

Actually, the way I had it set up is correct. Looking through the source code for ffmpeg, it appears that all you have to do to get it to encode 4:2:2 profile and 4:2:2 chroma is to set the incoming pixel format to PIX_FMT_YUV422P.

The cause of the problem? I was watching the video file back on VLC in a virtual machine, which at some stage had changed its video resolution from 32-bit to 16-bit.

That's right! IT changed it. I didn't change it - IT did it! BY ITSELF, YOU HEAR ME!!

Apologies if anyone wasted their time chasing down this non-issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文