FFMPEG:sws_scale 返回错误:切片参数 0、2160 无效

Posted

技术标签:

【中文标题】FFMPEG:sws_scale 返回错误:切片参数 0、2160 无效【英文标题】:FFMPEG: sws_scale returns error: Slice parameters 0, 2160 are invalid 【发布时间】:2020-01-16 21:48:44 【问题描述】:

我正在尝试按照教程在 SDL 中显示 ffmpeg AVFrame 输出。本教程(以及我在网上看到的所有示例)仍在使用“sws_getContext”,它已被弃用并从最新版本的 ffmpeg 中删除。尝试将当前像素格式从当前的任何格式更改为 PIX_FMT_YUV420P,以便我可以显示它。我相信我需要 sws_scale 函数来完成这个。

但是,sws_scale 是导致以下命令行错误的函数: 切片参数0、2160无效

这是我所有与 swsContext 相关的代码:

struct SwsContext* av_sws_ctx = NULL;
av_sws_ctx = sws_alloc_context();

sws_init_context(av_sws_ctx, NULL, NULL);

sws_scale(av_sws_ctx, (uint8_t const* const*)av_frame->data,
                        av_frame->linesize, 0, av_codec_context->height,
                        av_frame->data, av_frame->linesize);

更复杂的是,SwsContext 仅在 ffmpeg 内部定义,在外部我无法设置/获取任何变量,甚至无法在调试器中查看它们。

int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[])

除av_sws_ctx以外的其他参数值:

srcSlice: av_frame->data = 
     8 arrays, first is filled with "\x10\x10\x10\x10\x10..."
     second and third are "€€€€€€€€€€€€€€€€€..."
     rest are NULL
linesize(av_frame->linesize) is an array:
    3840,1920,1920,0,0,0,0,0
srcSliceY:0
srcSliceH:2160
dest: same as second parameter (av_frame->data)
dstStride: av_frame->linesize again

如果我钻研 sws_scale 源代码,我发现这个错误是由这块代码抛出的:

if ((srcSliceY & (macro_height-1)) ||
        ((srcSliceH& (macro_height-1)) && srcSliceY + srcSliceH != c->srcH) ||
        srcSliceY + srcSliceH > c->srcH) 
        av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH);
        return AVERROR(EINVAL);
    

因此,我认为问题在于我的视频的高度大于 sws_context(4k 视频)。但无法弄清楚如何使用 sws_alloc_context 或 sws_init_context 或任何其他函数告诉 sws_context 它的高度。

看到我遗漏的东西了吗?谢谢。

【问题讨论】:

【参考方案1】:

是的,缺少一些东西。

忘记sws_init_context(av_sws_ctx, NULL, NULL);

1) 使用以下之一初始化 sws_context(一次):

// for UPSCALE
av_sws_ctx = sws_getContext(src_width, src_height, src_pixfmt,
                            dst_width, dst_height, dst_pixfmt,
                            SWS_BILINEAR, NULL, NULL, NULL);
// for DOWNSCALE
av_sws_ctx = sws_getContext(src_width, src_height, src_pixfmt,
                            dst_width, dst_height, dst_pixfmt,
                            SWS_BICUBIC, NULL, NULL, NULL);

2) 然后调用转换:

int ret = sws_scale(swsContext,
                    srcframe->data,         /* srcSlice[]  */
                    srcframe->linesize,     /* srcStride[] */
                    0,                      /* srcSliceY   */
                    src_height,             /* srcSliceH   */
                    dstframe->data,         /* dst[]       */
                    dstframe->linesize);    /* dstStride[] */

请注意,src 和 dst 帧是不同的 AVFrame 实例。 上面的高档和低档线是建议,因为我更喜欢不同的算法(双线性与双三次)。 希望对您有所帮助。

【讨论】:

谢谢,这确实有帮助。使用 sws_getContext 能够得到这个工作。遇到说 getContext 已贬值的东西,但就这样吧。我想我现在必须坚持这个。 你说得对,建议改用这个:sws_getCachedContext

以上是关于FFMPEG:sws_scale 返回错误:切片参数 0、2160 无效的主要内容,如果未能解决你的问题,请参考以下文章

FFmpeg源码简单分析:libswscale的sws_scale()

FFmpeg(10)-基于FFmpeg进行像素格式转换(sws_getCachedContext(), sws_scale())

ffmpeg中sws_scale和sws_getContext的api分析

sws_scale函数的用法-具体应用

使用sws_scale转换视频使用swr_convert转换音频

使用sws_scale转换视频使用swr_convert转换音频