ac3parse: extract and use some more details for Enhanced Ac-3 streams

This commit is contained in:
Mark Nauwelaerts 2009-10-29 15:19:04 +01:00 committed by Tim-Philipp Müller
parent 0777806170
commit d90c80e017

View file

@ -141,6 +141,7 @@ static const struct
static const guint fscod_rates[4] = { 48000, 44100, 32000, 0 }; static const guint fscod_rates[4] = { 48000, 44100, 32000, 0 };
static const guint acmod_chans[8] = { 2, 1, 2, 3, 3, 4, 4, 5 }; static const guint acmod_chans[8] = { 2, 1, 2, 3, 3, 4, 4, 5 };
static const guint numblks[4] = { 1, 2, 3, 6 };
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
@ -250,7 +251,7 @@ gst_ac3_parse_is_seekable (GstBaseParse * parse)
static gboolean static gboolean
gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf, gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
guint * frame_size, guint * rate, guint * chans) guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
{ {
GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf); GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
guint8 fscod, frmsizcod, bsid, bsmod, acmod, lfe_on; guint8 fscod, frmsizcod, bsid, bsmod, acmod, lfe_on;
@ -289,17 +290,21 @@ gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
*rate = fscod_rates[fscod]; *rate = fscod_rates[fscod];
if (chans) if (chans)
*chans = acmod_chans[acmod] + lfe_on; *chans = acmod_chans[acmod] + lfe_on;
if (blks)
*blks = 6;
if (sid)
*sid = 0;
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf, gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
guint * frame_size, guint * rate, guint * chans) guint * frame_size, guint * rate, guint * chans, guint * blks, guint * sid)
{ {
GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf); GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
guint16 frmsiz, sample_rate; guint16 frmsiz, sample_rate, blocks;
guint8 strmtyp, fscod, fscod2, acmod, lfe_on; guint8 strmtyp, fscod, fscod2, acmod, lfe_on, strmid, numblkscod;
gst_bit_reader_skip (&bits, 16 + 16); gst_bit_reader_skip (&bits, 16 + 16);
gst_bit_reader_get_bits_uint8 (&bits, &strmtyp, 2); /* strmtyp */ gst_bit_reader_get_bits_uint8 (&bits, &strmtyp, 2); /* strmtyp */
@ -308,7 +313,7 @@ gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
return FALSE; return FALSE;
} }
gst_bit_reader_skip (&bits, 3); /* substreamid */ gst_bit_reader_get_bits_uint8 (&bits, &strmid, 3); /* substreamid */
gst_bit_reader_get_bits_uint16 (&bits, &frmsiz, 11); /* frmsiz */ gst_bit_reader_get_bits_uint16 (&bits, &frmsiz, 11); /* frmsiz */
gst_bit_reader_get_bits_uint8 (&bits, &fscod, 2); /* fscod */ gst_bit_reader_get_bits_uint8 (&bits, &fscod, 2); /* fscod */
if (fscod == 3) { if (fscod == 3) {
@ -318,9 +323,11 @@ gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
return FALSE; return FALSE;
} }
sample_rate = fscod_rates[fscod2] / 2; sample_rate = fscod_rates[fscod2] / 2;
blocks = 6;
} else { } else {
gst_bit_reader_skip (&bits, 2); /* numblkscod */ gst_bit_reader_get_bits_uint8 (&bits, &numblkscod, 2); /* numblkscod */
sample_rate = fscod_rates[fscod]; sample_rate = fscod_rates[fscod];
blocks = numblks[numblkscod];
} }
gst_bit_reader_get_bits_uint8 (&bits, &acmod, 3); /* acmod */ gst_bit_reader_get_bits_uint8 (&bits, &acmod, 3); /* acmod */
@ -334,13 +341,17 @@ gst_ac3_parse_frame_header_eac3 (GstAc3Parse * ac3parse, GstBuffer * buf,
*rate = sample_rate; *rate = sample_rate;
if (chans) if (chans)
*chans = acmod_chans[acmod] + lfe_on; *chans = acmod_chans[acmod] + lfe_on;
if (blks)
*blks = blocks;
if (sid)
*sid = (strmtyp & 0x1) << 3 | strmid;
return TRUE; return TRUE;
} }
static gboolean static gboolean
gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf, gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf,
guint * framesize, guint * rate, guint * chans) guint * framesize, guint * rate, guint * chans, guint * blocks, guint * sid)
{ {
GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf); GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
guint16 sync; guint16 sync;
@ -356,9 +367,11 @@ gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf,
return FALSE; return FALSE;
if (bsid <= 10) { if (bsid <= 10) {
return gst_ac3_parse_frame_header_ac3 (parse, buf, framesize, rate, chans); return gst_ac3_parse_frame_header_ac3 (parse, buf, framesize, rate, chans,
blocks, sid);
} else if (bsid <= 16) { } else if (bsid <= 16) {
return gst_ac3_parse_frame_header_eac3 (parse, buf, framesize, rate, chans); return gst_ac3_parse_frame_header_eac3 (parse, buf, framesize, rate, chans,
blocks, sid);
} else { } else {
GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid); GST_DEBUG_OBJECT (parse, "unexpected bsid %d", bsid);
return FALSE; return FALSE;
@ -392,7 +405,8 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
} }
/* make sure the values in the frame header look sane */ /* make sure the values in the frame header look sane */
if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, NULL, NULL)) { if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, NULL, NULL,
NULL, NULL)) {
*skipsize = off + 2; *skipsize = off + 2;
return FALSE; return FALSE;
} }
@ -432,13 +446,19 @@ static GstFlowReturn
gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
{ {
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse); GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
guint fsize, rate, chans; guint fsize, rate, chans, blocks, sid;
if (!gst_ac3_parse_frame_header (ac3parse, buf, &fsize, &rate, &chans)) if (!gst_ac3_parse_frame_header (ac3parse, buf, &fsize, &rate, &chans,
&blocks, &sid))
goto broken_header; goto broken_header;
GST_LOG_OBJECT (parse, "size: %u, rate: %u, chans: %u", fsize, rate, chans); GST_LOG_OBJECT (parse, "size: %u, rate: %u, chans: %u", fsize, rate, chans);
if (G_UNLIKELY (sid)) {
GST_LOG_OBJECT (parse, "sid: %d", sid);
GST_BUFFER_FLAG_SET (buf, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME);
}
if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans)) { if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans)) {
GstCaps *caps = gst_caps_new_simple ("audio/x-ac3", GstCaps *caps = gst_caps_new_simple ("audio/x-ac3",
"framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate, "framed", G_TYPE_BOOLEAN, TRUE, "rate", G_TYPE_INT, rate,
@ -450,7 +470,7 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
ac3parse->sample_rate = rate; ac3parse->sample_rate = rate;
ac3parse->channels = chans; ac3parse->channels = chans;
gst_base_parse_set_frame_props (parse, rate, 256 * 6, 50); gst_base_parse_set_frame_props (parse, rate, 256 * blocks, 50);
} }
return GST_FLOW_OK; return GST_FLOW_OK;