[vlc-commits] [Git][videolan/vlc][master] 11 commits: avcodec: pass the whole es_format when looking for a codec.
Steve Lhomme (@robUx4)
gitlab at videolan.org
Tue Feb 6 12:31:21 UTC 2024
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
8828f7d7 by Steve Lhomme at 2024-02-06T11:53:38+00:00
avcodec: pass the whole es_format when looking for a codec.
- - - - -
62056349 by Steve Lhomme at 2024-02-06T11:53:38+00:00
omxil: pass the whole es_format when looking for a video codec.
- - - - -
442723ed by Steve Lhomme at 2024-02-06T11:53:38+00:00
mmal: pass the whole es_format when looking for a codec.
- - - - -
18278324 by Steve Lhomme at 2024-02-06T11:53:38+00:00
chromecast: pass the whole es_format when looking for a codec
- - - - -
b2309174 by Steve Lhomme at 2024-02-06T11:53:38+00:00
fourcc: add codec FourCC for VP8/VP9 with alpha
They need 2 parallel decoders to handle the planes.
- - - - -
f459d4ed by Steve Lhomme at 2024-02-06T11:53:38+00:00
core: add ancillary data for VPX alpha channel
- - - - -
27350e78 by Steve Lhomme at 2024-02-06T11:53:38+00:00
codec: add a pseudo-decoder for VP8/VP9 with alpha
It uses 2 decoders in parallel and then merges the planes on output.
Only software decoders are supported for now.
- - - - -
652d8c08 by Steve Lhomme at 2024-02-06T11:53:38+00:00
vpx: allow decoding of the alpha channel bitstream
libavcodec is enable to do it without VPX. And when it does, it uses libvpx.
So we can just use libvpx directly.
- - - - -
ac942ef0 by Steve Lhomme at 2024-02-06T11:53:38+00:00
avcodec: handle the VP9 alpha channel as a VP9 stream
It can decode it in hardware and software.
- - - - -
62200d31 by Steve Lhomme at 2024-02-06T11:53:38+00:00
mkv: check the AlphaMode of the video tracks
When the flag is set the BlockAdditional Element with BlockAddID of "1"
contains alpha channel data.
See https://www.ietf.org/archive/id/draft-ietf-cellar-matroska-15.html#section-5.1.4.1.29.4
- - - - -
2367cf2e by Steve Lhomme at 2024-02-06T11:53:38+00:00
mkv: handle alpha BlockAddId for VP8/VP9
- - - - -
25 changed files:
- include/vlc_ancillary.h
- include/vlc_fourcc.h
- modules/codec/Makefile.am
- modules/codec/avcodec/avcodec.c
- modules/codec/avcodec/avcodec.h
- modules/codec/avcodec/encoder.c
- modules/codec/avcodec/fourcc.c
- modules/codec/gstreamer/gstdecode.c
- modules/codec/meson.build
- modules/codec/omxil/mediacodec.c
- modules/codec/omxil/omxil.c
- modules/codec/omxil/omxil_utils.h
- modules/codec/omxil/utils.c
- modules/codec/vpx.c
- + modules/codec/vpx_alpha.c
- modules/demux/avformat/mux.c
- modules/demux/mkv/matroska_segment_parse.cpp
- modules/demux/mkv/mkv.cpp
- modules/demux/mkv/mkv.hpp
- modules/hw/mmal/codec.c
- modules/hw/nvdec/nvdec.c
- modules/packetizer/avparser.c
- modules/stream_out/chromecast/cast.cpp
- modules/stream_out/rtpfmt.c
- src/misc/fourcc_list.h
Changes:
=====================================
include/vlc_ancillary.h
=====================================
@@ -217,5 +217,17 @@ typedef struct vlc_icc_profile_t
uint8_t data[]; /* binary profile data, see ICC.1:2022 (or later) */
} vlc_icc_profile_t;
+/**
+ * VPx alpha data
+ */
+
+#define VLC_ANCILLARY_ID_VPX_ALPHA VLC_FOURCC('v','p','x','A')
+
+typedef struct vlc_vpx_alpha_t
+{
+ size_t size;
+ uint8_t *data;
+} vlc_vpx_alpha_t;
+
/** @} */
#endif /* VLC_ANCILLARY_H */
=====================================
include/vlc_fourcc.h
=====================================
@@ -122,7 +122,9 @@
#define VLC_CODEC_VP4 VLC_FOURCC('V','P','4','0')
#define VLC_CODEC_VP7 VLC_FOURCC('V','P','7','0')
#define VLC_CODEC_VP8 VLC_FOURCC('V','P','8','0')
+#define VLC_CODEC_VP8ALPHA_ES VLC_FOURCC('V','P','8','a')
#define VLC_CODEC_VP9 VLC_FOURCC('V','P','9','0')
+#define VLC_CODEC_VP9ALPHA_ES VLC_FOURCC('V','P','9','a')
#define VLC_CODEC_VP10 VLC_FOURCC('V','P',':','0')
#define VLC_CODEC_AV1 VLC_FOURCC('a','v','0','1')
#define VLC_CODEC_JPEG2000 VLC_FOURCC('J','P','2','K')
=====================================
modules/codec/Makefile.am
=====================================
@@ -568,6 +568,9 @@ libvpx_plugin_la_LIBADD = $(VPX_LIBS)
EXTRA_LTLIBRARIES += libvpx_plugin.la
codec_LTLIBRARIES += $(LTLIBvpx)
+libvpx_alpha_plugin_la_SOURCES = codec/vpx_alpha.c
+codec_LTLIBRARIES += libvpx_alpha_plugin.la
+
libaom_plugin_la_SOURCES = codec/aom.c \
packetizer/iso_color_tables.h
libaom_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
=====================================
modules/codec/avcodec/avcodec.c
=====================================
@@ -230,8 +230,7 @@ AVCodecContext *ffmpeg_AllocContext( decoder_t *p_dec,
const AVCodec *p_codec = NULL;
/* *** determine codec type *** */
- if( !GetFfmpegCodec( p_dec->fmt_in->i_cat, p_dec->fmt_in->i_codec,
- &i_codec_id, &psz_namecodec ) ||
+ if( !GetFfmpegCodec( p_dec->fmt_in, &i_codec_id, &psz_namecodec ) ||
i_codec_id == AV_CODEC_ID_RAWVIDEO )
return NULL;
=====================================
modules/codec/avcodec/avcodec.h
=====================================
@@ -24,7 +24,7 @@
#include "avcommon.h"
/* VLC <-> avcodec tables */
-bool GetFfmpegCodec( enum es_format_category_e cat, vlc_fourcc_t i_fourcc,
+bool GetFfmpegCodec( const es_format_t *,
enum AVCodecID *pi_ffmpeg_codec, const char **ppsz_name );
vlc_fourcc_t GetVlcFourcc( enum AVCodecID i_ffmpeg_codec );
vlc_fourcc_t GetVlcAudioFormat( int i_sample_fmt );
=====================================
modules/codec/avcodec/encoder.c
=====================================
@@ -336,8 +336,7 @@ int InitVideoEnc( vlc_object_t *p_this )
psz_namecodec = "MPEG-1 video";
break;
}
- if( GetFfmpegCodec( VIDEO_ES, p_enc->fmt_out.i_codec, &i_codec_id,
- &psz_namecodec ) )
+ if( GetFfmpegCodec( &p_enc->fmt_out, &i_codec_id, &psz_namecodec ) )
break;
bool uv_flipped;
if( FindFfmpegChroma( p_enc->fmt_out.i_codec, &uv_flipped ) != AV_PIX_FMT_NONE )
@@ -350,8 +349,7 @@ int InitVideoEnc( vlc_object_t *p_this )
case AUDIO_ES:
encoder_ops = &audio_ops;
- if( GetFfmpegCodec( AUDIO_ES, p_enc->fmt_out.i_codec, &i_codec_id,
- &psz_namecodec ) )
+ if( GetFfmpegCodec( &p_enc->fmt_out, &i_codec_id, &psz_namecodec ) )
break;
/* fall through */
default:
=====================================
modules/codec/avcodec/fourcc.c
=====================================
@@ -251,6 +251,7 @@ static const struct vlc_avcodec_fourcc video_codecs[] =
{ VLC_CODEC_CLLC, AV_CODEC_ID_CLLC },
{ VLC_CODEC_MSS2, AV_CODEC_ID_MSS2 },
{ VLC_CODEC_VP9, AV_CODEC_ID_VP9 },
+ { VLC_CODEC_VP9ALPHA_ES, AV_CODEC_ID_VP9 },
#if LIBAVCODEC_VERSION_CHECK( 57, 83, 101 )
{ VLC_CODEC_AV1, AV_CODEC_ID_AV1 },
#endif
@@ -556,13 +557,18 @@ static const struct vlc_avcodec_fourcc spu_codecs[] =
/* ffmpeg only: AV_CODEC_ID_ASS */
};
-bool GetFfmpegCodec( enum es_format_category_e cat, vlc_fourcc_t i_fourcc,
+bool GetFfmpegCodec( const es_format_t *es,
enum AVCodecID *pi_ffmpeg_codec, const char **ppsz_name )
{
const struct vlc_avcodec_fourcc *base;
size_t count;
- switch( cat )
+ if (es->i_codec == VLC_CODEC_VP8 && es->i_level) // contains alpha extradata
+ return false;
+ if (es->i_codec == VLC_CODEC_VP9 && es->i_level) // contains alpha extradata
+ return false;
+
+ switch( es->i_cat )
{
case VIDEO_ES:
base = video_codecs;
@@ -581,7 +587,7 @@ bool GetFfmpegCodec( enum es_format_category_e cat, vlc_fourcc_t i_fourcc,
count = 0;
}
- i_fourcc = vlc_fourcc_GetCodec( cat, i_fourcc );
+ vlc_fourcc_t i_fourcc = vlc_fourcc_GetCodec( es->i_cat, es->i_codec );
for( size_t i = 0; i < count; i++ )
{
@@ -590,7 +596,7 @@ bool GetFfmpegCodec( enum es_format_category_e cat, vlc_fourcc_t i_fourcc,
if( pi_ffmpeg_codec != NULL )
*pi_ffmpeg_codec = base[i].i_codec;
if( ppsz_name )
- *ppsz_name = vlc_fourcc_GetDescription( cat, i_fourcc );
+ *ppsz_name = vlc_fourcc_GetDescription( es->i_cat, i_fourcc );
return true;
}
}
=====================================
modules/codec/gstreamer/gstdecode.c
=====================================
@@ -408,9 +408,13 @@ static GstStructure* vlc_to_gst_fmt( const es_format_t *p_fmt )
"systemstream", G_TYPE_BOOLEAN, FALSE, NULL );
break;
case VLC_CODEC_VP8:
+ if (p_fmt->i_level) // contains alpha extradata
+ return NULL;
p_str = gst_structure_new_empty( "video/x-vp8" );
break;
case VLC_CODEC_VP9:
+ if (p_fmt->i_level) // contains alpha extradata
+ return NULL;
p_str = gst_structure_new_empty( "video/x-vp9" );
break;
case VLC_CODEC_AV1:
=====================================
modules/codec/meson.build
=====================================
@@ -810,6 +810,13 @@ if vpx_dep.found()
}
endif
+# VP8/VP9 with alpha pseudo-decoder
+vlc_modules += {
+ 'name' : 'vpx_alpha',
+ 'sources' : files('vpx_alpha.c')
+}
+
+
# libaom AV1 codec
aom_dep = dependency('aom', required: get_option('aom'))
if aom_dep.found()
=====================================
modules/codec/omxil/mediacodec.c
=====================================
@@ -808,8 +808,14 @@ static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
break;
case VLC_CODEC_WMV3: mime = "video/x-ms-wmv"; break;
case VLC_CODEC_VC1: mime = "video/wvc1"; break;
- case VLC_CODEC_VP8: mime = "video/x-vnd.on2.vp8"; break;
- case VLC_CODEC_VP9: mime = "video/x-vnd.on2.vp9"; break;
+ case VLC_CODEC_VP8:
+ if (p_dec->fmt_in->i_level) // contains alpha extradata
+ return VLC_ENOTSUP;
+ mime = "video/x-vnd.on2.vp8"; break;
+ case VLC_CODEC_VP9:
+ if (p_dec->fmt_in->i_level) // contains alpha extradata
+ return VLC_ENOTSUP;
+ mime = "video/x-vnd.on2.vp9"; break;
}
}
else
=====================================
modules/codec/omxil/omxil.c
=====================================
@@ -211,7 +211,7 @@ static OMX_ERRORTYPE SetPortDefinition(decoder_t *p_dec, OmxPort *p_port,
def->format.video.nFrameHeight * 2;
p_port->i_frame_size = def->nBufferSize;
- def->format.video.eCompressionFormat = GetOmxVideoFormat(p_fmt->i_codec);
+ def->format.video.eCompressionFormat = GetOmxVideoFormat(p_fmt);
if( def->format.video.eCompressionFormat == OMX_VIDEO_CodingUnused)
{
def->format.video.eColorFormat = GetOmxChromaFormat(p_fmt->i_codec);
=====================================
modules/codec/omxil/omxil_utils.h
=====================================
@@ -225,7 +225,7 @@ int OMXCodec_GetQuirks( enum es_format_category_e i_cat, vlc_fourcc_t i_codec,
/*****************************************************************************
* fourcc -> omx id mapping
*****************************************************************************/
-OMX_VIDEO_CODINGTYPE GetOmxVideoFormat( vlc_fourcc_t i_fourcc );
+OMX_VIDEO_CODINGTYPE GetOmxVideoFormat( const es_format_t * );
vlc_fourcc_t GetVlcVideoFormat( OMX_VIDEO_CODINGTYPE i_omx_codec );
OMX_AUDIO_CODINGTYPE GetOmxAudioFormat( vlc_fourcc_t i_fourcc );
vlc_fourcc_t OmxToVlcAudioFormat( OMX_AUDIO_CODINGTYPE i_omx_codec );
=====================================
modules/codec/omxil/utils.c
=====================================
@@ -588,13 +588,23 @@ static const struct
{ VLC_CODEC_VYUY, OMX_COLOR_FormatCrYCbY, 4, 2, 0 },
};
-OMX_VIDEO_CODINGTYPE GetOmxVideoFormat( vlc_fourcc_t i_fourcc )
+OMX_VIDEO_CODINGTYPE GetOmxVideoFormat( const es_format_t *es )
{
- i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
+ if ( unlikely( es->i_cat != VIDEO_ES ) )
+ return OMX_VIDEO_CodingUnused;
+
+ vlc_fourcc_t i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, es->i_codec );
for( size_t i = 0; i < ARRAY_SIZE(video_format_table); i++ )
if( video_format_table[i].i_fourcc == i_fourcc )
+ {
+ if (es->i_codec == VLC_CODEC_VP8 && es->i_level) // contains alpha extradata
+ continue;
+ if (es->i_codec == VLC_CODEC_VP9 && es->i_level) // contains alpha extradata
+ continue;
+
return video_format_table[i].i_codec;
+ }
return OMX_VIDEO_CodingUnused;
}
@@ -608,13 +618,23 @@ vlc_fourcc_t GetVlcVideoFormat( OMX_VIDEO_CODINGTYPE i_omx_codec )
return 0;
}
-static const char *GetOmxVideoRole( vlc_fourcc_t i_fourcc )
+static const char *GetOmxVideoRole( const es_format_t *es )
{
- i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, i_fourcc );
+ if ( unlikely( es->i_cat != VIDEO_ES ) )
+ return NULL;
+
+ vlc_fourcc_t i_fourcc = vlc_fourcc_GetCodec( VIDEO_ES, es->i_codec );
for( size_t i = 0; i < ARRAY_SIZE(video_format_table); i++ )
if( video_format_table[i].i_fourcc == i_fourcc )
+ {
+ if (es->i_codec == VLC_CODEC_VP8 && es->i_level) // contains alpha extradata
+ continue;
+ if (es->i_codec == VLC_CODEC_VP9 && es->i_level) // contains alpha extradata
+ continue;
+
return video_format_table[i].psz_role;
+ }
return NULL;
}
@@ -682,7 +702,7 @@ const char *GetOmxRole( const es_format_t *es,
GetOmxVideoEncRole( es->i_codec ) : GetOmxAudioEncRole( es->i_codec );
return es->i_cat == VIDEO_ES ?
- GetOmxVideoRole( es->i_codec ) : GetOmxAudioRole( es->i_codec );
+ GetOmxVideoRole( es ) : GetOmxAudioRole( es->i_codec );
}
OMX_COLOR_FORMATTYPE GetOmxChromaFormat( vlc_fourcc_t i_fourcc )
=====================================
modules/codec/vpx.c
=====================================
@@ -309,14 +309,22 @@ static int OpenDecoder(vlc_object_t *p_this)
switch (dec->fmt_in->i_codec)
{
#ifdef ENABLE_VP8_DECODER
- case VLC_CODEC_WEBP:
case VLC_CODEC_VP8:
+ if (dec->fmt_in->i_level) // contains alpha extradata
+ return VLC_ENOTSUP;
+ // fallthrough
+ case VLC_CODEC_WEBP:
+ case VLC_CODEC_VP8ALPHA_ES:
iface = &vpx_codec_vp8_dx_algo;
vp_version = 8;
break;
#endif
#ifdef ENABLE_VP9_DECODER
case VLC_CODEC_VP9:
+ if (dec->fmt_in->i_level) // contains alpha extradata
+ return VLC_ENOTSUP;
+ // fallthrough
+ case VLC_CODEC_VP9ALPHA_ES:
iface = &vpx_codec_vp9_dx_algo;
vp_version = 9;
break;
@@ -404,14 +412,19 @@ static int OpenEncoder(vlc_object_t *p_this)
switch (p_enc->fmt_out.i_codec)
{
#ifdef ENABLE_VP8_ENCODER
- case VLC_CODEC_WEBP:
case VLC_CODEC_VP8:
+ if (p_enc->fmt_out.i_level) // contains alpha extradata
+ return VLC_ENOTSUP;
+ // fallthrough
+ case VLC_CODEC_WEBP:
iface = &vpx_codec_vp8_cx_algo;
vp_version = 8;
break;
#endif
#ifdef ENABLE_VP9_ENCODER
case VLC_CODEC_VP9:
+ if (p_enc->fmt_out.i_level) // contains alpha extradata
+ return VLC_ENOTSUP;
iface = &vpx_codec_vp9_cx_algo;
vp_version = 9;
break;
=====================================
modules/codec/vpx_alpha.c
=====================================
@@ -0,0 +1,531 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+
+// vpx_alpha.c : pseudo-decoder for VP8/VP9 streams with alpha side-channel
+// Copyright © 2023 VideoLabs, VLC authors and VideoLAN
+
+// Authors: Steve Lhomme <robux4 at videolabs.io>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <vlc_common.h>
+#include <vlc_plugin.h>
+#include <vlc_codec.h>
+#include <vlc_ancillary.h>
+#include <vlc_modules.h>
+#include <vlc_atomic.h>
+#include <vlc_picture_pool.h>
+
+static int OpenDecoder(vlc_object_t *);
+static void CloseDecoder(vlc_object_t *);
+
+vlc_module_begin ()
+ set_description(N_("VPx+alpha video decoder"))
+ set_capability("video decoder", 150)
+ set_callbacks(OpenDecoder, CloseDecoder)
+ set_subcategory(SUBCAT_INPUT_VCODEC)
+vlc_module_end ()
+
+struct vp_decoder
+{
+ decoder_t dec;
+ es_format_t fmt_in;
+ es_format_t fmt_out;
+ vlc_picture_chain_t decoded;
+};
+
+typedef struct
+{
+ struct vp_decoder *opaque;
+ struct vp_decoder *alpha;
+ vlc_mutex_t lock;
+ vlc_video_context *vctx;
+ picture_t *(*pf_combine)(decoder_t *, picture_t *opaque, picture_t *alpha, vlc_video_context *);
+
+ picture_pool_t *pool;
+} vpx_alpha;
+
+
+static vlc_decoder_device *GetDevice( decoder_t *dec )
+{
+ decoder_t *bdec = container_of(vlc_object_parent(dec), decoder_t, obj);
+ vpx_alpha *p_sys = bdec->p_sys;
+ vlc_mutex_lock(&p_sys->lock);
+ vlc_decoder_device *res = decoder_GetDecoderDevice(bdec);
+ vlc_mutex_unlock(&p_sys->lock);
+ return res;
+}
+
+struct cpu_alpha_context
+{
+ picture_context_t ctx;
+ picture_t *opaque;
+ picture_t *alpha;
+};
+
+static void cpu_alpha_destroy(picture_context_t *ctx)
+{
+ struct cpu_alpha_context *pctx = container_of(ctx, struct cpu_alpha_context, ctx);
+ picture_Release(pctx->opaque);
+ picture_Release(pctx->alpha);
+ free(pctx);
+}
+
+static picture_context_t *cpu_alpha_copy(picture_context_t *src)
+{
+ struct cpu_alpha_context *pctx = container_of(src, struct cpu_alpha_context, ctx);
+ struct cpu_alpha_context *alpha_ctx = calloc(1, sizeof(*alpha_ctx));
+ if (unlikely(alpha_ctx == NULL))
+ return NULL;
+ alpha_ctx->ctx = *src;
+ alpha_ctx->opaque = picture_Hold(pctx->opaque);
+ alpha_ctx->alpha = picture_Hold(pctx->alpha);
+ return &alpha_ctx->ctx;
+}
+
+static picture_t *CombinePicturesCPU(decoder_t *bdec, picture_t *opaque, picture_t *alpha, vlc_video_context *vctx)
+{
+ assert(vctx == NULL); VLC_UNUSED(vctx);
+ vpx_alpha *p_sys = bdec->p_sys;
+ picture_t *out = picture_pool_Wait(p_sys->pool);
+ if (out == NULL)
+ return NULL;
+
+ struct cpu_alpha_context *alpha_ctx = calloc(1, sizeof(*alpha_ctx));
+ if (unlikely(alpha_ctx == NULL))
+ {
+ picture_Release(out);
+ return NULL;
+ }
+ alpha_ctx->ctx = (picture_context_t) {
+ cpu_alpha_destroy, cpu_alpha_copy, NULL
+ };
+ alpha_ctx->opaque = picture_Hold(opaque);
+ alpha_ctx->alpha = picture_Hold(alpha);
+ out->context = &alpha_ctx->ctx;
+
+ for (int i=0; i<opaque->i_planes; i++)
+ out->p[i] = opaque->p[i];
+ out->p[opaque->i_planes] = alpha->p[0];
+ return out;
+}
+
+static int SetupCPU(decoder_t *bdec)
+{
+ vpx_alpha *p_sys = bdec->p_sys;
+ picture_t *pics[4];
+ size_t i=0;
+
+ if (p_sys->pool)
+ {
+ picture_pool_Release(p_sys->pool);
+ p_sys->pool = NULL;
+ }
+
+ for (; i<ARRAY_SIZE(pics); i++)
+ {
+ pics[i] = picture_NewFromResource(&bdec->fmt_out.video, &(picture_resource_t){0});
+ if (pics[i] == NULL)
+ goto error;
+ }
+ p_sys->pool = picture_pool_New(ARRAY_SIZE(pics), pics);
+ if (p_sys->pool)
+ return VLC_SUCCESS;
+
+error:
+ while (i-- > 0)
+ picture_Release(pics[i]);
+ return VLC_EGENERIC;
+}
+
+static picture_t *CombineKeepAlpha(decoder_t *bdec, picture_t *opaque, picture_t *alpha, vlc_video_context *vctx)
+{
+ VLC_UNUSED(bdec); VLC_UNUSED(opaque); VLC_UNUSED(vctx);
+ return picture_Hold(alpha);
+}
+
+static picture_t *CombineKeepOpaque(decoder_t *bdec, picture_t *opaque, picture_t *alpha, vlc_video_context *vctx)
+{
+ VLC_UNUSED(bdec); VLC_UNUSED(alpha); VLC_UNUSED(vctx);
+ return picture_Hold(opaque);
+}
+
+static int FormatUpdate( decoder_t *dec, vlc_video_context *vctx )
+{
+ decoder_t *bdec = container_of(vlc_object_parent(dec), decoder_t, obj);
+ vpx_alpha *p_sys = bdec->p_sys;
+ vlc_mutex_lock(&p_sys->lock);
+
+ int res = VLC_SUCCESS;
+ if (dec == &p_sys->alpha->dec)
+ {
+ if (es_format_IsSimilar(&p_sys->alpha->fmt_out, &dec->fmt_out))
+ // nothing changed
+ goto done;
+ es_format_Clean(&p_sys->alpha->fmt_out);
+ es_format_Copy(&p_sys->alpha->fmt_out, &dec->fmt_out);
+ if (p_sys->opaque->dec.fmt_out.video.i_chroma == 0)
+ {
+ // not ready
+ bdec->fmt_out.video.i_chroma = bdec->fmt_out.i_codec = dec->fmt_out.video.i_chroma;
+ p_sys->pf_combine = CombineKeepAlpha;
+ goto done;
+ }
+ }
+ else
+ {
+ if (es_format_IsSimilar(&p_sys->opaque->fmt_out, &dec->fmt_out))
+ // nothing changed
+ goto done;
+ es_format_Clean(&p_sys->opaque->fmt_out);
+ es_format_Copy(&p_sys->opaque->fmt_out, &dec->fmt_out);
+ if (p_sys->alpha->dec.fmt_out.video.i_chroma == 0)
+ {
+ // not ready
+ bdec->fmt_out.video.i_chroma = bdec->fmt_out.i_codec = dec->fmt_out.video.i_chroma;
+ p_sys->pf_combine = CombineKeepOpaque;
+ goto done;
+ }
+ }
+ es_format_Clean(&bdec->fmt_out);
+ es_format_Copy(&bdec->fmt_out, &dec->fmt_out);
+
+ switch (dec->fmt_out.video.i_chroma)
+ {
+ case VLC_CODEC_I420:
+ // TODO support other formats
+ bdec->fmt_out.video.i_chroma = bdec->fmt_out.i_codec = VLC_CODEC_YUV420A;
+ res = SetupCPU(bdec);
+ if (res == VLC_SUCCESS)
+ {
+ p_sys->pf_combine = CombinePicturesCPU;
+ }
+ break;
+ default:
+ msg_Err(dec, "unsupported decoder output %4.4s", (char*)&dec->fmt_out.video.i_chroma);
+ res = VLC_EGENERIC;
+ break;
+ }
+ if (res == VLC_SUCCESS)
+ res = decoder_UpdateVideoOutput(bdec, vctx);
+
+done:
+ vlc_mutex_unlock(&p_sys->lock);
+ return res;
+}
+
+static bool SendMergedLocked(decoder_t *bdec)
+{
+ vpx_alpha *p_sys = bdec->p_sys;
+
+ picture_t *opaque = vlc_picture_chain_PeekFront(&p_sys->opaque->decoded);
+ picture_t *alpha = vlc_picture_chain_PeekFront(&p_sys->alpha->decoded);
+ while (opaque != NULL && alpha != NULL)
+ {
+ if (opaque->date == alpha->date)
+ {
+ // dequeue if both first of the queue match DTS/PTS
+ // merge alpha and opaque pictures with same DTS/PTS and send them
+ picture_t *out = p_sys->pf_combine(bdec, opaque, alpha, p_sys->vctx);
+ if (out != NULL)
+ {
+ video_format_CopyCropAr(&out->format, &opaque->format);
+ picture_CopyProperties(out, opaque);
+ }
+
+ vlc_picture_chain_PopFront(&p_sys->opaque->decoded);
+ picture_Release(opaque);
+
+ vlc_picture_chain_PopFront(&p_sys->alpha->decoded);
+ picture_Release(alpha);
+
+ if (out == NULL)
+ return false;
+
+ decoder_QueueVideo(bdec, out);
+ return true;
+ }
+
+ // in case decoders drop some frames
+ if (opaque->date > alpha->date)
+ {
+ msg_Dbg(bdec, "missing decoded opaque at %" PRId64 " dropping alpha", alpha->date);
+ vlc_picture_chain_PopFront(&p_sys->alpha->decoded);
+ picture_Release(alpha);
+ }
+ else
+ {
+ msg_Dbg(bdec, "missing decoded alpha at %" PRId64 " dropping opaque", opaque->date);
+ vlc_picture_chain_PopFront(&p_sys->opaque->decoded);
+ picture_Release(opaque);
+ }
+ opaque = vlc_picture_chain_PeekFront(&p_sys->opaque->decoded);
+ alpha = vlc_picture_chain_PeekFront(&p_sys->alpha->decoded);
+ }
+ return false;
+}
+
+static void QueuePic( decoder_t *dec, picture_t *pic )
+{
+ decoder_t *bdec = container_of(vlc_object_parent(dec), decoder_t, obj);
+ vpx_alpha *p_sys = bdec->p_sys;
+
+ vlc_mutex_lock(&p_sys->lock);
+ if (dec == &p_sys->alpha->dec)
+ {
+ vlc_picture_chain_Append(&p_sys->alpha->decoded, pic);
+ }
+ else
+ {
+ vlc_picture_chain_Append(&p_sys->opaque->decoded, pic);
+ }
+
+ SendMergedLocked(bdec);
+ vlc_mutex_unlock(&p_sys->lock);
+}
+
+static vlc_tick_t GetDisplayDate( decoder_t *dec, vlc_tick_t sys_now, vlc_tick_t ts)
+{
+ decoder_t *bdec = container_of(vlc_object_parent(dec), decoder_t, obj);
+ return decoder_GetDisplayDate(bdec, sys_now, ts);
+}
+
+static float GetDisplayRate( decoder_t *dec )
+{
+ decoder_t *bdec = container_of(vlc_object_parent(dec), decoder_t, obj);
+ return decoder_GetDisplayRate(bdec);
+}
+
+static int GetAttachments( decoder_t *dec,
+ input_attachment_t ***ppp_attachment,
+ int *pi_attachment )
+{
+ decoder_t *bdec = container_of(vlc_object_parent(dec), decoder_t, obj);
+ return decoder_GetInputAttachments(bdec, ppp_attachment, pi_attachment);
+}
+
+struct alpha_frame
+{
+ vlc_atomic_rc_t rc;
+ vlc_frame_t *frame; // source frame
+ vlc_frame_t opaque; // opaque bitstream
+ vlc_frame_t alpha; // alpha bitstream
+};
+
+static void ReleaseAlphaFrame(vlc_frame_t *frame)
+{
+ struct alpha_frame *alpha_frame = container_of(frame, struct alpha_frame, alpha);
+
+ if (vlc_atomic_rc_dec(&alpha_frame->rc))
+ {
+ vlc_frame_Release(alpha_frame->frame);
+ free(alpha_frame);
+ }
+}
+
+static void ReleaseOpaqueFrame(vlc_frame_t *frame)
+{
+ struct alpha_frame *alpha_frame = container_of(frame, struct alpha_frame, opaque);
+
+ if (vlc_atomic_rc_dec(&alpha_frame->rc))
+ {
+ vlc_frame_Release(alpha_frame->frame);
+ free(alpha_frame);
+ }
+}
+
+static int Decode( decoder_t *dec, vlc_frame_t *frame )
+{
+ vpx_alpha *p_sys = dec->p_sys;
+
+ int res;
+ if (frame != NULL)
+ {
+ struct vlc_ancillary *p_alpha;
+ p_alpha = vlc_frame_GetAncillary(frame, VLC_ANCILLARY_ID_VPX_ALPHA);
+ if (p_alpha == NULL)
+ {
+ msg_Err(dec, "missing alpha data");
+ return VLCDEC_ECRITICAL;
+ }
+
+ struct alpha_frame *alpha_frame = malloc(sizeof(*alpha_frame));
+ if (unlikely(alpha_frame == NULL))
+ return VLCDEC_ECRITICAL;
+
+ vlc_vpx_alpha_t *alpha = vlc_ancillary_GetData(p_alpha);
+
+ static const struct vlc_frame_callbacks cbs_alpha = {
+ ReleaseAlphaFrame,
+ };
+
+ static const struct vlc_frame_callbacks cbs_opaque = {
+ ReleaseOpaqueFrame,
+ };
+
+ alpha_frame->frame = frame;
+ vlc_atomic_rc_init(&alpha_frame->rc);
+
+ vlc_frame_Init(&alpha_frame->alpha, &cbs_alpha, alpha->data, alpha->size);
+ vlc_atomic_rc_inc(&alpha_frame->rc);
+ alpha_frame->alpha.i_dts = frame->i_dts;
+ alpha_frame->alpha.i_pts = frame->i_pts;
+ alpha_frame->alpha.i_length = frame->i_length;
+ alpha_frame->alpha.i_flags = frame->i_flags;
+
+ vlc_frame_Init(&alpha_frame->opaque, &cbs_opaque, frame->p_buffer, frame->i_buffer);
+ alpha_frame->opaque.i_dts = frame->i_dts;
+ alpha_frame->opaque.i_pts = frame->i_pts;
+ alpha_frame->opaque.i_length = frame->i_length;
+ alpha_frame->opaque.i_flags = frame->i_flags;
+
+ res = p_sys->opaque->dec.pf_decode(&p_sys->opaque->dec, &alpha_frame->opaque);
+ if (res != VLCDEC_SUCCESS)
+ {
+ ReleaseOpaqueFrame(&alpha_frame->opaque);
+ return VLCDEC_ECRITICAL;
+ }
+
+ res = p_sys->alpha->dec.pf_decode(&p_sys->alpha->dec, &alpha_frame->alpha);
+ if (res != VLCDEC_SUCCESS)
+ {
+ ReleaseAlphaFrame(&alpha_frame->alpha);
+ return VLCDEC_ECRITICAL;
+ }
+ }
+ else
+ {
+ // drain
+ vlc_mutex_lock(&p_sys->lock);
+ while ( !vlc_picture_chain_IsEmpty(&p_sys->opaque->decoded) &&
+ !vlc_picture_chain_IsEmpty(&p_sys->alpha->decoded) )
+ SendMergedLocked(dec);
+
+ // drain remaining pushed pictures from one decoder
+ picture_t *picture;
+ while ((picture = vlc_picture_chain_PopFront(&p_sys->alpha->decoded)) != NULL)
+ picture_Release(picture);
+ while ((picture = vlc_picture_chain_PopFront(&p_sys->opaque->decoded)) != NULL)
+ picture_Release(picture);
+ vlc_mutex_unlock(&p_sys->lock);
+ }
+
+ return VLCDEC_SUCCESS;
+}
+
+static void Flush( decoder_t *dec )
+{
+ vpx_alpha *p_sys = dec->p_sys;
+ vlc_mutex_lock(&p_sys->lock);
+
+ if ( p_sys->opaque->dec.pf_flush != NULL )
+ p_sys->opaque->dec.pf_flush( &p_sys->opaque->dec );
+
+ if ( p_sys->alpha->dec.pf_flush != NULL )
+ p_sys->alpha->dec.pf_flush( &p_sys->alpha->dec );
+
+ picture_t *picture;
+ while ((picture = vlc_picture_chain_PopFront(&p_sys->opaque->decoded)) != NULL)
+ picture_Release(picture);
+ while ((picture = vlc_picture_chain_PopFront(&p_sys->alpha->decoded)) != NULL)
+ picture_Release(picture);
+ vlc_mutex_unlock(&p_sys->lock);
+}
+
+int OpenDecoder(vlc_object_t *o)
+{
+ decoder_t *dec = container_of(o, decoder_t, obj);
+ if (dec->fmt_in->i_codec != VLC_CODEC_VP8 && dec->fmt_in->i_codec != VLC_CODEC_VP9)
+ return VLC_ENOTSUP;
+ if (dec->fmt_in->i_level == 0)
+ return VLC_ENOTSUP;
+
+ vpx_alpha *p_sys = vlc_obj_calloc(o, 1, sizeof(*p_sys));
+ if (unlikely(p_sys == NULL))
+ return VLC_ENOMEM;
+
+ p_sys->opaque = vlc_object_create( o, sizeof( *p_sys->opaque ) );
+ if (unlikely(p_sys->opaque == NULL))
+ return VLC_EGENERIC;
+ p_sys->alpha = vlc_object_create( o, sizeof( *p_sys->alpha ) );
+ if (unlikely(p_sys->alpha == NULL))
+ {
+ vlc_object_delete(&p_sys->opaque->dec);
+ return VLC_EGENERIC;
+ }
+
+ es_format_t fmt;
+ es_format_Copy(&fmt, dec->fmt_in);
+ if (dec->fmt_in->i_codec == VLC_CODEC_VP8)
+ fmt.i_codec = VLC_CODEC_VP8;
+ else
+ fmt.i_codec = VLC_CODEC_VP9;
+ decoder_Init( &p_sys->opaque->dec, &p_sys->opaque->fmt_in, &fmt );
+ vlc_picture_chain_Init(&p_sys->opaque->decoded);
+ es_format_Init(&p_sys->opaque->fmt_out, VIDEO_ES, 0);
+
+ if (dec->fmt_in->i_codec == VLC_CODEC_VP8)
+ fmt.i_codec = VLC_CODEC_VP8ALPHA_ES;
+ else
+ fmt.i_codec = VLC_CODEC_VP9ALPHA_ES;
+ decoder_Init( &p_sys->alpha->dec, &p_sys->alpha->fmt_in, &fmt );
+ vlc_picture_chain_Init(&p_sys->alpha->decoded);
+ es_format_Init(&p_sys->alpha->fmt_out, VIDEO_ES, 0);
+
+ vlc_mutex_init(&p_sys->lock);
+ dec->p_sys = p_sys;
+
+ static const struct decoder_owner_callbacks dec_cbs =
+ {
+ .video = {
+ .get_device = GetDevice,
+ .format_update = FormatUpdate,
+ .queue = QueuePic,
+ .get_display_date = GetDisplayDate,
+ .get_display_rate = GetDisplayRate,
+ },
+ .get_attachments = GetAttachments,
+ };
+
+ p_sys->opaque->dec.cbs = &dec_cbs;
+ p_sys->opaque->dec.p_module =
+ module_need_var( &p_sys->opaque->dec, "video decoder", "codec" );
+ if (p_sys->opaque->dec.p_module == NULL)
+ {
+ decoder_Destroy(&p_sys->alpha->dec);
+ decoder_Destroy(&p_sys->opaque->dec);
+ return VLC_EGENERIC;
+ }
+ p_sys->alpha->dec.cbs = &dec_cbs;
+ p_sys->alpha->dec.p_module =
+ module_need_var( &p_sys->alpha->dec, "video decoder", "codec" );
+ if (p_sys->alpha->dec.p_module == NULL)
+ {
+ decoder_Destroy(&p_sys->alpha->dec);
+ decoder_Destroy(&p_sys->opaque->dec);
+ return VLC_EGENERIC;
+ }
+
+ dec->pf_decode = Decode;
+ dec->pf_flush = Flush;
+
+ return VLC_SUCCESS;
+}
+
+void CloseDecoder(vlc_object_t *o)
+{
+ decoder_t *dec = container_of(o, decoder_t, obj);
+ vpx_alpha *p_sys = dec->p_sys;
+
+ es_format_Clean(&p_sys->opaque->fmt_out);
+ decoder_Destroy(&p_sys->opaque->dec);
+ es_format_Clean(&p_sys->alpha->fmt_out);
+ decoder_Destroy(&p_sys->alpha->dec);
+
+ if (p_sys->pool)
+ picture_pool_Release(p_sys->pool);
+
+ if (p_sys->vctx)
+ vlc_video_context_Release(p_sys->vctx);
+}
=====================================
modules/demux/avformat/mux.c
=====================================
@@ -204,7 +204,7 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
msg_Dbg( p_mux, "adding input" );
- if( !GetFfmpegCodec( fmt->i_cat, fmt->i_codec, &i_codec_id, NULL )
+ if( !GetFfmpegCodec( fmt, &i_codec_id, NULL )
|| i_codec_id == AV_CODEC_ID_NONE )
{
msg_Dbg( p_mux, "couldn't find codec for fourcc '%4.4s'",
=====================================
modules/demux/mkv/matroska_segment_parse.cpp
=====================================
@@ -580,6 +580,14 @@ void matroska_segment_c::ParseTrackEntry( const KaxTrackEntry *m )
}
}
}
+#if LIBMATROSKA_VERSION >= 0x010400
+ E_CASE( KaxVideoAlphaMode, mode )
+ {
+ ONLY_FMT(VIDEO);
+ debug( vars, "Track Video Alpha Mode %u", static_cast<uint8>( mode ) ) ;
+ vars.tk->b_has_alpha = static_cast<uint8>( mode ) == 1;
+ }
+#endif
#if LIBMATROSKA_VERSION >= 0x010406
E_CASE( KaxVideoProjection, proj )
{
@@ -1765,10 +1773,14 @@ bool matroska_segment_c::TrackInit( mkv_track_t * p_tk )
}
S_CASE("V_VP8") {
vars.p_fmt->i_codec = VLC_CODEC_VP8;
+ if (vars.p_tk->b_has_alpha)
+ vars.p_fmt->i_level = 0x1000; // mark as containing alpha data
vars.p_tk->b_pts_only = true;
}
S_CASE("V_VP9") {
vars.p_fmt->i_codec = VLC_CODEC_VP9;
+ if (vars.p_tk->b_has_alpha)
+ vars.p_fmt->i_level = 0x1000; // mark as containing alpha data
vars.p_fmt->b_packetized = false;
vars.p_tk->b_pts_only = true;
=====================================
modules/demux/mkv/mkv.cpp
=====================================
@@ -39,6 +39,7 @@ extern "C" {
#include <vlc_fs.h>
#include <vlc_url.h>
+#include <vlc_ancillary.h>
/*****************************************************************************
* Module descriptor
@@ -534,6 +535,13 @@ static int Seek( demux_t *p_demux, vlc_tick_t i_mk_date, double f_percent, virtu
return p_vsegment->Seek( *p_demux, i_mk_date, p_vchapter, b_precise ) ? VLC_SUCCESS : VLC_EGENERIC;
}
+static void ReleaseVpxAlpha(void *opaque)
+{
+ auto alpha = static_cast<vlc_vpx_alpha_t*>(opaque);
+ free(alpha->data);
+ delete alpha;
+}
+
/* Needed by matroska_segment::Seek() and Seek */
void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock,
KaxBlockAdditions *additions,
@@ -698,6 +706,52 @@ void BlockDecode( demux_t *p_demux, KaxBlock *block, KaxSimpleBlock *simpleblock
if( unlikely( !p_block ) )
continue;
break;
+
+ case VLC_CODEC_VP8:
+ case VLC_CODEC_VP9:
+ if (additions && track.fmt.i_level) // contains alpha extradata
+ {
+ KaxBlockMore *blockMore = FindChild<KaxBlockMore>(*additions);
+ if(blockMore == nullptr)
+ break;
+ KaxBlockAddID *addId = FindChild<KaxBlockAddID>(*blockMore);
+ if(addId == nullptr)
+ break;
+ if (static_cast<uint64>(*addId) != 1)
+ break;
+
+ KaxBlockAdditional *addition = FindChild<KaxBlockAdditional>(*blockMore);
+ if(addition == nullptr)
+ break;
+
+ auto alpha_data = new(std::nothrow) vlc_vpx_alpha_t();
+ if (unlikely(alpha_data == nullptr))
+ {
+ block_Release( p_block );
+ return;
+ }
+ alpha_data->data = static_cast<uint8_t*>(malloc(addition->GetSize()));
+ if (unlikely(alpha_data->data == nullptr))
+ {
+ delete alpha_data;
+ block_Release( p_block );
+ return;
+ }
+ alpha_data->size = addition->GetSize();
+ memcpy(alpha_data->data, addition->GetBuffer(), addition->GetSize());
+ vlc_ancillary *alpha =
+ vlc_ancillary_CreateWithFreeCb(alpha_data, VLC_ANCILLARY_ID_VPX_ALPHA,
+ ReleaseVpxAlpha);
+ if (likely(alpha != NULL))
+ vlc_frame_AttachAncillary(p_block, alpha);
+ else
+ {
+ ReleaseVpxAlpha(alpha_data);
+ block_Release( p_block );
+ return;
+ }
+ }
+ break;
}
if( track.fmt.i_cat != VIDEO_ES )
@@ -884,6 +938,7 @@ mkv_track_t::mkv_track_t(enum es_format_category_e es_cat) :
,i_chans_to_reorder(0)
,p_sys(NULL)
,b_discontinuity(false)
+ ,b_has_alpha(false)
,i_compression_type(MATROSKA_COMPRESSION_NONE)
,i_encoding_scope(MATROSKA_ENCODING_SCOPE_ALL_FRAMES)
,p_compression_data(NULL)
=====================================
modules/demux/mkv/mkv.hpp
=====================================
@@ -191,6 +191,7 @@ class mkv_track_t
PrivateTrackData *p_sys;
bool b_discontinuity;
+ bool b_has_alpha;
/* informative */
std::string str_codec_name;
=====================================
modules/hw/mmal/codec.c
=====================================
@@ -132,9 +132,9 @@ static bool set_and_test_enc_supported(vlc_object_t *obj, supported_mmal_enc_t *
return is_enc_supported(support, fcc);
}
-static MMAL_FOURCC_T vlc_to_mmal_es_fourcc(const unsigned int fcc)
+static MMAL_FOURCC_T vlc_to_mmal_es_fourcc(const es_format_t *es)
{
- switch (fcc){
+ switch (es->i_codec){
case VLC_CODEC_MJPG:
return MMAL_ENCODING_MJPEG;
case VLC_CODEC_MP1V:
@@ -151,6 +151,8 @@ static MMAL_FOURCC_T vlc_to_mmal_es_fourcc(const unsigned int fcc)
case VLC_CODEC_VP6:
return MMAL_ENCODING_VP6;
case VLC_CODEC_VP8:
+ if (es->i_level) // contains alpha extradata
+ return 0;
return MMAL_ENCODING_VP8;
case VLC_CODEC_WMV1:
return MMAL_ENCODING_WMV1;
@@ -594,7 +596,7 @@ static int OpenDecoder(vlc_object_t *p_this)
int ret = VLC_EGENERIC;
decoder_sys_t *sys;
MMAL_STATUS_T status;
- const MMAL_FOURCC_T in_fcc = vlc_to_mmal_es_fourcc(dec->fmt_in->i_codec);
+ const MMAL_FOURCC_T in_fcc = vlc_to_mmal_es_fourcc(dec->fmt_in);
if (in_fcc == 0) {
msg_Dbg(p_this, "codec %4.4s not supported", (const char*)&dec->fmt_in->i_codec);
return VLC_EGENERIC;
=====================================
modules/hw/nvdec/nvdec.c
=====================================
@@ -813,7 +813,10 @@ static int OpenDecoder(vlc_object_t *p_this)
case VLC_CODEC_MP2V:
case VLC_CODEC_MPGV:
case VLC_CODEC_MP4V:
+ break;
case VLC_CODEC_VP8:
+ if (p_dec->fmt_in->i_level) // contains alpha extradata
+ goto early_exit;
break;
case VLC_CODEC_VP9:
if (p_dec->fmt_in->i_profile != 0 && p_dec->fmt_in->i_profile != 2)
@@ -821,6 +824,8 @@ static int OpenDecoder(vlc_object_t *p_this)
msg_Warn(p_dec, "Unsupported VP9 profile %d", p_dec->fmt_in->i_profile);
goto early_exit;
}
+ if (p_dec->fmt_in->i_level) // contains alpha extradata
+ goto early_exit;
break;
default:
goto early_exit;
=====================================
modules/packetizer/avparser.c
=====================================
@@ -87,12 +87,13 @@ int avparser_OpenPacketizer( vlc_object_t *p_this )
/* Restrict to VP9 for now */
if( p_dec->fmt_in->i_codec != VLC_CODEC_VP9 )
- return VLC_EGENERIC;
+ return VLC_ENOTSUP;
+ if( p_dec->fmt_in->i_level ) // contains alpha extradata
+ return VLC_ENOTSUP;
enum AVCodecID i_avcodec_id;
- if( !GetFfmpegCodec( p_dec->fmt_in->i_cat, p_dec->fmt_in->i_codec,
- &i_avcodec_id, NULL ) )
+ if( !GetFfmpegCodec( p_dec->fmt_in, &i_avcodec_id, NULL ) )
return VLC_EGENERIC;
/* init avcodec */
=====================================
modules/stream_out/chromecast/cast.cpp
=====================================
@@ -116,7 +116,7 @@ struct sout_stream_sys_t
{
}
- bool canDecodeVideo( vlc_fourcc_t i_codec ) const;
+ bool canDecodeVideo( const es_format_t * ) const;
bool canDecodeAudio( sout_stream_t* p_stream, vlc_fourcc_t i_codec,
const audio_format_t* p_fmt ) const;
bool startSoutChain(sout_stream_t* p_stream,
@@ -763,16 +763,22 @@ static void Del(sout_stream_t *p_stream, void *_id)
* Supported formats: https://developers.google.com/cast/docs/media
*/
-bool sout_stream_sys_t::canDecodeVideo( vlc_fourcc_t i_codec ) const
+bool sout_stream_sys_t::canDecodeVideo( const es_format_t *es ) const
{
if( transcoding_state & TRANSCODING_VIDEO )
return false;
- switch( i_codec )
+ switch( es->i_codec )
{
case VLC_CODEC_H264:
case VLC_CODEC_HEVC:
+ return true;
case VLC_CODEC_VP8:
+ if (es->i_level) // contains alpha extradata
+ return false;
+ return true;
case VLC_CODEC_VP9:
+ if (es->i_level) // contains alpha extradata
+ return false;
return true;
default:
return false;
@@ -986,7 +992,7 @@ bool sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream )
{
if (p_es->i_cat == VIDEO_ES && p_original_video == NULL)
{
- if (!canDecodeVideo( p_es->i_codec ))
+ if (!canDecodeVideo( p_es ))
{
msg_Dbg( p_stream, "can't remux video track %d codec %4.4s",
p_es->i_id, (const char*)&p_es->i_codec );
=====================================
modules/stream_out/rtpfmt.c
=====================================
@@ -644,6 +644,8 @@ int rtp_get_fmt( vlc_object_t *obj, const es_format_t *p_fmt, const char *mux,
rtp_fmt->fmtp = strdup( "sprop-stereo=1" );
break;
case VLC_CODEC_VP8:
+ if (p_fmt->i_level) // contains alpha extradata
+ return VLC_ENOTSUP;
rtp_fmt->ptname = "VP8";
rtp_fmt->pf_packetize = rtp_packetize_vp8;
break;
=====================================
src/misc/fourcc_list.h
=====================================
@@ -521,9 +521,15 @@ static const staticentry_t p_list_video[] = {
B(VLC_CODEC_VP8, "Google/On2's VP8 Video"),
A("VP80"),
+ B(VLC_CODEC_VP8ALPHA_ES, "Google/On2's VP8 Alpha"),
+ A("VP8a"),
+
B(VLC_CODEC_VP9, "Google/On2's VP9 Video"),
A("VP90"),
+ B(VLC_CODEC_VP9ALPHA_ES, "Google/On2's VP9 Alpha"),
+ A("VP9a"),
+
B(VLC_CODEC_AV1, "AOMedia's AV1 Video"),
A("av10"),
A("AV01"),
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/dc3d6b67a75418051667b0f9e597604a4074826e...2367cf2e9e1436cdf9bc02df34bc8e3c0c10fd0e
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/dc3d6b67a75418051667b0f9e597604a4074826e...2367cf2e9e1436cdf9bc02df34bc8e3c0c10fd0e
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list