From 12969757c2d1c63c3fce7a663402841cfe6d1092 Mon Sep 17 00:00:00 2001 From: Sejun Park Date: Mon, 26 Mar 2018 14:39:08 +0900 Subject: [PATCH 01/16] fixed svace issues Change-Id: I8c76d1e63d51b7c5a14edd737b06be4b23668e8e --- src/media_codec_port_gst.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index c787b0c..771e632 100644 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -1669,7 +1669,8 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) LOGD("factory name : %s, output_fmt : %x", factory_name, out_mime); /* create media_packet for output fmt */ - if ((ret = _mc_output_media_packet_new(new_core, video, encoder, out_mime)) != MC_ERROR_NONE) { + ret = _mc_output_media_packet_new(new_core, video, encoder, out_mime); + if (ret != MC_ERROR_NONE) { LOGE("Failed to create output pakcet"); return ret; } @@ -1686,13 +1687,15 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) mc_handle->core = new_core; /* create basic core elements */ - if ((ret = _mc_gst_create_pipeline(mc_handle->core, factory_name) != MC_ERROR_NONE)) { + ret = _mc_gst_create_pipeline(mc_handle->core, factory_name); + if (ret != MC_ERROR_NONE) { LOGE("failed to create pipeline"); return ret; } /* link vtable */ - if ((ret = _mc_link_vtable(mc_handle->core, id, encoder, hardware)) != MC_ERROR_NONE) { + ret = _mc_link_vtable(mc_handle->core, id, encoder, hardware); + if (ret != MC_ERROR_NONE) { LOGE("vtable link failed"); return ret; } -- 2.7.4 From 673705926faaf5a3abd1aefc7f47d890220a50ff Mon Sep 17 00:00:00 2001 From: Sejun Park Date: Fri, 23 Mar 2018 10:05:12 +0900 Subject: [PATCH 02/16] Add audioresample for supporting various samplerates Change-Id: Ic41c21a21cf5ea621b047917ac5b2045712d1a4c --- include/media_codec_port.h | 55 +-- include/media_codec_port_gst.h | 29 +- src/media_codec_port.c | 52 +-- src/media_codec_port_gst.c | 740 +++++++++++++++++++++++------------------ test/media_codec_test.c | 156 ++++----- 5 files changed, 546 insertions(+), 486 deletions(-) mode change 100644 => 100755 include/media_codec_port_gst.h diff --git a/include/media_codec_port.h b/include/media_codec_port.h index f1c3fca..f2a732c 100644 --- a/include/media_codec_port.h +++ b/include/media_codec_port.h @@ -163,41 +163,21 @@ typedef enum _mc_codec_port_type_e { CODEC_PORT_TYPE_MAX, } mc_codec_port_type_e; -typedef enum _mc_vendor_e { - MC_VENDOR_DEFAULT, - MC_VENDOR_SLSI_SEC, - MC_VENDOR_SLSI_EXYNOS, - MC_VENDOR_QCT, - MC_VENDOR_SPRD -} mc_vendor_e; - -struct _mc_decoder_info_t { - int width; - int height; - int actwidth; - int actheight; - - int samplerate; - int channel; - int bit; -}; - -struct _mc_encoder_info_t { - int width; - int height; - int bitrate; - int format; - int fps; - int qp_min; - int qp_max; - int vbvbuffer_size; - int level; - int profile; - - int samplerate; - int channel; - int bit; -}; +typedef struct mc_audio_port_definition_t { + gint samplerate; + gint channel; + gint bit_depth; + gint bitrate; +} mc_audio_port_definition_t; + +typedef struct mc_video_port_definition_t { + gchar *format; + gint width; + gint height; + gint stride; + gint bitrate; + gint framerate; +} mc_video_port_definition_t; /* Codec Private data */ struct _mc_handle_t { @@ -209,14 +189,13 @@ struct _mc_handle_t { mediacodec_port_type_e port_type; mediacodec_codec_type_e codec_id; - mc_vendor_e vendor; void *ports[2]; void *core; union { - mc_decoder_info_t decoder; - mc_encoder_info_t encoder; + mc_audio_port_definition_t audio; + mc_video_port_definition_t video; } info; /* for process done cb */ diff --git a/include/media_codec_port_gst.h b/include/media_codec_port_gst.h old mode 100644 new mode 100755 index 4373b7b..4d9198f --- a/include/media_codec_port_gst.h +++ b/include/media_codec_port_gst.h @@ -59,17 +59,26 @@ extern "C" { #define THRESHOLD_QNUM 5 /* gst port layer */ +typedef struct _mc_gst_port_def_t mc_gst_port_def_t; typedef struct _mc_gst_port_t mc_gst_port_t; typedef struct _mc_gst_core_t mc_gst_core_t; typedef struct _GstMCBuffer GstMCBuffer; -typedef struct _ion_mmu_data_t ion_mmu_data_t; + typedef enum { - BUF_SHARE_METHOD_PADDR = 0, - BUF_SHARE_METHOD_FD, - BUF_SHARE_METHOD_TIZEN_BUFFER, - BUF_SHARE_METHOD_FLUSH_BUFFER -} buf_share_method_t; + in_port_index = 0, + out_port_index +} port_index_e; + + +struct _mc_gst_port_def_t { + gchar *mime_type; + media_format_mimetype_e coding_type; + union { + mc_audio_port_definition_t audio; + mc_video_port_definition_t video; + } info; +}; struct _mc_gst_port_t { mc_gst_core_t *core; @@ -77,19 +86,21 @@ struct _mc_gst_port_t { guint buffer_size; guint index; gboolean is_allocated; - media_packet_h *buffers; GQueue *queue; GMutex mutex; GCond buffer_cond; + mc_gst_port_def_t port_def; }; struct _mc_gst_core_t { gint(**vtable)(); const gchar *mime; - gchar *format; GstElement *pipeline; GstElement *appsrc; GstElement *audioconvert; + GstElement *audioresample; + GstElement *videoscale; + GstElement *videoconvert; GstElement *capsfilter; GstElement *parser; GstElement *fakesink; @@ -137,8 +148,8 @@ struct _mc_gst_core_t { mc_aqueue_t *available_queue; GQueue *output_queue; - void *codec_info; GstBuffer *codec_data; + GstCaps* (*mc_caps_new)(mc_gst_core_t *, mediacodec_codec_type_e, gint); void* user_cb[_MEDIACODEC_EVENT_TYPE_NUM]; void* user_data[_MEDIACODEC_EVENT_TYPE_NUM]; diff --git a/src/media_codec_port.c b/src/media_codec_port.c index 3584dd5..cf6843a 100644 --- a/src/media_codec_port.c +++ b/src/media_codec_port.c @@ -174,8 +174,8 @@ int mc_set_vdec_info(MMHandleType mediacodec, int width, int height) MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && !mc_handle->is_encoder, MC_INVALID_ARG, "MEDIACODEC_ERROR_INVALID_PARAMETER"); - mc_handle->info.decoder.width = width; - mc_handle->info.decoder.height = height; + mc_handle->info.video.width = width; + mc_handle->info.video.height = height; mc_handle->is_prepared = true; @@ -198,10 +198,10 @@ int mc_set_venc_info(MMHandleType mediacodec, int width, int height, int fps, in MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && mc_handle->is_encoder, MC_INVALID_ARG, "MEDIACODEC_ERROR_INVALID_PARAMETER"); - mc_handle->info.encoder.width = width; - mc_handle->info.encoder.height = height; - mc_handle->info.encoder.fps = fps; - mc_handle->info.encoder.bitrate = target_bits * 1000; + mc_handle->info.video.width = width; + mc_handle->info.video.height = height; + mc_handle->info.video.framerate = fps; + mc_handle->info.video.bitrate = target_bits * 1000; mc_handle->is_prepared = true; return ret; @@ -223,9 +223,9 @@ int mc_set_adec_info(MMHandleType mediacodec, int samplerate, int channel, int b MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && !mc_handle->is_encoder, MC_INVALID_ARG, "MEDIACODEC_ERROR_INVALID_PARAMETER"); - mc_handle->info.decoder.samplerate = samplerate; - mc_handle->info.decoder.channel = channel; - mc_handle->info.decoder.bit = bit; + mc_handle->info.audio.samplerate = samplerate; + mc_handle->info.audio.channel = channel; + mc_handle->info.audio.bit_depth = bit; mc_handle->is_prepared = true; return ret; @@ -247,10 +247,10 @@ int mc_set_aenc_info(MMHandleType mediacodec, int samplerate, int channel, int b MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && mc_handle->is_encoder, MC_INVALID_ARG, "MEDIACODEC_ERROR_INVALID_PARAMETER"); - mc_handle->info.encoder.samplerate = samplerate; - mc_handle->info.encoder.channel = channel; - mc_handle->info.encoder.bit = bit; - mc_handle->info.encoder.bitrate = bitrate * 1000; + mc_handle->info.audio.samplerate = samplerate; + mc_handle->info.audio.channel = channel; + mc_handle->info.audio.bit_depth = bit; + mc_handle->info.audio.bitrate = bitrate * 1000; mc_handle->is_prepared = true; @@ -294,19 +294,19 @@ int mc_configure(MMHandleType mediacodec, media_format_h format, int flags) return MC_PARAM_ERROR; } - mc_handle->info.encoder.samplerate = samplerate; - mc_handle->info.encoder.channel = channel; - mc_handle->info.encoder.bit = bit; - mc_handle->info.encoder.bitrate = bitrate * 1000; + mc_handle->info.audio.samplerate = samplerate; + mc_handle->info.audio.channel = channel; + mc_handle->info.audio.bit_depth = bit; + mc_handle->info.audio.bitrate = bitrate * 1000; } else if (GET_IS_DECODER(flags)) { if ((samplerate <= 0) || (channel <= 0) || (bit <= 0)) { LOGE("invalid pram is set : samplerate : %d, channel : %d, bit : %d", samplerate, channel, bit); return MC_PARAM_ERROR; } - mc_handle->info.decoder.samplerate = samplerate; - mc_handle->info.decoder.channel = channel; - mc_handle->info.decoder.bit = bit; + mc_handle->info.audio.samplerate = samplerate; + mc_handle->info.audio.channel = channel; + mc_handle->info.audio.bit_depth = bit; } else { LOGE("either an encoder or a decoder must be set"); return MC_PARAM_ERROR; @@ -322,10 +322,10 @@ int mc_configure(MMHandleType mediacodec, media_format_h format, int flags) return MC_PARAM_ERROR; } - mc_handle->info.encoder.width = width; - mc_handle->info.encoder.height = height; - mc_handle->info.encoder.fps = fps; - mc_handle->info.encoder.bitrate = bitrate * 1000; + mc_handle->info.video.width = width; + mc_handle->info.video.height = height; + mc_handle->info.video.framerate = fps; + mc_handle->info.video.bitrate = bitrate * 1000; } else if (GET_IS_DECODER(flags)) { if ((width <= 0) || (height <= 0)) { LOGE("invalid pram is set : width : %d, height : %d", @@ -333,8 +333,8 @@ int mc_configure(MMHandleType mediacodec, media_format_h format, int flags) return MC_PARAM_ERROR; } - mc_handle->info.decoder.width = width; - mc_handle->info.decoder.height = height; + mc_handle->info.video.width = width; + mc_handle->info.video.height = height; } else { LOGE("either an encoder or a decoder must be set"); return MC_PARAM_ERROR; diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index 771e632..6d32a7b 100644 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -41,11 +41,10 @@ static mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, 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); -static int _mc_gst_update_caps(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool codec_config); -static gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h fmt); +static gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h format); static GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet_h packet, bool codec_config); static int _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *mcbuffer); -static gchar *__mc_get_gst_input_format(media_packet_h packet, bool is_hw); +static gchar *__mc_get_gst_input_format(media_format_mimetype_e mimetype, bool is_hw); static GstMCBuffer *__mc_gst_make_media_packet(mc_gst_core_t *core, GstBuffer *buffer); static gboolean __mc_gst_bus_callback(GstBus *bus, GstMessage *msg, gpointer data); static GstBusSyncReply __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data); @@ -82,6 +81,9 @@ static void __csc_tiled_to_linear_crop(unsigned char *yuv420_dest, static void _mc_send_eos_signal(mc_gst_core_t *core); static void _mc_wait_for_eos(mc_gst_core_t *core); static int _mc_get_mime(mc_gst_core_t *core); +static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer); +GstCaps *_mc_gst_vid_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index); +GstCaps *_mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index); /* video vtable */ int(*vdec_vtable[])() = {&__mc_fill_input_buffer_with_packet, &__mc_fill_packet_with_output_buffer}; @@ -287,10 +289,10 @@ int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h uint32_t plane_num; guint8 *planes[2]; - mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; + mc_gst_port_def_t *port_def = &core->ports[in_port_index]->port_def; - width = enc_info->width; - height = enc_info->height; + width = port_def->info.video.width; + height = port_def->info.video.height; ret = media_packet_get_number_of_video_planes(packet, &plane_num); if (ret != MEDIA_PACKET_ERROR_NONE) { @@ -402,11 +404,11 @@ int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, in g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + mc_gst_port_def_t *port_def = &core->ports[out_port_index]->port_def; if (!core->is_hw) { - width = dec_info->width; - height = dec_info->height; + width = port_def->info.video.width; + height = port_def->info.video.height; stride_width = GST_ROUND_UP_4(width); stride_height = height; buf_size = stride_width * stride_height * 3 / 2; @@ -419,8 +421,8 @@ int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, in return MC_ERROR; } - tsurf_info.width = dec_info->width; - tsurf_info.height = dec_info->height; + tsurf_info.width = port_def->info.video.width; + tsurf_info.height = port_def->info.video.height; tsurf_info.format = TBM_FORMAT_YVU420; tsurf_info.bpp = tbm_surface_internal_get_bpp(TBM_FORMAT_YVU420); tsurf_info.num_planes = tbm_surface_internal_get_num_planes(TBM_FORMAT_YVU420); @@ -463,8 +465,8 @@ int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, in } if (bo_num > 0) { - tsurf_info.width = dec_info->width; - tsurf_info.height = dec_info->height; + tsurf_info.width = port_def->info.video.width; + tsurf_info.height = port_def->info.video.height; tsurf_info.format = TBM_FORMAT_NV12; /* bo_format */ tsurf_info.bpp = tbm_surface_internal_get_bpp(TBM_FORMAT_NV12); tsurf_info.num_planes = tbm_surface_internal_get_num_planes(TBM_FORMAT_NV12); @@ -542,13 +544,13 @@ int __mc_fill_venc_packet_with_output_buffer(mc_gst_core_t *core, void *data, in g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - switch (core->out_mime) { + switch (core->ports[out_port_index]->port_def.coding_type) { case MEDIA_FORMAT_H264_SP: case MEDIA_FORMAT_H264_MP: case MEDIA_FORMAT_H264_HP: data_size = _mc_check_h264_bytestream((unsigned char *)data, size, 1, &codec_config, &sync_flag, &slice); - if (data_size <= 0) { + if (data_size < 0) { LOGE("No valid SPS/PPS ..."); return MC_INVALID_IN_BUF; } @@ -904,41 +906,36 @@ int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, m LOGE("media format create failed"); return MC_ERROR; } + mc_gst_port_def_t *port_def = &core->ports[out_port_index]->port_def; if (encoder) { - mc_encoder_info_t *info; - - info = (mc_encoder_info_t *)core->codec_info; if (video) { media_format_set_video_mime(core->output_fmt, out_mime); - media_format_set_video_width(core->output_fmt, info->width); - media_format_set_video_height(core->output_fmt, info->height); - media_format_set_video_avg_bps(core->output_fmt, info->bitrate); + media_format_set_video_width(core->output_fmt, port_def->info.video.width); + media_format_set_video_height(core->output_fmt, port_def->info.video.height); + media_format_set_video_avg_bps(core->output_fmt, port_def->info.video.bitrate); } else { int support_bit = 0; support_bit = _mc_get_support_bit_from_format(out_mime); media_format_set_audio_mime(core->output_fmt, out_mime); - media_format_set_audio_channel(core->output_fmt, info->channel); - media_format_set_audio_samplerate(core->output_fmt, info->samplerate); + media_format_set_audio_channel(core->output_fmt, port_def->info.audio.channel); + media_format_set_audio_samplerate(core->output_fmt, port_def->info.audio.samplerate); media_format_set_audio_bit(core->output_fmt, support_bit); - media_format_set_audio_avg_bps(core->output_fmt, info->bitrate); + media_format_set_audio_avg_bps(core->output_fmt, port_def->info.audio.bitrate); } } else { - mc_decoder_info_t *info; - - info = (mc_decoder_info_t *)core->codec_info; if (video) { media_format_set_video_mime(core->output_fmt, out_mime); - media_format_set_video_width(core->output_fmt, info->width); - media_format_set_video_height(core->output_fmt, info->height); + media_format_set_video_width(core->output_fmt, port_def->info.video.width); + media_format_set_video_height(core->output_fmt, port_def->info.video.height); } else { media_format_set_audio_mime(core->output_fmt, out_mime); - media_format_set_audio_channel(core->output_fmt, info->channel); - media_format_set_audio_samplerate(core->output_fmt, info->samplerate); - media_format_set_audio_bit(core->output_fmt, info->bit); + media_format_set_audio_channel(core->output_fmt, port_def->info.audio.channel); + media_format_set_audio_samplerate(core->output_fmt, port_def->info.audio.samplerate); + media_format_set_audio_bit(core->output_fmt, port_def->info.audio.bit_depth); } } return MC_ERROR_NONE; @@ -956,7 +953,8 @@ mc_gst_core_t *mc_gst_core_new() core = g_new0(mc_gst_core_t, 1); /* 0 : input, 1 : output */ - core->ports[0] = NULL; + core->ports[0] = mc_gst_port_new(core); + core->ports[0]->index = 0; core->ports[1] = mc_gst_port_new(core); core->ports[1]->index = 1; @@ -1018,6 +1016,11 @@ void mc_gst_core_free(mc_gst_core_t *core) if (core->codec_data) gst_buffer_unref(core->codec_data); + if (core->ports[0] != NULL) { + mc_gst_port_free(core->ports[0]); + core->ports[0] = NULL; + } + if (core->ports[1] != NULL) { mc_gst_port_free(core->ports[1]); core->ports[1] = NULL; @@ -1043,7 +1046,6 @@ mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core) port->num_buffers = -1; port->buffer_size = 0; port->is_allocated = 0; - port->buffers = NULL; g_mutex_init(&port->mutex); port->queue = g_queue_new(); @@ -1069,33 +1071,43 @@ void mc_gst_port_free(mc_gst_port_t *port) return; } -gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h fmt) +gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h format) { - gboolean is_updated = FALSE; + gboolean is_format_change = FALSE; - mc_decoder_info_t *codec_info = (mc_decoder_info_t *)core->codec_info; + mc_gst_port_def_t *input_port_def = &core->ports[in_port_index]->port_def; if (core->video) { gint width = 0; gint height = 0; gint bitrate = 0; + gint framerate = 0; + gchar *sformat = NULL; + media_format_mimetype_e mimetype = 0; - media_format_get_video_info(fmt, NULL, &width, &height, &bitrate, NULL); + media_format_get_video_info(format, &mimetype, &width, &height, &bitrate, NULL); + media_format_get_video_frame_rate(format, &framerate); - if ((codec_info->width != width) || (codec_info->height != height)) { - LOGD("Resolution changed : %dx%d -> %dx%d", codec_info->width, codec_info->height, width, height); - codec_info->width = width; - codec_info->height = height; - is_updated = TRUE; + is_format_change |= input_port_def->info.video.width != width; + is_format_change |= input_port_def->info.video.height != height; + is_format_change |= (input_port_def->info.video.framerate != framerate) && (framerate != 0); + if (is_format_change) { + LOGD("Format changed : resolution %dx%d -> %dx%d, framerate %d -> %d", + input_port_def->info.video.width, input_port_def->info.video.height, width, height, + input_port_def->info.video.framerate, framerate); + input_port_def->info.video.width = width; + input_port_def->info.video.height = height; } if (core->encoder) { - mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; - - if (bitrate != 0 && enc_info->bitrate != bitrate * 1000) { - LOGD("Bitrate changed : %d -> %d", enc_info->bitrate, bitrate); - enc_info->bitrate = bitrate * 1000; - is_updated = TRUE; + sformat = __mc_get_gst_input_format(mimetype, core->is_hw); + is_format_change |= input_port_def->info.video.bitrate != bitrate * 1000; + is_format_change |= g_strcmp0(input_port_def->info.video.format, sformat); + if (is_format_change) { + LOGD("Bitrate changed : %d -> %d", input_port_def->info.video.bitrate, bitrate); + LOGD("Format changed : %s -> %s", input_port_def->info.video.format, sformat); + input_port_def->info.video.bitrate = bitrate * 1000; + input_port_def->info.video.format = g_strdup(sformat); } } } else { @@ -1104,31 +1116,34 @@ gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h fmt) gint bit; gint bitrate; - media_format_get_audio_info(fmt, NULL, &channel, &samplerate, &bit, &bitrate); + media_format_get_audio_info(format, NULL, &channel, &samplerate, &bit, &bitrate); - if ((codec_info->channel != channel) || (codec_info->samplerate != samplerate) || (codec_info->bit != bit)) { - LOGD("Audio info. changed : %d -> %d, %d -> %d, %d -> %d", codec_info->channel, channel, codec_info->samplerate, samplerate, codec_info->bit, bit); - codec_info->channel = channel; - codec_info->samplerate = samplerate; - codec_info->bit = bit; - is_updated = TRUE; + is_format_change |= input_port_def->info.audio.channel != channel; + is_format_change |= input_port_def->info.audio.samplerate != samplerate; + is_format_change |= input_port_def->info.audio.bit_depth != bit; + if (is_format_change) { + LOGD("Audio info. changed : %d -> %d, %d -> %d, %d -> %d", + input_port_def->info.audio.channel, channel, + input_port_def->info.audio.samplerate, samplerate, + input_port_def->info.audio.bit_depth, bit); + input_port_def->info.audio.channel = channel; + input_port_def->info.audio.samplerate = samplerate; + input_port_def->info.audio.bit_depth = bit; } if (core->encoder) { - mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; - - if (bitrate != 0 && enc_info->bitrate != bitrate * 1000) { - LOGD("Bitrate changed : %d -> %d", enc_info->bitrate, bitrate); - enc_info->bitrate = bitrate * 1000; - is_updated = TRUE; + is_format_change |= input_port_def->info.audio.bitrate != bitrate * 1000; + if (is_format_change) { + LOGD("Bitrate changed : %d -> %d", input_port_def->info.audio.bitrate, bitrate); + input_port_def->info.audio.bitrate = bitrate * 1000; } } } - return is_updated; + return is_format_change; } -static int _mc_gst_update_caps(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool codec_config) +static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer) { MEDIACODEC_FENTER(); @@ -1137,88 +1152,43 @@ static int _mc_gst_update_caps(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool int ret = MC_ERROR_NONE; - if (core->video) { - if (core->encoder) { - mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; - - core->format = __mc_get_gst_input_format(mcbuffer->packet, core->is_hw); - gst_caps_set_simple(core->caps, - "format", G_TYPE_STRING, core->format, - "width", G_TYPE_INT, enc_info->width, - "height", G_TYPE_INT, enc_info->height, - "framerate", GST_TYPE_FRACTION, enc_info->fps, 1, - NULL); - - if (g_object_class_find_property(G_OBJECT_GET_CLASS(core->codec), "bitrate")) - g_object_set(GST_OBJECT(core->codec), "bitrate", enc_info->bitrate, NULL); - else - g_object_set(GST_OBJECT(core->codec), "target-bitrate", enc_info->bitrate, NULL); - LOGD("set bitrate = %d.", enc_info->bitrate); - } else { - mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; - - gst_caps_set_simple(core->caps, - "width", G_TYPE_INT, dec_info->width, - "height", G_TYPE_INT, dec_info->height, - NULL); - - ret = __mc_set_caps_codecdata(core, mcbuffer, CODECDATA_NOT_USE); - if (ret != MC_ERROR_NONE) - LOGW("__mc_set_caps_codecdata failed"); - } - } else { - if (core->encoder) { - mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; - - gst_caps_set_simple(core->caps, - "format", G_TYPE_STRING, _mc_bit_to_string(enc_info->bit), - "rate", G_TYPE_INT, enc_info->samplerate, - "channels", G_TYPE_INT, enc_info->channel, - NULL); - g_object_set(GST_OBJECT(core->codec), "bitrate", enc_info->bitrate, NULL); - } else { - mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; - - gst_caps_set_simple(core->caps, - "rate", G_TYPE_INT, dec_info->samplerate, - "channels", G_TYPE_INT, dec_info->channel, - NULL); - - if (codec_config) { - switch (core->codec_id) { - case MEDIACODEC_AAC: - case MEDIACODEC_AAC_HE: - case MEDIACODEC_AAC_HE_PS: - ret = __mc_set_caps_codecdata(core, mcbuffer, AAC_CODECDATA_SIZE); - if (ret != MC_ERROR_NONE) - LOGW("__mc_set_caps_codecdata failed"); - break; - case MEDIACODEC_WMAV1: - case MEDIACODEC_WMAV2: - case MEDIACODEC_WMAPRO: - case MEDIACODEC_WMALSL: - ret = __mc_set_caps_codecdata(core, mcbuffer, WMA_CODECDATA_SIZE); - if (ret != MC_ERROR_NONE) - LOGW("__mc_set_caps_codecdata failed"); - break; - case MEDIACODEC_VORBIS: - case MEDIACODEC_FLAC: - ret = __mc_set_caps_streamheader(core, mcbuffer, VORBIS_CODECDATA_SIZE); - if (ret != MC_ERROR_NONE) - LOGW("__mc_set_caps_streamheader failed"); - break; - default: - LOGD("doesn't need to set codecdata"); - break; - - } - } - } + switch (core->codec_id) { + case MEDIACODEC_AAC: + case MEDIACODEC_AAC_HE: + case MEDIACODEC_AAC_HE_PS: + ret = __mc_set_caps_codecdata(core, mcbuffer, AAC_CODECDATA_SIZE); + if (ret != MC_ERROR_NONE) + LOGW("__mc_set_caps_codecdata failed"); + break; + case MEDIACODEC_WMAV1: + case MEDIACODEC_WMAV2: + case MEDIACODEC_WMAPRO: + case MEDIACODEC_WMALSL: + ret = __mc_set_caps_codecdata(core, mcbuffer, WMA_CODECDATA_SIZE); + if (ret != MC_ERROR_NONE) + LOGW("__mc_set_caps_codecdata failed"); + break; + case MEDIACODEC_VORBIS: + case MEDIACODEC_FLAC: + ret = __mc_set_caps_streamheader(core, mcbuffer, VORBIS_CODECDATA_SIZE); + if (ret != MC_ERROR_NONE) + LOGW("__mc_set_caps_streamheader failed"); + break; + case MEDIACODEC_H264: + case MEDIACODEC_MPEG4: + ret = __mc_set_caps_codecdata(core, mcbuffer, CODECDATA_NOT_USE); + if (ret != MC_ERROR_NONE) + LOGW("__mc_set_caps_codecdata failed"); + break; + default: + LOGD("doesn't need to set codecdata"); + break; } - g_object_set(core->appsrc, "caps", core->caps, NULL); MEDIACODEC_FLEAVE(); return ret; + + } static gpointer feed_task(gpointer data) @@ -1227,8 +1197,9 @@ static gpointer feed_task(gpointer data) bool codec_config = FALSE; bool eos = FALSE; bool initiative = TRUE; - media_format_h fmt = NULL; - media_packet_h in_buf = NULL; + bool is_format_change = FALSE; + media_format_h format = NULL; + media_packet_h input_buffer = NULL; GstMCBuffer *mcbuffer = NULL; MEDIACODEC_FENTER(); @@ -1237,23 +1208,23 @@ static gpointer feed_task(gpointer data) while (g_atomic_int_get(&core->available_queue->running)) { LOGD("waiting for next input...."); - in_buf = _mc_get_input_buffer(core); - if (!in_buf) + input_buffer = _mc_get_input_buffer(core); + if (!input_buffer) goto LEAVE; - media_packet_get_format(in_buf, &fmt); - if (fmt) { - if (_mc_update_packet_info(core, fmt)) - initiative = TRUE; - media_format_unref(fmt); + media_packet_get_format(input_buffer, &format); + if (format) { + if (_mc_update_packet_info(core, format)) + is_format_change = TRUE; + media_format_unref(format); } - if (media_packet_is_codec_config(in_buf, &codec_config) != MEDIA_PACKET_ERROR_NONE) { + if (media_packet_is_codec_config(input_buffer, &codec_config) != MEDIA_PACKET_ERROR_NONE) { LOGE("media_packet_is_codec_config failed"); goto ERROR; } - if (media_packet_is_end_of_stream(in_buf, &eos) != MEDIA_PACKET_ERROR_NONE) { + if (media_packet_is_end_of_stream(input_buffer, &eos) != MEDIA_PACKET_ERROR_NONE) { LOGE("media_packet_is_end_of_stream failed"); goto ERROR; } @@ -1265,41 +1236,43 @@ static gpointer feed_task(gpointer data) LOGD("end of stream"); gst_app_src_end_of_stream(GST_APP_SRC(core->appsrc)); _mc_wait_for_eos(core); - initiative = true; + initiative = TRUE; - _mc_gst_handle_input_buffer_used(core, in_buf); + _mc_gst_handle_input_buffer_used(core, input_buffer); goto LEAVE; } - mcbuffer = _mc_gst_media_packet_to_gstbuffer(core, in_buf, codec_config); + mcbuffer = _mc_gst_media_packet_to_gstbuffer(core, input_buffer, codec_config); if (!mcbuffer) { LOGW("gstbuffer can't make"); goto ERROR; } - /* mcbuffer took the ownership of the in_buf, so set in_buf to NULL to aviod double unref */ - in_buf = NULL; + /* mcbuffer took the ownership of the input_buffer, so set input_buffer to NULL to aviod double unref */ + input_buffer = NULL; - if (codec_config) - initiative = TRUE; - - if (initiative) { + if (codec_config || initiative) { GstPad *pad; - - ret = _mc_gst_update_caps(core, mcbuffer, codec_config); + ret = _mc_set_codec_data(core, mcbuffer); if (ret != MC_ERROR_NONE) { - LOGE("failed to update caps"); - /* unref mcbuff->buffer will invoke the finalize() of GstMcBuffer */ + LOGE("failed to set codec data"); gst_buffer_unref(mcbuffer->buffer); goto ERROR; } - pad = gst_element_get_static_pad(core->appsrc, "src"); gst_pad_push_event(pad, gst_event_new_stream_start("start")); gst_object_unref(pad); + initiative = FALSE; + } + if (is_format_change) { + GstCaps *caps; + caps = core->mc_caps_new(core, core->codec_id, in_port_index); + g_object_set(core->appsrc, "caps", caps, NULL); + gst_caps_unref(caps); LOGD("caps updated"); } + /* inject buffer */ ret = _mc_gst_gstbuffer_to_appsrc(core, mcbuffer); if (ret != GST_FLOW_OK) { @@ -1307,12 +1280,10 @@ static gpointer feed_task(gpointer data) goto ERROR; } - initiative = false; - continue; ERROR: - if (in_buf) - _mc_gst_handle_input_buffer_used(core, in_buf); + if (input_buffer) + _mc_gst_handle_input_buffer_used(core, input_buffer); _mc_gst_set_flush_input(core); @@ -1323,13 +1294,13 @@ ERROR: continue; LEAVE: - /*LOGE("status : in_buf : %p, codec_config : %d, eos : %d, encoder : %d in feed_task", in_buf, codec_config, eos, core->encoder);*/ + /*LOGE("status : input_buffer : %p, codec_config : %d, eos : %d, encoder : %d in feed_task", input_buffer, codec_config, eos, core->encoder);*/ continue; } - LOGI("status : in_buf : %p, codec_config : %d, eos : %d, video : %d, encoder : %d in feed_task", - in_buf, codec_config, eos, core->video, core->encoder); + LOGI("status : input_buffer : %p, codec_config : %d, eos : %d, video : %d, encoder : %d in feed_task", + input_buffer, codec_config, eos, core->video, core->encoder); LOGD("feed task finished %p v(%d)e(%d)", core, core->video, core->encoder); MEDIACODEC_FLEAVE(); @@ -1360,6 +1331,210 @@ static void __mc_gst_start_feed(GstElement *pipeline, guint size, gpointer data) } } +GstCaps *_mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index) +{ + GstCaps *caps = NULL; + mc_gst_port_def_t *port_def = &core->ports[index]->port_def; + + caps = gst_caps_new_simple(core->mime, + "rate", G_TYPE_INT, port_def->info.audio.samplerate, + "channels", G_TYPE_INT, port_def->info.audio.channel, NULL); + + switch (codec_id) { + case MEDIACODEC_AAC: + if (core->encoder) { + gst_caps_set_simple(caps, + "layout", G_TYPE_STRING, "interleaved", NULL); + g_object_set(GST_OBJECT(core->codec), "compliance", -2, NULL); + } else { + gst_caps_set_simple(caps, + "framed", G_TYPE_BOOLEAN, TRUE, + "mpegversion", G_TYPE_INT, 4, + "stream-format", G_TYPE_STRING, "adts", + NULL); + LOGD("CAPS for codec_id (MEDIACODEC_AAC_LC - normal ADTS)"); + } + break; + case MEDIACODEC_AAC_HE: + case MEDIACODEC_AAC_HE_PS: + if (core->encoder) { + LOGD("[MC_NOT_SUPPORTED] he-aac-v12 encoder is not supported yet!!!"); + return NULL; + } else { + gst_caps_set_simple(caps, + "mpegversion", G_TYPE_INT, 4, + "framed", G_TYPE_BOOLEAN, TRUE, + "stream-format", G_TYPE_STRING, "raw", + NULL); + LOGD("CAPS for codec_id (MEDIACODEC_AAC_HE)"); + } + break; + case MEDIACODEC_MP3: + if (core->encoder) { + LOGD("[MC_NOT_SUPPORTED] mp3 encoder is not supported yet!!!"); + return NULL; + } else { + gst_caps_set_simple(caps, + "framed", G_TYPE_BOOLEAN, TRUE, + "mpegversion", G_TYPE_INT, 1, /* To-Do : plz check */ + "mpegaudioversion", G_TYPE_INT, 1, /* To-Do : plz check */ + "layer", G_TYPE_INT, 3, /* To-Do : plz check */ + NULL); + LOGD("CAPS for codec_id (MEDIACODEC_MP3)"); + } + break; + case MEDIACODEC_AMR_NB: + 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); + LOGD("CAPS for codec_id (MEDIACODEC_AMR_NB)"); + } else { + gst_caps_set_simple(caps, + "rate", G_TYPE_INT, 8000, + NULL); + } + break; + case MEDIACODEC_AMR_WB: + if (core->encoder) { + LOGD("[MC_NOT_SUPPORTED] amr-wb encoder is not supported yet!!!"); + return NULL; + } else { + gst_caps_set_simple(caps, + "rate", G_TYPE_INT, 16000, + NULL); + } + break; + case MEDIACODEC_VORBIS: + if (core->encoder) { + LOGD("[MC_NOT_SUPPORTED] vorbis encoder is not supported yet!!!"); + return NULL; + } else { + } + break; + case MEDIACODEC_FLAC: + if (core->encoder) { + LOGD("[MC_NOT_SUPPORTED] flac encoder is not supported yet!!!"); + return NULL; + } else { + gst_caps_set_simple(caps, + "framed", G_TYPE_BOOLEAN, TRUE, + /* FIXME - Insert More Info */ + NULL); + } + break; + case MEDIACODEC_WMAV1: + case MEDIACODEC_WMAV2: + case MEDIACODEC_WMAPRO: + case MEDIACODEC_WMALSL: + if (core->encoder) { + LOGD("[MC_NOT_SUPPORTED] wma encoder is not supported yet!!!"); + return NULL; + } else { + /* + * Need to extract from Stream Type Specific ... or + * Need to get Demuxer's Caps from Stream Type Specific + */ + guint16 format_tag = 0; + gint wma_version = 0; + gint block_align = 1024; /*FIXME : Need checking */ + gint bitrate = 128000; /*FIXME : Need checking */ + + LOGD(" ----- WMA Need Additional Caps -----------"); + if (core->codec_id == MEDIACODEC_WMAV1) { + format_tag = 352; /* 0x160 */ + wma_version = 1; + } else if (core->codec_id == MEDIACODEC_WMAV2) { + format_tag = 353; /* 0x161 */ + wma_version = 2; + } else if (core->codec_id == MEDIACODEC_WMAPRO) { + format_tag = 354; /* 0x162 */ + wma_version = 3; + } else if (core->codec_id == MEDIACODEC_WMALSL) { + format_tag = 355; /* 0x163 */ + wma_version = 3; + } else { + LOGE("Not support WMA format"); + } + + gst_caps_set_simple(caps, + "bitrate", G_TYPE_INT, bitrate, + "depth", G_TYPE_INT, port_def->info.audio.bit_depth, + /* FIXME - Need More Info */ + "wmaversion", G_TYPE_INT, wma_version, + "format_tag", G_TYPE_INT, format_tag, + "block_align", G_TYPE_INT, block_align, + NULL); + } + break; + default: + break; + } + return caps; +} + +GstCaps *_mc_gst_vid_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index) +{ + GstCaps *caps = NULL; + mc_gst_port_def_t *port_def = &core->ports[index]->port_def; + + caps = gst_caps_new_simple(core->mime, + "width", G_TYPE_INT, port_def->info.video.width, + "height", G_TYPE_INT, port_def->info.video.height, + "framerate", GST_TYPE_FRACTION, port_def->info.video.framerate, 1, + NULL); + + switch (codec_id) { + case MEDIACODEC_H263: + if (core->encoder) { + gst_caps_set_simple(caps, + "format", G_TYPE_STRING, port_def->info.video.format, + NULL); + } else { + gst_caps_set_simple(caps, + "mpegversion", G_TYPE_INT, 4, + "framerate", GST_TYPE_FRACTION, 30, 1, + NULL); + } + break; + case MEDIACODEC_MPEG4: + if (core->encoder) { + gst_caps_set_simple(caps, + "format", G_TYPE_STRING, port_def->info.video.format, + NULL); + } else { + gst_caps_set_simple(caps, + "mpegversion", G_TYPE_INT, 4, + "systemstream", G_TYPE_BOOLEAN, false, + "parsed", G_TYPE_BOOLEAN, TRUE, + "framerate", GST_TYPE_FRACTION, 30, 1, + NULL); + } + break; + case MEDIACODEC_H264: + if (core->encoder) { + gst_caps_set_simple(caps, + "format", G_TYPE_STRING, port_def->info.video.format, + NULL); + g_object_set(GST_OBJECT(core->codec), "byte-stream", TRUE, NULL); + LOGE("format : %s", port_def->info.video.format); + } else { + gst_caps_set_simple(caps, + "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, + NULL); + } + break; + default: + break; + } + + return caps; +} + static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboolean encoder, gboolean is_hw) { MEDIACODEC_FENTER(); @@ -1368,69 +1543,35 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo switch (id) { case MEDIACODEC_AAC: - /* if set to 'CODEC_CONFIG', then It is also available case of MEDIA_FORMAT_AAC_LC (RAW) */ - LOGD("aac lc (adts) vtable"); if (encoder) { core->vtable = aenc_aac_vtable; - core->caps = gst_caps_new_simple(core->mime, - "layout", G_TYPE_STRING, "interleaved", NULL); - g_object_set(GST_OBJECT(core->codec), "compliance", -2, NULL); } else { - LOGD("CAPS for codec_id (MEDIACODEC_AAC_LC - normal ADTS)"); - core->vtable = adec_aac_vtable; - core->caps = gst_caps_new_simple(core->mime, - "framed", G_TYPE_BOOLEAN, TRUE, - "mpegversion", G_TYPE_INT, 4, - "stream-format", G_TYPE_STRING, "adts", - NULL); } break; case MEDIACODEC_AAC_HE: case MEDIACODEC_AAC_HE_PS: - LOGD("aac he v12 vtable"); if (encoder) { LOGD("[MC_NOT_SUPPORTED] he-aac-v12 encoder is not supported yet!!!"); return MC_NOT_SUPPORTED; } else { - LOGD("CAPS for codec_id (MEDIACODEC_AAC_HE and _PS - MP4/M4A case)"); core->vtable = adec_aacv12_vtable; - core->caps = gst_caps_new_simple(core->mime, - "mpegversion", G_TYPE_INT, 4, /*TODO : need adding version /profile*/ - "framed", G_TYPE_BOOLEAN, TRUE, - "stream-format", G_TYPE_STRING, "raw", - NULL); } break; case MEDIACODEC_MP3: - LOGD("mp3 vtable - Only support decoder"); if (encoder) { LOGD("[MC_NOT_SUPPORTED] mp3 encoder is not supported yet!!!"); return MC_NOT_SUPPORTED; } else { core->vtable = adec_mp3_vtable; - core->caps = gst_caps_new_simple(core->mime, - "framed", G_TYPE_BOOLEAN, TRUE, - "mpegversion", G_TYPE_INT, 1, /* To-Do : plz check */ - "mpegaudioversion", G_TYPE_INT, 1, /* To-Do : plz check */ - "layer", G_TYPE_INT, 3, /* To-Do : plz check */ - NULL); } break; case MEDIACODEC_AMR_NB: LOGD("amrnb vtable"); if (encoder) { core->vtable = aenc_amrnb_vtable; - core->caps = gst_caps_new_simple(core->mime, - "format", G_TYPE_STRING, "S16LE", - "layout", G_TYPE_STRING, "interleaved", - NULL); - } else { core->vtable = adec_amrnb_vtable; - core->caps = gst_caps_new_simple(core->mime, - "rate", G_TYPE_INT, 8000, - NULL); } break; case MEDIACODEC_AMR_WB: @@ -1440,9 +1581,6 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo return MC_NOT_SUPPORTED; } else { core->vtable = adec_amrwb_vtable; - core->caps = gst_caps_new_simple(core->mime, - "rate", G_TYPE_INT, 16000, - NULL); } break; case MEDIACODEC_VORBIS: @@ -1452,7 +1590,6 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo return MC_NOT_SUPPORTED; } else { core->vtable = adec_vorbis_vtable; - core->caps = gst_caps_new_empty_simple("audio/x-vorbis"); } break; case MEDIACODEC_FLAC: @@ -1462,10 +1599,6 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo return MC_NOT_SUPPORTED; } else { core->vtable = adec_flac_vtable; - core->caps = gst_caps_new_simple(core->mime, - "framed", G_TYPE_BOOLEAN, TRUE, - /* FIXME - Insert More Info */ - NULL); } break; case MEDIACODEC_WMAV1: @@ -1477,64 +1610,18 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo LOGD("[MC_NOT_SUPPORTED] wma encoder is not supported yet!!!"); return MC_NOT_SUPPORTED; } else { - mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; - core->vtable = adec_wma_vtable; - - /* - * Need to extract from Stream Type Specific ... or - * Need to get Demuxer's Caps from Stream Type Specific - */ - guint16 format_tag = 0; - gint wma_version = 0; - gint block_align = 1024; /*FIXME : Need checking */ - gint bitrate = 128000; /*FIXME : Need checking */ - - LOGD(" ----- WMA Need Additional Caps -----------"); - if (core->codec_id == MEDIACODEC_WMAV1) { - format_tag = 352; /* 0x160 */ - wma_version = 1; - } else if (core->codec_id == MEDIACODEC_WMAV2) { - format_tag = 353; /* 0x161 */ - wma_version = 2; - } else if (core->codec_id == MEDIACODEC_WMAPRO) { - format_tag = 354; /* 0x162 */ - wma_version = 3; - } else if (core->codec_id == MEDIACODEC_WMALSL) { - format_tag = 355; /* 0x163 */ - wma_version = 3; - } else { - LOGE("Not support WMA format"); - } - - core->caps = gst_caps_new_simple(core->mime, - "bitrate", G_TYPE_INT, bitrate, - "depth", G_TYPE_INT, dec_info->bit, - /* FIXME - Need More Info */ - "wmaversion", G_TYPE_INT, wma_version, - "format_tag", G_TYPE_INT, format_tag, - "block_align", G_TYPE_INT, block_align, - NULL); } break; case MEDIACODEC_H263: LOGD("h263 vtable"); if (encoder) { core->vtable = is_hw ? venc_h263_hw_vtable : venc_h263_sw_vtable; - core->caps = gst_caps_new_empty_simple("video/x-raw"); } else { if (is_hw) { core->vtable = vdec_h263_hw_vtable; - core->caps = gst_caps_new_simple(core->mime, - "mpegversion", G_TYPE_INT, 4, - "framerate", GST_TYPE_FRACTION, 30, 1, - NULL); } else { core->vtable = vdec_h263_sw_vtable; - core->caps = gst_caps_new_simple(core->mime, - "variant", G_TYPE_STRING, "itu", - "framerate", GST_TYPE_FRACTION, 30, 1, - NULL); } } break; @@ -1542,47 +1629,25 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo LOGD("mpeg4 vtable"); if (encoder) { core->vtable = is_hw ? venc_mpeg4_hw_vtable : venc_mpeg4_sw_vtable; - core->caps = gst_caps_new_empty_simple("video/x-raw"); } else { core->vtable = is_hw ? vdec_mpeg4_hw_vtable : vdec_mpeg4_sw_vtable; - core->caps = gst_caps_new_simple(core->mime, - "mpegversion", G_TYPE_INT, 4, - "systemstream", G_TYPE_BOOLEAN, false, - "parsed", G_TYPE_BOOLEAN, TRUE, - "framerate", GST_TYPE_FRACTION, 30, 1, - NULL); } break; case MEDIACODEC_H264: LOGD("h264 vtable"); if (encoder) { core->vtable = is_hw ? venc_h264_hw_vtable : venc_vtable; - core->caps = gst_caps_new_empty_simple("video/x-raw"); - g_object_set(GST_OBJECT(core->codec), "byte-stream", TRUE, NULL); } else { if (is_hw) { core->vtable = vdec_h264_hw_vtable; - core->caps = gst_caps_new_simple(core->mime, - "parsed", G_TYPE_BOOLEAN, TRUE, - "alignment", G_TYPE_STRING, "au", - "stream-format", G_TYPE_STRING, "byte-stream", - "framerate", GST_TYPE_FRACTION, 30, 1, - NULL); } else { core->vtable = vdec_h264_sw_vtable; - core->caps = gst_caps_new_simple(core->mime, - "alignment", G_TYPE_STRING, "au", - "stream-format", G_TYPE_STRING, "byte-stream", - "framerate", GST_TYPE_FRACTION, 30, 1, - NULL); } } break; default: break; } - /* set caps */ - g_object_set(core->appsrc, "caps", core->caps, NULL); MEDIACODEC_FLEAVE(); @@ -1618,6 +1683,7 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) media_format_mimetype_e out_mime; int num_supported_codec = 0; int i = 0; + GstCaps *caps = NULL; if (!mc_handle) return MC_PARAM_ERROR; @@ -1655,9 +1721,11 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) new_core->eos = false; new_core->encoder = encoder; new_core->video = video; - new_core->codec_info = encoder ? (void *)&mc_handle->info.encoder : (void *)&mc_handle->info.decoder; - new_core->out_mime = codec_map[i].type.out_format; + memcpy(&new_core->ports[in_port_index]->port_def.info, &mc_handle->info, sizeof(mc_handle->info)); + memcpy(&new_core->ports[out_port_index]->port_def.info, &mc_handle->info, sizeof(mc_handle->info)); + new_core->ports[out_port_index]->port_def.coding_type = out_mime; new_core->codec_id = id; + new_core->mc_caps_new = video ? &_mc_gst_vid_caps_new : &_mc_gst_aud_caps_new; new_core->bufmgr = tbm_bufmgr_init(new_core->drm_fd); if (new_core->bufmgr == NULL) { @@ -1684,8 +1752,6 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) } } - mc_handle->core = new_core; - /* create basic core elements */ ret = _mc_gst_create_pipeline(mc_handle->core, factory_name); if (ret != MC_ERROR_NONE) { @@ -1700,6 +1766,22 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) return ret; } + /* set caps in capsfilter as default*/ + caps = new_core->mc_caps_new(new_core, id, out_port_index); + + /* FIXME will parse input format from ini. format is needed when linking elements*/ + if (new_core->video && new_core->encoder) { + gchar *format = NULL; + + format = new_core->is_hw ? "SN12" : "I420"; + gst_caps_set_simple(caps, + "format", G_TYPE_STRING, format, + NULL); + } + g_object_set(new_core->capsfilter, "caps", caps, NULL); + gst_caps_unref(caps); + + mc_handle->core = new_core; LOGD("initialized... %d", ret); MEDIACODEC_FLEAVE(); @@ -2009,6 +2091,28 @@ mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, gchar *factory_name) LOGE("capsfilter can't create"); goto ERROR; } + + core->audioresample = gst_element_factory_make("audioresample", NULL); + + if (!core->audioresample) { + LOGE("capsfilter can't create"); + goto ERROR; + } + } + + if (core->video && core->encoder) { + core->videoconvert = gst_element_factory_make("videoconvert", NULL); + + if (!core->videoconvert) { + LOGE("videoconvert can't create"); + goto ERROR; + } + + core->videoscale = gst_element_factory_make("videoscale", NULL); + if (!core->videoscale) { + LOGE("videoscale can't create"); + goto ERROR; + } } core->capsfilter = gst_element_factory_make("capsfilter", NULL); @@ -2028,10 +2132,18 @@ mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, gchar *factory_name) /*__mc_link_elements(core);*/ if (!core->video && core->encoder) { - gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->audioconvert, core->codec, core->fakesink, NULL); + gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->audioresample, core->audioconvert, core->capsfilter, core->codec, core->fakesink, NULL); /* link elements */ - if (!(gst_element_link_many(core->appsrc, core->capsfilter, core->audioconvert, core->codec, core->fakesink, NULL))) { + if (!(gst_element_link_many(core->appsrc, core->audioresample, core->audioconvert, core->capsfilter, core->codec, core->fakesink, NULL))) { + LOGE("gst_element_link_many is failed"); + goto ERROR; + } + } else if (core->video && core->encoder) { + gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL); + + /* link elements */ + if (!(gst_element_link_many(core->appsrc, core->codec, core->fakesink, NULL))) { LOGE("gst_element_link_many is failed"); goto ERROR; } @@ -2089,6 +2201,15 @@ ERROR: if (core->capsfilter) gst_object_unref(GST_OBJECT(core->capsfilter)); + if (core->audioresample) + gst_object_unref(GST_OBJECT(core->audioresample)); + + if (core->videoscale) + gst_object_unref(GST_OBJECT(core->videoscale)); + + if (core->videoconvert) + gst_object_unref(GST_OBJECT(core->videoconvert)); + if (core->audioconvert) gst_object_unref(GST_OBJECT(core->audioconvert)); @@ -2263,16 +2384,9 @@ int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void * return MEDIA_PACKET_FINALIZE; } -gchar *__mc_get_gst_input_format(media_packet_h packet, bool is_hw) +gchar *__mc_get_gst_input_format(media_format_mimetype_e mimetype, bool is_hw) { gchar *format = NULL; - media_format_h fmt = NULL; - media_format_mimetype_e mimetype = 0; - - media_packet_get_format(packet, &fmt); - media_format_get_video_info(fmt, &mimetype, NULL, NULL, NULL, NULL); - media_format_unref(fmt); - LOGD("input packet mimetype : %x", mimetype); switch (mimetype) { case MEDIA_FORMAT_I420: @@ -3409,29 +3523,19 @@ mc_ret_e mc_gst_get_packet_pool(mc_handle_t *mc_handle, media_packet_pool_h *pac mime_format = _mc_get_mime(core); if (core->video) { - if (core->encoder) { - media_format_set_video_mime(fmt_handle, mime_format); - media_format_set_video_width(fmt_handle, mc_handle->info.encoder.width); - media_format_set_video_height(fmt_handle, mc_handle->info.encoder.height); - media_format_set_video_avg_bps(fmt_handle, mc_handle->info.encoder.bitrate); - } else { - media_format_set_video_mime(fmt_handle, mime_format); - media_format_set_video_width(fmt_handle, mc_handle->info.decoder.width); - media_format_set_video_height(fmt_handle, mc_handle->info.decoder.height); - } + media_format_set_video_mime(fmt_handle, mime_format); + media_format_set_video_width(fmt_handle, mc_handle->info.video.width); + media_format_set_video_height(fmt_handle, mc_handle->info.video.height); + if (core->encoder) + media_format_set_video_avg_bps(fmt_handle, mc_handle->info.video.bitrate); } else { - if (core->encoder) { media_format_set_audio_mime(fmt_handle, mime_format); - media_format_set_audio_channel(fmt_handle, mc_handle->info.encoder.channel); - media_format_set_audio_samplerate(fmt_handle, mc_handle->info.encoder.samplerate); - media_format_set_audio_bit(fmt_handle, mc_handle->info.encoder.bit); - } else { - media_format_set_audio_mime(fmt_handle, mime_format); - media_format_set_audio_channel(fmt_handle, mc_handle->info.decoder.channel); - media_format_set_audio_samplerate(fmt_handle, mc_handle->info.decoder.samplerate); - media_format_set_audio_bit(fmt_handle, mc_handle->info.decoder.bit); - } + media_format_set_audio_channel(fmt_handle, mc_handle->info.audio.channel); + media_format_set_audio_samplerate(fmt_handle, mc_handle->info.audio.samplerate); + media_format_set_audio_bit(fmt_handle, mc_handle->info.audio.bit_depth); + if (core->encoder) + media_format_set_audio_avg_bps(fmt_handle, mc_handle->info.audio.bitrate); } ret = media_packet_pool_set_media_format(pool, fmt_handle); diff --git a/test/media_codec_test.c b/test/media_codec_test.c index 5b592f5..dc46195 100644 --- a/test/media_codec_test.c +++ b/test/media_codec_test.c @@ -799,6 +799,7 @@ int _configure(App *app, int codecid, int flag, gboolean *hardware, media_forma if (encoder) { extractor = amrenc_extractor; mime = MEDIA_FORMAT_PCM_F32LE; /* FIXME need to check according to verdor */ + *codec_mime = MEDIA_FORMAT_AMR_NB; app->is_amr_nb = TRUE; } else { extractor = amrdec_extractor; @@ -1408,6 +1409,7 @@ void _mediacodec_prepare(App *app, gboolean frame_all) media_format_set_video_width(fmt, app->width); media_format_set_video_height(fmt, app->height); media_format_set_video_avg_bps(fmt, app->target_bits); + media_format_set_video_frame_rate(fmt, app->fps); media_format_create(&codec_format); media_format_set_video_mime(codec_format, codec_mime); @@ -1985,30 +1987,33 @@ void displaymenu(void) g_print("*** input mediapath.\n"); } else if (g_menu_state == CURRENT_STATUS_SET_CODEC) { g_print("*** Codec id : Select Codec ID Numbe (e.g. AAC_LC = 96)\n"); - g_print(" L16 = 16 (0x10)\n"); - g_print(" ALAW = 32 (0x20)\n"); - g_print(" ULAW = 48 (0x30)\n"); - g_print(" AMR_NB = 64 (0x40)\n"); - g_print(" AMR_WB = 65 (0x41)\n"); - g_print(" G729 = 80 (0x50)\n"); - g_print(" AAC_LC = 96 (0x60)\n"); - g_print(" AAC_HE = 97 (0x61)\n"); - g_print(" AAC_PS = 98 (0x62)\n"); - g_print(" MP3 = 112 (0x70)\n"); - g_print(" VORBIS = 128 (0x80)\n"); - g_print(" FLAC = 144 (0x90)\n"); - g_print(" WMAV1 = 160 (0xA0)\n"); - g_print(" WMAV2 = 161 (0xA1)\n"); - g_print(" WMAPRO = 162 (0xA2)\n"); - g_print(" WMALSL = 163 (0xA3)\n"); + g_print(" L16 = 0\n"); + g_print(" ALAW = 1\n"); + g_print(" ULAW = 2\n"); + g_print(" AMR_NB = 3\n"); + g_print(" AMR_WB = 4\n"); + g_print(" G729 = 5\n"); + g_print(" AAC_LC = 6\n"); + g_print(" AAC_HE = 7\n"); + g_print(" AAC_PS = 8\n"); + g_print(" MP3 = 9\n"); + g_print(" VORBIS = 10\n"); + g_print(" FLAC = 11\n"); + g_print(" WMAV1 = 12\n"); + g_print(" WMAV2 = 13\n"); + g_print(" WMAPRO = 14\n"); + g_print(" WMALSL = 15\n"); g_print(" -------------------\n"); - g_print(" H261 = 101\n"); - g_print(" H263 = 102\n"); - g_print(" H264 = 103\n"); - g_print(" MJPEG = 104\n"); - g_print(" MPEG1 = 105\n"); - g_print(" MPEG2 = 106\n"); - g_print(" MPEG4 = 107\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(" -------------------\n"); g_print("*** Flags : Select Combination Number (e.g. DEOCDER + TYPE_SW = 10)\n"); g_print(" CODEC : ENCODER = 1 DECODER = 2\n"); @@ -2046,6 +2051,7 @@ void interpret(char *cmd) { App *app = &s_app; gint tmp = 0; + static gint cnt = 0; switch (g_menu_state) { case CURRENT_STATUS_MAINMENU: @@ -2057,111 +2063,83 @@ void interpret(char *cmd) break; case CURRENT_STATUS_SET_CODEC: { - static gint cnt = 0; - gchar **ptr = NULL; - switch (cnt) { - case 0: - tmp = atoi(cmd); + 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 }; - if (tmp > 100 && - (tmp != 112) && - (tmp != 128) && - (tmp != 144) && - (tmp != 160) && (tmp != 161) && (tmp != 162) && (tmp != 163)) { - tmp = strtol(cmd, ptr, 16); - app->codecid = 0x2000 + ((tmp & 0xFF) << 4); - } else - app->codecid = 0x1000 + tmp; + if (cnt == 0) { + gint n_sizes = G_N_ELEMENTS(ids); + tmp = atoi(cmd); + if (tmp < 0 || tmp >= n_sizes - 1) { + cnt = 0; + g_print("Invalid value\n"); + reset_menu_state(); + break; + } + app->codecid = ids[tmp]; cnt++; - break; - case 1: + } else if (cnt == 1) { app->flag = atoi(cmd); cnt = 0; reset_menu_state(); - break; - default: - break; } } break; case CURRENT_STATUS_SET_VDEC_INFO: { - static gint cnt = 0; - switch (cnt) { - case 0: + if (cnt == 0) { app->width = atoi(cmd); cnt++; - break; - case 1: + } else if (cnt == 1) { app->height = atoi(cmd); app->type = VIDEO_DEC; reset_menu_state(); cnt = 0; - break; - default: - break; } } break; case CURRENT_STATUS_SET_VENC_INFO: { - static gint cnt = 0; - switch (cnt) { - case 0: - app->width = atoi(cmd); + if (cnt == 0) { + app->width = atol(cmd); cnt++; - break; - case 1: - app->height = atoi(cmd); + } else if (cnt == 1) { + app->height = atol(cmd); cnt++; - break; - case 2: + } else if (cnt == 2) { app->fps = atol(cmd); cnt++; - break; - case 3: - app->target_bits = atoi(cmd); + } else if (cnt == 3) { + app->target_bits = atol(cmd); app->type = VIDEO_ENC; reset_menu_state(); cnt = 0; - break; - default: - break; } } break; case CURRENT_STATUS_SET_ADEC_INFO: { - static gint cnt = 0; - switch (cnt) { - case 0: + if (cnt == 0) { app->samplerate = atoi(cmd); cnt++; - break; - case 1: + } else if (cnt == 1) { app->channel = atoi(cmd); cnt++; - break; - case 2: + } else if (cnt == 2) { app->bit = atoi(cmd); app->type = AUDIO_DEC; reset_menu_state(); cnt = 0; - break; - default: - break; } } break; case CURRENT_STATUS_SET_AENC_INFO: { - static int cnt = 0; - switch (cnt) { - case 0: + if (cnt == 0) { tmp = atoi(cmd); if (tmp <= 0 || tmp > 96000) { @@ -2171,8 +2149,7 @@ void interpret(char *cmd) } app->samplerate = tmp; cnt++; - break; - case 1: + } else if (cnt == 1) { tmp = atoi(cmd); if (tmp <= 0 || tmp > 6) { @@ -2182,8 +2159,7 @@ void interpret(char *cmd) } app->channel = tmp; cnt++; - break; - case 2: + } else if (cnt == 2) { tmp = atoi(cmd); if (tmp <= 0 || tmp > 32) { @@ -2193,8 +2169,7 @@ void interpret(char *cmd) } app->bit = tmp; cnt++; - break; - case 3: + } else if (cnt == 3) { tmp = atoi(cmd); if (tmp <= 0 || tmp >= INT_MAX) { @@ -2207,9 +2182,6 @@ void interpret(char *cmd) reset_menu_state(); cnt = 0; - break; - default: - break; } } break; @@ -2237,22 +2209,16 @@ void interpret(char *cmd) case CURRENT_STATUS_AUTO_TEST: { int len; - static int cnt = 0; - switch (cnt) { - case 0: + if (cnt == 0) { len = strlen(cmd); strncpy(app->filepath, cmd, len + 1); g_print("%s, %d\n", app->filepath, len); cnt++; - break; - case 1: + } else if (cnt == 1) { app->is_video = atoi(cmd) ? 1 : 0; _mediacodec_auto_test(app, app->filepath); reset_menu_state(); cnt = 0; - break; - default: - break; } } break; -- 2.7.4 From 6e514281315352dff296762d447854f25c624030 Mon Sep 17 00:00:00 2001 From: Sejun Park Date: Thu, 29 Mar 2018 16:53:23 +0900 Subject: [PATCH 03/16] Sync with tizen 4.0 Change-Id: I4e77a485916bb78806c28484ea4e6a980ad53525 --- doc/media_codec_doc.h | 12 +++ include/media_codec.h | 26 +++++++ include/media_codec_port.h | 4 +- packaging/capi-media-codec.spec | 4 +- src/media_codec_port.c | 161 +++++++++++++++++++++++++++++++++++++--- src/media_codec_port_gst.c | 89 +++++----------------- 6 files changed, 211 insertions(+), 85 deletions(-) mode change 100644 => 100755 doc/media_codec_doc.h mode change 100644 => 100755 include/media_codec.h mode change 100644 => 100755 include/media_codec_port.h mode change 100644 => 100755 src/media_codec_port.c mode change 100644 => 100755 src/media_codec_port_gst.c diff --git a/doc/media_codec_doc.h b/doc/media_codec_doc.h old mode 100644 new mode 100755 index 5899e57..36a1586 --- a/doc/media_codec_doc.h +++ b/doc/media_codec_doc.h @@ -33,6 +33,18 @@ * * @section CAPI_MEDIA_CODEC_MODULE_OVERVIEW Overview * + * @section CAPI_MEDIA_CODEC_FEATURE Related Features + * This API is related with the following features:\n + * - %http://tizen.org/feature/multimedia.media_codec:\n + * + * It is recommended to design feature related codes in your application for reliability.\n + * + * You can check if a device supports the related features for this API by using @ref CAPI_SYSTEM_SYSTEM_INFO_MODULE, thereby controlling the procedure of your application.\n + * + * To ensure your application is only running on the device with specific features, please define the features in your manifest file using the manifest editor in the SDK.\n + * + * More details on featuring your application can be found from Feature Element. + * * MEDIA CODEC API allows : * The API allows you to direct access to the media codec on device. It operates on "raw" data, so any file headers * must be stripped off. media_packet is used for zero-copy. diff --git a/include/media_codec.h b/include/media_codec.h old mode 100644 new mode 100755 index 5899592..835cbec --- a/include/media_codec.h +++ b/include/media_codec.h @@ -212,6 +212,7 @@ typedef bool (*mediacodec_supported_codec_cb)(mediacodec_codec_type_e codec_type * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_create(mediacodec_h *mediacodec); @@ -227,6 +228,7 @@ int mediacodec_create(mediacodec_h *mediacodec); * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_destroy(mediacodec_h mediacodec); @@ -246,6 +248,7 @@ int mediacodec_destroy(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation * @retval #MEDIACODEC_ERROR_CODEC_NOT_FOUND Codec not found + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_type, int flags); @@ -260,6 +263,7 @@ int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height); @@ -278,6 +282,7 @@ int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height); * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_set_venc_info(mediacodec_h mediacodec, int width, int height, int fps, int target_bits); @@ -293,6 +298,7 @@ int mediacodec_set_venc_info(mediacodec_h mediacodec, int width, int height, int * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_set_adec_info(mediacodec_h mediacodec, int samplerate, int channel, int bit); @@ -309,6 +315,7 @@ int mediacodec_set_adec_info(mediacodec_h mediacodec, int samplerate, int channe * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_set_aenc_info(mediacodec_h mediacodec, int samplerate, int channel, int bit, int bitrate); @@ -336,6 +343,7 @@ int mediacodec_set_aenc_info(mediacodec_h mediacodec, int samplerate, int channe * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_CODEC_NOT_FOUND Unsupported codec + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @pre The media format has been created and the required values for configuration have been set. * @see media_format_set_video_mime() * @see media_format_set_audio_mime() @@ -359,6 +367,7 @@ int mediacodec_configure_from_media_format(mediacodec_h mediacodec, media_format * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @pre The mediacodec should call mediacodec_set_codec()and mediacodec_set_vdec_info()/mediacodec_set_venc_info() before calling mediacodec_prepare() * If the decoder is set by mediacodec_set_codec(), mediacodec_set_vdec_info() should be called. If the encoder is set by * mediacodec_set_codec(), mediacodec_set_venc_info() should be called. @@ -374,6 +383,7 @@ int mediacodec_prepare(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_unprepare(mediacodec_h mediacodec); @@ -391,6 +401,7 @@ int mediacodec_unprepare(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation * @retval #MEDIACODEC_ERROR_OVERFLOW_INBUFFER Overflow inputbuffer + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint64_t timeOutUs); @@ -407,6 +418,7 @@ int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_get_output(mediacodec_h mediacodec, media_packet_h *outbuf, uint64_t timeOutUs); @@ -417,6 +429,7 @@ int mediacodec_get_output(mediacodec_h mediacodec, media_packet_h *outbuf, uint6 * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_flush_buffers(mediacodec_h mediacodec); @@ -429,6 +442,7 @@ int mediacodec_flush_buffers(mediacodec_h mediacodec); * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @pre mediacodec_set_input_buffer_used_cb should be called before mediacodec_preare(). * @post mediacodec_input_buffer_used_cb will be invoked. * @see mediacodec_set_input_buffer_used_cb() @@ -443,6 +457,7 @@ int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_inpu * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @see mediacodec_set_input_buffer_used_cb() */ int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec); @@ -456,6 +471,7 @@ int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec); * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @pre mediacodec_set_output_buffer_available_cb should be called before mediacodec_preare(). * @post mediacodec_output_buffer_available_cb will be invoked. * @see mediacodec_set_output_buffer_available_cb() @@ -470,6 +486,7 @@ int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacode * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @see mediacodec_set_output_buffer_available_cb() */ int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec); @@ -483,6 +500,7 @@ int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec); * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @pre mediacodec_set_error_cb should be called before mediacodec_preare(). * @post mediacodec_error_cb will be invoked. * @see mediacodec_set_error_cb() @@ -497,6 +515,7 @@ int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callbac * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @see mediacodec_set_error_cb() */ int mediacodec_unset_error_cb(mediacodec_h mediacodec); @@ -510,6 +529,7 @@ int mediacodec_unset_error_cb(mediacodec_h mediacodec); * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @pre mediacodec_set_eos_cb should be called before mediacodec_preare(). * @post mediacodec_eos_cb will be invoked. * @see mediacodec_set_eos_cb() @@ -524,6 +544,7 @@ int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, v * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @see mediacodec_set_event_handler_cb() */ int mediacodec_unset_eos_cb(mediacodec_h mediacodec); @@ -537,6 +558,7 @@ int mediacodec_unset_eos_cb(mediacodec_h mediacodec); * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @pre mediacodec_set_buffer_status_cb should be called before mediacodec_preare(). * @post mediacodec_buffer_status_cb will be invoked. * @see mediacodec_set_buffer_status_cb() @@ -551,6 +573,7 @@ int mediacodec_set_buffer_status_cb(mediacodec_h mediacodec, mediacodec_buffer_s * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ int mediacodec_unset_buffer_status_cb(mediacodec_h mediacodec); @@ -563,6 +586,7 @@ int mediacodec_unset_buffer_status_cb(mediacodec_h mediacodec); * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @see mediacodec_foreach_supported_codec() */ int mediacodec_foreach_supported_codec(mediacodec_h mediacodec, mediacodec_supported_codec_cb callback, void *user_data); @@ -577,6 +601,7 @@ int mediacodec_foreach_supported_codec(mediacodec_h mediacodec, mediacodec_suppo * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) @code #include mediacodec_h mediacodec; @@ -611,6 +636,7 @@ int mediacodec_get_supported_type(mediacodec_h mediacodec, mediacodec_codec_type * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION The user calls mediacodec_get_packet_pool() before calling mediacodec_prepare(). + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) * @pre mediacodec_get_packet_pool() should be called after calling mediacodec_prepare(). * @post If the pool is used, media_packet_pool_deallocate() and media_packet_pool_destroy() should be called. * @see media_packet_pool_acquire_packet() diff --git a/include/media_codec_port.h b/include/media_codec_port.h old mode 100644 new mode 100755 index f2a732c..986bdd3 --- a/include/media_codec_port.h +++ b/include/media_codec_port.h @@ -267,8 +267,8 @@ void _mc_create_codec_map_from_ini_static(mc_ini_t *ini, mc_codec_spec_t *spec_e void _mc_create_decoder_map_from_ini(mc_handle_t *mc_handle); void _mc_create_encoder_map_from_ini(mc_handle_t *mc_handle); -const codec_type_e simple_to_codec_type_enumeration(codec_type_e codec_id); -const codec_type_e codec_type_to_simple_enumeration(mediacodec_codec_type_e media_codec_id); +mediacodec_codec_type_e simple_to_codec_type_enumeration(codec_type_e codec_id); +codec_type_e codec_type_to_simple_enumeration(mediacodec_codec_type_e media_codec_id); #ifdef __cplusplus } diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 9f9ee77..0d2a3bb 100755 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -4,8 +4,8 @@ Name: capi-media-codec Summary: A Media Codec library in Tizen Native API -Version: 0.5.8 -Release: 2 +Version: 0.5.10 +Release: 0 Group: Multimedia/API License: Apache-2.0 Source0: %{name}-%{version}.tar.gz diff --git a/src/media_codec_port.c b/src/media_codec_port.c old mode 100644 new mode 100755 index cf6843a..804a7cb --- a/src/media_codec_port.c +++ b/src/media_codec_port.c @@ -27,6 +27,9 @@ #include #include +static gboolean _check_support_audio_info(mediacodec_codec_type_e codec_id, int samplerate, int channel, int bit_depth); +static gboolean _check_support_video_info(mediacodec_codec_type_e codec_id, int width, int height); + int mc_create(MMHandleType *mediacodec) { mc_handle_t *new_mediacodec = NULL; @@ -168,7 +171,7 @@ int mc_set_vdec_info(MMHandleType mediacodec, int width, int height) return MC_INVALID_ARG; } - if ((width <= 0) || (height <= 0)) + if (!_check_support_video_info(mc_handle->codec_id, width, height)) return MC_PARAM_ERROR; MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && !mc_handle->is_encoder, @@ -192,7 +195,7 @@ int mc_set_venc_info(MMHandleType mediacodec, int width, int height, int fps, in return MC_INVALID_ARG; } - if ((width <= 0) || (height <= 0)) + if (!_check_support_video_info(mc_handle->codec_id, width, height) || fps < 0 || target_bits < 0) return MC_PARAM_ERROR; MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && mc_handle->is_encoder, @@ -217,7 +220,7 @@ int mc_set_adec_info(MMHandleType mediacodec, int samplerate, int channel, int b return MC_INVALID_ARG; } - if ((samplerate <= 0) || (channel <= 0) || (bit <= 0)) + if (!_check_support_audio_info(mc_handle->codec_id, samplerate, channel, bit)) return MC_PARAM_ERROR; MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && !mc_handle->is_encoder, @@ -241,7 +244,7 @@ int mc_set_aenc_info(MMHandleType mediacodec, int samplerate, int channel, int b return MC_INVALID_ARG; } - if ((samplerate <= 0) || (channel <= 0) || (bit <= 0)) + if (!_check_support_audio_info(mc_handle->codec_id, samplerate, channel, bit)) return MC_PARAM_ERROR; MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && mc_handle->is_encoder, @@ -287,8 +290,10 @@ int mc_configure(MMHandleType mediacodec, media_format_h format, int flags) if (type == MEDIA_FORMAT_AUDIO) { media_format_get_audio_info(format, &mimetype, &channel, &samplerate, &bit, &bitrate); + codec_id = mimetype & codec_mask; + if (GET_IS_ENCODER(flags)) { - if ((samplerate <= 0) || (channel <= 0) || (bit <= 0) || (bitrate <= 0)) { + if (!_check_support_audio_info(codec_id, samplerate, channel, bit)) { LOGE("invalid pram is set : samplerate : %d, channel : %d, bit : %d, bitrate : %d", samplerate, channel, bit, bitrate); return MC_PARAM_ERROR; @@ -299,7 +304,7 @@ int mc_configure(MMHandleType mediacodec, media_format_h format, int flags) mc_handle->info.audio.bit_depth = bit; mc_handle->info.audio.bitrate = bitrate * 1000; } else if (GET_IS_DECODER(flags)) { - if ((samplerate <= 0) || (channel <= 0) || (bit <= 0)) { + if (!_check_support_audio_info(codec_id, samplerate, channel, bit)) { LOGE("invalid pram is set : samplerate : %d, channel : %d, bit : %d", samplerate, channel, bit); return MC_PARAM_ERROR; @@ -314,9 +319,10 @@ int mc_configure(MMHandleType mediacodec, media_format_h format, int flags) } else if (type == MEDIA_FORMAT_VIDEO) { media_format_get_video_info(format, &mimetype, &width, &height, &bitrate, NULL); media_format_get_video_frame_rate(format, &fps); + codec_id = mimetype & codec_mask; if (GET_IS_ENCODER(flags)) { - if ((width <= 0) || (height <= 0) || (bitrate <= 0) || (fps <= 0)) { + if (!_check_support_video_info(codec_id, width, height) || fps <= 0 || bitrate <= 0) { LOGE("invalid pram is set : width : %d, height : %d, bitrate : %d, fps : %d", width, height, bitrate, fps); return MC_PARAM_ERROR; @@ -327,7 +333,7 @@ int mc_configure(MMHandleType mediacodec, media_format_h format, int flags) mc_handle->info.video.framerate = fps; mc_handle->info.video.bitrate = bitrate * 1000; } else if (GET_IS_DECODER(flags)) { - if ((width <= 0) || (height <= 0)) { + if (!_check_support_video_info(codec_id, width, height)) { LOGE("invalid pram is set : width : %d, height : %d", width, height); return MC_PARAM_ERROR; @@ -347,8 +353,6 @@ int mc_configure(MMHandleType mediacodec, media_format_h format, int flags) if (!GET_IS_HW(flags) && !GET_IS_SW(flags)) flags |= MEDIACODEC_SUPPORT_TYPE_SW; - codec_id = mimetype & codec_mask; - for (i = 0; i < mc_handle->ini->num_supported_codecs; i++) { if ((codec_id == spec_emul[i].codec_id) && (flags == spec_emul[i].codec_type)) break; @@ -988,7 +992,7 @@ void _mc_create_codec_map_from_ini_static(mc_ini_t *ini, mc_codec_spec_t *spec_e return; } -const codec_type_e codec_type_to_simple_enumeration(mediacodec_codec_type_e media_codec_id) +codec_type_e codec_type_to_simple_enumeration(mediacodec_codec_type_e media_codec_id) { guint media_codec_id_u = (guint)media_codec_id; @@ -1052,7 +1056,7 @@ const codec_type_e codec_type_to_simple_enumeration(mediacodec_codec_type_e medi } } -const codec_type_e simple_to_codec_type_enumeration(codec_type_e codec_id) +mediacodec_codec_type_e simple_to_codec_type_enumeration(codec_type_e codec_id) { guint codec_id_u = (guint)codec_id; @@ -1115,3 +1119,136 @@ const codec_type_e simple_to_codec_type_enumeration(codec_type_e codec_id) return NONE; } } + +gboolean _check_support_audio_info(mediacodec_codec_type_e codec_id, int samplerate, int channel, int bit_depth) +{ + gint i = 0; + gint maxchannels = 2; + gint n_rates = 0; + gint s_bit_depth = 32; + + switch (codec_id) { + case MEDIACODEC_AMR_NB: + { + const static gint l_rates[] = { 8000 }; + maxchannels = 1; + n_rates = G_N_ELEMENTS(l_rates); + s_bit_depth = 16; /* NOTE: amrnbenc/amrnbdec surpports S16LE as format*/ + + while (i < n_rates) { + if (l_rates[i] == samplerate) + break; + i++; + } + + if (i == n_rates) { + LOGE("Invalid samplerate set"); + return false; + } + break; + } + case MEDIACODEC_AAC_LC: + case MEDIACODEC_AAC_HE: + { + const static gint l_rates[] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350 }; + maxchannels = 6; + n_rates = G_N_ELEMENTS(l_rates); + s_bit_depth = 32; /* NOTE: avdec_aac/avenc_aac surpports S32LE as format*/ + + while (i < n_rates) { + if (l_rates[i] == samplerate) + break; + i++; + } + + if (i == n_rates) { + LOGE("Invalid samplerate set"); + return false; + } + break; + } + case MEDIACODEC_MP3: + { + s_bit_depth = 16; /* NOTE: amrenc/amrnbdec surpports S16LE as format*/ + break; + } + case MEDIACODEC_VORBIS: + { + s_bit_depth = 32; /* NOTE: vorbisenc/vorbisdec surpports S32LE as format */ + break; + } + case MEDIACODEC_FLAC: + { + s_bit_depth = 32; /* NOTE: avdec_flac surpports S32LE as format */ + break; + } + default: + break; + } + + if (channel < 0 || channel > maxchannels) { + LOGE("Invalid channel set"); + return false; + } + + if (bit_depth != s_bit_depth) { + LOGE("Invalid bit set"); + return false; + } + + return true; +} + +gboolean _check_support_video_info(mediacodec_codec_type_e codec_id, int width, int height) +{ + gint i = 0; + gint n_sizes = 0; + + if (width <= 0 || height <= 0) { + LOGE("Invalid resolution set"); + return false; + } + + switch (codec_id) { + case MEDIACODEC_H261: + { + const static gint widths[] = { 352, 176 }; + const static gint heights[] = { 288, 144 }; + n_sizes = G_N_ELEMENTS(widths); + + while (i < n_sizes) { + if ((widths[i] == width) && (heights[i] == height)) + break; + i++; + } + + if (i == n_sizes) { + LOGE("Invalid resolution set"); + return false; + } + break; + } + case MEDIACODEC_H263: + { + const static gint widths[] = { 352, 704, 176, 1408, 128 }; + const static gint heights[] = { 288, 576, 144, 1152, 96 }; + n_sizes = G_N_ELEMENTS(widths); + + while (i < n_sizes) { + if ((widths[i] == width) && (heights[i] == height)) + break; + i++; + } + + if (i == n_sizes) { + LOGE("Invalid resolution set"); + return false; + } + break; + } + default: + break; + } + + return true; +} diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c old mode 100644 new mode 100755 index 6d32a7b..753b309 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -64,7 +64,6 @@ static gint __gst_handle_library_error(mc_gst_core_t *core, int code); static gint __gst_handle_core_error(mc_gst_core_t *core, int code); static const gchar * _mc_error_to_string(mc_ret_e err); static const gchar * _mc_bit_to_string(int bit); -static int _mc_get_support_bit_from_format(media_format_mimetype_e format); static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboolean is_encoder, gboolean is_hw); static int _mc_gst_flush_buffers(mc_gst_core_t *core); @@ -908,36 +907,23 @@ int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, m } mc_gst_port_def_t *port_def = &core->ports[out_port_index]->port_def; - if (encoder) { + if (video) { + media_format_set_video_mime(core->output_fmt, out_mime); + media_format_set_video_width(core->output_fmt, port_def->info.video.width); + media_format_set_video_height(core->output_fmt, port_def->info.video.height); - if (video) { - media_format_set_video_mime(core->output_fmt, out_mime); - media_format_set_video_width(core->output_fmt, port_def->info.video.width); - media_format_set_video_height(core->output_fmt, port_def->info.video.height); + if (encoder) media_format_set_video_avg_bps(core->output_fmt, port_def->info.video.bitrate); - } else { - int support_bit = 0; - support_bit = _mc_get_support_bit_from_format(out_mime); - - media_format_set_audio_mime(core->output_fmt, out_mime); - media_format_set_audio_channel(core->output_fmt, port_def->info.audio.channel); - media_format_set_audio_samplerate(core->output_fmt, port_def->info.audio.samplerate); - media_format_set_audio_bit(core->output_fmt, support_bit); - media_format_set_audio_avg_bps(core->output_fmt, port_def->info.audio.bitrate); - } } else { + media_format_set_audio_mime(core->output_fmt, out_mime); + media_format_set_audio_channel(core->output_fmt, port_def->info.audio.channel); + media_format_set_audio_samplerate(core->output_fmt, port_def->info.audio.samplerate); + media_format_set_audio_bit(core->output_fmt, port_def->info.audio.bit_depth); - if (video) { - media_format_set_video_mime(core->output_fmt, out_mime); - media_format_set_video_width(core->output_fmt, port_def->info.video.width); - media_format_set_video_height(core->output_fmt, port_def->info.video.height); - } else { - media_format_set_audio_mime(core->output_fmt, out_mime); - media_format_set_audio_channel(core->output_fmt, port_def->info.audio.channel); - media_format_set_audio_samplerate(core->output_fmt, port_def->info.audio.samplerate); - media_format_set_audio_bit(core->output_fmt, port_def->info.audio.bit_depth); - } + if (encoder) + media_format_set_audio_avg_bps(core->output_fmt, port_def->info.audio.bitrate); } + return MC_ERROR_NONE; } @@ -1090,7 +1076,7 @@ gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h format) is_format_change |= input_port_def->info.video.width != width; is_format_change |= input_port_def->info.video.height != height; - is_format_change |= (input_port_def->info.video.framerate != framerate) && (framerate != 0); + is_format_change |= ((input_port_def->info.video.framerate != framerate) && (framerate != 0)); if (is_format_change) { LOGD("Format changed : resolution %dx%d -> %dx%d, framerate %d -> %d", input_port_def->info.video.width, input_port_def->info.video.height, width, height, @@ -1101,7 +1087,7 @@ gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h format) if (core->encoder) { sformat = __mc_get_gst_input_format(mimetype, core->is_hw); - is_format_change |= input_port_def->info.video.bitrate != bitrate * 1000; + is_format_change |= ((input_port_def->info.video.bitrate != bitrate * 1000) && (bitrate != 0)); is_format_change |= g_strcmp0(input_port_def->info.video.format, sformat); if (is_format_change) { LOGD("Bitrate changed : %d -> %d", input_port_def->info.video.bitrate, bitrate); @@ -1132,7 +1118,7 @@ gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h format) } if (core->encoder) { - is_format_change |= input_port_def->info.audio.bitrate != bitrate * 1000; + is_format_change |= ((input_port_def->info.audio.bitrate != bitrate * 1000) && (bitrate != 0)); if (is_format_change) { LOGD("Bitrate changed : %d -> %d", input_port_def->info.audio.bitrate, bitrate); input_port_def->info.audio.bitrate = bitrate * 1000; @@ -1261,6 +1247,7 @@ static gpointer feed_task(gpointer data) pad = gst_element_get_static_pad(core->appsrc, "src"); gst_pad_push_event(pad, gst_event_new_stream_start("start")); gst_object_unref(pad); + is_format_change = TRUE; initiative = FALSE; } @@ -1344,6 +1331,7 @@ GstCaps *_mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec case MEDIACODEC_AAC: 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); g_object_set(GST_OBJECT(core->codec), "compliance", -2, NULL); } else { @@ -1656,17 +1644,7 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo static gint _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *mcbuffer) { - gint ret = MC_ERROR_NONE; - - MEDIACODEC_FENTER(); - - ret = gst_app_src_push_buffer(GST_APP_SRC(core->appsrc), mcbuffer->buffer); - LOGD("pushed buffer to appsrc : %p, buffer of size %" G_GSIZE_FORMAT "", - mcbuffer->buffer, gst_buffer_get_size(mcbuffer->buffer)); - - MEDIACODEC_FLEAVE(); - - return ret; + return gst_app_src_push_buffer(GST_APP_SRC(core->appsrc), mcbuffer->buffer); } media_packet_h _mc_get_input_buffer(mc_gst_core_t *core) @@ -1753,14 +1731,14 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) } /* create basic core elements */ - ret = _mc_gst_create_pipeline(mc_handle->core, factory_name); + ret = _mc_gst_create_pipeline(new_core, factory_name); if (ret != MC_ERROR_NONE) { LOGE("failed to create pipeline"); return ret; } /* link vtable */ - ret = _mc_link_vtable(mc_handle->core, id, encoder, hardware); + ret = _mc_link_vtable(new_core, id, encoder, hardware); if (ret != MC_ERROR_NONE) { LOGE("vtable link failed"); return ret; @@ -3397,33 +3375,6 @@ const gchar * _mc_bit_to_string(int bit) } } -int _mc_get_support_bit_from_format(media_format_mimetype_e format) -{ - gint bit = 0; - - switch (format) { - case MEDIA_FORMAT_PCM_S16LE: - case MEDIA_FORMAT_PCM_S16BE: - case MEDIA_FORMAT_PCM_U16LE: - case MEDIA_FORMAT_PCM_U16BE: - bit = 16; - break; - case MEDIA_FORMAT_PCM_S32LE: - case MEDIA_FORMAT_PCM_S32BE: - case MEDIA_FORMAT_PCM_U32LE: - case MEDIA_FORMAT_PCM_U32BE: - case MEDIA_FORMAT_PCM_F32LE: - case MEDIA_FORMAT_PCM_F32BE: - bit = 32; - break; - default: - LOGE("NOT SUPPORTED!!!!"); - break; - } - - return bit; -} - int _mc_get_mime(mc_gst_core_t *core) { media_format_mimetype_e mime = MEDIA_FORMAT_MAX; -- 2.7.4 From 06263b0fe5c2e3e5485e6c6ab4a3d4dca6e7a846 Mon Sep 17 00:00:00 2001 From: Sejun Park Date: Fri, 6 Apr 2018 16:21:32 +0900 Subject: [PATCH 04/16] Fixed a problem when packet with codec config flag queued Change-Id: I1051324d90fc2ba1125b51b706f2ab25a37e82c8 --- packaging/capi-media-codec.spec | 2 +- src/media_codec_port_gst.c | 44 +++++++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 0d2a3bb..88d1a85 100755 --- 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.5.10 +Version: 0.5.11 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index 753b309..a9ea98a 100755 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -80,7 +80,7 @@ static void __csc_tiled_to_linear_crop(unsigned char *yuv420_dest, static void _mc_send_eos_signal(mc_gst_core_t *core); static void _mc_wait_for_eos(mc_gst_core_t *core); static int _mc_get_mime(mc_gst_core_t *core); -static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer); +static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool codec_config); GstCaps *_mc_gst_vid_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index); GstCaps *_mc_gst_aud_caps_new(mc_gst_core_t *core, mediacodec_codec_type_e codec_id, gint index); @@ -1129,7 +1129,7 @@ gboolean _mc_update_packet_info(mc_gst_core_t *core, media_format_h format) return is_format_change; } -static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer) +static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer, bool codec_config) { MEDIACODEC_FENTER(); @@ -1142,23 +1142,29 @@ static int _mc_set_codec_data(mc_gst_core_t *core, GstMCBuffer *mcbuffer) case MEDIACODEC_AAC: case MEDIACODEC_AAC_HE: case MEDIACODEC_AAC_HE_PS: - ret = __mc_set_caps_codecdata(core, mcbuffer, AAC_CODECDATA_SIZE); - if (ret != MC_ERROR_NONE) - LOGW("__mc_set_caps_codecdata failed"); + if (codec_config) { + ret = __mc_set_caps_codecdata(core, mcbuffer, AAC_CODECDATA_SIZE); + if (ret != MC_ERROR_NONE) + LOGW("__mc_set_caps_codecdata failed"); + } break; case MEDIACODEC_WMAV1: case MEDIACODEC_WMAV2: case MEDIACODEC_WMAPRO: case MEDIACODEC_WMALSL: - ret = __mc_set_caps_codecdata(core, mcbuffer, WMA_CODECDATA_SIZE); - if (ret != MC_ERROR_NONE) - LOGW("__mc_set_caps_codecdata failed"); + if (codec_config) { + ret = __mc_set_caps_codecdata(core, mcbuffer, WMA_CODECDATA_SIZE); + if (ret != MC_ERROR_NONE) + LOGW("__mc_set_caps_codecdata failed"); + } break; case MEDIACODEC_VORBIS: case MEDIACODEC_FLAC: - ret = __mc_set_caps_streamheader(core, mcbuffer, VORBIS_CODECDATA_SIZE); - if (ret != MC_ERROR_NONE) - LOGW("__mc_set_caps_streamheader failed"); + if (codec_config) { + ret = __mc_set_caps_streamheader(core, mcbuffer, VORBIS_CODECDATA_SIZE); + if (ret != MC_ERROR_NONE) + LOGW("__mc_set_caps_streamheader failed"); + } break; case MEDIACODEC_H264: case MEDIACODEC_MPEG4: @@ -1237,12 +1243,14 @@ static gpointer feed_task(gpointer data) input_buffer = NULL; if (codec_config || initiative) { - GstPad *pad; - ret = _mc_set_codec_data(core, mcbuffer); - if (ret != MC_ERROR_NONE) { - LOGE("failed to set codec data"); - gst_buffer_unref(mcbuffer->buffer); - goto ERROR; + GstPad *pad = NULL; + if (!core->encoder) { + ret = _mc_set_codec_data(core, mcbuffer, codec_config); + if (ret != MC_ERROR_NONE) { + LOGE("failed to set codec data"); + gst_buffer_unref(mcbuffer->buffer); + goto ERROR; + } } pad = gst_element_get_static_pad(core->appsrc, "src"); gst_pad_push_event(pad, gst_event_new_stream_start("start")); @@ -1257,6 +1265,7 @@ static gpointer feed_task(gpointer data) g_object_set(core->appsrc, "caps", caps, NULL); gst_caps_unref(caps); LOGD("caps updated"); + is_format_change = FALSE; } @@ -1747,6 +1756,7 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) /* set caps in capsfilter as default*/ caps = new_core->mc_caps_new(new_core, id, out_port_index); + new_core->caps = caps; /* FIXME will parse input format from ini. format is needed when linking elements*/ if (new_core->video && new_core->encoder) { gchar *format = NULL; -- 2.7.4 From 7840c0abe4e500193d266a8265a2e6ef7688a510 Mon Sep 17 00:00:00 2001 From: Sejun Park Date: Thu, 12 Apr 2018 10:49:55 +0900 Subject: [PATCH 05/16] Added offset to check for discontinuity when timestamp is not available Change-Id: Ia09e5a8c92630e6035e178fd42b6a665c8b766bd --- include/media_codec_port_gst.h | 1 + packaging/capi-media-codec.spec | 2 +- src/media_codec_port_gst.c | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/media_codec_port_gst.h b/include/media_codec_port_gst.h index 4d9198f..2888192 100755 --- a/include/media_codec_port_gst.h +++ b/include/media_codec_port_gst.h @@ -138,6 +138,7 @@ struct _mc_gst_core_t { guint prepare_count; guint num_live_buffers; guint etb_count; + gint64 offset; mediacodec_codec_type_e codec_id; media_format_mimetype_e out_mime; diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 88d1a85..5c09524 100755 --- 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.5.11 +Version: 0.5.12 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index a9ea98a..5036d3e 100755 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -1257,6 +1257,7 @@ static gpointer feed_task(gpointer data) gst_object_unref(pad); is_format_change = TRUE; initiative = FALSE; + core->offset = GST_BUFFER_OFFSET_NONE; } if (is_format_change) { @@ -2450,6 +2451,11 @@ GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet media_packet_get_duration(packet, &dur); GST_BUFFER_DURATION(mcbuffer->buffer) = dur; + GST_BUFFER_OFFSET(mcbuffer->buffer) = core->offset; + + core->offset += buf_size; + GST_BUFFER_OFFSET_END(mcbuffer->buffer) = core->offset; + return mcbuffer; } -- 2.7.4 From 41162f9d3827a7fa06a976ebbe0eca32e9354a70 Mon Sep 17 00:00:00 2001 From: Sejun Park Date: Thu, 3 May 2018 10:51:41 +0900 Subject: [PATCH 06/16] [ACR-1217] Added enum for resource conflict Change-Id: I5029960a6024f9b4710928808a555012f38476eb --- doc/media_codec_doc.h | 2 +- include/media_codec.h | 106 ++++++++++++++++++++++------------------ packaging/capi-media-codec.spec | 2 +- src/media_codec.c | 11 ++--- 4 files changed, 65 insertions(+), 56 deletions(-) diff --git a/doc/media_codec_doc.h b/doc/media_codec_doc.h index 36a1586..1c41347 100755 --- a/doc/media_codec_doc.h +++ b/doc/media_codec_doc.h @@ -35,7 +35,7 @@ * * @section CAPI_MEDIA_CODEC_FEATURE Related Features * This API is related with the following features:\n - * - %http://tizen.org/feature/multimedia.media_codec:\n + * - %http://tizen.org/feature/multimedia.media_codec\n * * It is recommended to design feature related codes in your application for reliability.\n * diff --git a/include/media_codec.h b/include/media_codec.h index 835cbec..5626215 100755 --- a/include/media_codec.h +++ b/include/media_codec.h @@ -43,7 +43,7 @@ extern "C" { typedef struct mediacodec_s *mediacodec_h; /** - * @brief Enumeration of media codec support type + * @brief Enumeration of media codec support type. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @remarks If this codec is to be used as an encoder or decoder, the codec flag must be set to #MEDIACODEC_ENCODER or * #MEDIACODEC_DECODER. If user doesn't set optional flag, default flags will be set to #MEDIACODEC_SUPPORT_TYPE_SW. @@ -56,7 +56,7 @@ typedef enum { } mediacodec_support_type_e; /** - * @brief Enumerations of media codec type + * @brief Enumerations of media codec type. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ typedef enum { @@ -94,7 +94,7 @@ typedef enum { } mediacodec_codec_type_e; /** - * @brief Enumeration of media codec error + * @brief Enumeration of media codec error. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif */ typedef enum { @@ -118,46 +118,54 @@ typedef enum { MEDIACODEC_ERROR_BUFFER_NOT_AVAILABLE = TIZEN_ERROR_MEDIACODEC | 0x0c, /**< Not available buffer */ MEDIACODEC_ERROR_OVERFLOW_INBUFFER = TIZEN_ERROR_MEDIACODEC | 0x0d, /**< Overflow input buffer (Since @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif)*/ MEDIACODEC_ERROR_RESOURCE_OVERLOADED = TIZEN_ERROR_MEDIACODEC | 0x0e, /**< Exceed the instance limits (Since @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif)*/ + MEDIACODEC_ERROR_RESOURCE_CONFLICT = TIZEN_ERROR_MEDIACODEC | 0x0f, /**< Interrupted by a resource conflict (Since 5.0)*/ } mediacodec_error_e; /** - * @brief Enumeration of buffer status + * @brief Enumeration of buffer status. * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif */ typedef enum { - MEDIACODEC_NEED_DATA, - MEDIACODEC_ENOUGH_DATA + MEDIACODEC_NEED_DATA, /**< The internal queue is running out of data */ + MEDIACODEC_ENOUGH_DATA /**< The internal queue is full */ } mediacodec_status_e; /** - * @brief Called when the input buffer(pkt) used up. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @brief Called when the input buffer(packet) used up. * @details It will be invoked when mediacodec has used input buffer. - * @param[in] pkt The media packet handle + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @remarks The @a packet should be released using media_packet_destroy(). + * @param[in] packet The media packet handle * @param[in] user_data The user data passed from the callback registration function * @pre It will be invoked when input buffer process completed if you register this callback using mediacodec_set_input_buffer_used_cb(). * @see mediacodec_set_input_buffer_used_cb() * @see mediacodec_unset_input_buffer_used_cb() */ -typedef void (*mediacodec_input_buffer_used_cb)(media_packet_h pkt, void *user_data); +typedef void (*mediacodec_input_buffer_used_cb)(media_packet_h packet, void *user_data); /** * @brief Called when the output buffer is available. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @details It will be invoked when mediacodec has output buffer. - * @param[in] pkt The media packet handle + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @remarks The @a packet should be released using media_packet_destroy(). + * @param[in] packet The media packet handle * @param[in] user_data The user data passed from the callback registration function * @pre It will be invoked when mediacodec process completed(had output buffer) if you register this callback using mediacodec_set_fill_buffer_cb(). * @see mediacodec_set_output_buffer_available_cb() * @see mediacodec_unset_output_buffer_available_cb() */ -typedef void (*mediacodec_output_buffer_available_cb)(media_packet_h pkt, void *user_data); +typedef void (*mediacodec_output_buffer_available_cb)(media_packet_h packet, void *user_data); /** - * @brief Called when the error has occured - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @brief Called when the error has occured. * @details It will be invoked when the error has occured. - * @param[in] error_code The error code + * Following error codes can be delivered. + * #MEDIACODEC_ERROR_INTERNAL, + * #MEDIACODEC_ERROR_INVALID_STREAM, + * #MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT, + * #MEDIACODEC_ERROR_RESOURCE_CONFLICT + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @param[in] error The error code * @param[in] user_data The user data passed from the callback registration function * @pre It will be invoked when the error has occured if you register this callback using mediacodec_set_error_cb(). * @see mediacodec_set_error_cb() @@ -166,9 +174,9 @@ typedef void (*mediacodec_output_buffer_available_cb)(media_packet_h pkt, void * typedef void (*mediacodec_error_cb)(mediacodec_error_e error, void *user_data); /** - * @brief Called when there is no data to decode/encode - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @brief Called when there is no data to decode/encode. * @details It will be invoked when the end-of-stream is reached. + * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] user_data The user data passed from the callback registration function * @pre It will be invoked when the eos event generate if you register this callback using mediacodec_set_eos_cb(). * @see mediacodec_set_eos_cb() @@ -178,9 +186,10 @@ typedef void (*mediacodec_eos_cb)(void *user_data); /** * @brief Called when the mediacodec needs more data or has enough data. + * @details It is recommended that the application stops calling mediacodec_process_input() when #MEDIACODEC_ENOUGH_DATA * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif - * @details It is recommended that the application stops calling mediacodec_process_input() when MEDIACODEC_ENOUGH_DATA * is invoked. + * @param[in] status The state of the buffer * @param[in] user_data The user data passed from the callback registration function * @see mediacodec_set_buffer_status_cb() * @see mediacodec_unset_buffer_status_cb() @@ -199,7 +208,7 @@ typedef void (*mediacodec_buffer_status_cb)(mediacodec_status_e status, void *us typedef bool (*mediacodec_supported_codec_cb)(mediacodec_codec_type_e codec_type, void *user_data); /** - * @brief Creates a mediacodec handle for decoding/encoding + * @brief Creates a mediacodec handle for decoding/encoding. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @remarks you must release @a mediacodec using mediacodec_destroy().\n * Although you can create multiple mediacodec handles at the same time, @@ -253,7 +262,7 @@ int mediacodec_destroy(mediacodec_h mediacodec); int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_type, int flags); /** - * @brief Sets the default info for the video decoder + * @brief Sets the default info for the video decoder. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @param[in] width The width for video decoding. @@ -268,7 +277,7 @@ int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_ int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height); /** - * @brief Sets the default info for the video encoder + * @brief Sets the default info for the video encoder. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @remarks The frame rate is the speed of recording and the speed of playback. * If user wants the default setting for ratecontrol, set @a target_bits to @c 0. @@ -287,7 +296,7 @@ int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height); int mediacodec_set_venc_info(mediacodec_h mediacodec, int width, int height, int fps, int target_bits); /** - * @brief Sets the default info for the audio decoder + * @brief Sets the default info for the audio decoder. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @param[in] samplerate The samplerate for audio decoding. @@ -303,7 +312,7 @@ int mediacodec_set_venc_info(mediacodec_h mediacodec, int width, int height, int int mediacodec_set_adec_info(mediacodec_h mediacodec, int samplerate, int channel, int bit); /** - * @brief Sets the default info for the audio encoder + * @brief Sets the default info for the audio encoder. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @param[in] samplerate The samplerate for audio encoding. @@ -368,6 +377,8 @@ int mediacodec_configure_from_media_format(mediacodec_h mediacodec, media_format * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) + * @retval #MEDIACODEC_ERROR_RESOURCE_OVERLOADED Exceed the instance limits (Since 5.0) + * @retval #MEDIACODEC_ERROR_INTERNAL Internal error (Since 5.0) * @pre The mediacodec should call mediacodec_set_codec()and mediacodec_set_vdec_info()/mediacodec_set_venc_info() before calling mediacodec_prepare() * If the decoder is set by mediacodec_set_codec(), mediacodec_set_vdec_info() should be called. If the encoder is set by * mediacodec_set_codec(), mediacodec_set_venc_info() should be called. @@ -408,8 +419,9 @@ int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint /** * @brief Gets the decoded or encoded packet from the output queue. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @remarks The @a packet should be released using media_packet_destroy(). * @param[in] mediacodec The handle to mediacodec - * @param[out] outbuf The current output of the decoder/encoder. + * @param[out] packet The current output of the decoder/encoder. * this function passed decoded/encoded frame to output queue. * @param[in] timeOutUs The timeout in microseconds. \n * The input buffer wait up to "timeOutUs" microseconds. @@ -420,7 +432,7 @@ int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) */ -int mediacodec_get_output(mediacodec_h mediacodec, media_packet_h *outbuf, uint64_t timeOutUs); +int mediacodec_get_output(mediacodec_h mediacodec, media_packet_h *packet, uint64_t timeOutUs); /** * @brief Flushes both input and output buffers. @@ -434,7 +446,7 @@ int mediacodec_get_output(mediacodec_h mediacodec, media_packet_h *outbuf, uint6 int mediacodec_flush_buffers(mediacodec_h mediacodec); /** - * @brief set empty buffer callback the media codec for process, asynchronously. + * @brief Sets empty buffer callback the media codec for process, asynchronously. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register @@ -443,15 +455,15 @@ int mediacodec_flush_buffers(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) - * @pre mediacodec_set_input_buffer_used_cb should be called before mediacodec_preare(). - * @post mediacodec_input_buffer_used_cb will be invoked. + * @pre mediacodec_set_input_buffer_used_cb() should be called before mediacodec_preare(). + * @post mediacodec_input_buffer_used_cb() will be invoked. * @see mediacodec_set_input_buffer_used_cb() * @see mediacodec_unset_input_buffer_used_cb() */ int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_input_buffer_used_cb callback, void* user_data); /** - * @brief unset input buffer used callback the media codec for process, asynchronously. + * @brief Unsets input buffer used callback the media codec for process, asynchronously. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value @@ -463,7 +475,7 @@ int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_inpu int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec); /** - * @brief set output buffer available callback the media codec for process, asynchronously. + * @brief Sets output buffer available callback the media codec for process, asynchronously. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register @@ -472,15 +484,15 @@ int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) - * @pre mediacodec_set_output_buffer_available_cb should be called before mediacodec_preare(). - * @post mediacodec_output_buffer_available_cb will be invoked. + * @pre mediacodec_set_output_buffer_available_cb() should be called before mediacodec_preare(). + * @post mediacodec_output_buffer_available_cb() will be invoked. * @see mediacodec_set_output_buffer_available_cb() * @see mediacodec_unset_output_buffer_available_cb() */ int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacodec_output_buffer_available_cb callback, void* user_data); /** - * @brief unset output buffer available callback the media codec for process, asynchronously. + * @brief unsets output buffer available callback the media codec for process, asynchronously. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value @@ -492,7 +504,7 @@ int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacode int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec); /** - * @brief set error callback the media codec for process, asynchronously. + * @brief Sets error callback the media codec for process, asynchronously. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register @@ -501,15 +513,15 @@ int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) - * @pre mediacodec_set_error_cb should be called before mediacodec_preare(). - * @post mediacodec_error_cb will be invoked. + * @pre mediacodec_set_error_cb() should be called before mediacodec_preare(). + * @post mediacodec_error_cb() will be invoked. * @see mediacodec_set_error_cb() * @see mediacodec_unset_error_cb() */ int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callback, void* user_data); /** - * @brief unset error callback the media codec for process, asynchronously. + * @brief Unsets error callback the media codec for process, asynchronously. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value @@ -521,7 +533,7 @@ int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callbac int mediacodec_unset_error_cb(mediacodec_h mediacodec); /** - * @brief set eos callback the media codec for process, asynchronously. + * @brief Sets eos callback the media codec for process, asynchronously. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register @@ -530,15 +542,15 @@ int mediacodec_unset_error_cb(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) - * @pre mediacodec_set_eos_cb should be called before mediacodec_preare(). - * @post mediacodec_eos_cb will be invoked. + * @pre mediacodec_set_eos_cb() should be called before mediacodec_preare(). + * @post mediacodec_eos_cb() will be invoked. * @see mediacodec_set_eos_cb() * @see mediacodec_unset_eos_cb() */ int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, void* user_data); /** - * @brief unset eos callback the media codec for process, asynchronously. + * @brief unsets eos callback the media codec for process, asynchronously. * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value @@ -550,7 +562,7 @@ int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, v int mediacodec_unset_eos_cb(mediacodec_h mediacodec); /** - * @brief Registers a callback function to be invoked when the mediacodec needs more data or has enough data. + * @brief Sets a callback function to be invoked when the mediacodec needs more data or has enough data. * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register @@ -559,15 +571,15 @@ int mediacodec_unset_eos_cb(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device (Since 4.0) - * @pre mediacodec_set_buffer_status_cb should be called before mediacodec_preare(). - * @post mediacodec_buffer_status_cb will be invoked. + * @pre mediacodec_set_buffer_status_cb() should be called before mediacodec_preare(). + * @post mediacodec_buffer_status_cb() will be invoked. * @see mediacodec_set_buffer_status_cb() * @see mediacodec_unset_buffer_status_cb() */ int mediacodec_set_buffer_status_cb(mediacodec_h mediacodec, mediacodec_buffer_status_cb callback, void* user_data); /** - * @brief Unregisters the callback function. + * @brief Unsets the callback function. * @since_tizen @if MOBILE 2.4 @elseif WEARABLE 3.0 @endif * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value @@ -597,7 +609,7 @@ int mediacodec_foreach_supported_codec(mediacodec_h mediacodec, mediacodec_suppo * @param[in] mediacodec The handle to mediacodec * @param[in] codec_type The identifier of the codec type of the encoder. * @param[in] encoder Whether the encoder or decoder : (@c true = encoder, @c false = decoder). - * @param[out] support_type (@c MEDIACODEC_SUPPORT_TYPE_HW = mediacodec can be performed with hardware codec, @c MEDIACODEC_SUPPORT_TYPE_SW = mediacodec can be performed with software codec) + * @param[out] support_type (@c #MEDIACODEC_SUPPORT_TYPE_HW = mediacodec can be performed with hardware codec, @c #MEDIACODEC_SUPPORT_TYPE_SW = mediacodec can be performed with software codec) * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 5c09524..daabadd 100755 --- 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.5.12 +Version: 0.5.13 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_codec.c b/src/media_codec.c index 526c1b3..b76269a 100644 --- a/src/media_codec.c +++ b/src/media_codec.c @@ -327,6 +327,7 @@ int mediacodec_prepare(mediacodec_h mediacodec) 1, &resource); if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) switch (rm_ret) { + LOGE("Failed to acquire resource manager %x", rm_ret); case MM_RESOURCE_MANAGER_ERROR_NOT_SUPPORTED: return MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE; case MM_RESOURCE_MANAGER_ERROR_NOT_ENOUGH: @@ -338,12 +339,8 @@ int mediacodec_prepare(mediacodec_h mediacodec) rm_ret = mm_resource_manager_commit(resource_manager); if (rm_ret != MM_RESOURCE_MANAGER_ERROR_NONE) { mm_resource_manager_mark_for_release(resource_manager, resource); - switch (rm_ret) { - case MM_RESOURCE_MANAGER_ERROR_LOW_PRIORITY: - return MEDIACODEC_ERROR_RESOURCE_OVERLOADED; - default: - return MEDIACODEC_ERROR_INTERNAL; - } + LOGE("Failed to commit resource manager : %x", rm_ret); + return MEDIACODEC_ERROR_INTERNAL; } handle->codec_resource = resource; @@ -711,7 +708,7 @@ static int __mediacodec_resource_release_cb(mm_resource_manager_h rm, */ handle->codec_resource = NULL; mediacodec_unprepare((mediacodec_h)handle); - __mediacodec_error_cb(MEDIACODEC_ERROR_RESOURCE_OVERLOADED, handle); + __mediacodec_error_cb(MEDIACODEC_ERROR_RESOURCE_CONFLICT, handle); break; } } -- 2.7.4 From 40784902baada12295340f66f82df0d2397d53a3 Mon Sep 17 00:00:00 2001 From: Sejun Park Date: Tue, 21 Aug 2018 17:58:03 +0900 Subject: [PATCH 07/16] Apply tizen allocator to mediacodec Change-Id: I4304b314d499fb53d694b330eaf391cccbc54c98 --- CMakeLists.txt | 4 +- include/media_codec_port_gst.h | 2 + packaging/capi-media-codec.spec | 2 +- src/media_codec_port_gst.c | 214 ++++++++++------------------------------ 4 files changed, 55 insertions(+), 167 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc41164..217ee07 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ 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 mm-resource-manager" ) -SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 mm-resource-manager" ) +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 mm-resource-manager gstreamer-allocators-1.0" ) +SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 mm-resource-manager gstreamer-allocators-1.0" ) INCLUDE(FindPkgConfig) pkg_check_modules(${fw_name} REQUIRED ${dependents}) diff --git a/include/media_codec_port_gst.h b/include/media_codec_port_gst.h index 2888192..18010d4 100755 --- a/include/media_codec_port_gst.h +++ b/include/media_codec_port_gst.h @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -151,6 +152,7 @@ struct _mc_gst_core_t { GstBuffer *codec_data; GstCaps* (*mc_caps_new)(mc_gst_core_t *, mediacodec_codec_type_e, gint); + GstAllocator *allocator; void* user_cb[_MEDIACODEC_EVENT_TYPE_NUM]; void* user_data[_MEDIACODEC_EVENT_TYPE_NUM]; diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index daabadd..6f405a3 100755 --- 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.5.13 +Version: 0.6.0 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index 5036d3e..5d09f4b 100755 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -48,7 +48,7 @@ static gchar *__mc_get_gst_input_format(media_format_mimetype_e mimetype, bool i static GstMCBuffer *__mc_gst_make_media_packet(mc_gst_core_t *core, GstBuffer *buffer); static gboolean __mc_gst_bus_callback(GstBus *bus, GstMessage *msg, gpointer data); static GstBusSyncReply __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data); -static MMVideoBuffer *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, media_packet_h packet); +static GstMemory *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, GstMCBuffer *mcbuffer); static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_h packet, uint64_t size); static void __mc_input_buffer_finalize_cb(GstMCBuffer *buffer); static int __mc_set_caps_streamheader(mc_gst_core_t *core, GstMCBuffer *mcbuffer, guint streamheader_size); @@ -168,7 +168,7 @@ int __mc_fill_inbuf_with_mm_video_buffer(mc_gst_core_t *core, media_packet_h pac { gint ret = MC_ERROR_NONE; uint64_t buf_size = 0; - MMVideoBuffer *mm_vbuffer = NULL; + GstMemory *mem; void *buf_data = NULL; ret = media_packet_get_buffer_size(packet, &buf_size); @@ -183,21 +183,15 @@ int __mc_fill_inbuf_with_mm_video_buffer(mc_gst_core_t *core, media_packet_h pac return MC_ERROR; } - mm_vbuffer = __mc_gst_make_tbm_buffer(core, mcbuffer->packet); - - if (mm_vbuffer != NULL) { - gst_buffer_prepend_memory(mcbuffer->buffer, - gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, mm_vbuffer, sizeof(*mm_vbuffer), 0, - sizeof(*mm_vbuffer), mm_vbuffer, free)); - LOGD("mm_vbuffer appended, %d, %d", sizeof(*mm_vbuffer), gst_buffer_n_memory(mcbuffer->buffer)); + mem = __mc_gst_make_tbm_buffer(core, mcbuffer); + if (mem == NULL) { + LOGW("Failed to make tizen memory"); + return MC_ERROR; } - if (buf_data != NULL) { - gst_buffer_prepend_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, %d, %d", buf_size, gst_buffer_n_memory(mcbuffer->buffer)); - } + gst_buffer_append_memory(mcbuffer->buffer, mem); + LOGD("tizen memory appended"); + return ret; } @@ -359,21 +353,17 @@ int __mc_fill_input_buffer_with_venc_packet(mc_gst_core_t *core, media_packet_h } } } else { - MMVideoBuffer *mm_video_buffer = NULL; - - mm_video_buffer = __mc_gst_make_tbm_buffer(core, packet); + GstMemory *mem = NULL; - gst_buffer_prepend_memory(mcbuffer->buffer, - gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, mm_video_buffer, sizeof(MMVideoBuffer), 0, - sizeof(MMVideoBuffer), mm_video_buffer, free)); + mem = __mc_gst_make_tbm_buffer(core, mcbuffer); + if (mem == NULL) { + LOGW("Failed to make tizen memory"); + return MC_ERROR; + } - LOGD("mm_video_buffer appended, %d, %d", sizeof(MMVideoBuffer), gst_buffer_n_memory(mcbuffer->buffer)); + gst_buffer_append_memory(mcbuffer->buffer, mem); + LOGD("tizen memory appended"); } - - gst_buffer_prepend_memory(mcbuffer->buffer, - gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, planes[0], mcbuffer->buf_size, 0, - mcbuffer->buf_size, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb)); - return ret; } @@ -447,45 +437,7 @@ int __mc_fill_vdec_packet_with_output_buffer(mc_gst_core_t *core, void *data, in tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, bo, 1); } else { - int bo_num = 0; - MMVideoBuffer *mm_vbuffer = NULL; - mm_vbuffer = (MMVideoBuffer *)data; - - if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) { - tbm_surface_info_s tsurf_info; - memset(&tsurf_info, 0x0, sizeof(tbm_surface_info_s)); - - /* create tbm surface */ - for (i = 0; i < MM_VIDEO_BUFFER_PLANE_MAX; i++) { - if (mm_vbuffer->handle.bo[i]) { - bo_num++; - tsurf_info.planes[i].stride = mm_vbuffer->stride_width[i]; - } - } - - if (bo_num > 0) { - tsurf_info.width = port_def->info.video.width; - tsurf_info.height = port_def->info.video.height; - tsurf_info.format = TBM_FORMAT_NV12; /* bo_format */ - tsurf_info.bpp = tbm_surface_internal_get_bpp(TBM_FORMAT_NV12); - tsurf_info.num_planes = tbm_surface_internal_get_num_planes(TBM_FORMAT_NV12); - tsurf_info.size = 0; - - for (i = 0; i < tsurf_info.num_planes; i++) { - tsurf_info.planes[i].stride = mm_vbuffer->stride_width[i]; - tsurf_info.planes[i].size = mm_vbuffer->stride_width[i] * mm_vbuffer->stride_height[i]; - - if (i < bo_num) - tsurf_info.planes[i].offset = 0; - else - tsurf_info.planes[i].offset = tsurf_info.planes[i-1].offset + tsurf_info.planes[i - 1].size; - - tsurf_info.size += tsurf_info.planes[i].size; - LOGD("%d plane stride : %d, size : %d", i, tsurf_info.planes[i].stride, tsurf_info.planes[i].size); - } - tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, (tbm_bo *)mm_vbuffer->handle.bo, bo_num); - } - } + tsurf = (tbm_surface_h)data; } if (tsurf) { @@ -966,6 +918,7 @@ mc_gst_core_t *mc_gst_core_new() g_atomic_int_set(&core->available_queue->running, 1); core->available_queue->thread = g_thread_new("feed thread", &feed_task, core); + core->allocator = gst_tizen_allocator_new(); core->bufmgr = NULL; core->drm_fd = -1; @@ -999,6 +952,11 @@ void mc_gst_core_free(mc_gst_core_t *core) mc_async_queue_free(async_queue->input); g_free(async_queue); + if (core->allocator) { + gst_object_unref(core->allocator); + core->allocator = NULL; + } + if (core->codec_data) gst_buffer_unref(core->codec_data); @@ -2328,36 +2286,11 @@ void __mc_gst_buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gp int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data) { - int i = 0; - guint n; - GstMemory *mem; - GstMapInfo map = GST_MAP_INFO_INIT; - MMVideoBuffer *mm_video_buf = NULL; - MEDIACODEC_FENTER(); GstMCBuffer *mcbuffer = (GstMCBuffer *)user_data; - if (mcbuffer->buffer) { - n = gst_buffer_n_memory(mcbuffer->buffer); - - if (n > 1) { - mem = gst_buffer_peek_memory(mcbuffer->buffer, n-1); - gst_memory_map(mem, &map, GST_MAP_READ); - mm_video_buf = (MMVideoBuffer *)map.data; - - if (!mm_video_buf) { - LOGW("gstbuffer map.data is null"); - } else { - for (i = 0; i < MM_VIDEO_BUFFER_PLANE_MAX; i++) { - if (mm_video_buf->handle.bo[i]) - tbm_bo_unref(mm_video_buf->handle.bo[i]); - } - } - gst_memory_unmap(mem, &map); - } - gst_buffer_unref((GstBuffer *)mcbuffer->buffer); - } + gst_buffer_unref((GstBuffer *)mcbuffer->buffer); if (mcbuffer->ext_mem) { g_free(mcbuffer->ext_mem); @@ -2462,10 +2395,12 @@ GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, media_packet GstMCBuffer *__mc_gst_make_media_packet(mc_gst_core_t *core, GstBuffer *buffer) { gint ret = MEDIA_PACKET_ERROR_NONE; - guint n; GstMemory *mem; GstMapInfo map = GST_MAP_INFO_INIT; GstMCBuffer *mcbuffer = NULL; + void *data = NULL; + gint size = 0; + mcbuffer = (GstMCBuffer *)g_malloc0(sizeof(*mcbuffer)); @@ -2474,24 +2409,27 @@ GstMCBuffer *__mc_gst_make_media_packet(mc_gst_core_t *core, GstBuffer *buffer) return NULL; } - n = gst_buffer_n_memory(buffer); + mem = gst_buffer_peek_memory(buffer, 0); - mem = gst_buffer_peek_memory(buffer, n-1); - - gst_memory_map(mem, &map, GST_MAP_READ); + if (gst_is_tizen_memory(mem)) { + data = (void *)gst_tizen_memory_get_surface(mem); + size = tbm_surface_internal_get_size((tbm_surface_h)data); + } else { + gst_memory_map(mem, &map, GST_MAP_READ); + data = map.data; + size = map.size; + gst_memory_unmap(mem, &map); + } mcbuffer->buffer = buffer; mcbuffer->core = core; - mcbuffer->buf_size = map.size; + mcbuffer->buf_size = size; - LOGD("n : %d, map.data : %p, map.size : %d", n, map.data, map.size); - ret = __mc_fill_output_buffer(core, map.data, map.size, mcbuffer); + ret = __mc_fill_output_buffer(core, data, mcbuffer->buf_size, mcbuffer); if (ret != MC_ERROR_NONE) { LOGW("failed to fill outbuf: %s (ox%08x)", _mc_error_to_string(ret), ret); - gst_memory_unmap(mem, &map); return NULL; } - gst_memory_unmap(mem, &map); return mcbuffer; } @@ -2689,85 +2627,33 @@ static GstBusSyncReply __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, return reply; } -static MMVideoBuffer *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, media_packet_h packet) +static GstMemory *__mc_gst_make_tbm_buffer(mc_gst_core_t *core, GstMCBuffer *mcbuffer) { - gint i; - gint num_bos; - gint err; int ret = MEDIA_PACKET_ERROR_NONE; tbm_surface_h surface = NULL; - tbm_surface_info_s surface_info; - tbm_bo_handle handle_bo; + GstVideoInfo vinfo; + GstMemory *mem = NULL; - if (!packet) { + if (!mcbuffer->packet) { LOGE("output is null"); return NULL; } - MMVideoBuffer *mm_vbuffer = NULL; - mm_vbuffer = (MMVideoBuffer *)malloc(sizeof(MMVideoBuffer)); - if (!mm_vbuffer) { - LOGE("Failed to alloc MMVideoBuffer"); - return NULL; - } - memset(mm_vbuffer, 0x00, sizeof(MMVideoBuffer)); - - ret = media_packet_get_tbm_surface(packet, &surface); + ret = media_packet_get_tbm_surface(mcbuffer->packet, &surface); if (ret != MEDIA_PACKET_ERROR_NONE) { LOGE("Failed to get tbm surface"); - free(mm_vbuffer); return NULL; } - num_bos = tbm_surface_internal_get_num_bos(surface); - err = tbm_surface_get_info((tbm_surface_h)surface, &surface_info); - if (err != TBM_SURFACE_ERROR_NONE) { - LOGE("get tbm surface is failed"); - free(mm_vbuffer); + if (!gst_video_info_from_caps(&vinfo, core->caps)) { + LOGE("Failed to get video info"); return NULL; } - for (i = 0; i < num_bos; i++) { - mm_vbuffer->handle.bo[i] = tbm_surface_internal_get_bo(surface, i); - LOGD("mm_vbuffer->handle.bo[%d] : %p", i, mm_vbuffer->handle.bo[i]); - tbm_bo_map(mm_vbuffer->handle.bo[i], TBM_DEVICE_CPU, TBM_OPTION_READ); - tbm_bo_unmap(mm_vbuffer->handle.bo[i]); - } - - mm_vbuffer->type = MM_VIDEO_BUFFER_TYPE_TBM_BO; - mm_vbuffer->width[0] = surface_info.width; - mm_vbuffer->height[0] = surface_info.height; - mm_vbuffer->width[1] = surface_info.width; - mm_vbuffer->height[1] = surface_info.height>>1; - mm_vbuffer->size[0] = surface_info.planes[0].size; - mm_vbuffer->size[1] = surface_info.planes[1].size; - mm_vbuffer->stride_width[0] = surface_info.planes[0].stride; - mm_vbuffer->stride_height[0] = surface_info.planes[0].size / surface_info.planes[0].stride; - mm_vbuffer->stride_width[1] = surface_info.planes[1].stride; - mm_vbuffer->stride_height[1] = surface_info.planes[1].size / surface_info.planes[1].stride; - - if (mm_vbuffer->handle.bo[0]) { - handle_bo = tbm_bo_get_handle(mm_vbuffer->handle.bo[0], TBM_DEVICE_CPU); - mm_vbuffer->data[0] = handle_bo.ptr; - - handle_bo = tbm_bo_get_handle(mm_vbuffer->handle.bo[0], TBM_DEVICE_MM); - mm_vbuffer->handle.dmabuf_fd[0] = handle_bo.u32; - } - - if (mm_vbuffer->handle.bo[1]) { - handle_bo = tbm_bo_get_handle(mm_vbuffer->handle.bo[1], TBM_DEVICE_CPU); - mm_vbuffer->data[1] = handle_bo.ptr; - - handle_bo = tbm_bo_get_handle(mm_vbuffer->handle.bo[1], TBM_DEVICE_MM); - mm_vbuffer->handle.dmabuf_fd[1] = handle_bo.u32; - } else { - mm_vbuffer->data[1] = mm_vbuffer->data[0] + mm_vbuffer->stride_width[0] * mm_vbuffer->stride_height[0]; - } - mm_vbuffer->plane_num = 2; - - LOGD("size[0] : %d, size[1] : %d, bo[0] :%p, bo[1] :%p", mm_vbuffer->size[0], mm_vbuffer->size[1], mm_vbuffer->handle.bo[0], mm_vbuffer->handle.bo[1]); + mem = gst_tizen_allocator_alloc_surface(core->allocator, + &vinfo, surface, mcbuffer, (GDestroyNotify)__mc_input_buffer_finalize_cb); - return mm_vbuffer; + return mem; } static void __mc_input_buffer_finalize_cb(GstMCBuffer *mcbuffer) -- 2.7.4 From e5dd80e572cb291e38f157d85208ef7f9f9c84fa Mon Sep 17 00:00:00 2001 From: SeokHoon Lee Date: Tue, 18 Sep 2018 17:09:02 +0900 Subject: [PATCH 08/16] Add gcov environment Signed-off-by: SeokHoon Lee Change-Id: I22f77c8cffa0ad72d5d377fa5cb1db43dc143e9b --- packaging/capi-media-codec.spec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 6f405a3..f74b8b7 100755 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -47,6 +47,12 @@ Requires: %{name} = %{version}-%{release} export CFLAGS="$CFLAGS -DSYSCONFDIR=\\\"%{_sysconfdir}\\\"" +%if 0%{?gcov:1} +export CFLAGS+=" -fprofile-arcs -ftest-coverage" +export CXXFLAGS+=" -fprofile-arcs -ftest-coverage" +export LDFLAGS+=" -lgcov" +%endif + MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER} -- 2.7.4 From 1b8fe3e95c2f9d55055329613cb1353a028a498e Mon Sep 17 00:00:00 2001 From: Sejun Park Date: Thu, 17 Jan 2019 17:34:42 +0900 Subject: [PATCH 09/16] fixed typo Change-Id: If48dd381aae4d820b2b9a79fbe78919d4abbe9bb --- include/media_codec.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/media_codec.h b/include/media_codec.h index 5626215..fd6da1e 100755 --- a/include/media_codec.h +++ b/include/media_codec.h @@ -157,8 +157,8 @@ typedef void (*mediacodec_input_buffer_used_cb)(media_packet_h packet, void *use typedef void (*mediacodec_output_buffer_available_cb)(media_packet_h packet, void *user_data); /** - * @brief Called when the error has occured. - * @details It will be invoked when the error has occured. + * @brief Called when the error has occurred. + * @details It will be invoked when the error has occurred. * Following error codes can be delivered. * #MEDIACODEC_ERROR_INTERNAL, * #MEDIACODEC_ERROR_INVALID_STREAM, @@ -167,7 +167,7 @@ typedef void (*mediacodec_output_buffer_available_cb)(media_packet_h packet, voi * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif * @param[in] error The error code * @param[in] user_data The user data passed from the callback registration function - * @pre It will be invoked when the error has occured if you register this callback using mediacodec_set_error_cb(). + * @pre It will be invoked when the error has occurred if you register this callback using mediacodec_set_error_cb(). * @see mediacodec_set_error_cb() * @see mediacodec_unset_error_cb() */ -- 2.7.4 From e0bb18d6870a29fa310d4205804454f8f215821f Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 2 Jul 2019 15:06:25 +0900 Subject: [PATCH 10/16] Make a gcov package for measuring coverage easier [Version] 0.6.0-1 [Issue Type] Update Change-Id: I5acb3c2a06cbfe5ad5f9c21ae58e1f9b974c2cd7 Signed-off-by: Jeongmo Yang --- packaging/capi-media-codec.spec | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index f74b8b7..ad913b6 100755 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -5,7 +5,7 @@ Name: capi-media-codec Summary: A Media Codec library in Tizen Native API Version: 0.6.0 -Release: 0 +Release: 1 Group: Multimedia/API License: Apache-2.0 Source0: %{name}-%{version}.tar.gz @@ -39,6 +39,15 @@ Requires: %{name} = %{version}-%{release} %description devel +%if 0%{?gcov:1} +%package gcov +Summary: Line Coverage of Media Codec library in Tizen Native API +Group: Development/Multimedia + +%description gcov +Collection of files related to Line Coverage. It is tested as gcov for a media codec library in Tizen native API +%endif + %prep %setup -q @@ -59,6 +68,11 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` make %{?jobs:-j%jobs} +%if 0%{?gcov:1} +mkdir -p gcov-obj +find . -name '*.gcno' -exec cp '{}' gcov-obj ';' +%endif + %install rm -rf %{buildroot} mkdir -p %{buildroot}/usr/bin @@ -66,6 +80,12 @@ cp test/media_codec_test %{buildroot}/usr/bin %make_install +%if 0%{?gcov:1} +mkdir -p %{buildroot}%{_datadir}/gcov/obj +install -m 0644 gcov-obj/* %{buildroot}%{_datadir}/gcov/obj +%endif + + %post /sbin/ldconfig @@ -85,4 +105,8 @@ cp test/media_codec_test %{buildroot}/usr/bin %{_libdir}/pkgconfig/*.pc %{_libdir}/libcapi-media-codec.so +%if 0%{?gcov:1} +%files gcov +%{_datadir}/gcov/obj/* +%endif -- 2.7.4 From 33cea5135f54206e7e2aa7719b42babfdd76351f Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Thu, 19 Sep 2019 14:33:56 +0900 Subject: [PATCH 11/16] Add media codec sync APIs for internal [Version] 0.6.1 [Profile] Common [Issue Type] New Internal API Change-Id: Ibd04deb782ecacc227fd85f7996bd989c34b3a7a Signed-off-by: Jeongmo Yang --- include/media_codec.h | 0 include/media_codec_port.h | 0 include/media_codec_port_gst.h | 0 include/media_codec_private.h | 3 +- include/media_codec_sync_internal.h | 215 ++++++++ include/media_codec_sync_private.h | 88 ++++ packaging/capi-media-codec.spec | 4 +- src/media_codec_port.c | 0 src/media_codec_port_gst.c | 0 src/media_codec_sync_internal.c | 955 ++++++++++++++++++++++++++++++++++++ 10 files changed, 1261 insertions(+), 4 deletions(-) mode change 100755 => 100644 include/media_codec.h mode change 100755 => 100644 include/media_codec_port.h mode change 100755 => 100644 include/media_codec_port_gst.h create mode 100644 include/media_codec_sync_internal.h create mode 100644 include/media_codec_sync_private.h mode change 100755 => 100644 src/media_codec_port.c mode change 100755 => 100644 src/media_codec_port_gst.c create mode 100644 src/media_codec_sync_internal.c diff --git a/include/media_codec.h b/include/media_codec.h old mode 100755 new mode 100644 diff --git a/include/media_codec_port.h b/include/media_codec_port.h old mode 100755 new mode 100644 diff --git a/include/media_codec_port_gst.h b/include/media_codec_port_gst.h old mode 100755 new mode 100644 diff --git a/include/media_codec_private.h b/include/media_codec_private.h index c574563..0057fa0 100644 --- a/include/media_codec_private.h +++ b/include/media_codec_private.h @@ -37,8 +37,7 @@ extern "C" { #define MEDIACODEC_CHECK_CONDITION(condition, error, msg) \ - if (condition) {} else \ - {LOGE("[%s] %s(0x%08x)", __FUNCTION__, msg, error); return error; }; \ + if (!(condition)) {LOGE("%s(0x%08x)", msg, error); return error; } #define MEDIACODEC_INSTANCE_CHECK(mediacodec) \ MEDIACODEC_CHECK_CONDITION(mediacodec != NULL, MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER") diff --git a/include/media_codec_sync_internal.h b/include/media_codec_sync_internal.h new file mode 100644 index 0000000..c193bb0 --- /dev/null +++ b/include/media_codec_sync_internal.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_MEDIA_CODEC_SYNC_INTERNAL_H__ +#define __TIZEN_MEDIA_CODEC_SYNC_INTERNAL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @file media_codec_sync_internal.h +* @brief This file contains the internal capi media codec sync API. +*/ + +/** +* @addtogroup CAPI_MEDIA_CODEC_SYNC_MODULE +* @{ +*/ + +/** + * @brief Media Codec Sync type handle. + * @since_tizen 5.5 + */ +typedef struct mediacodecsync_s *mediacodecsync_h; + + +typedef enum { + MEDIACODECSYNC_STATE_CREATED = 0, /**< Media codec sync is created */ + MEDIACODECSYNC_STATE_READY, /**< Media codec sync is ready to run */ + MEDIACODECSYNC_STATE_RUNNING, /**< Media codec sync is running */ + MEDIACODECSYNC_STATE_PAUSED /**< Media codec sync is paused */ +} mediacodecsync_state_e; + +typedef enum { + MEDIACODECSYNC_PACKET_TYPE_AUDIO = 0, + MEDIACODECSYNC_PACKET_TYPE_VIDEO +} mediacodecsync_packet_type_e; + +typedef void (*mediacodecsync_buffer_used_cb)(media_packet_h packet, mediacodecsync_packet_type_e type, void *user_data); + +/** + * @brief Creates a mediacodecsync handle for synchronous AV rendering. + * @since_tizen 5.5 + * @remarks you must release @a mediacodecsync using mediacodecsync_destroy().\n + * Although you can create multiple mediacodecsync handles at the same time, + * the mediacodec cannot guarantee proper operation because of limited resources, like + * audio or display device. + * + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @param[out] mediacodecsync A new handle to mediacodecsync + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @post If it succeeds, the state will be #MEDIACODECSYNC_STATE_CREATED. + */ +int mediacodecsync_create(mediacodecsync_buffer_used_cb callback, void *userdata, mediacodecsync_h *mediacodecsync); + +/** + * @brief Destroys the mediacodecsync handle and releases all its resources. + * @since_tizen 5.5 + * @param[in] mediacodecsync The handle to mediacodecsync to be destroyed. + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @pre The state should be #MEDIACODECSYNC_STATE_CREATED. + */ +int mediacodecsync_destroy(mediacodecsync_h mediacodecsync); + +/** + * @brief Sets the media format to be rendered. + * @since_tizen 5.5 + * @param[in] mediacodecsync The mediacodecsync handle + * @param[in] audio_format The #media_format_h of audio data + * @param[in] video_format The #media_format_h of video data + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE Not supported on device + * @pre The state should be #MEDIACODECSYNC_STATE_CREATED. + * @pre The media format has been created and the required values have been set. + * @see media_format_set_video_mime() + * @see media_format_set_audio_mime() + * @see media_format_set_video_width() + * @see media_format_set_video_height() + * @see media_format_set_video_avg_bps() + * @see media_format_set_video_frame_rate() + * @see media_format_set_audio_channel() + * @see media_format_set_audio_samplerate() + * @see media_format_set_audio_bit() + * @see media_format_set_audio_avg_bps() + */ +int mediacodecsync_set_format(mediacodecsync_h mediacodecsync, media_format_h audio_format, media_format_h video_format); + +/** + * @brief Prepares @a mediacodecsync for synchronous rendering. + * @since_tizen 5.5 + * @param[in] mediacodecsync The handle to mediacodecsync + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_RESOURCE_OVERLOADED Exceed the instance limits + * @retval #MEDIACODEC_ERROR_INTERNAL Internal error + * @pre The mediacodecsync should call mediacodecsync_set_format() before calling mediacodec_prepare(). + * @pre The state should be #MEDIACODECSYNC_STATE_CREATED. + * @post If it succeeds, the state will be #MEDIACODECSYNC_STATE_READY. + */ +int mediacodecsync_prepare(mediacodecsync_h mediacodecsync); + +/** + * @brief Unprepares @a mediacodecsync. + * @since_tizen 5.5 + * @param[in] mediacodecsync The handle to mediacodecsync + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @pre The state should be #MEDIACODECSYNC_STATE_READY. + * @post If it succeeds, the state will be #MEDIACODECSYNC_STATE_CREATED. + */ +int mediacodecsync_unprepare(mediacodecsync_h mediacodecsync); + +/** + * @brief Runs @a mediacodecsync. + * @since_tizen 5.5 + * @param[in] mediacodecsync The handle to mediacodecsync + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @pre The state should be #MEDIACODECSYNC_STATE_READY or #MEDIACODECSYNC_STATE_PAUSED. + * @post If it succeeds, the state will be #MEDIACODECSYNC_STATE_RUNNING. + */ +int mediacodecsync_run(mediacodecsync_h mediacodecsync); + +/** + * @brief Stops @a mediacodecsync. + * @since_tizen 5.5 + * @param[in] mediacodecsync The handle to mediacodecsync + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @pre The state should be #MEDIACODECSYNC_STATE_RUN or #MEDIACODECSYNC_STATE_PAUSED. + * @post If it succeeds, the state will be #MEDIACODECSYNC_STATE_READY. + */ +int mediacodecsync_stop(mediacodecsync_h mediacodecsync); + +/** + * @brief Pauses @a mediacodecsync. + * @since_tizen 5.5 + * @param[in] mediacodecsync The handle to mediacodecsync + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @pre The state should be #MEDIACODECSYNC_STATE_RUN. + * @post If it succeeds, the state will be #MEDIACODECSYNC_STATE_PAUSED. + */ +int mediacodecsync_pause(mediacodecsync_h mediacodecsync); + +/** + * @brief Pushes packets to render. + * @since_tizen 5.5 + * @param[in] mediacodecsync The handle to mediacodecsync + * @param[in] packet The packet to render + * @param[in] type The type of packet + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @pre The state should be #MEDIACODECSYNC_STATE_RUN. + */ +int mediacodecsync_push_packet(mediacodecsync_h mediacodecsync, media_packet_h packet, mediacodecsync_packet_type_e type); + +/** + * @brief Gets state of @a mediacodecsync. + * @since_tizen 5.5 + * @param[in] mediacodecsync The handle to mediacodecsync + * @param[out] state The state of mediacodecsync + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + */ +int mediacodecsync_get_state(mediacodecsync_h mediacodecsync, mediacodecsync_state_e *state); + +/** + * @} + */ +#ifdef __cplusplus +} +#endif +#endif /*__TIZEN_MEDIA_CODEC_INTERNAL_H__*/ diff --git a/include/media_codec_sync_private.h b/include/media_codec_sync_private.h new file mode 100644 index 0000000..2f6fa53 --- /dev/null +++ b/include/media_codec_sync_private.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_MEDIA_CODEC_SYNC_PRIVATE_H__ +#define __TIZEN_MEDIA_CODEC_SYNC_PRIVATE_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + MEDIACODECSYNC_PIPELINE = 0, + MEDIACODECSYNC_ELEMENT_APPSRC, + MEDIACODECSYNC_ELEMENT_CAPS, + MEDIACODECSYNC_ELEMENT_QUE, + MEDIACODECSYNC_ELEMENT_SINK, + MEDIACODECSYNC_ELEMENT_NUM +}; + +#define AUDIO_FORMAT_TABLE_SIZE 15 +#define VIDEO_FORMAT_TABLE_SIZE 8 + +typedef struct _format_table { + media_format_mimetype_e mime_type; + char *format_string; +} format_table; + +typedef struct _packet_info { + bool has_tbm_surface; + void *data; + uint64_t data_size; + uint64_t dts; + uint64_t pts; + uint64_t duration; +} packet_info; + +typedef struct _mediacodecsync_s { + GMutex lock; + media_format_h audio_format; + media_format_h video_format; + + GstAllocator *allocator; + GstClock *clock; + GstElement *audio_pipe[MEDIACODECSYNC_ELEMENT_NUM]; + GstElement *video_pipe[MEDIACODECSYNC_ELEMENT_NUM]; + GstCaps *video_caps; + GstVideoInfo video_info; + + mediacodecsync_buffer_used_cb buffer_used_cb; + void *buffer_used_cb_userdata; + + mediacodecsync_state_e state; +} mediacodecsync_s; + +typedef struct _GstMCSBuffer { + GstBuffer *gst_buffer; + int type; + mediacodecsync_s *handle; + media_packet_h packet; +} GstMCSBuffer; + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_MEDIA_CODEC_SYNC_PRIVATE_H__ */ diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index ad913b6..455600a 100755 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -4,8 +4,8 @@ Name: capi-media-codec Summary: A Media Codec library in Tizen Native API -Version: 0.6.0 -Release: 1 +Version: 0.6.1 +Release: 0 Group: Multimedia/API License: Apache-2.0 Source0: %{name}-%{version}.tar.gz diff --git a/src/media_codec_port.c b/src/media_codec_port.c old mode 100755 new mode 100644 diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c old mode 100755 new mode 100644 diff --git a/src/media_codec_sync_internal.c b/src/media_codec_sync_internal.c new file mode 100644 index 0000000..5d95d6f --- /dev/null +++ b/src/media_codec_sync_internal.c @@ -0,0 +1,955 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "TIZEN_N_MEDIACODECSYNC" + +#define PIPELINE_NAME_AUDIO "MEDIACODECSYNC_AUDIO" +#define PIPELINE_NAME_VIDEO "MEDIACODECSYNC_VIDEO" + +#define _MEDIACODECSYNC_PIPELINE_MAKE(handle, pipeline, name) \ + do { \ + if (pipeline) { \ + gst_object_unref(pipeline); \ + pipeline = NULL; \ + } \ + pipeline = gst_pipeline_new(name); \ + if (!pipeline) { \ + LOGE("create pipeline[%s] failed", name); \ + goto _CREATE_PIPELINE_FAILED; \ + } \ + g_object_weak_ref(G_OBJECT(pipeline), (GWeakNotify)__mediacodecsync_element_release_noti, handle); \ + LOGD("create pipeline [%s] done", name); \ + } while (0) + +#define _MEDIACODECSYNC_ELEMENT_MAKE(handle, element, name, prefix, nick) \ + do { \ + char nick_name[24]; \ + if (element) { \ + gst_object_unref(element); \ + element = NULL; \ + } \ + snprintf(nick_name, sizeof(nick_name), "%s%s", prefix, nick); \ + element = gst_element_factory_make(name, nick_name); \ + if (!element) { \ + LOGE("create element[%s,%s] failed", name, nick_name); \ + goto _CREATE_PIPELINE_FAILED; \ + } \ + g_object_weak_ref(G_OBJECT(element), (GWeakNotify)__mediacodecsync_element_release_noti, handle); \ + LOGD("create element [%s,%s] done", name, nick_name); \ + } while (0) + +#define _MEDIACODECSYNC_ELEMENT_REMOVE(element) \ + do { \ + if (element != NULL) \ + gst_object_unref(element); \ + } while (0) + + + +static void __mediacodecsync_need_audio_data_cb(GstElement *appsrc, guint size, gpointer data) +{ + /*mediacodecsync_s *handle = (mediacodecsync_s *)data;*/ + + LOGI("audio data is needed"); +} + + +static void __mediacodecsync_enough_audio_data_cb(GstElement *appsrc, gpointer data) +{ + /*mediacodecsync_s *handle = (mediacodecsync_s *)data;*/ + + LOGI("audio data is enough"); +} + + +static void __mediacodecsync_need_video_data_cb(GstElement *appsrc, guint size, gpointer data) +{ + /*mediacodecsync_s *handle = (mediacodecsync_s *)data;*/ + + LOGI("video data is needed"); +} + + +static void __mediacodecsync_enough_video_data_cb(GstElement *appsrc, gpointer data) +{ + /*mediacodecsync_s *handle = (mediacodecsync_s *)data;*/ + + LOGI("video data is enough"); +} + + +static int _mediacodecsync_get_packet_info(media_packet_h packet, packet_info *info) +{ + int ret = MEDIACODEC_ERROR_NONE; + bool has_tbm_surface = false; + void *data = NULL; + uint64_t data_size = 0; + uint64_t dts = 0; + uint64_t pts = 0; + uint64_t duration = 0; + + if (!packet || !info) { + LOGE("NULL params %p %p", packet, info); + return MEDIACODEC_ERROR_INVALID_PARAMETER; + } + + /* get packet info */ + ret = media_packet_has_tbm_surface_buffer(packet, &has_tbm_surface); + ret |= media_packet_get_buffer_data_ptr(packet, &data); + ret |= media_packet_get_buffer_size(packet, &data_size); + ret |= media_packet_get_dts(packet, &dts); + ret |= media_packet_get_pts(packet, &pts); + ret |= media_packet_get_duration(packet, &duration); + + if (ret == MEDIACODEC_ERROR_NONE) { + info->has_tbm_surface = has_tbm_surface; + info->data = data; + info->data_size = data_size; + info->dts = dts; + info->pts = pts; + info->duration = duration; + + LOGI("packet info[%u], %p, size %"PRIu64", dts %"PRIu64", pts %"PRIu64", duration %"PRIu64, + has_tbm_surface, data, data_size, dts, pts, duration); + } + + return ret; +} + + +static void _mediacodecsync_gst_buffer_finalize(GstMCSBuffer *mcs_buffer) +{ + mediacodecsync_s *handle = NULL; + + if (!mcs_buffer || !mcs_buffer->handle) { + LOGE("NULL buffer(%p) or handle", mcs_buffer); + return; + } + + handle = mcs_buffer->handle; + + LOGI("[type %d] mcs_buffer %p, gst buffer %p, packet %p", + mcs_buffer->type, mcs_buffer, mcs_buffer->gst_buffer, mcs_buffer->packet); + + if (mcs_buffer->packet) { + if (handle->buffer_used_cb) + handle->buffer_used_cb(mcs_buffer->packet, mcs_buffer->type, handle->buffer_used_cb_userdata); + else + LOGE("No buffer used callback"); + } + + free(mcs_buffer); +} + + +static GstMCSBuffer *_mediacodecsync_gst_buffer_new(mediacodecsync_s *handle, media_packet_h packet, int type) +{ + GstMCSBuffer *new_buffer = NULL; + GstMemory *memory = NULL; + tbm_surface_h tbm_surface = NULL; + packet_info info; + + if (!handle || !packet) { + LOGE("invalid params %p, %p", handle, packet); + return NULL; + } + + /* get packet info */ + if (_mediacodecsync_get_packet_info(packet, &info) != MEDIA_PACKET_ERROR_NONE) { + LOGE("_mediacodecsync_get_packet_info failed"); + return NULL; + } + + new_buffer = (GstMCSBuffer *)calloc(1, sizeof(GstMCSBuffer)); + if (!new_buffer) { + LOGE("GstMCSBuffer alloc failed"); + return NULL; + } + + new_buffer->gst_buffer = gst_buffer_new(); + new_buffer->type = type; + new_buffer->packet = packet; + new_buffer->handle = handle; + + if (info.has_tbm_surface) { + /* get tbm surface from packet */ + if (media_packet_get_tbm_surface(packet, &tbm_surface) != MEDIA_PACKET_ERROR_NONE) { + LOGE("get tbm surface failed"); + goto _BUFFER_NEW_FAILED; + } + + /* create tizen memory for gst buffer with tbm surface */ + memory = gst_tizen_allocator_alloc_surface(handle->allocator, + &handle->video_info, tbm_surface, (gpointer)new_buffer, + (GDestroyNotify)_mediacodecsync_gst_buffer_finalize); + } else { + /* If tbm is not used, the data from packet will be used. */ + memory = gst_memory_new_wrapped(0, info.data, (gsize)info.data_size, + 0, (gsize)info.data_size, (gpointer)new_buffer, + (GDestroyNotify)_mediacodecsync_gst_buffer_finalize); + } + + if (!memory) { + LOGE("GstMemory failed"); + goto _BUFFER_NEW_FAILED; + } + + gst_buffer_append_memory(new_buffer->gst_buffer, memory); + + /* set buffer meta */ + gst_buffer_set_size(new_buffer->gst_buffer, info.data_size); + GST_BUFFER_DTS(new_buffer->gst_buffer) = info.dts; + GST_BUFFER_PTS(new_buffer->gst_buffer) = info.pts; + GST_BUFFER_DURATION(new_buffer->gst_buffer) = info.duration; + GST_BUFFER_OFFSET(new_buffer->gst_buffer) = 0; + GST_BUFFER_OFFSET_END(new_buffer->gst_buffer) = info.data_size; + + return new_buffer; + +_BUFFER_NEW_FAILED: + gst_buffer_unref(new_buffer->gst_buffer); + free(new_buffer); + return NULL; +} + +static void __mediacodecsync_element_release_noti(gpointer data, GObject *obj) +{ + int i = 0; + mediacodecsync_s *handle = (mediacodecsync_s *)data; + + if (!handle) { + LOGE("NULL handle"); + return; + } + + for (i = 0 ; i < MEDIACODECSYNC_ELEMENT_NUM ; i++) { + if (handle->audio_pipe[i] && G_OBJECT(handle->audio_pipe[i]) == obj) { + LOGD("audio element[%d] was released", i); + handle->audio_pipe[i] = NULL; + return; + } + } + + for (i = 0 ; i < MEDIACODECSYNC_ELEMENT_NUM ; i++) { + if (handle->video_pipe[i] && G_OBJECT(handle->video_pipe[i]) == obj) { + LOGD("video element[%d] was released", i); + handle->video_pipe[i] = NULL; + return; + } + } + + LOGW("no matched element [%p]", obj); +} + + +static GstCaps *_mediacodecsync_make_caps_from_mediaformat(media_format_h format) +{ + int i = 0; + GstCaps *new_caps = NULL; + media_format_type_e type = MEDIA_FORMAT_NONE; + media_format_mimetype_e mime_type = 0; + + format_table audio_table[AUDIO_FORMAT_TABLE_SIZE] = { + {MEDIA_FORMAT_PCM, "S16LE"}, + {MEDIA_FORMAT_PCM_S16LE, "S16LE"}, + {MEDIA_FORMAT_PCM_S24LE, "S24LE"}, + {MEDIA_FORMAT_PCM_S32LE, "S32LE"}, + {MEDIA_FORMAT_PCM_S16BE, "S16BE"}, + {MEDIA_FORMAT_PCM_S24BE, "S24BE"}, + {MEDIA_FORMAT_PCM_S32BE, "S32BE"}, + {MEDIA_FORMAT_PCM_F32LE, "F32LE"}, + {MEDIA_FORMAT_PCM_F32BE, "F32BE"}, + {MEDIA_FORMAT_PCM_U16LE, "U16LE"}, + {MEDIA_FORMAT_PCM_U24LE, "U24LE"}, + {MEDIA_FORMAT_PCM_U32LE, "U32LE"}, + {MEDIA_FORMAT_PCM_U16BE, "U16BE"}, + {MEDIA_FORMAT_PCM_U24BE, "U24BE"}, + {MEDIA_FORMAT_PCM_U32BE, "U32BE"} + }; + format_table video_table[VIDEO_FORMAT_TABLE_SIZE] = { + {MEDIA_FORMAT_I420, "I420"}, + {MEDIA_FORMAT_NV12, "SN12"}, + {MEDIA_FORMAT_NV12T, "NV12T"}, + {MEDIA_FORMAT_YV12, "YV12"}, + {MEDIA_FORMAT_NV21, "NV21"}, + {MEDIA_FORMAT_NV16, "NV16"}, + {MEDIA_FORMAT_YUYV, "YUYV"}, + {MEDIA_FORMAT_UYVY, "UYVY"} + }; + + if (media_format_get_type(format, &type) != MEDIA_FORMAT_ERROR_NONE) { + LOGE("get type failed"); + return NULL; + } + + if (type & MEDIA_FORMAT_AUDIO) { + int channel; + int samplerate; + int bit; + + if (media_format_get_audio_info(format, &mime_type, &channel, + &samplerate, &bit, NULL) != MEDIA_FORMAT_ERROR_NONE) { + LOGE("get audio info failed"); + return NULL; + } + + for (i = 0 ; i < AUDIO_FORMAT_TABLE_SIZE ; i++) { + if (audio_table[i].mime_type == mime_type) { + new_caps = gst_caps_new_simple("audio/x-raw", + "rate", G_TYPE_INT, samplerate, + "channels", G_TYPE_INT, channel, + "format", G_TYPE_STRING, audio_table[i].format_string, + NULL); + break; + } + } + } else if (type & MEDIA_FORMAT_VIDEO) { + int width; + int height; + + if (media_format_get_video_info(format, &mime_type, + &width, &height, NULL, NULL) != MEDIA_FORMAT_ERROR_NONE) { + LOGE("get video info failed"); + return NULL; + } + + for (i = 0 ; i < VIDEO_FORMAT_TABLE_SIZE ; i++) { + if (video_table[i].mime_type == mime_type) { + new_caps = gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, video_table[i].format_string, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, 30, 1, + NULL); + break; + } + } + } + + if (new_caps) { + gchar *caps_string = gst_caps_to_string(new_caps); + if (caps_string) { + LOGD("caps [%s]", caps_string); + g_free(caps_string); + } + } else { + LOGE("new caps failed [type:0x%x,0x%x]", type, mime_type); + } + + return new_caps; +} + + +static void _mediacodecsync_destroy_pipeline(GstElement *pipeline[MEDIACODECSYNC_ELEMENT_NUM]) +{ + GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; + + if (!pipeline[MEDIACODECSYNC_PIPELINE]) { + LOGW("NULL pipeline"); + return; + } + + result = gst_element_set_state(pipeline[MEDIACODECSYNC_PIPELINE], GST_STATE_NULL); + + LOGD("set state NULL : %d", result); + + _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_PIPELINE]); + _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC]); + _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_ELEMENT_CAPS]); + _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_ELEMENT_QUE]); + _MEDIACODECSYNC_ELEMENT_REMOVE(pipeline[MEDIACODECSYNC_ELEMENT_SINK]); +} + + +static int _mediacodecsync_create_pipeline(mediacodecsync_s *handle, media_format_h format, + GstElement *pipeline[MEDIACODECSYNC_ELEMENT_NUM], const char *pipe_name, const char *nick_prefix, + GCallback need_data_cb, GCallback enough_data_cb, GstCaps **out_caps) +{ + GstCaps *caps = NULL; + + LOGD("name : %s", pipe_name); + + /* main pipeline */ + _MEDIACODECSYNC_PIPELINE_MAKE(handle, pipeline[MEDIACODECSYNC_PIPELINE], pipe_name); + + /* elements */ + _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_APPSRC], "appsrc", nick_prefix, "src"); + _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_CAPS], "capsfilter", nick_prefix, "caps"); + + if (!strncmp(nick_prefix, "audio", 5)) { + _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_QUE], "queue", nick_prefix, "queue"); + _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_SINK], "pulsesink", nick_prefix, "sink"); + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "qos", 1, NULL); + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "provide-clock", 0, NULL); + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "slave-method", 2, NULL); /* GST_AUDIO_BASE_SINK_SLAVE_NONE */ + } else { + _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_QUE], "queue", nick_prefix, "queue"); + _MEDIACODECSYNC_ELEMENT_MAKE(handle, pipeline[MEDIACODECSYNC_ELEMENT_SINK], "tizenwlsink", nick_prefix, "sink"); + + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "use-tbm", 1, NULL); + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "enable-last-sample", 0, NULL); + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "show-preroll-frame", 0, NULL); + } + + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC]), "max-bytes", (guint64)0, NULL); /* unlimited */ + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_QUE]), "max-size-time", 0, NULL); + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_QUE]), "max-size-bytes", 0, NULL); + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_QUE]), "max-size-buffers", 0, NULL); + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC]), "format", 3, NULL); /* GST_FORMAT_TIME */ + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_SINK]), "sync", 1, NULL); + + /* add elements to pipeline */ + gst_bin_add_many(GST_BIN(pipeline[MEDIACODECSYNC_PIPELINE]), + pipeline[MEDIACODECSYNC_ELEMENT_APPSRC], + pipeline[MEDIACODECSYNC_ELEMENT_CAPS], + pipeline[MEDIACODECSYNC_ELEMENT_QUE], + pipeline[MEDIACODECSYNC_ELEMENT_SINK], + NULL); + + /* link elements */ + if (!(gst_element_link_many(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC], + pipeline[MEDIACODECSYNC_ELEMENT_CAPS], + pipeline[MEDIACODECSYNC_ELEMENT_QUE], + pipeline[MEDIACODECSYNC_ELEMENT_SINK], + NULL))) { + LOGE("link elements failed"); + goto _CREATE_PIPELINE_FAILED; + } + + /* set capsfilter */ + caps = _mediacodecsync_make_caps_from_mediaformat(format); + if (!caps) { + LOGE("pipeline caps failed"); + goto _CREATE_PIPELINE_FAILED; + } + + g_object_set(G_OBJECT(pipeline[MEDIACODECSYNC_ELEMENT_CAPS]), "caps", caps, NULL); + + if (out_caps) { + if (*out_caps) { + LOGD("unref previous video_caps %p", *out_caps); + gst_caps_unref(*out_caps); + *out_caps = NULL; + } + + *out_caps = caps; + } else { + gst_caps_unref(caps); + caps = NULL; + } + + g_signal_connect(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC], "need-data", need_data_cb, handle); + g_signal_connect(pipeline[MEDIACODECSYNC_ELEMENT_APPSRC], "enough-data", enough_data_cb, handle); + + LOGD("done"); + + return MEDIACODEC_ERROR_NONE; + +_CREATE_PIPELINE_FAILED: + LOGE("[%s] failed", pipe_name); + + _mediacodecsync_destroy_pipeline(pipeline); + + return MEDIACODEC_ERROR_INTERNAL; +} + + +static int _mediacodecsync_prepare_pipeline(mediacodecsync_s *handle) +{ + int ret = MEDIACODEC_ERROR_NONE; + GstClock *clock = NULL; + GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; + + LOGD("enter"); + + if (handle->audio_format) { + /* create audio pipeline */ + ret = _mediacodecsync_create_pipeline(handle, handle->audio_format, + handle->audio_pipe, PIPELINE_NAME_AUDIO, "audio", + (GCallback)__mediacodecsync_need_audio_data_cb, + (GCallback)__mediacodecsync_enough_audio_data_cb, + NULL); + if (ret != MEDIACODEC_ERROR_NONE) + return ret; + + /* set state */ + result = gst_element_set_state(handle->audio_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PAUSED); + if (result == GST_STATE_CHANGE_FAILURE) { + LOGE("state change failed - VIDEO pipeline"); + ret = MEDIACODEC_ERROR_INTERNAL; + goto _PREPARE_FAILED; + } + + LOGD("audio pipeline done"); + } + + if (handle->video_format) { + /* create video pipeline */ + ret = _mediacodecsync_create_pipeline(handle, handle->video_format, + handle->video_pipe, PIPELINE_NAME_VIDEO, "video", + (GCallback)__mediacodecsync_need_video_data_cb, + (GCallback)__mediacodecsync_enough_video_data_cb, + &handle->video_caps); + if (ret != MEDIACODEC_ERROR_NONE) + goto _PREPARE_FAILED; + + /* get video info */ + if (!gst_video_info_from_caps(&handle->video_info, handle->video_caps)) { + LOGE("failed to get video info"); + goto _PREPARE_FAILED; + } + + /* set state */ + result = gst_element_set_state(handle->video_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PAUSED); + if (result == GST_STATE_CHANGE_FAILURE) { + LOGE("state change failed - VIDEO pipeline"); + ret = MEDIACODEC_ERROR_INTERNAL; + goto _PREPARE_FAILED; + } + + LOGD("video pipeline done"); + + /* share clock to synchronize */ + if (handle->audio_pipe[MEDIACODECSYNC_PIPELINE]) { + LOGD("set clock of audio pipeline to video pipeline"); + + clock = gst_pipeline_get_clock(GST_PIPELINE(handle->audio_pipe[MEDIACODECSYNC_PIPELINE])); + + if (!gst_pipeline_set_clock(GST_PIPELINE(handle->video_pipe[MEDIACODECSYNC_PIPELINE]), clock)) + LOGW("failed to set clock to video pipeline"); + + gst_object_unref(clock); + clock = NULL; + } + } + + LOGD("done"); + + return ret; + +_PREPARE_FAILED: + _mediacodecsync_destroy_pipeline(handle->audio_pipe); + _mediacodecsync_destroy_pipeline(handle->video_pipe); + + return ret; +} + + +static void _mediacodecsync_unprepare_pipeline(mediacodecsync_s *handle) +{ + _mediacodecsync_destroy_pipeline(handle->audio_pipe); + _mediacodecsync_destroy_pipeline(handle->video_pipe); +} + + + +int mediacodecsync_create(mediacodecsync_buffer_used_cb callback, void *userdata, mediacodecsync_h *mediacodecsync) +{ + mediacodecsync_s *new_handle = NULL; + + MEDIACODEC_NULL_ARG_CHECK(mediacodecsync); + MEDIACODEC_NULL_ARG_CHECK(callback); + + LOGD("enter"); + + new_handle = (mediacodecsync_s *)malloc(sizeof(mediacodecsync_s)); + if (new_handle == NULL) { + LOGE("handle allocation failed"); + return MEDIACODEC_ERROR_OUT_OF_MEMORY; + } + + memset(new_handle, 0x0, sizeof(mediacodecsync_s)); + + new_handle->buffer_used_cb = callback; + new_handle->buffer_used_cb_userdata = userdata; + new_handle->state = MEDIACODECSYNC_STATE_CREATED; + new_handle->allocator = gst_tizen_allocator_new(); + g_mutex_init(&new_handle->lock); + + *mediacodecsync = (mediacodecsync_h)new_handle; + + LOGD("new handle : %p", *mediacodecsync); + + return MEDIACODEC_ERROR_NONE; +} + + +int mediacodecsync_destroy(mediacodecsync_h mediacodecsync) +{ + mediacodecsync_s *handle = NULL; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + + handle = (mediacodecsync_s *)mediacodecsync; + + LOGD("handle to destroy : %p", handle); + + g_mutex_lock(&handle->lock); + + if (handle->state != MEDIACODECSYNC_STATE_CREATED) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return MEDIACODEC_ERROR_INVALID_STATE; + } + + if (handle->audio_format) { + media_format_unref(handle->audio_format); + handle->audio_format = NULL; + } + + if (handle->video_format) { + media_format_unref(handle->video_format); + handle->video_format = NULL; + } + + if (handle->video_caps) { + gst_caps_unref(handle->video_caps); + handle->video_caps = NULL; + } + + g_mutex_unlock(&handle->lock); + + g_mutex_clear(&handle->lock); + + free(handle); + + LOGD("done"); + + return MEDIACODEC_ERROR_NONE; +} + + +int mediacodecsync_set_format(mediacodecsync_h mediacodecsync, media_format_h audio_format, media_format_h video_format) +{ + int ret = MEDIACODEC_ERROR_NONE; + mediacodecsync_s *handle = NULL; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + + if (!audio_format && !video_format) { + LOGE("all formats are NULL"); + return MEDIACODEC_ERROR_INVALID_PARAMETER; + } + + handle = (mediacodecsync_s *)mediacodecsync; + + g_mutex_lock(&handle->lock); + + if (handle->state != MEDIACODECSYNC_STATE_CREATED) { + LOGE("invalid state %d", handle->state); + ret = MEDIACODEC_ERROR_INVALID_STATE; + goto _SET_FORMAT_DONE; + } + + if (audio_format) { + LOGD("set audio format : %p", audio_format); + + if (media_format_ref(audio_format) != MEDIACODEC_ERROR_NONE) { + LOGE("audio format ref failed"); + ret = MEDIACODEC_ERROR_INTERNAL; + goto _SET_FORMAT_DONE; + } + + if (handle->audio_format) + media_format_unref(handle->audio_format); + + handle->audio_format = audio_format; + } + + if (video_format) { + LOGD("set video format : %p", audio_format); + + if (media_format_ref(video_format) != MEDIACODEC_ERROR_NONE) { + LOGE("video format ref failed"); + ret = MEDIACODEC_ERROR_INTERNAL; + goto _SET_FORMAT_DONE; + } + + if (handle->video_format) + media_format_unref(handle->video_format); + + handle->video_format = video_format; + } + +_SET_FORMAT_DONE: + g_mutex_unlock(&handle->lock); + + return ret; +} + + +int mediacodecsync_prepare(mediacodecsync_h mediacodecsync) +{ + int ret = MEDIACODEC_ERROR_NONE; + mediacodecsync_s *handle = NULL; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + + handle = (mediacodecsync_s *)mediacodecsync; + + g_mutex_lock(&handle->lock); + + if (handle->state != MEDIACODECSYNC_STATE_CREATED) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return MEDIACODEC_ERROR_INVALID_STATE; + } + + ret = _mediacodecsync_prepare_pipeline(handle); + if (ret == MEDIACODEC_ERROR_NONE) + handle->state = MEDIACODECSYNC_STATE_READY; + + g_mutex_unlock(&handle->lock); + + return ret; +} + + +int mediacodecsync_unprepare(mediacodecsync_h mediacodecsync) +{ + int ret = MEDIACODEC_ERROR_NONE; + mediacodecsync_s *handle = NULL; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + + handle = (mediacodecsync_s *)mediacodecsync; + + g_mutex_lock(&handle->lock); + + if (handle->state != MEDIACODECSYNC_STATE_READY) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return MEDIACODEC_ERROR_INVALID_STATE; + } + + _mediacodecsync_unprepare_pipeline(handle); + handle->state = MEDIACODECSYNC_STATE_CREATED; + + g_mutex_unlock(&handle->lock); + + return ret; +} + + +int mediacodecsync_run(mediacodecsync_h mediacodecsync) +{ + int ret = MEDIACODEC_ERROR_NONE; + mediacodecsync_s *handle = NULL; + GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + + handle = (mediacodecsync_s *)mediacodecsync; + + g_mutex_lock(&handle->lock); + + if (handle->state != MEDIACODECSYNC_STATE_READY && + handle->state != MEDIACODECSYNC_STATE_PAUSED) { + LOGE("invalid state %d", handle->state); + ret = MEDIACODEC_ERROR_INVALID_STATE; + goto _RUN_DONE; + } + + /* set state */ + if (handle->audio_pipe[MEDIACODECSYNC_PIPELINE]) { + result = gst_element_set_state(handle->audio_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PLAYING); + if (result == GST_STATE_CHANGE_FAILURE) { + LOGE("state change failed - AUDIO pipeline"); + ret = MEDIACODEC_ERROR_INTERNAL; + goto _RUN_DONE; + } + } + + if (handle->video_pipe[MEDIACODECSYNC_PIPELINE]) { + result = gst_element_set_state(handle->video_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PLAYING); + if (result == GST_STATE_CHANGE_FAILURE) { + LOGE("state change failed - VIDEO pipeline"); + ret = MEDIACODEC_ERROR_INTERNAL; + goto _RUN_DONE; + } + } + + LOGD("pipeline is now playing"); + handle->state = MEDIACODECSYNC_STATE_RUNNING; + +_RUN_DONE: + g_mutex_unlock(&handle->lock); + + return ret; +} + + +int mediacodecsync_stop(mediacodecsync_h mediacodecsync) +{ + int ret = MEDIACODEC_ERROR_NONE; + mediacodecsync_s *handle = NULL; + GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + + handle = (mediacodecsync_s *)mediacodecsync; + + g_mutex_lock(&handle->lock); + + if (handle->state < MEDIACODECSYNC_STATE_RUNNING) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return MEDIACODEC_ERROR_INVALID_STATE; + } + + /* set state */ + result = gst_element_set_state(handle->video_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_READY); + if (result == GST_STATE_CHANGE_FAILURE) { + LOGE("state change failed - VIDEO pipeline"); + ret = MEDIACODEC_ERROR_INTERNAL; + } else { + LOGD("pipeline is ready"); + handle->state = MEDIACODECSYNC_STATE_READY; + } + + g_mutex_unlock(&handle->lock); + + return ret; +} + + +int mediacodecsync_pause(mediacodecsync_h mediacodecsync) +{ + int ret = MEDIACODEC_ERROR_NONE; + mediacodecsync_s *handle = NULL; + GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + + handle = (mediacodecsync_s *)mediacodecsync; + + g_mutex_lock(&handle->lock); + + if (handle->state != MEDIACODECSYNC_STATE_RUNNING) { + LOGE("invalid state %d", handle->state); + g_mutex_unlock(&handle->lock); + return MEDIACODEC_ERROR_INVALID_STATE; + } + + /* set state */ + result = gst_element_set_state(handle->video_pipe[MEDIACODECSYNC_PIPELINE], GST_STATE_PAUSED); + if (result == GST_STATE_CHANGE_FAILURE) { + LOGE("state change failed - VIDEO pipeline"); + ret = MEDIACODEC_ERROR_INTERNAL; + } else { + LOGD("pipeline is paused"); + handle->state = MEDIACODECSYNC_STATE_PAUSED; + } + + g_mutex_unlock(&handle->lock); + + return ret; +} + + +static int _mediacodecsync_push_packet_to_pipeline(GstElement *appsrc, GstBuffer *buffer) +{ + GstFlowReturn gst_ret = GST_FLOW_OK; + + if (!appsrc || !buffer) { + LOGE("NULL params %p,%p", appsrc, buffer); + return MEDIACODEC_ERROR_INTERNAL; + } + + gst_ret = gst_app_src_push_buffer((GstAppSrc *)appsrc, buffer); + if (gst_ret != GST_FLOW_OK) { + LOGE("appsrc push failed %d", gst_ret); + return MEDIACODEC_ERROR_INTERNAL; + } + + return MEDIACODEC_ERROR_NONE; +} + + +int mediacodecsync_push_packet(mediacodecsync_h mediacodecsync, media_packet_h packet, mediacodecsync_packet_type_e type) +{ + int ret = MEDIACODEC_ERROR_NONE; + mediacodecsync_s *handle = NULL; + GstMCSBuffer *mcs_buffer = NULL; + GstElement *appsrc = NULL; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + + handle = (mediacodecsync_s *)mediacodecsync; + + g_mutex_lock(&handle->lock); + + if (handle->state != MEDIACODECSYNC_STATE_RUNNING) { + LOGE("invalid state %d", handle->state); + ret = MEDIACODEC_ERROR_INVALID_STATE; + goto _PUSH_PACKET_DONE; + } + + mcs_buffer = _mediacodecsync_gst_buffer_new(handle, packet, type); + if (!mcs_buffer) { + LOGE("mediacodecsync new buffer failed"); + ret = MEDIACODEC_ERROR_INTERNAL; + goto _PUSH_PACKET_DONE; + } + + LOGI("type %u, new buffer %p [gst %p][packet %p]", + type, mcs_buffer, mcs_buffer->gst_buffer, packet); + + switch (type) { + case MEDIACODECSYNC_PACKET_TYPE_AUDIO: + appsrc = handle->audio_pipe[MEDIACODECSYNC_ELEMENT_APPSRC]; + break; + case MEDIACODECSYNC_PACKET_TYPE_VIDEO: + appsrc = handle->video_pipe[MEDIACODECSYNC_ELEMENT_APPSRC]; + break; + default: + LOGE("unhandled packet type %u, release created buffer", type); + gst_buffer_unref(mcs_buffer->gst_buffer); + ret = MEDIACODEC_ERROR_INTERNAL; + goto _PUSH_PACKET_DONE; + } + + ret = _mediacodecsync_push_packet_to_pipeline(appsrc, mcs_buffer->gst_buffer); + +_PUSH_PACKET_DONE: + g_mutex_unlock(&handle->lock); + + return ret; +} + + +int mediacodecsync_get_state(mediacodecsync_h mediacodecsync, mediacodecsync_state_e *state) +{ + mediacodecsync_s *handle = NULL; + + MEDIACODEC_INSTANCE_CHECK(mediacodecsync); + MEDIACODEC_NULL_ARG_CHECK(state); + + handle = (mediacodecsync_s *)mediacodecsync; + + *state = handle->state; + + LOGI("state %u", *state); + + return MEDIACODEC_ERROR_NONE; +} -- 2.7.4 From cfe5e588c2356c156ffb7ff7fce381b652ad4c18 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 1 Oct 2019 17:27:36 +0900 Subject: [PATCH 12/16] Update _mediacodec_foreach_supported_codec function - Remove unnecessary callback with invalid argument - Remove improper error log [Version] 0.6.2 [Profile] Common [Issue Type] Update Change-Id: I3649cc7e101f86faaf8ede047c247ad21997fb78 Signed-off-by: Jeongmo Yang --- packaging/capi-media-codec.spec | 2 +- src/media_codec_port.c | 16 ++++++---------- test/media_codec_test.c | 11 ----------- 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 455600a..f540901 100755 --- 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.1 +Version: 0.6.2 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_codec_port.c b/src/media_codec_port.c index 804a7cb..d78a1d4 100644 --- a/src/media_codec_port.c +++ b/src/media_codec_port.c @@ -800,7 +800,6 @@ int mc_set_supported_codec_cb(MMHandleType mediacodec, mediacodec_supported_code int _mediacodec_foreach_supported_codec(mediacodec_supported_codec_cb callback, void *user_data) { - int ret = MEDIACODEC_NONE; int i; int index; @@ -814,19 +813,16 @@ int _mediacodec_foreach_supported_codec(mediacodec_supported_codec_cb callback, for (i = 0; i < CODEC_NR_ITEMS; i++) { if (codec[i]) { index = (int)simple_to_codec_type_enumeration(i); - if (!callback(index, user_data)) - goto CALLBACK_ERROR; + if (!callback(index, user_data)) { + LOGW("stop foreach callback"); + break; + } } } - if (!callback(-1, user_data)) { - ret = MEDIACODEC_ERROR_INTERNAL; - goto CALLBACK_ERROR; - } + LOGD("done"); -CALLBACK_ERROR: - LOGD("foreach callback returned error"); - return ret; + return MEDIACODEC_ERROR_NONE; } int mc_get_packet_pool(MMHandleType mediacodec, media_packet_pool_h *pool) diff --git a/test/media_codec_test.c b/test/media_codec_test.c index dc46195..34a9945 100644 --- a/test/media_codec_test.c +++ b/test/media_codec_test.c @@ -1405,12 +1405,6 @@ void _mediacodec_prepare(App *app, gboolean frame_all) g_print("mediacodec_configure failed\n"); break; case VIDEO_ENC: - media_format_set_video_mime(fmt, app->mime); - media_format_set_video_width(fmt, app->width); - media_format_set_video_height(fmt, app->height); - media_format_set_video_avg_bps(fmt, app->target_bits); - media_format_set_video_frame_rate(fmt, app->fps); - media_format_create(&codec_format); media_format_set_video_mime(codec_format, codec_mime); media_format_set_video_width(codec_format, app->width); @@ -1434,11 +1428,6 @@ void _mediacodec_prepare(App *app, gboolean frame_all) g_print("mediacodec_configure failed\n"); break; case AUDIO_ENC: - media_format_set_audio_mime(fmt, app->mime); - 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_create(&codec_format); media_format_set_audio_mime(codec_format, codec_mime); media_format_set_audio_channel(codec_format, app->channel); -- 2.7.4 From b38a4bd78e6b0c35ab7ff1deef0731b3fc2cdb10 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 2 Oct 2019 15:49:10 +0900 Subject: [PATCH 13/16] Code clean up - Remove unused assignment - Remove dead code - Correct mismatched log [Version] 0.6.3 [Profile] Common [Issue Type] Clean up Change-Id: I3815198618eca58444b6785a8851af5317d56f94 Signed-off-by: Jeongmo Yang --- packaging/capi-media-codec.spec | 2 +- src/media_codec_port_gst.c | 11 +---------- src/media_codec_sync_internal.c | 2 +- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index f540901..cc14806 100755 --- 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.2 +Version: 0.6.3 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index 5d09f4b..0cc3a0a 100644 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -2664,16 +2664,12 @@ static void __mc_input_buffer_finalize_cb(GstMCBuffer *mcbuffer) return; LOGD("============>>>>> _finalize_cb : %p, %p", mcbuffer, mcbuffer->packet); - mc_gst_core_t *core = (mc_gst_core_t *)mcbuffer->core; - _mc_gst_handle_input_buffer_used(core, mcbuffer->packet); + _mc_gst_handle_input_buffer_used(mcbuffer->core, mcbuffer->packet); g_free(mcbuffer); - mcbuffer = NULL; MEDIACODEC_FLEAVE(); - - return; } static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t *core, media_packet_h packet, uint64_t size) @@ -2682,11 +2678,6 @@ 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; diff --git a/src/media_codec_sync_internal.c b/src/media_codec_sync_internal.c index 5d95d6f..e17390b 100644 --- a/src/media_codec_sync_internal.c +++ b/src/media_codec_sync_internal.c @@ -677,7 +677,7 @@ int mediacodecsync_set_format(mediacodecsync_h mediacodecsync, media_format_h au } if (video_format) { - LOGD("set video format : %p", audio_format); + LOGD("set video format : %p", video_format); if (media_format_ref(video_format) != MEDIACODEC_ERROR_NONE) { LOGE("video format ref failed"); -- 2.7.4 From cb529a4c40b7cc5746448c63d60b4b82799d29e0 Mon Sep 17 00:00:00 2001 From: Hyuntae Kim Date: Tue, 22 Oct 2019 13:26:46 +0900 Subject: [PATCH 14/16] [mediacodec] disable mm-resource-manager when tv profile Change-Id: Iec9caf6101ff01c2247f2caf4bfe6289e5453bd3 --- CMakeLists.txt | 10 ++++++++-- include/media_codec_private.h | 4 ++++ packaging/capi-media-codec.spec | 12 +++++++++--- src/media_codec.c | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) mode change 100755 => 100644 CMakeLists.txt mode change 100755 => 100644 packaging/capi-media-codec.spec diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100755 new mode 100644 index 217ee07..b073bc8 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,11 @@ 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 mm-resource-manager gstreamer-allocators-1.0" ) -SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 mm-resource-manager 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 capi-system-info gstreamer-allocators-1.0" ) +SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 gstreamer-allocators-1.0" ) +IF(TIZEN_FEATURE_MM_RESOURCE_MANAGER) +SET(dependents "${dependents} mm-resource-manager") +ENDIF(TIZEN_FEATURE_MM_RESOURCE_MANAGER) INCLUDE(FindPkgConfig) pkg_check_modules(${fw_name} REQUIRED ${dependents}) @@ -28,6 +31,9 @@ ENDIF("${ARCH}" STREQUAL "arm") ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") ADD_DEFINITIONS("-DTIZEN_DEBUG") +IF(TIZEN_FEATURE_MM_RESOURCE_MANAGER) +ADD_DEFINITIONS("-DUSE_MM_RESOURCE_MANAGER") +ENDIF(TIZEN_FEATURE_MM_RESOURCE_MANAGER) SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}") diff --git a/include/media_codec_private.h b/include/media_codec_private.h index 0057fa0..bc196ec 100644 --- a/include/media_codec_private.h +++ b/include/media_codec_private.h @@ -24,7 +24,9 @@ #include #include +#ifdef USE_MM_RESOURCE_MANAGER #include +#endif #ifdef __cplusplus extern "C" { @@ -101,7 +103,9 @@ typedef struct _mediacodec_s { int state; bool is_omx; char *m_mime; +#ifdef USE_MM_RESOURCE_MANAGER mm_resource_manager_res_h codec_resource; +#endif mediacodec_input_buffer_used_cb empty_buffer_cb; void* empty_buffer_cb_userdata; diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec old mode 100755 new mode 100644 index cc14806..311c106 --- 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.3 +Version: 0.6.4 Release: 0 Group: Multimedia/API License: Apache-2.0 @@ -21,7 +21,9 @@ BuildRequires: pkgconfig(gstreamer-plugins-base-1.0) BuildRequires: pkgconfig(gstreamer-app-1.0) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(iniparser) +%if "%{tizen_profile_name}" != "tv" BuildRequires: pkgconfig(mm-resource-manager) +%endif #BuildRequires: pkgconfig(capi-media-camera) #BuildRequires: pkgconfig(capi-mediademuxer) #BuildRequires: pkgconfig(capi-mediamuxer) @@ -63,8 +65,12 @@ export LDFLAGS+=" -lgcov" %endif MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` -%cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER} - +%cmake . -DCMAKE_INSTALL_PREFIX=/usr -DFULLVER=%{version} -DMAJORVER=${MAJORVER} \ +%if "%{tizen_profile_name}" == "tv" + -DTIZEN_FEATURE_MM_RESOURCE_MANAGER=NO +%else + -DTIZEN_FEATURE_MM_RESOURCE_MANAGER=YES +%endif make %{?jobs:-j%jobs} diff --git a/src/media_codec.c b/src/media_codec.c index b76269a..88e12d8 100644 --- a/src/media_codec.c +++ b/src/media_codec.c @@ -26,9 +26,11 @@ #define MC_PREALLOCATED_HANDLE_ARRAY_SIZE 16 +#ifdef USE_MM_RESOURCE_MANAGER static mm_resource_manager_h resource_manager; static GPtrArray *mediacodec_handles; static GMutex mediacodec_handles_lock; +#endif static gboolean __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data); static gboolean __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data); @@ -36,10 +38,12 @@ static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data) static gboolean __mediacodec_eos_cb(void *user_data); static gboolean __mediacodec_supported_codec_cb(mediacodec_codec_type_e codec_type, void *user_data); static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data); +#ifdef USE_MM_RESOURCE_MANAGER static void __mediacodec_init_lib() __attribute__((constructor)); static void __mediacodec_deinit_lib() __attribute__((destructor)); static int __mediacodec_resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h resource_h, void *user_data); +#endif /* * Internal Implementation @@ -131,8 +135,10 @@ int mediacodec_create(mediacodec_h *mediacodec) LOGD("mediacodec_create.."); +#ifdef USE_MM_RESOURCE_MANAGER if (resource_manager == NULL) return MEDIACODEC_ERROR_INTERNAL; +#endif handle = (mediacodec_s *)malloc(sizeof(mediacodec_s)); if (handle != NULL) { @@ -164,9 +170,11 @@ int mediacodec_create(mediacodec_h *mediacodec) mc_set_buffer_status_cb(handle->mc_handle, (mediacodec_buffer_status_cb)__mediacodec_buffer_status_cb, handle); mc_set_supported_codec_cb(handle->mc_handle, (mediacodec_supported_codec_cb)__mediacodec_supported_codec_cb, handle); +#ifdef USE_MM_RESOURCE_MANAGER g_mutex_lock(&mediacodec_handles_lock); g_ptr_array_insert(mediacodec_handles, -1, *mediacodec); g_mutex_unlock(&mediacodec_handles_lock); +#endif return MEDIACODEC_ERROR_NONE; @@ -183,9 +191,11 @@ int mediacodec_destroy(mediacodec_h mediacodec) LOGD("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION); return MEDIACODEC_ERROR_INVALID_OPERATION; } else { +#ifdef USE_MM_RESOURCE_MANAGER g_mutex_lock(&mediacodec_handles_lock); g_ptr_array_remove_fast(mediacodec_handles, mediacodec); g_mutex_unlock(&mediacodec_handles_lock); +#endif handle->state = MEDIACODEC_STATE_NONE; free(handle); @@ -294,11 +304,14 @@ int mediacodec_prepare(mediacodec_h mediacodec) { MEDIACODEC_INSTANCE_CHECK(mediacodec); mediacodec_s *handle = (mediacodec_s *)mediacodec; +#ifdef USE_MM_RESOURCE_MANAGER mc_handle_t *mc_handle = (mc_handle_t *) handle->mc_handle; int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE; mm_resource_manager_res_h resource; +#endif MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); +#ifdef USE_MM_RESOURCE_MANAGER if (mc_handle->is_hw && mc_handle->is_video) { if (handle->codec_resource) { @@ -345,6 +358,7 @@ int mediacodec_prepare(mediacodec_h mediacodec) handle->codec_resource = resource; } +#endif int ret = mc_prepare(handle->mc_handle); @@ -360,13 +374,16 @@ int mediacodec_unprepare(mediacodec_h mediacodec) { MEDIACODEC_INSTANCE_CHECK(mediacodec); mediacodec_s *handle = (mediacodec_s *)mediacodec; +#ifdef USE_MM_RESOURCE_MANAGER int rm_ret = MM_RESOURCE_MANAGER_ERROR_NONE; +#endif int ret = mc_unprepare(handle->mc_handle); if (ret != MEDIACODEC_ERROR_NONE) { return __convert_error_code(ret, (char *)__FUNCTION__); } else { +#ifdef USE_MM_RESOURCE_MANAGER if (handle->codec_resource != NULL) { mm_resource_manager_mark_for_release(resource_manager, handle->codec_resource); @@ -384,6 +401,7 @@ int mediacodec_unprepare(mediacodec_h mediacodec) } else { LOGD("No codec resource to release. Probably resource release cb called\n"); } +#endif handle->state = MEDIACODEC_STATE_IDLE; return MEDIACODEC_ERROR_NONE; @@ -689,6 +707,7 @@ static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void * } +#ifdef USE_MM_RESOURCE_MANAGER static int __mediacodec_resource_release_cb(mm_resource_manager_h rm, mm_resource_manager_res_h resource_h, void *user_data) { @@ -734,3 +753,4 @@ static void __mediacodec_deinit_lib() mm_resource_manager_destroy(resource_manager); g_ptr_array_unref(mediacodec_handles); } +#endif -- 2.7.4 From d998035d4965be121e7a97ab278958cb7ec87a79 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 25 Oct 2019 14:04:41 +0900 Subject: [PATCH 15/16] Remove unnecessary dependency for pc file [Version] 0.6.4-1 [Profile] Common [Issue Type] Update Change-Id: I5c5b30ea0b51ed6e17aab6c84df2be4874f4966b Signed-off-by: Jeongmo Yang --- CMakeLists.txt | 4 ++-- packaging/capi-media-codec.spec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b073bc8..f2b7204 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ 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(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 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 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") ENDIF(TIZEN_FEATURE_MM_RESOURCE_MANAGER) diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index 311c106..ab8829e 100644 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -5,7 +5,7 @@ Name: capi-media-codec Summary: A Media Codec library in Tizen Native API Version: 0.6.4 -Release: 0 +Release: 1 Group: Multimedia/API License: Apache-2.0 Source0: %{name}-%{version}.tar.gz -- 2.7.4 From 385aadca8059bbe9f7ef5c28038ba32c26e4a1de Mon Sep 17 00:00:00 2001 From: Gilbok Lee Date: Wed, 30 Oct 2019 11:43:49 +0900 Subject: [PATCH 16/16] Do not alloc memory in eos packet - EOS packet has dummy data [Version] 0.6.5 [Profile] Common [Issue Type] Fix bugs Change-Id: I94df9c25d03fda7fdba934d50974381532b4dca9 --- packaging/capi-media-codec.spec | 4 ++-- src/media_codec_port_gst.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index ab8829e..3fff575 100644 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -4,8 +4,8 @@ Name: capi-media-codec Summary: A Media Codec library in Tizen Native API -Version: 0.6.4 -Release: 1 +Version: 0.6.5 +Release: 0 Group: Multimedia/API License: Apache-2.0 Source0: %{name}-%{version}.tar.gz diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index 0cc3a0a..5ebf95e 100644 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -2440,8 +2440,8 @@ int __mc_gst_create_eos_packet(media_format_h fmt, GstMCBuffer *mcbuffer) media_packet_h packet = NULL; MEDIACODEC_FENTER(); - if (media_packet_create_alloc(fmt, __mc_output_buffer_finalize_cb, mcbuffer, &packet)) { - LOGE("media_packet_create_alloc failed\n"); + if (media_packet_create(fmt, __mc_output_buffer_finalize_cb, mcbuffer, &packet)) { + LOGE("media_packet_create failed\n"); ret = MC_ERROR; goto ERROR; } -- 2.7.4