From 3e1528f1fb41ae538e789a37c3b4689395b24bdc Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 27 May 2022 05:15:13 +1000 Subject: [PATCH] amc: Add H.265 encoder mapping. Add mime type mapping to enable the use of Android H.265 encoders Part-of: --- .../sys/androidmedia/gstamc-constants.h | 3 +- .../gst-plugins-bad/sys/androidmedia/gstamc.c | 36 +++++----- .../sys/androidmedia/gstamcvideoenc.c | 67 ++++++++++++++++--- .../sys/androidmedia/gstamcvideoenc.h | 4 ++ 4 files changed, 85 insertions(+), 25 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/androidmedia/gstamc-constants.h b/subprojects/gst-plugins-bad/sys/androidmedia/gstamc-constants.h index cc43f61512..6166b34588 100644 --- a/subprojects/gst-plugins-bad/sys/androidmedia/gstamc-constants.h +++ b/subprojects/gst-plugins-bad/sys/androidmedia/gstamc-constants.h @@ -148,7 +148,8 @@ enum HEVCHighTierLevel6 = 0x200000, HEVCMainTierLevel61 = 0x400000, HEVCHighTierLevel61 = 0x800000, - HEVCMainTierLevel62 = 0x1000000 + HEVCMainTierLevel62 = 0x1000000, + HEVCHighTierLevel62 = 0x2000000 }; enum diff --git a/subprojects/gst-plugins-bad/sys/androidmedia/gstamc.c b/subprojects/gst-plugins-bad/sys/androidmedia/gstamc.c index 527446a5fa..b858d51e9d 100644 --- a/subprojects/gst-plugins-bad/sys/androidmedia/gstamc.c +++ b/subprojects/gst-plugins-bad/sys/androidmedia/gstamc.c @@ -1141,7 +1141,8 @@ static const struct HEVCHighTierLevel51, "high", "5.1"}, { HEVCHighTierLevel52, "high", "5.2"}, { HEVCHighTierLevel6, "high", "6"}, { - HEVCHighTierLevel61, "high", "6.1"} + HEVCHighTierLevel61, "high", "6.1"}, { + HEVCHighTierLevel62, "high", "6.2"} }; const gchar * @@ -2334,35 +2335,40 @@ gst_amc_codec_info_to_caps (const GstAmcCodecInfo * codec_info, tmp2 = gst_structure_copy (tmp); gst_structure_set (tmp2, "profile", G_TYPE_STRING, profile, NULL); - /* FIXME: Implement tier/level support here */ -#if 0 if (codec_info->is_encoder) { const gchar *level, *tier; 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_hevc_tier_level_to_string (k, &tier); - if (!level) + if (!level || !tier) continue; - g_value_set_string (&v, level); - gst_value_list_append_value (&va, &v); + tmp3 = gst_structure_copy (tmp2); + + g_value_set_string (&v, tier); + gst_structure_set_value (tmp3, "tier", &v); g_value_reset (&v); + + g_value_set_string (&v, level); + gst_structure_set_value (tmp3, "level", &v); + g_value_reset (&v); + + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp3); + + have_profile_level = TRUE; } - - gst_structure_set_value (tmp2, "level", &va); - - g_value_unset (&va); - g_value_unset (&v); } -#endif - encoded_ret = gst_caps_merge_structure (encoded_ret, tmp2); + if (have_profile_level) { + gst_structure_free (tmp2); + } else { + encoded_ret = gst_caps_merge_structure (encoded_ret, tmp2); + } + have_profile_level = TRUE; } } diff --git a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.c b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.c index 591ca35de0..e777aa46fe 100644 --- a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.c +++ b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.c @@ -213,6 +213,21 @@ create_amc_format (GstAmcVideoEnc * encoder, GstVideoCodecState * input_state, amc_level.key = "level"; /* named level ? */ amc_level.id = gst_amc_avc_level_from_string (level_string); } + } else if (strcmp (name, "video/x-h265") == 0) { + const gchar *tier_string = gst_structure_get_string (s, "tier"); + + mime = "video/hevc"; + + if (profile_string) { + amc_profile.key = "profile"; /* named profile ? */ + amc_profile.id = gst_amc_hevc_profile_from_string (profile_string); + } + + if (level_string && tier_string) { + amc_level.key = "level"; /* named level ? */ + amc_level.id = + gst_amc_hevc_tier_level_from_string (tier_string, level_string); + } } else if (strcmp (name, "video/x-vp8") == 0) { mime = "video/x-vnd.on2.vp8"; } else if (strcmp (name, "video/x-vp9") == 0) { @@ -414,6 +429,32 @@ caps_from_amc_format (GstAmcFormat * amc_format) gst_caps_set_simple (caps, "level", G_TYPE_STRING, level_string, NULL); } + } else if (strcmp (mime, "video/hevc") == 0) { + const gchar *profile_string, *level_string, *tier_string; + + caps = + gst_caps_new_simple ("video/x-h265", + "stream-format", G_TYPE_STRING, "byte-stream", NULL); + + if (gst_amc_format_get_int (amc_format, "profile", &amc_profile, NULL)) { + profile_string = gst_amc_avc_profile_to_string (amc_profile, NULL); + if (!profile_string) + goto unsupported_profile; + + gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile_string, + NULL); + } + + if (gst_amc_format_get_int (amc_format, "level", &amc_level, NULL)) { + level_string = + gst_amc_hevc_tier_level_to_string (amc_profile, &tier_string); + if (!level_string || !tier_string) + goto unsupported_level; + + gst_caps_set_simple (caps, + "level", G_TYPE_STRING, level_string, + "tier", G_TYPE_STRING, tier_string, NULL); + } } else if (strcmp (mime, "video/x-vnd.on2.vp8") == 0) { caps = gst_caps_new_empty_simple ("video/x-vp8"); } else if (strcmp (mime, "video/x-vnd.on2.vp9") == 0) { @@ -847,6 +888,7 @@ gst_amc_video_enc_set_src_caps (GstAmcVideoEnc * self, GstAmcFormat * format) { GstCaps *caps; GstVideoCodecState *output_state; + GstStructure *s; caps = caps_from_amc_format (format); if (!caps) { @@ -871,6 +913,17 @@ gst_amc_video_enc_set_src_caps (GstAmcVideoEnc * self, GstAmcFormat * format) if (!gst_video_encoder_negotiate (GST_VIDEO_ENCODER (self))) return FALSE; + output_state = gst_video_encoder_get_output_state (GST_VIDEO_ENCODER (self)); + s = gst_caps_get_structure (output_state->caps, 0); + + if (!strcmp (gst_structure_get_name (s), "video/x-h264") || + !strcmp (gst_structure_get_name (s), "video/x-h265")) { + self->codec_data_in_bytestream = TRUE; + } else { + self->codec_data_in_bytestream = FALSE; + } + gst_video_codec_state_unref (output_state); + return TRUE; } @@ -906,14 +959,8 @@ gst_amc_video_enc_handle_output_frame (GstAmcVideoEnc * self, * gstomxvideoenc.c and gstomxh264enc.c */ if ((buffer_info->flags & BUFFER_FLAG_CODEC_CONFIG) && buffer_info->size > 0) { - GstStructure *s; - GstVideoCodecState *state; - - state = gst_video_encoder_get_output_state (encoder); - s = gst_caps_get_structure (state->caps, 0); - if (!strcmp (gst_structure_get_name (s), "video/x-h264")) { - gst_video_codec_state_unref (state); + if (self->codec_data_in_bytestream) { if (buffer_info->size > 4 && GST_READ_UINT32_BE (buf->data + buffer_info->offset) == 0x00000001) { GList *l = NULL; @@ -933,14 +980,16 @@ gst_amc_video_enc_handle_output_frame (GstAmcVideoEnc * self, } } else { GstBuffer *codec_data; + GstVideoCodecState *output_state = + gst_video_encoder_get_output_state (GST_VIDEO_ENCODER (self)); GST_DEBUG_OBJECT (self, "Handling codec data"); codec_data = gst_buffer_new_and_alloc (buffer_info->size); gst_buffer_fill (codec_data, 0, buf->data + buffer_info->offset, buffer_info->size); - state->codec_data = codec_data; - gst_video_codec_state_unref (state); + output_state->codec_data = codec_data; + gst_video_codec_state_unref (output_state); if (!gst_video_encoder_negotiate (encoder)) { gst_video_codec_frame_unref (frame); diff --git a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.h b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.h index e72ac56304..6965bce1a9 100644 --- a/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.h +++ b/subprojects/gst-plugins-bad/sys/androidmedia/gstamcvideoenc.h @@ -56,6 +56,10 @@ struct _GstAmcVideoEnc GstAmcCodec *codec; GstAmcFormat *amc_format; + /* Set to TRUE if codec headers should be placed + * in the stream, or FALSE if they go in the headers */ + gboolean codec_data_in_bytestream; + GstVideoCodecState *input_state; /* Input format of the codec */