diff --git a/sys/androidmedia/gstamc.c b/sys/androidmedia/gstamc.c index 4acf3cb4cd..e94dad8835 100644 --- a/sys/androidmedia/gstamc.c +++ b/sys/androidmedia/gstamc.c @@ -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; diff --git a/sys/androidmedia/gstamc.h b/sys/androidmedia/gstamc.h index 8c8a6bd25d..32c601c9fa 100644 --- a/sys/androidmedia/gstamc.h +++ b/sys/androidmedia/gstamc.h @@ -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); diff --git a/sys/androidmedia/gstamcvideodec.c b/sys/androidmedia/gstamcvideodec.c index 449e4419ee..d83b19079c 100644 --- a/sys/androidmedia/gstamcvideodec.c +++ b/sys/androidmedia/gstamcvideodec.c @@ -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; }