From: Hyuntae Kim Date: Tue, 14 Apr 2020 04:53:29 +0000 (+0900) Subject: enable opus encoder X-Git-Tag: submit/tizen/20200422.081514^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b5e55dfce714159160554e31c7a867ee3b3fc0fe;p=platform%2Fcore%2Fapi%2Fmediacodec.git enable opus encoder Change-Id: I140b4a6df22aed2af7ab65d64a2f58e8e9b7d9d9 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index f2b7204..d39a089 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(INC_DIR include) INCLUDE_DIRECTORIES(${INC_DIR}) -SET(dependents "dlog glib-2.0 mm-common libtbm capi-media-tool iniparser gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 capi-system-info gstreamer-allocators-1.0") +SET(dependents "dlog glib-2.0 mm-common libtbm capi-media-tool iniparser gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 gstreamer-pbutils-1.0 gstreamer-tag-1.0 capi-system-info gstreamer-allocators-1.0") SET(pc_dependents "capi-base-common capi-media-tool") IF(TIZEN_FEATURE_MM_RESOURCE_MANAGER) SET(dependents "${dependents} mm-resource-manager") diff --git a/include/media_codec_port.h b/include/media_codec_port.h index 986bdd3..b34afa9 100644 --- a/include/media_codec_port.h +++ b/include/media_codec_port.h @@ -104,6 +104,7 @@ typedef enum { WMAV2, WMAPRO, WMALSL, + OPUS, H261, H263, H264, diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 548d4c6..3da38ba 100644 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -4,7 +4,7 @@ Name: capi-media-codec Summary: A Media Codec library in Tizen Native API -Version: 0.6.11 +Version: 0.6.12 Release: 0 Group: Multimedia/API License: Apache-2.0 @@ -19,6 +19,8 @@ BuildRequires: pkgconfig(libtbm) BuildRequires: pkgconfig(gstreamer-1.0) BuildRequires: pkgconfig(gstreamer-plugins-base-1.0) BuildRequires: pkgconfig(gstreamer-app-1.0) +BuildRequires: pkgconfig(gstreamer-pbutils-1.0) +BuildRequires: pkgconfig(gstreamer-tag-1.0) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(iniparser) %if "%{tizen_profile_name}" != "tv" @@ -28,6 +30,7 @@ BuildRequires: pkgconfig(mm-resource-manager) #BuildRequires: pkgconfig(capi-mediademuxer) #BuildRequires: pkgconfig(capi-mediamuxer) + %description A Media Codec library in Tizen Native API diff --git a/src/media_codec_ini.c b/src/media_codec_ini.c index ce51083..35bc0b0 100644 --- a/src/media_codec_ini.c +++ b/src/media_codec_ini.c @@ -71,6 +71,7 @@ static codec_list_t general_codec_list[] = { {"wmav1", MEDIACODEC_WMAV1}, {"wmav2", MEDIACODEC_WMAV2}, {"wmapro", MEDIACODEC_WMAPRO}, + {"opus", MEDIACODEC_OPUS}, }; /* internal functions, macros here */ @@ -287,6 +288,9 @@ media_format_mimetype_e _mc_convert_media_format_str_to_int(char *sformat) } else if (!strcmp(sformat, "WMAPRO")) { iformat = MEDIA_FORMAT_WMAPRO; goto endf; + } else if (!strcmp(sformat, "OPUS")) { + iformat = MEDIA_FORMAT_OPUS; + goto endf; } endf: diff --git a/src/media_codec_port.c b/src/media_codec_port.c index d78a1d4..70b5cc3 100644 --- a/src/media_codec_port.c +++ b/src/media_codec_port.c @@ -399,7 +399,7 @@ int mc_prepare(MMHandleType mediacodec) break; case MEDIACODEC_PORT_TYPE_GST: - mc_gst_prepare(mc_handle); + ret = mc_gst_prepare(mc_handle); break; default: @@ -1047,6 +1047,8 @@ codec_type_e codec_type_to_simple_enumeration(mediacodec_codec_type_e media_code return VP9; case MEDIACODEC_VC1: return VC1; + case MEDIACODEC_OPUS: + return OPUS; default: return NONE; } @@ -1111,6 +1113,8 @@ mediacodec_codec_type_e simple_to_codec_type_enumeration(codec_type_e codec_id) return MEDIACODEC_VP9; case VC1: return MEDIACODEC_VC1; + case OPUS: + return MEDIACODEC_OPUS; default: return NONE; } @@ -1178,6 +1182,11 @@ gboolean _check_support_audio_info(mediacodec_codec_type_e codec_id, int sampler s_bit_depth = 32; /* NOTE: avdec_flac surpports S32LE as format */ break; } + case MEDIACODEC_OPUS: + { + s_bit_depth = 16; /* NOTE: opusenc/ opusdec support S16LE as format according to opus specification*/ + break; + } default: break; } diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index bd2cf50..5f2078f 100644 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include /* * Internal Implementation @@ -37,7 +39,7 @@ static media_packet_h _mc_get_input_buffer(mc_gst_core_t *core); static gboolean __mc_gst_init_gstreamer(); static int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, media_format_mimetype_e out_mime); -static mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, gchar *factory_name); +static mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name); static mc_ret_e _mc_gst_destroy_pipeline(mc_gst_core_t *core); static void __mc_gst_buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data); static int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data); @@ -172,6 +174,9 @@ int(*adec_flac_vtable[])() = {&__mc_fill_input_buffer_with_packet, int(*adec_wma_vtable[])() = {&__mc_fill_input_buffer_with_packet, /* WMA Decoder Vtable */ &__mc_fill_packet_with_output_buffer}; +int(*aenc_opus_vtable[])() = {&__mc_fill_input_buffer_with_packet, /* Opus Encoder Vtable */ + &__mc_fill_aenc_packet_with_output_buffer}; + #define MEDIACODEC_ELEMENT_SET_STATE(x_element, x_state) \ do { \ LOGD("setting state [%s:%d] to [%s]\n", #x_state, x_state, GST_ELEMENT_NAME(x_element)); \ @@ -238,12 +243,13 @@ static int __mc_fill_input_buffer_with_packet(mc_gst_core_t *core, media_packet_ return MC_ERROR; } - if (buf_data != NULL) { - gst_buffer_append_memory(mcbuffer->buffer, - gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0, - buf_size, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb)); - LOGD("packet data apended"); - } + if (buf_data == NULL) + return MC_ERROR; + + gst_buffer_append_memory(mcbuffer->buffer, + gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0, + buf_size, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb)); + LOGD("packet data apended"); return ret; } @@ -616,6 +622,9 @@ static int __mc_fill_aenc_packet_with_output_buffer(mc_gst_core_t *core, void *d s = gst_caps_get_structure(peercaps, 0); codec_data = gst_structure_get_value(s, "codec_data"); + if (codec_data == NULL && gst_structure_has_field(s, "streamheader")) + codec_data = gst_structure_get_value(s, "streamheader"); + core->codec_data = GST_BUFFER(g_value_dup_boxed(codec_data)); gst_caps_unref(peercaps); } @@ -817,6 +826,31 @@ int __mc_set_caps_streamheader(mc_gst_core_t *core, GstMCBuffer *mcbuffer, guint __mc_gst_caps_set_buffer_array(core->caps, "streamheader", header1, header2, NULL); gst_buffer_unref(header1); gst_buffer_unref(header2); + } else if (core->codec_id == MEDIACODEC_OPUS) { + const GstTagList *tags; + GstTagList *empty_tags = NULL; + GstBuffer *header, *comments; + guint8 *decoding_channel_mapping = NULL; + mc_gst_port_def_t *port_def = &core->ports[in_port_index]->port_def; + + header = gst_codec_utils_opus_create_header(port_def->info.audio.samplerate, + port_def->info.audio.channel, + 0, /* channel mapping family */ + 1, /* stream count */ + 0, /* coupled count */ + decoding_channel_mapping, + 0, /* FIXME: look ahead configured value */ + 0); + tags = gst_tag_setter_get_tag_list(GST_TAG_SETTER(core->codec)); + if (!tags) + tags = empty_tags = gst_tag_list_new_empty(); + comments = gst_tag_list_to_vorbiscomment_buffer(tags, (const guint8 *) "OpusTags", + 8, "Encoded with GStreamer opusenc"); + core->caps = gst_codec_utils_opus_create_caps_from_header(header, comments); + if (empty_tags) + gst_tag_list_unref(empty_tags); + gst_buffer_unref(header); + gst_buffer_unref(comments); } else { LOGE("Not support case of Stream header Caps"); } @@ -1143,6 +1177,7 @@ static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool c break; case MEDIACODEC_VORBIS: case MEDIACODEC_FLAC: + case MEDIACODEC_OPUS: if (codec_config) { ret = __mc_set_caps_streamheader(core, mcbuffer, VORBIS_CODECDATA_SIZE); if (ret != MC_ERROR_NONE) @@ -1449,6 +1484,16 @@ GstCaps *_mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec NULL); } break; + case MEDIACODEC_OPUS: + if (core->encoder) { + gst_caps_set_simple(caps, + "format", G_TYPE_STRING, _mc_bit_to_string(port_def->info.audio.bit_depth), + "layout", G_TYPE_STRING, "interleaved", NULL); + } else { + LOGD("[MC_NOT_SUPPORTED] opus decoder is not supported yet!!!"); + return NULL; + } + break; default: break; } @@ -1502,7 +1547,7 @@ GstCaps *_mc_gst_vid_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec LOGE("format : %s", port_def->info.video.format); } else { gst_caps_set_simple(caps, - "parsed", G_TYPE_BOOLEAN, TRUE, /* FIXME different from sw */ + "parsed", G_TYPE_BOOLEAN, TRUE, /* FIXME different from sw */ "alignment", G_TYPE_STRING, "au", "stream-format", G_TYPE_STRING, "byte-stream", "framerate", GST_TYPE_FRACTION, 30, 1, @@ -1524,11 +1569,10 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo switch (id) { case MEDIACODEC_AAC: - if (encoder) { + if (encoder) core->vtable = aenc_aac_vtable; - } else { + else core->vtable = adec_aac_vtable; - } break; case MEDIACODEC_AAC_HE: case MEDIACODEC_AAC_HE_PS: @@ -1549,11 +1593,10 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo break; case MEDIACODEC_AMR_NB: LOGD("amrnb vtable"); - if (encoder) { + if (encoder) core->vtable = aenc_amrnb_vtable; - } else { + else core->vtable = adec_amrnb_vtable; - } break; case MEDIACODEC_AMR_WB: LOGD("amrwb vtable - Only support decoder"); @@ -1566,12 +1609,10 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo break; case MEDIACODEC_VORBIS: LOGD("vorbis vtable"); - if (encoder) { - LOGD("[MC_NOT_SUPPORTED] vorbis encoder is not supported yet!!!"); + if (encoder) return MC_NOT_SUPPORTED; - } else { + else core->vtable = adec_vorbis_vtable; - } break; case MEDIACODEC_FLAC: LOGD("flac vtable"); @@ -1582,6 +1623,13 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo core->vtable = adec_flac_vtable; } break; + case MEDIACODEC_OPUS: + LOGD("opus vtable"); + if (encoder) + core->vtable = aenc_opus_vtable; + else + core->vtable = adec_vtable; + break; case MEDIACODEC_WMAV1: case MEDIACODEC_WMAV2: case MEDIACODEC_WMAPRO: @@ -1599,31 +1647,28 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo if (encoder) { core->vtable = is_hw ? venc_h263_hw_vtable : venc_h263_sw_vtable; } else { - if (is_hw) { + if (is_hw) core->vtable = vdec_h263_hw_vtable; - } else { + else core->vtable = vdec_h263_sw_vtable; - } } break; case MEDIACODEC_MPEG4: LOGD("mpeg4 vtable"); - if (encoder) { + if (encoder) core->vtable = is_hw ? venc_mpeg4_hw_vtable : venc_mpeg4_sw_vtable; - } else { + else core->vtable = is_hw ? vdec_mpeg4_hw_vtable : vdec_mpeg4_sw_vtable; - } break; case MEDIACODEC_H264: LOGD("h264 vtable"); if (encoder) { core->vtable = is_hw ? venc_h264_hw_vtable : venc_vtable; } else { - if (is_hw) { + if (is_hw) core->vtable = vdec_h264_hw_vtable; - } else { + else core->vtable = vdec_h264_sw_vtable; - } } break; default: @@ -2017,7 +2062,7 @@ ERROR: return FALSE; } -mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, gchar *factory_name) +mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, const gchar *factory_name) { GstBus *bus = NULL; @@ -2703,6 +2748,11 @@ static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_ mcbuffer = (GstMCBuffer *)g_malloc0(sizeof(GstMCBuffer)); + if (mcbuffer == NULL) { + LOGE("malloc fail"); + return NULL; + } + mcbuffer->buffer = gst_buffer_new(); mcbuffer->buf_size = 0; @@ -3355,8 +3405,14 @@ int _mc_get_mime(mc_gst_core_t *core) case MEDIACODEC_AMR_WB: mime = MEDIA_FORMAT_AMR_WB; break; + case MEDIACODEC_OPUS: + if (core->encoder) + mime = MEDIA_FORMAT_OPUS; + else + mime = MEDIA_FORMAT_PCM_S16LE; + break; default: - LOGE("NOT SUPPORTED!!!!"); + LOGE("NOT SUPPORTED!!!! 0x%x ", core->codec_id); break; } return mime; diff --git a/test/media_codec_test.c b/test/media_codec_test.c index dc46195..bab3988 100644 --- a/test/media_codec_test.c +++ b/test/media_codec_test.c @@ -47,6 +47,7 @@ #define ADTS_HEADER_SIZE 7 #define AMRNB_PCM_INPUT_SIZE 320 #define AMRWB_PCM_INPUT_SIZE 640 +#define OPUS_PCM_INPUT_SIZE 4096 #define CHECK_BIT(x, y) (((x) >> (y)) & 0x01) #define GET_IS_ENCODER(x) CHECK_BIT(x, 0) @@ -568,6 +569,22 @@ void amrenc_extractor(App *app, guint8 **data, int *size, gboolean *have_frame, app->offset += *size; } +void opusenc_extractor(App *app, guint8 **data, int *size, gboolean *have_frame, gboolean *codec_data) +{ + gint read_size = OPUS_PCM_INPUT_SIZE; + gint offset = app->length - app->offset; + + *have_frame = TRUE; + *data = app->data + app->offset; + + if (read_size >= offset) + *size = offset; + else + *size = read_size; + + app->offset += *size; +} + /** * Extract Input data for AAC decoder * (case of (LC profile) ADTS format) @@ -816,6 +833,18 @@ int _configure(App *app, int codecid, int flag, gboolean *hardware, media_forma mime = MEDIA_FORMAT_AMR_WB; } break; + case MEDIACODEC_OPUS: + if (encoder) { + extractor = opusenc_extractor; + mime = MEDIA_FORMAT_OPUS; /* FIXME need to check according to verdor */ + *codec_mime = MEDIA_FORMAT_OPUS; + app->is_amr_nb = FALSE; + } else { + mime = MEDIA_FORMAT_OPUS; + *codec_mime = MEDIA_FORMAT_OPUS; + } + break; + default: LOGE("NOT SUPPORTED!!!!"); break; @@ -1438,6 +1467,7 @@ void _mediacodec_prepare(App *app, gboolean frame_all) media_format_set_audio_channel(fmt, app->channel); media_format_set_audio_samplerate(fmt, app->samplerate); media_format_set_audio_bit(fmt, app->bit); + media_format_set_audio_avg_bps(fmt, app->bitrate); media_format_create(&codec_format); media_format_set_audio_mime(codec_format, codec_mime); @@ -2003,17 +2033,18 @@ void displaymenu(void) g_print(" WMAV2 = 13\n"); g_print(" WMAPRO = 14\n"); g_print(" WMALSL = 15\n"); + g_print(" OPUS = 16\n"); g_print(" -------------------\n"); - g_print(" H261 = 16\n"); - g_print(" H263 = 17\n"); - g_print(" H264 = 18\n"); - g_print(" MJPEG = 19\n"); - g_print(" MPEG1 = 20\n"); - g_print(" MPEG2 = 21\n"); - g_print(" MPEG4 = 22\n"); - g_print(" HEVC = 23\n"); - g_print(" VP8 = 24\n"); - g_print(" VP9 = 25\n"); + g_print(" H261 = 17\n"); + g_print(" H263 = 18\n"); + g_print(" H264 = 19\n"); + g_print(" MJPEG = 20\n"); + g_print(" MPEG1 = 21\n"); + g_print(" MPEG2 = 22\n"); + g_print(" MPEG4 = 23\n"); + g_print(" HEVC = 24\n"); + g_print(" VP8 = 25\n"); + g_print(" VP9 = 26\n"); g_print(" -------------------\n"); g_print("*** Flags : Select Combination Number (e.g. DEOCDER + TYPE_SW = 10)\n"); g_print(" CODEC : ENCODER = 1 DECODER = 2\n"); @@ -2063,9 +2094,12 @@ void interpret(char *cmd) break; case CURRENT_STATUS_SET_CODEC: { - gint ids[] = { 0x1010, 0x1020, 0x1030, 0x1040, 0x1041, 0x1050, 0x1060, 0x1061, 0x1062, - 0x1070, 0x1080, 0x1090, 0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x2010, 0x2020, - 0x2030, 0x2040, 0x2050, 0x2060, 0x2070, 0x2080, 0x2090, 0x20A0, 0x20B0 }; + gint ids[] = { 0x1010, 0x1020, 0x1030, 0x1040, 0x1041, + 0x1050, 0x1060, 0x1061, 0x1062, 0x1070, + 0x1080, 0x1090, 0x10A0, 0x10A1, 0x10A2, + 0x10A3, 0x10D0, 0x2010, 0x2020, 0x2030, + 0x2040, 0x2050, 0x2060, 0x2070, 0x2080, + 0x2090, 0x20A0, 0x20B0 }; if (cnt == 0) { gint n_sizes = G_N_ELEMENTS(ids); @@ -2488,6 +2522,8 @@ const char* codec_type_to_string(mediacodec_codec_type_e media_codec_id) return "VP9"; case MEDIACODEC_VC1: return "VC1"; + case MEDIACODEC_OPUS: + return "OPUS"; default: return "NONE"; }