h264parse: rework PAR parsing
authorAlessandro Decina <alessandro.decina@collabora.co.uk>
Wed, 23 Nov 2011 17:26:44 +0000 (18:26 +0100)
committerAlessandro Decina <alessandro.d@gmail.com>
Thu, 1 Dec 2011 08:06:56 +0000 (09:06 +0100)
And in the process refactor _update_src_caps a bit

gst/videoparsers/gsth264parse.c
gst/videoparsers/gsth264parse.h

index 6e9f907..1327d18 100644 (file)
@@ -193,6 +193,7 @@ gst_h264_parse_reset (GstH264Parse * h264parse)
   h264parse->height = 0;
   h264parse->fps_num = 0;
   h264parse->fps_den = 0;
+  h264parse->aspect_ratio_idc = 0;
   h264parse->sar_width = 0;
   h264parse->sar_height = 0;
   gst_buffer_replace (&h264parse->codec_data, NULL);
@@ -814,6 +815,92 @@ gst_h264_parse_make_codec_data (GstH264Parse * h264parse)
 }
 
 static void
+gst_h264_parse_get_par (GstH264Parse * h264parse, gint * num, gint * den)
+{
+  gint par_n, par_d;
+
+  par_n = par_d = 0;
+  switch (h264parse->aspect_ratio_idc) {
+    case 0:
+      par_n = par_d = 0;
+      break;
+    case 1:
+      par_n = 1;
+      par_d = 1;
+      break;
+    case 2:
+      par_n = 12;
+      par_d = 11;
+      break;
+    case 3:
+      par_n = 10;
+      par_d = 11;
+      break;
+    case 4:
+      par_n = 16;
+      par_d = 11;
+      break;
+    case 5:
+      par_n = 40;
+      par_d = 33;
+      break;
+    case 6:
+      par_n = 24;
+      par_d = 11;
+      break;
+    case 7:
+      par_n = 20;
+      par_d = 11;
+      break;
+    case 8:
+      par_n = 32;
+      par_d = 11;
+      break;
+    case 9:
+      par_n = 80;
+      par_d = 33;
+      break;
+    case 10:
+      par_n = 18;
+      par_d = 11;
+      break;
+    case 11:
+      par_n = 15;
+      par_d = 11;
+      break;
+    case 12:
+      par_n = 64;
+      par_d = 33;
+      break;
+    case 13:
+      par_n = 160;
+      par_d = 99;
+      break;
+    case 14:
+      par_n = 4;
+      par_d = 3;
+      break;
+    case 15:
+      par_n = 3;
+      par_d = 2;
+      break;
+    case 16:
+      par_n = 2;
+      par_d = 1;
+      break;
+    case 255:
+      par_n = h264parse->sar_width;
+      par_d = h264parse->sar_height;
+      break;
+    default:
+      par_n = par_d = 0;
+  }
+
+  *num = par_n;
+  *den = par_d;
+}
+
+static void
 gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps)
 {
   GstH264SPS *sps;
@@ -861,46 +948,80 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps)
   caps = NULL;
   if (G_UNLIKELY (!sps)) {
     caps = gst_caps_copy (sink_caps);
-  } else if (G_UNLIKELY (h264parse->width != sps->width ||
-          h264parse->height != sps->height || h264parse->fps_num != sps->fps_num
-          || h264parse->fps_den != sps->fps_den ||
-          h264parse->sar_width != sps->vui_parameters.sar_width ||
-          h264parse->sar_height != sps->vui_parameters.sar_height
-          || modified)) {
-    caps = gst_caps_copy (sink_caps);
-    /* sps should give this */
-    gst_caps_set_simple (caps, "width", G_TYPE_INT, sps->width,
-        "height", G_TYPE_INT, sps->height, NULL);
-    h264parse->height = sps->height;
-    h264parse->width = sps->width;
-    /* but not necessarily or reliably this */
-    if ((!h264parse->fps_num || !h264parse->fps_den) &&
-        sps->fps_num > 0 && sps->fps_den > 0) {
-      gst_caps_set_simple (caps, "framerate",
-          GST_TYPE_FRACTION, sps->fps_num, sps->fps_den, NULL);
-      h264parse->fps_num = sps->fps_num;
-      h264parse->fps_den = sps->fps_den;
-      gst_base_parse_set_frame_rate (GST_BASE_PARSE (h264parse),
-          h264parse->fps_num, h264parse->fps_den, 0, 0);
+  } else {
+    if (G_UNLIKELY (h264parse->width != sps->width ||
+            h264parse->height != sps->height)) {
+      GST_INFO_OBJECT (h264parse, "resolution changed %dx%d",
+          sps->width, sps->height);
+      h264parse->width = sps->width;
+      h264parse->height = sps->height;
+      modified = TRUE;
+    }
+
+    /* 0/1 is set as the default in the codec parser */
+    if (sps->vui_parameters.timing_info_present_flag &&
+        !(sps->fps_num == 0 && sps->fps_den == 1)) {
+      if (G_UNLIKELY (h264parse->fps_num != sps->fps_num
+              || h264parse->fps_den != sps->fps_den)) {
+        GST_INFO_OBJECT (h264parse, "framerate changed %d/%d",
+            sps->fps_num, sps->fps_den);
+        h264parse->fps_num = sps->fps_num;
+        h264parse->fps_den = sps->fps_den;
+        gst_base_parse_set_frame_rate (GST_BASE_PARSE (h264parse),
+            h264parse->fps_num, h264parse->fps_den, 0, 0);
+        modified = TRUE;
+      }
+    }
+
+    if (sps->vui_parameters.aspect_ratio_info_present_flag) {
+      if (G_UNLIKELY (h264parse->aspect_ratio_idc !=
+              sps->vui_parameters.aspect_ratio_idc)) {
+        h264parse->aspect_ratio_idc = sps->vui_parameters.aspect_ratio_idc;
+        GST_INFO_OBJECT (h264parse, "aspect ratio idc changed %d",
+            h264parse->aspect_ratio_idc);
+        modified = TRUE;
+      }
+
+      /* 255 means sar_width and sar_height present */
+      if (G_UNLIKELY (sps->vui_parameters.aspect_ratio_idc == 255 &&
+              (h264parse->sar_width != sps->vui_parameters.sar_width ||
+                  h264parse->sar_height != sps->vui_parameters.sar_height))) {
+        h264parse->sar_width = sps->vui_parameters.sar_width;
+        h264parse->sar_height = sps->vui_parameters.sar_height;
+        GST_INFO_OBJECT (h264parse, "aspect ratio SAR changed %d/%d",
+            h264parse->sar_width, h264parse->sar_height);
+        modified = TRUE;
+      }
     }
-    if ((sps->vui_parameters.sar_width > 0 &&
-            sps->vui_parameters.sar_height > 0) &&
-        (h264parse->sar_width != sps->vui_parameters.sar_width ||
-            h264parse->sar_height != sps->vui_parameters.sar_height)) {
-      h264parse->sar_width = sps->vui_parameters.sar_width;
-      h264parse->sar_height = sps->vui_parameters.sar_height;
+
+    if (G_UNLIKELY (modified)) {
+      caps = gst_caps_copy (sink_caps);
+      /* sps should give this */
+      gst_caps_set_simple (caps, "width", G_TYPE_INT, sps->width,
+          "height", G_TYPE_INT, sps->height, NULL);
+      /* but not necessarily or reliably this */
+      if (h264parse->fps_num > 0 && h264parse->fps_den > 0)
+        gst_caps_set_simple (caps, "framerate",
+            GST_TYPE_FRACTION, sps->fps_num, sps->fps_den, NULL);
     }
   }
 
   if (caps) {
+    gint par_n, par_d;
+
     gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE,
         "stream-format", G_TYPE_STRING,
         gst_h264_parse_get_string (h264parse, TRUE, h264parse->format),
         "alignment", G_TYPE_STRING,
         gst_h264_parse_get_string (h264parse, FALSE, h264parse->align), NULL);
-    if (h264parse->sar_width > 0 && h264parse->sar_height > 0)
+
+    gst_h264_parse_get_par (h264parse, &par_n, &par_d);
+    if (par_n != 0 && par_d != 0) {
+      GST_INFO_OBJECT (h264parse, "PAR %d/%d", par_n, par_d);
       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
-          h264parse->sar_width, h264parse->sar_height, NULL);
+          par_n, par_d, NULL);
+    }
+
     if (buf) {
       gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
       gst_buffer_replace (&h264parse->codec_data, buf);
index d311dd0..c724aa0 100644 (file)
@@ -58,6 +58,7 @@ struct _GstH264Parse
   /* stream */
   gint width, height;
   gint fps_num, fps_den;
+  gint aspect_ratio_idc;
   gint sar_width, sar_height;
   GstBuffer *codec_data;
   guint nal_length_size;