diff options
author | jk7744.park <jk7744.park@samsung.com> | 2015-10-24 16:24:05 +0900 |
---|---|---|
committer | jk7744.park <jk7744.park@samsung.com> | 2015-10-24 16:24:05 +0900 |
commit | 7a70cadf0d29290af314cb8852108d900efff74d (patch) | |
tree | 292c8ed343896ef66648d5f3a17b81ea0c93f152 | |
parent | 76414ed7332777509a4c804fe5ea97a6400ee181 (diff) | |
download | mediacodec-accepted/tizen_2.4_mobile.tar.gz mediacodec-accepted/tizen_2.4_mobile.tar.bz2 mediacodec-accepted/tizen_2.4_mobile.zip |
tizen 2.4 releasetizen_2.4_mobile_releasesubmit/tizen_2.4/20151028.063611accepted/tizen/2.4/mobile/20151029.034705accepted/tizen_2.4_mobile
171 files changed, 5416 insertions, 1746 deletions
@@ -1,2 +1 @@ -Kangho Hur <kanho.hur@samsung.com> -Seungkeun Lee <sngn.lee@samsung.com> +Sejun Park <sejun79.park@samsung.com> diff --git a/CMakeLists.txt b/CMakeLists.txt index e0daaf3..5b4b584 100755..100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,8 +10,8 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) SET(INC_DIR include) INCLUDE_DIRECTORIES(${INC_DIR}) -SET(dependents "dlog glib-2.0 mm-common capi-media-tool libtbm libdri2 gstreamer-0.10 gstreamer-plugins-base-0.10 gstreamer-app-0.10" ) -SET(pc_dependents "capi-base-common capi-media-tool gstreamer-0.10 gstreamer-plugins-base-0.10 gstreamer-app-0.10" ) +SET(dependents "dlog glib-2.0 mm-common libtbm, capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0 capi-system-info" ) +SET(pc_dependents "capi-base-common capi-media-tool gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0" ) INCLUDE(FindPkgConfig) pkg_check_modules(${fw_name} REQUIRED ${dependents}) @@ -19,7 +19,7 @@ FOREACH(flag ${${fw_name}_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) -SET(CMAKE_C_FLAGS "-I./include -I./include/headers ${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Werror") +SET(CMAKE_C_FLAGS "-I./include -I./include/headers ${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") IF("${ARCH}" STREQUAL "arm") diff --git a/capi-media-codec.manifest b/capi-media-codec.manifest index e3deed8..0ee3ca6 100644 --- a/capi-media-codec.manifest +++ b/capi-media-codec.manifest @@ -3,6 +3,6 @@ <domain name="_" /> </request> <assign> - <filesystem path="/usr/bin/player_test" label="_" exec_label="none" /> + <filesystem path="/usr/bin/media_codec_test" label="_" exec_label="none" /> </assign> </manifest> diff --git a/include/media_codec.h b/include/media_codec.h index 678123e..c5161b9 100755 --- a/include/media_codec.h +++ b/include/media_codec.h @@ -37,15 +37,15 @@ extern "C" { /** * @brief Media Codec type handle. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 */ typedef struct mediacodec_s *mediacodec_h; /** * @brief Enumeration of media codec support type - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @remarks If this codec is to be used as an encoder or decoder, the codec flag must be set to #MEDIACODEC_ENCODER or - * #MEDIACODEC_DECODER. If user doesn't set optional flag, default flags will be set to #MEDIACODEC_SUPPORT_TYPE_HW. + * #MEDIACODEC_DECODER. If user doesn't set optional flag, default flags will be set to #MEDIACODEC_SUPPORT_TYPE_SW. */ typedef enum { @@ -57,31 +57,46 @@ typedef enum /** * @brief Enumerations of media codec type - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 */ typedef enum { - MEDIACODEC_NONE = 0x0, /**< NONE*/ - MEDIACODEC_L16 = 0x1010, /**< L16*/ - MEDIACODEC_ALAW = 0x1020, /**< ALAW*/ - MEDIACODEC_ULAW = 0x1030, /**< ULAW*/ - MEDIACODEC_AMR = 0x1040, /**< AMR*/ - MEDIACODEC_G729 = 0x1050, /**< G729*/ - MEDIACODEC_AAC = 0x1060, /**< AAC*/ - MEDIACODEC_MP3 = 0x1070, /**< MP3*/ - - MEDIACODEC_H261 = 0x2010, /**< H.261*/ - MEDIACODEC_H263 = 0x2020, /**< H.263*/ - MEDIACODEC_H264 = 0x2030, /**< H.264*/ - MEDIACODEC_MJPEG = 0x2040, /**< MJPEG*/ - MEDIACODEC_MPEG1 = 0x2050, /**< MPEG1*/ - MEDIACODEC_MPEG2 = 0x2060, /**< MPEG2*/ - MEDIACODEC_MPEG4 = 0x2070, /**< MPEG4*/ + MEDIACODEC_NONE = 0x0, /**< NONE*/ + MEDIACODEC_L16 = 0x1010, /**< L16*/ + MEDIACODEC_ALAW = 0x1020, /**< ALAW*/ + MEDIACODEC_ULAW = 0x1030, /**< ULAW*/ + MEDIACODEC_AMR = 0x1040, /**< MEDIACDEC_AMR indicates AMR-NB (Since 2.4)*/ + MEDIACODEC_AMR_NB = 0x1040, /**< AMR-NB (Since 2.4)*/ + MEDIACODEC_AMR_WB = 0x1041, /**< AMR-WB (Since 2.4)*/ + MEDIACODEC_G729 = 0x1050, /**< G729*/ + MEDIACODEC_AAC = 0x1060, /**< MEDIACDEC_AAC indicates AAC-LC (Since 2.4)*/ + MEDIACODEC_AAC_LC = 0x1060, /**< AAC-LC (Since 2.4)*/ + MEDIACODEC_AAC_HE = 0x1061, /**< HE-AAC (Since 2.4)*/ + MEDIACODEC_AAC_HE_PS = 0x1062, /**< HE-AAC-PS (Since 2.4)*/ + MEDIACODEC_MP3 = 0x1070, /**< MP3*/ + MEDIACODEC_VORBIS = 0x1080, /**< VORBIS (Since 2.4)*/ + MEDIACODEC_FLAC = 0x1090, /**< FLAC (Since 2.4)*/ + MEDIACODEC_WMAV1 = 0x10A0, /**< WMA version 1 (Since 2.4)*/ + MEDIACODEC_WMAV2 = 0x10A1, /**< WMA version 2 (Since 2.4)*/ + MEDIACODEC_WMAPRO = 0x10A2, /**< WMA Professional (Since 2.4)*/ + MEDIACODEC_WMALSL = 0x10A3, /**< WMA Lossless (Since 2.4)*/ + + MEDIACODEC_H261 = 0x2010, /**< H.261*/ + MEDIACODEC_H263 = 0x2020, /**< H.263*/ + MEDIACODEC_H264 = 0x2030, /**< H.264*/ + MEDIACODEC_MJPEG = 0x2040, /**< MJPEG*/ + MEDIACODEC_MPEG1 = 0x2050, /**< MPEG1*/ + MEDIACODEC_MPEG2 = 0x2060, /**< MPEG2*/ + MEDIACODEC_MPEG4 = 0x2070, /**< MPEG4*/ + MEDIACODEC_HEVC = 0x2080, /**< HEVC (Since 2.4)*/ + MEDIACODEC_VP8 = 0x2090, /**< VP8 (Since 2.4)*/ + MEDIACODEC_VP9 = 0x20A0, /**< VP9 (Since 2.4)*/ + MEDIACODEC_VC1 = 0x20B0, /**< VC1 (Since 2.4)*/ } mediacodec_codec_type_e; /** * @brief Enumeration of media codec error - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 */ typedef enum { @@ -103,11 +118,23 @@ typedef enum MEDIACODEC_ERROR_STREAM_NOT_FOUND = TIZEN_ERROR_MEDIACODEC | 0x0a, /**< Cannot find stream */ MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT = TIZEN_ERROR_MEDIACODEC | 0x0b, /**< Not supported format */ MEDIACODEC_ERROR_BUFFER_NOT_AVAILABLE = TIZEN_ERROR_MEDIACODEC | 0x0c, /**< Not available buffer */ + MEDIACODEC_ERROR_OVERFLOW_INBUFFER = TIZEN_ERROR_MEDIACODEC | 0x0d, /**< Overflow input buffer (Since 2.4)*/ + MEDIACODEC_ERROR_RESOURCE_OVERLOADED = TIZEN_ERROR_MEDIACODEC | 0x0e, /**< Exceed the instance limits (Since 2.4)*/ } mediacodec_error_e; /** + * @brief Enumeration of buffer status + * @since_tizen 2.4 + */ +typedef enum +{ + MEDIACODEC_NEED_DATA, + MEDIACODEC_ENOUGH_DATA +} mediacodec_status_e; + +/** * @brief Called when the input buffer(pkt) used up. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @details It will be invoked when mediacodec has used input buffer. * @param[in] pkt The media packet handle * @param[in] user_data The user data passed from the callback registration function @@ -119,7 +146,7 @@ typedef void (*mediacodec_input_buffer_used_cb)(media_packet_h pkt, void *user_d /** * @brief Called when the output buffer is available. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @details It will be invoked when mediacodec has output buffer. * @param[in] pkt The media packet handle * @param[in] user_data The user data passed from the callback registration function @@ -131,7 +158,7 @@ typedef void (*mediacodec_output_buffer_available_cb)(media_packet_h pkt, void * /** * @brief Called when the error has occured - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @details It will be invoked when the error has occured. * @param[in] error_code The error code * @param[in] user_data The user data passed from the callback registration function @@ -143,7 +170,7 @@ typedef void (*mediacodec_error_cb)(mediacodec_error_e error, void *user_data); /** * @brief Called when there is no data to decode/encode - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @details It will be invoked when the end-of-stream is reached. * @param[in] user_data The user data passed from the callback registration function * @pre It will be invoked when the eos event generate if you register this callback using mediacodec_set_eos_cb(). @@ -153,8 +180,30 @@ typedef void (*mediacodec_error_cb)(mediacodec_error_e error, void *user_data); typedef void (*mediacodec_eos_cb)(void *user_data); /** + * @brief Called when the mediacodec needs more data or has enough data. + * @since_tizen 2.4 + * @details It is recommended that the application stops calling mediacodec_process_input() when MEDIACODEC_ENOUGH_DATA + * is invoked. + * @param[in] user_data The user data passed from the callback registration function + * @see mediacodec_set_buffer_status_cb() + * @see mediacodec_unset_buffer_status_cb() + */ +typedef void (*mediacodec_buffer_status_cb)(mediacodec_status_e status, void *user_data); + +/** + * @brief Called once for each supported codec types. + * @since_tizen 2.4 + * @param[in] codec_type The codec type + * @param[in] user_data The user data passed from the foreach function + * @return @c true to continue with the next iteration of the loop, @c false to break out of the loop. + * @pre mediacodec_foreach_supported_codec() will invoke this callback. + * @see mediacodec_foreach_supported_codec() + */ +typedef bool (*mediacodec_supported_codec_cb)(mediacodec_codec_type_e codec_type, void *user_data); + +/** * @brief Creates a mediacodec handle for decoding/encoding - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @remarks you must release @a mediacodec using mediacodec_destroy().\n * Although you can create multiple mediacodec handles at the same time, * the mediacodec cannot guarantee proper operation because of limited resources, like @@ -171,7 +220,7 @@ int mediacodec_create(mediacodec_h *mediacodec); /** * @brief Destroys the mediacodec handle and releases all its resources. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @remarks To completely shutdown the mediacodec operation, call this function with a valid player handle from any * mediacodec * @@ -181,18 +230,24 @@ int mediacodec_create(mediacodec_h *mediacodec); * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + @code + #include <media_codec.h> + mediacodec_h mediacodec; + + mediacodec_create(&mediacodec); + @endcode */ int mediacodec_destroy(mediacodec_h mediacodec); /** * @brief Sets the codec type and decoder/encoder. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @remarks If this codec is to be used as a decoder, pass the #MEDIACODEC_DECODER flag. * If this codec is to be used as an encoder, pass the #MEDIACODEC_ENCODER flag. - * By default, It is used hardware default setting. If user want software setting, pass the + * By default, It is used software default setting. If user want software setting, pass the * #MEDIACODEC_SUPPORT_TYPE_SW flags. * @param[in] mediacodec The handle of mediacodec - * @param[in] codec_id The identifier of the codec type of the decoder/encoder + * @param[in] codec_type The identifier of the codec type of the decoder/encoder * @param[in] flags The encoding/decoding scheme. * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful @@ -200,12 +255,19 @@ int mediacodec_destroy(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation * @retval #MEDIACODEC_ERROR_CODEC_NOT_FOUND Codec not found + @code + #include <media_codec.h> + mediacodec_h mediacodec; + + mediacodec_create(&mediacodec); + mediacodec_destroy(mediacodec); + @endcode */ -int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_id, mediacodec_support_type_e flags); +int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_type, mediacodec_support_type_e flags); /** * @brief Sets the default info for the video decoder - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @param[in] width The width for video decoding. * @param[in] height The height for video decoding. @@ -214,12 +276,19 @@ int mediacodec_set_codec(mediacodec_h mediacodec, mediacodec_codec_type_e codec_ * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + @code + #include <media_codec.h> + mediacodec_h mediacodec; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW); + @endcode */ int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height); /** * @brief Sets the default info for the video encoder - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @remarks The frame rate is the speed of recording and the speed of playback. * If user wants the default setting for ratecontrol, set @a target_bits to @c 0. * @param[in] mediacodec The handle to mediacodec @@ -232,12 +301,20 @@ int mediacodec_set_vdec_info(mediacodec_h mediacodec, int width, int height); * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + @code + #include <media_codec.h> + mediacodec_h mediacodec; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_H264, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_HW); + mediacodec_set_venc_info(mediacodec, 640, 480, 30, 1000); + @endcode */ int mediacodec_set_venc_info(mediacodec_h mediacodec, int width, int height, int fps, int target_bits); /** * @brief Sets the default info for the audio decoder - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @param[in] samplerate The samplerate for audio decoding. * @param[in] channel The channels for audio decoding. @@ -247,28 +324,44 @@ int mediacodec_set_venc_info(mediacodec_h mediacodec, int width, int height, int * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + @code + #include <media_codec.h> + mediacodec_h mediacodec; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_AAC, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW); + mediacodec_set_adec_info(mediacodec, 44100, 2, 16); + @endcode */ int mediacodec_set_adec_info(mediacodec_h mediacodec, int samplerate, int channel, int bit); /** * @brief Sets the default info for the audio encdoer - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @param[in] samplerate The samplerate for audio encoding. * @param[in] channel The channels for audio encoding. - * @param[in] bit The bits resolution for audio encoding. - * @param[in] bitrate The bitrate for audio encoding. + * @param[in] bit The bits resolution for audio encoding. + * @param[in] bitrate The bitrate for audio encoding. * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + @code + #include <media_codec.h> + mediacodec_h mediacodec; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_AAC, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_SW); + mediacodec_set_aenc_info(mediacodec, 44100, 2, 16, 128); + @endcode */ int mediacodec_set_aenc_info(mediacodec_h mediacodec, int samplerate, int channel, int bit, int bitrate); /** * @brief Prepares @a mediacodec for encoding/decoding. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful @@ -278,25 +371,42 @@ int mediacodec_set_aenc_info(mediacodec_h mediacodec, int samplerate, int channe * @pre The mediacodec should call mediacodec_set_codec()and mediacodec_set_vdec_info()/mediacodec_set_venc_info() before calling mediacodec_prepare() * If the decoder is set by mediacodec_set_codec(), mediacodec_set_vdec_info() should be called. If the encoder is set by * mediacodec_set_codec(), mediacodec_set_venc_info() should be called. + @code + #include <media_codec.h> + mediacodec_h mediacodec; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW); + mediacodec_prepare(mediacodec); + @endcode */ int mediacodec_prepare(mediacodec_h mediacodec); /** * @brief Unprepares @a mediacodec for encoding/decoding. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + @code + #include <media_codec.h> + mediacodec_h mediacodec; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW); + mediacodec_prepare(mediacodec); + mediacodec_unprepare(mediacodec); + @endcode */ int mediacodec_unprepare(mediacodec_h mediacodec); /** * @brief Decodes/Encodes a packet. The function passed undecoded/unencoded packet to the input queue and decode/encode a * frame sequentially. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @param[in] inbuf The current input format for the decoder/encoder * @param[in] timeOutUs The timeout in microseconds. \n @@ -306,14 +416,25 @@ int mediacodec_unprepare(mediacodec_h mediacodec); * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + * @retval #MEDIACODEC_ERROR_OVERFLOW_INBUFFER Overflow inputbuffer + @code + #include <media_codec.h> + mediacodec_h mediacodec; + media_packet_h pkt; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW); + mediacodec_prepare(mediacodec); + mediacodec_process_input(pkt); + @endcode */ int mediacodec_process_input (mediacodec_h mediacodec, media_packet_h inbuf, uint64_t timeOutUs); /** * @brief Gets the decoded or encoded packet from the output queue. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec - * @param[in] outbuf The current output of the decoder/encoder. this function passed decoded/encoded frame to output + * @param[out] outbuf The current output of the decoder/encoder. this function passed decoded/encoded frame to output * queue. * @param[in] timeOutUs The timeout in microseconds. \n * The input buffer wait up to "timeOutUs" microseconds. @@ -322,12 +443,46 @@ int mediacodec_process_input (mediacodec_h mediacodec, media_packet_h inbuf, uin * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter * @retval #MEDIACODEC_ERROR_OUT_OF_MEMORY Out of memory * @retval #MEDIACODEC_ERROR_INVALID_OPERATION Invalid operation + @code + #include <media_codec.h> + mediacodec_h mediacodec; + media_packet_h pkt; + media_packet_h out_pkt; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW); + mediacodec_prepare(mediacodec); + mediacodec_process_input(pkt); + mediacodec_get_output(mediacodec, &out_pkt, 1000); + @endcode */ int mediacodec_get_output (mediacodec_h mediacodec, media_packet_h *outbuf, uint64_t timeOutUs); /** + * @brief Flushes both input and output buffers. + * @since_tizen 2.4 + * @param[in] mediacodec The handle to mediacodec + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + @code + #include <media_codec.h> + mediacodec_h mediacodec; + media_packet_h pkt; + media_packet_h out_pkt; + + mediacodec_create(&mediacodec); + mediacodec_set_codec(mediacodec, MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW); + mediacodec_prepare(mediacodec); + mediacodec_process_input(pkt); + mediacodec_flush_buffers(mediacodec); + @endcode + */ +int mediacodec_flush_buffers (mediacodec_h mediacodec); + +/** * @brief set empty buffer callback the media codec for process, asynchronously. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register * @param[in] user_data The user data to be passed to the callback function @@ -343,7 +498,7 @@ int mediacodec_set_input_buffer_used_cb(mediacodec_h mediacodec, mediacodec_inpu /** * @brief unset input buffer used callback the media codec for process, asynchronously. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful @@ -354,7 +509,7 @@ int mediacodec_unset_input_buffer_used_cb(mediacodec_h mediacodec); /** * @brief set output buffer available callback the media codec for process, asynchronously. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register * @param[in] user_data The user data to be passed to the callback function @@ -370,7 +525,7 @@ int mediacodec_set_output_buffer_available_cb(mediacodec_h mediacodec, mediacode /** * @brief unset output buffer available callback the media codec for process, asynchronously. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful @@ -381,7 +536,7 @@ int mediacodec_unset_output_buffer_available_cb(mediacodec_h mediacodec); /** * @brief set error callback the media codec for process, asynchronously. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register * @param[in] user_data The user data to be passed to the callback function @@ -397,7 +552,7 @@ int mediacodec_set_error_cb(mediacodec_h mediacodec, mediacodec_error_cb callbac /** * @brief unset error callback the media codec for process, asynchronously. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful @@ -408,7 +563,7 @@ int mediacodec_unset_error_cb(mediacodec_h mediacodec); /** * @brief set eos callback the media codec for process, asynchronously. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @param[in] callback The callback function to register * @param[in] user_data The user data to be passed to the callback function @@ -424,7 +579,7 @@ int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, v /** * @brief unset eos callback the media codec for process, asynchronously. - * @since_tizen @if MOBILE 2.3 @elseif WEARABLE 2.3.1 @endif + * @since_tizen 2.3 * @param[in] mediacodec The handle to mediacodec * @return @c 0 on success, otherwise a negative error value * @retval #MEDIACODEC_ERROR_NONE Successful @@ -434,6 +589,77 @@ int mediacodec_set_eos_cb(mediacodec_h mediacodec, mediacodec_eos_cb callback, v int mediacodec_unset_eos_cb(mediacodec_h mediacodec); /** + * @brief Registers a callback function to be invoked when the mediacodec needs more data or has enough data. + * @since_tizen 2.4 + * @param[in] mediacodec The handle to mediacodec + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @pre mediacodec_set_buffer_status_cb should be called before mediacodec_preare(). + * @post mediacodec_buffer_status_cb will be invoked. + * @see mediacodec_set_buffer_status_cb() + * @see mediacodec_unset_buffer_status_cb() + */ +int mediacodec_set_buffer_status_cb(mediacodec_h mediacodec, mediacodec_buffer_status_cb callback, void* user_data); + +/** + * @brief Unregisters the callback function. + * @since_tizen 2.4 + * @param[in] mediacodec The handle to mediacodec + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + */ +int mediacodec_unset_buffer_status_cb(mediacodec_h mediacodec); + +/** + * @brief Retrieves all supported codecs by invoking callback function once for each supported codecs. + * @since_tizen 2.4 + * @param[in] mediacodec The handle to mediacodec + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + * @see mediacodec_foreach_supported_codec() + */ +int mediacodec_foreach_supported_codec(mediacodec_h mediacodec, mediacodec_supported_codec_cb callback, void *user_data); + +/** + * @brief Verifies whether encoding can be performed with codec_type or not. + * @since_tizen 2.4 + * @param[in] mediacodec The handle to mediacodec + * @param[in] codec_type The identifier of the codec type of the encoder. + * @param[in] encoder Whether the encoder or decoder : (@c true = encoder, @c false = decoder). + * @param[out] support_type (@c MEDIACODEC_SUPPORT_TYPE_HW = mediacodec can be performed with hardware codec, @c MEDIACODEC_SUPPORT_TYPE_SW = mediacodec can be performed with software codec) + * @return @c 0 on success, otherwise a negative error value + * @retval #MEDIACODEC_ERROR_NONE Successful + * @retval #MEDIACODEC_ERROR_INVALID_PARAMETER Invalid parameter + @code + #include <media_codec.h> + mediacodec_h mediacodec; + mediacodec_support_type_e type; + mediacodec_codec_type_e codec_type = MEDIACODEC_H264; + + mediacodec_create(&mediacodec); + mediacodec_get_supported_type(mediacodec, codec_type, 1, &type); + + if(type == MEDIACODEC_SUPPORT_TYPE_HW) + // only h/w supported + else if (type == MEDIACODEC_SUPPORT_TYPE_SW) + // only s/w supported + else if (type == (MEDIACODEC_SUPPORT_TYPE_HW|MEDIACODEC_SUPPORT_TYPE_SW) + // both supported + + mediacodec_set_codec(mediacodec, codec_type, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_HW); + @endcode + */ +int mediacodec_get_supported_type(mediacodec_h mediacodec, mediacodec_codec_type_e codec_type, bool encoder, int *support_type); + + +/** * @} */ diff --git a/include/media_codec_bitstream.h b/include/media_codec_bitstream.h new file mode 100755 index 0000000..44329ba --- /dev/null +++ b/include/media_codec_bitstream.h @@ -0,0 +1,113 @@ +/* +* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __TIZEN_MEDIA_CODEC_BITSTREAM_H__ +#define __TIZEN_MEDIA_CODEC_BITSTREAM_H__ + +#include <tizen.h> +#include <media_codec_port.h> + +typedef struct _mc_bitstream_t mc_bitstream_t; + +typedef enum +{ + NAL_SLICE_NO_PARTITIONING = 1, + NAL_SLICE_PART_A, + NAL_SLICE_PART_B, + NAL_SLICE_PART_C, + NAL_SLICE_IDR, + NAL_SEI, + NAL_SEQUENCE_PARAMETER_SET, + NAL_PICTURE_PARAMETER_SET, + NAL_PICTURE_DELIMITER, + NAL_END_OF_SEQUENCE, + NAL_END_OF_STREAM, + NAL_FILLER_DATA, + NAL_PREFIX_SVC = 14 +} mc_nal_unit_type_e; + +enum +{ + MC_EXIST_SPS = 1 << 0, + MC_EXIST_PPS = 1 << 1, + MC_EXIST_IDR = 1 << 2, + MC_EXIST_SLICE = 1 << 3, + + MC_VALID_HEADER = ( MC_EXIST_SPS | MC_EXIST_PPS ), + MC_VALID_FIRST_SLICE = ( MC_EXIST_SPS | MC_EXIST_PPS | MC_EXIST_IDR ) +}; + +#define CHECK_VALID_PACKET(state, expected_state) \ + ((state & (expected_state)) == (expected_state)) + +static const unsigned int mask[33] = +{ + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, + 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, + 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, + 0xffffffff +}; + +struct _mc_bitstream_t +{ + unsigned char *data; + unsigned int numBytes; + unsigned int bytePos; + unsigned int buffer; + unsigned int dataBitPos; + unsigned int bitcnt; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + +#define MC_READ16B(x) ((((const unsigned char*)(x))[0] << 8) | ((const unsigned char*)(x))[1]) + +#define MC_READ32B(x) ((((const unsigned char*)(x))[0] << 24) | \ + (((const unsigned char*)(x))[1] << 16) | \ + (((const unsigned char*)(x))[2] << 8) | \ + ((const unsigned char*)(x))[3]) + +void mc_init_bits(mc_bitstream_t *stream, unsigned char *data, int size); +short mc_show_bits(mc_bitstream_t *stream, unsigned char nbits, unsigned int *pulOutData); +short mc_read_bits( mc_bitstream_t *stream, unsigned char nbits, unsigned int *pulOutData ); +short mc_byte_align( mc_bitstream_t *stream ); + +bool _mc_is_voss(unsigned char *buf, int size, int *codec_size); +bool _mc_is_ivop(unsigned char *p, int size, int pos); +bool _mc_is_vop(unsigned char *p, int size, int pos); + + +int __mc_decode_sps(mc_bitstream_t *pstream, int *width, int *height); +unsigned int __mc_bytestream_to_nal( unsigned char* data, int size ); +int _mc_check_h264_bytestream ( unsigned char *nal, int byte_length, bool port, bool *codec_config, bool *sync_flag, bool *slice); +int _mc_check_valid_h263_frame(unsigned char *p, int size); +bool _mc_check_h263_out_bytestream(unsigned char *p, int buf_length, bool* need_sync_flag); +int _mc_check_mpeg4_out_bytestream(unsigned char *buf, int buf_length, bool* need_codec_data, bool *need_sync_flag); + + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_MEDIA_CODEC_BITSTREAM_H__ */ diff --git a/include/media_codec_ini.h b/include/media_codec_ini.h new file mode 100755 index 0000000..daca4e7 --- /dev/null +++ b/include/media_codec_ini.h @@ -0,0 +1,103 @@ +/* +* 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 __TIZEN_MEDIA_CODEC_INI_H__ +#define __TIZEN_MEDIA_CODEC_INI_H__ + +#include <glib.h> +#include <mm_types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define MEDIA_CODEC_INI_DEFAULT_PATH "/usr/etc/mmfw_media_codec.ini" +#define MEDIA_CODEC_INI_MAX_STRLEN 256 +#define DEFAULT_PORT "GST_PORT" +#define MEDIA_CODEC_MAX_CODEC_TYPE 100 +#define MEDIA_CODEC_MAX_CODEC_ROLE 4 + +#define MEDICODEC_INI_MAX_ELEMENT 10 +#define MEDIA_CODEC_MAX_VIDEO_CODEC 100 +#define MEDIA_CODEC_MAX_AUDIO_CODEC 100 + + +typedef enum { + GST_PORT = 0, + FFMPEG_PORT, + CUSTOM_PORT, +} port_mode; + +typedef struct { + gchar name[MEDIA_CODEC_INI_MAX_STRLEN]; + gchar mime[MEDIA_CODEC_INI_MAX_STRLEN]; + gchar format[MEDIA_CODEC_INI_MAX_STRLEN]; +} codec_info_t; + +typedef struct { + gint codec_id; + codec_info_t codec_info[MEDIA_CODEC_MAX_CODEC_ROLE]; +} codec_t; + + +/* @ mark means the item has tested */ +typedef struct __mc_ini { + port_mode port_type; + /* general */ + gchar port_name[MEDIA_CODEC_INI_MAX_STRLEN]; + codec_t codec[MEDIA_CODEC_MAX_CODEC_TYPE]; +} mc_ini_t; + +/*Default sink ini values*/ +/* General*/ + +/* NOTE : following content should be same with above default values */ +/* FIXIT : need smarter way to generate default ini file. */ +/* FIXIT : finally, it should be an external file */ +#define MEDIA_CODEC_DEFAULT_INI \ + "\ +[general] \n\ +\n\ +;Add general config parameters here\n\ +\n\ +\n\ +\n\ +[port_in_use] \n\ +\n\ +;media_codec_port = GST_PORT \n\ +;media_codec_port = FFMPEG_PORT \n\ +;media_codec_port = CUSTOM_PORT \n\ +media_codec_port = GST_PORT \n\ +\n\ +[gst_port] \n\ +\n\ +;Add gst port specific config paramters here\n\ +\n\ +\n\ +[custom_port] \n\ +\n\ +;Add custom port specific config paramters here\n\ +\n\ +\n\ +\n\ +" + +int mc_ini_load(mc_ini_t *ini); + +#ifdef __cplusplus +} +#endif +#endif /*__TIZEN_MEDIA_CODEC_INI_H__*/ diff --git a/include/media_codec_port.h b/include/media_codec_port.h index 92d80f2..cd6d76f 100755 --- a/include/media_codec_port.h +++ b/include/media_codec_port.h @@ -24,7 +24,9 @@ #include <media_codec.h> #include <media_codec_queue.h> +#include <media_codec_bitstream.h> #include <media_codec_spec_emul.h> +#include <media_codec_ini.h> /*=========================================================================================== @@ -36,7 +38,6 @@ /*--------------------------------------------------------------------------- | GLOBAL #defines: | ---------------------------------------------------------------------------*/ -#define OUT_BUF_SIZE 9000000 #define CHECK_BIT(x, y) (((x) >> (y)) & 0x01) #define GET_IS_ENCODER(x) CHECK_BIT(x, 0) #define GET_IS_DECODER(x) CHECK_BIT(x, 1) @@ -46,6 +47,13 @@ //#define GET_IS_OMX(x) CHECK_BIT(x, 4) //#define GET_IS_GEN(x) CHECK_BIT(x, 5) +#if 1 +#define MEDIACODEC_FENTER(); +#define MEDIACODEC_FLEAVE(); +#else +#define MEDIACODEC_FENTER(); LOGW("%s Enter",__FUNCTION__); +#define MEDIACODEC_FLEAVE(); LOGW("%s Exit",__FUNCTION__); +#endif /*--------------------------------------------------------------------------- | GLOBAL CONSTANT DEFINITIONS: | @@ -74,6 +82,7 @@ typedef enum MC_OUTPUT_BUFFER_EMPTY = -16, MC_OUTPUT_BUFFER_OVERFLOW = -17, /**< codec output buffer is overflow */ MC_MEMORY_ALLOCED = -18, /**< codec has got memory and can decode one frame */ + MC_COURRPTED_INI = -19, } mc_ret_e; /*--------------------------------------------------------------------------- @@ -88,18 +97,25 @@ typedef enum * @see mediacodec_unset_dequeue_input_buffer_cb() */ + typedef struct _mc_decoder_info_t mc_decoder_info_t; typedef struct _mc_encoder_info_t mc_encoder_info_t; typedef struct _mc_handle_t mc_handle_t; -#define MEDIACODEC_CMD_LOCK(x_mediacodec) g_mutex_lock(&((mc_handle_t*)x_mediacodec)->cmd_lock ) -#define MEDIACODEC_CMD_UNLOCK(x_mediacodec) g_mutex_unlock( &((mc_handle_t*)x_mediacodec)->cmd_lock ) - typedef void (*mc_dequeue_input_buffer_cb)(media_packet_h pkt, void *user_data); typedef void (*mc_empty_buffer_cb)(media_packet_h pkt, void *user_data); typedef void (*mc_fill_buffer_cb)(media_packet_h pkt, void *user_data); typedef void (*mc_error_cb)(mediacodec_error_e error, void *user_data); typedef void (*mc_eos_cb)(void *user_data); +typedef void (*mc_buffer_status_cb)(mediacodec_status_e status, void *user_data); +typedef void (*mc_supported_codec_cb)(mediacodec_codec_type_e codec_type, void *user_data); + +int (*mc_sniff_bitstream)(mc_handle_t *handle, media_packet_h pkt); + +int mc_sniff_h264_bitstream(mc_handle_t *handle, media_packet_h pkt); +int mc_sniff_mpeg4_bitstream(mc_handle_t *handle, media_packet_h pkt); +int mc_sniff_h263_bitstream(mc_handle_t *handle, media_packet_h pkt); +int mc_sniff_yuv(mc_handle_t *handle, media_packet_h pkt); typedef enum { _MEDIACODEC_EVENT_TYPE_COMPLETE, @@ -107,19 +123,30 @@ typedef enum { _MEDIACODEC_EVENT_TYPE_FILLBUFFER, _MEDIACODEC_EVENT_TYPE_ERROR, _MEDIACODEC_EVENT_TYPE_EOS, + _MEDIACODEC_EVENT_TYPE_BUFFER_STATUS, _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER, + _MEDIACODEC_EVENT_TYPE_SUPPORTED_CODEC, _MEDIACODEC_EVENT_TYPE_NUM } _mediacodec_event_e; typedef enum _mc_codec_port_type_e { - CODEC_PORT_TYPE_GENERAL, - CODEC_PORT_TYPE_OMX, - CODEC_PORT_TYPE_GST, - CODEC_PORT_TYPE_MAX, + CODEC_PORT_TYPE_GENERAL, + CODEC_PORT_TYPE_OMX, + CODEC_PORT_TYPE_GST, + CODEC_PORT_TYPE_MAX, } mc_codec_port_type_e; +typedef enum _mc_vendor_e +{ + MC_VENDOR_DEFAULT, + MC_VENDOR_SLSI_SEC, + MC_VENDOR_SLSI_EXYNOS, + MC_VENDOR_QCT, + MC_VENDOR_SPRD +} mc_vendor_e; + struct _mc_decoder_info_t { int width; @@ -150,7 +177,6 @@ struct _mc_encoder_info_t int bit; }; - /* Codec Private data */ struct _mc_handle_t { @@ -160,9 +186,10 @@ struct _mc_handle_t bool is_hw; bool is_prepared; - GMutex cmd_lock; + GList *supported_codecs; mediacodec_port_type_e port_type; mediacodec_codec_type_e codec_id; + mc_vendor_e vendor; void *ports[2]; void *core; @@ -177,6 +204,14 @@ struct _mc_handle_t void* user_cb[_MEDIACODEC_EVENT_TYPE_NUM]; void* user_data[_MEDIACODEC_EVENT_TYPE_NUM]; + mc_codec_map_t encoder_map[MEDIA_CODEC_MAX_CODEC_TYPE]; + mc_codec_map_t decoder_map[MEDIA_CODEC_MAX_CODEC_TYPE]; + + int num_supported_codecs; + int num_supported_decoder; + int num_supported_encoder; + + mc_ini_t ini; }; /*=========================================================================================== @@ -206,6 +241,9 @@ int mc_unprepare(MMHandleType mediacodec); int mc_process_input(MMHandleType mediacodec, media_packet_h inbuf, uint64_t timeOutUs); int mc_get_output(MMHandleType mediacodec, media_packet_h *outbuf, uint64_t timeOutUs); +int mc_flush_buffers(MMHandleType mediacodec); +int mc_get_supported_type(MMHandleType mediacodec, mediacodec_codec_type_e codec_type, bool encoder, int *support_type); + int mc_set_empty_buffer_cb(MMHandleType mediacodec, mediacodec_input_buffer_used_cb callback, void* user_data); int mc_unset_empty_buffer_cb(MMHandleType mediacodec); @@ -218,6 +256,10 @@ int mc_unset_error_cb(MMHandleType mediacodec); int mc_set_eos_cb(MMHandleType mediacodec, mediacodec_eos_cb callback, void* user_data); int mc_unset_eos_cb(MMHandleType mediacodec); +int mc_set_buffer_status_cb(MMHandleType mediacodec, mediacodec_buffer_status_cb callback, void* user_data); +int mc_unset_buffer_status_cb(MMHandleType mediacodec); + + #ifdef __cplusplus } #endif diff --git a/include/media_codec_port_gst.h b/include/media_codec_port_gst.h index 4a3dd5c..1908081 100755 --- a/include/media_codec_port_gst.h +++ b/include/media_codec_port_gst.h @@ -23,42 +23,38 @@ #include <media_codec.h> #include <media_codec_private.h> #include <media_codec_port.h> +#include <media_codec_bitstream.h> #include <tbm_type.h> #include <tbm_surface.h> #include <tbm_bufmgr.h> #include <tbm_surface_internal.h> +#include <gst/video/video-format.h> #ifdef __cplusplus extern "C" { #endif -#if 0 -#define MMPLAYER_FENTER(); debug_fenter(); -#define MMPLAYER_FLEAVE(); debug_fleave(); -#else -#define MMPLAYER_FENTER(); LOGW("%s Enter",__FUNCTION__); -#define MMPLAYER_FLEAVE(); LOGW("%s Exit",__FUNCTION__); -#endif - - #define GST_INIT_STRUCTURE(param) \ memset(&(param), 0, sizeof(param)); -#define MEDIACODEC_ELEMENT_SET_STATE( x_element, x_state ) \ -LOGD("setting state [%s:%d] to [%s]\n", #x_state, x_state, GST_ELEMENT_NAME( x_element ) ); \ -if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state ( x_element, x_state) ) \ -{ \ - LOGE("failed to set state %s to %s\n", #x_state, GST_ELEMENT_NAME( x_element )); \ - goto STATE_CHANGE_FAILED; \ -} +#define MEDIACODEC_ELEMENT_SET_STATE( x_element, x_state ) \ + do { \ + LOGD("setting state [%s:%d] to [%s]\n", #x_state, x_state, GST_ELEMENT_NAME( x_element ) ); \ + if ( GST_STATE_CHANGE_FAILURE == gst_element_set_state ( x_element, x_state) ) \ + { \ + LOGE("failed to set state %s to %s\n", #x_state, GST_ELEMENT_NAME( x_element )); \ + goto STATE_CHANGE_FAILED; \ + } \ + } while (0) #define SCMN_IMGB_MAX_PLANE 4 -#define TBM_API_CHANGE //this need for temporary test - tbm_surface_internal_create_with_bos() API change +#define TBM_API_CHANGE + /* gst port layer */ typedef struct _mc_gst_port_t mc_gst_port_t; typedef struct _mc_gst_core_t mc_gst_core_t; -typedef struct _mc_gst_buffer_t mc_gst_buffer_t; +typedef struct _GstMCBuffer GstMCBuffer; typedef enum { BUF_SHARE_METHOD_PADDR = 0, @@ -69,37 +65,13 @@ typedef enum { #ifdef TIZEN_PROFILE_LITE struct ion_mmu_data { - int fd_buffer; - unsigned long iova_addr; - size_t iova_size; + int master_id; + int fd_buffer; + unsigned long iova_addr; + size_t iova_size; }; #endif -typedef struct -{ - int w[SCMN_IMGB_MAX_PLANE]; /* width of each image plane */ - int h[SCMN_IMGB_MAX_PLANE]; /* height of each image plane */ - int s[SCMN_IMGB_MAX_PLANE]; /* stride of each image plane */ - int e[SCMN_IMGB_MAX_PLANE]; /* elevation of each image plane */ - void *a[SCMN_IMGB_MAX_PLANE]; /* user space address of each image plane */ - void *p[SCMN_IMGB_MAX_PLANE]; /* physical address of each image plane, if needs */ - int cs; /* color space type of image */ - int x; /* left postion, if needs */ - int y; /* top position, if needs */ - int __dummy2; /* to align memory */ - int data[16]; /* arbitrary data */ - int dma_buf_fd[SCMN_IMGB_MAX_PLANE]; /* DMABUF fd of each image plane */ - /* buffer share method */ - int buf_share_method; /* will be 2(BUF_SHARE_METHOD_TIZEN_BUFFER)*/ - int y_size; /* Y plane size in case of ST12 */ - /* UV plane size in case of ST12 */ - int uv_size; /* UV plane size in case of ST12 */ - tbm_bo bo[SCMN_IMGB_MAX_PLANE]; /* Tizen buffer object of each image plane */ - void *jpeg_data; /* JPEG data */ - int jpeg_size; /* JPEG size */ - int tz_enable; /* TZ memory buffer */ -} SCMN_IMGB; - struct _mc_gst_port_t { mc_gst_core_t *core; @@ -118,12 +90,17 @@ struct _mc_gst_core_t { int(**vtable)(); const char *mime; - int format; + //int format; + gchar *format; GstElement* pipeline; GstElement* appsrc; + GstElement* capsfilter; + GstElement* parser; GstElement* fakesink; GstElement* codec; - SCMN_IMGB *psimgb; + MMVideoBuffer *psimgb; + tbm_bufmgr bufmgr; + int drm_fd; GMainContext *thread_default; gulong signal_handoff; @@ -132,12 +109,10 @@ struct _mc_gst_core_t GMutex eos_mutex; GMutex eos_wait_mutex; - GMutex drain_mutex; GMutex prepare_lock; + GMutex drain_lock; GCond eos_cond; GCond eos_waiting_cond; - //mc_sem_t *push_sem; - //mc_sem_t *pop_sem; GstState state; bool output_allocated; @@ -148,49 +123,91 @@ struct _mc_gst_core_t bool eos_waiting; bool codec_config; bool need_feed; - int prepare_count; - int num_live_buffers; + bool need_codec_data; + bool need_sync_flag; + bool unprepare_flag; + unsigned int prepare_count; + unsigned int num_live_buffers; + unsigned int queued_count; + unsigned int dequeued_count; + mediacodec_codec_type_e codec_id; + media_format_mimetype_e out_mime; media_format_h output_fmt; mc_gst_port_t *ports[2]; + mc_bitstream_t bits; mc_aqueue_t *available_queue; GQueue *output_queue; void *codec_info; + unsigned char codec_data[100]; + int codec_data_size; void* user_cb[_MEDIACODEC_EVENT_TYPE_NUM]; void* user_data[_MEDIACODEC_EVENT_TYPE_NUM]; }; -struct _mc_gst_buffer_t +struct _GstMCBuffer { - GstBuffer buffer; + GstBuffer *buffer; + int buf_size; mc_gst_core_t* core; media_packet_h pkt; + bool has_imgb; }; enum { fill_inbuf, fill_outbuf, create_caps }; -int __mc_fill_input_buffer(mc_gst_core_t *core, mc_gst_buffer_t *buff); -int __mc_fill_output_buffer(mc_gst_core_t *core, GstBuffer *buff, media_packet_h *out_pkt); -int __mc_create_caps(mc_gst_core_t *core, GstCaps **caps); - -int __mc_fill_inbuf_with_bo(mc_gst_core_t *core, mc_gst_buffer_t *buff); -int __mc_fill_inbuf_with_packet(mc_gst_core_t *core, mc_gst_buffer_t *buff); - -int __mc_fill_outbuf_with_bo(mc_gst_core_t *core, GstBuffer *buff, media_packet_h *out_pkt); -int __mc_fill_outbuf_with_packet(mc_gst_core_t *core, GstBuffer *buff, media_packet_h *out_pkt); - -int __mc_venc_caps(mc_gst_core_t *core, GstCaps **caps); -int __mc_vdec_caps(mc_gst_core_t *core, GstCaps **caps); -int __mc_aenc_caps(mc_gst_core_t *core, GstCaps **caps); -int __mc_adec_caps(mc_gst_core_t *core, GstCaps **caps); -int __mc_mp3dec_caps(mc_gst_core_t *core, GstCaps **caps); -int __mc_h263enc_caps(mc_gst_core_t *core, GstCaps **caps); - +//int __mc_link_elements(mc_gst_core_t *core); +int __mc_fill_input_buffer(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer *buff); +int __mc_fill_output_buffer(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt); +int __mc_create_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); + +//int __mc_venc_link(mc_gst_core_t *core); +//int __mc_general_link(mc_gst_core_t *core); + +int __mc_fill_inbuf_with_mm_video_buffer(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer *buff); +int __mc_fill_inbuf_with_packet(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer *buff); +int __mc_fill_inbuf_with_venc_packet(mc_gst_core_t *core, media_packet_h pkt, GstMCBuffer *mc_buffer); + +int __mc_fill_packet_with_outbuf(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt); +int __mc_fill_venc_packet_with_outbuf(mc_gst_core_t *core, void *data, int size, 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); +int __mc_fill_vdec_packet_with_outbuf(mc_gst_core_t *core, void *data, int size, media_packet_h *pkt); + +int __mc_vdec_h264_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_venc_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_vdec_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_vdec_h263_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_vdec_mpeg4_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_h264dec_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_sprddec_mpeg4_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_sprddec_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_sprdenc_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_sprdenc_mpeg4_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_aenc_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_aac_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_aenc_aac_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_aacv12_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_mp3_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_amrnb_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_amrwb_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_aenc_amrnb_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_vorbis_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_flac_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +int __mc_adec_wma_caps(mc_gst_core_t *core, GstCaps **caps, GstMCBuffer* buff, bool codec_config); +bool _mc_is_voss (unsigned char *p, int size, int *codec_size); +bool _mc_is_ivop (unsigned char *p, int size, int pos); +bool _mc_is_vop (unsigned char *p, int size, int pos); + + +void _mc_create_codec_map_from_ini(mc_handle_t *mc_handle, mc_codec_spec_t *spec_emul); +void _mc_create_decoder_map_from_ini(mc_handle_t *mc_handle); +void _mc_create_encoder_map_from_ini(mc_handle_t *mc_handle); mc_gst_core_t *mc_gst_core_new(); void mc_gst_core_free(mc_gst_core_t *core); @@ -203,6 +220,8 @@ mc_ret_e mc_gst_unprepare(mc_handle_t *mc_handle); mc_ret_e mc_gst_process_input(mc_handle_t *mc_handle, media_packet_h inbuf, uint64_t timeOutUs); mc_ret_e mc_gst_get_output(mc_handle_t *mc_handle, media_packet_h *outbuf, uint64_t timeOutUs); +mc_ret_e mc_gst_flush_buffers(mc_handle_t *mc_handle); + #ifdef __cplusplus } #endif diff --git a/include/media_codec_private.h b/include/media_codec_private.h index 7bc76fc..c703087 100755 --- a/include/media_codec_private.h +++ b/include/media_codec_private.h @@ -47,6 +47,8 @@ extern "C" { #define MEDIACODEC_NULL_ARG_CHECK(arg) \ MEDIACODEC_CHECK_CONDITION(arg != NULL,MEDIACODEC_ERROR_INVALID_PARAMETER,"MEDIACODEC_ERROR_INVALID_PARAMETER") +#define MEDIACODEC_SUPPORT_CHECK(arg) \ + MEDIACODEC_CHECK_CONDITION(arg != false, MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE, "MEDIACODEC_ERROR_NOT_SUPPORTED_ON_DEVICE") /** * @brief Enumeration of media codec state * @since_tizen 2.3 @@ -110,6 +112,10 @@ typedef struct _mediacodec_s { void* error_cb_userdata; mediacodec_eos_cb eos_cb; void* eos_cb_userdata; + mediacodec_buffer_status_cb buffer_status_cb; + void* buffer_status_cb_userdata; + mediacodec_supported_codec_cb supported_codec_cb; + void* supported_codec_cb_userdata; } mediacodec_s; diff --git a/include/media_codec_queue.h b/include/media_codec_queue.h index 428a53c..5242997 100755 --- a/include/media_codec_queue.h +++ b/include/media_codec_queue.h @@ -55,6 +55,8 @@ void mc_async_queue_enable (async_queue_t *async_queue); void mc_async_queue_flush(async_queue_t *async_queue); +gboolean mc_async_queue_is_empty(async_queue_t *async_queue); + #ifdef __cplusplus } #endif diff --git a/include/media_codec_spec_emul.h b/include/media_codec_spec_emul.h index 597d4b0..3ba2129 100755 --- a/include/media_codec_spec_emul.h +++ b/include/media_codec_spec_emul.h @@ -51,38 +51,6 @@ struct _mc_codec_map_t mc_codec_type_t type; }; -static const mc_codec_spec_t spec_emul[] = -{ - {MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, - {MEDIACODEC_H263, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, - {MEDIACODEC_AAC, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, - {MEDIACODEC_AAC, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, - {MEDIACODEC_MP3, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST} -}; - -static const mc_codec_map_t encoder_map[] = -{ -#ifdef ENABLE_FFMPEG_CODEC - {MEDIACODEC_H263, SOFTWARE, {"ffenc_h263", "video/x-raw-yuv", MEDIA_FORMAT_H263P }}, - {MEDIACODEC_AAC, SOFTWARE, {"ffenc_aac", "audio/x-raw-int", MEDIA_FORMAT_AAC}} -#else - {MEDIACODEC_H263, SOFTWARE, {"maru_h263enc", "video/x-raw-yuv", MEDIA_FORMAT_H263P}}, - {MEDIACODEC_AAC, SOFTWARE, {"maru_aacenc", "audio/x-raw-int", MEDIA_FORMAT_AAC}} -#endif -}; - -static const mc_codec_map_t decoder_map[] = -{ -#ifdef ENABLE_FFMPEG_CODEC - {MEDIACODEC_H264, SOFTWARE, {"ffdec_h264", "video/x-h264", MEDIA_FORMAT_I420}}, - {MEDIACODEC_AAC, SOFTWARE, {"ffdec_aac", "audio/mpeg", MEDIA_FORMAT_PCM}}, - {MEDIACODEC_MP3, SOFTWARE, {"ffdec_mp3", "audio/mpeg", MEDIA_FORMAT_PCM}} -#else - {MEDIACODEC_H264, SOFTWARE, {"maru_h264dec", "video/x-h264", MEDIA_FORMAT_I420}}, - {MEDIACODEC_AAC, SOFTWARE, {"maru_aacdec", "audio/mpeg", MEDIA_FORMAT_PCM}}, - {MEDIACODEC_MP3, SOFTWARE, {"maru_mp3dec", "audio/mpeg", MEDIA_FORMAT_PCM}} -#endif -}; #ifdef __cplusplus } diff --git a/include/media_codec_util.h b/include/media_codec_util.h index 5acf139..2142b1d 100755 --- a/include/media_codec_util.h +++ b/include/media_codec_util.h @@ -27,15 +27,6 @@ extern "C" { #endif -#if 1 -#define MEDIACODEC_FENTER(); LOGI("%s Enter",__FUNCTION__); -#define MEDIACODEC_FLEAVE(); LOGI("%s Exit",__FUNCTION__); -#else -#define MEDIACODEC_FENTER(); LOGD("%s Enter",__FUNCTION__); -#define MEDIACODEC_FLEAVE(); LOGD("%s Exit",__FUNCTION__); -#endif - - typedef enum { CODEC_RET_SUCCESS = 0, @@ -67,6 +58,7 @@ mc_sem_t *mc_sem_new(); void mc_sem_free(mc_sem_t *sem); void mc_sem_down(mc_sem_t *sem); void mc_sem_up(mc_sem_t *sem); + void mc_hex_dump(char *desc, void *addr, int len); #define MC_FREEIF(x) \ @@ -74,9 +66,6 @@ if ( x ) \ g_free( x ); \ x = NULL; - - - #ifdef __cplusplus } #endif diff --git a/packaging/capi-media-codec.spec b/packaging/capi-media-codec.spec index d6c1027..542839d 100755 --- a/packaging/capi-media-codec.spec +++ b/packaging/capi-media-codec.spec @@ -1,6 +1,6 @@ Name: capi-media-codec Summary: A Media Codec library in Tizen Native API -Version: 0.1.2 +Version: 0.4.2 Release: 0 Group: Multimedia/API License: Apache-2.0 @@ -13,11 +13,16 @@ BuildRequires: pkgconfig(capi-base-common) BuildRequires: pkgconfig(appcore-efl) BuildRequires: pkgconfig(capi-media-tool) BuildRequires: pkgconfig(libtbm) -BuildRequires: pkgconfig(gstreamer-0.10) -BuildRequires: pkgconfig(gstreamer-plugins-base-0.10) -BuildRequires: pkgconfig(gstreamer-app-0.10) -BuildRequires: pkgconfig(libdri2) - +BuildRequires: pkgconfig(gstreamer-1.0) +BuildRequires: pkgconfig(gstreamer-plugins-base-1.0) +BuildRequires: pkgconfig(gstreamer-app-1.0) +BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(iniparser) +%if "%{tizen_target_name}" == "Z130H" || "%{?tizen_target_name}" == "Z300H" +#!BuildIgnore: kernel-headers +BuildConflicts: linux-glibc-devel +BuildRequires: kernel-headers-tizen-dev +%endif Requires(post): /sbin/ldconfig Requires(post): libprivilege-control Requires(postun): /sbin/ldconfig @@ -27,7 +32,7 @@ Requires(postun): /sbin/ldconfig %package devel Summary: A Media Player library in Tizen Native API (Development) -Group: Multimedia/API +Group: TO_BE/FILLED_IN Requires: %{name} = %{version}-%{release} %description devel @@ -37,6 +42,9 @@ Requires: %{name} = %{version}-%{release} %build +%if "%{tizen_target_name}" == "Z130H" || "%{?tizen_target_name}" == "Z300H" +export CFLAGS="$CFLAGS -DTIZEN_PROFILE_LITE" +%endif %if 0%{?sec_build_binary_debug_enable} export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE" export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE" @@ -56,8 +64,9 @@ make %{?jobs:-j%jobs} rm -rf %{buildroot} mkdir -p %{buildroot}/usr/share/license mkdir -p %{buildroot}/usr/bin -cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name} cp test/media_codec_test %{buildroot}/usr/bin +cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name} + %make_install %post 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); } - diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7b7990e..e9400f4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,4 +20,3 @@ FOREACH(src ${sources}) ADD_EXECUTABLE(${src_name} ${src}) TARGET_LINK_LIBRARIES(${src_name} capi-media-codec ${${fw_test}_LDFLAGS}) ENDFOREACH() - diff --git a/test/media_codec_test.c b/test/media_codec_test.c index e0a0690..b390c8e 100755 --- a/test/media_codec_test.c +++ b/test/media_codec_test.c @@ -46,6 +46,19 @@ #define DEFAULT_SAMPLEBYTE 1024 #define ADTS_HEADER_SIZE 7 +/* + * 0 (disable) : used in (*.aac_lc, adts) + * 1 (enable) : used in (*.m4a, mp4), Need "codec_data" + * TODO : AAC_CODECDATA_SIZE is temporal size (16 byte) for codec_data + * TODO : WMA_CODECDATA_SIZE is temporal size (64 byte) for codec_data + */ +#if 1 + #define AAC_CODECDATA_SIZE 16 + #define WMA_CODECDATA_SIZE 64 /*MAX sizeof(WMAUDIO3WAVEFORMAT)*/ + #define VORBIS_CODECDATA_SIZE 4096 + #define FLAC_CODECDATA_SIZE 4096 /* MAX sizeof(2^24) */ +#endif + #define DUMP_OUTBUF 1 #define MAX_INPUT_BUF_NUM 20 #define USE_INPUT_QUEUE 1 @@ -80,17 +93,18 @@ int g_menu_state = CURRENT_STATUS_MAINMENU; int g_handle_num = 1; static mediacodec_h g_media_codec[MAX_HANDLE] = {0}; char g_uri[MAX_STRING_LEN]; +int g_len,bMultipleFiles; FILE *fp_src = NULL; media_format_h input_fmt = NULL; #if USE_INPUT_QUEUE -media_packet_h *input_buf = NULL; +//media_packet_h *input_buf = NULL; +media_packet_h input_buf[MAX_INPUT_BUF_NUM]; #else media_packet_h in_buf = NULL; #endif media_packet_h output_buf = NULL; -async_queue_t *input_avaliable = NULL; - -//static GThread *thread; +//async_queue_t *input_avaliable = NULL; +GQueue input_available; uint64_t pts = 0; @@ -106,6 +120,11 @@ static int bitrate = DEFAULT_BITRATE; static int samplebyte = DEFAULT_SAMPLEBYTE; unsigned char buf_adts[ADTS_HEADER_SIZE]; +unsigned char sps[100]; +unsigned char pps[100]; +unsigned char tmp_buf[1000000]; +static int sps_len, pps_len; + media_format_mimetype_e mimetype; int use_video = 0; @@ -113,6 +132,7 @@ int use_encoder = 0; int frame_count = 0; #if DUMP_OUTBUF +int g_OutFileCtr; FILE *fp_out = NULL; #endif //static gpointer _feed_pa(gpointer data); @@ -146,16 +166,19 @@ unsigned int bytestream2nalunit(FILE *fd, unsigned char* nal) int read_size = 1; unsigned char buffer[1000000]; unsigned char val, zero_count, i; + int nal_unit_type; + int init; zero_count = 0; if (feof(fd)) - return 0; + return -1; result = fread(buffer, 1, read_size, fd); if(result != read_size) { - exit(1); + //exit(1); + return -1; } val = buffer[0]; while (!val) @@ -178,6 +201,7 @@ unsigned int bytestream2nalunit(FILE *fd, unsigned char* nal) nal[nal_length++] = 0; nal[nal_length++] = 1; zero_count = 0; + init = 1; while(1) { if (feof(fd)) @@ -190,6 +214,10 @@ unsigned int bytestream2nalunit(FILE *fd, unsigned char* nal) } val = buffer[0]; + if(init) { + nal_unit_type = val & 0xf; + init = 0; + } if (!val) { zero_count++; @@ -214,6 +242,27 @@ unsigned int bytestream2nalunit(FILE *fd, unsigned char* nal) fseek(fd, -(zero_count + 1), SEEK_CUR); + if (nal_unit_type == 0x7) + { + sps_len = nal_length; + memcpy(sps, nal, nal_length); + return 0; + } + else if (nal_unit_type == 0x8) + { + pps_len = nal_length; + memcpy(pps, nal, nal_length); + return 0; + } + else if (nal_unit_type == 0x5) + { + memcpy(tmp_buf, nal, nal_length); + memcpy(nal, sps, sps_len); + memcpy(nal + sps_len, pps, pps_len); + memcpy(nal + sps_len + pps_len, tmp_buf, nal_length); + nal_length += sps_len + pps_len; + } + return nal_length; } @@ -231,7 +280,8 @@ unsigned int bytestream2yuv420(FILE *fd, unsigned char* yuv) result = fread(buffer, 1,read_size, fd); if(result != read_size) { - exit(1); + //exit(1); + return -1; } memcpy(yuv, buffer, width*height*3/2); @@ -239,6 +289,121 @@ unsigned int bytestream2yuv420(FILE *fd, unsigned char* yuv) return width*height*3/2; } +int bytestream2h263unit(FILE *fd, unsigned char* p) +{ + int len = 0; + size_t result; + int read_size = 1, state = 1, bStart = 0; + unsigned char val; + + if (feof(fd)) + return -1; + + while(1) + { + if(fread(&val, 1, read_size, fd) != read_size) + return -1; + p[len] = val; + len += read_size; + + switch(state) + { + case 1: + if(val==0x00) + state++; + break; + case 2: + if(val==0x00) + state++; + else + state = 1; + break; + case 3: + state = 1; + if((val&0xFC)==0x80) + { + if(bStart) + { + // Got next PSC + fseek(fd, -3, SEEK_CUR); + return len - 3; + } + else + { + bStart = 1; + // Flush header + len = 3; + p[0] = p[1] = 0; + p[2] = 0x80; + } + } + break; + } + } +} + +int bytestream2mpeg4unit(FILE *fd, unsigned char* p,int* is_voss) +{ + int len = 0; + size_t result; + int read_size = 1, state = 1, bType=0; + unsigned char val; + + if (feof(fd)) + return -1; + + while(1) + { + if(fread(&val, 1, read_size, fd) != read_size) + return -1; + p[len] = val; + len += read_size; + + switch(state) + { + case 1: + if(val==0x00) + state++; + break; + case 2: + if(val==0x00) + state++; + else + state = 1; + break; + case 3: + if(val==0x01) + state++; + else + state = 1; + break; + case 4: + state = 1; + if(val==0xB0 || val==0xB6) + { + if(bType == 0xB6) + { + // Got next VOSS/IVOP + fseek(fd, -4, SEEK_CUR); + return len - 4; + } + if(!bType) + { + // Flush header + len = 4; + p[0] = p[1] = 0x00; + p[2] = 0x01; + p[3] = val; + if(is_voss && val==0xB0) + *is_voss = 1; + } + bType = val; + } + break; + } + } +} + /** * Extract Input data for MP3 decoder @@ -274,6 +439,12 @@ unsigned int extract_input_mp3dec(FILE *fd, unsigned char* mp3data) guint padding, bitrate, lsf, layer, mpg25; guint hdr_bitrate, sf; + /* + * It is not support skip logicif ID3 Tag and Xing Header. + * So It MUST start as mp3 valid frame sequence. + * Testsuit that are not guaranteed to be available on functionality of all General DEMUXER/PARSER. + */ + if (feof(fd)) return 0; @@ -372,35 +543,525 @@ unsigned int extract_input_mp3dec(FILE *fd, unsigned char* mp3data) /** * Extract Input data for AAC decoder * (case of (LC profile) ADTS format) + * codec_data : Don't need **/ unsigned int extract_input_aacdec(FILE *fd, unsigned char* aacdata) { int readsize; size_t result; + unsigned int header_size = ADTS_HEADER_SIZE; + unsigned char buffer[1000000]; + + if (feof(fd)) + return 0; + + result = fread(buffer, 1, header_size, fd); //adts header + if(result != header_size) + { + return -1; + } + + if ((buffer != NULL) && (buffer[0] == 0xff) && ((buffer[1] & 0xf6) == 0xf0)) { + readsize = ((buffer[3] & 0x03) << 11) | (buffer[4] << 3) | ((buffer[5] & 0xe0) >> 5); + result = fread(buffer + header_size, 1,(readsize - header_size), fd); + memcpy(aacdata, buffer, readsize); + } else { + readsize = 0; + g_print("[FAIL] Not found aac frame sync.....\n"); + } + + return readsize; +} + +/** + * Extract Input data for AAC decoder + * (case of (AAC+/EAAC+ profile) RAW format) + * codec_data : Need + * profile : AAC_LC(2) AAC_HE(5), AAC_HE_PS (29) + **/ +unsigned int extract_input_aacdec_m4a_test(FILE *fd, unsigned char* aacdata) +{ + int readsize = 0; + size_t result; + unsigned int header_size = ADTS_HEADER_SIZE; unsigned char buffer[1000000]; + unsigned char codecdata[AAC_CODECDATA_SIZE] = {0,}; + + /* + * It is not support full parsing MP4 container box. + * So It MUST start as RAW valid frame sequence. + * Testsuit that are not guaranteed to be available on functionality of all General DEMUXER/PARSER. + */ if (feof(fd)) return 0; - result = fread(buffer, 1, 6, fd); //adts header - if(result != 6) + if (frame_count == 0) + { + /* + * CAUTION : Codec data is needed only once in first time + * Codec data is made(or extracted) by MP4 demuxer in 'esds' box. + * So I use this data (byte) as hard coding for temporary our testing. + */ +#if 1 + /* + * The codec_data data is according to AudioSpecificConfig, + * ISO/IEC 14496-3, 1.6.2.1 + * + * below example is test for using "test.aac" or "TestSample-AAC-LC.m4a" + * case : M4A - LC profile + * codec_data=(buffer)119056e5000000000000000000000000 + * savs aac decoder get codec_data. size: 16 (Tag size : 5 byte) + * - codec data: profile : 2 + * - codec data: samplrate: 48000 + * - codec data: channels : 2 + */ + /* 2 bytes are mandatory */ + codecdata[0] = 0x11; //ex) (5bit) 2 (LC) / (4bit) 3 (48khz) + codecdata[1] = 0x90; //ex) (4bit) 2 (2ch) + /* othter bytes are (optional) epconfig information */ + codecdata[2] = 0x56; + codecdata[3] = 0xE5; + codecdata[4] = 0x00; +#else + /* + * below example is test for using "TestSample-EAAC+.m4a" + * + * case : M4A - HE-AAC v1 and v2 profile + * codec_data=(buffer)138856e5a54880000000000000000000 + * savs aac decoder get codec_data. size: 16 (Tag size : 7 byte) + * - codec data: profile : 2 + * - codec data: samplrate: 22050 + * - codec data: channels : 1 + */ + /* 2 bytes are mandatory */ + codecdata[0] = 0x13; //ex) (5bit) 2 (LC) / (4bit) 9 (22khz) + codecdata[1] = 0x88; //ex) (4bit) 1 (1ch) + /* othter bytes are (optional) epconfig information */ + codecdata[2] = 0x56; + codecdata[3] = 0xE5; + codecdata[4] = 0xA5; + codecdata[5] = 0x48; + codecdata[6] = 0x80; +#endif + + memcpy(aacdata, codecdata, AAC_CODECDATA_SIZE); + + result = fread(buffer, 1, header_size, fd); //adts header + if(result != header_size) + { + return -1; + } + + if ((buffer != NULL) && (buffer[0] == 0xff) && ((buffer[1] & 0xf6) == 0xf0)) { + readsize = ((buffer[3] & 0x03) << 11) | (buffer[4] << 3) | ((buffer[5] & 0xe0) >> 5); + readsize = readsize -header_size; + result = fread(buffer, 1, readsize, fd); //Make only RAW data, so exclude header 7 bytes + memcpy(aacdata+AAC_CODECDATA_SIZE, buffer, readsize); + } + + g_print( "[example] Insert 'codec_data' in 1st frame buffer size (%d)\n", readsize+AAC_CODECDATA_SIZE); + return (readsize + AAC_CODECDATA_SIZE); //return combination of (codec_data + raw_data) + } + + result = fread(buffer, 1, header_size, fd); //adts header + if(result != header_size) { exit(1); } if ((buffer != NULL) && (buffer[0] == 0xff) && ((buffer[1] & 0xf6) == 0xf0)) { readsize = ((buffer[3] & 0x03) << 11) | (buffer[4] << 3) | ((buffer[5] & 0xe0) >> 5); - result = fread(buffer+6, 1,(readsize - 6), fd); - memcpy(aacdata, buffer,readsize); + readsize = readsize -header_size; + result = fread(buffer, 1, readsize, fd); //Make only RAW data, so exclude header 7 bytes + memcpy(aacdata, buffer, readsize); } else { readsize = 0; g_print("[FAIL] Not found aac frame sync.....\n"); } + return readsize; //return only raw_data +} + +/** + * Extract Input data for AMR-NB/WB decoder + * - AMR-NB : mime type ("audio/AMR") / 8Khz / 1 ch / 16 bits + * - AMR-WB : mime type ("audio/AMR-WB") / 16Khz / 1 ch / 16 bits + **/ +static const char AMR_header [] = "#!AMR\n"; +static const char AMRWB_header [] = "#!AMR-WB\n"; +#define AMR_NB_MIME_HDR_SIZE 6 +#define AMR_WB_MIME_HDR_SIZE 9 +static const int block_size_nb[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 }; +static const int block_size_wb[16] = { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, -1, -1, -1, -1, 0, 0 }; +int *blocksize_tbl; + +unsigned int extract_input_amrdec(FILE *fd, unsigned char* amrdata) +{ + int readsize = 0; + size_t result; + unsigned int mime_size = AMR_NB_MIME_HDR_SIZE; + unsigned char buffer[1000000]; + unsigned int fsize, mode; + + if (feof(fd)) + return 0; + + if (frame_count == 0) + { + /* Check if the given data contains an AMR mime header. */ + result = fread(buffer, 1, mime_size, fd); //amr-nb header + if(result != mime_size) + return -1; + + if ( !memcmp (buffer, AMR_header, AMR_NB_MIME_HDR_SIZE)) + { + blocksize_tbl = (int *)block_size_nb; + g_print("[----AMR-NB mime header detected----]\n"); + } + else + { + result = fread(buffer + mime_size, 1, 3, fd); //need more (3) bytes for checking amr-wb mime header + if (!memcmp (buffer, AMRWB_header, AMR_WB_MIME_HDR_SIZE)) + { + mime_size = AMR_WB_MIME_HDR_SIZE; + blocksize_tbl = (int *)block_size_wb; + g_print("[----AMR-WB mime header detected----]\n"); + } + else + { + g_print("[ERROR] AMR-NB/WB don't detected..\n"); + return 0; + } + } + } + + result = fread(buffer, 1, 1, fd); /* mode byte check */ + if(result != 1) + return -1; + if ((buffer[0] & 0x83) == 0) + { + mode = (buffer[0] >> 3) & 0x0F; /* Yep. Retrieve the frame size */ + fsize = blocksize_tbl[mode]; + + result = fread(buffer+1, 1, fsize, fd); /* +1 for the previous mode byte */ + if(result != fsize) + return -1; + memcpy(amrdata, buffer, fsize); + readsize = fsize + 1; + } else { + readsize = 0; + g_print("[FAIL] Not found amr frame sync.....\n"); + } + return readsize; } /** + * Extract Input data for WMA decoder + * codec_data : Need + * format : WMAV1, WMAV2, WMAPRO, WMALSL + **/ + #if 1 +unsigned int extract_input_wmadec_test(FILE *fd, unsigned char* wmadata) +{ + int readsize = 0; + size_t result = 0; + unsigned char buffer[1000000]; + unsigned char codecdata[WMA_CODECDATA_SIZE] = {0,}; + + /* + * It is not support full parsing ASF container. + * So It MUST start as each Payload sequence. + * Testsuit that are not guaranteed to be available on functionality of all General DEMUXER/PARSER. + */ + if (feof(fd)) + return 0; + + if (frame_count == 0) + { + /* FIXME : temp test ONLY using case of 'test_t1.wma' that Generates a file for testing purposes + * This file is consist of + * - Only ES : each payload data (total = (16EA * 1024) bytes) + * Stream Format is (Codec_data(64 bytes) + ES) + ES + ES + ES .. + */ + codecdata[0] = 0x00; + codecdata[1] = 0x00; + codecdata[2] = 0x00; + codecdata[3] = 0x00; + codecdata[4] = 0x01; + codecdata[5] = 0x00; + codecdata[6] = 0x00; + codecdata[7] = 0x00; + codecdata[8] = 0x00; + codecdata[9] = 0x00; + + memcpy(wmadata, codecdata, WMA_CODECDATA_SIZE); + + readsize = 1024; /* payload size */ + result = fread(buffer, 1, readsize, fd); + if(result != readsize) + return -1; + memcpy(wmadata+WMA_CODECDATA_SIZE, buffer, readsize); + + g_print( "[Info] Insert 'stream header (%d)' and 1st readsize (%d) in 1st frame buffer size (%d)\n", + WMA_CODECDATA_SIZE, readsize, readsize+WMA_CODECDATA_SIZE); + return ( WMA_CODECDATA_SIZE + readsize); //return combination of (codec_data + raw_data) + + } + + readsize = 1024; /* payload size */ + result = fread(buffer, 1, readsize, fd); + if(result != readsize) + return -1; + memcpy(wmadata, buffer, readsize); + + return readsize; //return only raw_data +} +#else +unsigned int extract_input_wmadec_test_1(FILE *fd, unsigned char* wmadata) +{ + int readsize = 0; + size_t result = 0; + unsigned char buffer[1000000]; + unsigned char codecdata[WMA_CODECDATA_SIZE] = {0,}; + + if (feof(fd)) + return 0; + + if (frame_count == 0) + { + /* FIXME : temp test ONLY using case of 'test_t1_2.wma' + * This file is consist of + * - Codec_data : 'Stream Type Specific(28 bytes)' in Stream Properties Object(ObjectID : B7DC0791-A9B7-11CF-8EE6-00C00C205365) + * -> 18 bytes (Stream Type Specific data) + 10 bytes (Extra data) + * -> 18 bytes is used for Caps + * -> 10 bytes is used for real codec_data + * - ES : each payload data (total = (16EA * 1024) bytes) + * + * Stream Format is (Codec_data(28 bytes) + ES) + ES + ES + ES .. + */ + readsize = 28; /* Stream Type Specific size */ + result = fread(codecdata, 1, readsize, fd); + memcpy(wmadata, codecdata, WMA_CODECDATA_SIZE); + + readsize = 1024; /* 1st payload size */ + result = fread(buffer, 1, readsize, fd); + if(result != readsize) + exit(1); + memcpy(wmadata+WMA_CODECDATA_SIZE, buffer, readsize); + + g_print( "[example] Insert 'codec_data' in 1st frame buffer size (%d)\n", readsize+WMA_CODECDATA_SIZE); + return ( WMA_CODECDATA_SIZE + readsize); //return combination of (codec_data + raw_data) + + } + + readsize = 1024; /* payload size */ + result = fread(buffer, 1, readsize, fd); + memcpy(wmadata, buffer, readsize); + + return readsize; //return only raw_data +} +#endif + +/** + * Extract Input data for VORBIS decoder + * codec_data : Need as stream header pattern + * format : audio/x-vorbis + **/ +static const int Key0_t1_segment_size_tbl[12] = { 1, 1, 1, 47, 45, 99, 73, 74, 91,146, 1 }; /* Only Used for key0_t1.ogg */ +static const int Key0_t2_segment_size_tbl[15] = {30, 45, 3776, 1, 1, 1, 47, 45, 99, 73, 74, 91,146, 1 }; /* Only Used for key0_t1.ogg */ +int *psize_tbl; +unsigned int extract_input_vorbisdec_test(FILE *fd, unsigned char* vorbisdata) +{ + int readsize = 0; + size_t result = 0; + unsigned char buffer[1000000]; + unsigned char codecdata[VORBIS_CODECDATA_SIZE] = {0,}; + + /* + * It is not support full parsing OGG container. + * So It MUST start as each Segment sequence. + * Testsuit that are not guaranteed to be available on functionality of all General DEMUXER/PARSER. + */ + if (feof(fd)) { + g_print("%s - [WARN][EOF] at frame_count (%4d)\n",__func__, frame_count); + return 0; + } + + if (frame_count == 0) + { + /* FIXME : temp test ONLY using case of 'key0_t1.ogg' that Generates a file for testing purposes + * This file is consist of + * - Codec_data : 'vorbis header(3851 bytes)' in evey packet starts with a packet type byte(0x01, 0x03,0x05) and the 6 byte indentification string "vorbis" + * -> 30 bytes is used for Identifcation Header + * -> 45 bytes is used for Comment Header + * -> 3776 bytes is used for Setup Header + * - Only ES : each Segment data (total = 579 bytes for 10 frames) + * Stream Format is (Codec_data(4096 bytes) + ES) + ES + ES + ES .. + */ + + readsize = 3851; /* stream header size */ + result = fread(codecdata, sizeof(char), readsize, fd); + if(result != readsize) { + g_print("%s - [ERROR] fread fail : readsize (%4d) at frame_count (%4d) \n",__func__, readsize, frame_count); + return -1; + } + memcpy(vorbisdata, codecdata, VORBIS_CODECDATA_SIZE); + +#if 0 + psize_tbl = (int *)Key0_t1_segment_size_tbl; +#else + fseek(fd, 0, SEEK_SET); + psize_tbl = (int *)Key0_t2_segment_size_tbl; +#endif + + readsize = psize_tbl[frame_count]; /* 1st segment size */ + result = fread(buffer, 1, readsize, fd); + if(result != readsize) { + g_print("%s - [ERROR] fread fail : readsize (%4d) at frame_count (%4d) \n",__func__, readsize, frame_count); + return -1; + } + memcpy(vorbisdata+VORBIS_CODECDATA_SIZE, buffer, readsize); + + g_print( "[Info] Insert 'stream header (%d)' and 1st readsize (%d) in 1st frame buffer size (%d)\n", + VORBIS_CODECDATA_SIZE, readsize, readsize+VORBIS_CODECDATA_SIZE); + return (VORBIS_CODECDATA_SIZE + readsize); //return combination of (codec_data + raw_data) + + } + + readsize = psize_tbl[frame_count]; /* next segment size */ + result = fread(buffer, 1, readsize, fd); + if(result != readsize) { + g_print("%s - [ERROR] fread fail : readsize (%4d) at frame_count (%4d) \n",__func__, readsize, frame_count); + return -1; + } + memcpy(vorbisdata, buffer, readsize); + + return readsize; //return only raw_data +} + +/** + * Extract Input data for FLAC decoder + * codec_data : Need as stream header pattern + * format : audio/x-flac + **/ +static const int key0_segment_size_tbl[3+3] = { 4, 38, 44, 1940, 774 }; /* Only Used for key0.flac */ +static const int test_segment_size_tbl[3+11] = { 4, 38, 151, 6314, 5769, 6294, 5780, 6597, 9718, 8691, 8180, 7443, 7953, }; /* Only Used for test.flac */ +int *flac_psize_tbl; +unsigned int extract_input_flacdec_test(FILE *fd, unsigned char* flacdata) +{ + int readsize = 0; + size_t result = 0; + unsigned char buffer[1000000]; + unsigned char codecdata[FLAC_CODECDATA_SIZE] = {0,}; + int codecdata_size = 0; + guint readsize1 = 0; + guint readsize2 = 0; + + /* + * It is not support full parsing FLAC container. + * So It MUST start as each valid flac stream sequence. + * Testsuit that are not guaranteed to be available on functionality of all General FLAC PARSER. + */ + if (feof(fd)) { + g_print("%s - [WARN][EOF] at frame_count (%4d)\n",__func__, frame_count); + return 0; + } + + if (frame_count == 0) + { + /* FIXME : temp test ONLY using case of 'key0.flac' that original file for testing purposes + * This file is consist of + * - Stream: METADATA_BLOCK (INFO + COMMRNT) + FRAME (two frame (1940 + 774) bytes) + * Stream Format is (Codec_data(51 bytes) + ES) + ES.. + */ + + /* Pre-append : add marker is madatory */ + codecdata[0] = 0x7f; + codecdata[1] = 0x46; /* F */ + codecdata[2] = 0x4c; /* L*/ + codecdata[3] = 0x41; /* A */ + codecdata[4] = 0x43; /* C */ + codecdata[5] = 0x01; /* mapping version major */ + codecdata[6] = 0x00; /* mapping version minor */ + codecdata[7] = 0x00; + codecdata[8] = 0x02; + + codecdata_size = 9; + memcpy(flacdata, codecdata, codecdata_size); + + /* case1 : using fixed method of codec data size */ + /* For 1st stream header */ + readsize1 = 42; /* 'fLaC' + STREAMINFO (38) */ + result = fread(codecdata + codecdata_size, 1, readsize1, fd); + if(result != readsize1) { + g_print("%s - [ERROR] fread fail : readsize1 (%4d) at frame_count (%4d) \n",__func__, readsize1, frame_count); + return -1; + } + + /* For check valid marker */ + if ((codecdata[9] == 0x66) && (codecdata[10] == 0x4c) && (codecdata[11] == 0x61) && (codecdata[12] == 0x43)) + { + codecdata_size += readsize1; + } else { + g_print ("[ERROR] invalid maker\n"); + return 0; + } + + /* For 2nd stream header */ + readsize2 = 4; + result = fread(codecdata + codecdata_size, 1, readsize2, fd); + if(result != readsize2) { + g_print("%s - [ERROR] fread fail : readsize (%4d) at frame_count (%4d) \n",__func__, readsize2, frame_count); + return -1; + } + if ((codecdata[51] & 0x7f) == 4) + { + codecdata_size += readsize2; + /* For size of 2nd stream header */ + readsize2 = ((codecdata[52] << 16) | (codecdata[53] << 8) | (codecdata[54])); + result = fread(codecdata + codecdata_size, 1, readsize2, fd); + codecdata_size += readsize2; + if(result != readsize2) { + g_print("%s - [ERROR] fread fail : readsize (%4d) at frame_count (%4d) \n",__func__, readsize2, frame_count); + return -1; + } + memcpy(flacdata, codecdata, FLAC_CODECDATA_SIZE); + } else { + g_print ("[ERROR] invalid type(4) of vorbis comment \n"); + return 0; + } + + /* codec plugins don't used streamheader, So It want to fead direct file sequence */ + fseek(fd, 0, SEEK_SET); + flac_psize_tbl = (int *)key0_segment_size_tbl; + + readsize = flac_psize_tbl[frame_count]; /* 1st segment size */ + result = fread(buffer, 1, readsize, fd); + if(result != readsize) { + g_print("%s - [ERROR] fread fail : readsize (%4d) at frame_count (%4d) \n",__func__, readsize, frame_count); + return -1; + } + memcpy(flacdata + FLAC_CODECDATA_SIZE, buffer, readsize); + + g_print( "[Info] Insert 'stream header (%d)' and 1st readsize (%d) in 1st frame buffer size (%d)\n", + FLAC_CODECDATA_SIZE, readsize, readsize+FLAC_CODECDATA_SIZE); + return ( FLAC_CODECDATA_SIZE + readsize); //return combination of (codec_data + raw_data) + } + + readsize = flac_psize_tbl[frame_count]; /* next segment size */ + result = fread(buffer, 1, readsize, fd); + if(result != readsize) { + g_print("%s - [ERROR] fread fail : readsize (%4d) at frame_count (%4d) \n",__func__, readsize, frame_count); + return -1; + } + memcpy(flacdata, buffer, readsize); + + return readsize; //return only raw_data +} + +/** * Extract Input data for AAC encoder **/ unsigned int extract_input_aacenc(FILE *fd, unsigned char* rawdata) @@ -416,7 +1077,7 @@ unsigned int extract_input_aacenc(FILE *fd, unsigned char* rawdata) result = fread(buffer, 1, readsize, fd); if(result != readsize) { - exit(1); + return -1; } memcpy(rawdata, buffer,readsize); @@ -460,6 +1121,46 @@ void add_adts_header_for_aacenc(unsigned char *buffer, int packetLen) { buffer[6] = (char)0xFC; } + +/** + * Extract Input data for AMR-NB/WB encoder + * But, WB encoder is not support because we don't have WB decoder for reference. + **/ +#define AMRNB_PCM_INPUT_SIZE 320 +#define AMRWB_PCM_INPUT_SIZE 640 +#define AMRNB_ENC_TEST 1 /* 1: AMR-NB , 0: AMR-WB*/ +int write_amr_header = 1; /* write magic number for AMR Header at one time */ +unsigned int extract_input_amrenc(FILE *fd, unsigned char* rawdata, int is_amr_nb) +{ + int readsize; + size_t result; + unsigned char buffer[1000000]; + + if (feof(fd)) + return 0; + + if (is_amr_nb) + readsize = AMRNB_PCM_INPUT_SIZE; + else + readsize = AMRWB_PCM_INPUT_SIZE; + + result = fread(buffer, 1, readsize, fd); + if(result != readsize) + { + return -1; + } + + memcpy(rawdata, buffer,readsize); + + if (frame_count == 0) + { + g_print("amr encoder input size (%d) - NB(320) / WB(640)\n", readsize); + } + + return readsize; +} + + static void input_filepath(char *filename) { int len = strlen(filename); @@ -488,9 +1189,15 @@ static void input_filepath(char *filename) #if DUMP_OUTBUF fp_out = fopen("/opt/usr/media/codec_dump.out", "wb"); + g_OutFileCtr = 0; #endif strncpy (g_uri, filename, len); + g_len = len; + + bMultipleFiles = 0; + if(g_uri[g_len-1] == '/') + bMultipleFiles = 1; return; } @@ -501,14 +1208,15 @@ void _allocate_buf(void) int i = 0; // !!!! remove dependency on internal headers. - input_avaliable = mc_async_queue_new(); - input_buf = (media_packet_h *)malloc(sizeof(media_packet_h)*MAX_INPUT_BUF_NUM); + //input_avaliable = mc_async_queue_new(); + //input_buf = (media_packet_h *)malloc(sizeof(media_packet_h)*MAX_INPUT_BUF_NUM); for (i = 0; i < MAX_INPUT_BUF_NUM; i++) { media_packet_create_alloc(input_fmt, NULL, NULL, &input_buf[i]); g_print("input queue buf = %p\n", input_buf[i]); - mc_async_queue_push(input_avaliable, input_buf[i]); + //mc_async_queue_push(input_avaliable, input_buf[i]); + g_queue_push_tail(&input_available, input_buf[i]); } #else media_packet_create_alloc(input_fmt, NULL, NULL, &in_buf); @@ -523,8 +1231,7 @@ void _free_buf(void) { int i = 0; - if (input_avaliable) - mc_async_queue_free(input_avaliable); + //mc_async_queue_free(input_avaliable); if (input_buf) { @@ -537,9 +1244,10 @@ void _free_buf(void) } media_format_unref(input_fmt); input_fmt = NULL; - free(input_buf); - input_buf = NULL; + //free(input_buf); + //input_buf = NULL; } + g_queue_clear(&input_available); return; } #endif @@ -550,7 +1258,8 @@ static void _mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data) { #if USE_INPUT_QUEUE media_packet_unset_flags(pkt, MEDIA_PACKET_CODEC_CONFIG); - mc_async_queue_push(input_avaliable, pkt); + //mc_async_queue_push(input_avaliable, pkt); + g_queue_push_tail(&input_available, pkt); g_print("availablebuf = %p\n", pkt); #else g_print("Used input buffer = %p\n", pkt); @@ -574,6 +1283,13 @@ static void _mediacodec_eos_cb(void *user_data) g_print("event : eos\n"); } +static bool _mcdiacodec_supported_cb(mediacodec_codec_type_e type, void *user_data) +{ + if(type != -1) + g_printf("type : %x\n", type); + return true; +} + void _mediacodec_destroy(void) { int i = 0; @@ -604,7 +1320,7 @@ void _mediacodec_set_codec(int codecid, int flag) { int encoder = 0; g_print("_mediacodec_configure\n"); - g_print("codecid = %x, flag = %d\n", codecid, flag); + g_print("codecid = 0x%x, flag = %d\n", codecid, flag); if (g_media_codec[0] != NULL) { mediacodec_set_codec(g_media_codec[0], (mediacodec_codec_type_e)codecid, flag); @@ -614,15 +1330,19 @@ void _mediacodec_set_codec(int codecid, int flag) if (encoder) { //input_fmt->mimetype |= MEDIA_FORMAT_RAW; - //input_fmt->mimetype |= MEDIA_FORMAT_NV12; - mimetype |= MEDIA_FORMAT_RAW; mimetype |= MEDIA_FORMAT_NV12; + mimetype |= MEDIA_FORMAT_RAW; //mimetype |= MEDIA_FORMAT_I420; } else { //input_fmt->mimetype |= MEDIA_FORMAT_H264_SP; - mimetype |= MEDIA_FORMAT_H264_SP; + if(codecid == MEDIACODEC_MPEG4) + mimetype |= MEDIA_FORMAT_MPEG4_SP; + else if(codecid == MEDIACODEC_H263) + mimetype |= MEDIA_FORMAT_H263; + else + mimetype |= MEDIA_FORMAT_H264_SP; } mimetype |= MEDIA_FORMAT_VIDEO; } @@ -635,13 +1355,33 @@ void _mediacodec_set_codec(int codecid, int flag) } else { - if (codecid == MEDIACODEC_AAC) - mimetype |= MEDIA_FORMAT_AAC; /* MPEG-2 : (*.aac, adts) */ + if (codecid == MEDIACODEC_AAC) /* same as MEDIACODEC_AAC_LC */ + mimetype |= MEDIA_FORMAT_AAC; /* MPEG-2/4 : (*.aac, adts), need adts header */ + else if (codecid == MEDIACODEC_AAC_HE) + mimetype |= MEDIA_FORMAT_AAC_HE; /* MPEG-4 : (*.m4a, mp4) */ + else if (codecid == MEDIACODEC_AAC_HE_PS) + mimetype |= MEDIA_FORMAT_AAC_HE_PS; /* MPEG-4 : (*.m4a, mp4) */ else if (codecid == MEDIACODEC_MP3) mimetype |= MEDIA_FORMAT_MP3; + else if (codecid == MEDIACODEC_AMR_NB) + mimetype |= MEDIA_FORMAT_AMR_NB; + else if (codecid == MEDIACODEC_AMR_WB) + mimetype |= MEDIA_FORMAT_AMR_WB; + else if (codecid == MEDIACODEC_VORBIS) + mimetype |= MEDIA_FORMAT_VORBIS; + else if (codecid == MEDIACODEC_FLAC) + mimetype |= MEDIA_FORMAT_FLAC; + else if (codecid == MEDIACODEC_WMAV1) + mimetype |= MEDIA_FORMAT_WMAV1; + else if (codecid == MEDIACODEC_WMAV2) + mimetype |= MEDIA_FORMAT_WMAV2; + else if (codecid == MEDIACODEC_WMAPRO) + mimetype |= MEDIA_FORMAT_WMAPRO; + else if (codecid == MEDIACODEC_WMALSL) + mimetype |= MEDIA_FORMAT_WMALSL; } mimetype |= MEDIA_FORMAT_AUDIO; - g_print(" [audio test] mimetype (0x%x)\n", mimetype); + g_print("[audio test] mimetype (0x%x)\n", mimetype); } } else @@ -743,6 +1483,8 @@ void _mediacodec_prepare(void) mediacodec_set_output_buffer_available_cb(g_media_codec[i], _mediacodec_fill_buffer_cb, g_media_codec[i]); mediacodec_set_eos_cb(g_media_codec[i], _mediacodec_eos_cb, g_media_codec[i]); + mediacodec_foreach_supported_codec(g_media_codec[i], _mcdiacodec_supported_cb, g_media_codec[i]); + err = mediacodec_prepare(g_media_codec[i]); if (err != MEDIACODEC_ERROR_NONE) @@ -762,36 +1504,8 @@ void _mediacodec_prepare(void) return; } -/* -static gpointer -feed_thread(gpointer data) -{ - int i; - int err = 0; - - for (i=0; i < g_handle_num; i++) - { - if(g_media_codec[i] != NULL) - { - mediacodec_unset_input_buffer_used_cb(g_media_codec[i]); - mediacodec_unset_output_buffer_available_cb(g_media_codec[i]); - err = mediacodec_unprepare(g_media_codec[i]); - if (err != MEDIACODEC_ERROR_NONE) - { - g_print("mediacodec_unprepare failed error = %d \n", err); - } - } - else - { - g_print("mediacodec handle is not created\n"); - } - } - g_print("mediacodec unprepare is called"); - return NULL; -} -*/ void _mediacodec_unprepare(void) { @@ -818,29 +1532,49 @@ void _mediacodec_unprepare(void) } } frame_count = 0; - - //thread = g_thread_create(feed_thread, sejun, TRUE, NULL); return; } +int extract_input_per_frame (FILE *fp, unsigned char *rawdata) +{ + int readsize=0; + size_t result = 0; + while (!feof(fp)) + readsize += fread(rawdata+readsize, 1, 1, fp); + return readsize; +} int _mediacodec_process_input(void) { - g_print("_mediacodec_process_input\n"); - unsigned int buf_size = 0; +// g_print("_mediacodec_process_input (frame_count :%d)\n", frame_count); + int buf_size = 0; #if USE_INPUT_QUEUE media_packet_h in_buf = NULL; #endif void *data = NULL; - int ret = 0; + int ret = 0, codec_config=0; + mediacodec_s * handle = NULL; + mc_handle_t* mc_handle = NULL; + int err = MEDIACODEC_ERROR_NONE; if (g_media_codec[0] == NULL) { g_print("mediacodec handle is not created\n"); return MEDIACODEC_ERROR_INVALID_PARAMETER; } + else + { + handle = (mediacodec_s *) g_media_codec[0]; + mc_handle = (mc_handle_t*) handle->mc_handle; + } if (fp_src == NULL) { + if (bMultipleFiles) + { + if(g_uri[g_len-1] != '/') + g_uri[g_len++] = '/'; + sprintf(g_uri+g_len, "%05d", frame_count); + } fp_src = fopen(g_uri, "r"); if (fp_src == NULL) { @@ -849,12 +1583,12 @@ int _mediacodec_process_input(void) } } #if USE_INPUT_QUEUE - in_buf = mc_async_queue_pop(input_avaliable); + //in_buf = mc_async_queue_pop(input_avaliable); + in_buf = g_queue_pop_head(&input_available); #else _allocate_buf(); #endif - if (in_buf != NULL) { media_packet_get_buffer_data_ptr(in_buf, &data); @@ -865,7 +1599,25 @@ int _mediacodec_process_input(void) { if (use_video) { - buf_size = bytestream2yuv420(fp_src, data); + /* + * Video Encoder + */ + if (bMultipleFiles) + { + buf_size = extract_input_per_frame(fp_src, data); + fclose(fp_src); + sprintf(g_uri+g_len, "%05d", frame_count+1); + fp_src = fopen(g_uri, "r"); + if (fp_src == NULL) + { + media_packet_set_flags(in_buf, MEDIA_PACKET_END_OF_STREAM); + err = MEDIACODEC_ERROR_INVALID_INBUFFER; + } + } + else + { + buf_size = bytestream2yuv420(fp_src, data); + } media_packet_set_pts (in_buf, pts); g_print("input pts = %llu\n", pts); if (fps != 0) @@ -875,12 +1627,29 @@ int _mediacodec_process_input(void) } else { - buf_size = extract_input_aacenc(fp_src, data); - media_packet_set_pts (in_buf, pts); - g_print("input pts = %llu\n", pts); - if (samplerate != 0) + /* + * Aduio Encoder - AAC /AMR-NB + */ + if (mc_handle->codec_id == MEDIACODEC_AAC_LC) + { + buf_size = extract_input_aacenc(fp_src, data); + media_packet_set_pts (in_buf, pts); + g_print("input pts = %llu\n", pts); + if (samplerate != 0) + { + pts += ((GST_SECOND / samplerate) * samplebyte); + } + } + else if(mc_handle->codec_id == MEDIACODEC_AMR_NB) + { + buf_size = extract_input_amrenc(fp_src, data, 1); + media_packet_set_pts (in_buf, pts); + g_print("input pts = %llu\n", pts); + pts += (GST_SECOND / 50); /* (20ms/frame) AMR_FRAMES_PER_SECOND = 50 */ + } + else { - pts += ((GST_SECOND / samplerate) * samplebyte); + g_print(" [Input process] Not Suppor Audio Encodert!!!!! - mimetype (0x%x) codecid (0x%x)\n", mimetype, mc_handle->codec_id); } } } @@ -888,38 +1657,184 @@ int _mediacodec_process_input(void) { if (use_video) { - if(frame_count == 0) - ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG); - else if(frame_count == 300) - ret = media_packet_set_flags(in_buf, MEDIA_PACKET_END_OF_STREAM); + /* + * Video Decoder + */ + //else if(frame_count == 150) + // ret = media_packet_set_flags(in_buf, MEDIA_PACKET_END_OF_STREAM); + switch(mimetype) + { + case MEDIA_FORMAT_H264_SP: + case MEDIA_FORMAT_H264_MP: + case MEDIA_FORMAT_H264_HP: + { + buf_size = bytestream2nalunit(fp_src, data); + + if(frame_count == 2) + ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG); + } + break; + + case MEDIA_FORMAT_MPEG4_SP: + case MEDIA_FORMAT_MPEG4_ASP: + codec_config = 0; + if(bMultipleFiles) + { + buf_size = extract_input_per_frame(fp_src, data); + /* check for voss for setting codec_data flag 0x000001B0 */ + if(*(int*)data==0xb0010000) + codec_config = 1; + fclose(fp_src); + sprintf(g_uri+g_len, "%05d", frame_count+1); + fp_src = fopen(g_uri, "r"); + + if (fp_src == NULL) + { + media_packet_set_flags(in_buf, MEDIA_PACKET_END_OF_STREAM); + err = MEDIACODEC_ERROR_INVALID_INBUFFER; + } + } + else + { + buf_size = bytestream2mpeg4unit(fp_src,data,&codec_config); + } + if(codec_config) + { + ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG); + g_print("%s MPEG4 frame Set Codec Config\n",__func__); + } + break; - buf_size = bytestream2nalunit(fp_src, data); + case MEDIA_FORMAT_H263: + case MEDIA_FORMAT_H263P: + if(bMultipleFiles) + { + buf_size = extract_input_per_frame(fp_src, data); + fclose(fp_src); + sprintf(g_uri+g_len, "%05d", frame_count+1); + fp_src = fopen(g_uri, "r"); + if (fp_src == NULL) + { + media_packet_set_flags(in_buf, MEDIA_PACKET_END_OF_STREAM); + err = MEDIACODEC_ERROR_INVALID_INBUFFER; + } + } + else + { + buf_size = bytestream2h263unit(fp_src,data); + } + break; + + default: + g_print("packet feeding not support for this codec type\n",__func__); + break; + } +//mc_hex_dump("nal",data, 16); } else { - if (mimetype == MEDIA_FORMAT_AAC) + /* + * Audio Decoder - MP3 + * - AAC_LC (adts) + * - AAC_LC (raw) / AAC_HE (v1) / AAC_HE_PS (v2) + * - AMR-NB / AMR-WB + */ + if (mimetype == MEDIA_FORMAT_AAC_LC) { - buf_size = extract_input_aacdec(fp_src, data); +#if 1 /* ORG */ + /* It is available case of MEDIA_FORMAT_AAC_LC (ADTS) */ + buf_size = extract_input_aacdec(fp_src, data); +#else /* temp TEST (aac-lc raw) using codec data */ + /* It is also available case of MEDIA_FORMAT_AAC_LC (RAW) */ + if(frame_count[i] == 0) { + g_print("%s -[LEO] Enable 'AAC_LC_RAW' for *.mp4 or *.m4a case\n",__func__); + ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG); + //To-Do for inserting codec_data + } + buf_size = extract_input_aacdec_m4a_test(fp_src, data, i); +#endif + } + else if (mimetype == MEDIA_FORMAT_AAC_HE || mimetype == MEDIA_FORMAT_AAC_HE_PS) + { + if(frame_count == 0) { + g_print("%s -Enable 'HE_AAC_V12_ENABLE' for *.mp4 or *.m4a case\n",__func__); + ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG); + //To-Do for inserting codec_data + } + buf_size = extract_input_aacdec_m4a_test(fp_src, data); } else if (mimetype == MEDIA_FORMAT_MP3) { buf_size = extract_input_mp3dec(fp_src, data); } + else if (mimetype == MEDIA_FORMAT_AMR_NB || mimetype == MEDIA_FORMAT_AMR_WB) + { + buf_size = extract_input_amrdec(fp_src, data); + } + else if (mimetype == MEDIA_FORMAT_WMAV1 || mimetype == MEDIA_FORMAT_WMAV2 || + mimetype == MEDIA_FORMAT_WMAPRO || mimetype == MEDIA_FORMAT_WMALSL) + { + if (frame_count == 0) { + g_print("%s -Enable 'MEDIA_PACKET_CODEC_CONFIG' for *.wma case\n",__func__); + ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG); + //Need 'To-Do' for inserting codec_data + } + buf_size = extract_input_wmadec_test(fp_src, data); + } + else if (mimetype == MEDIA_FORMAT_VORBIS) + { + if (frame_count == 0) { + g_print("%s -Enable 'MEDIA_PACKET_CODEC_CONFIG' for *.ogg case\n",__func__); + ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG); + //Need 'To-Do' for inserting streamheader + } + buf_size = extract_input_vorbisdec_test(fp_src, data); + } + else if (mimetype == MEDIA_FORMAT_FLAC) + { + if (frame_count == 0) { + g_print("%s -Enable 'MEDIA_PACKET_CODEC_CONFIG' for *.flac case\n",__func__); + ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG); + //Need 'To-Do' for inserting streamheader + } + buf_size = extract_input_flacdec_test(fp_src, data); + } + else + { + g_print(" [Input process] Not Suppor Audio Decodert!!!!! - mimetype (0x%x) codecid (0x%x)\n", mimetype, mc_handle->codec_id); + } } } - if (buf_size == 0) + if (buf_size >= 0) { - g_print("input file read failed\n"); - return MEDIACODEC_ERROR_INVALID_PARAMETER; - } + if (use_video && buf_size == 4) + { + media_packet_set_flags(in_buf, MEDIA_PACKET_END_OF_STREAM); + media_packet_set_buffer_size(in_buf, 4); + mediacodec_process_input (g_media_codec[0], in_buf, 0); + g_printf("eos packet is sent\n"); + + return MEDIACODEC_ERROR_INVALID_INBUFFER; + } + media_packet_set_buffer_size(in_buf, buf_size); + g_print("%s - input_buf size = %4d (0x%x) at %4d frame, %p\n",__func__, buf_size, buf_size, frame_count, in_buf); - media_packet_set_buffer_size(in_buf, buf_size); - g_print("%s - input_buf size = %d (0x%x), frame_count : %d\n",__func__, buf_size, buf_size, frame_count); - ret = mediacodec_process_input (g_media_codec[0], in_buf, 0); - if(frame_count == 300) + ret = mediacodec_process_input (g_media_codec[0], in_buf, 0); + if (use_video && buf_size == -1) + { + g_print("%s - END : input_buf size = %d frame_count : %d\n",__func__, buf_size, frame_count); + return MEDIACODEC_ERROR_INVALID_INBUFFER; + } + } + else + { + g_print("%s - [WARN] Check to input buf_size = %4d at %4d frame, %p\n",__func__, buf_size, frame_count, in_buf); return MEDIACODEC_ERROR_INVALID_INBUFFER; + } + frame_count++; + return ret; } @@ -931,32 +1846,78 @@ int _mediacodec_get_output(void) int err = 0; uint64_t buf_size = 0; void *data = NULL; + mediacodec_s * handle = NULL; + mc_handle_t* mc_handle = NULL; + g_print("_mediacodec_get_output\n"); if (g_media_codec[0] == NULL) { g_print("mediacodec handle is not created\n"); return MEDIACODEC_ERROR_INVALID_PARAMETER; } + else + { + handle = (mediacodec_s *) g_media_codec[0]; + mc_handle = (mc_handle_t*) handle->mc_handle; + } err = mediacodec_get_output(g_media_codec[0], &output_buf, 0); if( err == MEDIACODEC_ERROR_NONE) { media_packet_get_buffer_size(output_buf, &buf_size); - g_print("%s - output_buf size =%p, %lld\n",__func__, output_buf, buf_size); + g_print("%s - output_buf size = %lld\n",__func__, buf_size); #if DUMP_OUTBUF media_packet_get_buffer_data_ptr(output_buf, &data); + if ((!use_video) && (use_encoder)) { - if (buf_size > 0) + /* + * Prepend Header For Aduio Encoder of AAC(adts) and AMR-NB + */ + if (mc_handle->codec_id == MEDIACODEC_AAC_LC) { - /* This is used only AAC encoder case for adding each ADTS frame header */ - add_adts_header_for_aacenc(buf_adts, (buf_size+ADTS_HEADER_SIZE)); - fwrite(&buf_adts[0], 1, ADTS_HEADER_SIZE, fp_out); + if (buf_size > 0) + { + /* This is used only AAC encoder case for adding each ADTS frame header */ + add_adts_header_for_aacenc(buf_adts, (buf_size+ADTS_HEADER_SIZE)); + fwrite(&buf_adts[0], 1, ADTS_HEADER_SIZE, fp_out); + } + } + else if (mc_handle->codec_id == MEDIACODEC_AMR_NB) + { + if ((buf_size > 0) && (write_amr_header == 1)) + { + /* This is used only AMR encoder case for adding AMR masic header in only first frame */ + g_print("%s - AMR_header write in first frame\n",__func__); + fwrite(&AMR_header[0], 1, sizeof(AMR_header) - 1, fp_out); /* AMR-NB magic number */ + write_amr_header = 0; + } } } if (data != NULL) + { fwrite(data, 1, buf_size, fp_out); + + // if g_OutFileCtr is set to 1 by developer, dump the output frame by frame in specified output folder + if(g_OutFileCtr) + { + FILE* fp; + char str[200]; + sprintf(str,"/media/frames/%05d", g_OutFileCtr-1); + fp = fopen(str,"wb"); + if(fp) + { + g_OutFileCtr++; + fwrite(data, 1, buf_size, fp); + fclose(fp); + } + else + { + g_OutFileCtr = 0; // Avoid trying to open file next time + } + } + } #endif // printf("%s - output_buf : %p\n",__func__, output_buf); // mediacodec_reset_output_buffer(g_media_codec[0], &output_buf); @@ -1015,20 +1976,58 @@ void _mediacodec_get_output_n(int num) } return; } +static gpointer vdec_task(gpointer data) +{ + int i; + //TODO extract packets from MediaDemuxer + /* + for(i=0; demuxer->get_track_count; i++) + { + } + */ + return NULL; +} void _mediacodec_process_all(void) { g_print("_mediacodec_process_all\n"); int ret = MEDIACODEC_ERROR_NONE; + GThread *vdec_thread, *venc_thread, *adec_thread, *aenc_thread; while(1) { ret = _mediacodec_process_input(); - if(ret != MEDIACODEC_ERROR_NONE) + if(ret != MEDIACODEC_ERROR_NONE) { + g_print ("_mediacodec_process_input ret = %d\n", ret); break; + } + } + +/* + if(use_encoder) + { + if(use_video) + { + } + else + { + } } + else + { + if(use_video) + { + vdec_thread = g_thread_create(vdec_task, NULL, TRUE, NULL); + + g_thread_join(vdec_thread); + } + else + { + } + } +*/ return; } @@ -1147,6 +2146,39 @@ static void displaymenu(void) } else if (g_menu_state == CURRENT_STATUS_SET_CODEC) { +#if 1 //NEW + g_print("*** Codec id : Select Codec ID Number (e.g. AAC_LC = 96)\n"); + g_print(" L16 = 16 (0x10)\n"); + g_print(" ALAW = 32 (0x20)\n"); + g_print(" ULAW = 48 (0x30)\n"); + g_print(" AMR_NB = 64 (0x40)\n"); + g_print(" AMR_WB = 65 (0x41)\n"); + g_print(" G729 = 80 (0x50)\n"); + g_print(" AAC_LC = 96 (0x60)\n"); + g_print(" AAC_HE = 97 (0x61)\n"); + g_print(" AAC_PS = 98 (0x62)\n"); + g_print(" MP3 = 112 (0x70)\n"); + g_print(" VORBIS = 128 (0x80)\n"); + g_print(" FLAC = 144 (0x90)\n"); + g_print(" WMAV1 = 160 (0xA0)\n"); + g_print(" WMAV2 = 161 (0xA1)\n"); + g_print(" WMAPRO = 162 (0xA2)\n"); + g_print(" WMALSL = 163 (0xA3)\n"); + g_print(" -------------------\n"); + g_print(" H261 = 101\n"); + g_print(" H263 = 102\n"); + g_print(" H264 = 103\n"); + g_print(" MJPEG = 104\n"); + g_print(" MPEG1 = 105\n"); + g_print(" MPEG2 = 106\n"); + g_print(" MPEG4 = 107\n"); + g_print(" -------------------\n"); + g_print("*** Flags : Select Combination Number (e.g. DEOCDER + TYPE_SW = 10)\n"); + g_print(" CODEC : ENCODER = 1 DECODER = 2\n"); + g_print(" TYPE : HW = 4 SW = 8\n"); + g_print(" TYPE : OMX = 16 GEN = 32\n"); + g_print("*** input codec id, flags.\n"); +#else g_print("*** Codec id : L16 = 1 Flags : MEDIACODEC_ENCODER = 1\n"); g_print(" ALAW = 2 MEDIACODEC_DECODER = 2\n"); g_print(" ULAW = 3 MEDIACODEC_SUPPORT_TYPE_HW = 4,\n"); @@ -1161,7 +2193,8 @@ static void displaymenu(void) g_print(" MPEG1 = 105\n"); g_print(" MPEG2 = 106\n"); g_print(" MPEG4 = 107\n"); - g_print("*** input codec id, flags.\n"); + g_print("*** input codec id, falgs.\n"); +#endif } else if (g_menu_state == CURRENT_STATUS_SET_VDEC_INFO) { @@ -1173,11 +2206,11 @@ static void displaymenu(void) } else if (g_menu_state == CURRENT_STATUS_SET_ADEC_INFO) { - g_print("*** input audio decode configure.(samplerate, channel, bit)\n"); + g_print("*** input audio decode configure.(samplerate, channel, bit (e.g. 48000, 2, 16))\n"); } else if (g_menu_state == CURRENT_STATUS_SET_AENC_INFO) { - g_print("*** input audio encode configure.(samplerate, channel, bit, bitrate)\n"); + g_print("*** input audio encode configure.(samplerate, channel, bit, bitrate (e.g. 48000, 2, 16, 128000))\n"); } else if (g_menu_state == CURRENT_STATUS_PROCESS_INPUT) { @@ -1230,7 +2263,15 @@ static void interpret (char *cmd) case 0: tmp = atoi(cmd); - if(tmp > 100) +#if 1 //NEW - ToDo : TEST for case of MP3 (112 = 0x70), VORBIS(128), FLAC(144), WMA(160~163) + if(tmp > 100 && + (tmp != 112) && + (tmp != 128) && + (tmp != 144) && + (tmp != 160) && (tmp != 161) && (tmp != 162) && (tmp != 163)) //Temporary +#else + if(tmp > 100) //orginal +#endif { tmp = strtol(cmd, ptr, 16); codecid = 0x2000 + ((tmp & 0xFF) << 4); @@ -1238,7 +2279,11 @@ static void interpret (char *cmd) } else { +#if 1 //NEW + codecid = 0x1000 + tmp; +#else codecid = 0x1000 + (tmp<<4); +#endif } cnt++; break; @@ -1385,18 +2430,18 @@ static void display_sub_basic() g_print("=========================================================================================\n"); g_print(" media codec test\n"); g_print("-----------------------------------------------------------------------------------------\n"); - g_print("a. Create \t"); - g_print("sc. Set codec \t\t"); - g_print("vd. Set vdec info w, h\t"); + g_print("a. Create \t\t"); + g_print("sc. Set codec \n"); + g_print("vd. Set vdec info \t"); g_print("ve. Set venc info \n"); - g_print("ad. Set adec info s, c, b\t"); + g_print("ad. Set adec info \t"); g_print("ae. Set aenc info \n"); - g_print("pr. Prepare \t"); - g_print("pi. Process input \t"); + g_print("pr. Prepare \t\t"); + g_print("pi. Process input \n"); g_print("o. Get output \t\t"); g_print("rb. Reset output buffer \n"); g_print("pa. Process all frames \n"); - g_print("un. Unprepare \t"); + g_print("un. Unprepare \t\t"); g_print("dt. Destroy \t\t"); g_print("q. quite test suite \t"); g_print("\n"); diff --git a/test/test_samples/sample_mpeg4/00000 b/test/test_samples/sample_mpeg4/00000 Binary files differnew file mode 100644 index 0000000..9fe87ee --- /dev/null +++ b/test/test_samples/sample_mpeg4/00000 diff --git a/test/test_samples/sample_mpeg4/00001 b/test/test_samples/sample_mpeg4/00001 Binary files differnew file mode 100644 index 0000000..2bb3c75 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00001 diff --git a/test/test_samples/sample_mpeg4/00002 b/test/test_samples/sample_mpeg4/00002 Binary files differnew file mode 100644 index 0000000..c87335c --- /dev/null +++ b/test/test_samples/sample_mpeg4/00002 diff --git a/test/test_samples/sample_mpeg4/00003 b/test/test_samples/sample_mpeg4/00003 Binary files differnew file mode 100644 index 0000000..b847bd8 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00003 diff --git a/test/test_samples/sample_mpeg4/00004 b/test/test_samples/sample_mpeg4/00004 Binary files differnew file mode 100644 index 0000000..0ce410b --- /dev/null +++ b/test/test_samples/sample_mpeg4/00004 diff --git a/test/test_samples/sample_mpeg4/00005 b/test/test_samples/sample_mpeg4/00005 Binary files differnew file mode 100644 index 0000000..68a2b92 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00005 diff --git a/test/test_samples/sample_mpeg4/00006 b/test/test_samples/sample_mpeg4/00006 Binary files differnew file mode 100644 index 0000000..2c8b4d3 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00006 diff --git a/test/test_samples/sample_mpeg4/00007 b/test/test_samples/sample_mpeg4/00007 Binary files differnew file mode 100644 index 0000000..2d37adf --- /dev/null +++ b/test/test_samples/sample_mpeg4/00007 diff --git a/test/test_samples/sample_mpeg4/00008 b/test/test_samples/sample_mpeg4/00008 Binary files differnew file mode 100644 index 0000000..55be446 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00008 diff --git a/test/test_samples/sample_mpeg4/00009 b/test/test_samples/sample_mpeg4/00009 Binary files differnew file mode 100644 index 0000000..302ba22 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00009 diff --git a/test/test_samples/sample_mpeg4/00010 b/test/test_samples/sample_mpeg4/00010 Binary files differnew file mode 100644 index 0000000..d5c4561 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00010 diff --git a/test/test_samples/sample_mpeg4/00011 b/test/test_samples/sample_mpeg4/00011 Binary files differnew file mode 100644 index 0000000..4d85436 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00011 diff --git a/test/test_samples/sample_mpeg4/00012 b/test/test_samples/sample_mpeg4/00012 Binary files differnew file mode 100644 index 0000000..bdb2245 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00012 diff --git a/test/test_samples/sample_mpeg4/00013 b/test/test_samples/sample_mpeg4/00013 Binary files differnew file mode 100644 index 0000000..29dc6b5 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00013 diff --git a/test/test_samples/sample_mpeg4/00014 b/test/test_samples/sample_mpeg4/00014 Binary files differnew file mode 100644 index 0000000..64cafd0 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00014 diff --git a/test/test_samples/sample_mpeg4/00015 b/test/test_samples/sample_mpeg4/00015 Binary files differnew file mode 100644 index 0000000..00feaca --- /dev/null +++ b/test/test_samples/sample_mpeg4/00015 diff --git a/test/test_samples/sample_mpeg4/00016 b/test/test_samples/sample_mpeg4/00016 Binary files differnew file mode 100644 index 0000000..f9e9a0f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00016 diff --git a/test/test_samples/sample_mpeg4/00017 b/test/test_samples/sample_mpeg4/00017 Binary files differnew file mode 100644 index 0000000..9a2d75f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00017 diff --git a/test/test_samples/sample_mpeg4/00018 b/test/test_samples/sample_mpeg4/00018 Binary files differnew file mode 100644 index 0000000..decf4a0 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00018 diff --git a/test/test_samples/sample_mpeg4/00019 b/test/test_samples/sample_mpeg4/00019 Binary files differnew file mode 100644 index 0000000..8c05bca --- /dev/null +++ b/test/test_samples/sample_mpeg4/00019 diff --git a/test/test_samples/sample_mpeg4/00020 b/test/test_samples/sample_mpeg4/00020 Binary files differnew file mode 100644 index 0000000..1e0591e --- /dev/null +++ b/test/test_samples/sample_mpeg4/00020 diff --git a/test/test_samples/sample_mpeg4/00021 b/test/test_samples/sample_mpeg4/00021 Binary files differnew file mode 100644 index 0000000..e01d631 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00021 diff --git a/test/test_samples/sample_mpeg4/00022 b/test/test_samples/sample_mpeg4/00022 Binary files differnew file mode 100644 index 0000000..5a1eec2 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00022 diff --git a/test/test_samples/sample_mpeg4/00023 b/test/test_samples/sample_mpeg4/00023 Binary files differnew file mode 100644 index 0000000..472b97f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00023 diff --git a/test/test_samples/sample_mpeg4/00024 b/test/test_samples/sample_mpeg4/00024 Binary files differnew file mode 100644 index 0000000..bfd7017 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00024 diff --git a/test/test_samples/sample_mpeg4/00025 b/test/test_samples/sample_mpeg4/00025 Binary files differnew file mode 100644 index 0000000..046a5ed --- /dev/null +++ b/test/test_samples/sample_mpeg4/00025 diff --git a/test/test_samples/sample_mpeg4/00026 b/test/test_samples/sample_mpeg4/00026 Binary files differnew file mode 100644 index 0000000..3679c9a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00026 diff --git a/test/test_samples/sample_mpeg4/00027 b/test/test_samples/sample_mpeg4/00027 Binary files differnew file mode 100644 index 0000000..6cf1066 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00027 diff --git a/test/test_samples/sample_mpeg4/00028 b/test/test_samples/sample_mpeg4/00028 Binary files differnew file mode 100644 index 0000000..c386c14 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00028 diff --git a/test/test_samples/sample_mpeg4/00029 b/test/test_samples/sample_mpeg4/00029 Binary files differnew file mode 100644 index 0000000..609452d --- /dev/null +++ b/test/test_samples/sample_mpeg4/00029 diff --git a/test/test_samples/sample_mpeg4/00030 b/test/test_samples/sample_mpeg4/00030 Binary files differnew file mode 100644 index 0000000..629ecce --- /dev/null +++ b/test/test_samples/sample_mpeg4/00030 diff --git a/test/test_samples/sample_mpeg4/00031 b/test/test_samples/sample_mpeg4/00031 Binary files differnew file mode 100644 index 0000000..69bb74a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00031 diff --git a/test/test_samples/sample_mpeg4/00032 b/test/test_samples/sample_mpeg4/00032 Binary files differnew file mode 100644 index 0000000..fd494b5 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00032 diff --git a/test/test_samples/sample_mpeg4/00033 b/test/test_samples/sample_mpeg4/00033 Binary files differnew file mode 100644 index 0000000..dcd15a5 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00033 diff --git a/test/test_samples/sample_mpeg4/00034 b/test/test_samples/sample_mpeg4/00034 Binary files differnew file mode 100644 index 0000000..70b100a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00034 diff --git a/test/test_samples/sample_mpeg4/00035 b/test/test_samples/sample_mpeg4/00035 Binary files differnew file mode 100644 index 0000000..f677dad --- /dev/null +++ b/test/test_samples/sample_mpeg4/00035 diff --git a/test/test_samples/sample_mpeg4/00036 b/test/test_samples/sample_mpeg4/00036 Binary files differnew file mode 100644 index 0000000..ec1a7e8 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00036 diff --git a/test/test_samples/sample_mpeg4/00037 b/test/test_samples/sample_mpeg4/00037 Binary files differnew file mode 100644 index 0000000..e3a97c0 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00037 diff --git a/test/test_samples/sample_mpeg4/00038 b/test/test_samples/sample_mpeg4/00038 Binary files differnew file mode 100644 index 0000000..f4e0e36 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00038 diff --git a/test/test_samples/sample_mpeg4/00039 b/test/test_samples/sample_mpeg4/00039 Binary files differnew file mode 100644 index 0000000..ab306d1 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00039 diff --git a/test/test_samples/sample_mpeg4/00040 b/test/test_samples/sample_mpeg4/00040 Binary files differnew file mode 100644 index 0000000..9654862 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00040 diff --git a/test/test_samples/sample_mpeg4/00041 b/test/test_samples/sample_mpeg4/00041 Binary files differnew file mode 100644 index 0000000..494199d --- /dev/null +++ b/test/test_samples/sample_mpeg4/00041 diff --git a/test/test_samples/sample_mpeg4/00042 b/test/test_samples/sample_mpeg4/00042 Binary files differnew file mode 100644 index 0000000..d587d9b --- /dev/null +++ b/test/test_samples/sample_mpeg4/00042 diff --git a/test/test_samples/sample_mpeg4/00043 b/test/test_samples/sample_mpeg4/00043 Binary files differnew file mode 100644 index 0000000..fb95f36 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00043 diff --git a/test/test_samples/sample_mpeg4/00044 b/test/test_samples/sample_mpeg4/00044 Binary files differnew file mode 100644 index 0000000..b3c0924 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00044 diff --git a/test/test_samples/sample_mpeg4/00045 b/test/test_samples/sample_mpeg4/00045 Binary files differnew file mode 100644 index 0000000..f126cc1 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00045 diff --git a/test/test_samples/sample_mpeg4/00046 b/test/test_samples/sample_mpeg4/00046 Binary files differnew file mode 100644 index 0000000..667e973 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00046 diff --git a/test/test_samples/sample_mpeg4/00047 b/test/test_samples/sample_mpeg4/00047 Binary files differnew file mode 100644 index 0000000..164b22a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00047 diff --git a/test/test_samples/sample_mpeg4/00048 b/test/test_samples/sample_mpeg4/00048 Binary files differnew file mode 100644 index 0000000..159be6a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00048 diff --git a/test/test_samples/sample_mpeg4/00049 b/test/test_samples/sample_mpeg4/00049 Binary files differnew file mode 100644 index 0000000..765b9e7 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00049 diff --git a/test/test_samples/sample_mpeg4/00050 b/test/test_samples/sample_mpeg4/00050 Binary files differnew file mode 100644 index 0000000..1ff4292 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00050 diff --git a/test/test_samples/sample_mpeg4/00051 b/test/test_samples/sample_mpeg4/00051 Binary files differnew file mode 100644 index 0000000..080e5b6 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00051 diff --git a/test/test_samples/sample_mpeg4/00052 b/test/test_samples/sample_mpeg4/00052 Binary files differnew file mode 100644 index 0000000..0328527 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00052 diff --git a/test/test_samples/sample_mpeg4/00053 b/test/test_samples/sample_mpeg4/00053 Binary files differnew file mode 100644 index 0000000..aa47e71 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00053 diff --git a/test/test_samples/sample_mpeg4/00054 b/test/test_samples/sample_mpeg4/00054 Binary files differnew file mode 100644 index 0000000..f7b0ea7 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00054 diff --git a/test/test_samples/sample_mpeg4/00055 b/test/test_samples/sample_mpeg4/00055 Binary files differnew file mode 100644 index 0000000..bc58546 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00055 diff --git a/test/test_samples/sample_mpeg4/00056 b/test/test_samples/sample_mpeg4/00056 Binary files differnew file mode 100644 index 0000000..0938c91 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00056 diff --git a/test/test_samples/sample_mpeg4/00057 b/test/test_samples/sample_mpeg4/00057 Binary files differnew file mode 100644 index 0000000..a28a399 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00057 diff --git a/test/test_samples/sample_mpeg4/00058 b/test/test_samples/sample_mpeg4/00058 Binary files differnew file mode 100644 index 0000000..7962b94 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00058 diff --git a/test/test_samples/sample_mpeg4/00059 b/test/test_samples/sample_mpeg4/00059 Binary files differnew file mode 100644 index 0000000..ba9c8c8 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00059 diff --git a/test/test_samples/sample_mpeg4/00060 b/test/test_samples/sample_mpeg4/00060 Binary files differnew file mode 100644 index 0000000..8d1e482 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00060 diff --git a/test/test_samples/sample_mpeg4/00061 b/test/test_samples/sample_mpeg4/00061 Binary files differnew file mode 100644 index 0000000..bdbd18f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00061 diff --git a/test/test_samples/sample_mpeg4/00062 b/test/test_samples/sample_mpeg4/00062 Binary files differnew file mode 100644 index 0000000..0ed6743 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00062 diff --git a/test/test_samples/sample_mpeg4/00063 b/test/test_samples/sample_mpeg4/00063 Binary files differnew file mode 100644 index 0000000..742c36d --- /dev/null +++ b/test/test_samples/sample_mpeg4/00063 diff --git a/test/test_samples/sample_mpeg4/00064 b/test/test_samples/sample_mpeg4/00064 Binary files differnew file mode 100644 index 0000000..07310d0 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00064 diff --git a/test/test_samples/sample_mpeg4/00065 b/test/test_samples/sample_mpeg4/00065 Binary files differnew file mode 100644 index 0000000..c89ba06 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00065 diff --git a/test/test_samples/sample_mpeg4/00066 b/test/test_samples/sample_mpeg4/00066 Binary files differnew file mode 100644 index 0000000..b9fa77b --- /dev/null +++ b/test/test_samples/sample_mpeg4/00066 diff --git a/test/test_samples/sample_mpeg4/00067 b/test/test_samples/sample_mpeg4/00067 Binary files differnew file mode 100644 index 0000000..c688e67 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00067 diff --git a/test/test_samples/sample_mpeg4/00068 b/test/test_samples/sample_mpeg4/00068 Binary files differnew file mode 100644 index 0000000..8994657 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00068 diff --git a/test/test_samples/sample_mpeg4/00069 b/test/test_samples/sample_mpeg4/00069 Binary files differnew file mode 100644 index 0000000..31be525 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00069 diff --git a/test/test_samples/sample_mpeg4/00070 b/test/test_samples/sample_mpeg4/00070 Binary files differnew file mode 100644 index 0000000..fcd920f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00070 diff --git a/test/test_samples/sample_mpeg4/00071 b/test/test_samples/sample_mpeg4/00071 Binary files differnew file mode 100644 index 0000000..544849d --- /dev/null +++ b/test/test_samples/sample_mpeg4/00071 diff --git a/test/test_samples/sample_mpeg4/00072 b/test/test_samples/sample_mpeg4/00072 Binary files differnew file mode 100644 index 0000000..e28d543 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00072 diff --git a/test/test_samples/sample_mpeg4/00073 b/test/test_samples/sample_mpeg4/00073 Binary files differnew file mode 100644 index 0000000..607a281 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00073 diff --git a/test/test_samples/sample_mpeg4/00074 b/test/test_samples/sample_mpeg4/00074 Binary files differnew file mode 100644 index 0000000..6fcdb61 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00074 diff --git a/test/test_samples/sample_mpeg4/00075 b/test/test_samples/sample_mpeg4/00075 Binary files differnew file mode 100644 index 0000000..f9943b1 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00075 diff --git a/test/test_samples/sample_mpeg4/00076 b/test/test_samples/sample_mpeg4/00076 Binary files differnew file mode 100644 index 0000000..8637bbe --- /dev/null +++ b/test/test_samples/sample_mpeg4/00076 diff --git a/test/test_samples/sample_mpeg4/00077 b/test/test_samples/sample_mpeg4/00077 Binary files differnew file mode 100644 index 0000000..c2f1dd6 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00077 diff --git a/test/test_samples/sample_mpeg4/00078 b/test/test_samples/sample_mpeg4/00078 Binary files differnew file mode 100644 index 0000000..9753748 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00078 diff --git a/test/test_samples/sample_mpeg4/00079 b/test/test_samples/sample_mpeg4/00079 Binary files differnew file mode 100644 index 0000000..298cc66 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00079 diff --git a/test/test_samples/sample_mpeg4/00080 b/test/test_samples/sample_mpeg4/00080 Binary files differnew file mode 100644 index 0000000..c8d61e0 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00080 diff --git a/test/test_samples/sample_mpeg4/00081 b/test/test_samples/sample_mpeg4/00081 Binary files differnew file mode 100644 index 0000000..c8f52a1 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00081 diff --git a/test/test_samples/sample_mpeg4/00082 b/test/test_samples/sample_mpeg4/00082 Binary files differnew file mode 100644 index 0000000..f61ee32 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00082 diff --git a/test/test_samples/sample_mpeg4/00083 b/test/test_samples/sample_mpeg4/00083 Binary files differnew file mode 100644 index 0000000..907fe02 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00083 diff --git a/test/test_samples/sample_mpeg4/00084 b/test/test_samples/sample_mpeg4/00084 Binary files differnew file mode 100644 index 0000000..fc82703 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00084 diff --git a/test/test_samples/sample_mpeg4/00085 b/test/test_samples/sample_mpeg4/00085 Binary files differnew file mode 100644 index 0000000..51d7c9e --- /dev/null +++ b/test/test_samples/sample_mpeg4/00085 diff --git a/test/test_samples/sample_mpeg4/00086 b/test/test_samples/sample_mpeg4/00086 Binary files differnew file mode 100644 index 0000000..17820ea --- /dev/null +++ b/test/test_samples/sample_mpeg4/00086 diff --git a/test/test_samples/sample_mpeg4/00087 b/test/test_samples/sample_mpeg4/00087 Binary files differnew file mode 100644 index 0000000..c54c572 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00087 diff --git a/test/test_samples/sample_mpeg4/00088 b/test/test_samples/sample_mpeg4/00088 Binary files differnew file mode 100644 index 0000000..02b774b --- /dev/null +++ b/test/test_samples/sample_mpeg4/00088 diff --git a/test/test_samples/sample_mpeg4/00089 b/test/test_samples/sample_mpeg4/00089 Binary files differnew file mode 100644 index 0000000..ea59f67 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00089 diff --git a/test/test_samples/sample_mpeg4/00090 b/test/test_samples/sample_mpeg4/00090 Binary files differnew file mode 100644 index 0000000..8f73e5f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00090 diff --git a/test/test_samples/sample_mpeg4/00091 b/test/test_samples/sample_mpeg4/00091 Binary files differnew file mode 100644 index 0000000..c59ba0e --- /dev/null +++ b/test/test_samples/sample_mpeg4/00091 diff --git a/test/test_samples/sample_mpeg4/00092 b/test/test_samples/sample_mpeg4/00092 Binary files differnew file mode 100644 index 0000000..1e235a1 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00092 diff --git a/test/test_samples/sample_mpeg4/00093 b/test/test_samples/sample_mpeg4/00093 Binary files differnew file mode 100644 index 0000000..8d2ed0a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00093 diff --git a/test/test_samples/sample_mpeg4/00094 b/test/test_samples/sample_mpeg4/00094 Binary files differnew file mode 100644 index 0000000..4ca9256 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00094 diff --git a/test/test_samples/sample_mpeg4/00095 b/test/test_samples/sample_mpeg4/00095 Binary files differnew file mode 100644 index 0000000..1501237 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00095 diff --git a/test/test_samples/sample_mpeg4/00096 b/test/test_samples/sample_mpeg4/00096 Binary files differnew file mode 100644 index 0000000..a553d5a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00096 diff --git a/test/test_samples/sample_mpeg4/00097 b/test/test_samples/sample_mpeg4/00097 Binary files differnew file mode 100644 index 0000000..d3d9d7a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00097 diff --git a/test/test_samples/sample_mpeg4/00098 b/test/test_samples/sample_mpeg4/00098 Binary files differnew file mode 100644 index 0000000..3912121 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00098 diff --git a/test/test_samples/sample_mpeg4/00099 b/test/test_samples/sample_mpeg4/00099 Binary files differnew file mode 100644 index 0000000..b270029 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00099 diff --git a/test/test_samples/sample_mpeg4/00100 b/test/test_samples/sample_mpeg4/00100 Binary files differnew file mode 100644 index 0000000..c4710db --- /dev/null +++ b/test/test_samples/sample_mpeg4/00100 diff --git a/test/test_samples/sample_mpeg4/00101 b/test/test_samples/sample_mpeg4/00101 Binary files differnew file mode 100644 index 0000000..ca19426 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00101 diff --git a/test/test_samples/sample_mpeg4/00102 b/test/test_samples/sample_mpeg4/00102 Binary files differnew file mode 100644 index 0000000..091b7b8 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00102 diff --git a/test/test_samples/sample_mpeg4/00103 b/test/test_samples/sample_mpeg4/00103 Binary files differnew file mode 100644 index 0000000..674a2eb --- /dev/null +++ b/test/test_samples/sample_mpeg4/00103 diff --git a/test/test_samples/sample_mpeg4/00104 b/test/test_samples/sample_mpeg4/00104 Binary files differnew file mode 100644 index 0000000..1f561ec --- /dev/null +++ b/test/test_samples/sample_mpeg4/00104 diff --git a/test/test_samples/sample_mpeg4/00105 b/test/test_samples/sample_mpeg4/00105 Binary files differnew file mode 100644 index 0000000..2e4823f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00105 diff --git a/test/test_samples/sample_mpeg4/00106 b/test/test_samples/sample_mpeg4/00106 Binary files differnew file mode 100644 index 0000000..98878ef --- /dev/null +++ b/test/test_samples/sample_mpeg4/00106 diff --git a/test/test_samples/sample_mpeg4/00107 b/test/test_samples/sample_mpeg4/00107 Binary files differnew file mode 100644 index 0000000..937cedc --- /dev/null +++ b/test/test_samples/sample_mpeg4/00107 diff --git a/test/test_samples/sample_mpeg4/00108 b/test/test_samples/sample_mpeg4/00108 Binary files differnew file mode 100644 index 0000000..4970beb --- /dev/null +++ b/test/test_samples/sample_mpeg4/00108 diff --git a/test/test_samples/sample_mpeg4/00109 b/test/test_samples/sample_mpeg4/00109 Binary files differnew file mode 100644 index 0000000..4c43d2e --- /dev/null +++ b/test/test_samples/sample_mpeg4/00109 diff --git a/test/test_samples/sample_mpeg4/00110 b/test/test_samples/sample_mpeg4/00110 Binary files differnew file mode 100644 index 0000000..e99e35c --- /dev/null +++ b/test/test_samples/sample_mpeg4/00110 diff --git a/test/test_samples/sample_mpeg4/00111 b/test/test_samples/sample_mpeg4/00111 Binary files differnew file mode 100644 index 0000000..8f7e6e4 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00111 diff --git a/test/test_samples/sample_mpeg4/00112 b/test/test_samples/sample_mpeg4/00112 Binary files differnew file mode 100644 index 0000000..073d7bb --- /dev/null +++ b/test/test_samples/sample_mpeg4/00112 diff --git a/test/test_samples/sample_mpeg4/00113 b/test/test_samples/sample_mpeg4/00113 Binary files differnew file mode 100644 index 0000000..f34e20c --- /dev/null +++ b/test/test_samples/sample_mpeg4/00113 diff --git a/test/test_samples/sample_mpeg4/00114 b/test/test_samples/sample_mpeg4/00114 Binary files differnew file mode 100644 index 0000000..ce64abc --- /dev/null +++ b/test/test_samples/sample_mpeg4/00114 diff --git a/test/test_samples/sample_mpeg4/00115 b/test/test_samples/sample_mpeg4/00115 Binary files differnew file mode 100644 index 0000000..d844164 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00115 diff --git a/test/test_samples/sample_mpeg4/00116 b/test/test_samples/sample_mpeg4/00116 Binary files differnew file mode 100644 index 0000000..bba3338 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00116 diff --git a/test/test_samples/sample_mpeg4/00117 b/test/test_samples/sample_mpeg4/00117 Binary files differnew file mode 100644 index 0000000..ae22d23 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00117 diff --git a/test/test_samples/sample_mpeg4/00118 b/test/test_samples/sample_mpeg4/00118 Binary files differnew file mode 100644 index 0000000..eb397fc --- /dev/null +++ b/test/test_samples/sample_mpeg4/00118 diff --git a/test/test_samples/sample_mpeg4/00119 b/test/test_samples/sample_mpeg4/00119 Binary files differnew file mode 100644 index 0000000..cafae96 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00119 diff --git a/test/test_samples/sample_mpeg4/00120 b/test/test_samples/sample_mpeg4/00120 Binary files differnew file mode 100644 index 0000000..d06a53a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00120 diff --git a/test/test_samples/sample_mpeg4/00121 b/test/test_samples/sample_mpeg4/00121 Binary files differnew file mode 100644 index 0000000..13b606f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00121 diff --git a/test/test_samples/sample_mpeg4/00122 b/test/test_samples/sample_mpeg4/00122 Binary files differnew file mode 100644 index 0000000..aaa1220 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00122 diff --git a/test/test_samples/sample_mpeg4/00123 b/test/test_samples/sample_mpeg4/00123 Binary files differnew file mode 100644 index 0000000..a515ab1 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00123 diff --git a/test/test_samples/sample_mpeg4/00124 b/test/test_samples/sample_mpeg4/00124 Binary files differnew file mode 100644 index 0000000..b56a8d6 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00124 diff --git a/test/test_samples/sample_mpeg4/00125 b/test/test_samples/sample_mpeg4/00125 Binary files differnew file mode 100644 index 0000000..79998e4 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00125 diff --git a/test/test_samples/sample_mpeg4/00126 b/test/test_samples/sample_mpeg4/00126 Binary files differnew file mode 100644 index 0000000..1977791 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00126 diff --git a/test/test_samples/sample_mpeg4/00127 b/test/test_samples/sample_mpeg4/00127 Binary files differnew file mode 100644 index 0000000..1308e04 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00127 diff --git a/test/test_samples/sample_mpeg4/00128 b/test/test_samples/sample_mpeg4/00128 Binary files differnew file mode 100644 index 0000000..5df6e5a --- /dev/null +++ b/test/test_samples/sample_mpeg4/00128 diff --git a/test/test_samples/sample_mpeg4/00129 b/test/test_samples/sample_mpeg4/00129 Binary files differnew file mode 100644 index 0000000..f8d428e --- /dev/null +++ b/test/test_samples/sample_mpeg4/00129 diff --git a/test/test_samples/sample_mpeg4/00130 b/test/test_samples/sample_mpeg4/00130 Binary files differnew file mode 100644 index 0000000..5c3be66 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00130 diff --git a/test/test_samples/sample_mpeg4/00131 b/test/test_samples/sample_mpeg4/00131 Binary files differnew file mode 100644 index 0000000..3727828 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00131 diff --git a/test/test_samples/sample_mpeg4/00132 b/test/test_samples/sample_mpeg4/00132 Binary files differnew file mode 100644 index 0000000..3bdf862 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00132 diff --git a/test/test_samples/sample_mpeg4/00133 b/test/test_samples/sample_mpeg4/00133 Binary files differnew file mode 100644 index 0000000..f41909b --- /dev/null +++ b/test/test_samples/sample_mpeg4/00133 diff --git a/test/test_samples/sample_mpeg4/00134 b/test/test_samples/sample_mpeg4/00134 Binary files differnew file mode 100644 index 0000000..f7b25ec --- /dev/null +++ b/test/test_samples/sample_mpeg4/00134 diff --git a/test/test_samples/sample_mpeg4/00135 b/test/test_samples/sample_mpeg4/00135 Binary files differnew file mode 100644 index 0000000..6f33d05 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00135 diff --git a/test/test_samples/sample_mpeg4/00136 b/test/test_samples/sample_mpeg4/00136 Binary files differnew file mode 100644 index 0000000..6ad916f --- /dev/null +++ b/test/test_samples/sample_mpeg4/00136 diff --git a/test/test_samples/sample_mpeg4/00137 b/test/test_samples/sample_mpeg4/00137 Binary files differnew file mode 100644 index 0000000..bd83431 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00137 diff --git a/test/test_samples/sample_mpeg4/00138 b/test/test_samples/sample_mpeg4/00138 Binary files differnew file mode 100644 index 0000000..df51024 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00138 diff --git a/test/test_samples/sample_mpeg4/00139 b/test/test_samples/sample_mpeg4/00139 Binary files differnew file mode 100644 index 0000000..a3556d7 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00139 diff --git a/test/test_samples/sample_mpeg4/00140 b/test/test_samples/sample_mpeg4/00140 Binary files differnew file mode 100644 index 0000000..30fe669 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00140 diff --git a/test/test_samples/sample_mpeg4/00141 b/test/test_samples/sample_mpeg4/00141 Binary files differnew file mode 100644 index 0000000..9bc3b16 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00141 diff --git a/test/test_samples/sample_mpeg4/00142 b/test/test_samples/sample_mpeg4/00142 Binary files differnew file mode 100644 index 0000000..911ad85 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00142 diff --git a/test/test_samples/sample_mpeg4/00143 b/test/test_samples/sample_mpeg4/00143 Binary files differnew file mode 100644 index 0000000..26f7f25 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00143 diff --git a/test/test_samples/sample_mpeg4/00144 b/test/test_samples/sample_mpeg4/00144 Binary files differnew file mode 100644 index 0000000..ffbc95b --- /dev/null +++ b/test/test_samples/sample_mpeg4/00144 diff --git a/test/test_samples/sample_mpeg4/00145 b/test/test_samples/sample_mpeg4/00145 Binary files differnew file mode 100644 index 0000000..bb99f41 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00145 diff --git a/test/test_samples/sample_mpeg4/00146 b/test/test_samples/sample_mpeg4/00146 Binary files differnew file mode 100644 index 0000000..d2fc6be --- /dev/null +++ b/test/test_samples/sample_mpeg4/00146 diff --git a/test/test_samples/sample_mpeg4/00147 b/test/test_samples/sample_mpeg4/00147 Binary files differnew file mode 100644 index 0000000..83b0129 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00147 diff --git a/test/test_samples/sample_mpeg4/00148 b/test/test_samples/sample_mpeg4/00148 Binary files differnew file mode 100644 index 0000000..d208ad4 --- /dev/null +++ b/test/test_samples/sample_mpeg4/00148 |