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