mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-09-08 21:28:45 +00:00
matroska: Export h.264 profile and level in caps
This replicates the code in qtdemux to export the h.264 profile and level in the stream caps. https://bugzilla.gnome.org/show_bug.cgi?id=614651
This commit is contained in:
parent
9317ad6fe9
commit
95c6d558f0
2 changed files with 113 additions and 0 deletions
|
@ -50,6 +50,7 @@
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <glib/gprintf.h>
|
||||||
|
|
||||||
/* For AVI compatibility mode
|
/* For AVI compatibility mode
|
||||||
and for fourcc stuff */
|
and for fourcc stuff */
|
||||||
|
@ -5803,6 +5804,103 @@ gst_matroska_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: This code is duplicated in gst/qtdemux/qtdemux.c. Please replicate any
|
||||||
|
* changes you make over there as well.
|
||||||
|
*/
|
||||||
|
static gchar *
|
||||||
|
avc_profile_idc_to_string (guint profile_idc, guint constraint_set_flags)
|
||||||
|
{
|
||||||
|
const gchar *profile = NULL;
|
||||||
|
gint csf1, csf3;
|
||||||
|
|
||||||
|
csf1 = (constraint_set_flags & 0x40) >> 6;
|
||||||
|
csf3 = (constraint_set_flags & 0x10) >> 4;
|
||||||
|
|
||||||
|
switch (profile_idc) {
|
||||||
|
case 66:
|
||||||
|
if (csf1)
|
||||||
|
profile = "constrained-baseline";
|
||||||
|
else
|
||||||
|
profile = "baseline";
|
||||||
|
break;
|
||||||
|
case 77:
|
||||||
|
profile = "main";
|
||||||
|
break;
|
||||||
|
case 88:
|
||||||
|
profile = "extended";
|
||||||
|
break;
|
||||||
|
case 100:
|
||||||
|
profile = "high";
|
||||||
|
break;
|
||||||
|
case 110:
|
||||||
|
if (csf3)
|
||||||
|
profile = "high-10-intra";
|
||||||
|
else
|
||||||
|
profile = "high-10";
|
||||||
|
break;
|
||||||
|
case 122:
|
||||||
|
if (csf3)
|
||||||
|
profile = "high-4:2:2-intra";
|
||||||
|
else
|
||||||
|
profile = "high-4:2:2";
|
||||||
|
break;
|
||||||
|
case 244:
|
||||||
|
if (csf3)
|
||||||
|
profile = "high-4:4:4-intra";
|
||||||
|
else
|
||||||
|
profile = "high-4:4:4";
|
||||||
|
break;
|
||||||
|
case 44:
|
||||||
|
profile = "cavlc-4:4:4-intra";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_strdup (profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
avc_level_idc_to_string (guint level_idc, guint constraint_set_flags)
|
||||||
|
{
|
||||||
|
const gchar *level = NULL;
|
||||||
|
gchar buf[4];
|
||||||
|
gint csf3;
|
||||||
|
|
||||||
|
csf3 = (constraint_set_flags & 0x10) >> 4;
|
||||||
|
|
||||||
|
if (level_idc == 11 && csf3)
|
||||||
|
level = "1b";
|
||||||
|
else {
|
||||||
|
/* Level is (level_idc / 10) */
|
||||||
|
if (level_idc % 10 == 0)
|
||||||
|
g_sprintf (buf, "%u", level_idc / 10);
|
||||||
|
else
|
||||||
|
g_sprintf (buf, "%u.%u", level_idc / 10, level_idc % 10);
|
||||||
|
|
||||||
|
level = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_strdup (level);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
avc_get_profile_and_level_string (const guint8 * avc_data, gint size,
|
||||||
|
gchar ** profile, gchar ** level)
|
||||||
|
{
|
||||||
|
if (size >= 2)
|
||||||
|
/* First byte is the version, second is the profile indication,
|
||||||
|
* and third is the 5 contraint_set_flags and 3 reserved bits */
|
||||||
|
*profile = avc_profile_idc_to_string (GST_READ_UINT8 (avc_data + 1),
|
||||||
|
GST_READ_UINT8 (avc_data + 2));
|
||||||
|
|
||||||
|
if (size >= 4)
|
||||||
|
/* Fourth byte is the level indication */
|
||||||
|
*level = avc_level_idc_to_string (GST_READ_UINT8 (avc_data + 3),
|
||||||
|
GST_READ_UINT8 (avc_data + 2));
|
||||||
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
|
gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
|
||||||
videocontext, const gchar * codec_id, guint8 * data, guint size,
|
videocontext, const gchar * codec_id, guint8 * data, guint size,
|
||||||
|
@ -5967,6 +6065,17 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
|
||||||
caps = gst_caps_new_simple ("video/x-h264", NULL);
|
caps = gst_caps_new_simple ("video/x-h264", NULL);
|
||||||
if (data) {
|
if (data) {
|
||||||
GstBuffer *priv = gst_buffer_new_and_alloc (size);
|
GstBuffer *priv = gst_buffer_new_and_alloc (size);
|
||||||
|
gchar *profile = NULL, *level = NULL;
|
||||||
|
|
||||||
|
avc_get_profile_and_level_string (data, size, &profile, &level);
|
||||||
|
if (profile) {
|
||||||
|
gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL);
|
||||||
|
g_free (profile);
|
||||||
|
}
|
||||||
|
if (level) {
|
||||||
|
gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL);
|
||||||
|
g_free (level);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy (GST_BUFFER_DATA (priv), data, size);
|
memcpy (GST_BUFFER_DATA (priv), data, size);
|
||||||
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
|
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
|
||||||
|
|
|
@ -5013,6 +5013,10 @@ qtdemux_get_rtsp_uri_from_hndl (GstQTDemux * qtdemux, GNode * minf)
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: This code is duplicated in gst/mastroska/matroska-demux.c. Please
|
||||||
|
* replicate any changes you make over there as well.
|
||||||
|
*/
|
||||||
static gchar *
|
static gchar *
|
||||||
avc_profile_idc_to_string (guint profile_idc, guint constraint_set_flags)
|
avc_profile_idc_to_string (guint profile_idc, guint constraint_set_flags)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue