summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorChen Jie <chenj@lemote.com>2013-10-08 21:11:48 +0800
committerSebastian Dröge <sebastian@centricular.com>2014-05-26 16:29:01 +0200
commit557d6b974fe98d09ddd0a500548b8a13211dab1c (patch)
tree83dc387d86e4c41070f7c7d0c7163b8d6d4d7bd2 /sys
parentf3489442468f0c1be747a0b26cde24aa4a39d4aa (diff)
downloadgstreamer-plugins-bad-557d6b974fe98d09ddd0a500548b8a13211dab1c.tar.gz
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.
Diffstat (limited to 'sys')
-rw-r--r--sys/androidmedia/gstamc.c481
-rw-r--r--sys/androidmedia/gstamc.h6
-rw-r--r--sys/androidmedia/gstamcaudiodec.c155
-rw-r--r--sys/androidmedia/gstamcvideodec.c239
-rw-r--r--sys/androidmedia/gstamcvideoenc.c306
5 files changed, 507 insertions, 680 deletions
diff --git a/sys/androidmedia/gstamc.c b/sys/androidmedia/gstamc.c
index 326ae1e15..e6f3d5f2d 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 b48a3ee7c..f10943174 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 f8649e896..30751e11f 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 00b237a59..721318048 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 b54aa9cb2..f96ca4844 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,