David
David

Reputation: 41

Is there a way to force FFMPEG to decode a video stream with alpha from ​a WebM video encoded with libvpx-vp9?

I have a ​WebM file with one video stream that was encoded with VP9 (libvpx-vp9).

I wrote a C++ program to extract the frames from the video stream and save them out as PNG's. This works fine except that the resulting PNG's are missing alpha.

If I extract the frames from the same WebM file using FFMPEG the resulting PNG's do contain alpha. Here is the output from 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 identifies the stream format as yuva420p.

Here is the output from my program when av_dump_format is called:

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

Notice that the detected stream format is yuv420p (the alpha is missing).

Does anybody know how to force the stream format to use alpha?

My setup code resembles the following (error handling is omitted)

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;

Gyan pointed out what the problem was. Here is the corrected code:

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,

Upvotes: 4

Views: 2181

Answers (1)

Gyan
Gyan

Reputation: 93068

Like your ffmpeg command, you have to force the vpx decoder.

Use

auto decoder = avcodec_find_decoder_by_name("libvpx-vp9");

Upvotes: 4

Related Questions