diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/media_codec.c | 310 | ||||
-rwxr-xr-x | src/media_codec_bitstream.c | 372 | ||||
-rwxr-xr-x | src/media_codec_ini.c | 571 | ||||
-rwxr-xr-x | src/media_codec_port.c | 683 | ||||
-rwxr-xr-x | src/media_codec_port_gst.c | 3018 | ||||
-rwxr-xr-x | src/media_codec_queue.c | 80 | ||||
-rwxr-xr-x | src/media_codec_util.c | 26 |
7 files changed, 3605 insertions, 1455 deletions
diff --git a/src/media_codec.c b/src/media_codec.c index 75988a3..efd6591 100755 --- a/src/media_codec.c +++ b/src/media_codec.c @@ -20,6 +20,7 @@ #include <media_codec.h> #include <media_codec_private.h> #include <media_codec_port.h> +#include <system_info.h> #include <dlog.h> @@ -27,16 +28,19 @@ static gboolean __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_dat static gboolean __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data); 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); + /* * Internal Implementation */ -int __convert_error_code(int code, char* func_name) +int __convert_error_code(int code, char *func_name) { int ret = MEDIACODEC_ERROR_INVALID_OPERATION; - char* msg = "MEDIACOODEC_INVALID_OPERATION"; - switch(code) - { + char *msg = "MEDIACOODEC_INVALID_OPERATION"; + + switch (code) { case MC_ERROR_NONE: ret = MEDIACODEC_ERROR_NONE; msg = "MEDIACODEC_ERROR_NONE"; @@ -102,15 +106,9 @@ int __convert_error_code(int code, char* func_name) return ret; } -bool __mediacodec_state_validate(mediacodec_h mediacodec, mediacodec_state_e threshold) -{ - mediacodec_s * handle = (mediacodec_s *) mediacodec; - - if(handle->state < threshold) - return FALSE; - return TRUE; -} - +/* + * Public Implementation + */ int mediacodec_create(mediacodec_h *mediacodec) { @@ -118,31 +116,25 @@ int mediacodec_create(mediacodec_h *mediacodec) mediacodec_s *handle; int ret; - LOGD ("mediacodec_create..\n"); + LOGD("mediacodec_create.."); - handle = (mediacodec_s*)malloc( sizeof(mediacodec_s)); - if (handle != NULL) - { + handle = (mediacodec_s *)malloc(sizeof(mediacodec_s)); + if (handle != NULL) { memset(handle, 0 , sizeof(mediacodec_s)); - } - else - { + } else { LOGE("MEDIACODEC_ERROR_OUT_OF_MEMORY(0x%08x)", MEDIACODEC_ERROR_OUT_OF_MEMORY); return MEDIACODEC_ERROR_OUT_OF_MEMORY; } ret = mc_create(&handle->mc_handle); - if (ret != MEDIACODEC_ERROR_NONE) - { + if (ret != MEDIACODEC_ERROR_NONE) { LOGE("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION); handle->state = MEDIACODEC_STATE_NONE; free(handle); handle = NULL; return MEDIACODEC_ERROR_INVALID_OPERATION; - } - else - { - *mediacodec = (mediacodec_h) handle; + } else { + *mediacodec = (mediacodec_h)handle; handle->state = MEDIACODEC_STATE_IDLE; LOGD("new handle : %p", *mediacodec); } @@ -152,6 +144,8 @@ int mediacodec_create(mediacodec_h *mediacodec) mc_set_fill_buffer_cb(handle->mc_handle, (mediacodec_output_buffer_available_cb)__mediacodec_fill_buffer_cb, handle); mc_set_error_cb(handle->mc_handle, (mediacodec_error_cb)__mediacodec_error_cb, handle); mc_set_eos_cb(handle->mc_handle, (mediacodec_eos_cb)__mediacodec_eos_cb, handle); + 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); return MEDIACODEC_ERROR_NONE; @@ -159,17 +153,15 @@ int mediacodec_create(mediacodec_h *mediacodec) int mediacodec_destroy(mediacodec_h mediacodec) { - LOGD ("[%s] Start, handle to destroy : %p", __FUNCTION__, mediacodec); + LOGD("[%s] Start, handle to destroy : %p", __FUNCTION__, mediacodec); MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; int ret = mc_destroy(handle->mc_handle); if (ret != MEDIACODEC_ERROR_NONE) { LOGD("MEDIACODEC_ERROR_INVALID_OPERATION(0x%08x)", MEDIACODEC_ERROR_INVALID_OPERATION); return MEDIACODEC_ERROR_INVALID_OPERATION; - } - else - { + } else { handle->state = MEDIACODEC_STATE_NONE; free(handle); handle = NULL; @@ -180,17 +172,14 @@ int mediacodec_destroy(mediacodec_h mediacodec) int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_id, mediacodec_support_type_e flags) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); int ret = mc_set_codec(handle->mc_handle, codec_id, flags); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); - } - else - { + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { handle->state = MEDIACODEC_STATE_IDLE; return MEDIACODEC_ERROR_NONE; } @@ -199,17 +188,14 @@ int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_ int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); int ret = mc_set_vdec_info(handle->mc_handle, width, height); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); - } - else - { + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { handle->state = MEDIACODEC_STATE_IDLE; return MEDIACODEC_ERROR_NONE; } @@ -218,17 +204,14 @@ 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) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); int ret = mc_set_venc_info(handle->mc_handle, width, height, fps, target_bits); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); - } - else - { + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { handle->state = MEDIACODEC_STATE_IDLE; return MEDIACODEC_ERROR_NONE; } @@ -237,17 +220,14 @@ 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) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); int ret = mc_set_adec_info(handle->mc_handle, samplerate, channel, bit); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); - } - else - { + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { handle->state = MEDIACODEC_STATE_IDLE; return MEDIACODEC_ERROR_NONE; } @@ -256,17 +236,14 @@ int mediacodec_set_adec_info(mediacodec_h mediacodec, int samplerate, int channe int mediacodec_set_aenc_info(mediacodec_h mediacodec, int samplerate, int channel, int bit, int bitrate) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); int ret = mc_set_aenc_info(handle->mc_handle, samplerate, channel, bit, bitrate); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); - } - else - { + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { handle->state = MEDIACODEC_STATE_IDLE; return MEDIACODEC_ERROR_NONE; } @@ -275,17 +252,14 @@ int mediacodec_set_aenc_info(mediacodec_h mediacodec, int samplerate, int channe int mediacodec_prepare(mediacodec_h mediacodec) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); int ret = mc_prepare(handle->mc_handle); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); - } - else - { + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { handle->state = MEDIACODEC_STATE_READY; return MEDIACODEC_ERROR_NONE; } @@ -294,16 +268,13 @@ int mediacodec_prepare(mediacodec_h mediacodec) int mediacodec_unprepare(mediacodec_h mediacodec) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; int ret = mc_unprepare(handle->mc_handle); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); - } - else - { + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { handle->state = MEDIACODEC_STATE_IDLE; return MEDIACODEC_ERROR_NONE; } @@ -312,18 +283,14 @@ int mediacodec_unprepare(mediacodec_h mediacodec) int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint64_t timeOutUs) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_READY); int ret = mc_process_input(handle->mc_handle, inbuf, timeOutUs); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); - } - else - { - //handle->state = MEDIACODEC_STATE_EXCUTE; + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { return MEDIACODEC_ERROR_NONE; } } @@ -331,26 +298,52 @@ int mediacodec_process_input(mediacodec_h mediacodec, media_packet_h inbuf, uint int mediacodec_get_output(mediacodec_h mediacodec, media_packet_h *outbuf, uint64_t timeOutUs) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_READY); int ret = mc_get_output(handle->mc_handle, outbuf, timeOutUs); - if (ret != MEDIACODEC_ERROR_NONE) - { - return __convert_error_code(ret,(char*)__FUNCTION__); + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + return MEDIACODEC_ERROR_NONE; } - else - { - //handle->state = MEDIACODEC_STATE_EXCUTE; +} + +int mediacodec_flush_buffers(mediacodec_h mediacodec) +{ + MEDIACODEC_INSTANCE_CHECK(mediacodec); + mediacodec_s *handle = (mediacodec_s *)mediacodec; + + int ret = mc_flush_buffers(handle->mc_handle); + + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + return MEDIACODEC_ERROR_NONE; + } +} + +int mediacodec_get_supported_type(mediacodec_h mediacodec, mediacodec_codec_type_e codec_type, bool encoder, int *support_type) +{ + MEDIACODEC_INSTANCE_CHECK(mediacodec); + mediacodec_s *handle = (mediacodec_s *)mediacodec; + MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); + + int ret = mc_get_supported_type(handle->mc_handle, codec_type, encoder, support_type); + + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + handle->state = MEDIACODEC_STATE_IDLE; return MEDIACODEC_ERROR_NONE; } } -int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_input_buffer_used_cb callback, void* user_data) +int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_input_buffer_used_cb callback, void *user_data) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); handle->empty_buffer_cb = callback; @@ -364,7 +357,7 @@ int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_inpu int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; handle->empty_buffer_cb = NULL; handle->empty_buffer_cb_userdata = NULL; @@ -373,10 +366,10 @@ int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec) } -int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacodec_output_buffer_available_cb callback, void* user_data) +int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacodec_output_buffer_available_cb callback, void *user_data) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); handle->fill_buffer_cb = callback; @@ -391,7 +384,7 @@ int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacode int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; handle->fill_buffer_cb = NULL; handle->fill_buffer_cb_userdata = NULL; @@ -399,10 +392,10 @@ int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec) return MEDIACODEC_ERROR_NONE; } -int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callback, void* user_data) +int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callback, void *user_data) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); handle->error_cb = callback; @@ -417,7 +410,7 @@ int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callbac int mediacodec_unset_error_cb(mediacodec_h mediacodec) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; handle->error_cb = NULL; handle->error_cb_userdata = NULL; @@ -425,10 +418,10 @@ int mediacodec_unset_error_cb(mediacodec_h mediacodec) return MEDIACODEC_ERROR_NONE; } -int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, void* user_data) +int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, void *user_data) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); handle->eos_cb = callback; @@ -443,7 +436,7 @@ int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, v int mediacodec_unset_eos_cb(mediacodec_h mediacodec) { MEDIACODEC_INSTANCE_CHECK(mediacodec); - mediacodec_s * handle = (mediacodec_s *) mediacodec; + mediacodec_s *handle = (mediacodec_s *)mediacodec; handle->eos_cb = NULL; handle->eos_cb_userdata = NULL; @@ -451,15 +444,61 @@ int mediacodec_unset_eos_cb(mediacodec_h mediacodec) return MEDIACODEC_ERROR_NONE; } +int mediacodec_set_buffer_status_cb(mediacodec_h mediacodec, mediacodec_buffer_status_cb callback, void *user_data) +{ + MEDIACODEC_INSTANCE_CHECK(mediacodec); + mediacodec_s *handle = (mediacodec_s *)mediacodec; + MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE); + + handle->buffer_status_cb = callback; + handle->buffer_status_cb_userdata = user_data; + + LOGD("set buffer_status_cb(%p)", callback); + + return MEDIACODEC_ERROR_NONE; + +} + +int mediacodec_unset_buffer_status_cb(mediacodec_h mediacodec) +{ + MEDIACODEC_INSTANCE_CHECK(mediacodec); + mediacodec_s *handle = (mediacodec_s *)mediacodec; + + handle->buffer_status_cb = NULL; + handle->buffer_status_cb_userdata = NULL; + + return MEDIACODEC_ERROR_NONE; +} + +int mediacodec_foreach_supported_codec(mediacodec_h mediacodec, mediacodec_supported_codec_cb callback, void *user_data) +{ + MEDIACODEC_INSTANCE_CHECK(mediacodec); + mediacodec_s *handle = (mediacodec_s *)mediacodec; + + handle->supported_codec_cb = callback; + handle->supported_codec_cb_userdata = user_data; + + LOGD("set supported_codec_cb(%p)", callback); + int ret = _mediacodec_foreach_supported_codec(handle->mc_handle, callback, handle); + + if (ret != MEDIACODEC_ERROR_NONE) { + return __convert_error_code(ret, (char *)__FUNCTION__); + } else { + return MEDIACODEC_ERROR_NONE; + } + + return MEDIACODEC_ERROR_NONE; + +} + static gboolean __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data) { - if(user_data == NULL || pkt == NULL) + if (user_data == NULL || pkt == NULL) return 0; - mediacodec_s * handle = (mediacodec_s *) user_data; + mediacodec_s *handle = (mediacodec_s *)user_data; - if ( handle->empty_buffer_cb ) - { + if (handle->empty_buffer_cb) { ((mediacodec_input_buffer_used_cb)handle->empty_buffer_cb)(pkt, handle->empty_buffer_cb_userdata); } @@ -468,13 +507,12 @@ 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) { - if(user_data == NULL || pkt == NULL) + if (user_data == NULL || pkt == NULL) return 0; - mediacodec_s * handle = (mediacodec_s *) user_data; + mediacodec_s *handle = (mediacodec_s *)user_data; - if ( handle->fill_buffer_cb ) - { + if (handle->fill_buffer_cb) { ((mediacodec_output_buffer_available_cb)handle->fill_buffer_cb)(pkt, handle->fill_buffer_cb_userdata); } @@ -483,13 +521,12 @@ static gboolean __mediacodec_fill_buffer_cb(media_packet_h pkt, void *user_data static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data) { - if(user_data == NULL) + if (user_data == NULL) return 0; - mediacodec_s * handle = (mediacodec_s *) user_data; + mediacodec_s *handle = (mediacodec_s *)user_data; - if ( handle->error_cb ) - { + if (handle->error_cb) { ((mediacodec_error_cb)handle->error_cb)(error, handle->error_cb_userdata); } @@ -498,15 +535,42 @@ static gboolean __mediacodec_error_cb(mediacodec_error_e error, void *user_data) static gboolean __mediacodec_eos_cb(void *user_data) { - if(user_data == NULL) + if (user_data == NULL) return 0; - mediacodec_s * handle = (mediacodec_s *) user_data; + mediacodec_s *handle = (mediacodec_s *)user_data; - if ( handle->eos_cb ) - { + if (handle->eos_cb) { ((mediacodec_eos_cb)handle->eos_cb)(handle->eos_cb_userdata); } return 1; } + +static gboolean __mediacodec_supported_codec_cb(mediacodec_codec_type_e codec_type, void *user_data) +{ + if (user_data == NULL) + return 0; + + mediacodec_s *handle = (mediacodec_s *)user_data; + + if (handle->supported_codec_cb) { + return ((mediacodec_supported_codec_cb)handle->supported_codec_cb)(codec_type, handle->supported_codec_cb_userdata); + } + return false; +} + +static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data) +{ + if (user_data == NULL) + return 0; + + mediacodec_s *handle = (mediacodec_s *)user_data; + + if (handle->buffer_status_cb) { + ((mediacodec_buffer_status_cb)handle->buffer_status_cb)(status, handle->buffer_status_cb_userdata); + } + + return 1; +} + diff --git a/src/media_codec_bitstream.c b/src/media_codec_bitstream.c new file mode 100755 index 0000000..7e08491 --- /dev/null +++ b/src/media_codec_bitstream.c @@ -0,0 +1,372 @@ +/* +* Copyright (c) 2011 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 <stdio.h> +#include <dlog.h> +#include <media_codec_bitstream.h> + +void mc_init_bits(mc_bitstream_t *stream, unsigned char *data, int size) +{ + stream->data = data; + stream->numBytes = size; + stream->bitcnt = 32; + stream->bytePos = 0; + stream->dataBitPos = 0; + stream->buffer = 0; +} + +short mc_show_bits(mc_bitstream_t *stream, unsigned char nbits, unsigned int *pulOutData) +{ + unsigned char *bits; + unsigned int dataBitPos = stream->dataBitPos; + unsigned int bitcnt = stream->bitcnt; + unsigned int dataBytePos; + unsigned int i; + + if (nbits > (32 - bitcnt)) { + dataBytePos = dataBitPos >> 3; + bitcnt = dataBitPos & 7; + if (dataBytePos > stream->numBytes - 4) { + stream->buffer = 0; + for (i = 0; i < stream->numBytes - dataBytePos; i++) { + stream->buffer |= stream->data[dataBytePos + i]; + stream->buffer <<= 8; + } + stream->buffer <<= 8 * (3 - i); + } else { + bits = &stream->data[dataBytePos]; + stream->buffer = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3]; + } + stream->bitcnt = bitcnt; + } + bitcnt += nbits; + + *pulOutData = (stream->buffer >> (32 - bitcnt)) & mask[(unsigned short)nbits]; + + return 0; +} + +short mc_read_bits(mc_bitstream_t *stream, unsigned char nbits, unsigned int *pulOutData) +{ + unsigned char *bits; + unsigned int dataBitPos = stream->dataBitPos; + unsigned int bitcnt = stream->bitcnt; + unsigned int dataBytePos; + + if ((dataBitPos + nbits) > (stream->numBytes << 3)) { + *pulOutData = 0; + return -1; + } + + if (nbits > (32 - bitcnt)) { + dataBytePos = dataBitPos >> 3; + bitcnt = dataBitPos & 7; + bits = &stream->data[dataBytePos]; + stream->buffer = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3]; + } + + + stream->dataBitPos += nbits; + stream->bitcnt = (unsigned char)(bitcnt + nbits); + + + *pulOutData = (stream->buffer >> (32 - stream->bitcnt)) & mask[(unsigned short)nbits]; + + return 0; +} + +short mc_byte_align(mc_bitstream_t *stream) +{ + unsigned char *bits; + unsigned int dataBitPos = stream->dataBitPos; + unsigned int bitcnt = stream->bitcnt; + unsigned int dataBytePos; + unsigned int leftBits; + + leftBits = 8 - (dataBitPos & 0x7); + if (leftBits == 8) { + if ((dataBitPos + 8) > (unsigned int)(stream->numBytes << 3)) + return (-1); + dataBitPos += 8; + bitcnt += 8; + } else { + dataBytePos = dataBitPos >> 3; + dataBitPos += leftBits; + bitcnt += leftBits; + } + + if (bitcnt > 32) { + dataBytePos = dataBitPos >> 3; + bits = &stream->data[dataBytePos]; + stream->buffer = (bits[0] << 24) | (bits[1] << 16) | (bits[2] << 8) | bits[3]; + } + + + stream->dataBitPos = dataBitPos; + stream->bitcnt = bitcnt; + + return 0; +} +unsigned int __mc_bytestream_to_nal(unsigned char *data, int size) +{ + unsigned char val, zero_count; + unsigned char *pNal = data; + int index = 0; + + zero_count = 0; + + val = pNal[index++]; + while (!val) { + zero_count++; + val = pNal[index++]; + } + + zero_count = 0; + + while (1) { + if (index >= size) + return (index - 1); + + val = pNal[index++]; + + if (!val) + zero_count++; + else { + if ((zero_count >= 2) && (val == 1)) + break; + else { + zero_count = 0; + } + } + } + + if (zero_count > 3) + zero_count = 3; + + return (index - zero_count - 1); +} + +int __mc_decode_sps(mc_bitstream_t *pstream, int *width, int *height) +{ + int ret = MC_ERROR_NONE; + unsigned int tmp = 0; + + int profile_idc = 0; + + mc_read_bits(pstream, 8, &tmp); + mc_read_bits(pstream, 1, &tmp); + mc_read_bits(pstream, 1, &tmp); + mc_read_bits(pstream, 1, &tmp); + mc_read_bits(pstream, 5, &tmp); + mc_read_bits(pstream, 8, &tmp); + + profile_idc = tmp; + + if (profile_idc > 51) + ret = MC_INVALID_IN_BUF; + + /*TODO parse width, height, etc...*/ + + return ret; +} + +int _mc_check_h264_bytestream(unsigned char *nal, int byte_length, bool port, bool *codec_config, bool *sync_flag, bool *slice) +{ + int ret = MC_ERROR_NONE; + int stacked_length = 0; + int nal_length = 0; + unsigned int syntax = 0; + unsigned int state = 0; + int count = 0; + int nal_unit_type = 0; + + mc_bitstream_t pstream; + + nal_unit_type = nal[2] == 1 ? (nal[3] & 0x1F) : (nal[4] & 0x1F); + + if (nal_unit_type == 0x7 || nal_unit_type == 0x8 || nal_unit_type == 0x9) { + + while (1) { + nal_length = __mc_bytestream_to_nal(nal + stacked_length, byte_length - stacked_length); + + mc_init_bits(&pstream, nal + stacked_length, byte_length - stacked_length); + mc_read_bits(&pstream, 32, &syntax); + mc_read_bits(&pstream, 8, &syntax); + + switch (syntax & 0x1F) { + case NAL_SEQUENCE_PARAMETER_SET: + LOGD("nal_unit_type : SPS"); + if ((ret = __mc_decode_sps(&pstream, NULL, NULL)) != MC_ERROR_NONE) + return ret; + state |= MC_EXIST_SPS; + break; + case NAL_PICTURE_PARAMETER_SET: + LOGD("nal_unit_type : PPS"); + state |= MC_EXIST_PPS; + break; + case NAL_SLICE_IDR: + LOGD("nal_unit_type : IDR"); + state |= MC_EXIST_IDR; + break; + default: + state |= MC_EXIST_SLICE; + LOGD("nal_unit_type : %x", syntax & 0x1F); + break; + } + + LOGD("stacked_length : %d, nal_length : %d, byte_length : %d", stacked_length, nal_length, byte_length); + + stacked_length += nal_length; + count++; + + if ((stacked_length >= byte_length) || count > 5) + break; + } + } else if (nal_unit_type == 0x5) { + state |= MC_EXIST_IDR; + LOGD("nal_unit_type is IDR"); + } else if (nal_unit_type == 0x01 || nal_unit_type == 0x02 || nal_unit_type == 0x03 || nal_unit_type == 0x04) { + state |= MC_EXIST_SLICE; + LOGD("nal_unit_type : %x", nal_unit_type); + } else { + LOGD("Non VCL"); + } + + LOGD("for debug state :%d, %d", state, MC_VALID_FIRST_SLICE); + + /* input port */ + if (!port && !CHECK_VALID_PACKET(state, MC_VALID_FIRST_SLICE)) + return MC_INVALID_IN_BUF; + + /* output port */ + if (port) { + *codec_config = CHECK_VALID_PACKET(state, MC_VALID_HEADER) ? 1 : 0; + *sync_flag = CHECK_VALID_PACKET(state, MC_EXIST_IDR) ? 1 : 0; + *slice = CHECK_VALID_PACKET(state, MC_EXIST_SLICE) ? 1 : 0; + } + + return ret; +} + +int _mc_check_valid_h263_frame(unsigned char *p, int size) +{ + unsigned char *end = p + size - 3; + int count = 0; + + do { + /* Found the start of the frame, now try to find the end */ + if ((p[0] == 0x00) && (p[1] == 0x00) && ((p[2]&0xFC) == 0x80)) + count++; + p++; + } while (count == 1 && p < end); + + if (count != 1) + return MC_INVALID_IN_BUF; /* frame boundary violated */ + + return MC_ERROR_NONE; +} + +bool _mc_is_voss(unsigned char *buf, int size, int *codec_size) +{ + unsigned char *p = buf; + unsigned char *end = p + size - 3; + if (size < 4) + return false; + + if (!((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xB0))) + return false; + + if (codec_size) { + for (; p < end ; p++) { + if ((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xB6)) { + *codec_size = p-buf; + break; + } + } + } + + return true; +} + +bool _mc_is_ivop(unsigned char *p, int size, int pos) +{ + if (size < (pos + 5)) + return false; + + p = p + pos; + + if ((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xB6)) { + /* VOP_CODING_TYPE (binary) Coding method + // 00 intra-coded (I) + // 01 predictive-coded (P) + // 10 bidirectionally-predictive-coded (B) + // 11 sprite (S) + */ + if ((p[4] & 0xC0) == 0x0) /*I-VOP */ + return true; + } + return false; +} + +bool _mc_is_vop(unsigned char *p, int size, int pos) +{ + if (size < (pos + 4)) + return false; + + p = p + pos; + + if ((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xB6)) + return true; + + return false; +} + +int _mc_check_mpeg4_out_bytestream(unsigned char *buf, int buf_length, bool* need_codec_data, bool *need_sync_flag) +{ + int codec_data_size = 0; + g_return_val_if_fail(need_codec_data != NULL, MC_PARAM_ERROR); + g_return_val_if_fail(need_sync_flag != NULL, MC_PARAM_ERROR); + + *need_codec_data = FALSE; + *need_sync_flag = FALSE; + + if (_mc_is_voss(buf, buf_length, &codec_data_size)) + *need_codec_data = TRUE; + if (_mc_is_ivop(buf, buf_length, codec_data_size)) + *need_sync_flag = TRUE; + + return codec_data_size; +} + +bool _mc_check_h263_out_bytestream(unsigned char *p, int buf_length, bool* need_sync_flag) +{ + g_return_val_if_fail(need_sync_flag != NULL, MC_PARAM_ERROR); + + *need_sync_flag = FALSE; + + /* PSC not present */ + if ((p[0] != 0x00) || (p[1] != 0x00) || ((p[2]&0xFC) != 0x80)) { + return false; + } + + /* PTYPE Field, Bit 9: Picture Coding Type, "0" INTRA (I-picture), "1" INTER (P-picture) */ + if (!(p[4] & 0x2)) { + *need_sync_flag = TRUE; + } + + return TRUE; +} + diff --git a/src/media_codec_ini.c b/src/media_codec_ini.c new file mode 100755 index 0000000..dd79ebc --- /dev/null +++ b/src/media_codec_ini.c @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2011 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 __MEDIA_CODEC_INI_C__ +#define __MEDIA_CODEC_INI_C__ + +/* includes here */ +#include <glib.h> +#include <stdlib.h> +#include <glib/gstdio.h> +#include <mm_debug.h> +#include <mm_error.h> +#include "iniparser.h" +#include <media_codec_ini.h> +#include <media_codec_port.h> + +#define DEFAULT_VALUE "" + +#define DEFAULT_HW_DECODER_NAME "" +#define DEFAULT_HW_DECODER_MIME "" +#define DEFAULT_HW_DECODER_FORMAT "" + +#define DEFAULT_HW_ENCODER_NAME "" +#define DEFAULT_HW_ENCODER_MIME "" +#define DEFAULT_HW_ENCODER_FORMAT "" + +#define DEFAULT_SW_DECODER_NAME "" +#define DEFAULT_SW_DECODER_MIME "" +#define DEFAULT_SW_DECODER_FORMAT "" + +#define DEFAULT_SW_ENCODER_NAME "" +#define DEFAULT_SW_ENCODER_MIME "" +#define DEFAULT_SW_ENCODER_FORMAT "" + + +#define CNAME_SIZE 512 + +typedef struct { + gchar cname[MEDIA_CODEC_INI_MAX_STRLEN]; + mediacodec_codec_type_e ctype; +}codec_list_t; + +static codec_list_t general_codec_list[]={ + {"h261", MEDIACODEC_H261}, + {"h263", MEDIACODEC_H263}, + {"h264", MEDIACODEC_H264}, + {"mjpeg", MEDIACODEC_MJPEG}, + {"mpeg1", MEDIACODEC_MPEG1}, + {"mpeg2", MEDIACODEC_MPEG2}, + {"mpeg4", MEDIACODEC_MPEG4}, + {"hevc", MEDIACODEC_HEVC}, + {"vp8", MEDIACODEC_VP8}, + {"vp9", MEDIACODEC_VP9}, + {"vc1", MEDIACODEC_VC1}, + {"aac_lc", MEDIACODEC_AAC_LC}, + {"aac_he", MEDIACODEC_AAC_HE}, + {"aac_he_ps", MEDIACODEC_AAC_HE_PS}, + {"mp3", MEDIACODEC_MP3}, + {"amr_nb", MEDIACODEC_AMR_NB}, + {"amr_wb", MEDIACODEC_AMR_WB}, + {"vorbis", MEDIACODEC_VORBIS}, + {"flac", MEDIACODEC_FLAC}, + {"wmav1", MEDIACODEC_WMAV1}, + {"wmav2", MEDIACODEC_WMAV2}, + {"wmapro", MEDIACODEC_WMAPRO}, +}; + +/* internal functions, macros here */ +#ifdef MEDIA_CODEC_DEFAULT_INI +static gboolean _generate_default_ini(void); +#endif + +static void _mc_ini_check_ini_status(void); + +/* macro */ +#define MEDIA_CODEC_INI_GET_STRING( x_dict, x_item, x_ini, x_default ) \ + do \ +{ \ + gchar* str = iniparser_getstring(x_dict, x_ini, x_default); \ + \ + if ( str && \ + ( strlen( str ) > 0 ) && \ + ( strlen( str ) < MEDIA_CODEC_INI_MAX_STRLEN ) ) \ + { \ + strncpy ( x_item, str, strlen(str)+1 ); \ + } \ + else \ + { \ + strncpy ( x_item, x_default, strlen(x_default)+1 ); \ + } \ +}while(0) + +#define MEDIA_CODEC_INI_GET_STRING_FROM_LIST( x_dict, x_list, x_ini, x_default ) \ + do \ +{ \ + char *token = NULL; \ + char *usr_ptr = NULL; \ + int index = 0; \ + const char *delimiters = " ,"; \ + gchar temp_arr[MEDIA_CODEC_INI_MAX_STRLEN] = {0}; \ + MEDIA_CODEC_INI_GET_STRING(x_dict, temp_arr, x_ini, x_default); \ + token = strtok_r( temp_arr, delimiters, &usr_ptr ); \ + while (token) \ + { \ + if (index == 0) \ + strncpy(x_list.name,token, MEDIA_CODEC_INI_MAX_STRLEN-1 );\ + else if (index == 1) \ + strncpy(x_list.mime,token, MEDIA_CODEC_INI_MAX_STRLEN-1 );\ + else if (index == 2) \ + strncpy(x_list.format,token, MEDIA_CODEC_INI_MAX_STRLEN-1 );\ + index++;\ + token = strtok_r( NULL, delimiters, &usr_ptr ); \ + } \ +}while(0) + +#define MEDIA_CODEC_INI_GET_COLOR( x_dict, x_item, x_ini, x_default ) \ + do \ +{ \ + gchar* str = iniparser_getstring(x_dict, x_ini, x_default); \ + \ + if ( str && \ + ( strlen( str ) > 0 ) && \ + ( strlen( str ) < MEDIA_CODEC_INI_MAX_STRLEN ) ) \ + { \ + x_item = (guint) strtoul(str, NULL, 16); \ + } \ + else \ + { \ + x_item = (guint) strtoul(x_default, NULL, 16); \ + } \ +}while(0) + +/* x_ini is the list of index to set TRUE at x_list[index] */ +#define MEDIA_CODEC_INI_GET_BOOLEAN_FROM_LIST( x_dict, x_list, x_list_max, x_ini, x_default ) \ + do \ +{ \ + int index = 0; \ + const char *delimiters = " ,"; \ + char *usr_ptr = NULL; \ + char *token = NULL; \ + gchar temp_arr[MEDIA_CODEC_INI_MAX_STRLEN] = {0}; \ + MEDIA_CODEC_INI_GET_STRING( x_dict, temp_arr, x_ini, x_default); \ + token = strtok_r( temp_arr, delimiters, &usr_ptr ); \ + while (token) \ + { \ + index = atoi(token); \ + if (index < 0 || index > x_list_max -1) \ + { \ + LOGW("%d is not valid index\n", index); \ + } \ + else \ + { \ + x_list[index] = TRUE; \ + } \ + token = strtok_r( NULL, delimiters, &usr_ptr ); \ + } \ +}while(0) + +/* x_ini is the list of value to be set at x_list[index] */ +#define MEDIA_CODEC_INI_GET_INT_FROM_LIST( x_dict, x_list, x_list_max, x_ini, x_default ) \ + do \ +{ \ + int index = 0; \ + int value = 0; \ + const char *delimiters = " ,"; \ + char *usr_ptr = NULL; \ + char *token = NULL; \ + gchar temp_arr[MEDIA_CODEC_INI_MAX_STRLEN] = {0}; \ + MEDIA_CODEC_INI_GET_STRING(x_dict, temp_arr, x_ini, x_default); \ + token = strtok_r( temp_arr, delimiters, &usr_ptr ); \ + while (token) \ + { \ + if ( index > x_list_max -1) \ + { \ + LOGE("%d is not valid index\n", index); \ + break; \ + } \ + else \ + { \ + value = atoi(token); \ + x_list[index] = value; \ + index++; \ + } \ + token = strtok_r( NULL, delimiters, &usr_ptr ); \ + } \ +}while(0) + +#define MEDIA_CODEC_GET_DEFAULT_LIST( x_list, x_default ) \ + do \ +{ \ + strncpy( x_list, x_default, MEDIA_CODEC_INI_MAX_STRLEN - 1);\ +}while(0) +#define MEDIA_CODEC_PRINT_LIST( x_list, x_message ) \ + do \ +{ \ + codec_info_t codec_list= x_list;\ + printf("%s =", x_message);\ + printf("%s %s %s\n", codec_list.name, codec_list.mime, codec_list.format);\ +}while(0) + +media_format_mimetype_e _mc_convert_media_format_str_to_int(char *sformat ) +{ + + media_format_mimetype_e iformat = MEDIA_FORMAT_I420; + if (!strcmp(sformat,"I420")) { + iformat = MEDIA_FORMAT_I420; + goto endf; + } else if (!strcmp(sformat,"NV12")) { + iformat = MEDIA_FORMAT_NV12; + goto endf; + } else if (!strcmp(sformat,"NV12T")) { + iformat = MEDIA_FORMAT_NV12T; + goto endf; + } else if (!strcmp(sformat,"YV12")) { + iformat = MEDIA_FORMAT_YV12; + goto endf; + } else if (!strcmp(sformat,"NV21")) { + iformat = MEDIA_FORMAT_NV21; + goto endf; + } else if (!strcmp(sformat,"NV16")) { + iformat = MEDIA_FORMAT_NV16; + } else if (!strcmp(sformat,"YUYV")) { + iformat = MEDIA_FORMAT_YUYV; + goto endf; + } else if (!strcmp(sformat,"UYVY")) { + iformat = MEDIA_FORMAT_UYVY; + goto endf; + } else if (!strcmp(sformat,"422P")) { + iformat = MEDIA_FORMAT_422P; + goto endf; + } else if (!strcmp(sformat,"RGB565")) { + iformat = MEDIA_FORMAT_RGB565; + goto endf; + } else if (!strcmp(sformat,"RGB888")) { + iformat = MEDIA_FORMAT_RGB888; + goto endf; + } else if (!strcmp(sformat,"RGBA")) { + iformat = MEDIA_FORMAT_RGBA; + goto endf; + } else if (!strcmp(sformat,"ARGB")) { + iformat = MEDIA_FORMAT_ARGB; + goto endf; + } else if (!strcmp(sformat,"PCM")) { + iformat = MEDIA_FORMAT_PCM; + goto endf; + } else if (!strcmp(sformat,"H261")) { + iformat = MEDIA_FORMAT_H261; + goto endf; + } else if (!strcmp(sformat,"H263")) { + iformat = MEDIA_FORMAT_H263; + goto endf; + } else if (!strcmp(sformat,"H263P")) { + iformat = MEDIA_FORMAT_H263P; + goto endf; + } else if (!strcmp(sformat,"H264_SP")) { + iformat = MEDIA_FORMAT_H264_SP; + goto endf; + } else if (!strcmp(sformat,"H264_MP")) { + iformat = MEDIA_FORMAT_H264_MP; + goto endf; + } else if (!strcmp(sformat,"H264_HP")) { + iformat = MEDIA_FORMAT_H264_HP; + goto endf; + } else if (!strcmp(sformat,"MPEG4_SP")) { + iformat = MEDIA_FORMAT_MPEG4_SP; + goto endf; + } else if (!strcmp(sformat,"MPEG4_ASP")) { + iformat = MEDIA_FORMAT_MPEG4_ASP; + goto endf; + } else if (!strcmp(sformat,"AMR_NB")) { + iformat = MEDIA_FORMAT_AMR_NB; + goto endf; + } else if (!strcmp(sformat,"AMR_WB")) { + iformat = MEDIA_FORMAT_AMR_WB; + goto endf; + } else if (!strcmp(sformat,"AAC_LC")) { + iformat = MEDIA_FORMAT_AAC_LC; + goto endf; + } else if (!strcmp(sformat,"AAC_HE")) { + iformat = MEDIA_FORMAT_AAC_HE; + goto endf; + } else if (!strcmp(sformat,"AAC_HE_PS")) { + iformat = MEDIA_FORMAT_AAC_HE_PS; + goto endf; + } else if (!strcmp(sformat,"MP3")) { + iformat = MEDIA_FORMAT_MP3; + goto endf; + } else if (!strcmp(sformat,"VORBIS")) { + iformat = MEDIA_FORMAT_VORBIS; + goto endf; + } else if (!strcmp(sformat,"FLAC")) { + iformat = MEDIA_FORMAT_FLAC; + goto endf; + } else if (!strcmp(sformat,"WMAV1")) { + iformat = MEDIA_FORMAT_WMAV1; + goto endf; + } else if (!strcmp(sformat,"WMAV2")) { + iformat = MEDIA_FORMAT_WMAV2; + goto endf; + } else if (!strcmp(sformat,"WMAPRO")) { + iformat = MEDIA_FORMAT_WMAPRO; + goto endf; + } + +endf: + LOGD("sformat : %x", iformat); + return iformat; +} + +int mc_ini_load(mc_ini_t *ini) +{ + gchar cname[CNAME_SIZE]; + int i = 0; + dictionary *dict = NULL; + + static const int codec_list = sizeof(general_codec_list) / sizeof(general_codec_list[0]); + + _mc_ini_check_ini_status(); + + /* first, try to load existing ini file */ + dict = iniparser_load(MEDIA_CODEC_INI_DEFAULT_PATH); + + /* if no file exists. create one with set of default values */ + if (!dict) { +#ifdef MEDIA_CODEC_DEFAULT_INI + LOGD("No inifile found. codec will create default inifile.\n"); + if (FALSE == _generate_default_ini()) { + LOGW("Creating default inifile failed. Media Codec will use default values.\n"); + } else { + /* load default ini */ + dict = iniparser_load(MEDIA_CODEC_INI_DEFAULT_PATH); + } +#else + LOGD("No ini file found. \n"); + return LOGERROR_FILE_NOT_FOUND; +#endif + } + + /* get ini values */ + memset(ini, 0, sizeof(mc_ini_t)); + + if (dict) {/* if dict is available */ + /* general */ + MEDIA_CODEC_INI_GET_STRING( dict, ini->port_name, "port_in_use:media_codec_port",DEFAULT_PORT); + /* codec */ + for (i = 0; i < codec_list; i++) { + memset(cname, 0x00, CNAME_SIZE); + snprintf(cname, CNAME_SIZE, "%s", general_codec_list[i].cname); + int len = strlen(cname); + + ini->codec[i].codec_id = general_codec_list[i].ctype; + snprintf(cname+len, CNAME_SIZE-len, "%s", ":hw_decoder"); + MEDIA_CODEC_INI_GET_STRING_FROM_LIST( dict, ini->codec[i].codec_info[0], cname, DEFAULT_VALUE); + snprintf(cname+len, CNAME_SIZE-len, "%s",":hw_encoder"); + MEDIA_CODEC_INI_GET_STRING_FROM_LIST( dict, ini->codec[i].codec_info[1], cname, DEFAULT_VALUE); + snprintf(cname+len, CNAME_SIZE-len, "%s",":sw_decoder"); + MEDIA_CODEC_INI_GET_STRING_FROM_LIST( dict, ini->codec[i].codec_info[2], cname, DEFAULT_VALUE); + snprintf(cname+len, CNAME_SIZE-len, "%s",":sw_encoder"); + MEDIA_CODEC_INI_GET_STRING_FROM_LIST( dict, ini->codec[i].codec_info[3], cname, DEFAULT_VALUE); + } + } else {/* if dict is not available just fill the structure with default value */ + + LOGW("failed to load ini. using hardcoded default\n"); + /* general */ + snprintf(ini->port_name, sizeof(ini->port_name), "%s", DEFAULT_PORT); + for (i = 0;i < codec_list; i++) { + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[0].name, DEFAULT_HW_DECODER_NAME); + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[0].mime, DEFAULT_HW_DECODER_MIME); + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[0].format, DEFAULT_HW_DECODER_FORMAT); + + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[1].name, DEFAULT_HW_ENCODER_NAME); + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[1].mime, DEFAULT_HW_ENCODER_MIME); + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[1].format, DEFAULT_HW_ENCODER_FORMAT); + + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[2].name, DEFAULT_SW_DECODER_NAME); + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[2].mime, DEFAULT_SW_DECODER_MIME); + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[2].format, DEFAULT_SW_DECODER_FORMAT); + + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[3].name, DEFAULT_SW_ENCODER_NAME); + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[3].mime, DEFAULT_SW_ENCODER_MIME); + MEDIA_CODEC_GET_DEFAULT_LIST( ini->codec[i].codec_info[3].format, DEFAULT_SW_ENCODER_FORMAT); + } + } + + if (0 == strcmp(ini->port_name, "GST_PORT")) + ini->port_type = GST_PORT; + else { + LOGE("Invalid port is set to [%s] [%d]\n", ini->port_name,ini->port_type); + iniparser_freedict(dict); + goto ERROR; + } + LOGD("The port is set to [%s] [%d]\n", ini->port_name, ini->port_type); + + for (i = 0;i < codec_list; i++) { + memset(cname, 0x00, CNAME_SIZE); + snprintf(cname, CNAME_SIZE, "%s", general_codec_list[i].cname); + int len = strlen(cname); + + snprintf(cname+len, CNAME_SIZE-len, "%s",":hw_decoder"); + MEDIA_CODEC_PRINT_LIST(ini->codec[i].codec_info[0],cname); + snprintf(cname+len, CNAME_SIZE-len, "%s",":hw_encoder"); + MEDIA_CODEC_PRINT_LIST(ini->codec[i].codec_info[1],cname); + snprintf(cname+len, CNAME_SIZE-len, "%s",":sw_decoder"); + MEDIA_CODEC_PRINT_LIST(ini->codec[i].codec_info[2],cname); + snprintf(cname+len, CNAME_SIZE-len, "%s",":sw_encoder"); + MEDIA_CODEC_PRINT_LIST(ini->codec[i].codec_info[3],cname); + } + + /* free dict as we got our own structure */ + iniparser_freedict(dict); + + /* dump structure */ + LOGD("codec settings -----------------------------------\n"); + + /* general */ + LOGD("port_name: %s\n", ini->port_name); + LOGD("port_type : %d\n", ini->port_type); + + return MC_ERROR_NONE; +ERROR: + return MC_COURRPTED_INI; + +} + +static void _mc_ini_check_ini_status(void) +{ + struct stat ini_buff; + + if (g_stat(MEDIA_CODEC_INI_DEFAULT_PATH, &ini_buff) < 0) { + LOGW("failed to get codec ini status\n"); + } else { + if (ini_buff.st_size < 5) { + LOGW("codec.ini file size=%d, Corrupted! So, Removed\n", (int)ini_buff.st_size); + + if (g_remove(MEDIA_CODEC_INI_DEFAULT_PATH) == -1) { + LOGE("failed to delete corrupted ini"); + } + } + } +} + +#ifdef MEDIA_CODEC_DEFAULT_INI +static gboolean _generate_default_ini(void) +{ + FILE *fp = NULL; + gchar *default_ini = MEDIA_CODEC_DEFAULT_INI; + + /* create new file */ + fp = fopen(MEDIA_CODEC_INI_DEFAULT_PATH, "wt"); + + if (!fp) { + return FALSE; + } + + /* writing default ini file */ + if (strlen(default_ini) != + fwrite(default_ini, 1, strlen(default_ini), fp)) { + fclose(fp); + return FALSE; + } + + fclose(fp); + return TRUE; +} +#endif + +void _mc_create_decoder_map_from_ini(mc_handle_t *mediacodec) +{ + int indx = 0, count = 0; + int codec_list = sizeof(general_codec_list) / sizeof(general_codec_list[0]); + for (indx=0;indx <codec_list;indx++) { + if (strcmp(mediacodec->ini.codec[indx].codec_info[0].name, "")) { + mediacodec->decoder_map[count].id = mediacodec->ini.codec[indx].codec_id; + mediacodec->decoder_map[count].hardware = 1; // hardware + mediacodec->decoder_map[count].type.factory_name = mediacodec->ini.codec[indx].codec_info[0].name; + mediacodec->decoder_map[count].type.mime = mediacodec->ini.codec[indx].codec_info[0].mime; + mediacodec->decoder_map[count].type.out_format= _mc_convert_media_format_str_to_int(mediacodec->ini.codec[indx].codec_info[0].format); + count++; + } + + if (strcmp(mediacodec->ini.codec[indx].codec_info[2].name, "")) { + mediacodec->decoder_map[count].id = mediacodec->ini.codec[indx].codec_id; + mediacodec->decoder_map[count].hardware = 0; // software + mediacodec->decoder_map[count].type.factory_name = mediacodec->ini.codec[indx].codec_info[2].name; + mediacodec->decoder_map[count].type.mime = mediacodec->ini.codec[indx].codec_info[2].mime; + mediacodec->decoder_map[count].type.out_format= _mc_convert_media_format_str_to_int(mediacodec->ini.codec[indx].codec_info[2].format); + count++; + } + } + mediacodec->num_supported_decoder = count; + return; + +} + +void _mc_create_encoder_map_from_ini(mc_handle_t *mediacodec) +{ + int indx = 0, count = 0; + int codec_list = sizeof(general_codec_list) / sizeof(general_codec_list[0]); + + for (indx=0;indx <codec_list;indx++) { + if (strcmp(mediacodec->ini.codec[indx].codec_info[1].name, "")) { + mediacodec->encoder_map[count].id = mediacodec->ini.codec[indx].codec_id; + mediacodec->encoder_map[count].hardware = 1; + mediacodec->encoder_map[count].type.factory_name = mediacodec->ini.codec[indx].codec_info[1].name; + mediacodec->encoder_map[count].type.mime = mediacodec->ini.codec[indx].codec_info[1].mime; + mediacodec->encoder_map[count].type.out_format= _mc_convert_media_format_str_to_int(mediacodec->ini.codec[indx].codec_info[1].format); + count++; + } + + if (strcmp(mediacodec->ini.codec[indx].codec_info[3].name, "")) { + mediacodec->encoder_map[count].id = mediacodec->ini.codec[indx].codec_id; + mediacodec->encoder_map[count].hardware = 0; + mediacodec->encoder_map[count].type.factory_name = mediacodec->ini.codec[indx].codec_info[3].name; + mediacodec->encoder_map[count].type.mime = mediacodec->ini.codec[indx].codec_info[3].mime; + mediacodec->encoder_map[count].type.out_format= _mc_convert_media_format_str_to_int(mediacodec->ini.codec[indx].codec_info[3].format); + count++; + } + } + mediacodec->num_supported_encoder = count; + return; + +} +void _mc_create_codec_map_from_ini(mc_handle_t *mediacodec, mc_codec_spec_t *spec_emul) +{ + int indx = 0, count = 0; + int codec_list = sizeof(general_codec_list) / sizeof(general_codec_list[0]); + for (indx=0;indx <codec_list;indx++) { + if (strcmp(mediacodec->ini.codec[indx].codec_info[0].name, "")) { + spec_emul[count].codec_id = mediacodec->ini.codec[indx].codec_id; + spec_emul[count].codec_type = MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW; + spec_emul[count].port_type = MEDIACODEC_PORT_TYPE_GST; + count++; + } + if (strcmp(mediacodec->ini.codec[indx].codec_info[1].name, "")) { + spec_emul[count].codec_id = mediacodec->ini.codec[indx].codec_id; + spec_emul[count].codec_type = MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_HW; + spec_emul[count].port_type = MEDIACODEC_PORT_TYPE_GST; + count++; + } + if (strcmp(mediacodec->ini.codec[indx].codec_info[2].name, "")) { + spec_emul[count].codec_id = mediacodec->ini.codec[indx].codec_id; + spec_emul[count].codec_type = MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW; + spec_emul[count].port_type = MEDIACODEC_PORT_TYPE_GST; + count++; + } + if (strcmp(mediacodec->ini.codec[indx].codec_info[3].name, "")) { + spec_emul[count].codec_id = mediacodec->ini.codec[indx].codec_id; + spec_emul[count].codec_type = MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_SW; + spec_emul[count].port_type = MEDIACODEC_PORT_TYPE_GST; + count++; + } + } + + mediacodec->num_supported_codecs = count; + return; +} + +#endif /* #ifdef _MEDIA_CODEC_INI_C_ */ diff --git a/src/media_codec_port.c b/src/media_codec_port.c index 112b788..0cda9ab 100755 --- a/src/media_codec_port.c +++ b/src/media_codec_port.c @@ -27,22 +27,25 @@ #include <media_codec_spec_emul.h> -//static gboolean _mc_check_is_supported(mc_handle_t* mc_handle, mediacodec_codec_type_e codec_id, mediacodec_support_type_e flags); +static mc_codec_spec_t spec_emul[MEDIA_CODEC_MAX_CODEC_TYPE]; int mc_create(MMHandleType *mediacodec) { - mc_handle_t* new_mediacodec = NULL; + mc_handle_t *new_mediacodec = NULL; int ret = MC_ERROR_NONE; + int i; + int support_list = sizeof(spec_emul) / sizeof(spec_emul[0]); /* alloc mediacodec structure */ - new_mediacodec = (mc_handle_t*)g_malloc(sizeof(mc_handle_t)); - if ( ! new_mediacodec ) - { - LOGE("Cannot allocate memory for player\n"); + new_mediacodec = (mc_handle_t *)g_malloc(sizeof(mc_handle_t)); + + if (!new_mediacodec) { + LOGE("Cannot allocate memory for mediacodec"); ret = MC_ERROR; goto ERROR; } memset(new_mediacodec, 0, sizeof(mc_handle_t)); + memset(spec_emul, 0, sizeof(mc_codec_spec_t)*MEDIA_CODEC_MAX_CODEC_TYPE); new_mediacodec->is_encoder = false; new_mediacodec->is_video = false; @@ -53,102 +56,95 @@ int mc_create(MMHandleType *mediacodec) new_mediacodec->ports[0] = NULL; new_mediacodec->ports[1] = NULL; + new_mediacodec->num_supported_codecs = 0; + new_mediacodec->num_supported_decoder = 0; + new_mediacodec->num_supported_encoder = 0; + new_mediacodec->core = NULL; - g_mutex_init(&new_mediacodec->cmd_lock); - /* - if(!new_mediacodec->cmd_lock) - { - LOGE("failed to create cmd_lock"); + /* load ini files */ + ret = mc_ini_load(&new_mediacodec->ini); + if(ret != MC_ERROR_NONE) goto ERROR; + _mc_create_codec_map_from_ini(new_mediacodec, spec_emul); + + for (i = 0; i < new_mediacodec->num_supported_codecs; i++) { + new_mediacodec->supported_codecs = + g_list_append(new_mediacodec->supported_codecs, GINT_TO_POINTER(spec_emul[i].codec_id)); } - */ + + /* create decoder map from ini */ + _mc_create_decoder_map_from_ini(new_mediacodec); + + /* create encoder map from ini */ + _mc_create_encoder_map_from_ini(new_mediacodec); + *mediacodec = (MMHandleType)new_mediacodec; return ret; - // TO DO ERROR: - // TO DO - // If we need destroy and release for others (cmd, mutex..) - g_mutex_clear(&new_mediacodec->cmd_lock); - free(new_mediacodec); - new_mediacodec = NULL; - return MC_INVALID_ARG; - return ret; + return MC_INVALID_ARG; } int mc_destroy(MMHandleType mediacodec) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *) mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } - MEDIACODEC_CMD_LOCK( mediacodec ); - LOGD("mediacodec : %p", mediacodec); - if(mc_handle->core != NULL) - { - if(mc_gst_unprepare(mc_handle) != MC_ERROR_NONE) - { + if (mc_handle->core != NULL) { + if (mc_gst_unprepare(mc_handle) != MC_ERROR_NONE) { LOGE("mc_gst_unprepare() failed"); return MC_ERROR; } } mc_handle->is_prepared = false; - - MEDIACODEC_CMD_UNLOCK( mediacodec ); + g_list_free(mc_handle->supported_codecs); /* free mediacodec structure */ - if(mc_handle) { - g_free( (void*)mc_handle ); + if (mc_handle) { + g_free((void *)mc_handle); mc_handle = NULL; } + return ret; } int mc_set_codec(MMHandleType mediacodec, mediacodec_codec_type_e codec_id, mediacodec_support_type_e flags) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; - static const int support_list = sizeof(spec_emul) / sizeof(spec_emul[0]); + mc_handle_t *mc_handle = (mc_handle_t *) mediacodec; int i; - if (!mc_handle) - { - LOGE("fail invaild param\n"); + if (!mc_handle) { + LOGE("fail invaild param"); return MC_INVALID_ARG; } - // Mandatory setting - if ( !GET_IS_ENCODER(flags) && !GET_IS_DECODER(flags) ) - { - LOGE("should be encoder or decoder\n"); + /* Mandatory setting */ + if (!GET_IS_ENCODER(flags) && !GET_IS_DECODER(flags)) { + LOGE("should be encoder or decoder"); return MC_PARAM_ERROR; } -/* - if(!_mc_check_is_supported(mc_handle, codec_id, flags)) - return MC_NOT_SUPPORTED; -*/ - for(i = 0; i < support_list; i++) - { - if((codec_id == spec_emul[i].codec_id) && (flags == spec_emul[i].codec_type)) - { + + + for (i = 0; i < mc_handle->num_supported_codecs; i++) { + if ((codec_id == spec_emul[i].codec_id) && (flags == spec_emul[i].codec_type)) { break; } } + LOGD("support_list : %d, i : %d", mc_handle->num_supported_codecs, i); - LOGD("support_list : %d, i : %d", support_list, i); - - if(i == support_list) + if (i == mc_handle->num_supported_codecs) return MC_NOT_SUPPORTED; mc_handle->port_type = spec_emul[i].port_type; @@ -162,66 +158,16 @@ int mc_set_codec(MMHandleType mediacodec, mediacodec_codec_type_e codec_id, medi LOGD("encoder : %d, hardware : %d, codec_id : %x, video : %d", mc_handle->is_encoder, mc_handle->is_hw, mc_handle->codec_id, mc_handle->is_video); -#if 0 - // mc_handle->is_omx = use_omx; - // !!!! make it dynamic - mc_handle->port_type = MEDIACODEC_PORT_TYPE_GST; - - // !!!! only gst case is here. expend it to all. - if (encoder) - { - switch(codec_id) - { - case MEDIACODEC_H264: - mc_handle->supported_codec = GST_ENCODE_H264; - mc_handle->mimetype = MEDIA_FORMAT_H264_HP; - mc_handle->is_video = 1; - break; - case MEDIACODEC_AAC: - mc_handle->supported_codec = GST_ENCODE_AAC; - mc_handle->mimetype = MEDIA_FORMAT_AAC; - mc_handle->is_video = 0; - break; - default: - LOGE("NOT SUPPORTED!!!!"); - break; - } - mc_handle->is_encoder = true; - } - else - { - switch(codec_id) - { - case MEDIACODEC_H264: - mc_handle->supported_codec = GST_DECODE_H264; - mc_handle->mimetype = MEDIA_FORMAT_NV12; - mc_handle->is_video = 1; - break; - case MEDIACODEC_AAC: - mc_handle->supported_codec = GST_DECODE_AAC; - mc_handle->mimetype = MEDIA_FORMAT_PCM; - mc_handle->is_video = 0; - break; - default: - LOGE("NOT SUPPORTED!!!!"); - break; - } - - // !!!! check if need to be dynamic - mc_handle->is_encoder = false; - } -#endif return ret; } int mc_set_vdec_info(MMHandleType mediacodec, int width, int height) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t* mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } @@ -230,23 +176,38 @@ int mc_set_vdec_info(MMHandleType mediacodec, int width, int height) return MC_PARAM_ERROR; MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && !mc_handle->is_encoder, - MEDIACODEC_ERROR_INVALID_PARAMETER,"MEDIACODEC_ERROR_INVALID_PARAMETER"); + MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER"); mc_handle->info.decoder.width = width; mc_handle->info.decoder.height = height; mc_handle->is_prepared = true; + switch (mc_handle->codec_id) { + case MEDIACODEC_H264: + mc_sniff_bitstream = mc_sniff_h264_bitstream; + LOGD("mc_sniff_h264_bitstream"); + break; + case MEDIACODEC_MPEG4: + mc_sniff_bitstream = mc_sniff_mpeg4_bitstream; + break; + case MEDIACODEC_H263: + mc_sniff_bitstream = mc_sniff_h263_bitstream; + break; + default: + LOGE("NOT SUPPORTED!!!!"); + break; + } + return ret; } int mc_set_venc_info(MMHandleType mediacodec, int width, int height, int fps, int target_bits) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *) mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } @@ -255,14 +216,14 @@ int mc_set_venc_info(MMHandleType mediacodec, int width, int height, int fps, in return MC_PARAM_ERROR; MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && mc_handle->is_encoder, - MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER"); + MEDIACODEC_ERROR_INVALID_PARAMETER, "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; - mc_handle->is_prepared = true; + mc_sniff_bitstream = mc_sniff_yuv; return ret; } @@ -270,10 +231,9 @@ int mc_set_venc_info(MMHandleType mediacodec, int width, int height, int fps, in int mc_set_adec_info(MMHandleType mediacodec, int samplerate, int channel, int bit) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *) mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } @@ -282,24 +242,22 @@ int mc_set_adec_info(MMHandleType mediacodec, int samplerate, int channel, int b return MC_PARAM_ERROR; MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && !mc_handle->is_encoder, - MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER"); + MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER"); mc_handle->info.decoder.samplerate = samplerate; mc_handle->info.decoder.channel = channel; mc_handle->info.decoder.bit = bit; - mc_handle->is_prepared = true; return ret; } -int mc_set_aenc_info(MMHandleType mediacodec, int samplerate, int channel, int bit, int bitrate) +int mc_set_aenc_info(MMHandleType mediacodec, int samplerate, int channel, int bit, int bitrate) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t * mc_handle = (mc_handle_t *) mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } @@ -308,7 +266,7 @@ int mc_set_aenc_info(MMHandleType mediacodec, int samplerate, int channel, int b return MC_PARAM_ERROR; MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && mc_handle->is_encoder, - MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER"); + MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER"); mc_handle->info.encoder.samplerate = samplerate; mc_handle->info.encoder.channel = channel; @@ -323,22 +281,18 @@ int mc_set_aenc_info(MMHandleType mediacodec, int samplerate, int channel, int b int mc_prepare(MMHandleType mediacodec) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *) mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } - if(!mc_handle->is_prepared) + if (!mc_handle->is_prepared) return MC_NOT_INITIALIZED; - MEDIACODEC_CMD_LOCK( mediacodec ); - /* setting core details */ - switch ( mc_handle->port_type ) - { + switch (mc_handle->port_type) { case MEDIACODEC_PORT_TYPE_GENERAL: { } @@ -359,27 +313,21 @@ int mc_prepare(MMHandleType mediacodec) break; } - MEDIACODEC_CMD_UNLOCK( mediacodec ); - return ret; } int mc_unprepare(MMHandleType mediacodec) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } - MEDIACODEC_CMD_LOCK( mediacodec ); - /* deinit core details */ - switch ( mc_handle->port_type ) - { + switch (mc_handle->port_type) { case MEDIACODEC_PORT_TYPE_GENERAL: { } @@ -400,76 +348,67 @@ int mc_unprepare(MMHandleType mediacodec) break; } - MEDIACODEC_CMD_UNLOCK( mediacodec ); - return ret; } -int mc_process_input(MMHandleType mediacodec, media_packet_h inbuf, uint64_t timeOutUs ) +int mc_process_input(MMHandleType mediacodec, media_packet_h inbuf, uint64_t timeOutUs) { int ret = MC_ERROR_NONE; - uint64_t buf_size = 0; - void *buf_data = NULL; - bool eos = false; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - - if (!mc_handle) - { - LOGE("fail invaild param\n"); + if (!mc_handle) { + LOGE("fail invaild param"); return MC_INVALID_ARG; } - ret = media_packet_get_buffer_size(inbuf, &buf_size); - if (ret != MEDIA_PACKET_ERROR_NONE) - { - LOGE("invaild input buffer"); - return MC_INVALID_IN_BUF; + if (mc_handle->is_video) { + if ((ret = mc_sniff_bitstream(mc_handle, inbuf)) != MC_ERROR_NONE) { + return MC_INVALID_IN_BUF; + } } - ret = media_packet_get_buffer_data_ptr(inbuf, &buf_data); - if (ret != MEDIA_PACKET_ERROR_NONE) - { - LOGE("invaild input buffer"); - return MC_INVALID_IN_BUF; - } + switch (mc_handle->port_type) { + case MEDIACODEC_PORT_TYPE_GENERAL: + break; - ret = media_packet_is_end_of_stream(inbuf, &eos); - if (ret != MEDIA_PACKET_ERROR_NONE) - { - LOGE("invaild input buffer"); - return MC_INVALID_IN_BUF; - } + case MEDIACODEC_PORT_TYPE_OMX: + break; - if(!eos) - { - if((buf_data == NULL) || (buf_size == 0)) + case MEDIACODEC_PORT_TYPE_GST: { - LOGE("invaild input buffer"); - return MC_INVALID_IN_BUF; + ret = mc_gst_process_input(mc_handle, inbuf, timeOutUs); } + break; + + default: + break; } - MEDIACODEC_CMD_LOCK( mediacodec ); + return ret; +} - switch ( mc_handle->port_type ) - { +int mc_get_output(MMHandleType mediacodec, media_packet_h *outbuf, uint64_t timeOutUs) +{ + int ret = MC_ERROR_NONE; + mc_handle_t *mc_handle = (mc_handle_t *) mediacodec; + + if (!mc_handle) { + LOGE("fail invaild param\n"); + return MC_INVALID_ARG; + } + + /* setting core details */ + switch (mc_handle->port_type) { case MEDIACODEC_PORT_TYPE_GENERAL: - { - //ret = mc_general_process_input(mc_handle->gen_core, inbuf, timeOutUs); - } break; case MEDIACODEC_PORT_TYPE_OMX: - { - //ret = mc_omx_process_input(mc_handle, inbuf, timeOutUs); - } break; case MEDIACODEC_PORT_TYPE_GST: { - ret = mc_gst_process_input(mc_handle, inbuf, timeOutUs); + ret = mc_gst_get_output(mc_handle, outbuf, timeOutUs); } break; @@ -477,42 +416,30 @@ int mc_process_input(MMHandleType mediacodec, media_packet_h inbuf, uint64_t tim break; } - MEDIACODEC_CMD_UNLOCK( mediacodec ); - return ret; } -int mc_get_output(MMHandleType mediacodec, media_packet_h *outbuf, uint64_t timeOutUs) +int mc_flush_buffers(MMHandleType mediacodec) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } - MEDIACODEC_CMD_LOCK( mediacodec ); - /* setting core details */ - switch ( mc_handle->port_type ) - { + switch (mc_handle->port_type) { case MEDIACODEC_PORT_TYPE_GENERAL: - { - //ret= mc_general_get_output(mc_handle->gen_core, outbuf, timeOutUs); - } break; case MEDIACODEC_PORT_TYPE_OMX: - { - //ret = mc_omx_get_output(mc_handle, outbuf, timeOutUs); - } break; case MEDIACODEC_PORT_TYPE_GST: { - ret = mc_gst_get_output(mc_handle, outbuf, timeOutUs); + ret = mc_gst_flush_buffers(mc_handle); } break; @@ -520,49 +447,76 @@ int mc_get_output(MMHandleType mediacodec, media_packet_h *outbuf, uint64_t time break; } - MEDIACODEC_CMD_UNLOCK( mediacodec ); - return ret; } -int mc_set_empty_buffer_cb(MMHandleType mediacodec, mediacodec_input_buffer_used_cb callback, void* user_data) +int mc_get_supported_type(MMHandleType mediacodec, mediacodec_codec_type_e codec_type, bool encoder, int *support_type) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; + mc_codec_map_t *codec_map; + int num_supported_codec = 0; + int i; - if (!mc_handle) - { + *support_type = 0; + + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } + codec_map = encoder ? mc_handle->encoder_map : mc_handle->decoder_map; + num_supported_codec = encoder ? mc_handle->num_supported_encoder : mc_handle->num_supported_decoder; - if(mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) - { - LOGE("Already set mediacodec_empty_buffer_cb\n"); - return MC_PARAM_ERROR; - } - else + for (i = 0; i < num_supported_codec; i++) { - if (!callback) + if (codec_map[i].id == codec_type) { + if (codec_map[i].hardware) + *support_type |= MEDIACODEC_SUPPORT_TYPE_HW; + else + *support_type |= MEDIACODEC_SUPPORT_TYPE_SW; + break; + } + + } + + return ret; +} + +int mc_set_empty_buffer_cb(MMHandleType mediacodec, mediacodec_input_buffer_used_cb callback, void *user_data) +{ + int ret = MC_ERROR_NONE; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; + + if (!mc_handle) { + LOGE("fail invaild param\n"); + return MC_INVALID_ARG; + } + + if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) { + LOGE("Already set mediacodec_empty_buffer_cb"); + return MC_PARAM_ERROR; + } else { + if (!callback) { return MC_INVALID_ARG; } - LOGD("Set empty buffer callback(cb = %p, data = %p)\n", callback, user_data); + LOGD("Set empty buffer callback(cb = %p, data = %p)", callback, user_data); mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER] = (mc_empty_buffer_cb) callback; mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER] = user_data; + return MC_ERROR_NONE; } return ret; } + int mc_unset_empty_buffer_cb(MMHandleType mediacodec) { - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } @@ -573,29 +527,25 @@ int mc_unset_empty_buffer_cb(MMHandleType mediacodec) return MC_ERROR_NONE; } -int mc_set_fill_buffer_cb(MMHandleType mediacodec, mediacodec_output_buffer_available_cb callback, void* user_data) +int mc_set_fill_buffer_cb(MMHandleType mediacodec, mediacodec_output_buffer_available_cb callback, void *user_data) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } - if(mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]) - { - LOGE("Already set mediacodec_fill_buffer_cb\n"); + if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]) { + LOGE("Already set mediacodec_fill_buffer_cb"); return MC_PARAM_ERROR; - } - else - { + } else { if (!callback) { return MC_INVALID_ARG; } - LOGD("Set fill buffer callback(cb = %p, data = %p)\n", callback, user_data); + LOGD("Set fill buffer callback(cb = %p, data = %p)", callback, user_data); mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER] = (mc_fill_buffer_cb) callback; mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_FILLBUFFER] = user_data; @@ -604,12 +554,12 @@ int mc_set_fill_buffer_cb(MMHandleType mediacodec, mediacodec_output_buffer_avai return ret; } + int mc_unset_fill_buffer_cb(MMHandleType mediacodec) { - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } @@ -620,24 +570,20 @@ int mc_unset_fill_buffer_cb(MMHandleType mediacodec) return MC_ERROR_NONE; } -int mc_set_error_cb(MMHandleType mediacodec, mediacodec_error_cb callback, void* user_data) +int mc_set_error_cb(MMHandleType mediacodec, mediacodec_error_cb callback, void *user_data) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *) mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } - if(mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) - { + if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) { LOGE("Already set mediacodec_fill_buffer_cb\n"); return MC_PARAM_ERROR; - } - else - { + } else { if (!callback) { return MC_INVALID_ARG; } @@ -654,11 +600,10 @@ int mc_set_error_cb(MMHandleType mediacodec, mediacodec_error_cb callback, void* int mc_unset_error_cb(MMHandleType mediacodec) { - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { - LOGE("fail invaild param\n"); + if (!mc_handle) { + LOGE("fail invaild param"); return MC_INVALID_ARG; } @@ -668,24 +613,20 @@ int mc_unset_error_cb(MMHandleType mediacodec) return MC_ERROR_NONE; } -int mc_set_eos_cb(MMHandleType mediacodec, mediacodec_eos_cb callback, void* user_data) +int mc_set_eos_cb(MMHandleType mediacodec, mediacodec_eos_cb callback, void *user_data) { int ret = MC_ERROR_NONE; - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *) mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } - if(mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) - { - LOGE("Already set mediacodec_fill_buffer_cb\n"); + if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) { + LOGE("Already set mediacodec_fill_buffer_cb"); return MC_PARAM_ERROR; - } - else - { + } else { if (!callback) { return MC_INVALID_ARG; } @@ -702,10 +643,9 @@ int mc_set_eos_cb(MMHandleType mediacodec, mediacodec_eos_cb callback, void* use int mc_unset_eos_cb(MMHandleType mediacodec) { - mc_handle_t* mc_handle = (mc_handle_t*) mediacodec; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); return MC_INVALID_ARG; } @@ -715,34 +655,229 @@ int mc_unset_eos_cb(MMHandleType mediacodec) return MC_ERROR_NONE; } -/* -gboolean _mc_check_is_supported(mc_handle_t* mc_handle, mediacodec_codec_type_e codec_id, mediacodec_support_type_e flags) + +int mc_set_buffer_status_cb(MMHandleType mediacodec, mediacodec_buffer_status_cb callback, void *user_data) { - int i=0; + int ret = MC_ERROR_NONE; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; - if (!mc_handle) - { + if (!mc_handle) { LOGE("fail invaild param\n"); - return FALSE; + return MC_INVALID_ARG; } - for (i = 0; i < MC_MAX_NUM_CODEC; i++) - { - if (mc_handle->g_media_codec_spec_emul[i].mime == codec_id) - { - if (mc_handle->g_media_codec_spec_emul[i].codec_type & (flags & 0x3)) - { - if (mc_handle->g_media_codec_spec_emul[i].support_type & (flags & 0xC)) - { - mc_handle->port_type = mc_handle->g_media_codec_spec_emul[i].port_type; - LOGD("port type : %d", mc_handle->port_type); - return TRUE; + if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) { + LOGE("Already set mediacodec_need_data_cb\n"); + return MC_PARAM_ERROR; + } else { + if (!callback) { + return MC_INVALID_ARG; + } + + LOGD("Set start feed callback(cb = %p, data = %p)\n", callback, user_data); + + mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS] = (mc_buffer_status_cb) callback; + mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS] = user_data; + return MC_ERROR_NONE; + } + + return ret; +} + +int mc_unset_buffer_status_cb(MMHandleType mediacodec) +{ + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; + + if (!mc_handle) { + LOGE("fail invaild param\n"); + return MC_INVALID_ARG; + } + + mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS] = NULL; + mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS] = NULL; + + return MC_ERROR_NONE; +} + +int mc_set_supported_codec_cb(MMHandleType mediacodec, mediacodec_supported_codec_cb callback, void *user_data) +{ + int ret = MC_ERROR_NONE; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; + + if (!mc_handle) { + LOGE("fail invaild param\n"); + return MC_INVALID_ARG; + } + + if (mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_SUPPORTED_CODEC]) { + LOGE("Already set mediacodec_supported_codec_cb\n"); + return MC_PARAM_ERROR; + } else { + if (!callback) { + return MC_INVALID_ARG; + } + + LOGD("Set event handler callback(cb = %p, data = %p)", callback, user_data); + + mc_handle->user_cb[_MEDIACODEC_EVENT_TYPE_SUPPORTED_CODEC] = (mc_supported_codec_cb) callback; + mc_handle->user_data[_MEDIACODEC_EVENT_TYPE_SUPPORTED_CODEC] = user_data; + return MC_ERROR_NONE; + } + + return ret; +} + +int _mediacodec_foreach_supported_codec(MMHandleType mediacodec, mediacodec_supported_codec_cb callback, void *user_data) +{ + int ret = MC_ERROR_NONE; + mc_handle_t *mc_handle = (mc_handle_t *)mediacodec; + int codecs_num; + gpointer tmp; + + if (!mc_handle) { + LOGE("fail invaild param\n"); + return MC_INVALID_ARG; + } + + if (mc_handle->supported_codecs) { + codecs_num = g_list_length(mc_handle->supported_codecs); + LOGD("supported_codecs : %d", codecs_num); + + while (codecs_num) { + tmp = g_list_nth_data(mc_handle->supported_codecs, codecs_num - 1); + if (tmp) { + if (!callback(GPOINTER_TO_INT(tmp), user_data)) { + ret = MEDIACODEC_ERROR_INTERNAL; + goto CALLBACK_ERROR; } } + codecs_num--; + } + + if (!callback(-1, user_data)) { + ret = MEDIACODEC_ERROR_INTERNAL; + goto CALLBACK_ERROR; + } + } + +CALLBACK_ERROR: + LOGD("foreach callback returned error"); + return ret; +} + +int mc_sniff_h264_bitstream(mc_handle_t *handle, media_packet_h pkt) +{ + int ret = MC_ERROR_NONE; + void *buf_data = NULL; + void *codec_data = NULL; + unsigned int codec_data_size = 0; + uint64_t buf_size = 0; + bool eos = false; + bool codec_config = false; + + media_packet_get_buffer_size(pkt, &buf_size); + media_packet_get_buffer_data_ptr(pkt, &buf_data); + media_packet_get_codec_data(pkt, &codec_data, &codec_data_size); + media_packet_is_end_of_stream(pkt, &eos); + media_packet_is_codec_config(pkt, &codec_config); + + LOGD("codec_data_size : %d, buf_size : %d, codec_config : %d, eos : %d", + codec_data_size, (int)buf_size, codec_config, eos); + + if (codec_config) { + if (codec_data_size == 0) + ret = _mc_check_h264_bytestream(buf_data, (int)buf_size, 0, NULL, NULL, NULL); + } + + return ret; +} +int mc_sniff_mpeg4_bitstream(mc_handle_t *handle, media_packet_h pkt) +{ + uint64_t buf_size = 0; + unsigned char *buf_data = NULL; + void *codec_data = NULL; + int codec_data_size = 0, voss_size = 0; + bool eos = false; + bool codec_config = false; + bool sync_frame = false; + + media_packet_get_buffer_size(pkt, &buf_size); + media_packet_get_buffer_data_ptr(pkt, (void *)&buf_data); + media_packet_get_codec_data(pkt, &codec_data, &codec_data_size); + media_packet_is_end_of_stream(pkt, &eos); + media_packet_is_codec_config(pkt, &codec_config); + media_packet_is_sync_frame(pkt, &sync_frame); + + LOGD("codec_data_size : %d, buff_size : %d, codec_config : %d, sync_frame : %d, eos : %d", + codec_data_size, (int)buf_size, codec_config, sync_frame, eos); + + if (eos) + return MC_ERROR_NONE; + + if (codec_config) { + if (codec_data) { + if (!_mc_is_voss(codec_data, codec_data_size, NULL))/*voss not in codec data */ + return MC_INVALID_IN_BUF; + } + /* Codec data + I-frame in buffer */ + if (_mc_is_voss(buf_data, buf_size, &voss_size)) { + if (_mc_is_ivop(buf_data, buf_size, voss_size)) /* IVOP after codec_data */ + return MC_ERROR_NONE; + } else { + if (_mc_is_ivop(buf_data, buf_size, 0)) /* IVOP at the start */ + return MC_ERROR_NONE; } + } else if (_mc_is_vop(buf_data, buf_size, 0)) + return MC_ERROR_NONE; + + return MC_INVALID_IN_BUF; +} + +int mc_sniff_h263_bitstream(mc_handle_t *handle, media_packet_h pkt) +{ + void *buf_data = NULL; + uint64_t buf_size = 0; + bool eos = false; + + media_packet_get_buffer_size(pkt, &buf_size); + media_packet_get_buffer_data_ptr(pkt, &buf_data); + media_packet_is_end_of_stream(pkt, &eos); + + if (eos) + return MC_ERROR_NONE; + + return _mc_check_valid_h263_frame((unsigned char *)buf_data, (int)buf_size); +} + +int mc_sniff_yuv(mc_handle_t *handle, media_packet_h pkt) +{ + int ret = MC_ERROR_NONE; + +#if 0 /* libtbm, media-tool should be updated */ + uint64_t buf_size = 0; + int plane_num = 0; + int padded_width = 0; + int padded_height = 0; + int allocated_buffer = 0; + int index; + + media_packet_get_buffer_size(pkt, &buf_size); + media_packet_get_video_number_of_planes(pkt, &plane_num); + + for (index = 0; index < plane_num; index++) { + media_packet_get_video_stride_width(pkt, index, &padded_width); + media_packet_get_video_stride_height(pkt, index, &padded_height); + allocated_buffer += padded_width * padded_height; + + LOGD("%d plane size : %d", padded_width * padded_height); } - return FALSE; + if (buf_size > allocated_buffer) { + LOGE("Buffer exceeds maximum size [buf_size: %d, allocated_size :%d", (int)buf_size, allocated_buffer); + ret = MC_INVALID_IN_BUF; + } +#endif + return ret; } -*/ + diff --git a/src/media_codec_port_gst.c b/src/media_codec_port_gst.c index 170b45b..8da277e 100755 --- a/src/media_codec_port_gst.c +++ b/src/media_codec_port_gst.c @@ -33,461 +33,1330 @@ #include <linux/ion.h> #endif -#define GST_MC_EVENT_CODEC_DATA "GstEventCodecData" +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) /* * Internal Implementation */ static gpointer feed_task(gpointer data); +static void __mc_gst_stop_feed(GstElement *pipeline, gpointer data); +static void __mc_gst_start_feed(GstElement *pipeline, guint size, gpointer data); static media_packet_h _mc_get_input_buffer(mc_gst_core_t *core); static gboolean __mc_gst_init_gstreamer(); static int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, media_format_mimetype_e out_mime); -static mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t* core, gchar *factory_name); +static mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, 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 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_output_packet_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data); - -static void _mc_gst_update_caps(mc_gst_core_t *core, media_packet_h pkt, GstCaps **caps); -static mc_gst_buffer_t* _mc_gst_media_packet_to_gstbuffer(mc_gst_core_t* core, GstCaps **caps, media_packet_h pkt, bool codec_config); -static int _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, mc_gst_buffer_t *buff); -static guint32 __mc_get_gst_input_format(media_packet_h packet, bool is_hw); -static media_packet_h __mc_gst_gstbuffer_to_media_packet(mc_gst_core_t* core, GstBuffer* buffer); +static void _mc_gst_update_caps(mc_gst_core_t *core, media_packet_h pkt, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +static GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t *core, GstCaps **caps, media_packet_h pkt, bool codec_config); +static int _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *buff); +static gchar *__mc_get_gst_input_format(media_packet_h packet, bool is_hw); +static media_packet_h __mc_gst_make_media_packet(mc_gst_core_t *core, unsigned char *data, int size); 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 SCMN_IMGB* __mc_gst_make_tbm_buffer(mc_gst_core_t* core, media_packet_h pkt); -static gboolean event_probe_cb(GstPad *pad, GstEvent *event, gpointer user_data); -static GType __mc_gst_buffer_get_type(void); -static void __mc_gst_buffer_class_init(gpointer g_class, gpointer class_data); -static mc_gst_buffer_t* __mc_gst_buffer_new(mc_gst_core_t* core); -static void __mc_gst_buffer_finalize(mc_gst_buffer_t *buffer); - -static gint __gst_handle_stream_error(mc_gst_core_t* core, GError* error, GstMessage * message); -static gint __gst_transform_gsterror( mc_gst_core_t *core, GstMessage * message, GError* error ); -static gint __gst_handle_resource_error(mc_gst_core_t* core, int code ); -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 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 pkt); +static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t* core, media_packet_h pkt, uint64_t size); +static void gst_mediacodec_buffer_finalize(GstMCBuffer *buffer); +static int __mc_set_caps_streamheader(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer*buff, guint streamheader_size); +static int __mc_set_caps_codecdata(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer*buff, guint codecdata_size); + +static gint __gst_handle_stream_error(mc_gst_core_t *core, GError *error, GstMessage *message); +static gint __gst_transform_gsterror(mc_gst_core_t *core, GstMessage *message, GError *error); +static gint __gst_handle_resource_error(mc_gst_core_t *core, int code); +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 int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboolean is_encoder, gboolean is_hw); #ifdef TIZEN_PROFILE_LITE -static int __tbm_get_physical_addr_bo(tbm_bo_handle tbm_bo_handle_fd_t, int* phy_addr, int* phy_size); +static int __tbm_get_physical_addr_bo(tbm_bo_handle tbm_bo_handle_fd_t, int *phy_addr, int *phy_size); #endif +static int _mc_gst_flush_buffers(mc_gst_core_t *core); static void _mc_gst_set_flush_input(mc_gst_core_t *core); static void _mc_gst_set_flush_output(mc_gst_core_t *core); -static GstBufferClass *mc_gst_buffer_parent_class = NULL; - -#define GST_TYPE_MC_BUFFER (__mc_gst_buffer_get_type()) +static int __tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos); +static void __csc_tiled_to_linear_crop(unsigned char *yuv420_dest, + unsigned char *nv12t_src, int yuv420_width, int yuv420_height, + int left, int top, int right, int buttom); + +static void _mc_send_eos_signal(mc_gst_core_t *core); +static void _mc_wait_for_eos(mc_gst_core_t *core); + +/* video vtable */ +int(*vdec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_vdec_packet_with_outbuf, &__mc_vdec_caps}; +int(*venc_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_venc_packet_with_outbuf, &__mc_venc_caps}; + + +int(*vdec_h264_sw_vtable[])() = {&__mc_fill_inbuf_with_packet, /* FFMPEG H.264 Decoder Vtable */ + &__mc_fill_vdec_packet_with_outbuf, + &__mc_vdec_caps}; +int(*vdec_h264_hw_vtable[])() = {&__mc_fill_inbuf_with_packet, /* SPRD H.264 Decoder Vtable */ + &__mc_fill_video_packet_with_mm_video_buffer, + &__mc_sprddec_caps}; +int(*venc_h264_hw_vtable[])() = {&__mc_fill_inbuf_with_mm_video_buffer, /* SPRD H.264 Encoder Vtable */ + &__mc_fill_venc_packet_with_outbuf, + &__mc_sprdenc_caps}; +int(*vdec_mpeg4_sw_vtable[])() = {&__mc_fill_inbuf_with_packet, /* FFMPEG MPEG4 Decoder Vtable */ + &__mc_fill_vdec_packet_with_outbuf, + &__mc_vdec_mpeg4_caps}; +int(*vdec_mpeg4_hw_vtable[])() = {&__mc_fill_inbuf_with_packet, /* SPRD MPEG4 Decoder Vtable */ + &__mc_fill_video_packet_with_mm_video_buffer, + &__mc_sprddec_mpeg4_caps}; +int(*venc_mpeg4_sw_vtable[])() = {&__mc_fill_inbuf_with_venc_packet, /* SPRD MPEG4 Encoder Vtable */ + &__mc_fill_venc_packet_with_outbuf, + &__mc_venc_caps}; +int(*venc_mpeg4_hw_vtable[])() = {&__mc_fill_inbuf_with_mm_video_buffer, /* SPRD MPEG4 Encoder Vtable */ + &__mc_fill_venc_packet_with_outbuf, + &__mc_sprdenc_mpeg4_caps}; +int(*vdec_h263_sw_vtable[])() = {&__mc_fill_inbuf_with_packet, /* FFMPEG MPEG4 Decoder Vtable */ + &__mc_fill_vdec_packet_with_outbuf, + &__mc_vdec_h263_caps}; +int(*vdec_h263_hw_vtable[])() = {&__mc_fill_inbuf_with_packet, /* SPRD MPEG4 Decoder Vtable */ + &__mc_fill_video_packet_with_mm_video_buffer, + &__mc_sprddec_mpeg4_caps}; +int(*venc_h263_sw_vtable[])() = {&__mc_fill_inbuf_with_venc_packet, /* SPRD MPEG4 Encoder Vtable */ + &__mc_fill_venc_packet_with_outbuf, + &__mc_venc_caps}; +int(*venc_h263_hw_vtable[])() = {&__mc_fill_inbuf_with_mm_video_buffer, /* SPRD MPEG4 Encoder Vtable */ + &__mc_fill_venc_packet_with_outbuf, + &__mc_sprdenc_mpeg4_caps}; + +/* audio vtable */ +int(*aenc_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_packet_with_outbuf, &__mc_aenc_caps}; +int(*adec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_packet_with_outbuf, &__mc_adec_caps}; + +int(*aenc_aac_vtable[])() = {&__mc_fill_inbuf_with_packet, /* AAC LC Encoder vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_aenc_aac_caps}; +int(*adec_aac_vtable[])() = {&__mc_fill_inbuf_with_packet, /* AAC LC Decoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_adec_aac_caps}; +int(*adec_aacv12_vtable[])() = {&__mc_fill_inbuf_with_packet, /* AAC HE Decoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_adec_aacv12_caps}; +int(*adec_mp3_vtable[])() = {&__mc_fill_inbuf_with_packet, /* MP3 Decoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_adec_mp3_caps}; +int(*adec_amrnb_vtable[])() = {&__mc_fill_inbuf_with_packet, /* AMR-NB Decoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_adec_amrnb_caps}; +int(*adec_amrwb_vtable[])() = {&__mc_fill_inbuf_with_packet, /* AMR-WB Decoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_adec_amrwb_caps}; +int(*aenc_amrnb_vtable[])() = {&__mc_fill_inbuf_with_packet, /* AMR-NB Encoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_aenc_amrnb_caps}; +int(*adec_vorbis_vtable[])() = {&__mc_fill_inbuf_with_packet, /* VORBIS Decoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_adec_vorbis_caps}; +int(*adec_flac_vtable[])() = {&__mc_fill_inbuf_with_packet, /* FLAC Decoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_adec_flac_caps}; +int(*adec_wma_vtable[])() = {&__mc_fill_inbuf_with_packet, /* WMA Decoder Vtable */ + &__mc_fill_packet_with_outbuf, + &__mc_adec_wma_caps}; -//static uint64_t wait_until = g_get_monotonic_time() + G_TIME_SPAN_SECOND / 2; - -int(*vdec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_vdec_caps}; -int(*venc_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_venc_caps}; -int(*adec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_adec_caps}; -int(*aenc_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_aenc_caps}; -int(*mp3dec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_mp3dec_caps}; -int(*h264dec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_bo, &__mc_vdec_caps}; -int(*h264enc_vtable[])() = {&__mc_fill_inbuf_with_bo, &__mc_fill_outbuf_with_packet, &__mc_venc_caps}; -int(*h263dec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_bo, &__mc_vdec_caps}; -int(*h263enc_vtable[])() = {&__mc_fill_inbuf_with_bo, &__mc_fill_outbuf_with_packet, &__mc_h263enc_caps}; /* - * mc_gst_object functions + * fill_inbuf virtual functions */ -int __mc_fill_input_buffer(mc_gst_core_t *core, mc_gst_buffer_t *buff) -{ - return core->vtable[fill_inbuf](core, buff); -} - -int __mc_fill_output_buffer(mc_gst_core_t *core, GstBuffer* buff, media_packet_h *out_pkt) -{ - return core->vtable[fill_outbuf](core, buff, out_pkt); -} - -int __mc_create_caps(mc_gst_core_t *core, GstCaps **caps) +int __mc_fill_input_buffer(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer *buff) { - return core->vtable[create_caps](core, caps); + return core->vtable[fill_inbuf](core, pkt, buff); } -int __mc_fill_inbuf_with_bo(mc_gst_core_t *core, mc_gst_buffer_t *buff) +int __mc_fill_inbuf_with_mm_video_buffer(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer *mc_buffer) { int ret = MC_ERROR_NONE; - void* buf_data = NULL; - uint64_t buf_size = 0; - MEDIACODEC_FENTER(); + MMVideoBuffer *mm_vbuffer = NULL; + void *buf_data = NULL; + uint64_t buf_size = 0; - if (!buff->pkt) - { - LOGE("output is null"); - return MC_INTERNAL_ERROR; + ret = media_packet_get_buffer_size(pkt, &buf_size); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return MC_ERROR; } - /* copy media_packet to new gstbuffer */ - ret = media_packet_get_buffer_size(buff->pkt, &buf_size); - if (ret != MEDIA_PACKET_ERROR_NONE) - { + ret = media_packet_get_buffer_data_ptr(pkt, &buf_data); + if (ret != MEDIA_PACKET_ERROR_NONE) { LOGW("buffer size get fail"); + return MC_ERROR; } - ret = media_packet_get_buffer_data_ptr(buff->pkt, &buf_data); - if (ret != MEDIA_PACKET_ERROR_NONE) - { - LOGW("buffer size get fail"); - return MC_INTERNAL_ERROR; + mm_vbuffer = __mc_gst_make_tbm_buffer(core, mc_buffer->pkt); + + if (mm_vbuffer != NULL) { + gst_buffer_prepend_memory(mc_buffer->buffer, + gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, mm_vbuffer, sizeof(*mm_vbuffer), 0, + sizeof(*mm_vbuffer), mm_vbuffer, free)); + LOGD("scmn_mm_vbuffer is appended, %d, %d", sizeof(*mm_vbuffer), gst_buffer_n_memory(mc_buffer->buffer)); } - SCMN_IMGB *imgb = NULL; - GST_BUFFER_DATA(buff) = buf_data; - GST_BUFFER_SIZE (buff) = buf_size; - imgb = __mc_gst_make_tbm_buffer(core, buff->pkt); + if (buf_data != NULL) { + gst_buffer_prepend_memory(mc_buffer->buffer, + gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0, + buf_size, mc_buffer, (GDestroyNotify)gst_mediacodec_buffer_finalize)); + LOGD("packet data is apended, %d, %d", buf_size, gst_buffer_n_memory(mc_buffer->buffer)); + } + return ret; +} - if (!imgb) - { - LOGE("get imgb failed"); - return MC_INTERNAL_ERROR; +int __mc_fill_inbuf_with_packet(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer *mc_buffer) +{ + int ret = MC_ERROR_NONE; + void *buf_data = NULL; + uint64_t buf_size = 0; + + ret = media_packet_get_buffer_size(pkt, &buf_size); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return MC_ERROR; } - GST_BUFFER_MALLOCDATA(buff) = (guint8 *)imgb; - LOGD("__mc_fill_inbuf_with_bo :%llu", buf_size); + ret = media_packet_get_buffer_data_ptr(pkt, &buf_data); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return MC_ERROR; + } - MEDIACODEC_FLEAVE(); + if (buf_data != NULL) { + gst_buffer_append_memory(mc_buffer->buffer, + gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data, buf_size, 0, + buf_size, mc_buffer, (GDestroyNotify)gst_mediacodec_buffer_finalize)); + LOGD("packet data is apended"); + } return ret; } -int __mc_fill_inbuf_with_packet(mc_gst_core_t *core, mc_gst_buffer_t *buff) +int __mc_fill_inbuf_with_venc_packet(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer *mc_buffer) { - int ret = MEDIA_PACKET_ERROR_NONE; - void* buf_data = NULL; - uint64_t buf_size = 0; + int ret = MC_ERROR_NONE; + void *uv_ptr = NULL; + void *y_ptr = NULL; + int buf_size = 0; + int stride_width; + int stride_height; + int width; + int height; + uint32_t plane_num; + int i; + int j; + int stride = 0; - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); + mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; - MEDIACODEC_FENTER(); + width = enc_info->width; + height = enc_info->height; - /* copy media_packet to new gstbuffer */ - ret = media_packet_get_buffer_size(buff->pkt, &buf_size); - if (ret != MEDIA_PACKET_ERROR_NONE) - { - LOGW("buffer size get fail"); - return ret; + ret = media_packet_get_number_of_video_planes(pkt, &plane_num); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("media_packet_get_number_of_video_planes failed"); + return MC_ERROR; } - ret = media_packet_get_buffer_data_ptr(buff->pkt, &buf_data); - if (ret != MEDIA_PACKET_ERROR_NONE) - { - LOGW("buffer size get fail"); - return ret; + ret = media_packet_get_video_plane_data_ptr(pkt, 0, &y_ptr); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("media_packet_get_video_plane_data_ptr failed"); + return MC_ERROR; } - //mc_hex_dump("nal", buf_data, 8); - GST_BUFFER_DATA(buff) = buf_data; - GST_BUFFER_SIZE (buff) = buf_size; + ret = media_packet_get_video_stride_width(pkt, 0, &stride_width); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("media_packet_get_video_stride_width failed"); + return MC_ERROR; + } - LOGD("filled with packet,%d, %p", (int)buf_size, buf_data); - MEDIACODEC_FLEAVE(); + ret = media_packet_get_video_stride_height(pkt, 0, &stride_height); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("media_packet_get_video_stride_width failed"); + return MC_ERROR; + } + + if (width == stride_width) { + mc_buffer->buf_size += stride_width * stride_height; + + for (i = 1; i < plane_num; i++) { + media_packet_get_video_plane_data_ptr(pkt, i, &uv_ptr); + media_packet_get_video_stride_width(pkt, i, &stride_width); + media_packet_get_video_stride_height(pkt, i, &stride_height); + + buf_size = stride_width * stride_height; + + memcpy(y_ptr + mc_buffer->buf_size, uv_ptr, buf_size); + LOGD("width is same with stride"); + LOGD("plane : %d, buf_size : %d, total : %d", i, buf_size, mc_buffer->buf_size); + mc_buffer->buf_size += buf_size; + + } + } else { + + for (j = 0; j < height; j++) { + memcpy(y_ptr + mc_buffer->buf_size, y_ptr + stride, width); + mc_buffer->buf_size += width; + stride += stride_width; + } + + stride = 0; + + for (i = 1; i < plane_num; i++) { + media_packet_get_video_plane_data_ptr(pkt, i, &uv_ptr); + media_packet_get_video_stride_width(pkt, i, &stride_width); + media_packet_get_video_stride_height(pkt, i, &stride_height); + + for (j = 0; j < height>>1; j++) { + memcpy(y_ptr + mc_buffer->buf_size, uv_ptr + stride, width>>1); + mc_buffer->buf_size += width>>1; + stride += stride_width; + } + + memcpy(y_ptr + mc_buffer->buf_size, uv_ptr, buf_size); + LOGD("plane : %d, buf_size : %d, total : %d", i, buf_size, mc_buffer->buf_size); + mc_buffer->buf_size += buf_size; + } + } + + if (y_ptr != NULL) { + gst_buffer_append_memory(mc_buffer->buffer, + gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, y_ptr, mc_buffer->buf_size, 0, + mc_buffer->buf_size, mc_buffer, (GDestroyNotify)gst_mediacodec_buffer_finalize)); + LOGD("%d plane data apended : width : %d, height : %d, size : %d", + i, stride_width, stride_height, mc_buffer->buf_size); + } return ret; } -int __mc_fill_outbuf_with_bo(mc_gst_core_t *core, GstBuffer *buff, media_packet_h* out_pkt) -{ - int i = 0;; - int bo_num = 0; - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); - g_return_val_if_fail (buff != NULL, MC_PARAM_ERROR); +/* + * fill_outbuf virtual functions +*/ - MEDIACODEC_FENTER(); +int __mc_fill_output_buffer(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt) +{ + return core->vtable[fill_outbuf](core, data, size, out_pkt); +} - SCMN_IMGB *psimgb = NULL; +int __mc_fill_vdec_packet_with_outbuf(mc_gst_core_t *core, void *data, int size, media_packet_h *pkt) +{ + int i; + int stride_width; + int stride_height; + uint32_t width; + uint32_t height; + uint32_t plane_num; + uint32_t buf_size; + uint32_t plane_size; + int ret = MC_ERROR_NONE; + void *pkt_data = NULL; tbm_surface_h tsurf = NULL; - psimgb = (SCMN_IMGB*)GST_BUFFER_MALLOCDATA(buff); - mc_decoder_info_t *codec_info = (mc_decoder_info_t *)core->codec_info; -#ifdef TBM_API_CHANGE tbm_surface_info_s tsurf_info; + tbm_bo bo[MM_VIDEO_BUFFER_PLANE_MAX]; + tbm_bo_handle thandle; + + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + width = dec_info->width; + height = dec_info->height; + stride_width = ALIGN(width, 4); + stride_height = ALIGN(height, 4); + buf_size = stride_width * stride_height * 3 / 2; + + if (buf_size > size) + return MC_ERROR; + memset(&tsurf_info, 0x0, sizeof(tbm_surface_info_s)); -#endif - /* create tbm surface */ - for (i = 0; i < SCMN_IMGB_MAX_PLANE; i++) - { - if (psimgb->bo[i]) - { - bo_num++; -#ifdef TBM_API_CHANGE - tsurf_info.planes[i].stride = psimgb->s[i]; -#endif - } + bo[0] = tbm_bo_alloc(core->bufmgr, buf_size, TBM_BO_WC); + if (!bo[0]) { + LOGE("bo allocation failed"); + return MC_ERROR; } - if (bo_num > 0) - { -#ifdef TBM_API_CHANGE - tsurf_info.width = codec_info->width; - tsurf_info.height = codec_info->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 = psimgb->s[i]; - tsurf_info.planes[i].size = psimgb->s[i] * psimgb->e[i]; - - if(i < bo_num) - tsurf_info.planes[i].offset = 0; - else - tsurf_info.planes[i].offset = tsurf_info.planes[i - 1].size; + tsurf_info.width = dec_info->width; + tsurf_info.height = dec_info->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); + tsurf_info.size = 0; + + for (i = 0; i < tsurf_info.num_planes; i++) { + if (i == 0) { + tsurf_info.planes[i].stride = stride_width; + tsurf_info.planes[i].size = stride_width * stride_height; + tsurf_info.planes[i].offset = 0; + tsurf_info.size = tsurf_info.planes[i].size; + } else { + tsurf_info.planes[i].stride = stride_width>>1; + tsurf_info.planes[i].size = (stride_width>>1) * (stride_height>>1); + 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; } - - tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, (tbm_bo *)psimgb->bo, bo_num); - LOGD("[NEW API] tbm surface %p", tsurf); -#else - tsurf = tbm_surface_internal_create_with_bos(codec_info->width, codec_info->height, TBM_FORMAT_NV12, (tbm_bo *)psimgb->bo, bo_num); - LOGD("[OLD API] tbm surface %p", tsurf); -#endif } - if (tsurf) - { - media_packet_create_from_tbm_surface(core->output_fmt, tsurf, (media_packet_finalize_cb)__mc_output_buffer_finalize_cb, core, out_pkt); - LOGD("output pkt = %p", *out_pkt); - media_packet_set_extra(*out_pkt, buff); - media_packet_set_buffer_size(*out_pkt, GST_BUFFER_SIZE(buff)); - media_packet_set_pts(*out_pkt, GST_BUFFER_TIMESTAMP(buff)); - } + thandle = tbm_bo_map(bo[0], TBM_DEVICE_CPU, TBM_OPTION_WRITE); + memcpy(thandle.ptr, data, tsurf_info.size); + tbm_bo_unmap(bo[0]); - MEDIACODEC_FLEAVE(); + tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, bo, 1); + + if (tsurf) { + media_packet_create_from_tbm_surface(core->output_fmt, tsurf, + (media_packet_finalize_cb)__mc_output_buffer_finalize_cb, core, pkt); + } return MC_ERROR_NONE; } - -int __mc_fill_outbuf_with_packet(mc_gst_core_t *core, GstBuffer *buff, media_packet_h *out_pkt) +int __mc_fill_video_packet_with_mm_video_buffer(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt) { - void* pkt_data = NULL; + void *pkt_data = NULL; + MMVideoBuffer *mm_vbuffer = NULL; + int i; + int bo_num = 0; - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); - g_return_val_if_fail (buff != NULL, MC_PARAM_ERROR); + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - MEDIACODEC_FENTER(); + mc_decoder_info_t *codec_info = (mc_decoder_info_t *)core->codec_info; + mm_vbuffer = (MMVideoBuffer *)data; + + LOGD("buf_share_method %d", mm_vbuffer->type); + + LOGD("a[0] : %p, a[1] : %p, p[0] : %p, p[1] : %p", + mm_vbuffer->data[0], mm_vbuffer->data[1], mm_vbuffer->handle.paddr[0], mm_vbuffer->handle.paddr[1]); + LOGD("s[0]:%d, e[0]:%d, w[0]:%d, h[0]:%d", + mm_vbuffer->stride_width[0], mm_vbuffer->stride_height[0], mm_vbuffer->width[0], mm_vbuffer->height[0]); + + if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS) { + media_packet_set_buffer_size(*out_pkt, mm_vbuffer->width[0]*mm_vbuffer->height[0]*3/2); + media_packet_get_buffer_data_ptr(*out_pkt, &pkt_data); + + __csc_tiled_to_linear_crop(pkt_data, mm_vbuffer->data[0], + mm_vbuffer->stride_width[0], mm_vbuffer->stride_height[0], 0, 0, 0, 0); + __csc_tiled_to_linear_crop(pkt_data+mm_vbuffer->stride_width[0]*mm_vbuffer->stride_height[0], + mm_vbuffer->data[1], mm_vbuffer->stride_width[0], mm_vbuffer->stride_height[0]/2, 0, 0, 0, 0); + } else if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_DMABUF_FD) { + LOGD("FD type"); + } else if (mm_vbuffer->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) { + tbm_surface_h tsurf = NULL; + 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]; + } + } - media_packet_create_alloc(core->output_fmt, __mc_output_packet_buffer_finalize_cb, core, out_pkt); + if (bo_num > 0) { + tsurf_info.width = codec_info->width; + tsurf_info.height = codec_info->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; - if (!out_pkt) - { - LOGE("out_pkt is null"); - return MC_MEMORY_ERROR; + 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",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); + } + + if (tsurf) { + media_packet_create_from_tbm_surface(core->output_fmt, tsurf, + (media_packet_finalize_cb)__mc_output_buffer_finalize_cb, core, out_pkt); + } } - media_packet_set_extra(*out_pkt, buff); - LOGI("create_gst_buffer = %p", buff); - LOGI("gstbuffer refcount %d", GST_MINI_OBJECT_REFCOUNT_VALUE(buff)); + return MC_ERROR_NONE; +} + +int __mc_fill_packet_with_outbuf(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt) +{ + void *pkt_data = NULL; + int ret = MC_ERROR_NONE; + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - // !!!! this time do memcpy because no way to set data ptr to media packet. - media_packet_set_buffer_size(*out_pkt, GST_BUFFER_SIZE(buff)); + ret = media_packet_create_alloc(core->output_fmt, __mc_output_buffer_finalize_cb, core, out_pkt); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("media_packet_create_alloc failed"); + return MC_ERROR; + } + + media_packet_set_buffer_size(*out_pkt, size); media_packet_get_buffer_data_ptr(*out_pkt, &pkt_data); + memcpy(pkt_data, data, size); - if (!pkt_data) - { - media_packet_destroy(*out_pkt); - return MC_OUTPUT_BUFFER_EMPTY; + return MC_ERROR_NONE; +} + +int __mc_fill_venc_packet_with_outbuf(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt) +{ + void *pkt_data = NULL; + bool codec_config = FALSE; + bool sync_flag = FALSE; + bool slice = FALSE; + int codec_data_size = 0; + int ret = MC_ERROR_NONE; + + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + switch (core->out_mime) { + case MEDIA_FORMAT_H264_SP: + case MEDIA_FORMAT_H264_MP: + case MEDIA_FORMAT_H264_HP: + ret = _mc_check_h264_bytestream((unsigned char *)data, size, 1, &codec_config, &sync_flag, &slice); + break; + case MEDIA_FORMAT_MPEG4_SP: + case MEDIA_FORMAT_MPEG4_ASP: + codec_data_size = _mc_check_mpeg4_out_bytestream((unsigned char *)data, size, &codec_config, &sync_flag); + break; + case MEDIA_FORMAT_H263: + case MEDIA_FORMAT_H263P: + if (!_mc_check_h263_out_bytestream((unsigned char *)data, size, &sync_flag)) + return MC_INVALID_IN_BUF; + break; + default: + return MC_INVALID_IN_BUF; } + LOGD("codec_config : %d, sync_flag : %d, slice : %d", codec_config, sync_flag, slice); - memcpy(pkt_data, GST_BUFFER_DATA(buff), GST_BUFFER_SIZE(buff)); - media_packet_set_pts(*out_pkt, GST_BUFFER_TIMESTAMP(buff)); + ret = media_packet_create_alloc(core->output_fmt, __mc_output_buffer_finalize_cb, core, out_pkt); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("media_packet_create_alloc failed"); + return MC_ERROR; + } - MEDIACODEC_FLEAVE(); + media_packet_set_buffer_size(*out_pkt, size); + media_packet_get_buffer_data_ptr(*out_pkt, &pkt_data); + memcpy(pkt_data, data, size); - return MC_ERROR_NONE; + core->need_sync_flag = sync_flag ? 1 : 0; + core->need_codec_data = codec_config ? 1 : 0; + + return ret; } -int __mc_venc_caps(mc_gst_core_t *core, GstCaps **caps) +/* + * create_caps virtual functions +*/ + +int __mc_create_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) { - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); + return core->vtable[create_caps](core, caps, buff, codec_config); +} - MEDIACODEC_FENTER(); +int __mc_venc_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; - mc_encoder_info_t *enc_info = (mc_encoder_info_t*)core->codec_info; + *caps = gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, "I420", + "width", G_TYPE_INT, enc_info->width, + "height", G_TYPE_INT, enc_info->height, + "framerate", GST_TYPE_FRACTION, enc_info->fps, 1, + NULL); + + LOGD("%d, %d, %d", enc_info->width, enc_info->height, enc_info->fps); + + return MC_ERROR_NONE; +} + +int __mc_sprdenc_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; *caps = gst_caps_new_simple(core->mime, - "format", GST_TYPE_FOURCC, 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); + "format", G_TYPE_STRING, "SN12", + "width", G_TYPE_INT, enc_info->width, + "height", G_TYPE_INT, enc_info->height, + "framerate", GST_TYPE_FRACTION, enc_info->fps, 1, NULL); - g_object_set (GST_OBJECT(core->codec), "byte-stream", TRUE, NULL); - g_object_set (GST_OBJECT(core->codec), "bitrate", enc_info->bitrate*1000, NULL); + g_object_set(GST_OBJECT(core->codec), "byte-stream", TRUE, NULL); + g_object_set(GST_OBJECT(core->codec), "bitrate", enc_info->bitrate*1000, NULL); - LOGD("%d, %d, %d, %d", core->format, enc_info->width, enc_info->height, enc_info->fps); + LOGD("%s, %d, %d, %d", core->format, enc_info->width, enc_info->height, enc_info->fps); - MEDIACODEC_FLEAVE(); return MC_ERROR_NONE; } -int __mc_h263enc_caps(mc_gst_core_t *core, GstCaps **caps) +int __mc_sprdenc_mpeg4_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, bool codec_config) { - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - mc_encoder_info_t *enc_info = (mc_encoder_info_t*)core->codec_info; + mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; - MEDIACODEC_FENTER(); + *caps = gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, "SN12", + "width", G_TYPE_INT, enc_info->width, + "height", G_TYPE_INT, enc_info->height, + "framerate", GST_TYPE_FRACTION, enc_info->fps, 1, NULL); - *caps = gst_caps_new_simple(core->mime, - "format", GST_TYPE_FOURCC, 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); + g_object_set(GST_OBJECT(core->codec), "bitrate", enc_info->bitrate*1000, NULL); - g_object_set (GST_OBJECT(core->codec), "bitrate", enc_info->bitrate*1000, NULL); + LOGD("%s, %d, %d, %d", core->format, enc_info->width, enc_info->height, enc_info->fps); - LOGD("%d, %d, %d, %d", core->format, enc_info->width, enc_info->height, enc_info->fps); - MEDIACODEC_FLEAVE(); + return MC_ERROR_NONE; +} + +int __mc_h264dec_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + LOGD("%d, %d, ", dec_info->width, dec_info->height); + *caps = gst_caps_new_simple(core->mime, + "parsed", G_TYPE_BOOLEAN, TRUE, + "alignment", G_TYPE_STRING, "au", + "stream-format", G_TYPE_STRING, "byte-stream", + "width", G_TYPE_INT, dec_info->width, + "height", G_TYPE_INT, dec_info->height, NULL); + + LOGD("mime : %s, widht :%d, height : %d", core->mime, dec_info->width, dec_info->height); return MC_ERROR_NONE; } -int __mc_mp3dec_caps(mc_gst_core_t *core, GstCaps **caps) +int __mc_sprddec_mpeg4_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) { - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - MEDIACODEC_FENTER(); - mc_decoder_info_t *dec_info = (mc_decoder_info_t*)core->codec_info; + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + LOGD("%d, %d, ", dec_info->width, dec_info->height); *caps = gst_caps_new_simple(core->mime, - "mpegversion", G_TYPE_INT, 1, - "layer", G_TYPE_INT, 3, - "channels", G_TYPE_INT, dec_info->channel, - "rate", G_TYPE_INT, dec_info->samplerate, - NULL); + "mpegversion", G_TYPE_INT, 4, + "width", G_TYPE_INT, dec_info->width, + "height", G_TYPE_INT, dec_info->height, + "framerate", GST_TYPE_FRACTION, 30, 1, + NULL); - MEDIACODEC_FLEAVE(); + LOGD("mime : %s, widht :%d, height : %d", core->mime, dec_info->width, dec_info->height); return MC_ERROR_NONE; } -int __mc_vdec_caps(mc_gst_core_t *core, GstCaps **caps) +int __mc_sprddec_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) { - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - MEDIACODEC_FENTER(); - mc_decoder_info_t *dec_info = (mc_decoder_info_t*)core->codec_info; + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; LOGD("%d, %d, ", dec_info->width, dec_info->height); *caps = gst_caps_new_simple(core->mime, - "width", G_TYPE_INT, dec_info->width, - "height", G_TYPE_INT, dec_info->height, - "framerate", GST_TYPE_FRACTION, 30, 1, NULL); + "width", G_TYPE_INT, dec_info->width, + "height", G_TYPE_INT, dec_info->height, + "framerate", GST_TYPE_FRACTION, 30, 1, + "alignment", G_TYPE_STRING, "au", + "stream-format", G_TYPE_STRING, "byte-stream", NULL); LOGD("mime : %s, widht :%d, height : %d", core->mime, dec_info->width, dec_info->height); - MEDIACODEC_FLEAVE(); + return MC_ERROR_NONE; +} + +int __mc_vdec_h263_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + *caps = gst_caps_new_simple(core->mime, + "variant", G_TYPE_STRING, "itu", NULL); + LOGD("mime : %s, widht :%d, height : %d", core->mime, dec_info->width, dec_info->height); return MC_ERROR_NONE; } -int __mc_aenc_caps(mc_gst_core_t *core, GstCaps **caps) +int __mc_vdec_mpeg4_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) { - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - mc_encoder_info_t *enc_info = (mc_encoder_info_t*)core->codec_info; + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; - MEDIACODEC_FENTER(); + *caps = gst_caps_new_simple(core->mime, + "mpegversion", G_TYPE_INT, 4, + "systemstream", G_TYPE_BOOLEAN, false, NULL); + + LOGD("mime : %s, widht :%d, height : %d", core->mime, dec_info->width, dec_info->height); + return MC_ERROR_NONE; +} + +int __mc_vdec_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; *caps = gst_caps_new_simple(core->mime, - "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, enc_info->bit, - "depth", G_TYPE_INT, enc_info->bit, - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "channels", G_TYPE_INT, enc_info->channel, - "rate", G_TYPE_INT, enc_info->samplerate, NULL); + "alignment", G_TYPE_STRING, "au", + "stream-format", G_TYPE_STRING, "byte-stream", NULL); - MEDIACODEC_FLEAVE(); + LOGD("mime : %s, widht :%d, height : %d", core->mime, dec_info->width, dec_info->height); + return MC_ERROR_NONE; +} + +int __mc_vdec_h264_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + *caps = gst_caps_new_simple(core->mime, + "alignment", G_TYPE_STRING, "au", + "stream-format", G_TYPE_STRING, "byte-stream", NULL); + + LOGD("mime : %s, widht :%d, height : %d", core->mime, dec_info->width, dec_info->height); return MC_ERROR_NONE; } -int __mc_adec_caps(mc_gst_core_t *core, GstCaps **caps) +int __mc_aenc_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) { - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - mc_decoder_info_t *dec_info = (mc_decoder_info_t*)core->codec_info; + mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; - MEDIACODEC_FENTER(); + *caps = gst_caps_new_simple(core->mime, + "rate", G_TYPE_INT, enc_info->samplerate, + "channels", G_TYPE_INT, enc_info->channel, + "format", G_TYPE_STRING, "F32LE", + "layout", G_TYPE_STRING, "interleaved", NULL); + +/* ++----GstAudioEncoder + +----avenc_aac + +Element Properties: + compliance : Adherence of the encoder to the specifications + flags: readable, writable + Enum "GstFFMpegCompliance" Default: 0, "normal" + (2): verystrict - Strictly conform to older spec + (1): strict - Strictly conform to current spec + (0): normal - Normal behavior + (-1): unofficial - Allow unofficial extensions + (-2): experimental - Allow nonstandardized experimental things +*/ + g_object_set(GST_OBJECT(core->codec), "compliance", -2, NULL); + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, enc_info->samplerate, enc_info->channel); + + return MC_ERROR_NONE; +} + +int __mc_aenc_aac_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; *caps = gst_caps_new_simple(core->mime, - "mpegversion", G_TYPE_INT, 4, - "channels", G_TYPE_INT, dec_info->channel, - "rate", G_TYPE_INT, dec_info->samplerate, - NULL); + "rate", G_TYPE_INT, enc_info->samplerate, + "channels", G_TYPE_INT, enc_info->channel, + "format", G_TYPE_STRING, "F32LE", + "layout", G_TYPE_STRING, "interleaved", NULL); - MEDIACODEC_FLEAVE(); + g_object_set(GST_OBJECT(core->codec), "compliance", -2, NULL); + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, enc_info->samplerate, enc_info->channel); return MC_ERROR_NONE; } -int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, media_format_mimetype_e out_mime) +int __mc_aenc_amrnb_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) { - MEDIACODEC_FENTER(); + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); - if(media_format_create(&core->output_fmt) != MEDIA_FORMAT_ERROR_NONE) - { + mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; + + *caps = gst_caps_new_simple(core->mime, + "rate", G_TYPE_INT, enc_info->samplerate, + "channels", G_TYPE_INT, enc_info->channel, + "format", G_TYPE_STRING, "S16LE", + "layout", G_TYPE_STRING, "interleaved", + NULL); + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, enc_info->samplerate, enc_info->channel); + + return MC_ERROR_NONE; +} + +int __mc_adec_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + int ret = MC_ERROR_NONE; + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + LOGD("CAPS for codec_id (MEDIACODEC_AAC_LC - normal ADTS)"); + *caps = gst_caps_new_simple(core->mime, + "framed", G_TYPE_BOOLEAN, TRUE, + "mpegversion", G_TYPE_INT, 4, + "stream-format", G_TYPE_STRING, "adts", + "rate", G_TYPE_INT, dec_info->samplerate, + "channels", G_TYPE_INT, dec_info->channel, + NULL); + + if (codec_config && (!core->encoder)) { + guint codecdata_size = 16; /*AAC_CODECDATA_SIZE = 16 (in testsuit)*/ + ret = __mc_set_caps_codecdata(core, caps, buff, codecdata_size); + if (ret != MC_ERROR_NONE) { + LOGW("__mc_set_caps_codecdata failed"); + return ret; + } + } + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return ret; +} + +int __mc_adec_aac_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config) +{ + int ret = MC_ERROR_NONE; + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + LOGD("CAPS for codec_id (MEDIACODEC_AAC_LC - normal ADTS)"); + *caps = gst_caps_new_simple(core->mime, + "framed", G_TYPE_BOOLEAN, TRUE, + "mpegversion", G_TYPE_INT, 4, + "stream-format", G_TYPE_STRING, "adts", + "rate", G_TYPE_INT, dec_info->samplerate, + "channels", G_TYPE_INT, dec_info->channel, + NULL); + + if (codec_config && (!core->encoder)) { + guint codecdata_size = 16; /*AAC_CODECDATA_SIZE = 16 (in testsuit)*/ + ret = __mc_set_caps_codecdata(core, caps, buff, codecdata_size); + if (ret != MC_ERROR_NONE) { + LOGW("__mc_set_caps_codecdata failed"); + return ret; + } + } + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return ret; +} + +int __mc_adec_aacv12_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, bool codec_config) +{ + int ret = MC_ERROR_NONE; + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + LOGD("CAPS for codec_id (MEDIACODEC_AAC_HE and _PS - MP4/M4A case)"); + *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", + "channels", G_TYPE_INT, dec_info->channel, + "rate", G_TYPE_INT, dec_info->samplerate, + NULL); + + if (codec_config && (!core->encoder)) { + guint codecdata_size = 16; /*AAC_CODECDATA_SIZE = 16 (in testsuit)*/ + ret = __mc_set_caps_codecdata(core, caps, buff, codecdata_size); + if (ret != MC_ERROR_NONE) { + LOGW("__mc_set_caps_codecdata failed"); + return ret; + } + } + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return ret; +} + +int __mc_adec_mp3_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + *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 */ + "rate", G_TYPE_INT, dec_info->samplerate, + "channels", G_TYPE_INT, dec_info->channel, + NULL); + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return MC_ERROR_NONE; +} + +int __mc_adec_amrnb_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + *caps = gst_caps_new_simple(core->mime, + "rate", G_TYPE_INT, 8000, + "channels", G_TYPE_INT, dec_info->channel, /* FIXME - by 1 */ + NULL); + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return MC_ERROR_NONE; +} + +int __mc_adec_amrwb_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + *caps = gst_caps_new_simple(core->mime, + "rate", G_TYPE_INT, 16000, + "channels", G_TYPE_INT, dec_info->channel, /* FIXME - by 1 */ + NULL); + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return MC_ERROR_NONE; +} + +int __mc_adec_vorbis_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + int ret = MC_ERROR_NONE; + + *caps = gst_caps_new_simple(core->mime, + "channels", G_TYPE_INT, dec_info->channel, + "rate", G_TYPE_INT, dec_info->samplerate, + /* FIXME - Insert 'Stream Header' */ + NULL); + + LOGD(" ----- VORBIS Need Additional Caps -----------"); + /* + * Need to extract from each Stream header ... or + * Need to get Demuxer's Caps from each Stream heade + */ + if (codec_config && (!core->encoder)) { + guint streamheader_size = 4096; /* VORBIS_CODECDATA_SIZE = 4096 */ + ret = __mc_set_caps_streamheader(core, caps, buff, streamheader_size); + if (ret != MC_ERROR_NONE) { + LOGW("__mc_set_caps_streamheader failed"); + return ret; + } + } + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return ret; +} + +int __mc_adec_flac_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, bool codec_config) +{ + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + int ret = MC_ERROR_NONE; + + *caps = gst_caps_new_simple(core->mime, + "channels", G_TYPE_INT, dec_info->channel, + "rate", G_TYPE_INT, dec_info->samplerate, + "framed", G_TYPE_BOOLEAN, TRUE, + /* FIXME - Insert More Info */ + NULL); + + LOGD(" ----- FLAC Need Additional Caps -----------"); + /* + * Need to extract from each Stream header ... or + * Need to get Demuxer's Caps from each Stream heade + */ + if (codec_config && (!core->encoder)) { + guint streamheader_size = 4096; /* FLAC_CODECDATA_SIZE = 4096 */ + ret = __mc_set_caps_streamheader(core, caps, buff, streamheader_size); + if (ret != MC_ERROR_NONE) { + LOGW("__mc_set_caps_streamheader failed"); + return ret; + } + } + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return ret; +} + +int __mc_adec_wma_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, bool codec_config) +{ + int ret = MC_ERROR_NONE; + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + mc_decoder_info_t *dec_info = (mc_decoder_info_t *)core->codec_info; + + /* + * 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_WMAPRO) { + format_tag = 355; /* 0x163 */ + wma_version = 3; + } else { + LOGE("Not support WMA format"); + } + + *caps = gst_caps_new_simple(core->mime, + "rate", G_TYPE_INT, dec_info->samplerate, + "channels", G_TYPE_INT, dec_info->channel, + "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); + + if (codec_config && (!core->encoder)) { + guint codecdata_size = 64; /* WMA_CODECDATA_SIZE = 64 */ + ret = __mc_set_caps_codecdata(core, caps, buff, codecdata_size); + if (ret != MC_ERROR_NONE) { + LOGW("__mc_set_caps_codecdata failed"); + return ret; + } + } + + LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel); + + return ret; +} + +/** + * _gst_caps_set_buffer_array: + * @caps: a #GstCaps + * @field: field in caps to set + * @buf: header buffers + * + * Adds given buffers to an array of buffers set as the given @field + * on the given @caps. List of buffer arguments must be NULL-terminated. + * + * Returns: input caps with a streamheader field added, or NULL if some error + */ +static GstCaps *__mc_gst_caps_set_buffer_array(GstCaps * caps, const gchar * field, GstBuffer * buf, ...) +{ + GstStructure *structure = NULL; + va_list va; + GValue array = { 0 }; + GValue value = { 0 }; + + g_return_val_if_fail(caps != NULL, NULL); + g_return_val_if_fail(gst_caps_is_fixed(caps), NULL); + g_return_val_if_fail(field != NULL, NULL); + + caps = gst_caps_make_writable(caps); + structure = gst_caps_get_structure(caps, 0); + + g_value_init(&array, GST_TYPE_ARRAY); + + va_start(va, buf); + /* put buffers in a fixed list */ + while (buf) { + g_value_init(&value, GST_TYPE_BUFFER); + gst_value_set_buffer(&value, buf); + gst_value_array_append_value(&array, &value); + g_value_unset(&value); + + buf = va_arg(va, GstBuffer *); + } + va_end(va); + + gst_structure_take_value(structure, field, &array); + + return caps; +} + + +int __mc_set_caps_streamheader(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer*buff, guint streamheader_size) +{ + int ret = MEDIA_PACKET_ERROR_NONE; + void *buf_data = NULL; + uint64_t buf_size = 0; + GstBuffer *header1, *header2, *header3; + guint hsize1, hsize2, hsize3; + GstBuffer *tmp_header; + guint8 *tmp_buf = NULL; + GstMapInfo map; + + ret = media_packet_get_buffer_size(buff->pkt, &buf_size); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return ret; + } + + ret = media_packet_get_buffer_data_ptr(buff->pkt, &buf_data); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return ret; + } + + LOGD("Set caps for streamheader in mime : %s and codec_id (0x%x)", core->mime, core->codec_id); + + if (core->codec_id == MEDIACODEC_VORBIS) { + /* + * hsize1 : Identification Header (packet type 1) - fixed 30 byte + * hsize2 : Comment Header (packet type 3) - variable byte (need calculate) + * hsize3 : Setup Header (packet type 5) - variable byte (Used remained bytes) + */ + + /* First of all, Need to fins and calculate size of hsize2 */ + tmp_header = gst_buffer_new_and_alloc(streamheader_size); + gst_buffer_fill(tmp_header, 0, buf_data, streamheader_size); + gst_buffer_map(tmp_header, &map, GST_MAP_READ); + tmp_buf = map.data; + tmp_buf += (30 + 7); /* hsize1 + '0x03' + 'vorbis'*/ + hsize2 = (7 + 4); + hsize2 += GST_READ_UINT32_LE(tmp_buf); + hsize2 += (4 + 1); + LOGD("Find streamheader hsize2(%d)", hsize2); + gst_buffer_unmap(tmp_header, &map); + gst_buffer_unref(tmp_header); + + /* hsize1 : Identification Header (packet type 1) - fixed 30 byte */ + hsize1 = 30; + header1 = gst_buffer_new_and_alloc(hsize1); + gst_buffer_fill(header1, 0, buf_data, hsize1); + gst_buffer_map(header1, &map, GST_MAP_READ); + tmp_buf = map.data; + /* '0x01' + 'vorbis' */ + if (*tmp_buf != 0x01) { + LOGE("[ERROR] Invalid Caps of Stream header1"); + gst_buffer_unmap(header1, &map); + return MEDIA_PACKET_ERROR_INVALID_PARAMETER; + } + gst_buffer_unmap(header1, &map); + + /* hsize2 : Comment Header (packet type 3) - variable byte */ + header2 = gst_buffer_new_and_alloc(hsize2); + gst_buffer_fill(header2, 0, (buf_data + (hsize1)), hsize2); + gst_buffer_map(header2, &map, GST_MAP_READ); + tmp_buf = map.data; + /* '0x03' + 'vorbis' */ + if (*tmp_buf != 0x03) { + LOGE("[ERROR] Invalid Caps of Stream header2"); + gst_buffer_unmap(header2, &map); + return MEDIA_PACKET_ERROR_INVALID_PARAMETER; + } + gst_buffer_unmap(header2, &map); + + /* hsize3 : Setup Header (packet type 5) - variable byte */ + hsize3 = streamheader_size - (hsize1 + hsize2); + header3 = gst_buffer_new_and_alloc(hsize3); + gst_buffer_fill(header3, 0, (buf_data + (hsize1 + hsize2)), hsize3); + gst_buffer_map(header3, &map, GST_MAP_READ); + tmp_buf = map.data; + /* '0x05' + 'vorbis' */ + if (*tmp_buf != 0x05) { + LOGE("[ERROR] Invalid Caps of Stream header3"); + gst_buffer_unmap(header3, &map); + return MEDIA_PACKET_ERROR_INVALID_PARAMETER; + } + gst_buffer_unmap(header3, &map); + + LOGD("[vorbis] streamheader hsize1 (%d) + hsize2 (%d) + hsize3 (%d) = Total (%d)", + hsize1, hsize2, hsize3, (hsize1 + hsize2 + hsize3)); + + __mc_gst_caps_set_buffer_array(*caps, "streamheader", header1, header2, header3, NULL); + + gst_buffer_unref(header1); + gst_buffer_unref(header2); + gst_buffer_unref(header3); + } else if (core->codec_id == MEDIACODEC_FLAC) { + /* + * hsize1 : Stream Info (type 0) - fixed 51 byte + * hsize2 : Stream Comment (type 4) - variable byte (need calculate) + */ + + /* First of all, Need to fins and calculate size of hsize2 */ + tmp_header = gst_buffer_new_and_alloc(streamheader_size); + gst_buffer_fill(tmp_header, 0, buf_data, streamheader_size); + gst_buffer_map(tmp_header, &map, GST_MAP_READ); + tmp_buf = map.data; + hsize2 = 4 + ((tmp_buf[52] << 16) | (tmp_buf[53] << 8) | (tmp_buf[54])); + LOGD("Find streamheader hsize2(%d)", hsize2); + gst_buffer_unmap(tmp_header, &map); + gst_buffer_unref(tmp_header); + + /* hsize1 : Stream Info (type 0) - fixed 51 byte */ + hsize1 = 51; + header1 = gst_buffer_new_and_alloc(hsize1); + gst_buffer_fill(header1, 0, buf_data, hsize1); + gst_buffer_map(header1, &map, GST_MAP_READ); + tmp_buf = map.data; + /* '0x7f' + 'FLAC' */ + if (*tmp_buf != 0x07f) { + LOGE("[ERROR] Invalid Caps of Stream header1 (Info)"); + gst_buffer_unmap(header1, &map); + gst_buffer_unref(header1); + return MEDIA_PACKET_ERROR_INVALID_PARAMETER; + } + gst_buffer_unmap(header1, &map); + + /* hsize2 : Stream Comment (type 4) - variable byte (need calculate) */ + header2 = gst_buffer_new_and_alloc(hsize2); + gst_buffer_fill(header2, 0, (buf_data + (hsize1)), hsize2); + gst_buffer_map(header2, &map, GST_MAP_READ); + tmp_buf = map.data; + /* '0x84' */ + if (*tmp_buf != 0x84) { + LOGE("[ERROR] Invalid Caps of Stream header2 (Comment)"); + gst_buffer_unmap(header2, &map); + gst_buffer_unref(header1); + gst_buffer_unref(header2); + return MEDIA_PACKET_ERROR_INVALID_PARAMETER; + } + gst_buffer_unmap(header2, &map); + + LOGD("[flac] streamheader hsize1 (%d) + hsize2 (%d) = Total (%d)", hsize1, hsize2, (hsize1 + hsize2)); + __mc_gst_caps_set_buffer_array(*caps, "streamheader", header1, header2, NULL); + gst_buffer_unref(header1); + gst_buffer_unref(header2); + } else { + LOGE("Not support case of Stream header Caps"); + } + + /* Update gstbuffer's data ptr and size for using previous streamheader.*/ + LOGD("BEFORE : buff->buffer of size %" G_GSIZE_FORMAT "", gst_buffer_get_size(buff->buffer)); + gst_buffer_remove_memory_range(buff->buffer, streamheader_size, -1); + gst_buffer_set_size(buff->buffer, buf_size - streamheader_size); + LOGD("AFTER : buff->buffer of size %" G_GSIZE_FORMAT "", gst_buffer_get_size(buff->buffer)); + + return ret; +} + + + +int __mc_set_caps_codecdata(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer *buff, guint codecdata_size) +{ + int ret = MEDIA_PACKET_ERROR_NONE; + void *buf_data = NULL; + uint64_t buf_size = 0; + GstBuffer *codecdata_buffer; + + ret = media_packet_get_buffer_size(buff->pkt, &buf_size); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return ret; + } + + ret = media_packet_get_buffer_data_ptr(buff->pkt, &buf_data); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return ret; + } + + LOGD("Set caps for codec_data in mime : %s and codec_id (0x%x)", core->mime, core->codec_id); + + /* Add the codec_data attribute to caps, if we have it */ + codecdata_buffer = gst_buffer_new(); + gst_buffer_copy_into(codecdata_buffer, buff->buffer, GST_BUFFER_COPY_MEMORY,0, codecdata_size); + gst_buffer_ref(codecdata_buffer); + LOGD("setting codec_data from (packet) buf_data used codecdata_size (%d)", codecdata_size); + + gst_caps_set_simple(*caps, "codec_data", GST_TYPE_BUFFER, codecdata_buffer, NULL); + gst_buffer_unref(codecdata_buffer); + + /* Update gstbuffer's data ptr and size for using previous codec_data..*/ + LOGD("BEFORE : buff->buffer of size %" G_GSIZE_FORMAT "", gst_buffer_get_size(buff->buffer)); + + gst_buffer_replace_memory(buff->buffer, 0, + gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, buf_data + codecdata_size , buf_size - codecdata_size, 0, + buf_size - codecdata_size, buff, (GDestroyNotify)gst_mediacodec_buffer_finalize)); + + LOGD("AFTER : buff->buffer of size %" G_GSIZE_FORMAT "", gst_buffer_get_size(buff->buffer)); + + return ret; +} + + +int _mc_output_media_packet_new(mc_gst_core_t *core, bool video, bool encoder, media_format_mimetype_e out_mime) +{ + if (media_format_create(&core->output_fmt) != MEDIA_FORMAT_ERROR_NONE) { LOGE("media format create failed"); return MC_ERROR; } - if(encoder) - { + if (encoder) { mc_encoder_info_t *info; - info = (mc_encoder_info_t*)core->codec_info; + info = (mc_encoder_info_t *)core->codec_info; - if (video) - { + 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); - } - else - { + } 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_avg_bps(core->output_fmt, info->bitrate); } - } - else - { + } else { mc_decoder_info_t *info; - info = (mc_decoder_info_t*)core->codec_info; + info = (mc_decoder_info_t *)core->codec_info; - if (video) - { + 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); - } - else - { + } 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); } } - - MEDIACODEC_FLEAVE(); - return MC_ERROR_NONE; } @@ -510,31 +1379,27 @@ mc_gst_core_t *mc_gst_core_new() core->available_queue = g_new0(mc_aqueue_t, 1); core->available_queue->input = mc_async_queue_new(); - //core->eos_mutex = g_mutex_new(); g_mutex_init(&core->eos_mutex); - //core->eos_wait_mutex = g_mutex_new(); - g_mutex_init(&core->eos_wait_mutex); - //core->drain_mutex = g_mutex_new(); - g_mutex_init(&core->drain_mutex); - //core->eos_cond = g_cond_new(); g_cond_init(&core->eos_cond); - //core->eos_waiting_cond = g_cond_new(); - g_cond_init(&core->eos_waiting_cond); - //core->prepare_lock = g_mutex_new(); g_mutex_init(&core->prepare_lock); - //core->push_sem = mc_sem_new(); - //core->pop_sem = mc_sem_new(); + g_mutex_init(&core->drain_lock); core->need_feed = false; core->eos = false; - core->eos_waiting = false; + core->need_codec_data = false; + core->need_sync_flag = false; + core->unprepare_flag = false; core->prepare_count = 0; - //g_atomic_int_set(&core->num_live_buffers, 0); + core->queued_count = 0; + core->dequeued_count = 0; g_atomic_int_set(&core->available_queue->running, 1); - //core->available_queue->thread = g_thread_create(feed_task, core, TRUE, NULL); core->available_queue->thread = g_thread_new("feed thread", &feed_task, core); + core->bufmgr = NULL; + core->drm_fd = -1; + LOGD("gst_core(%p) is created", core); + MEDIACODEC_FLEAVE(); return core; @@ -542,46 +1407,31 @@ mc_gst_core_t *mc_gst_core_new() void mc_gst_core_free(mc_gst_core_t *core) { - mc_aqueue_t *async_queue; - MEDIACODEC_FENTER(); + mc_aqueue_t *async_queue; + async_queue = core->available_queue; - _mc_gst_set_flush_input(core); mc_async_queue_disable(async_queue->input); - //mc_async_queue_flush(async_queue->input); g_atomic_int_set(&async_queue->running, 0); g_thread_join(async_queue->thread); - LOGD("@%p g_thread_join", core); - //mc_sem_free(core->push_sem); - //mc_sem_free(core->pop_sem); - //g_mutex_free(core->drain_mutex); - g_mutex_clear(&core->drain_mutex); - //g_mutex_free(core->eos_mutex); g_mutex_clear(&core->eos_mutex); - //g_mutex_free(core->eos_wait_mutex); - g_mutex_clear(&core->eos_wait_mutex); - //g_mutex_free(core->prepare_lock); g_mutex_clear(&core->prepare_lock); - //g_cond_free(core->eos_cond); + g_mutex_clear(&core->drain_lock); g_cond_clear(&core->eos_cond); - //g_cond_free(core->eos_waiting_cond); - g_cond_clear(&core->eos_waiting_cond); - mc_async_queue_free(async_queue->input); - //mc_async_queue_free(async_queue->output); - //g_queue_free(core->output_queue); + g_free(async_queue); - if(core->ports[1] != NULL) - { + if (core->ports[1] != NULL) { mc_gst_port_free(core->ports[1]); core->ports[1] = NULL; } + LOGD("gst_core(%p) is destroyed", core); g_free(core); MEDIACODEC_FLEAVE(); @@ -592,10 +1442,10 @@ void mc_gst_core_free(mc_gst_core_t *core) */ mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core) { - mc_gst_port_t *port; - MEDIACODEC_FENTER(); + mc_gst_port_t *port; + port = g_new0(mc_gst_port_t, 1); port->core = core; port->num_buffers = -1; @@ -603,14 +1453,13 @@ mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core) port->is_allocated = 0; port->buffers = NULL; - //port->mutex = g_mutex_new(); g_mutex_init(&port->mutex); - //port->buffer_cond = g_cond_new(); g_cond_init(&port->buffer_cond); port->queue = g_queue_new(); - MEDIACODEC_FLEAVE(); + LOGD("gst_port(%p) is created", port); + MEDIACODEC_FLEAVE(); return port; } @@ -622,7 +1471,7 @@ void mc_gst_port_free(mc_gst_port_t *port) g_cond_clear(&port->buffer_cond); g_queue_free(port->queue); - //destroy buffers + LOGD("gst_port(%p) is freed", port); g_free(port); MEDIACODEC_FLEAVE(); @@ -630,323 +1479,246 @@ void mc_gst_port_free(mc_gst_port_t *port) return; } -static void _mc_gst_update_caps(mc_gst_core_t *core, media_packet_h pkt, GstCaps **caps) +static void _mc_gst_update_caps(mc_gst_core_t *core, media_packet_h pkt, GstCaps **caps, GstMCBuffer* buff, bool codec_config) { - //TODO remove is_hw param + /*TODO remove is_hw param*/ core->format = __mc_get_gst_input_format(pkt, core->is_hw); - __mc_create_caps(core, caps); -} - -static gboolean event_probe_cb(GstPad *pad, GstEvent *event, gpointer user_data) -{ - mc_gst_core_t *core = (mc_gst_core_t*)user_data; - const GstStructure *s; - gboolean codec_config = false; - //uint64_t wait_until = g_get_monotonic_time() + G_TIME_SPAN_SECOND / 2; - - switch(GST_EVENT_TYPE (event)) - { - case GST_EVENT_CUSTOM_DOWNSTREAM: - { - s = gst_event_get_structure (event); - if(gst_structure_has_name (s, GST_MC_EVENT_CODEC_DATA)) - { - gst_structure_get_boolean (s, "codec_config", &codec_config); - core->codec_config = codec_config; - LOGD("codec_config : %d", codec_config); - } - break; - } -#if 0 - case GST_EVENT_EOS: - { - g_mutex_lock(core->eos_mutex); - - core->eos = true; - g_cond_signal(core->eos_cond); - LOGD("send eos signal"); - - g_mutex_unlock(core->eos_mutex); - LOGD ("End of stream\n"); - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) - { - ((mc_eos_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS])(core->user_data[_MEDIACODEC_EVENT_TYPE_EOS]); - } - g_mutex_lock(core->eos_mutex); -/* - while(!core->eos) - { - LOGD("waiting for eos signal..."); - //g_cond_wait(core->eos_cond, core->eos_mutex); - if(!g_cond_wait_until(core->eos_cond, core->eos_mutex, wait_until)) - { - core->eos = true; - LOGD("time out"); - - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) - { - ((mc_eos_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS])(core->user_data[_MEDIACODEC_EVENT_TYPE_EOS]); - } - - } - else - LOGD("recevied signal"); - } + GstPad *pad = NULL; + GstCaps *template_caps; - //_mc_gst_set_flush_input(core); - core->eos = false; - LOGD("eos flag set to false"); + pad = gst_element_get_static_pad(core->codec, "src"); + template_caps = gst_pad_get_pad_template_caps(pad); - g_mutex_unlock(core->eos_mutex); -*/ - break; + __mc_create_caps(core, caps, buff, codec_config); + g_object_set(core->appsrc, "caps", *caps, NULL); - } -#endif - default: - break; + if (gst_caps_is_subset(*caps, template_caps)) { + LOGD("new caps is subset of template caps"); } - return true; + gst_object_unref(pad); } static gpointer feed_task(gpointer data) { - mc_gst_core_t *core = (mc_gst_core_t*)data; + mc_gst_core_t *core = (mc_gst_core_t *)data; int ret = MC_ERROR_NONE; bool codec_config = FALSE; bool eos = FALSE; media_packet_h in_buf = NULL; - mc_gst_buffer_t* buff = NULL; + GstMCBuffer *buff = NULL; GstCaps *new_caps = NULL; bool initiative = true; - //uint64_t wait_until = g_get_monotonic_time() + G_TIME_SPAN_SECOND / 2; + MEDIACODEC_FENTER(); - while(g_atomic_int_get(&core->available_queue->running)) - { + while (g_atomic_int_get(&core->available_queue->running)) { LOGD("waiting for next input...."); in_buf = _mc_get_input_buffer(core); - if(!in_buf) + if (!in_buf) goto LEAVE; - if(media_packet_is_codec_config(in_buf, &codec_config) != MEDIA_PACKET_ERROR_NONE) - { + if (media_packet_is_codec_config(in_buf, &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(in_buf, &eos) != MEDIA_PACKET_ERROR_NONE) { LOGE("media_packet_is_end_of_stream failed"); goto ERROR; } - if(codec_config) - initiative = true; - - if(eos) - { - g_mutex_lock(&core->eos_wait_mutex); - core->eos_waiting = true; - g_mutex_unlock(&core->eos_wait_mutex); + buff = _mc_gst_media_packet_to_gstbuffer(core, &new_caps, in_buf, codec_config); + if (!buff) { + LOGW("gstbuffer can't make"); + goto ERROR; } - if(initiative) - { - GstStructure *s; - GstEvent *event; + if (codec_config) + initiative = true; + + if (initiative) { GstPad *pad; - _mc_gst_update_caps(core, in_buf, &new_caps); - gst_app_src_set_caps(GST_APP_SRC(core->appsrc), new_caps); + _mc_gst_update_caps(core, in_buf, &new_caps, buff, codec_config); pad = gst_element_get_static_pad(core->appsrc, "src"); - s = gst_structure_new (GST_MC_EVENT_CODEC_DATA, - "codec_config", G_TYPE_BOOLEAN, true, NULL); - event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); - gst_pad_push_event (pad,event); + gst_pad_push_event(pad, gst_event_new_stream_start("sejun")); gst_object_unref(pad); LOGD("caps updated"); } - buff = _mc_gst_media_packet_to_gstbuffer(core, &new_caps, in_buf, codec_config); - if (!buff) - { - LOGW("gstbuffer can't make"); - goto ERROR; - } - LOGD("gstbuffer refcount %d", GST_MINI_OBJECT_REFCOUNT_VALUE(buff)); - - g_mutex_lock(&core->drain_mutex); /* inject buffer */ ret = _mc_gst_gstbuffer_to_appsrc(core, buff); - if(ret != GST_FLOW_OK) - { + if (ret != GST_FLOW_OK) { LOGE("Failed to push gst buffer"); - g_mutex_unlock(&core->drain_mutex); goto ERROR; } - LOGD("after refcount %d", GST_MINI_OBJECT_REFCOUNT_VALUE(buff)); initiative = false; - g_mutex_unlock(&core->drain_mutex); -#if 1 - if (eos) - { + if (eos) { LOGD("end of stream"); - //goto EOS; - - uint64_t wait_until = g_get_monotonic_time() + G_TIME_SPAN_SECOND / 2; - - g_signal_emit_by_name(core->appsrc, "end-of-stream", &ret); - - while(!core->eos) - { - LOGD("waiting for eos signal..."); - if(!g_cond_wait_until(&core->eos_cond, &core->eos_mutex, wait_until)) - { - core->eos = true; - LOGD("time out"); - } - else - LOGD("recevied signal"); - } - - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) - { - LOGD("eos callback invoked"); - ((mc_eos_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS])(core->user_data[_MEDIACODEC_EVENT_TYPE_EOS]); - } -#if 1 - core->eos = false; - core->eos_waiting = false; - initiative = true; - g_cond_signal(&core->eos_waiting_cond); - LOGD("eos flag set to false"); -#endif -/* - - core->eos = true; - _mc_gst_set_flush_input(core); - - - g_mutex_lock(core->eos_mutex); - - core->eos = false; + gst_app_src_end_of_stream(GST_APP_SRC(core->appsrc)); + _mc_wait_for_eos(core); initiative = true; + } - g_mutex_unlock(core->eos_mutex); - - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) - { - ((mc_eos_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS])(core->user_data[_MEDIACODEC_EVENT_TYPE_EOS]); - LOGD("send eos callback"); - } - //g_signal_emit_by_name(core->appsrc, "end-of-stream", &ret); -*/ - } -#endif continue; ERROR: - - g_mutex_lock(&core->drain_mutex); _mc_gst_set_flush_input(core); - g_mutex_unlock(&core->drain_mutex); - - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) - { - ((mc_error_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR])(MC_INTERNAL_ERROR, core->user_data[_MEDIACODEC_EVENT_TYPE_ERROR]); - } - - continue; -/* -EOS: - - g_signal_emit_by_name(core->appsrc, "end-of-stream", &ret); - - while(!core->eos) - { - LOGD("waiting for eos signal..."); - //g_cond_wait(core->eos_cond, core->eos_mutex); - if(!g_cond_wait_until(core->eos_cond, core->eos_mutex, wait_until)) - { - core->eos = true; - LOGD("time out"); - - } - else - LOGD("recevied signal"); - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) - { - LOGD("eos callback invoked"); - ((mc_eos_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS])(core->user_data[_MEDIACODEC_EVENT_TYPE_EOS]); - } + if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) { + ((mc_error_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) + (MC_INTERNAL_ERROR, core->user_data[_MEDIACODEC_EVENT_TYPE_ERROR]); } - core->eos = false; - core->eos_waiting = false; - g_cond_signal(core->eos_waiting_cond); - initiative = true; - LOGD("eos flag set to false"); 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 : in_buf : %p, codec_config : %d, eos : %d, encoder : %d in feed_task", in_buf, codec_config, eos, core->encoder);*/ continue; } - if(new_caps) - { + if (new_caps) { gst_caps_unref(new_caps); } - 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 : in_buf : %p, codec_config : %d, eos : %d, video : %d, encoder : %d in feed_task", + in_buf, codec_config, eos, core->video, core->encoder); LOGD("feed task finished %p v(%d)e(%d)", core, core->video, core->encoder); + MEDIACODEC_FLEAVE(); return NULL; } +static void __mc_gst_stop_feed(GstElement *pipeline, gpointer data) +{ + mc_gst_core_t *core = (mc_gst_core_t *)data; + + LOGI("stop_feed called"); + if (core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) { + ((mc_buffer_status_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) + (MEDIACODEC_ENOUGH_DATA, core->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]); + } +} + +static void __mc_gst_start_feed(GstElement *pipeline, guint size, gpointer data) +{ + mc_gst_core_t *core = (mc_gst_core_t *)data; + + LOGI("start_feed called"); + + if (core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) { + ((mc_buffer_status_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]) + (MEDIACODEC_NEED_DATA, core->user_data[_MEDIACODEC_EVENT_TYPE_BUFFER_STATUS]); + } +} + static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboolean encoder, gboolean is_hw) { - g_return_val_if_fail (core != NULL, MC_PARAM_ERROR); + MEDIACODEC_FENTER(); - switch (id) - { + g_return_val_if_fail(core != NULL, MC_PARAM_ERROR); + + switch (id) { case MEDIACODEC_AAC: { - LOGD("aac vtable"); - core->vtable = encoder ? aenc_vtable : adec_vtable; + /* if set to 'CODEC_CONFIG', then It is also available case of MEDIA_FORMAT_AAC_LC (RAW) */ + LOGD("aac lc (adts) vtable"); + core->vtable = encoder ? aenc_aac_vtable : adec_aac_vtable; + break; + } + case MEDIACODEC_AAC_HE: + case MEDIACODEC_AAC_HE_PS: + { + LOGD("aac he v12 vtable"); + core->vtable = encoder ? aenc_aac_vtable : adec_aacv12_vtable; + if (encoder) { + LOGD("[MC_NOT_SUPPORTED] he-aac-v12 encoder is not supported yet!!!"); + return MC_NOT_SUPPORTED; + } break; } case MEDIACODEC_MP3: { - LOGD("mp3 vtable"); - core->vtable = encoder ? aenc_vtable :mp3dec_vtable; + LOGD("mp3 vtable - Only support decoder"); + core->vtable = encoder ? aenc_vtable : adec_mp3_vtable; + if (encoder) { + LOGD("[MC_NOT_SUPPORTED] mp3 encoder is not supported yet!!!"); + return MC_NOT_SUPPORTED; + } + break; + } + case MEDIACODEC_AMR_NB: + { + LOGD("amrnb vtable"); + core->vtable = encoder ? aenc_amrnb_vtable : adec_amrnb_vtable; + break; + } + case MEDIACODEC_AMR_WB: + { + LOGD("amrwb vtable - Only support decoder"); + core->vtable = encoder ? aenc_vtable : adec_amrwb_vtable; + if (encoder) { + LOGD("[MC_NOT_SUPPORTED] amr-wb encoder is not supported yet!!!"); + return MC_NOT_SUPPORTED; + } + break; + } + case MEDIACODEC_VORBIS: + { + LOGD("vorbis vtable"); + core->vtable = encoder ? aenc_vtable : adec_vorbis_vtable; + if (encoder) { + LOGD("[MC_NOT_SUPPORTED] vorbis encoder is not supported yet!!!"); + return MC_NOT_SUPPORTED; + } + break; + } + case MEDIACODEC_FLAC: + { + LOGD("flac vtable"); + core->vtable = encoder ? aenc_vtable : adec_flac_vtable; + if (encoder) { + LOGD("[MC_NOT_SUPPORTED] flac encoder is not supported yet!!!"); + return MC_NOT_SUPPORTED; + } + break; + } + case MEDIACODEC_WMAV1: + case MEDIACODEC_WMAV2: + case MEDIACODEC_WMAPRO: + case MEDIACODEC_WMALSL: + { + LOGD("wma(V1 / V2 / LSL / PRO) vtable"); + core->vtable = encoder ? aenc_vtable : adec_wma_vtable; + if (encoder) { + LOGD("[MC_NOT_SUPPORTED] wma encoder is not supported yet!!!"); + return MC_NOT_SUPPORTED; + } break; } case MEDIACODEC_H263: { LOGD("h263 vtable"); - if(is_hw) - core->vtable = encoder ? h263enc_vtable : h263dec_vtable; - else - core->vtable = encoder ? venc_vtable : vdec_vtable; + core->vtable = encoder ? (is_hw ? venc_h263_hw_vtable : venc_h263_sw_vtable) : is_hw ? vdec_h263_hw_vtable : vdec_h263_sw_vtable; + break; + } + case MEDIACODEC_MPEG4: + { + LOGD("mpeg4 vtable"); + core->vtable = encoder ? (is_hw ? venc_mpeg4_hw_vtable : venc_mpeg4_sw_vtable) : is_hw ? vdec_mpeg4_hw_vtable : vdec_mpeg4_sw_vtable; + break; } case MEDIACODEC_H264: { LOGD("h264 vtable"); - if(is_hw) - core->vtable = encoder ? h264enc_vtable : h264dec_vtable; - else - core->vtable = encoder ? venc_vtable : vdec_vtable; + core->vtable = encoder ? (is_hw ? venc_h264_hw_vtable : venc_vtable) : is_hw ? vdec_h264_hw_vtable : vdec_h264_sw_vtable; break; } default: @@ -956,14 +1728,16 @@ static int _mc_link_vtable(mc_gst_core_t *core, mediacodec_codec_type_e id, gboo return MC_ERROR_NONE; } -static int _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, mc_gst_buffer_t *buff) +static int _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *buff) { - int ret = MC_ERROR_NONE; MEDIACODEC_FENTER(); - ret = gst_app_src_push_buffer(GST_APP_SRC(core->appsrc), (GstBuffer*)buff); + int ret = MC_ERROR_NONE; - MEDIACODEC_FLEAVE(); + LOGD("pushed buffer to appsrc : %p, buffer of size %" G_GSIZE_FORMAT "", + buff->buffer, gst_buffer_get_size(buff->buffer)); + + ret = gst_app_src_push_buffer(GST_APP_SRC(core->appsrc), buff->buffer); return ret; } @@ -976,8 +1750,11 @@ media_packet_h _mc_get_input_buffer(mc_gst_core_t *core) mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) { + MEDIACODEC_FENTER(); + int ret = MC_ERROR_NONE; media_format_mimetype_e out_mime; + int num_supported_codec=0; int i = 0; if (!mc_handle) @@ -988,64 +1765,62 @@ mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle) bool encoder; bool hardware; gchar *factory_name = NULL; - static const mc_codec_map_t *codec_map; - //media_packet_h out_pkt = NULL; - - MEDIACODEC_FENTER(); + mc_codec_map_t *codec_map; id = mc_handle->codec_id; video = mc_handle->is_video; encoder = mc_handle->is_encoder; hardware = mc_handle->is_hw; + codec_map = encoder ? mc_handle->encoder_map : mc_handle->decoder_map; + num_supported_codec = encoder ? mc_handle->num_supported_encoder : mc_handle->num_supported_decoder; - const int codec_list = encoder ? (sizeof(encoder_map) / sizeof(encoder_map[0])) : (sizeof(decoder_map) / sizeof(decoder_map[0])); - - codec_map = encoder ? encoder_map : decoder_map; - - for(i = 0; i < codec_list; i++) - { - if((id == codec_map[i].id) && (hardware == codec_map[i].hardware)) + for (i = 0; i < num_supported_codec; i++){ + if ((id == codec_map[i].id) && (hardware == codec_map[i].hardware)) break; } - if( i == codec_list ) + if (i == num_supported_codec) return MC_NOT_SUPPORTED; factory_name = codec_map[i].type.factory_name; out_mime = codec_map[i].type.out_format; /* gst_core create */ - mc_gst_core_t* new_core = mc_gst_core_new(); + mc_gst_core_t *new_core = mc_gst_core_new(); new_core->mime = codec_map[i].type.mime; new_core->is_hw = hardware; 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->codec_info = encoder ? (void *)&mc_handle->info.encoder : (void *)&mc_handle->info.decoder; + new_core->out_mime = codec_map[i].type.out_format; + new_core->codec_id = id; + + new_core->bufmgr = tbm_bufmgr_init(new_core->drm_fd); + if (new_core->bufmgr == NULL) { + LOGE("TBM initialization failed"); + return MC_ERROR; + } LOGD("@%p(%p) core is initializing...v(%d)e(%d)", mc_handle, new_core, new_core->video, new_core->encoder); - LOGD("factory name : %s, output_fmt : %x, mime %s", factory_name, out_mime, new_core->mime); + 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) - { + if ((ret = _mc_output_media_packet_new(new_core, video, encoder, out_mime)) != MC_ERROR_NONE) { LOGE("Failed to create output pakcet"); return ret; } /* link vtable */ - if((ret = _mc_link_vtable(new_core, id, encoder, hardware)) != MC_ERROR_NONE) - { + if ((ret = _mc_link_vtable(new_core, id, encoder, hardware)) != MC_ERROR_NONE) { LOGE("vtable link failed"); return ret; } - for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER ; i++) - { + for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER ; i++) { LOGD("copy cb function [%d]", i); - if (mc_handle->user_cb[i]) - { + if (mc_handle->user_cb[i]) { new_core->user_cb[i] = mc_handle->user_cb[i]; new_core->user_data[i] = mc_handle->user_data[i]; LOGD("user_cb[%d] %p, %p", i, new_core->user_cb[i], mc_handle->user_cb[i]); @@ -1057,107 +1832,105 @@ 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); - MEDIACODEC_FLEAVE(); - + LOGD("initialized... %d", ret); return ret; } mc_ret_e mc_gst_unprepare(mc_handle_t *mc_handle) { + MEDIACODEC_FENTER(); + int i; int ret = MC_ERROR_NONE; mc_gst_core_t *core = NULL; - uint64_t wait_until = g_get_monotonic_time() + G_TIME_SPAN_SECOND / 2; - - MEDIACODEC_FENTER(); if (!mc_handle) return MC_PARAM_ERROR; - core = (mc_gst_core_t*)mc_handle->core; + core = (mc_gst_core_t *)mc_handle->core; - if(core) - { - LOGD("@%p(%p) core is uninitializing... v(%d)e(%d)",mc_handle, core, core->video, core->encoder); + if (core) { + LOGD("@%p(%p) core is uninitializing... v(%d)e(%d)", mc_handle, core, core->video, core->encoder); - g_mutex_lock(&core->eos_wait_mutex); - - if(core->eos_waiting) - { - LOGD("waiting for eos is finished"); - if(!g_cond_wait_until(&core->eos_waiting_cond, &core->eos_wait_mutex, wait_until)) - { - core->eos_waiting = false; - LOGD("time out"); - } - else - { - LOGD("recevied signal from feed_task"); - } + g_mutex_lock(&core->drain_lock); + core->unprepare_flag = TRUE; + g_mutex_unlock(&core->drain_lock); + if (core->eos) { + _mc_send_eos_signal(core); } - g_mutex_unlock(&core->eos_wait_mutex); - - - LOGD("%p/%p(%d) input flush", mc_handle, core, core->encoder); - g_mutex_lock(&core->drain_mutex); _mc_gst_set_flush_input(core); - g_mutex_unlock(&core->drain_mutex); - - - - _mc_gst_set_flush_output(core); - + ret = _mc_gst_destroy_pipeline(core); /* unset callback */ - for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER ; i++) - { + for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER; i++) { LOGD("unset cb function [%d]", i); - if (mc_handle->user_cb[i]) - { + if (mc_handle->user_cb[i]) { core->user_cb[i] = NULL; core->user_data[i] = NULL; LOGD("user_cb[%d] %p, %p", i, core->user_cb[i], mc_handle->user_cb[i]); } } - ret = _mc_gst_destroy_pipeline(core); + media_format_unref(core->output_fmt); - if(core != NULL) - { + if (core->bufmgr != NULL) { + tbm_bufmgr_deinit(core->bufmgr); + core->bufmgr = NULL; + } + + if(core->drm_fd != -1) { + close(core->drm_fd); + LOGD("close drm_fd"); + } + + if (core != NULL) { mc_gst_core_free(core); mc_handle->core = NULL; } } - MEDIACODEC_FLEAVE(); - return ret; } mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint64_t timeOutUs) { + MEDIACODEC_FENTER(); + int ret = MC_ERROR_NONE; mc_gst_core_t *core = NULL; + GTimeVal nowtv; if (!mc_handle) return MC_PARAM_ERROR; - core = (mc_gst_core_t*)mc_handle->core; - LOGI("@%p v(%d)e(%d)process_input", core, core->video, core->encoder); + core = (mc_gst_core_t *)mc_handle->core; - MEDIACODEC_FENTER(); + g_get_current_time(&nowtv); + g_time_val_add(&nowtv, 500 * 1000); /* usec */ +/* + if (!g_cond_timed_wait(&nowtv)) { + } +*/ - g_mutex_lock(&core->eos_mutex); + if (core->prepare_count == 0) + return MEDIACODEC_ERROR_INVALID_STATE; - if(!core->eos) + g_mutex_lock(&core->drain_lock); + + if (!core->eos || !core->unprepare_flag) { mc_async_queue_push(core->available_queue->input, inbuf); - else + + } else { ret = MC_INVALID_IN_BUF; + return ret; + } - g_mutex_unlock(&core->eos_mutex); + g_mutex_unlock(&core->drain_lock); + LOGI("@v(%d)e(%d)process_input(%d): %p", core->video, core->encoder, core->queued_count, inbuf); + core->queued_count++; MEDIACODEC_FLEAVE(); @@ -1166,6 +1939,8 @@ mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint64_t timeOutUs) { + MEDIACODEC_FENTER(); + int ret = MC_ERROR_NONE; mc_gst_core_t *core = NULL; media_packet_h out_pkt = NULL; @@ -1173,20 +1948,15 @@ mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint6 if (!mc_handle) return MC_PARAM_ERROR; - MEDIACODEC_FENTER(); - - core = (mc_gst_core_t*)mc_handle->core; + core = (mc_gst_core_t *)mc_handle->core; LOGI("@%p v(%d)e(%d) get_output", core, core->video, core->encoder); g_mutex_lock(&core->ports[1]->mutex); - if(!g_queue_is_empty(core->ports[1]->queue)) - { + if (!g_queue_is_empty(core->ports[1]->queue)) { out_pkt = g_queue_pop_head(core->ports[1]->queue); LOGD("pop from output_queue : %p", out_pkt); - } - else - { + } else { ret = MC_OUTPUT_BUFFER_EMPTY; LOGD("output_queue is empty"); } @@ -1201,19 +1971,18 @@ mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint6 mc_ret_e mc_gst_flush_buffers(mc_handle_t *mc_handle) { + MEDIACODEC_FENTER(); + int ret = MC_ERROR_NONE; mc_gst_core_t *core = NULL; if (!mc_handle) return MC_PARAM_ERROR; - MEDIACODEC_FENTER(); - - core = (mc_gst_core_t*)mc_handle->core; - LOGI("@%p v(%d)e(%d) get_output", core, core->video, core->encoder); + core = (mc_gst_core_t *)mc_handle->core; + LOGI("@%p v(%d)e(%d) flush_buffers", core, core->video, core->encoder); - _mc_gst_set_flush_input(core); - _mc_gst_set_flush_output(core); + ret = _mc_gst_flush_buffers(core); MEDIACODEC_FLEAVE(); @@ -1222,37 +1991,36 @@ mc_ret_e mc_gst_flush_buffers(mc_handle_t *mc_handle) static gboolean __mc_gst_init_gstreamer() { + MEDIACODEC_FENTER(); + static gboolean initialized = FALSE; static const int max_argc = 50; - gint* argc = NULL; - gchar** argv = NULL; - gchar** argv2 = NULL; + gint *argc = NULL; + gchar **argv = NULL; + gchar **argv2 = NULL; GError *err = NULL; int i = 0; int arg_count = 0; - MEDIACODEC_FENTER(); - - if ( initialized ) - { + if (initialized) { LOGD("gstreamer already initialized.\n"); return TRUE; } /* alloc */ - argc = malloc( sizeof(int) ); - argv = malloc( sizeof(gchar*) * max_argc ); - argv2 = malloc( sizeof(gchar*) * max_argc ); + argc = malloc(sizeof(int)); + argv = malloc(sizeof(gchar *) *max_argc); + argv2 = malloc(sizeof(gchar *) *max_argc); - if ( !argc || !argv || !argv2 ) + if (!argc || !argv || !argv2) goto ERROR; - memset( argv, 0, sizeof(gchar*) * max_argc ); - memset( argv2, 0, sizeof(gchar*) * max_argc ); + memset(argv, 0, sizeof(gchar *) *max_argc); + memset(argv2, 0, sizeof(gchar *) *max_argc); /* add initial */ *argc = 1; - argv[0] = g_strdup( "media codec" ); + argv[0] = g_strdup("media codec"); /* we would not do fork for scanning plugins */ argv[*argc] = g_strdup("--gst-disable-registry-fork"); @@ -1270,80 +2038,69 @@ static gboolean __mc_gst_init_gstreamer() LOGD("argc : %d\n", *argc); arg_count = *argc; - for ( i = 0; i < arg_count; i++ ) - { + for (i = 0; i < arg_count; i++) { argv2[i] = argv[i]; LOGD("argv[%d] : %s\n", i, argv2[i]); } /* initializing gstreamer */ - if ( ! gst_init_check (argc, &argv, &err)) - { + if (!gst_init_check(argc, &argv, &err)) { LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred"); - if (err) - { - g_error_free (err); + if (err) { + g_error_free(err); } goto ERROR; } /* release */ - for ( i = 0; i < arg_count; i++ ) - { - //debug_log("release - argv[%d] : %s\n", i, argv2[i]); - MC_FREEIF( argv2[i] ); + for (i = 0; i < arg_count; i++) { + MC_FREEIF(argv2[i]); } - MC_FREEIF( argv ); - MC_FREEIF( argv2 ); - MC_FREEIF( argc ); + MC_FREEIF(argv); + MC_FREEIF(argv2); + MC_FREEIF(argc); /* done */ initialized = TRUE; MEDIACODEC_FLEAVE(); - return TRUE; ERROR: /* release */ - for ( i = 0; i < arg_count; i++ ) - { + for (i = 0; i < arg_count; i++) { LOGD("free[%d] : %s\n", i, argv2[i]); - MC_FREEIF( argv2[i] ); + MC_FREEIF(argv2[i]); } - MC_FREEIF( argv ); - MC_FREEIF( argv2 ); - MC_FREEIF( argc ); + MC_FREEIF(argv); + MC_FREEIF(argv2); + MC_FREEIF(argc); return FALSE; } -mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t* core, gchar *factory_name) +mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t *core, gchar *factory_name) { GstBus *bus = NULL; - GstPad *pad = NULL; MEDIACODEC_FENTER(); g_mutex_lock(&core->prepare_lock); - if(core->prepare_count == 0) - { + if (core->prepare_count == 0) { - if (!__mc_gst_init_gstreamer()) - { - LOGE ("gstreamer initialize fail"); + if (!__mc_gst_init_gstreamer()) { + LOGE("gstreamer initialize fail"); g_mutex_unlock(&core->prepare_lock); return MC_NOT_INITIALIZED; } core->codec = gst_element_factory_make(factory_name, NULL); - if(!core->codec) - { - LOGE ("codec element create fail"); + if (!core->codec) { + LOGE("codec element create fail"); goto ERROR; } @@ -1353,65 +2110,63 @@ mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t* core, gchar *factory_name) /* create common elements */ core->pipeline = gst_pipeline_new(NULL); - if (!core->pipeline) - { - LOGE ("pipeline create fail"); + if (!core->pipeline) { + LOGE("pipeline create fail"); goto ERROR; } core->appsrc = gst_element_factory_make("appsrc", NULL); - if (!core->appsrc) - { - LOGE ("appsrc can't create"); + if (!core->appsrc) { + LOGE("appsrc can't create"); + goto ERROR; + } + + core->capsfilter = gst_element_factory_make("capsfilter", NULL); + + if (!core->capsfilter) { + LOGE("capsfilter can't create"); goto ERROR; } core->fakesink = gst_element_factory_make("fakesink", NULL); - if (!core->fakesink) - { - LOGE ("fakesink create fail"); + if (!core->fakesink) { + LOGE("fakesink create fail"); goto ERROR; } - g_object_set(core->fakesink, "enable-last-buffer", FALSE, NULL); + g_object_set(core->fakesink, "enable-last-sample", FALSE, NULL); - //__mc_link_elements(core); - gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->codec, core->fakesink, NULL); + /*__mc_link_elements(core);*/ + gst_bin_add_many(GST_BIN(core->pipeline), core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL); /* link elements */ - gst_element_link_many(core->appsrc, core->codec, core->fakesink, NULL); + if (!(gst_element_link_many(core->appsrc, core->capsfilter, core->codec, core->fakesink, NULL))) + { + LOGE("gst_element_link_many is failed"); + goto ERROR; + } /* connect signals, bus watcher */ - - bus = gst_pipeline_get_bus (GST_PIPELINE (core->pipeline)); - core->bus_whatch_id = gst_bus_add_watch (bus, __mc_gst_bus_callback, core); + bus = gst_pipeline_get_bus(GST_PIPELINE(core->pipeline)); + core->bus_whatch_id = gst_bus_add_watch(bus, __mc_gst_bus_callback, core); core->thread_default = g_main_context_get_thread_default(); /* set sync handler to get tag synchronously */ - gst_bus_set_sync_handler(bus, __mc_gst_bus_sync_callback, core); - - gst_object_unref (GST_OBJECT(bus)); + gst_bus_set_sync_handler(bus, __mc_gst_bus_sync_callback, core, NULL); + gst_object_unref(GST_OBJECT(bus)); - /* add pad probe */ - pad = gst_element_get_static_pad(core->fakesink, "sink"); - core->probe_id = gst_pad_add_event_probe(pad, G_CALLBACK(event_probe_cb), core); - gst_object_unref (pad); + /* app src */ + g_signal_connect(core->appsrc, "need-data", G_CALLBACK(__mc_gst_start_feed), core); + g_signal_connect(core->appsrc, "enough-data", G_CALLBACK(__mc_gst_stop_feed), core); /* connect handoff */ - g_object_set (GST_OBJECT(core->fakesink), "signal-handoffs", TRUE, NULL); + g_object_set(GST_OBJECT(core->fakesink), "signal-handoffs", TRUE, NULL); core->signal_handoff = g_signal_connect(core->fakesink, "handoff", G_CALLBACK(__mc_gst_buffer_add), core); - /* - __mc_create_caps(core, &caps); - gst_app_src_set_caps(GST_APP_SRC(core->appsrc), caps); - gst_caps_unref(caps); - */ /* set state PLAYING */ MEDIACODEC_ELEMENT_SET_STATE(GST_ELEMENT_CAST(core->pipeline), GST_STATE_PLAYING); - //g_mutex_unlock(core->prepare_lock); - } core->prepare_count++; g_mutex_unlock(&core->prepare_lock); @@ -1423,16 +2178,19 @@ mc_ret_e _mc_gst_create_pipeline(mc_gst_core_t* core, gchar *factory_name) STATE_CHANGE_FAILED: ERROR: - if(core->codec) + if (core->codec) gst_object_unref(GST_OBJECT(core->codec)); - if(core->pipeline) + if (core->pipeline) gst_object_unref(GST_OBJECT(core->pipeline)); - if(core->appsrc) + if (core->appsrc) gst_object_unref(GST_OBJECT(core->appsrc)); - if(core->fakesink) + if (core->capsfilter) + gst_object_unref(GST_OBJECT(core->capsfilter)); + + if (core->fakesink) gst_object_unref(GST_OBJECT(core->fakesink)); g_mutex_unlock(&core->prepare_lock); @@ -1443,40 +2201,29 @@ ERROR: mc_ret_e _mc_gst_destroy_pipeline(mc_gst_core_t *core) { int ret = MC_ERROR_NONE; - GstPad *pad = NULL; MEDIACODEC_FENTER(); g_mutex_lock(&core->prepare_lock); core->prepare_count--; - if(core->prepare_count == 0) - { + if (core->prepare_count == 0) { - if(core->pipeline) - { + if (core->pipeline) { /* disconnect signal */ - if(core->fakesink && GST_IS_ELEMENT(core->fakesink)) - { - if(g_signal_handler_is_connected(core->fakesink, core->signal_handoff)) - { + if (core->fakesink && GST_IS_ELEMENT(core->fakesink)) { + if (g_signal_handler_is_connected(core->fakesink, core->signal_handoff)) { g_signal_handler_disconnect(core->fakesink, core->signal_handoff); LOGD("handoff signal destroy"); } } - if(core->bus_whatch_id) - { + if (core->bus_whatch_id) { GSource *source = NULL; - source = g_main_context_find_source_by_id (core->thread_default, core->bus_whatch_id); + source = g_main_context_find_source_by_id(core->thread_default, core->bus_whatch_id); g_source_destroy(source); - //g_source_remove(core->bus_whatch_id); LOGD("bus_whatch_id destroy"); } - pad = gst_element_get_static_pad(core->fakesink, "sink"); - gst_pad_remove_event_probe(pad, core->probe_id); - g_object_unref(pad); - MEDIACODEC_ELEMENT_SET_STATE(core->pipeline, GST_STATE_NULL); gst_object_unref(GST_OBJECT(core->pipeline)); @@ -1491,7 +2238,7 @@ mc_ret_e _mc_gst_destroy_pipeline(mc_gst_core_t *core) return ret; STATE_CHANGE_FAILED: - if(core->pipeline) + if (core->pipeline) gst_object_unref(GST_OBJECT(core->pipeline)); LOGD("@%p v(%d)e(%d) destroy_pipeline failed", core, core->video, core->encoder); @@ -1500,237 +2247,243 @@ STATE_CHANGE_FAILED: return MC_ERROR; } -void __mc_gst_buffer_add (GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data) +void __mc_gst_buffer_add(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data) { - mc_gst_core_t* core = (mc_gst_core_t*) data; - + guint n; + GstMemory *mem; + GstMapInfo map = GST_MAP_INFO_INIT; media_packet_h out_pkt = NULL; MEDIACODEC_FENTER(); - //g_atomic_int_int(&core->num_live_buffers); - LOGI("@%p(%d)", core, core->encoder); + mc_gst_core_t *core = (mc_gst_core_t *)data; - out_pkt = __mc_gst_gstbuffer_to_media_packet(core, buffer); - if (out_pkt == NULL) - { - LOGE("out_pkt create failed."); - return; - } + gst_buffer_ref(buffer); - if(core->encoder && core->codec_config) - { - media_packet_set_flags(out_pkt, MEDIA_PACKET_CODEC_CONFIG); - LOGD("set the codec data %p", buffer); - } - core->codec_config = false; + n = gst_buffer_n_memory(buffer); - g_mutex_lock(&core->ports[1]->mutex); - /* push it to output buffer queue */ - //g_queue_push_tail(core->output_queue, out_pkt); - g_queue_push_tail(core->ports[1]->queue, out_pkt); + mem = gst_buffer_peek_memory(buffer, n-1); - g_mutex_unlock(&core->ports[1]->mutex); + gst_memory_map(mem, &map, GST_MAP_READ); + LOGD("n : %d, map.data : %p, map.size : %d", n, map.data, map.size); - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]) - { - ((mc_fill_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER])(out_pkt, core->user_data[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]); - } + out_pkt = __mc_gst_make_media_packet(core, map.data, map.size); - MEDIACODEC_FLEAVE(); -} + LOGI("@%p(%d) out_pkt : %p", core, core->encoder, out_pkt); + gst_memory_unmap(mem, &map); -static int __mc_output_packet_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data) -{ - void* buffer = NULL; - MEDIACODEC_FENTER(); + if (out_pkt) { + media_packet_set_extra(out_pkt, buffer); + media_packet_set_pts(out_pkt, GST_BUFFER_TIMESTAMP(buffer)); - LOGD("packet finalized: %p", packet); - media_packet_get_extra(packet, &buffer); - gst_buffer_unref((GstBuffer*)buffer); + if (core->need_codec_data) { + media_packet_set_flags(out_pkt, MEDIA_PACKET_CODEC_CONFIG); + core->need_codec_data = false; + } + + if (core->need_sync_flag) { + media_packet_set_flags(out_pkt, MEDIA_PACKET_SYNC_FRAME); + core->need_sync_flag = false; + } + + g_mutex_lock(&core->ports[1]->mutex); + /* push it to output buffer queue */ + g_queue_push_tail(core->ports[1]->queue, out_pkt); + + core->dequeued_count++; + LOGD("dequeued : %d", core->dequeued_count); + + g_mutex_unlock(&core->ports[1]->mutex); + + if (core->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]) { + ((mc_fill_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]) + (out_pkt, core->user_data[_MEDIACODEC_EVENT_TYPE_FILLBUFFER]); + } + } MEDIACODEC_FLEAVE(); - return MEDIA_PACKET_FINALIZE; + return; } int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data) { - void* buffer = NULL; - SCMN_IMGB *imgb = NULL; - tbm_surface_h surface = NULL; - bool has_tbm_surface = false; - - MEDIACODEC_FENTER(); + void *buffer = NULL; + int i = 0; + guint n; + GstMemory *mem; + GstMapInfo map = GST_MAP_INFO_INIT; + MMVideoBuffer *mm_video_buf = NULL; + mc_gst_core_t *core = NULL; - media_packet_has_tbm_surface_buffer(packet, &has_tbm_surface); - LOGI("has_tbm_surface : %d", has_tbm_surface); + core = (mc_gst_core_t*)user_data; - if(has_tbm_surface) - { - LOGI("destroy tbm surface"); - media_packet_get_tbm_surface(packet, &surface); - tbm_surface_destroy(surface); - } + LOGD("packet finalized: %p", packet); media_packet_get_extra(packet, &buffer); - LOGD("finalized_gst_buffer = %p", buffer); - LOGI("gstbuffer refcount %d", GST_MINI_OBJECT_REFCOUNT_VALUE(buffer)); - if (GST_BUFFER_MALLOCDATA(buffer)) - { - imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buffer); - if (imgb) - { - LOGI("imgb is destroyed"); - free(imgb); - imgb = NULL; - GST_BUFFER_MALLOCDATA(buffer) = NULL; + + n = gst_buffer_n_memory(buffer); + + if (n > 1) { + mem = gst_buffer_peek_memory(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 *)buffer); - //GST_BUFFER_DATA(buffer) = NULL; - gst_buffer_unref((GstBuffer*)buffer); - - MEDIACODEC_FLEAVE(); return MEDIA_PACKET_FINALIZE; } -guint32 __mc_get_gst_input_format(media_packet_h packet, bool is_hw) +gchar *__mc_get_gst_input_format(media_packet_h packet, bool is_hw) { - guint32 format = 0; + 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) - { + switch (mimetype) { case MEDIA_FORMAT_I420: - format = GST_MAKE_FOURCC ('I', '4', '2', '0'); + format = "I420"; break; case MEDIA_FORMAT_NV12: if (is_hw) - format = GST_MAKE_FOURCC ('S', 'N', '1', '2'); + format = "SN12"; else - format = GST_MAKE_FOURCC ('N', 'V', '1', '2'); + format = "NV12"; + break; + case MEDIA_FORMAT_ARGB: + format = "ARGB"; break; default: break; } + LOGD("input packet format : %s", format); return format; } - -mc_gst_buffer_t* _mc_gst_media_packet_to_gstbuffer(mc_gst_core_t* core, GstCaps **caps, media_packet_h pkt, bool codec_config) +GstMCBuffer *_mc_gst_media_packet_to_gstbuffer(mc_gst_core_t* core, GstCaps **caps, media_packet_h pkt, bool codec_config) { - mc_gst_buffer_t* buff = NULL; - uint64_t pts = 0, dur = 0; + int ret = MEDIA_PACKET_ERROR_NONE; + GstMCBuffer *mc_buffer = NULL; + void *buf_data = NULL; + uint64_t buf_size = 0; + uint64_t pts = 0; + uint64_t dur = 0; + + ret = media_packet_get_buffer_size(pkt, &buf_size); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return NULL; + } + + ret = media_packet_get_buffer_data_ptr(pkt, &buf_data); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return NULL; + } - buff = __mc_gst_buffer_new(core); - buff->pkt = pkt; + mc_buffer = gst_mediacodec_buffer_new(core, pkt, buf_size); + if (mc_buffer == NULL) { + LOGW("failed to create inbuf"); + return NULL; + } - //mc_hex_dump("nal", pkt, 8); + LOGD("pkt : %p, buf_size : %d", pkt, (int)buf_size); - __mc_fill_input_buffer(core, buff); + ret = __mc_fill_input_buffer(core, pkt, mc_buffer); + if (ret != MC_ERROR_NONE) { + LOGW("failed to fill inbuf"); + return NULL; + } /* pts */ media_packet_get_pts(pkt, &pts); - GST_BUFFER_TIMESTAMP(buff) = (GstClockTime) pts; - LOGD("GST_BUFFER_TIMESTAMP = %"GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buff))); - LOGD("PTS = %llu", pts); + GST_BUFFER_PTS(mc_buffer->buffer) = pts; /* duration */ media_packet_get_duration(pkt, &dur); - GST_BUFFER_DURATION(buff) = dur; - - GST_BUFFER_CAPS(buff) = gst_caps_copy(*caps); + GST_BUFFER_DURATION(mc_buffer->buffer) = dur; - return buff; + return mc_buffer; } -media_packet_h __mc_gst_gstbuffer_to_media_packet(mc_gst_core_t* core, GstBuffer* buff) +media_packet_h __mc_gst_make_media_packet(mc_gst_core_t *core, unsigned char *data, int size) { - media_packet_h out_pkt = NULL; - mc_ret_e ret = MC_ERROR_NONE; - if (!buff) - return NULL; + media_packet_h pkt = NULL; - ret = __mc_fill_output_buffer(core, buff, &out_pkt); - if (ret != MC_ERROR_NONE) - { - gst_buffer_ref(buff); - return NULL; - } + __mc_fill_output_buffer(core, data, size, &pkt); - gst_buffer_ref(buff); - return out_pkt; + return pkt; } -gboolean __mc_gst_bus_callback (GstBus *bus, GstMessage *msg, gpointer data) +gboolean __mc_gst_bus_callback(GstBus *bus, GstMessage *msg, gpointer data) { int ret = MC_ERROR_NONE; - mc_gst_core_t *core = (mc_gst_core_t*)data; + mc_gst_core_t *core = (mc_gst_core_t *)data; LOGD("@%p v(%d)e(%d)", core, core->video, core->encoder); - switch (GST_MESSAGE_TYPE (msg)) { + switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: { - core->eos = true; - g_cond_signal(&core->eos_cond); - LOGD("send eos signal"); + _mc_send_eos_signal(core); - LOGD ("End of stream\n"); -/* - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) - { + if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS]) { + LOGD("eos callback invoked"); ((mc_eos_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EOS])(core->user_data[_MEDIACODEC_EVENT_TYPE_EOS]); } -*/ + + LOGD("End of stream\n"); } break; case GST_MESSAGE_ERROR: { - GError* error = NULL; + GError *error = NULL; - gst_message_parse_error (msg, &error, NULL); + gst_message_parse_error(msg, &error, NULL); - if (!error) - { + if (!error) { LOGW("GST error message parsing failed"); break; } - LOGW ("Error: %s\n", error->message); + LOGW("Error: %s\n", error->message); - if(error) - { - if(error->domain == GST_STREAM_ERROR) - { + if (error) { + if (error->domain == GST_STREAM_ERROR) { ret = __gst_handle_stream_error(core, error, msg); - } - else if (error->domain == GST_RESOURCE_ERROR) - { + } else if (error->domain == GST_RESOURCE_ERROR) { ret = __gst_handle_resource_error(core, error->code); - } - else if (error->domain == GST_LIBRARY_ERROR) - { + } else if (error->domain == GST_LIBRARY_ERROR) { ret = __gst_handle_library_error(core, error->code); - } - else if (error->domain == GST_CORE_ERROR) - { + } else if (error->domain == GST_CORE_ERROR) { ret = __gst_handle_core_error(core, error->code); - } - else - { + } else { LOGW("Unexpected error has occured"); } + + if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) { + ((mc_error_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) + (ret, core->user_data[_MEDIACODEC_EVENT_TYPE_ERROR]); + } } - g_error_free (error); + g_error_free(error); } break; @@ -1738,27 +2491,19 @@ gboolean __mc_gst_bus_callback (GstBus *bus, GstMessage *msg, gpointer data) break; } - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR]) - { - ((mc_error_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_ERROR])(ret, core->user_data[_MEDIACODEC_EVENT_TYPE_ERROR]); - } - return TRUE; } -static gboolean -__mc_gst_check_useful_message(mc_gst_core_t *core, GstMessage *msg) +static gboolean __mc_gst_check_useful_message(mc_gst_core_t *core, GstMessage *msg) { gboolean retval = false; - if(!core->pipeline) - { + if (!core->pipeline) { LOGE("mediacodec pipeline handle is null"); return true; } - switch (GST_MESSAGE_TYPE (msg)) - { + switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_TAG: case GST_MESSAGE_EOS: case GST_MESSAGE_ERROR: @@ -1773,29 +2518,27 @@ __mc_gst_check_useful_message(mc_gst_core_t *core, GstMessage *msg) return retval; } -static GstBusSyncReply -__mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data) +static GstBusSyncReply __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data) { - mc_gst_core_t *core = (mc_gst_core_t*)data; + mc_gst_core_t *core = (mc_gst_core_t *)data; GstBusSyncReply reply = GST_BUS_DROP; - if(!core->pipeline) - { + LOGD("__mc_gst_bus_sync_callback is called"); + + if (!core->pipeline) { LOGE("mediacodec pipeline handle is null"); return GST_BUS_PASS; } - if(!__mc_gst_check_useful_message(core, msg)) - { + if (!__mc_gst_check_useful_message(core, msg)) { gst_message_unref(msg); return GST_BUS_DROP; } - switch (GST_MESSAGE_TYPE (msg)) - { - case GST_MESSAGE_STATE_CHANGED: + switch (GST_MESSAGE_TYPE(msg)) { + case GST_MESSAGE_EOS: + case GST_MESSAGE_ERROR: __mc_gst_bus_callback(NULL, msg, core); - //__mediacodec_gst_callback(NULL, msg, core); reply = GST_BUS_DROP; break; @@ -1804,141 +2547,113 @@ __mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data) break; } - if( reply == GST_BUS_DROP ) + if (reply == GST_BUS_DROP) gst_message_unref(msg); return reply; } -static SCMN_IMGB * __mc_gst_make_tbm_buffer(mc_gst_core_t* core, media_packet_h pkt) +static MMVideoBuffer *__mc_gst_make_tbm_buffer(mc_gst_core_t* core, media_packet_h pkt) { tbm_surface_h surface = NULL; tbm_bo bo = NULL; - mc_encoder_info_t *enc_info = (mc_encoder_info_t*)core->codec_info; + mc_encoder_info_t *enc_info = (mc_encoder_info_t *)core->codec_info; if (!pkt) { LOGE("output is null"); return NULL; } - SCMN_IMGB *psimgb = NULL; - psimgb = (SCMN_IMGB *)malloc(sizeof(SCMN_IMGB)); - if (!psimgb) { - LOGE("Failed to alloc SCMN_IMGB"); + MMVideoBuffer *mm_vbuffer = NULL; + mm_vbuffer = (MMVideoBuffer *)malloc(sizeof(MMVideoBuffer)); + if (!mm_vbuffer) { + LOGE("Failed to alloc MMVideoBuffer"); return NULL; } - memset(psimgb, 0x00, sizeof(SCMN_IMGB)); + memset(mm_vbuffer, 0x00, sizeof(MMVideoBuffer)); - media_packet_get_tbm_surface(pkt, &surface); + if (media_packet_get_tbm_surface(pkt, &surface) != MEDIA_PACKET_ERROR_NONE) + { + LOGE("get tbm surface is failed"); + free(mm_vbuffer); + return NULL; + } bo = tbm_surface_internal_get_bo(surface, 0); + tbm_bo_map(bo, TBM_DEVICE_MM, TBM_OPTION_READ); + tbm_bo_unmap(bo); + tbm_bo_handle handle = tbm_bo_get_handle(bo, TBM_DEVICE_CPU); #ifdef TIZEN_PROFILE_LITE int phy_addr = 0; int phy_size = 0; tbm_bo_handle handle_fd = tbm_bo_get_handle(bo, TBM_DEVICE_MM); - if (__tbm_get_physical_addr_bo(handle_fd, &phy_addr, &phy_size) == 0) - { - psimgb->p[0] = (void*)phy_addr; + if (__tbm_get_physical_addr_bo(handle_fd, &phy_addr, &phy_size) == 0) { + mm_vbuffer->handle.paddr[0] = (void *)phy_addr; + LOGD("mm_vbuffer->paddr : %p", mm_vbuffer->handle.paddr[0]); } + LOGD("paddr : %p", phy_addr); #endif - psimgb->buf_share_method = BUF_SHARE_METHOD_TIZEN_BUFFER; - psimgb->bo[0] = bo; - psimgb->a[0] = handle.ptr; - psimgb->w[0] = enc_info->width; - psimgb->h[0] = enc_info->height; - psimgb->s[0] = psimgb->w[0]; - psimgb->e[0] = psimgb->h[0]; + mm_vbuffer->type = MM_VIDEO_BUFFER_TYPE_TBM_BO; + mm_vbuffer->handle.bo[0] = bo; + mm_vbuffer->data[0] = handle.ptr; + mm_vbuffer->width[0] = enc_info->width; + mm_vbuffer->height[0] = enc_info->height; + mm_vbuffer->stride_width[0] = mm_vbuffer->width[0]; + mm_vbuffer->stride_height[0] = mm_vbuffer->height[0]; - return psimgb; + return mm_vbuffer; } -static GType __mc_gst_buffer_get_type(void) +static void gst_mediacodec_buffer_finalize(GstMCBuffer *mc_buffer) { - static GType _mc_gst_buffer_type; + if (!mc_buffer) + return; - if (G_UNLIKELY(_mc_gst_buffer_type == 0)) { - static const GTypeInfo mc_gst_buffer_info = { - sizeof (GstBufferClass), - NULL, - NULL, - __mc_gst_buffer_class_init, - NULL, - NULL, - sizeof (mc_gst_buffer_t), - 0, - NULL, - NULL - }; + mc_gst_core_t *core = (mc_gst_core_t *)mc_buffer->core; - _mc_gst_buffer_type = g_type_register_static(GST_TYPE_BUFFER, - "McGstBuffer", - &mc_gst_buffer_info, - 0); + if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) { + ((mc_empty_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) + (mc_buffer->pkt, core->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]); } - return _mc_gst_buffer_type; -} + LOGD("%p(%p) buffer finalized...", mc_buffer, mc_buffer->pkt); + free(mc_buffer); + mc_buffer = NULL; -static void __mc_gst_buffer_class_init(gpointer g_class, gpointer class_data) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class); - mc_gst_buffer_parent_class = g_type_class_peek_parent(g_class); - mini_object_class->finalize = (GstMiniObjectFinalizeFunction)__mc_gst_buffer_finalize; + return; } -static mc_gst_buffer_t* __mc_gst_buffer_new(mc_gst_core_t* core) +static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t* core, media_packet_h pkt, uint64_t size) { - mc_gst_buffer_t *ret = NULL; - ret = (mc_gst_buffer_t *)gst_mini_object_new(GST_TYPE_MC_BUFFER); - LOGD("creating buffer : %p", ret); - ret->core = core; - return ret; -} + GstMCBuffer *mc_buffer = NULL; -static void __mc_gst_buffer_finalize(mc_gst_buffer_t *buffer) -{ - SCMN_IMGB *imgb = NULL; - mc_gst_core_t *core = buffer->core; + mc_buffer = (GstMCBuffer *)malloc(sizeof(*mc_buffer)); - LOGD("__mc_gst_buffer_finalize() is called"); - if (GST_BUFFER_MALLOCDATA(buffer)) - { - imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buffer); - if (imgb) - { - LOGI("imgb is destroyed"); - free(imgb); - imgb = NULL; - GST_BUFFER_MALLOCDATA(buffer) = NULL; - } + if (mc_buffer == NULL) { + LOGE("malloc fail"); + return NULL; } - //GST_BUFFER_DATA(buffer) = NULL; + mc_buffer->buffer = gst_buffer_new(); + mc_buffer->buf_size = 0; - if (GST_MINI_OBJECT_CLASS (mc_gst_buffer_parent_class)->finalize) { - GST_MINI_OBJECT_CLASS (mc_gst_buffer_parent_class)->finalize (GST_MINI_OBJECT(buffer)); - } - - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) - { - ((mc_empty_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER])(buffer->pkt, core->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]); - LOGD("finalize, pkt : %p, buffer : %p", buffer->pkt, buffer); - } + LOGD("creating buffer : %p, %p", mc_buffer, mc_buffer->buffer); + mc_buffer->core = core; + mc_buffer->pkt = pkt; - return; + return mc_buffer; } -static gint __gst_handle_core_error(mc_gst_core_t* core, int code ) +static gint __gst_handle_core_error(mc_gst_core_t *core, int code) { gint trans_err = MEDIACODEC_ERROR_NONE; g_return_val_if_fail(core, MC_PARAM_ERROR); - switch ( code ) - { + switch (code) { case GST_CORE_ERROR_MISSING_PLUGIN: return MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT; case GST_CORE_ERROR_STATE_CHANGE: @@ -1962,14 +2677,13 @@ static gint __gst_handle_core_error(mc_gst_core_t* core, int code ) return trans_err; } -static gint __gst_handle_library_error(mc_gst_core_t* core, int code) +static gint __gst_handle_library_error(mc_gst_core_t *core, int code) { gint trans_err = MEDIACODEC_ERROR_NONE; g_return_val_if_fail(core, MC_PARAM_ERROR); - switch ( code ) - { + switch (code) { case GST_LIBRARY_ERROR_FAILED: case GST_LIBRARY_ERROR_TOO_LAZY: case GST_LIBRARY_ERROR_INIT: @@ -1985,14 +2699,13 @@ static gint __gst_handle_library_error(mc_gst_core_t* core, int code) } -static gint __gst_handle_resource_error(mc_gst_core_t* core, int code ) +static gint __gst_handle_resource_error(mc_gst_core_t *core, int code) { gint trans_err = MEDIACODEC_ERROR_NONE; g_return_val_if_fail(core, MC_PARAM_ERROR); - switch ( code ) - { + switch (code) { case GST_RESOURCE_ERROR_NO_SPACE_LEFT: trans_err = MEDIACODEC_ERROR_NO_FREE_SPACE; break; @@ -2014,16 +2727,15 @@ static gint __gst_handle_resource_error(mc_gst_core_t* core, int code ) return trans_err; } -static gint __gst_handle_stream_error(mc_gst_core_t* core, GError* error, GstMessage * message) +static gint __gst_handle_stream_error(mc_gst_core_t *core, GError* error, GstMessage * message) { gint trans_err = MEDIACODEC_ERROR_NONE; g_return_val_if_fail(core, MC_PARAM_ERROR); g_return_val_if_fail(error, MC_PARAM_ERROR); - g_return_val_if_fail (message, MC_PARAM_ERROR); + g_return_val_if_fail(message, MC_PARAM_ERROR); - switch ( error->code ) - { + switch (error->code) { case GST_STREAM_ERROR_FAILED: case GST_STREAM_ERROR_TYPE_NOT_FOUND: case GST_STREAM_ERROR_DECODE: @@ -2031,7 +2743,7 @@ static gint __gst_handle_stream_error(mc_gst_core_t* core, GError* error, GstMes case GST_STREAM_ERROR_DECRYPT: case GST_STREAM_ERROR_DECRYPT_NOKEY: case GST_STREAM_ERROR_CODEC_NOT_FOUND: - trans_err = __gst_transform_gsterror( core, message, error ); + trans_err = __gst_transform_gsterror(core, message, error); break; case GST_STREAM_ERROR_NOT_IMPLEMENTED: @@ -2048,35 +2760,34 @@ static gint __gst_handle_stream_error(mc_gst_core_t* core, GError* error, GstMes return trans_err; } -static gint __gst_transform_gsterror( mc_gst_core_t *core, GstMessage * message, GError* error ) +static gint __gst_transform_gsterror(mc_gst_core_t *core, GstMessage * message, GError* error) { gchar *src_element_name = NULL; GstElement *src_element = NULL; GstElementFactory *factory = NULL; - const gchar* klass = NULL; + const gchar *klass = NULL; src_element = GST_ELEMENT_CAST(message->src); - if ( !src_element ) + if (!src_element) goto INTERNAL_ERROR; src_element_name = GST_ELEMENT_NAME(src_element); - if ( !src_element_name ) + if (!src_element_name) goto INTERNAL_ERROR; factory = gst_element_get_factory(src_element); - if ( !factory ) + if (!factory) goto INTERNAL_ERROR; klass = gst_element_factory_get_klass(factory); - if ( !klass ) + if (!klass) goto INTERNAL_ERROR; LOGD("error code=%d, msg=%s, src element=%s, class=%s\n", error->code, error->message, src_element_name, klass); - switch ( error->code ) - { + switch (error->code) { case GST_STREAM_ERROR_DECODE: return MEDIACODEC_ERROR_INVALID_STREAM; break; @@ -2101,49 +2812,80 @@ INTERNAL_ERROR: return MEDIACODEC_ERROR_INTERNAL; } +static int _mc_gst_flush_buffers(mc_gst_core_t *core) +{ + gboolean ret = FALSE; + GstEvent *event = NULL; + + MEDIACODEC_FENTER(); + + _mc_gst_set_flush_input(core); + + event = gst_event_new_seek(1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1); + + ret = gst_element_send_event(core->appsrc, event); + if (ret != TRUE) { + LOGE("failed to send seek event"); + return MC_ERROR; + } + + _mc_gst_set_flush_output(core); + + MEDIACODEC_FLEAVE(); + + return MC_ERROR_NONE; +} + + static void _mc_gst_set_flush_input(mc_gst_core_t *core) { media_packet_h pkt = NULL; LOGI("_mc_gst_set_flush_input is called"); - while( pkt != mc_async_queue_pop_forced(core->available_queue->input) ) + + while (!mc_async_queue_is_empty(core->available_queue->input)) { - LOGD("%p pkt is poped"); - if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) - { + pkt = mc_async_queue_pop_forced(core->available_queue->input); + + if (core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) { ((mc_empty_buffer_cb) core->user_cb[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]) (pkt, core->user_data[_MEDIACODEC_EVENT_TYPE_EMPTYBUFFER]); } } mc_async_queue_flush(core->available_queue->input); + core->queued_count = 0; } static void _mc_gst_set_flush_output(mc_gst_core_t *core) { media_packet_h pkt = NULL; - LOGI("_mc_gst_set_flush_output is called"); + MEDIACODEC_FENTER(); g_mutex_lock(&core->ports[1]->mutex); - if(!g_queue_is_empty(core->ports[1]->queue)) + while(!g_queue_is_empty(core->ports[1]->queue)) { - while(pkt != g_queue_pop_head(core->ports[1]->queue)) - { - LOGD("outpkt in output_queue : %p", pkt); + pkt = g_queue_pop_head(core->ports[1]->queue); + LOGD("outpkt in output_queue : %p", pkt); + if (pkt) { media_packet_destroy(pkt); + LOGD("outpkt destroyed"); + pkt = NULL; } } - + core->dequeued_count = 0; g_mutex_unlock(&core->ports[1]->mutex); + MEDIACODEC_FLEAVE(); } #ifdef TIZEN_PROFILE_LITE -int __tbm_get_physical_addr_bo(tbm_bo_handle tbm_bo_handle_fd_t, int* phy_addr, int* phy_size) +int __tbm_get_physical_addr_bo(tbm_bo_handle tbm_bo_handle_fd_t, int *phy_addr, int *phy_size) { int tbm_bo_handle_fd; - int ret=0; + int ret = 0; tbm_bo_handle_fd = tbm_bo_handle_fd_t.u32; @@ -2157,36 +2899,302 @@ int __tbm_get_physical_addr_bo(tbm_bo_handle tbm_bo_handle_fd_t, int* phy_addr, custom_data.cmd = 4; custom_data.arg = (unsigned long)&mmu_data; - ion_fd = open ("/dev/ion", open_flags); - if (ion_fd < 0) - { - LOGE ("[tbm_get_physical_addr_bo] ion_fd open device failed"); + ion_fd = open("/dev/ion", open_flags); + if (ion_fd < 0) { + LOGE("[tbm_get_physical_addr_bo] ion_fd open device failed"); } - if (ioctl(ion_fd, ION_IOC_CUSTOM, &custom_data)<0) - { - LOGE ("[tbm_get_physical_addr_bo] ION_IOC_CUSTOM fails %d %s",errno,strerror(errno)); - ret=-1; + if (ioctl(ion_fd, ION_IOC_CUSTOM, &custom_data) < 0) { + LOGE("[tbm_get_physical_addr_bo] ION_IOC_CUSTOM failed"); + ret = -1; } - if (!ret) - { + if (!ret) { *phy_addr = mmu_data.iova_addr; *phy_size = mmu_data.iova_size; - } - else - { + } else { *phy_addr = 0; *phy_size = 0; - LOGW ("[tbm_get_physical_addr_bo] getting physical address is failed. phy_addr = 0"); + LOGW("[tbm_get_physical_addr_bo] getting physical address is failed. phy_addr = 0"); } - if (ion_fd != -1) - { - close (ion_fd); + if (ion_fd != -1) { + close(ion_fd); ion_fd = -1; } return 0; } #endif + +/* + * Get tiled address of position(x,y) + * + * @param x_size + * width of tiled[in] + * + * @param y_size + * height of tiled[in] + * + * @param x_pos + * x position of tield[in] + * + * @param src_size + * y position of tield[in] + * + * @return + * address of tiled data + */ +static int __tile_4x2_read(int x_size, int y_size, int x_pos, int y_pos) +{ + int pixel_x_m1, pixel_y_m1; + int roundup_x; + int linear_addr0, linear_addr1, bank_addr ; + int x_addr; + int trans_addr; + + pixel_x_m1 = x_size - 1; + pixel_y_m1 = y_size - 1; + + roundup_x = ((pixel_x_m1 >> 7) + 1); + + x_addr = x_pos >> 2; + + if ((y_size <= y_pos+32) && (y_pos < y_size) && + (((pixel_y_m1 >> 5) & 0x1) == 0) && (((y_pos >> 5) & 0x1) == 0)) { + linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 6) & 0x3f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } else { + linear_addr0 = (((y_pos & 0x1f) << 4) | (x_addr & 0xf)); + linear_addr1 = (((y_pos >> 6) & 0xff) * roundup_x + ((x_addr >> 5) & 0x7f)); + + if (((x_addr >> 5) & 0x1) == ((y_pos >> 5) & 0x1)) + bank_addr = ((x_addr >> 4) & 0x1); + else + bank_addr = 0x2 | ((x_addr >> 4) & 0x1); + } + + linear_addr0 = linear_addr0 << 2; + trans_addr = (linear_addr1 << 13) | (bank_addr << 11) | linear_addr0; + + return trans_addr; +} + +/* + * Converts tiled data to linear + * Crops left, top, right, buttom + * 1. Y of NV12T to Y of YUV420P + * 2. Y of NV12T to Y of YUV420S + * 3. UV of NV12T to UV of YUV420S + * + * @param yuv420_dest + * Y or UV plane address of YUV420[out] + * + * @param nv12t_src + * Y or UV plane address of NV12T[in] + * + * @param yuv420_width + * Width of YUV420[in] + * + * @param yuv420_height + * Y: Height of YUV420, UV: Height/2 of YUV420[in] + * + * @param left + * Crop size of left + * + * @param top + * Crop size of top + * + * @param right + * Crop size of right + * + * @param buttom + * Crop size of buttom + */ +static void __csc_tiled_to_linear_crop(unsigned char *yuv420_dest, unsigned char *nv12t_src, + int yuv420_width, int yuv420_height, + int left, int top, int right, int buttom) +{ + int i, j; + int tiled_offset = 0, tiled_offset1 = 0; + int linear_offset = 0; + int temp1 = 0, temp2 = 0, temp3 = 0, temp4 = 0; + + temp3 = yuv420_width-right; + temp1 = temp3-left; + /* real width is greater than or equal 256 */ + if (temp1 >= 256) { + for (i = top; i < yuv420_height-buttom; i += 1) { + j = left; + temp3 = (j>>8)<<8; + temp3 = temp3>>6; + temp4 = i>>5; + if (temp4 & 0x1) { + /* odd fomula: 2+x+(x>>2)<<2+x_block_num*(y-1) */ + tiled_offset = temp4-1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset+2; + temp1 = (temp3>>2)<<2; + tiled_offset = tiled_offset+temp1; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 8; + } else { + temp2 = ((yuv420_height+31)>>5)<<5; + if ((i + 32) < temp2) { + /* even1 fomula: x+((x+2)>>2)<<2+x_block_num*y */ + temp1 = temp3+2; + temp1 = (temp1>>2)<<2; + tiled_offset = temp3+temp1; + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = tiled_offset+temp4*(temp1>>6); + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset + 2048 * 6; + temp4 = 8; + } else { + /* even2 fomula: x+x_block_num*y */ + temp1 = ((yuv420_width+127)>>7)<<7; + tiled_offset = temp4*(temp1>>6); + tiled_offset = tiled_offset+temp3; + tiled_offset = tiled_offset<<11; + tiled_offset1 = tiled_offset+2048*2; + temp4 = 4; + } + } + + temp1 = i&0x1F; + tiled_offset = tiled_offset+64*(temp1); + tiled_offset1 = tiled_offset1+64*(temp1); + temp2 = yuv420_width-left-right; + linear_offset = temp2*(i-top); + temp3 = ((j+256)>>8)<<8; + temp3 = temp3-j; + temp1 = left&0x3F; + if (temp3 > 192) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+temp1, 64-temp1); + temp2 = ((left+63)>>6)<<6; + temp3 = ((yuv420_width-right)>>6)<<6; + if (temp2 == temp3) { + temp2 = yuv420_width-right-(64-temp1); + } + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+192-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+256-temp1; + } else if (temp3 > 128) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset+2048+temp1, 64-temp1); + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+128-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+192-temp1; + } else if (temp3 > 64) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+temp1, 64-temp1); + memcpy(yuv420_dest+linear_offset+64-temp1, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+128-temp1; + } else if (temp3 > 0) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset1+2048+temp1, 64-temp1); + linear_offset = linear_offset+64-temp1; + } + + tiled_offset = tiled_offset+temp4*2048; + j = (left>>8)<<8; + j = j + 256; + temp2 = yuv420_width-right-256; + for (; j <= temp2; j += 256) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + tiled_offset1 = tiled_offset1+temp4*2048; + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64); + tiled_offset = tiled_offset+temp4*2048; + memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, 64); + linear_offset = linear_offset+256; + } + + tiled_offset1 = tiled_offset1+temp4*2048; + temp2 = yuv420_width-right-j; + if (temp2 > 192) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, 64); + memcpy(yuv420_dest+linear_offset+192, nv12t_src+tiled_offset1+2048, temp2-192); + } else if (temp2 > 128) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, 64); + memcpy(yuv420_dest+linear_offset+128, nv12t_src+tiled_offset1, temp2-128); + } else if (temp2 > 64) { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + memcpy(yuv420_dest+linear_offset+64, nv12t_src+tiled_offset+2048, temp2-64); + } else { + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + } + } + } else if (temp1 >= 64) { + for (i = top; i < (yuv420_height-buttom); i += 1) { + j = left; + tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp2 = ((j+64)>>6)<<6; + temp2 = temp2-j; + linear_offset = temp1*(i-top); + temp4 = j&0x3; + tiled_offset = tiled_offset+temp4; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + linear_offset = linear_offset+temp2; + j = j+temp2; + if ((j+64) <= temp3) { + tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i); + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + linear_offset = linear_offset+64; + j = j+64; + } + if ((j+64) <= temp3) { + tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i); + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 64); + linear_offset = linear_offset+64; + j = j+64; + } + if (j < temp3) { + tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp2 = temp3-j; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, temp2); + } + } + } else { + for (i = top; i < (yuv420_height-buttom); i += 1) { + linear_offset = temp1*(i-top); + for (j = left; j < (yuv420_width - right); j += 2) { + tiled_offset = __tile_4x2_read(yuv420_width, yuv420_height, j, i); + temp4 = j&0x3; + tiled_offset = tiled_offset+temp4; + memcpy(yuv420_dest+linear_offset, nv12t_src+tiled_offset, 2); + linear_offset = linear_offset+2; + } + } + } +} + +void _mc_send_eos_signal(mc_gst_core_t *core) +{ + g_mutex_lock(&core->eos_mutex); + core->eos = FALSE; + g_cond_broadcast(&core->eos_cond); + g_mutex_unlock(&core->eos_mutex); + LOGD("send EOS signal"); +} + +void _mc_wait_for_eos(mc_gst_core_t *core) +{ + g_mutex_lock(&core->eos_mutex); + core->eos = TRUE; + LOGD("waiting for EOS"); + while (core->eos) { + g_cond_wait(&core->eos_cond, &core->eos_mutex); + } + LOGD("received EOS"); + g_mutex_unlock(&core->eos_mutex); +} diff --git a/src/media_codec_queue.c b/src/media_codec_queue.c index c719bf3..9713601 100755 --- a/src/media_codec_queue.c +++ b/src/media_codec_queue.c @@ -1,54 +1,55 @@ #include <media_codec_queue.h> +#include <dlog.h> -async_queue_t *mc_async_queue_new (void) +async_queue_t *mc_async_queue_new(void) { async_queue_t *async_queue; - async_queue = g_slice_new0 (async_queue_t); + async_queue = g_slice_new0(async_queue_t); + if (async_queue == NULL) { + LOGE("async_queue initialization failed"); + return NULL; + } - //async_queue->condition = g_cond_new (); - g_cond_init (&async_queue->condition); - //async_queue->mutex = g_mutex_new (); + g_cond_init(&async_queue->condition); g_mutex_init(&async_queue->mutex); async_queue->enabled = TRUE; return async_queue; } -void mc_async_queue_free (async_queue_t * async_queue) +void mc_async_queue_free(async_queue_t *async_queue) { - //g_cond_free (async_queue->condition); - g_cond_clear (&async_queue->condition); - //g_mutex_free (async_queue->mutex); - g_mutex_clear (&async_queue->mutex); + g_cond_clear(&async_queue->condition); + g_mutex_clear(&async_queue->mutex); - g_list_free (async_queue->head); - g_slice_free (async_queue_t, async_queue); + g_list_free(async_queue->head); + g_slice_free(async_queue_t, async_queue); } -void mc_async_queue_push (async_queue_t * async_queue, gpointer data) +void mc_async_queue_push(async_queue_t *async_queue, gpointer data) { - g_mutex_lock (&async_queue->mutex); + g_mutex_lock(&async_queue->mutex); async_queue->tail = g_list_append(async_queue->tail, data); - if(async_queue->tail && async_queue->tail->next) + if (async_queue->tail->next) async_queue->tail = async_queue->tail->next; else async_queue->head = async_queue->tail; async_queue->length++; - g_cond_signal (&async_queue->condition); - //LOGD("queue pushed : %p, %d, %p",queue, async_queue->length, data); + g_cond_signal(&async_queue->condition); + /*LOGD("queue pushed : %p, %d, %p",queue, async_queue->length, data);*/ - g_mutex_unlock (&async_queue->mutex); + g_mutex_unlock(&async_queue->mutex); } -gpointer mc_async_queue_pop (async_queue_t * async_queue) +gpointer mc_async_queue_pop(async_queue_t *async_queue) { gpointer data = NULL; - g_mutex_lock (&async_queue->mutex); + g_mutex_lock(&async_queue->mutex); if (!async_queue->enabled) { /* g_warning ("not enabled!"); */ @@ -56,7 +57,7 @@ gpointer mc_async_queue_pop (async_queue_t * async_queue) } if (!async_queue->head) { - g_cond_wait (&async_queue->condition, &async_queue->mutex); + g_cond_wait(&async_queue->condition, &async_queue->mutex); } if (async_queue->head) { @@ -64,26 +65,27 @@ gpointer mc_async_queue_pop (async_queue_t * async_queue) data = node->data; async_queue->head = node->next; + if (async_queue->head) async_queue->head->prev = NULL; else async_queue->tail = NULL; async_queue->length--; - //LOGD("async queue poped : %p, %d, %p",queue, async_queue->length, data); - g_list_free_1 (node); + /*LOGD("async queue poped : %p, %d, %p",queue, async_queue->length, data);*/ + g_list_free_1(node); } leave: - g_mutex_unlock (&async_queue->mutex); + g_mutex_unlock(&async_queue->mutex); return data; } -gpointer mc_async_queue_pop_forced (async_queue_t * async_queue) +gpointer mc_async_queue_pop_forced(async_queue_t *async_queue) { gpointer data = NULL; - g_mutex_lock (&async_queue->mutex); + g_mutex_lock(&async_queue->mutex); if (async_queue->head) { GList *node = async_queue->head; @@ -95,28 +97,28 @@ gpointer mc_async_queue_pop_forced (async_queue_t * async_queue) else async_queue->tail = NULL; async_queue->length--; - //LOGD("async queue poped : %p, %d, %p",queue, async_queue->length, data); - g_list_free_1 (node); + /*LOGD("async queue poped : %p, %d, %p",queue, async_queue->length, data);*/ + g_list_free_1(node); } - g_mutex_unlock (&async_queue->mutex); + g_mutex_unlock(&async_queue->mutex); return data; } -void mc_async_queue_disable (async_queue_t * async_queue) +void mc_async_queue_disable(async_queue_t *async_queue) { - g_mutex_lock (&async_queue->mutex); + g_mutex_lock(&async_queue->mutex); async_queue->enabled = FALSE; - g_cond_broadcast (&async_queue->condition); - g_mutex_unlock (&async_queue->mutex); + g_cond_broadcast(&async_queue->condition); + g_mutex_unlock(&async_queue->mutex); } -void mc_async_queue_enable (async_queue_t * async_queue) +void mc_async_queue_enable(async_queue_t *async_queue) { - g_mutex_lock (&async_queue->mutex); + g_mutex_lock(&async_queue->mutex); async_queue->enabled = TRUE; - g_mutex_unlock (&async_queue->mutex); + g_mutex_unlock(&async_queue->mutex); } void mc_async_queue_flush(async_queue_t *async_queue) @@ -129,3 +131,9 @@ void mc_async_queue_flush(async_queue_t *async_queue) g_mutex_unlock(&async_queue->mutex); } + +gboolean mc_async_queue_is_empty(async_queue_t *async_queue) +{ + return async_queue->head == NULL; +} + diff --git a/src/media_codec_util.c b/src/media_codec_util.c index 71d8262..ee16f7f 100755 --- a/src/media_codec_util.c +++ b/src/media_codec_util.c @@ -5,16 +5,15 @@ void *mc_aligned_malloc(int size, int alignment) unsigned char *pMem; unsigned char *tmp; - if((tmp = (unsigned char *)malloc(size + alignment)) != NULL) - { - pMem = (unsigned char*)((unsigned int)(tmp + alignment - 1) & (~(unsigned int)(alignment -1))); + if ((tmp = (unsigned char *)malloc(size + alignment)) != NULL) { + pMem = (unsigned char *)((unsigned int)(tmp + alignment - 1) & (~(unsigned int)(alignment - 1))); - if(pMem == tmp) + if (pMem == tmp) pMem += alignment; *(pMem - 1) = (unsigned int)(pMem - tmp); - return ((void*) pMem); + return ((void *) pMem); } return NULL; } @@ -23,7 +22,7 @@ void mc_aligned_free(void *mem) { unsigned char *ptr; - if(mem == NULL) + if (mem == NULL) return; ptr = mem; @@ -36,9 +35,7 @@ mc_sem_t *mc_sem_new() { mc_sem_t *sem; sem = g_new(mc_sem_t, 1); - //sem->cond = g_cond_new(); g_cond_init(&sem->cond); - //sem->mutex = g_mutex_new(); g_mutex_init(&sem->mutex); sem->counter = 0; @@ -47,9 +44,7 @@ mc_sem_t *mc_sem_new() void mc_sem_free(mc_sem_t *sem) { - //g_cond_free(sem->cond); g_cond_clear(&sem->cond); - //g_mutex_free(sem->mutex); g_mutex_clear(&sem->mutex); g_free(sem); } @@ -58,7 +53,7 @@ void mc_sem_down(mc_sem_t *sem) { g_mutex_lock(&sem->mutex); - while(sem->counter == 0) + while (sem->counter == 0) g_cond_wait(&sem->cond, &sem->mutex); sem->counter--; @@ -80,16 +75,14 @@ void mc_hex_dump(char *desc, void *addr, int len) { int i; unsigned char buff[17]; - unsigned char *pc = (unsigned char*)addr; + unsigned char *pc = (unsigned char *)addr; if (desc != NULL) printf("%s:\n", desc); - for (i = 0; i < len; i++) - { + for (i = 0; i < len; i++) { - if ((i % 16) == 0) - { + if ((i % 16) == 0) { if (i != 0) printf(" %s\n", buff); @@ -111,4 +104,3 @@ void mc_hex_dump(char *desc, void *addr, int len) } printf(" %s\n", buff); } - |