mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
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.
This commit is contained in:
parent
f348944246
commit
557d6b974f
5 changed files with 507 additions and 680 deletions
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue