typefind: rewrite h.264 detection
authorDavid Schleef <ds@schleef.org>
Tue, 19 Jan 2010 21:33:06 +0000 (13:33 -0800)
committerDavid Schleef <ds@schleef.org>
Tue, 19 Jan 2010 21:37:12 +0000 (13:37 -0800)
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.

gst/typefind/gsttypefindfunctions.c

index 93ddb63..c7b46dc 100644 (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 ((stat_slice > 4 || (stat_dpa > 4 && stat_dpb > 4 && stat_dpc > 4)) &&
-          stat_idr >= 1 && stat_sps >= 1 && stat_pps >= 1) {
+      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 */
+      }
+
+      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 ***/