[FFmpeg-devel] [PATCH] IEC61937_EAC3 decoding support
Denis Shulyaka
shulyaka at gmail.com
Sat Apr 10 11:16:06 EEST 2021
This patch adds support to decode IEC61937_EAC3 (aka dolby digital plus).
Signed-off-by: Denis Shulyaka <Shulyaka at gmail.com>
---
libavformat/spdifdec.c | 47 ++++++++++++++++++++++++++++++++++--------
1 file changed, 38 insertions(+), 9 deletions(-)
diff --git a/libavformat/spdifdec.c b/libavformat/spdifdec.c
index 1808fa9d65..58841e7775 100644
--- a/libavformat/spdifdec.c
+++ b/libavformat/spdifdec.c
@@ -93,6 +93,10 @@ static int spdif_get_offset_and_codec(AVFormatContext *s,
*offset = 8192;
*codec = AV_CODEC_ID_DTS;
break;
+ case IEC61937_EAC3:
+ *offset = AC3_FRAME_SIZE << 4;
+ *codec = AV_CODEC_ID_EAC3;
+ break;
default:
if (s) { /* be silent during a probe */
avpriv_request_sample(s, "Data type 0x%04x in IEC 61937",
@@ -103,9 +107,34 @@ static int spdif_get_offset_and_codec(AVFormatContext *s,
return 0;
}
-/* Largest offset between bursts we currently handle, i.e. AAC with
- samples = 4096 */
-#define SPDIF_MAX_OFFSET 16384
+static int spdif_read_burst_payload_length(AVFormatContext *s,
+ enum IEC61937DataType data_type)
+{
+ AVIOContext *pb = s->pb;
+ int pkt_size_bits, pkt_size_bytes;
+
+ switch (data_type & 0xff) {
+ case IEC61937_EAC3:
+ pkt_size_bytes = avio_rl16(pb);
+
+ if (pkt_size_bytes % 2)
+ avpriv_request_sample(s, "Packet not ending at a 16-bit boundary");
+
+ return FFALIGN(pkt_size_bytes, 2);
+ break;
+ default:
+ pkt_size_bits = avio_rl16(pb);
+
+ if (pkt_size_bits % 16)
+ avpriv_request_sample(s, "Packet not ending at a 16-bit boundary");
+
+ return FFALIGN(pkt_size_bits, 16) >> 3;
+ }
+ return 0;
+}
+
+/* Largest offset between bursts we currently handle, i.e. E-AC-3 */
+#define SPDIF_MAX_OFFSET 24576
static int spdif_probe(const AVProbeData *p)
{
@@ -140,7 +169,7 @@ int ff_spdif_probe(const uint8_t *p_buf, int buf_size, enum AVCodecID *codec)
break;
/* continue probing to find more sync codes */
- probe_end = FFMIN(buf + SPDIF_MAX_OFFSET, p_buf + buf_size - 1);
+ probe_end = FFMIN(buf + SPDIF_MAX_OFFSET + 1, p_buf + buf_size - 1);
/* skip directly to the next sync code */
if (!spdif_get_offset_and_codec(NULL, (buf[2] << 8) | buf[1],
@@ -176,7 +205,7 @@ int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
enum IEC61937DataType data_type;
enum AVCodecID codec_id;
uint32_t state = 0;
- int pkt_size_bits, offset, ret;
+ int pkt_size, offset, ret;
while (state != (AV_BSWAP16C(SYNCWORD1) << 16 | AV_BSWAP16C(SYNCWORD2))) {
state = (state << 8) | avio_r8(pb);
@@ -185,12 +214,12 @@ int ff_spdif_read_packet(AVFormatContext *s, AVPacket *pkt)
}
data_type = avio_rl16(pb);
- pkt_size_bits = avio_rl16(pb);
+ pkt_size = spdif_read_burst_payload_length(s, data_type);
- if (pkt_size_bits % 16)
- avpriv_request_sample(s, "Packet not ending at a 16-bit boundary");
+ if (!pkt_size)
+ return AVERROR_BUG;
- ret = av_new_packet(pkt, FFALIGN(pkt_size_bits, 16) >> 3);
+ ret = av_new_packet(pkt, pkt_size);
if (ret)
return ret;
--
2.30.2
More information about the ffmpeg-devel
mailing list