From 557d6b974fe98d09ddd0a500548b8a13211dab1c Mon Sep 17 00:00:00 2001 From: Chen Jie Date: Tue, 8 Oct 2013 21:11:48 +0800 Subject: [PATCH] androidmedia: move create_src|sink_caps to gstamc.c Some hack logic needs also to be present in create_src|sink_caps, for working around some broken codecs. These hacks are hidden in color_format/video_format conversion -- the prototypes of these functions are also changed to include more args for hack judgement. Also in case of multi-color_formats mapped to one video_format, then map that video_format back will not give the original color_format, which causes gst_amc_codec_configure failed with something like 'does not support color format N'. The new prototype involves with GstAmcCodecInfo and mime, which ensures the converted color_format is supported by the codec. A COLOR_FormatYCbYCr to GST_VIDEO_FORMAT_YUY2 mapping is also added, in order to work around bugs in OMX.k3.video.decoder.avc(which incorrectly reports supporting COLOR_FormatYCbYCr, which is actually COLOR_FormatYUV420SemiPlanar). There are already hacks for this in gst_amc_video_format_to_color_format, gst_amc_color_format_to_video_format and gst_amc_color_format_info_set, but the codec will still not work(be ignored because of "has unknown color formats") without adding this mapping. --- sys/androidmedia/gstamc.c | 481 +++++++++++++++++++++++++++++- sys/androidmedia/gstamc.h | 6 +- sys/androidmedia/gstamcaudiodec.c | 155 +--------- sys/androidmedia/gstamcvideodec.c | 239 ++------------- sys/androidmedia/gstamcvideoenc.c | 306 +------------------ 5 files changed, 507 insertions(+), 680 deletions(-) diff --git a/sys/androidmedia/gstamc.c b/sys/androidmedia/gstamc.c index 326ae1e154..e6f3d5f2d9 100644 --- a/sys/androidmedia/gstamc.c +++ b/sys/androidmedia/gstamc.c @@ -1857,13 +1857,6 @@ scan_codecs (GstPlugin * plugin) } for (k = 0; k < n_elems; k++) { - if (strcmp (name_str, "OMX.k3.video.decoder.avc") == 0) - if (n_elems == 1 && color_formats_elems[k] == COLOR_FormatYCbYCr) { - GST_INFO ("On HuaweiMediaPad it reports a wrong COLOR_FormatYCbYCr," - "should be COLOR_TI_FormatYUV420PackedSemiPlanar, fix it."); - color_formats_elems[k] = COLOR_TI_FormatYUV420PackedSemiPlanar; - } - GST_INFO ("Color format %d: 0x%x", k, color_formats_elems[k]); gst_codec_type->color_formats[k] = color_formats_elems[k]; } @@ -2144,7 +2137,8 @@ static const struct COLOR_QCOM_FormatYUV420SemiPlanar, GST_VIDEO_FORMAT_NV12}, { COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, GST_VIDEO_FORMAT_NV12}, { COLOR_QCOM_FormatYVU420SemiPlanar32m, GST_VIDEO_FORMAT_NV12}, { - COLOR_OMX_SEC_FormatNV12Tiled, GST_VIDEO_FORMAT_NV12} + COLOR_OMX_SEC_FormatNV12Tiled, GST_VIDEO_FORMAT_NV12}, { + COLOR_FormatYCbYCr, GST_VIDEO_FORMAT_YUY2} }; static gboolean @@ -2179,10 +2173,37 @@ accepted_color_formats (GstAmcCodecType * type, gboolean is_encoder) } GstVideoFormat -gst_amc_color_format_to_video_format (gint color_format) +gst_amc_color_format_to_video_format (const GstAmcCodecInfo * codec_info, + const gchar * mime, gint color_format) { gint i; + if (color_format == COLOR_FormatYCbYCr) { + if (strcmp (codec_info->name, "OMX.k3.video.decoder.avc") == 0) { + GST_INFO + ("OMX.k3.video.decoder.avc: COLOR_FormatYCbYCr is actually GST_VIDEO_FORMAT_NV12."); + return GST_VIDEO_FORMAT_NV12; + } + + /* FIXME COLOR_FormatYCbYCr doesn't work properly for OMX.k3.video.encoder.avc temporarily. */ + if (strcmp (codec_info->name, "OMX.k3.video.encoder.avc") == 0) { + GST_INFO + ("OMX.k3.video.encoder.avc: COLOR_FormatYCbYCr is not supported yet."); + return GST_VIDEO_FORMAT_UNKNOWN; + } + + /* FIXME COLOR_FormatYCbYCr is not supported in gst_amc_color_format_info_set yet, mask it. */ + return GST_VIDEO_FORMAT_UNKNOWN; + } + + if (color_format == COLOR_FormatYUV420SemiPlanar) { + if (strcmp (codec_info->name, "OMX.k3.video.encoder.avc") == 0) { + GST_INFO + ("OMX.k3.video.encoder.avc: COLOR_FormatYUV420SemiPlanar is actually GST_VIDEO_FORMAT_NV21."); + return GST_VIDEO_FORMAT_NV21; + } + } + for (i = 0; i < G_N_ELEMENTS (color_format_mapping_table); i++) { if (color_format_mapping_table[i].color_format == color_format) return color_format_mapping_table[i].video_format; @@ -2192,13 +2213,48 @@ gst_amc_color_format_to_video_format (gint color_format) } gint -gst_amc_video_format_to_color_format (GstVideoFormat video_format) +gst_amc_video_format_to_color_format (const GstAmcCodecInfo * codec_info, + const gchar * mime, GstVideoFormat video_format) { - gint i; + const GstAmcCodecType *codec_type = NULL; + gint i, j; + + for (i = 0; i < codec_info->n_supported_types; i++) { + if (strcmp (codec_info->supported_types[i].mime, mime) == 0) { + codec_type = &codec_info->supported_types[i]; + break; + } + } + + if (!codec_type) + return -1; + + if (video_format == GST_VIDEO_FORMAT_NV12) { + if (strcmp (codec_info->name, "OMX.k3.video.decoder.avc") == 0) { + GST_INFO + ("OMX.k3.video.decoder.avc: GST_VIDEO_FORMAT_NV12 is reported as COLOR_FormatYCbYCr."); + + return COLOR_FormatYCbYCr; + } + } + + if (video_format == GST_VIDEO_FORMAT_NV21) { + if (strcmp (codec_info->name, "OMX.k3.video.encoder.avc") == 0) { + GST_INFO + ("OMX.k3.video.encoder.avc: GST_VIDEO_FORMAT_NV21 is reported as COLOR_FormatYUV420SemiPlanar."); + + return COLOR_FormatYUV420SemiPlanar; + } + } for (i = 0; i < G_N_ELEMENTS (color_format_mapping_table); i++) { - if (color_format_mapping_table[i].video_format == video_format) - return color_format_mapping_table[i].color_format; + if (color_format_mapping_table[i].video_format == video_format) { + gint color_format = color_format_mapping_table[i].color_format; + + for (j = 0; j < codec_type->n_color_formats; j++) + if (color_format == codec_type->color_formats[j]) + return color_format; + } } return -1; @@ -2853,6 +2909,405 @@ plugin_init (GstPlugin * plugin) return TRUE; } +void +gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info, + GstCaps ** sink_caps, GstCaps ** src_caps) +{ + GstCaps *raw_ret = NULL, *encoded_ret = NULL; + gint i; + + if (codec_info->is_encoder) { + if (sink_caps) + *sink_caps = raw_ret = gst_caps_new_empty (); + + if (src_caps) + *src_caps = encoded_ret = gst_caps_new_empty (); + } else { + if (sink_caps) + *sink_caps = encoded_ret = gst_caps_new_empty (); + + if (src_caps) + *src_caps = raw_ret = gst_caps_new_empty (); + } + + for (i = 0; i < codec_info->n_supported_types; i++) { + const GstAmcCodecType *type = &codec_info->supported_types[i]; + GstStructure *tmp, *tmp2, *tmp3; + + if (g_str_has_prefix (type->mime, "audio/")) { + if (raw_ret) { + tmp = gst_structure_new ("audio/x-raw", + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "format", G_TYPE_STRING, GST_AUDIO_NE (S16), NULL); + + raw_ret = gst_caps_merge_structure (raw_ret, tmp); + } + + if (encoded_ret) { + if (strcmp (type->mime, "audio/mpeg") == 0) { + tmp = gst_structure_new ("audio/mpeg", + "mpegversion", G_TYPE_INT, 1, + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "parsed", G_TYPE_BOOLEAN, TRUE, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "audio/3gpp") == 0) { + tmp = gst_structure_new ("audio/AMR", + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "audio/amr-wb") == 0) { + tmp = gst_structure_new ("audio/AMR-WB", + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "audio/mp4a-latm") == 0) { + gint j; + gboolean have_profile = FALSE; + GValue va = { 0, }; + GValue v = { 0, }; + + g_value_init (&va, GST_TYPE_LIST); + g_value_init (&v, G_TYPE_STRING); + g_value_set_string (&v, "raw"); + gst_value_list_append_value (&va, &v); + g_value_set_string (&v, "adts"); + gst_value_list_append_value (&va, &v); + g_value_unset (&v); + + tmp = gst_structure_new ("audio/mpeg", + "mpegversion", G_TYPE_INT, 4, + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framed", G_TYPE_BOOLEAN, TRUE, NULL); + gst_structure_set_value (tmp, "stream-format", &va); + g_value_unset (&va); + + for (j = 0; j < type->n_profile_levels; j++) { + const gchar *profile; + + profile = + gst_amc_aac_profile_to_string (type->profile_levels[j].profile); + + if (!profile) { + GST_ERROR ("Unable to map AAC profile 0x%08x", + type->profile_levels[j].profile); + continue; + } + + tmp2 = gst_structure_copy (tmp); + gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp2); + + have_profile = TRUE; + } + + if (!have_profile) { + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else { + gst_structure_free (tmp); + } + } else if (strcmp (type->mime, "audio/g711-alaw") == 0) { + tmp = gst_structure_new ("audio/x-alaw", + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "audio/g711-mlaw") == 0) { + tmp = gst_structure_new ("audio/x-mulaw", + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "audio/vorbis") == 0) { + tmp = gst_structure_new ("audio/x-vorbis", + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "audio/flac") == 0) { + tmp = gst_structure_new ("audio/x-flac", + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framed", G_TYPE_BOOLEAN, TRUE, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "audio/mpeg-L2") == 0) { + tmp = gst_structure_new ("audio/mpeg", + "mpegversion", G_TYPE_INT, 1, + "layer", G_TYPE_INT, 2, + "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "parsed", G_TYPE_BOOLEAN, TRUE, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else { + GST_WARNING ("Unsupported mimetype '%s'", type->mime); + } + } + } else if (g_str_has_prefix (type->mime, "video/")) { + if (raw_ret) { + gint j; + + for (j = 0; j < type->n_color_formats; j++) { + GstVideoFormat format; + + format = + gst_amc_color_format_to_video_format (codec_info, + type->mime, type->color_formats[j]); + if (format == GST_VIDEO_FORMAT_UNKNOWN) { + GST_WARNING ("Unknown color format 0x%08x", type->color_formats[j]); + continue; + } + + tmp = gst_structure_new ("video/x-raw", + "format", G_TYPE_STRING, gst_video_format_to_string (format), + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + + raw_ret = gst_caps_merge_structure (raw_ret, tmp); + } + } + + if (encoded_ret) { + if (strcmp (type->mime, "video/mp4v-es") == 0) { + gint j; + gboolean have_profile_level = FALSE; + + tmp = gst_structure_new ("video/mpeg", + "width", GST_TYPE_INT_RANGE, 16, 4096, + "height", GST_TYPE_INT_RANGE, 16, 4096, + "framerate", GST_TYPE_FRACTION_RANGE, + 0, 1, G_MAXINT, 1, + "mpegversion", G_TYPE_INT, 4, + "systemstream", G_TYPE_BOOLEAN, FALSE, + "parsed", G_TYPE_BOOLEAN, TRUE, NULL); + + if (type->n_profile_levels) { + for (j = type->n_profile_levels - 1; j >= 0; j--) { + const gchar *profile; + + profile = + gst_amc_mpeg4_profile_to_string (type-> + profile_levels[j].profile); + if (!profile) { + GST_ERROR ("Unable to map MPEG4 profile 0x%08x", + type->profile_levels[j].profile); + continue; + } + + tmp2 = gst_structure_copy (tmp); + gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL); + + /* Don't put the level restrictions on the sinkpad caps for decoders, + * see 2b94641a4 */ + if (codec_info->is_encoder) { + const gchar *level; + gint k; + GValue va = { 0, }; + GValue v = { 0, }; + + g_value_init (&va, GST_TYPE_LIST); + g_value_init (&v, G_TYPE_STRING); + + 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); + } + + gst_structure_set_value (tmp2, "level", &va); + g_value_unset (&va); + g_value_unset (&v); + } + + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp2); + have_profile_level = TRUE; + } + } + + if (!have_profile_level) { + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else { + gst_structure_free (tmp); + } + + tmp = gst_structure_new ("video/x-divx", + "width", GST_TYPE_INT_RANGE, 16, 4096, + "height", GST_TYPE_INT_RANGE, 16, 4096, + "framerate", GST_TYPE_FRACTION_RANGE, + 0, 1, G_MAXINT, 1, + "divxversion", GST_TYPE_INT_RANGE, 3, 5, + "parsed", G_TYPE_BOOLEAN, TRUE, NULL); + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "video/3gpp") == 0) { + gint j; + gboolean have_profile_level = FALSE; + + tmp = gst_structure_new ("video/x-h263", + "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, + "variant", G_TYPE_STRING, "itu", NULL); + + if (type->n_profile_levels) { + for (j = type->n_profile_levels - 1; j >= 0; j--) { + gint profile; + + profile = + gst_amc_h263_profile_to_gst_id (type-> + profile_levels[j].profile); + + if (profile == -1) { + GST_ERROR ("Unable to map h263 profile 0x%08x", + type->profile_levels[j].profile); + continue; + } + + tmp2 = gst_structure_copy (tmp); + gst_structure_set (tmp2, "profile", G_TYPE_UINT, profile, NULL); + + if (codec_info->is_encoder) { + gint k; + gint level; + GValue va = { 0, }; + GValue v = { 0, }; + + g_value_init (&va, GST_TYPE_LIST); + g_value_init (&v, G_TYPE_UINT); + + 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); + } + + gst_structure_set_value (tmp2, "level", &va); + g_value_unset (&va); + g_value_unset (&v); + } + + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp2); + have_profile_level = TRUE; + } + } + + if (!have_profile_level) { + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else { + gst_structure_free (tmp); + } + } else if (strcmp (type->mime, "video/avc") == 0) { + gint j; + gboolean have_profile_level = FALSE; + + 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, + "stream-format", G_TYPE_STRING, "byte-stream", + "alignment", G_TYPE_STRING, "au", NULL); + + if (type->n_profile_levels) { + for (j = type->n_profile_levels - 1; j >= 0; j--) { + const gchar *profile, *alternative = NULL; + + profile = + 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; + } + + tmp2 = gst_structure_copy (tmp); + gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL); + + if (alternative) { + tmp3 = gst_structure_copy (tmp); + gst_structure_set (tmp3, "profile", G_TYPE_STRING, alternative, + NULL); + } else + tmp3 = NULL; + + if (codec_info->is_encoder) { + const gchar *level; + gint k; + GValue va = { 0, }; + GValue v = { 0, }; + + g_value_init (&va, GST_TYPE_LIST); + g_value_init (&v, G_TYPE_STRING); + 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); + } + + gst_structure_set_value (tmp2, "level", &va); + if (tmp3) + gst_structure_set_value (tmp3, "level", &va); + + g_value_unset (&va); + g_value_unset (&v); + } + + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp2); + if (tmp3) + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp3); + have_profile_level = TRUE; + } + } + + if (!have_profile_level) { + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else { + gst_structure_free (tmp); + } + } else if (strcmp (type->mime, "video/x-vnd.on2.vp8") == 0) { + tmp = gst_structure_new ("video/x-vp8", + "width", GST_TYPE_INT_RANGE, 16, 4096, + "height", GST_TYPE_INT_RANGE, 16, 4096, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else if (strcmp (type->mime, "video/mpeg2") == 0) { + tmp = gst_structure_new ("video/mpeg", + "width", GST_TYPE_INT_RANGE, 16, 4096, + "height", GST_TYPE_INT_RANGE, 16, 4096, + "framerate", GST_TYPE_FRACTION_RANGE, + 0, 1, G_MAXINT, 1, + "mpegversion", GST_TYPE_INT_RANGE, 1, 2, + "systemstream", G_TYPE_BOOLEAN, FALSE, + "parsed", G_TYPE_BOOLEAN, TRUE, NULL); + + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp); + } else { + GST_WARNING ("Unsupported mimetype '%s'", type->mime); + } + } + } + } +} + GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, androidmedia, diff --git a/sys/androidmedia/gstamc.h b/sys/androidmedia/gstamc.h index b48a3ee7cc..f109431745 100644 --- a/sys/androidmedia/gstamc.h +++ b/sys/androidmedia/gstamc.h @@ -119,8 +119,8 @@ void gst_amc_format_set_string (GstAmcFormat *format, const gchar *key, const gc gboolean gst_amc_format_get_buffer (GstAmcFormat *format, const gchar *key, guint8 **data, gsize *size); void gst_amc_format_set_buffer (GstAmcFormat *format, const gchar *key, guint8 *data, gsize size); -GstVideoFormat gst_amc_color_format_to_video_format (gint color_format); -gint gst_amc_video_format_to_color_format (GstVideoFormat video_format); +GstVideoFormat gst_amc_color_format_to_video_format (const GstAmcCodecInfo * codec_info, const gchar * mime, gint color_format); +gint gst_amc_video_format_to_color_format (const GstAmcCodecInfo * codec_info, const gchar * mime, GstVideoFormat video_format); const gchar * gst_amc_avc_profile_to_string (gint profile, const gchar **alternative); gint gst_amc_avc_profile_from_string (const gchar *profile); @@ -139,6 +139,8 @@ gint gst_amc_aac_profile_from_string (const gchar *profile); gboolean gst_amc_audio_channel_mask_to_positions (guint32 channel_mask, gint channels, GstAudioChannelPosition *pos); guint32 gst_amc_audio_channel_mask_from_positions (GstAudioChannelPosition *positions, gint channels); +void gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info, GstCaps **sink_caps, GstCaps **src_caps); + G_END_DECLS diff --git a/sys/androidmedia/gstamcaudiodec.c b/sys/androidmedia/gstamcaudiodec.c index f8649e8960..30751e11f6 100644 --- a/sys/androidmedia/gstamcaudiodec.c +++ b/sys/androidmedia/gstamcaudiodec.c @@ -106,134 +106,6 @@ gst_amc_audio_dec_get_type (void) return type; } -static GstCaps * -create_sink_caps (const GstAmcCodecInfo * codec_info) -{ - GstCaps *ret; - gint i; - - ret = gst_caps_new_empty (); - - for (i = 0; i < codec_info->n_supported_types; i++) { - const GstAmcCodecType *type = &codec_info->supported_types[i]; - - if (strcmp (type->mime, "audio/mpeg") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("audio/mpeg", - "mpegversion", G_TYPE_INT, 1, - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "audio/3gpp") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("audio/AMR", - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "audio/amr-wb") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("audio/AMR-WB", - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "audio/mp4a-latm") == 0) { - gint j; - GstStructure *tmp, *tmp2; - gboolean have_profile = FALSE; - GValue va = { 0, }; - GValue v = { 0, }; - - g_value_init (&va, GST_TYPE_LIST); - g_value_init (&v, G_TYPE_STRING); - g_value_set_string (&v, "raw"); - gst_value_list_append_value (&va, &v); - g_value_set_string (&v, "adts"); - gst_value_list_append_value (&va, &v); - g_value_unset (&v); - - tmp = gst_structure_new ("audio/mpeg", - "mpegversion", G_TYPE_INT, 4, - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "framed", G_TYPE_BOOLEAN, TRUE, NULL); - gst_structure_set_value (tmp, "stream-format", &va); - g_value_unset (&va); - - for (j = 0; j < type->n_profile_levels; j++) { - const gchar *profile; - - profile = - gst_amc_aac_profile_to_string (type->profile_levels[j].profile); - - if (!profile) { - GST_ERROR ("Unable to map AAC profile 0x%08x", - type->profile_levels[j].profile); - continue; - } - - tmp2 = gst_structure_copy (tmp); - gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL); - ret = gst_caps_merge_structure (ret, tmp2); - - have_profile = TRUE; - } - - if (!have_profile) { - ret = gst_caps_merge_structure (ret, tmp); - } else { - gst_structure_free (tmp); - } - } else if (strcmp (type->mime, "audio/g711-alaw") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("audio/x-alaw", - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "audio/g711-mlaw") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("audio/x-mulaw", - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "audio/vorbis") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("audio/x-vorbis", - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "audio/flac") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("audio/x-flac", - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "framed", G_TYPE_BOOLEAN, TRUE, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "audio/mpeg-L2") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("audio/mpeg", - "mpegversion", G_TYPE_INT, 1, - "layer", G_TYPE_INT, 2, - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else { - GST_WARNING ("Unsupported mimetype '%s'", type->mime); - } - } - - return ret; -} - static const gchar * caps_to_mime (GstCaps * caps) { @@ -277,19 +149,6 @@ caps_to_mime (GstCaps * caps) return NULL; } -static GstCaps * -create_src_caps (const GstAmcCodecInfo * codec_info) -{ - GstCaps *ret; - - ret = gst_caps_new_simple ("audio/x-raw", - "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "format", G_TYPE_STRING, GST_AUDIO_NE (S16), NULL); - - return ret; -} - static void gst_amc_audio_dec_base_init (gpointer g_class) { @@ -297,7 +156,7 @@ gst_amc_audio_dec_base_init (gpointer g_class) GstAmcAudioDecClass *amcaudiodec_class = GST_AMC_AUDIO_DEC_CLASS (g_class); const GstAmcCodecInfo *codec_info; GstPadTemplate *templ; - GstCaps *caps; + GstCaps *sink_caps, *src_caps; gchar *longname; codec_info = @@ -308,16 +167,16 @@ gst_amc_audio_dec_base_init (gpointer g_class) amcaudiodec_class->codec_info = codec_info; + gst_amc_codec_info_to_caps (codec_info, &sink_caps, &src_caps); /* Add pad templates */ - caps = create_sink_caps (codec_info); - templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps); + templ = + gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps); gst_element_class_add_pad_template (element_class, templ); - gst_caps_unref (caps); + gst_caps_unref (sink_caps); - caps = create_src_caps (codec_info); - templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps); + templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps); gst_element_class_add_pad_template (element_class, templ); - gst_caps_unref (caps); + gst_caps_unref (src_caps); longname = g_strdup_printf ("Android MediaCodec %s", codec_info->name); gst_element_class_set_metadata (element_class, diff --git a/sys/androidmedia/gstamcvideodec.c b/sys/androidmedia/gstamcvideodec.c index 00b237a594..721318048b 100644 --- a/sys/androidmedia/gstamcvideodec.c +++ b/sys/androidmedia/gstamcvideodec.c @@ -135,179 +135,6 @@ gst_amc_video_dec_get_type (void) return type; } -static GstCaps * -create_sink_caps (const GstAmcCodecInfo * codec_info) -{ - GstCaps *ret; - gint i; - - ret = gst_caps_new_empty (); - - for (i = 0; i < codec_info->n_supported_types; i++) { - const GstAmcCodecType *type = &codec_info->supported_types[i]; - - if (strcmp (type->mime, "video/mp4v-es") == 0) { - gint j; - GstStructure *tmp, *tmp2; - gboolean have_profile_level = FALSE; - - tmp = gst_structure_new ("video/mpeg", - "width", GST_TYPE_INT_RANGE, 16, 4096, - "height", GST_TYPE_INT_RANGE, 16, 4096, - "framerate", GST_TYPE_FRACTION_RANGE, - 0, 1, G_MAXINT, 1, - "mpegversion", G_TYPE_INT, 4, - "systemstream", G_TYPE_BOOLEAN, FALSE, - "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - - if (type->n_profile_levels) { - for (j = type->n_profile_levels - 1; j >= 0; j--) { - const gchar *profile; - - profile = - gst_amc_mpeg4_profile_to_string (type->profile_levels[j].profile); - if (!profile) { - GST_ERROR ("Unable to map MPEG4 profile 0x%08x", - type->profile_levels[j].profile); - continue; - } - - tmp2 = gst_structure_copy (tmp); - gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL); - ret = gst_caps_merge_structure (ret, tmp2); - have_profile_level = TRUE; - } - } - - if (!have_profile_level) { - ret = gst_caps_merge_structure (ret, tmp); - } else { - gst_structure_free (tmp); - } - - tmp = gst_structure_new ("video/x-divx", - "width", GST_TYPE_INT_RANGE, 16, 4096, - "height", GST_TYPE_INT_RANGE, 16, 4096, - "framerate", GST_TYPE_FRACTION_RANGE, - 0, 1, G_MAXINT, 1, - "divxversion", GST_TYPE_INT_RANGE, 3, 5, - "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "video/3gpp") == 0) { - gint j; - GstStructure *tmp, *tmp2; - gboolean have_profile_level = FALSE; - - tmp = gst_structure_new ("video/x-h263", - "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, - "variant", G_TYPE_STRING, "itu", NULL); - - if (type->n_profile_levels) { - for (j = type->n_profile_levels - 1; j >= 0; j--) { - gint profile; - - profile = - gst_amc_h263_profile_to_gst_id (type->profile_levels[j].profile); - - if (profile == -1) { - GST_ERROR ("Unable to map h263 profile 0x%08x", - type->profile_levels[j].profile); - continue; - } - - tmp2 = gst_structure_copy (tmp); - gst_structure_set (tmp2, "profile", G_TYPE_UINT, profile, NULL); - ret = gst_caps_merge_structure (ret, tmp2); - have_profile_level = TRUE; - } - } - - if (!have_profile_level) { - ret = gst_caps_merge_structure (ret, tmp); - } else { - gst_structure_free (tmp); - } - } else if (strcmp (type->mime, "video/avc") == 0) { - gint j; - GstStructure *tmp, *tmp2; - gboolean have_profile_level = FALSE; - - 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, - "stream-format", G_TYPE_STRING, "byte-stream", - "alignment", G_TYPE_STRING, "au", NULL); - - if (type->n_profile_levels) { - for (j = type->n_profile_levels - 1; j >= 0; j--) { - const gchar *profile, *alternative = NULL; - - profile = - 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; - } - - tmp2 = gst_structure_copy (tmp); - gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL); - ret = gst_caps_merge_structure (ret, tmp2); - - if (alternative) { - tmp2 = gst_structure_copy (tmp); - gst_structure_set (tmp2, "profile", G_TYPE_STRING, alternative, - NULL); - ret = gst_caps_merge_structure (ret, tmp2); - } - have_profile_level = TRUE; - } - } - - if (!have_profile_level) { - ret = gst_caps_merge_structure (ret, tmp); - } else { - gst_structure_free (tmp); - } - } else if (strcmp (type->mime, "video/x-vnd.on2.vp8") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("video/x-vp8", - "width", GST_TYPE_INT_RANGE, 16, 4096, - "height", GST_TYPE_INT_RANGE, 16, 4096, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "video/mpeg2") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("video/mpeg", - "width", GST_TYPE_INT_RANGE, 16, 4096, - "height", GST_TYPE_INT_RANGE, 16, 4096, - "framerate", GST_TYPE_FRACTION_RANGE, - 0, 1, G_MAXINT, 1, - "mpegversion", GST_TYPE_INT_RANGE, 1, 2, - "systemstream", G_TYPE_BOOLEAN, FALSE, - "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - - ret = gst_caps_merge_structure (ret, tmp); - } else { - GST_WARNING ("Unsupported mimetype '%s'", type->mime); - } - } - - return ret; -} - static const gchar * caps_to_mime (GstCaps * caps) { @@ -343,40 +170,6 @@ caps_to_mime (GstCaps * caps) return NULL; } -static GstCaps * -create_src_caps (const GstAmcCodecInfo * codec_info) -{ - GstCaps *ret; - gint i; - - ret = gst_caps_new_empty (); - - for (i = 0; i < codec_info->n_supported_types; i++) { - const GstAmcCodecType *type = &codec_info->supported_types[i]; - gint j; - - for (j = 0; j < type->n_color_formats; j++) { - GstVideoFormat format; - GstCaps *tmp; - - format = gst_amc_color_format_to_video_format (type->color_formats[j]); - if (format == GST_VIDEO_FORMAT_UNKNOWN) { - GST_WARNING ("Unknown color format 0x%08x", type->color_formats[j]); - continue; - } - - tmp = gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, gst_video_format_to_string (format), - "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - ret = gst_caps_merge (ret, tmp); - } - } - - return ret; -} - static void gst_amc_video_dec_base_init (gpointer g_class) { @@ -384,7 +177,7 @@ gst_amc_video_dec_base_init (gpointer g_class) GstAmcVideoDecClass *amcvideodec_class = GST_AMC_VIDEO_DEC_CLASS (g_class); const GstAmcCodecInfo *codec_info; GstPadTemplate *templ; - GstCaps *caps; + GstCaps *sink_caps, *src_caps; gchar *longname; codec_info = @@ -395,16 +188,16 @@ gst_amc_video_dec_base_init (gpointer g_class) amcvideodec_class->codec_info = codec_info; + gst_amc_codec_info_to_caps (codec_info, &sink_caps, &src_caps); /* Add pad templates */ - caps = create_sink_caps (codec_info); - templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps); + templ = + gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps); gst_element_class_add_pad_template (element_class, templ); - gst_caps_unref (caps); + gst_caps_unref (sink_caps); - caps = create_src_caps (codec_info); - templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps); + templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps); gst_element_class_add_pad_template (element_class, templ); - gst_caps_unref (caps); + gst_caps_unref (src_caps); longname = g_strdup_printf ("Android MediaCodec %s", codec_info->name); gst_element_class_set_metadata (element_class, @@ -648,6 +441,7 @@ static gboolean gst_amc_video_dec_set_src_caps (GstAmcVideoDec * self, GstAmcFormat * format) { GstVideoCodecState *output_state; + const gchar *mime; gint color_format, width, height; gint stride, slice_height; gint crop_left, crop_right; @@ -662,10 +456,6 @@ gst_amc_video_dec_set_src_caps (GstAmcVideoDec * self, GstAmcFormat * format) return FALSE; } - if (strcmp (klass->codec_info->name, "OMX.k3.video.decoder.avc") == 0 && - color_format == COLOR_FormatYCbYCr) - color_format = COLOR_TI_FormatYUV420PackedSemiPlanar; - if (!gst_amc_format_get_int (format, "stride", &stride) || !gst_amc_format_get_int (format, "slice-height", &slice_height)) { GST_ERROR_OBJECT (self, "Failed to get stride and slice-height"); @@ -695,7 +485,16 @@ gst_amc_video_dec_set_src_caps (GstAmcVideoDec * self, GstAmcFormat * format) if (crop_left) width = width - crop_left; - gst_format = gst_amc_color_format_to_video_format (color_format); + mime = caps_to_mime (self->input_state->caps); + if (!mime) { + GST_ERROR_OBJECT (self, "Failed to convert caps to mime"); + return FALSE; + } + + gst_format = + gst_amc_color_format_to_video_format (klass->codec_info, mime, + color_format); + if (gst_format == GST_VIDEO_FORMAT_UNKNOWN) { GST_ERROR_OBJECT (self, "Unknown color format 0x%08x", color_format); return FALSE; @@ -1148,7 +947,7 @@ retry: _find_nearest_frame (self, gst_util_uint64_scale (buffer_info.presentation_time_us, GST_USECOND, 1)); - is_eos = ! !(buffer_info.flags & BUFFER_FLAG_END_OF_STREAM); + is_eos = !!(buffer_info.flags & BUFFER_FLAG_END_OF_STREAM); if (frame && (deadline = diff --git a/sys/androidmedia/gstamcvideoenc.c b/sys/androidmedia/gstamcvideoenc.c index b54aa9cb22..f96ca4844b 100644 --- a/sys/androidmedia/gstamcvideoenc.c +++ b/sys/androidmedia/gstamcvideoenc.c @@ -135,294 +135,6 @@ gst_amc_video_enc_get_type (void) return type; } -static GstVideoFormat -color_format_to_video_format_hack (const GstAmcCodecInfo * codec_info, - gchar * mime, gint color_format) -{ - GstVideoFormat format; - format = gst_amc_color_format_to_video_format (color_format); - - if (format == GST_VIDEO_FORMAT_NV12) { - if (strcmp (codec_info->name, "OMX.k3.video.encoder.avc") == 0) { - GST_INFO - ("On HuaweiMediaPad, reported COLOR_FormatYUV420SemiPlanar is actually GST_VIDEO_FORMAT_NV21."); - format = GST_VIDEO_FORMAT_NV21; - } - } - - return format; -} - -static gint -video_format_to_color_format_hack (const GstAmcCodecInfo * codec_info, - gchar * mime, GstVideoFormat format) -{ - if (format == GST_VIDEO_FORMAT_NV21) { - if (strcmp (codec_info->name, "OMX.k3.video.encoder.avc") == 0) - format = GST_VIDEO_FORMAT_NV12; - } - - return gst_amc_video_format_to_color_format (format); -} - -static GstCaps * -create_src_caps (const GstAmcCodecInfo * codec_info) -{ - GstCaps *ret; - gint i; - - ret = gst_caps_new_empty (); - - for (i = 0; i < codec_info->n_supported_types; i++) { - const GstAmcCodecType *type = &codec_info->supported_types[i]; - - if (strcmp (type->mime, "video/mp4v-es") == 0) { - gint j; - GstStructure *tmp, *tmp2; - gboolean have_profile_level = FALSE; - - tmp = gst_structure_new ("video/mpeg", - "width", GST_TYPE_INT_RANGE, 16, 4096, - "height", GST_TYPE_INT_RANGE, 16, 4096, - "framerate", GST_TYPE_FRACTION_RANGE, - 0, 1, G_MAXINT, 1, - "mpegversion", G_TYPE_INT, 4, - "systemstream", G_TYPE_BOOLEAN, FALSE, - "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - - if (type->n_profile_levels) { - for (j = type->n_profile_levels - 1; j >= 0; 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); - 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, NULL); - gst_structure_set_value (tmp2, "level", &va); - g_value_unset (&va); - g_value_unset (&v); - ret = gst_caps_merge_structure (ret, tmp2); - have_profile_level = TRUE; - } - } - - if (!have_profile_level) { - ret = gst_caps_merge_structure (ret, tmp); - } else { - gst_structure_free (tmp); - } - } else if (strcmp (type->mime, "video/3gpp") == 0) { - gint j; - GstStructure *tmp, *tmp2; - gboolean have_profile_level = FALSE; - - tmp = gst_structure_new ("video/x-h263", - "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, - "variant", G_TYPE_STRING, "itu", NULL); - - if (type->n_profile_levels) { - for (j = type->n_profile_levels - 1; j >= 0; 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); - - 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, NULL); - gst_structure_set_value (tmp2, "level", &va); - g_value_unset (&va); - g_value_unset (&v); - ret = gst_caps_merge_structure (ret, tmp2); - have_profile_level = TRUE; - } - } - - if (!have_profile_level) { - ret = gst_caps_merge_structure (ret, tmp); - } else { - gst_structure_free (tmp); - } - } else if (strcmp (type->mime, "video/avc") == 0) { - gint j; - GstStructure *tmp, *tmp2; - gboolean have_profile_level = FALSE; - - 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, - "stream-format", G_TYPE_STRING, "byte-stream", - "alignment", G_TYPE_STRING, "au", NULL); - - if (type->n_profile_levels) { - for (j = type->n_profile_levels - 1; j >= 0; j--) { - 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, - &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, NULL); - gst_structure_set_value (tmp2, "level", &va); - if (!alternative) - g_value_unset (&va); - g_value_unset (&v); - ret = gst_caps_merge_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); - ret = gst_caps_merge_structure (ret, tmp2); - } - have_profile_level = TRUE; - } - } - - if (!have_profile_level) { - ret = gst_caps_merge_structure (ret, tmp); - } else { - gst_structure_free (tmp); - } - } else if (strcmp (type->mime, "video/x-vnd.on2.vp8") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("video/x-vp8", - "width", GST_TYPE_INT_RANGE, 16, 4096, - "height", GST_TYPE_INT_RANGE, 16, 4096, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - - ret = gst_caps_merge_structure (ret, tmp); - } else if (strcmp (type->mime, "video/mpeg2") == 0) { - GstStructure *tmp; - - tmp = gst_structure_new ("video/mpeg", - "width", GST_TYPE_INT_RANGE, 16, 4096, - "height", GST_TYPE_INT_RANGE, 16, 4096, - "framerate", GST_TYPE_FRACTION_RANGE, - 0, 1, G_MAXINT, 1, - "mpegversion", GST_TYPE_INT_RANGE, 1, 2, - "systemstream", G_TYPE_BOOLEAN, FALSE, - "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - - ret = gst_caps_merge_structure (ret, tmp); - } else { - GST_WARNING ("Unsupported mimetype '%s'", type->mime); - } - } - - return ret; -} - -static GstCaps * -create_sink_caps (const GstAmcCodecInfo * codec_info) -{ - GstCaps *ret; - gint i; - - ret = gst_caps_new_empty (); - - for (i = 0; i < codec_info->n_supported_types; i++) { - const GstAmcCodecType *type = &codec_info->supported_types[i]; - gint j; - - for (j = 0; j < type->n_color_formats; j++) { - GstVideoFormat format; - GstCaps *tmp; - - format = - color_format_to_video_format_hack (codec_info, type->mime, - type->color_formats[j]); - if (format == GST_VIDEO_FORMAT_UNKNOWN) { - GST_WARNING ("Unknown color format 0x%08x", type->color_formats[j]); - continue; - } - - tmp = gst_caps_new_simple ("video/x-raw", - "format", G_TYPE_STRING, gst_video_format_to_string (format), - "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - ret = gst_caps_merge (ret, tmp); - } - } - - return ret; -} - static GstAmcFormat * create_amc_format (GstAmcVideoEnc * encoder, GstVideoCodecState * input_state, GstCaps * src_caps) @@ -509,8 +221,8 @@ create_amc_format (GstAmcVideoEnc * encoder, GstVideoCodecState * input_state, } color_format = - video_format_to_color_format_hack (klass->codec_info, (gchar *) mime, - info->finfo->format); + gst_amc_video_format_to_color_format (klass->codec_info, + mime, info->finfo->format); if (color_format == -1) goto video_format_failed_to_convert; @@ -700,7 +412,7 @@ gst_amc_video_enc_base_init (gpointer g_class) GstAmcVideoEncClass *videoenc_class = GST_AMC_VIDEO_ENC_CLASS (g_class); const GstAmcCodecInfo *codec_info; GstPadTemplate *templ; - GstCaps *caps; + GstCaps *sink_caps, *src_caps; gchar *longname; codec_info = @@ -711,16 +423,16 @@ gst_amc_video_enc_base_init (gpointer g_class) videoenc_class->codec_info = codec_info; + gst_amc_codec_info_to_caps (codec_info, &sink_caps, &src_caps); /* Add pad templates */ - caps = create_sink_caps (codec_info); - templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps); + templ = + gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sink_caps); gst_element_class_add_pad_template (element_class, templ); - gst_caps_unref (caps); + gst_caps_unref (sink_caps); - caps = create_src_caps (codec_info); - templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps); + templ = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, src_caps); gst_element_class_add_pad_template (element_class, templ); - gst_caps_unref (caps); + gst_caps_unref (src_caps); longname = g_strdup_printf ("Android MediaCodec %s", codec_info->name); gst_element_class_set_metadata (element_class,