mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-28 20:05:38 +00:00
typefinding: improve AAC LOAS typefinding
Make AAC LOAS typefinding a bit more reliable; don't report a LIKELY probability already after just two sync points, but scan for a few more consecutive frames and determine probability based on how many we found. Fixes mis-detection of wavpack file. https://bugzilla.gnome.org/show_bug.cgi?id=687674
This commit is contained in:
parent
bccb3feebf
commit
61f04f1460
1 changed files with 108 additions and 33 deletions
|
@ -845,6 +845,90 @@ flac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* TODO: we could probably make a generic function for this.. */
|
||||
static gint
|
||||
aac_type_find_scan_loas_frames_ep (GstTypeFind * tf, DataScanCtx * scan_ctx,
|
||||
gint max_frames)
|
||||
{
|
||||
DataScanCtx c = *scan_ctx;
|
||||
guint16 snc;
|
||||
guint len;
|
||||
gint count = 0;
|
||||
|
||||
do {
|
||||
if (!data_scan_ctx_ensure_data (tf, &c, 5))
|
||||
break;
|
||||
|
||||
/* EPAudioSyncStream */
|
||||
len = ((c.data[2] & 0x0f) << 9) | (c.data[3] << 1) |
|
||||
((c.data[4] & 0x80) >> 7);
|
||||
|
||||
if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
|
||||
GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
|
||||
break;
|
||||
}
|
||||
|
||||
/* check length of frame */
|
||||
snc = GST_READ_UINT16_BE (c.data + len);
|
||||
if (snc != 0x4de1) {
|
||||
GST_DEBUG ("No sync found at 0x%" G_GINT64_MODIFIER "x", c.offset + len);
|
||||
break;
|
||||
}
|
||||
|
||||
++count;
|
||||
|
||||
GST_DEBUG ("Found LOAS syncword #%d at offset 0x%" G_GINT64_MODIFIER "x, "
|
||||
"framelen %u", count, c.offset, len);
|
||||
|
||||
data_scan_ctx_advance (tf, &c, len);
|
||||
} while (count < max_frames && (c.offset - scan_ctx->offset) < 64 * 1024);
|
||||
|
||||
GST_DEBUG ("found %d consecutive frames", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
static gint
|
||||
aac_type_find_scan_loas_frames (GstTypeFind * tf, DataScanCtx * scan_ctx,
|
||||
gint max_frames)
|
||||
{
|
||||
DataScanCtx c = *scan_ctx;
|
||||
guint16 snc;
|
||||
guint len;
|
||||
gint count = 0;
|
||||
|
||||
do {
|
||||
if (!data_scan_ctx_ensure_data (tf, &c, 3))
|
||||
break;
|
||||
|
||||
/* AudioSyncStream */
|
||||
len = ((c.data[1] & 0x1f) << 8) | c.data[2];
|
||||
/* add size of sync stream header */
|
||||
len += 3;
|
||||
|
||||
if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len)) {
|
||||
GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
|
||||
break;
|
||||
}
|
||||
|
||||
/* check length of frame */
|
||||
snc = GST_READ_UINT16_BE (c.data + len);
|
||||
if ((snc & 0xffe0) != 0x56e0) {
|
||||
GST_DEBUG ("No sync found at 0x%" G_GINT64_MODIFIER "x", c.offset + len);
|
||||
break;
|
||||
}
|
||||
|
||||
++count;
|
||||
|
||||
GST_DEBUG ("Found LOAS syncword #%d at offset 0x%" G_GINT64_MODIFIER "x, "
|
||||
"framelen %u", count, c.offset, len);
|
||||
|
||||
data_scan_ctx_advance (tf, &c, len);
|
||||
} while (count < max_frames && (c.offset - scan_ctx->offset) < 64 * 1024);
|
||||
|
||||
GST_DEBUG ("found %d consecutive frames", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*** audio/mpeg version 2, 4 ***/
|
||||
|
||||
static GstStaticCaps aac_caps = GST_STATIC_CAPS ("audio/mpeg, "
|
||||
|
@ -854,8 +938,10 @@ static GstStaticCaps aac_caps = GST_STATIC_CAPS ("audio/mpeg, "
|
|||
static void
|
||||
aac_type_find (GstTypeFind * tf, gpointer unused)
|
||||
{
|
||||
/* LUT to convert the AudioObjectType from the ADTS header to a string */
|
||||
DataScanCtx c = { 0, NULL, 0 };
|
||||
GstTypeFindProbability best_probability = GST_TYPE_FIND_NONE;
|
||||
GstCaps *best_caps = NULL;
|
||||
guint best_count = 0;
|
||||
|
||||
while (c.offset < AAC_AMOUNT) {
|
||||
guint snc, len;
|
||||
|
@ -941,45 +1027,29 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
}
|
||||
|
||||
GST_DEBUG ("No next frame found... (should have been at 0x%x)", len);
|
||||
} else if (G_UNLIKELY (((snc & 0xffe0) == 0x56e0) || (snc == 0x4de1))) {
|
||||
} else if (G_UNLIKELY ((snc & 0xffe0) == 0x56e0 || snc == 0x4de1)) {
|
||||
gint count;
|
||||
|
||||
/* LOAS frame */
|
||||
GST_INFO ("Possible LOAS syncword at offset 0x%" G_GINT64_MODIFIER
|
||||
"x, scanning for more frames...", c.offset);
|
||||
|
||||
GST_DEBUG ("Found one LOAS syncword at offset 0x%" G_GINT64_MODIFIER
|
||||
"x, tracing next...", c.offset);
|
||||
if (snc == 0x4de1)
|
||||
count = aac_type_find_scan_loas_frames_ep (tf, &c, 20);
|
||||
else
|
||||
count = aac_type_find_scan_loas_frames (tf, &c, 20);
|
||||
|
||||
/* check length of frame for each type of detectable LOAS streams */
|
||||
if (snc == 0x4de1) {
|
||||
/* EPAudioSyncStream */
|
||||
len = ((c.data[2] & 0x0f) << 9) | (c.data[3] << 1) |
|
||||
((c.data[4] & 0x80) >> 7);
|
||||
/* add size of EP sync stream header */
|
||||
len += 7;
|
||||
} else {
|
||||
/* AudioSyncStream */
|
||||
len = ((c.data[1] & 0x1f) << 8) | c.data[2];
|
||||
/* add size of sync stream header */
|
||||
len += 3;
|
||||
}
|
||||
|
||||
if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) {
|
||||
GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len);
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* check if there's a second LOAS frame */
|
||||
snc = GST_READ_UINT16_BE (c.data + len);
|
||||
if (((snc & 0xffe0) == 0x56e0) || (snc == 0x4de1)) {
|
||||
GST_DEBUG ("Found second LOAS syncword at offset 0x%"
|
||||
G_GINT64_MODIFIER "x, framelen %u", c.offset, len);
|
||||
|
||||
gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
|
||||
if (count >= 3 && count > best_count) {
|
||||
gst_caps_unref (best_caps);
|
||||
best_caps = gst_caps_new_simple ("audio/mpeg",
|
||||
"framed", G_TYPE_BOOLEAN, FALSE,
|
||||
"mpegversion", G_TYPE_INT, 4,
|
||||
"stream-format", G_TYPE_STRING, "loas", NULL);
|
||||
break;
|
||||
best_count = count;
|
||||
best_probability = GST_TYPE_FIND_POSSIBLE - 10 + count * 3;
|
||||
if (best_probability >= GST_TYPE_FIND_LIKELY)
|
||||
break;
|
||||
}
|
||||
|
||||
GST_DEBUG ("No next frame found... (should have been at 0x%x)", len);
|
||||
} else if (!memcmp (c.data, "ADIF", 4)) {
|
||||
/* ADIF header */
|
||||
gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg",
|
||||
|
@ -992,6 +1062,11 @@ aac_type_find (GstTypeFind * tf, gpointer unused)
|
|||
|
||||
data_scan_ctx_advance (tf, &c, 1);
|
||||
}
|
||||
|
||||
if (best_probability > GST_TYPE_FIND_NONE) {
|
||||
gst_type_find_suggest (tf, best_probability, best_caps);
|
||||
gst_caps_unref (best_caps);
|
||||
}
|
||||
}
|
||||
|
||||
/*** audio/mpeg version 1 ***/
|
||||
|
|
Loading…
Reference in a new issue