diff --git a/subprojects/gst-libav/docs/gst_plugins_cache.json b/subprojects/gst-libav/docs/gst_plugins_cache.json index 1bc1b0a328..e27deefd5b 100644 --- a/subprojects/gst-libav/docs/gst_plugins_cache.json +++ b/subprojects/gst-libav/docs/gst_plugins_cache.json @@ -6659,7 +6659,7 @@ "long-name": "libav DSD (Direct Stream Digital), least significant bit first decoder", "pad-templates": { "sink": { - "caps": "audio/x-dsd:\n lsbf: true\n planar: false\n", + "caps": "audio/x-dsd:\n format: DSDU8\n reversed-bytes: true\n layout: interleaved\n", "direction": "sink", "presence": "always" }, @@ -6687,7 +6687,7 @@ "long-name": "libav DSD (Direct Stream Digital), least significant bit first, planar decoder", "pad-templates": { "sink": { - "caps": "audio/x-dsd:\n lsbf: true\n planar: true\n", + "caps": "audio/x-dsd:\n format: DSDU8\n reversed-bytes: true\n layout: non-interleaved\n", "direction": "sink", "presence": "always" }, @@ -6715,7 +6715,7 @@ "long-name": "libav DSD (Direct Stream Digital), most significant bit first decoder", "pad-templates": { "sink": { - "caps": "audio/x-dsd:\n lsbf: false\n planar: false\n", + "caps": "audio/x-dsd:\n format: DSDU8\n reversed-bytes: false\n layout: interleaved\n", "direction": "sink", "presence": "always" }, @@ -6743,7 +6743,7 @@ "long-name": "libav DSD (Direct Stream Digital), most significant bit first, planar decoder", "pad-templates": { "sink": { - "caps": "audio/x-dsd:\n lsbf: false\n planar: true\n", + "caps": "audio/x-dsd:\n format: DSDU8\n reversed-bytes: false\n layout: non-interleaved\n", "direction": "sink", "presence": "always" }, diff --git a/subprojects/gst-libav/ext/libav/gstavcodecmap.c b/subprojects/gst-libav/ext/libav/gstavcodecmap.c index 716df19f26..2425913c35 100644 --- a/subprojects/gst-libav/ext/libav/gstavcodecmap.c +++ b/subprojects/gst-libav/ext/libav/gstavcodecmap.c @@ -34,6 +34,7 @@ #include #include +#include #include /* IMPORTANT: Keep this sorted by the ffmpeg channel masks */ @@ -640,6 +641,36 @@ gst_ff_aud_caps_new (AVCodecContext * context, AVCodec * codec, rates = l_rates; break; } + case AV_CODEC_ID_DSD_LSBF: + case AV_CODEC_ID_DSD_MSBF: + case AV_CODEC_ID_DSD_LSBF_PLANAR: + case AV_CODEC_ID_DSD_MSBF_PLANAR: + { + const static gint l_rates[] = { + GST_DSD_MAKE_DSD_RATE_44x (64), + GST_DSD_MAKE_DSD_RATE_48x (64), + GST_DSD_MAKE_DSD_RATE_44x (128), + GST_DSD_MAKE_DSD_RATE_48x (128), + GST_DSD_MAKE_DSD_RATE_44x (256), + GST_DSD_MAKE_DSD_RATE_48x (256), + GST_DSD_MAKE_DSD_RATE_44x (512), + GST_DSD_MAKE_DSD_RATE_48x (512), + GST_DSD_MAKE_DSD_RATE_44x (1024), + GST_DSD_MAKE_DSD_RATE_48x (1024), + GST_DSD_MAKE_DSD_RATE_44x (2048), + GST_DSD_MAKE_DSD_RATE_48x (2048), + }; + /* There is no clearly defined maximum number of channels in DSD. + * The DSF spec mentions a maximum of 6 channels, while the DSDIFF + * spec mentions up to 65535 channels. DSDIFF stores DSD in an + * interleaved, DSF in a planar fashion. But there is no reason + * why some other format couldn't have more than 6 interleaved + * channels for example. */ + maxchannels = 65535; + n_rates = G_N_ELEMENTS (l_rates); + rates = l_rates; + break; + } default: break; } @@ -2318,33 +2349,45 @@ gst_ffmpeg_codecid_to_caps (enum AVCodecID codec_id, NULL); break; case AV_CODEC_ID_DSD_LSBF: - caps = - gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dsd", - NULL); - gst_caps_set_simple (caps, "lsbf", G_TYPE_BOOLEAN, - TRUE, "planar", G_TYPE_BOOLEAN, FALSE, NULL); - break; case AV_CODEC_ID_DSD_MSBF: - caps = - gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dsd", - NULL); - gst_caps_set_simple (caps, "lsbf", G_TYPE_BOOLEAN, - FALSE, "planar", G_TYPE_BOOLEAN, FALSE, NULL); - break; case AV_CODEC_ID_DSD_LSBF_PLANAR: - caps = - gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dsd", - NULL); - gst_caps_set_simple (caps, "lsbf", G_TYPE_BOOLEAN, - TRUE, "planar", G_TYPE_BOOLEAN, TRUE, NULL); - break; case AV_CODEC_ID_DSD_MSBF_PLANAR: + { + gboolean reversed_bytes; + gboolean interleaved; + + switch (codec_id) { + case AV_CODEC_ID_DSD_LSBF: + reversed_bytes = TRUE; + interleaved = TRUE; + break; + case AV_CODEC_ID_DSD_MSBF: + reversed_bytes = FALSE; + interleaved = TRUE; + break; + case AV_CODEC_ID_DSD_LSBF_PLANAR: + reversed_bytes = TRUE; + interleaved = FALSE; + break; + case AV_CODEC_ID_DSD_MSBF_PLANAR: + reversed_bytes = FALSE; + interleaved = FALSE; + break; + default: + reversed_bytes = FALSE; + interleaved = FALSE; + break; + } + caps = gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/x-dsd", - NULL); - gst_caps_set_simple (caps, "lsbf", G_TYPE_BOOLEAN, - FALSE, "planar", G_TYPE_BOOLEAN, TRUE, NULL); + "format", G_TYPE_STRING, "DSDU8", + "reversed-bytes", G_TYPE_BOOLEAN, reversed_bytes, + "layout", G_TYPE_STRING, + (interleaved) ? "interleaved" : "non-interleaved", NULL); + break; + } case AV_CODEC_ID_APTX: caps = gst_ff_aud_caps_new (context, NULL, codec_id, encode, "audio/aptx", diff --git a/subprojects/gst-libav/ext/libav/gstavdemux.c b/subprojects/gst-libav/ext/libav/gstavdemux.c index 2d3d1645af..5433554a2c 100644 --- a/subprojects/gst-libav/ext/libav/gstavdemux.c +++ b/subprojects/gst-libav/ext/libav/gstavdemux.c @@ -30,6 +30,7 @@ /* #include */ #include #include +#include #include "gstav.h" #include "gstavcodecmap.h" @@ -1576,6 +1577,32 @@ gst_ffmpegdemux_loop (GstFFMpegDemux * demux) stream->discont = FALSE; } + /* If we are demuxing planar DSD data, add the necessary + * meta to inform downstream about the planar layout. */ + switch (avstream->codecpar->codec_id) { + case AV_CODEC_ID_DSD_LSBF_PLANAR: + case AV_CODEC_ID_DSD_MSBF_PLANAR: + { + int channel_idx; + int num_channels = avstream->codecpar->channels; + int num_bytes_per_channel = pkt.size / num_channels; + GstDsdPlaneOffsetMeta *plane_ofs_meta; + + plane_ofs_meta = gst_buffer_add_dsd_plane_offset_meta (outbuf, + avstream->codecpar->channels, num_bytes_per_channel, NULL); + + for (channel_idx = 0; channel_idx < num_channels; ++channel_idx) { + plane_ofs_meta->offsets[channel_idx] = + num_bytes_per_channel * channel_idx; + } + + break; + } + + default: + break; + } + GST_DEBUG_OBJECT (demux, "Sending out buffer time:%" GST_TIME_FORMAT " size:%" G_GSIZE_FORMAT, GST_TIME_ARGS (timestamp), gst_buffer_get_size (outbuf));