FFMPEG: sws_scale возвращает ошибку: параметры среза 0, 2160 недопустимы - PullRequest
1 голос
/ 17 января 2020

Я пытаюсь следовать руководству, чтобы отобразить вывод ffmpeg AVFrame в SDL. В учебнике (и во всех примерах, которые я вижу в сети) все еще используется 'sws_getContext', который устарел и удален из последней версии ffmpeg. Попытка изменить текущий формат пикселя с того, что он в настоящее время на PIX_FMT_YUV420P, чтобы я мог отобразить его. Я считаю, что мне нужна функция sws_scale для выполнения sh this.

Однако 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 dstStst )

Значения других параметров, отличных от 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_context, какую высоту он должен использовать, используя sws_alloc_context, sws_init_context или любую другую функцию.

Видите что-то, чего мне не хватает? Спасибо.

1 Ответ

1 голос
/ 21 января 2020

Да чего-то не хватает.

Забудьте 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[] */

Обратите внимание, что кадры sr c и dst - это разные экземпляры AVFrame.
Вышеуказанные строки верхнего и нижнего масштабов - это предложения, поскольку я предпочитаю другой алгоритм (билинейный и бикубический c) .
Надеюсь, это поможет.

...