简体   繁体   中英

FFMPEG: sws_scale returns error: Slice parameters 0, 2160 are invalid

I'm trying to follow a tutorial to display ffmpeg AVFrame output in SDL. The tutorial(and all examples I'm seeing online) are still using 'sws_getContext', which has been deprecated and removed from the newest version of ffmpeg. Trying to change current pixel format from whatever it currently is to PIX_FMT_YUV420P, so I can display it. I believe I need the sws_scale function to accomplish this.

However, sws_scale is the function that causes a command line error of: Slice parameters 0, 2160 are invalid

Here is all my code associate with 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);

Further complicating the matter, SwsContext is only defined internal to ffmpeg, externally I can't set/get any variables or even view them in the debugger.

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[] )

The vales of other parameters, other than 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

If I drill into sws_scale source code, I find that this error is thrown by this chunk of code:

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);
    }

I assume that the issue therefore is that the height of my video is bigger than sws_context(4k video). But can't figure out how to tell sws_context what it's height should be using sws_alloc_context or sws_init_context or any other function.

See something I'm missing? Thank you.

Yes something missing.

Forget sws_init_context(av_sws_ctx, NULL, NULL);

1) Init sws_context (once) with one of these:

// 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) Then call for the conversion:

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

Notice that, src and dst frames are different AVFrame instances.
Upscale and downscale lines above are suggestions, for I prefer different algorithm (bilinear vs bicubic).
Hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM