1

チュートリアルに従って、ffmpeg AVFrame 出力を SDL で表示しようとしています。チュートリアル (および私がオンラインで見ているすべての例) は、「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に伝える方法がわかりません。

見落としているものがありますか?ありがとうございました。

4

1 に答える 1

2

はい、何かが欠けています。

忘れるsws_init_context(av_sws_ctx, NULL, NULL);

1) 次のいずれかで sws_context を (1 回) 初期化します。

// 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 インスタンスであることに注意してください。
上記のアップスケールとダウンスケールの線は提案です。私は別のアルゴリズム (バイリニアとバイキュービック) を好みます。
それが役立つことを願っています。

于 2020-01-21T07:43:46.403 に答える