mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
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:
parent
7cf9967e0b
commit
861311e8f6
2 changed files with 71 additions and 30 deletions
|
@ -5342,45 +5342,85 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
|
||||||
const guint8 *avc_data = stsd_data + 0x66;
|
const guint8 *avc_data = stsd_data + 0x66;
|
||||||
|
|
||||||
/* find avcC */
|
/* find avcC */
|
||||||
while (len >= 0x8 &&
|
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;
|
|
||||||
gint size;
|
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;
|
size = QT_UINT32 (avc_data) - 0x8;
|
||||||
else
|
else
|
||||||
size = len - 0x8;
|
size = len - 0x8;
|
||||||
|
|
||||||
avc_get_profile_and_level_string (avc_data + 0x8, size, &profile,
|
if (size < 1)
|
||||||
&level);
|
/* No real data, so break out */
|
||||||
if (profile) {
|
break;
|
||||||
gst_caps_set_simple (stream->caps, "profile", G_TYPE_STRING,
|
|
||||||
profile, NULL);
|
switch (QT_FOURCC (avc_data + 0x4)) {
|
||||||
g_free (profile);
|
case FOURCC_avcC:
|
||||||
}
|
{
|
||||||
if (level) {
|
/* parse, if found */
|
||||||
gst_caps_set_simple (stream->caps, "level", G_TYPE_STRING,
|
GstBuffer *buf;
|
||||||
level, NULL);
|
gchar *profile = NULL, *level = NULL;
|
||||||
g_free (level);
|
|
||||||
|
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");
|
len -= QT_UINT32 (avc_data);
|
||||||
|
avc_data += QT_UINT32 (avc_data);
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
case FOURCC_mjp2:
|
case FOURCC_mjp2:
|
||||||
|
|
|
@ -136,6 +136,7 @@ G_BEGIN_DECLS
|
||||||
#define FOURCC_drmi GST_MAKE_FOURCC('d','r','m','i')
|
#define FOURCC_drmi GST_MAKE_FOURCC('d','r','m','i')
|
||||||
#define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1')
|
#define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1')
|
||||||
#define FOURCC_avcC GST_MAKE_FOURCC('a','v','c','C')
|
#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_VP31 GST_MAKE_FOURCC('V','P','3','1')
|
||||||
#define FOURCC_rle_ GST_MAKE_FOURCC('r','l','e',' ')
|
#define FOURCC_rle_ GST_MAKE_FOURCC('r','l','e',' ')
|
||||||
#define FOURCC_MAC6 GST_MAKE_FOURCC('M','A','C','6')
|
#define FOURCC_MAC6 GST_MAKE_FOURCC('M','A','C','6')
|
||||||
|
|
Loading…
Reference in a new issue