typefind: rewrite h.264 detection

Make detection simpler: check for NALs, check that they make
sense, and report how certain we are that it's a raw H.264 stream.
Fixes: #583376.
This commit is contained in:
David Schleef 2010-01-19 13:33:06 -08:00
parent ad399c8069
commit e432c8ebc2

View file

@ -1874,14 +1874,9 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
/* Stream consists of: a series of sync codes (00 00 00 01) followed
* by NALs
*/
int stat_slice = 0;
int stat_dpa = 0;
int stat_dpb = 0;
int stat_dpc = 0;
int stat_idr = 0;
int stat_sps = 0;
int stat_pps = 0;
int nut, ref;
int good = 0;
int bad = 0;
while (c.offset < H264_MAX_PROBE_LENGTH) {
if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4)))
@ -1892,27 +1887,33 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
ref = c.data[3] & 0x60; /* nal_ref_idc */
/* if forbiden bit is different to 0 won't be h264 */
if (nut > 0x1f)
if (nut > 0x1f) {
bad++;
break;
}
/* collect statistics about the NAL types */
if (nut == 1)
stat_slice++;
else if (nut == 2)
stat_dpa++;
else if (nut == 3)
stat_dpb++;
else if (nut == 4)
stat_dpc++;
else if ((nut == 5) && (ref != 0))
stat_idr++;
else if ((nut == 7) && (ref != 0))
stat_sps++;
else if ((nut == 8) && (ref != 0))
stat_pps++;
if ((nut >= 1 && nut <= 13) || nut == 19) {
if ((nut == 5 && ref == 0) ||
((nut == 6 || (nut >= 9 && nut <= 12)) && ref != 0)) {
bad++;
} else {
good++;
}
} else if (nut >= 14 && nut <= 33) {
/* reserved */
/* Theoretically these are good, since if they exist in the
stream it merely means that a newer backwards-compatible
h.264 stream. But we should be identifying that separately. */
bad++;
} else {
/* unspecified, application specific */
/* don't consider these bad */
}
if ((stat_slice > 4 || (stat_dpa > 4 && stat_dpb > 4 && stat_dpc > 4)) &&
stat_idr >= 1 && stat_sps >= 1 && stat_pps >= 1) {
GST_DEBUG ("good %d bad %d", good, bad);
if (good >= 10 && bad < 4) {
gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H264_VIDEO_CAPS);
return;
}
@ -1921,6 +1922,11 @@ h264_video_type_find (GstTypeFind * tf, gpointer unused)
}
data_scan_ctx_advance (tf, &c, 1);
}
if (good >= 2 && bad < 1) {
gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, H264_VIDEO_CAPS);
return;
}
}
/*** video/mpeg video stream ***/