qtdemux: Post avg./max. bitrate tags for H.264
authorArun Raghavan <ford_prefect@gentoo.org>
Tue, 6 Apr 2010 07:51:51 +0000 (13:21 +0530)
committerSebastian Dröge <sebastian.droege@collabora.co.uk>
Wed, 7 Apr 2010 09:55:32 +0000 (11:55 +0200)
This reads the average and maximum bitrates from the 'btrt' atom if
available, and pushes these as tags,

https://bugzilla.gnome.org/show_bug.cgi?id=614927

gst/qtdemux/qtdemux.c
gst/qtdemux/qtdemux_fourcc.h

index 070b621..558289c 100644 (file)
@@ -5342,45 +5342,85 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
           const guint8 *avc_data = stsd_data + 0x66;
 
           /* find avcC */
-          while (len >= 0x8 &&
-              QT_FOURCC (avc_data + 0x4) != FOURCC_avcC &&
-              QT_UINT32 (avc_data) < len) {
-            len -= QT_UINT32 (avc_data);
-            avc_data += QT_UINT32 (avc_data);
-          }
-
-          /* parse, if found */
-          if (len > 0x8 && QT_FOURCC (avc_data + 0x4) == FOURCC_avcC) {
-            GstBuffer *buf;
+          while (len >= 0x8) {
             gint size;
-            gchar *profile = NULL, *level = NULL;
 
-            if (QT_UINT32 (avc_data) < len)
+            if (QT_UINT32 (avc_data) <= len)
               size = QT_UINT32 (avc_data) - 0x8;
             else
               size = len - 0x8;
 
-            avc_get_profile_and_level_string (avc_data + 0x8, size, &profile,
-                &level);
-            if (profile) {
-              gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
-                  profile, NULL);
-              g_free (profile);
-            }
-            if (level) {
-              gst_caps_set_simple (stream->caps, "level", G_TYPE_STRING,
-                  level, NULL);
-              g_free (level);
-            }
+            if (size < 1)
+              /* No real data, so break out */
+              break;
 
-            GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
+            switch (QT_FOURCC (avc_data + 0x4)) {
+              case FOURCC_avcC:
+              {
+                /* parse, if found */
+                GstBuffer *buf;
+                gchar *profile = NULL, *level = NULL;
+
+                avc_get_profile_and_level_string (avc_data + 0x8, size,
+                    &profile, &level);
+                if (profile) {
+                  gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
+                      profile, NULL);
+                  g_free (profile);
+                }
+                if (level) {
+                  gst_caps_set_simple (stream->caps, "level", G_TYPE_STRING,
+                      level, NULL);
+                  g_free (level);
+                }
 
-            buf = gst_buffer_new_and_alloc (size);
-            memcpy (GST_BUFFER_DATA (buf), avc_data + 0x8, size);
-            gst_caps_set_simple (stream->caps,
-                "codec_data", GST_TYPE_BUFFER, buf, NULL);
-            gst_buffer_unref (buf);
+                GST_DEBUG_OBJECT (qtdemux, "found avcC codec_data in stsd");
+
+                buf = gst_buffer_new_and_alloc (size);
+                memcpy (GST_BUFFER_DATA (buf), avc_data + 0x8, size);
+                gst_caps_set_simple (stream->caps,
+                    "codec_data", GST_TYPE_BUFFER, buf, NULL);
+                gst_buffer_unref (buf);
+
+                break;
+              }
+              case FOURCC_btrt:
+              {
+                guint avg_bitrate, max_bitrate;
+
+                /* bufferSizeDB, maxBitrate and avgBitrate - 4 bytes each */
+                if (size < 12)
+                  break;
+
+                max_bitrate = QT_UINT32 (avc_data + 0xc);
+                avg_bitrate = QT_UINT32 (avc_data + 0x10);
+
+                if (!max_bitrate && !avg_bitrate)
+                  break;
+
+                if (!list)
+                  list = gst_tag_list_new ();
+
+                if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
+                  gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
+                      GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL);
+                }
+                if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) {
+                  gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
+                      GST_TAG_BITRATE, avg_bitrate, NULL);
+                }
+
+                break;
+              }
+
+              default:
+                break;
+            }
+
+            len -= QT_UINT32 (avc_data);
+            avc_data += QT_UINT32 (avc_data);
           }
+
           break;
         }
         case FOURCC_mjp2:
index 0ff4e53..345fe5e 100644 (file)
@@ -136,6 +136,7 @@ G_BEGIN_DECLS
 #define FOURCC_drmi     GST_MAKE_FOURCC('d','r','m','i')
 #define FOURCC_avc1     GST_MAKE_FOURCC('a','v','c','1')
 #define FOURCC_avcC     GST_MAKE_FOURCC('a','v','c','C')
+#define FOURCC_btrt     GST_MAKE_FOURCC('b','t','r','t')
 #define FOURCC_VP31     GST_MAKE_FOURCC('V','P','3','1')
 #define FOURCC_rle_     GST_MAKE_FOURCC('r','l','e',' ')
 #define FOURCC_MAC6     GST_MAKE_FOURCC('M','A','C','6')