Есть ли способ заставить FFMPEG декодировать видеопоток с альфа-каналом из видео WebM, закодированного с помощью libvpx-vp9?

У меня есть файл WebM с одним видеопотоком, который был закодирован с помощью VP9 (libvpx-vp9).

Я написал программу на C ++ для извлечения кадров из видеопотока и сохранения их в формате PNG. Это работает нормально, за исключением того, что в результирующих PNG-файлах отсутствует альфа-канал.

Если я извлеку кадры из того же файла WebM с помощью FFMPEG, результирующий PNG будет содержать альфа-канал. Вот результат FFMPEG:

$ ffmpeg -c:v libvpx-vp9 -i temp/anim.webm temp/output-%3d.png

[libvpx-vp9 @ 0000024732b106c0] v1.10.0-rc1-11-gcb0d8ce31
    Last message repeated 1 times
Input #0, matroska,webm, from 'temp/anim.webm':
  Metadata:
    ENCODER         : Lavf58.45.100
  Duration: 00:00:04.04, start: 0.000000, bitrate: 112 kb/s
  Stream #0:0: Video: vp9 (Profile 0), yuva420p(tv), 640x480, SAR 1:1 DAR 4:3, 25 fps, 25 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      alpha_mode      : 1
      ENCODER         : Lavc58.91.100 libvpx-vp9
      DURATION        : 00:00:04.040000000

FFMPEG определяет формат потока как yuva420p.

Вот результат моей программы при вызове av_dump_format:

Input #0, matroska,webm, from 'temp/anim.webm':
  Metadata:
    ENCODER         : Lavf58.45.100
  Duration: 00:00:04.04, start: 0.000000, bitrate: 112 kb/s
  Stream #0:0: Video: vp9 (Profile 0), yuv420p(tv), 640x480, SAR 1:1 DAR 4:3, 25 fps, 25 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      alpha_mode      : 1
      ENCODER         : Lavc58.91.100 libvpx-vp9
      DURATION        : 00:00:04.040000000

Обратите внимание, что обнаруженный формат потока - yuv420p (альфа отсутствует).

Кто-нибудь знает, как заставить формат потока использовать альфа?

Мой установочный код выглядит следующим образом (обработка ошибок опущена)

auto result = avformat_open_input(&formatContext, fileName.c_str(), nullptr, nullptr);
auto result = avformat_find_stream_info(formatContext, nullptr);
streamIndex = av_find_best_stream(formatContext, mediaType, -1, -1, nullptr, 0);
auto stream = formatContext->streams[streamIndex];
const auto codecIdentifier{ AV_CODEC_ID_VP9 };
auto decoder = avcodec_find_decoder(codecIdentifier);
pCodecContext = avcodec_alloc_context3(decoder);
auto result = avcodec_open2(pCodecContext, decoder, &options);
// AV_PIX_FMT_YUV420P - missing alpha
auto pixelFormat = pCodecContext->pix_fmt;

Гиан указал, в чем проблема. Вот исправленный код:

In case anybody else runs into this issue in the future here is the code (error handling omitted):

auto formatContext = avformat_alloc_context();
formatContext->video_codec_id = AV_CODEC_ID_VP9;
const auto decoder = avcodec_find_decoder_by_name("libvpx-vp9");
formatContext->video_codec = decoder;
avformat_open_input(&formatContext, fileName.c_str(), nullptr, nullptr);
avformat_find_stream_info(formatContext.get(), nullptr);
for (unsigned int streamIndex = 0; streamIndex < formatContext->nb_streams; ++streamIndex) {
    // Displayed the stream format as yuva420p (contains alpha)
    av_dump_format(formatContext, static_cast<int>(streamIndex), fileName.toStdString().c_str(), 0);
}
```

Thanks,

person David    schedule 19.03.2021    source источник


Ответы (1)


Как и ваша команда ffmpeg, вы должны принудительно включить декодер vpx.

Использовать

auto decoder = avcodec_find_decoder_by_name("libvpx-vp9");
person Gyan    schedule 19.03.2021
comment
Спасибо за ваше предложение. Я пробовал это, но, к сожалению, в AVCodecContext pix_fmt все еще отсутствует альфа-компонент (все еще AV_PIX_FMT_YUV420P). - person David; 22.03.2021
comment
Назначьте видеокодек в контексте формата перед открытием формата и find_stream_info - person Gyan; 22.03.2021
comment
Да, это устранило мою проблему! Спасибо еще раз. Очень признателен. - person David; 24.03.2021