FFMPEG: sws_scale returns error: Slice parameters 0, 2160 are invalid
FFMPEG: sws_scale returns error: Slice parameters 0, 2160 are invalid
我正在尝试按照教程在 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 内部定义,在外部我不能 set/get 任何变量,甚至不能在调试器中查看它们。
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 它的高度。
看到我遗漏了什么吗?谢谢。
是的,少了点东西。
忘记了 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 实例。
上面的高档和低档线是建议,因为我更喜欢不同的算法(双线性与双三次)。
希望对您有所帮助。
我正在尝试按照教程在 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 内部定义,在外部我不能 set/get 任何变量,甚至不能在调试器中查看它们。
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 它的高度。
看到我遗漏了什么吗?谢谢。
是的,少了点东西。
忘记了 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 实例。
上面的高档和低档线是建议,因为我更喜欢不同的算法(双线性与双三次)。
希望对您有所帮助。