qtdemux: Post avg./max. bitrate tags for H.264

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
This commit is contained in:
Arun Raghavan 2010-04-06 13:21:51 +05:30 committed by Sebastian Dröge
parent 7cf9967e0b
commit 861311e8f6
2 changed files with 71 additions and 30 deletions

View 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;
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);
}
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;
}
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);
len -= QT_UINT32 (avc_data);
avc_data += QT_UINT32 (avc_data);
}
break;
}
case FOURCC_mjp2:

View 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')