Improve level/profile handling

This commit is contained in:
Sebastian Dröge 2012-09-10 15:30:55 +02:00
parent 2eff8bf82d
commit d06af02637
3 changed files with 97 additions and 34 deletions

View file

@ -2047,25 +2047,28 @@ static const struct
{
gint id;
const gchar *str;
const gchar *alt_str;
} avc_profile_mapping_table[] = {
{
AVCProfileBaseline, "baseline"}, {
AVCProfileMain, "main"}, {
AVCProfileExtended, "extended"}, {
AVCProfileBaseline, "baseline", "constrained-baseline"}, {
AVCProfileMain, "main", NULL}, {
AVCProfileExtended, "extended", NULL}, {
AVCProfileHigh, "high"}, {
AVCProfileHigh10, "high-10"}, {
AVCProfileHigh422, "high-4:2:2"}, {
AVCProfileHigh444, "high-4:4:4"}
AVCProfileHigh10, "high-10", "high-10-intra"}, {
AVCProfileHigh422, "high-4:2:2", "high-4:2:2-intra"}, {
AVCProfileHigh444, "high-4:4:4", "high-4:4:4-intra"}
};
const gchar *
gst_amc_avc_profile_to_string (gint profile)
gst_amc_avc_profile_to_string (gint profile, const gchar ** alternative)
{
gint i;
for (i = 0; i < G_N_ELEMENTS (avc_profile_mapping_table); i++) {
if (avc_profile_mapping_table[i].id == profile)
if (avc_profile_mapping_table[i].id == profile) {
*alternative = avc_profile_mapping_table[i].alt_str;
return avc_profile_mapping_table[i].str;
}
}
return NULL;

View file

@ -119,7 +119,7 @@ void gst_amc_format_set_buffer (GstAmcFormat *format, const gchar *key, GstBuffe
GstVideoFormat gst_amc_color_format_to_video_format (gint color_format);
gint gst_amc_video_format_to_color_format (GstVideoFormat video_format);
const gchar * gst_amc_avc_profile_to_string (gint profile);
const gchar * gst_amc_avc_profile_to_string (gint profile, const gchar **alternative);
gint gst_amc_avc_profile_from_string (const gchar *profile);
const gchar * gst_amc_avc_level_to_string (gint level);
gint gst_amc_avc_level_from_string (const gchar *level);

View file

@ -120,20 +120,36 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
for (j = 0; j < type->n_profile_levels; j++) {
const gchar *profile, *level;
gint k;
GValue va = { 0, };
GValue v = { 0, };
g_value_init (&va, GST_TYPE_LIST);
g_value_init (&v, G_TYPE_STRING);
profile =
gst_amc_mpeg4_profile_to_string (type->profile_levels[j].profile);
level = gst_amc_mpeg4_level_to_string (type->profile_levels[j].level);
if (!profile || !level) {
GST_ERROR ("Unable to map MPEG4 profile/level 0x%08x/0x%08x",
type->profile_levels[j].profile, type->profile_levels[j].level);
if (!profile) {
GST_ERROR ("Unable to map MPEG4 profile 0x%08x",
type->profile_levels[j].profile);
continue;
}
for (k = 1; k <= type->profile_levels[j].level && k != 0; k <<= 1) {
level = gst_amc_mpeg4_level_to_string (k);
if (!level)
continue;
g_value_set_string (&v, level);
gst_value_list_append_value (&va, &v);
g_value_reset (&v);
}
tmp2 = gst_structure_copy (tmp);
gst_structure_set (tmp2,
"profile", G_TYPE_STRING, profile,
"level", G_TYPE_STRING, level, NULL);
gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL);
gst_structure_set_value (tmp2, "level", &va);
g_value_unset (&va);
g_value_unset (&v);
gst_caps_append_structure (ret, tmp2);
have_profile_level = TRUE;
}
@ -158,19 +174,36 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
for (j = 0; j < type->n_profile_levels; j++) {
gint profile, level;
gint k;
GValue va = { 0, };
GValue v = { 0, };
g_value_init (&va, GST_TYPE_LIST);
g_value_init (&v, G_TYPE_UINT);
profile =
gst_amc_h263_profile_to_gst_id (type->profile_levels[j].profile);
level = gst_amc_h263_level_to_gst_id (type->profile_levels[j].level);
if (profile == -1 || level == -1) {
GST_ERROR ("Unable to map h263 profile/level 0x%08x/0x%08x",
type->profile_levels[j].profile, type->profile_levels[j].level);
if (profile == -1) {
GST_ERROR ("Unable to map h263 profile 0x%08x",
type->profile_levels[j].profile);
continue;
}
for (k = 1; k <= type->profile_levels[j].level && k != 0; k <<= 1) {
level = gst_amc_h263_level_to_gst_id (k);
if (level == -1)
continue;
g_value_set_uint (&v, level);
gst_value_list_append_value (&va, &v);
g_value_reset (&v);
}
tmp2 = gst_structure_copy (tmp);
gst_structure_set (tmp2,
"profile", G_TYPE_UINT, profile, "level", G_TYPE_UINT, level, NULL);
gst_structure_set (tmp2, "profile", G_TYPE_UINT, profile, NULL);
gst_structure_set_value (tmp2, "level", &va);
g_value_unset (&va);
g_value_unset (&v);
gst_caps_append_structure (ret, tmp2);
have_profile_level = TRUE;
}
@ -185,31 +218,58 @@ create_sink_caps (const GstAmcCodecInfo * codec_info)
GstStructure *tmp, *tmp2;
gboolean have_profile_level = FALSE;
/* FIXME: Alignment and stream-format? */
tmp = gst_structure_new ("video/x-h264",
"width", GST_TYPE_INT_RANGE, 16, 4096,
"height", GST_TYPE_INT_RANGE, 16, 4096,
"framerate", GST_TYPE_FRACTION_RANGE,
0, 1, G_MAXINT, 1, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
0, 1, G_MAXINT, 1,
"parsed", G_TYPE_BOOLEAN, TRUE,
"stream-format", G_TYPE_STRING, "byte-stream",
"alignment", G_TYPE_STRING, "au", NULL);
for (j = 0; j < type->n_profile_levels; j++) {
const gchar *profile, *level;
const gchar *profile, *alternative = NULL, *level;
gint k;
GValue va = { 0, };
GValue v = { 0, };
g_value_init (&va, GST_TYPE_LIST);
g_value_init (&v, G_TYPE_STRING);
profile =
gst_amc_avc_profile_to_string (type->profile_levels[j].profile);
level = gst_amc_avc_level_to_string (type->profile_levels[j].level);
if (!profile || !level) {
GST_ERROR ("Unable to map h264 profile/level 0x%08x/0x%08x",
type->profile_levels[j].profile, type->profile_levels[j].level);
gst_amc_avc_profile_to_string (type->profile_levels[j].profile,
&alternative);
if (!profile) {
GST_ERROR ("Unable to map H264 profile 0x%08x",
type->profile_levels[j].profile);
continue;
}
for (k = 1; k <= type->profile_levels[j].level && k != 0; k <<= 1) {
level = gst_amc_avc_level_to_string (k);
if (!level)
continue;
g_value_set_string (&v, level);
gst_value_list_append_value (&va, &v);
g_value_reset (&v);
}
tmp2 = gst_structure_copy (tmp);
gst_structure_set (tmp2,
"profile", G_TYPE_STRING, profile,
"level", G_TYPE_STRING, level, NULL);
gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL);
gst_structure_set_value (tmp2, "level", &va);
if (!alternative)
g_value_unset (&va);
g_value_unset (&v);
gst_caps_append_structure (ret, tmp2);
if (alternative) {
tmp2 = gst_structure_copy (tmp);
gst_structure_set (tmp2, "profile", G_TYPE_STRING, alternative, NULL);
gst_structure_set_value (tmp2, "level", &va);
g_value_unset (&va);
gst_caps_append_structure (ret, tmp2);
}
have_profile_level = TRUE;
}