-Kangho Hur <kanho.hur@samsung.com>
-Seungkeun Lee <sngn.lee@samsung.com>
+Sejun Park <sejun79.park@samsung.com>
SET(INC_DIR include)
INCLUDE_DIRECTORIES(${INC_DIR})
-SET(dependents "dlog glib-2.0 mm-common capi-media-tool libtbm libdri2 gstreamer-1.0 gstreamer-plugins-base-1.0 gstreamer-app-1.0" )
+SET(dependents "dlog glib-2.0 mm-common libtbm libdri2 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)
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")
*/
typedef enum
{
- MEDIACODEC_NONE = 0x0,
- MEDIACODEC_L16 = 0x1010,
- MEDIACODEC_ALAW = 0x1020,
- MEDIACODEC_ULAW = 0x1030,
- MEDIACODEC_AMR = 0x1040,
- MEDIACODEC_G729 = 0x1050,
- MEDIACODEC_AAC = 0x1060,
- MEDIACODEC_MP3 = 0x1070,
-
- MEDIACODEC_H261 = 0x2010,
- MEDIACODEC_H263 = 0x2020,
- MEDIACODEC_H264 = 0x2030,
- MEDIACODEC_MJPEG = 0x2040,
- MEDIACODEC_MPEG1 = 0x2050,
- MEDIACODEC_MPEG2 = 0x2060,
- MEDIACODEC_MPEG4 = 0x2070,
+ 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;
/**
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 limt (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 2.3
*/
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 2.3
* @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);
* @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
* @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
* @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);
* @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);
* @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);
* @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);
* @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);
* @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);
* @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 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.
* @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 2.3
*/
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);
+
+
/**
* @}
*/
--- /dev/null
+/*
+* 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;
+
+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 );
+
+int __mc_decode_sps(mc_bitstream_t *pstream, int *width, int *height);
+unsigned int __mc_bytestream_to_nal( unsigned char* data, int size, unsigned char *nal );
+int _mc_check_bytestream ( media_packet_h pkt, unsigned char *nal, int byte_length, int *width, int *height);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_MEDIA_CODEC_BITSTREAM_H__ */
#include <media_codec.h>
#include <media_codec_queue.h>
+#include <media_codec_bitstream.h>
#include <media_codec_spec_emul.h>
/*---------------------------------------------------------------------------
| 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)
//#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: |
* @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;
-/* gst port layer */
-typedef struct _mc_gst_port_t mc_gst_port_t;
-typedef struct _mc_gst_core_t mc_gst_core_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,
_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;
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;
struct _mc_encoder_info_t
{
- int frame_width;
- int frame_height;
+ int width;
+ int height;
int bitrate;
+ int format;
int fps;
int qp_min;
int qp_max;
int bit;
};
-struct _mc_gst_port_t
-{
- mc_gst_core_t *core;
- unsigned int num_buffers;
- unsigned int buffer_size;
- unsigned int index;
- bool is_allocated;
- media_packet_h *buffers;
- //GSem
- GQueue *queue;
- GMutex *mutex;
- GCond *buffer_cond;
-};
-
-struct _mc_gst_core_t
-{
- GstState state;
- bool output_allocated;
- bool encoder;
- bool video;
- bool is_hw;
-
- mediacodec_codec_type_e codec_id;
- media_format_h output_fmt;
- mc_gst_port_t *ports[2];
-
- /* gst stuffs */
- GstElement* pipeline;
- GstElement* appsrc;
- GstElement* converter;
- GstElement* fakesink;
- GstElement* codec;
-
- gulong signal_handoff;
- gint bus_whatch_id;
-
- mc_aqueue_t *available_queue;
- GQueue *output_queue;
-
- mc_decoder_info_t *dec_info;
- mc_encoder_info_t *enc_info;
-
- void* user_cb[_MEDIACODEC_EVENT_TYPE_NUM];
- void* user_data[_MEDIACODEC_EVENT_TYPE_NUM];
-
- gchar *factory_name;
- gchar *mime;
-};
-
/* Codec Private data */
struct _mc_handle_t
{
- void *hcodec; /**< codec handle */
int state; /**< mc current state */
- mediacodec_port_type_e port_type;
bool is_encoder;
bool is_video;
bool is_hw;
- bool is_codec_config; /** < codec config data for first frame(SPS - using in AVC) */
- bool output_allocated;
bool is_prepared;
- int frame_count;
- int out_buf_cnt;
- int *out_buf_ref;
-
+ GList *supported_codecs;
+ GMutex cmd_lock;
+ mediacodec_port_type_e port_type;
mediacodec_codec_type_e codec_id;
+ mc_vendor_e vendor;
- /* for gst port */
- mc_gst_port_t *gst_ports[2];
- mc_gst_core_t *gst_core;
+ void *ports[2];
+ void *core;
- /* for Decoder */
- mc_decoder_info_t *dec_info;
-
- /* for Encoder */
- mc_encoder_info_t *enc_info;
+ union
+ {
+ mc_decoder_info_t decoder;
+ mc_encoder_info_t encoder;
+ } info;
/* for process done cb */
void* user_cb[_MEDIACODEC_EVENT_TYPE_NUM];
void* user_data[_MEDIACODEC_EVENT_TYPE_NUM];
- mc_codec_spec_t g_media_codec_spec_emul[MC_MAX_NUM_CODEC];
};
/*===========================================================================================
int mc_prepare(MMHandleType mediacodec);
int mc_unprepare(MMHandleType mediacodec);
-int mc_reset(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);
int mc_set_eos_cb(MMHandleType mediacodec, mediacodec_eos_cb callback, void* user_data);
int mc_unset_eos_cb(MMHandleType mediacodec);
+int mc_set_need_data_cb(MMHandleType mediacodec, mediacodec_buffer_status_cb callback, void* user_data);
+int mc_unset_need_data_cb(MMHandleType mediacodec);
+
+
#ifdef __cplusplus
}
#endif
--- /dev/null
+
+/*
+* 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_PORT_GST_H__
+#define __TIZEN_MEDIA_CODEC_PORT_GST_H__
+
+#include <unistd.h>
+#include <tizen.h>
+#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
+
+#define GST_INIT_STRUCTURE(param) \
+ memset(&(param), 0, sizeof(param));
+
+#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
+
+/* 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 _GstMCBuffer GstMCBuffer;
+
+typedef enum {
+ BUF_SHARE_METHOD_PADDR = 0,
+ BUF_SHARE_METHOD_FD,
+ BUF_SHARE_METHOD_TIZEN_BUFFER,
+ BUF_SHARE_METHOD_FLUSH_BUFFER
+} buf_share_method_t;
+
+#ifdef Z130H
+struct ion_mmu_data {
+ int fd_buffer;
+ unsigned long iova_addr;
+ size_t iova_size;
+};
+#endif
+
+struct _mc_gst_port_t
+{
+ mc_gst_core_t *core;
+ unsigned int num_buffers;
+ unsigned int buffer_size;
+ unsigned int index;
+ bool is_allocated;
+ media_packet_h *buffers;
+ //GSem
+ GQueue *queue;
+ GMutex mutex;
+ GCond buffer_cond;
+};
+
+struct _mc_gst_core_t
+{
+ int(**vtable)();
+ const char *mime;
+ //int format;
+ gchar *format;
+ GstElement* pipeline;
+ GstElement* appsrc;
+ GstElement* capsfilter;
+ GstElement* parser;
+ GstElement* fakesink;
+ GstElement* codec;
+ MMVideoBuffer *psimgb;
+
+ GMainContext *thread_default;
+ gulong signal_handoff;
+ gint bus_whatch_id;
+ gint probe_id;
+
+ GMutex eos_mutex;
+ GMutex eos_wait_mutex;
+ GMutex drain_mutex;
+ GMutex prepare_lock;
+ GCond eos_cond;
+ GCond eos_waiting_cond;
+
+ GstState state;
+ bool output_allocated;
+ bool encoder;
+ bool video;
+ bool is_hw;
+ bool eos;
+ bool eos_waiting;
+ bool codec_config;
+ bool need_feed;
+ bool need_codec_data;
+ bool need_sync_flag;
+ int prepare_count;
+ int num_live_buffers;
+ int idr_count;
+ int sps_size;
+ int pps_size;
+
+
+ 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 _GstMCBuffer
+{
+ 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_link_elements(mc_gst_core_t *core);
+int __mc_fill_input_buffer(mc_gst_core_t *core, void *buf_data, int buf_size, 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);
+
+//int __mc_venc_link(mc_gst_core_t *core);
+//int __mc_general_link(mc_gst_core_t *core);
+
+int __mc_fill_inbuf_with_bo(mc_gst_core_t *core, void *buf_data, int buf_size, GstMCBuffer *buff);
+int __mc_fill_inbuf_with_packet(mc_gst_core_t *core, void *buf_data, int buf_size, GstMCBuffer *buff);
+
+int __mc_fill_outbuf_with_bo(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt);
+int __mc_fill_outbuf_with_packet(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt);
+int __mc_fill_outbuf_with_h264_packet(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt);
+int __mc_fill_packet_with_mm_video_buffer(mc_gst_core_t *core, void *data, int size, 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_h264dec_caps(mc_gst_core_t *core, GstCaps **caps);
+int __mc_sprddec_caps(mc_gst_core_t *core, GstCaps **caps);
+int __mc_sprdenc_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_adec_aacv12_caps(mc_gst_core_t *core, GstCaps **caps);
+int __mc_adec_mp3_caps(mc_gst_core_t *core, GstCaps **caps);
+int __mc_adec_amrnb_caps(mc_gst_core_t *core, GstCaps **caps);
+int __mc_adec_amrwb_caps(mc_gst_core_t *core, GstCaps **caps);
+int __mc_aenc_amrnb_caps(mc_gst_core_t *core, GstCaps **caps);
+
+mc_gst_core_t *mc_gst_core_new();
+void mc_gst_core_free(mc_gst_core_t *core);
+
+mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core);
+void mc_gst_port_free(mc_gst_port_t *port);
+
+mc_ret_e mc_gst_prepare(mc_handle_t *mc_handle);
+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);
+
+int _mc_check_out_bytestream (mc_gst_core_t *core, unsigned char *nal, int byte_length);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TIZEN_MEDIA_CODEC_PORT_GST_H__ */
#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
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;
#endif
typedef struct _async_queue {
- GMutex *mutex;
- GCond *condition;
+ GMutex mutex;
+ GCond condition;
GList *head;
GList *tail;
guint length;
void mc_async_queue_push(async_queue_t *async_queue, gpointer data);
+gpointer mc_async_queue_pop_forced (async_queue_t * async_queue);
+
gpointer mc_async_queue_pop(async_queue_t *async_queue);
void mc_async_queue_disable (async_queue_t *async_queue);
#include <media_codec_private.h>
-#define MC_MAX_NUM_CODEC 4
-#define MC_MAX_NUM_MAP 4
-#define MC_MAX_FACTORY_STRLEN 20
-
enum { DECODER, ENCODER };
enum { SOFTWARE, HARDWARE };
-//typedef struct _mc_codec_mimetype_t mc_codec_mimetype_t;
typedef struct _mc_codec_spec_t mc_codec_spec_t;
typedef struct _mc_codec_map_t mc_codec_map_t;
typedef struct _mc_codec_type_t mc_codec_type_t;
struct _mc_codec_spec_t
{
- mediacodec_codec_type_e mime;
+ mediacodec_codec_type_e codec_id;
mediacodec_support_type_e codec_type;
- mediacodec_support_type_e support_type;
mediacodec_port_type_e port_type;
};
struct _mc_codec_type_t
{
char *factory_name;
- media_format_mimetype_e out_format;
char *mime;
+ media_format_mimetype_e out_format;
};
struct _mc_codec_map_t
mc_codec_type_t type;
};
-static const mc_codec_spec_t spec_emul[MC_MAX_NUM_CODEC] =
+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_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST},
+ {MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW, MEDIACODEC_PORT_TYPE_GST},
+ {MEDIACODEC_H264, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_HW, MEDIACODEC_PORT_TYPE_GST},
+ {MEDIACODEC_H263, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST},
+ {MEDIACODEC_MPEG4, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST},
+ {MEDIACODEC_MPEG4, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST},
+ {MEDIACODEC_AAC_LC, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST},
+ {MEDIACODEC_AAC_LC, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST},
+ /* Extension for supporting codec @since_tizen 2.4 */
+ {MEDIACODEC_AAC_HE, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, /* added for 2.4 extension */
+ {MEDIACODEC_AAC_HE_PS, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, /* added for 2.4 extension */
+ {MEDIACODEC_MP3, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, /* added for 2.4 extension */
+ {MEDIACODEC_AMR_NB, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, /* added for 2.4 extension */
+ {MEDIACODEC_AMR_WB, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST}, /* added for 2.4 extension */
+ {MEDIACODEC_AMR_NB, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_SW, MEDIACODEC_PORT_TYPE_GST} /* added for 2.4 extension */
};
static const mc_codec_map_t encoder_map[] =
{
#ifdef ENABLE_FFMPEG_CODEC
- {MEDIACODEC_H263, SOFTWARE, {"ffenc_h263p", MEDIA_FORMAT_H263P, "video/x-raw-yuv"}},
- {MEDIACODEC_AAC, SOFTWARE, {"ffenc_aac", MEDIA_FORMAT_AAC, "audio/x-raw-int"}}
+ //{MEDIACODEC_H264, HARDWARE, {"omxh264enc", "video/x-raw", MEDIA_FORMAT_H264_HP}},
+ {MEDIACODEC_H264, HARDWARE, {"sprdenc_h264", "video/x-raw", MEDIA_FORMAT_H264_HP}},
+ {MEDIACODEC_H263, SOFTWARE, {"avenc_h263p", "video/x-raw-yuv", MEDIA_FORMAT_H263P}},
+ {MEDIACODEC_MPEG4, SOFTWARE, {"avenc_mpeg4", "video/x-raw-yuv", MEDIA_FORMAT_MPEG4_SP}},
+ {MEDIACODEC_AAC_LC, SOFTWARE, {"avenc_aac", "audio/x-raw", MEDIA_FORMAT_AAC_LC}},
+ {MEDIACODEC_AMR_NB, SOFTWARE, {"amrnbenc", "audio/x-raw", MEDIA_FORMAT_AMR_NB}} /* for 2.4 temporary - use ffmpeg */
#else
- {MEDIACODEC_H263, SOFTWARE, {"maru_h263penc", MEDIA_FORMAT_H263P, "video/x-raw-yuv"}},
- {MEDIACODEC_AAC, SOFTWARE, {"maru_aacenc", MEDIA_FORMAT_AAC, "audio/x-raw-int"}}
+ {MEDIACODEC_H264, HARDWARE, {"sprdenc_h264", "video/x-raw", MEDIA_FORMAT_H264_HP}},
+ {MEDIACODEC_H263, SOFTWARE, {"maru_h263penc", "video/x-raw-yuv", MEDIA_FORMAT_H263P}},
+ {MEDIACODEC_MPEG4, SOFTWARE, {"maru_mpeg4", "video/x-raw-yuv", MEDIA_FORMAT_MPEG4_SP}},
+ {MEDIACODEC_AAC_LC, SOFTWARE, {"avenc_aac", "audio/x-raw", MEDIA_FORMAT_AAC_LC}}, /* for 2.4 temporary - use ffmpeg instead of maru_aacenc */
+ {MEDIACODEC_AMR_NB, SOFTWARE, {"amrnbenc", "audio/x-raw", MEDIA_FORMAT_AMR_NB}} /* for 2.4 temporary - use ffmpeg instead of ?? */
#endif
};
static const mc_codec_map_t decoder_map[] =
{
#ifdef ENABLE_FFMPEG_CODEC
- {MEDIACODEC_H264, SOFTWARE, {"ffdec_h264", MEDIA_FORMAT_I420, "video/x-h264"}},
- {MEDIACODEC_AAC, SOFTWARE, {"ffdec_aac", MEDIA_FORMAT_PCM, "audio/mpeg"}}
+ {MEDIACODEC_H264, SOFTWARE, {"avdec_h264", "video/x-h264", MEDIA_FORMAT_I420}},
+ {MEDIACODEC_H264, HARDWARE, {"sprddec_h264", "video/x-h264", MEDIA_FORMAT_NV12}},
+ //{MEDIACODEC_H264, SOFTWARE, {"omxh264dec", "video/x-h264", MEDIA_FORMAT_I420}},
+ {MEDIACODEC_MPEG4, SOFTWARE, {"avdec_mpeg4", "video/mpeg", MEDIA_FORMAT_I420}},
+ {MEDIACODEC_AAC_LC, SOFTWARE, {"avdec_aac", "audio/mpeg", MEDIA_FORMAT_PCM}},
+ {MEDIACODEC_AAC_HE, SOFTWARE, {"avdec_aac", "audio/mpeg", MEDIA_FORMAT_PCM}}, /* added for 2.4 extension */
+ {MEDIACODEC_AAC_HE_PS, SOFTWARE, {"avdec_aac", "audio/mpeg", MEDIA_FORMAT_PCM}}, /* added for 2.4 extension */
+ {MEDIACODEC_MP3, SOFTWARE, {"avdec_mp3", "audio/mpeg", MEDIA_FORMAT_PCM}}, /* added for 2.4 extension */
+ {MEDIACODEC_AMR_NB, SOFTWARE, {"avdec_amrnb", "audio/AMR", MEDIA_FORMAT_PCM}}, /* added for 2.4 extension */
+ {MEDIACODEC_AMR_WB, SOFTWARE, {"avdec_amrwb", "audio/AMR-WB", MEDIA_FORMAT_PCM}} /* added for 2.4 extension */
#else
- {MEDIACODEC_H264, SOFTWARE, {"maru_h264dec", MEDIA_FORMAT_I420, "video/x-h264"}},
- {MEDIACODEC_AAC, SOFTWARE, {"maru_aacdec", MEDIA_FORMAT_PCM, "audio/mpeg"}}
+ {MEDIACODEC_H264, SOFTWARE, {"avdec_h264", "video/x-h264", MEDIA_FORMAT_I420}},
+ {MEDIACODEC_H264, HARDWARE, {"omxh264dec", "video/x-h264", MEDIA_FORMAT_NV12}},
+ {MEDIACODEC_MPEG4, SOFTWARE, {"maru_mpeg4", "video/mpeg", MEDIA_FORMAT_I420}},
+ {MEDIACODEC_AAC_LC, SOFTWARE, {"avdec_aac", "audio/mpeg", MEDIA_FORMAT_PCM}}, /* for 2.4 temporary - use ffmpeg instead of maru_aacdec */
+ {MEDIACODEC_AAC_HE, SOFTWARE, {"avdec_aac", "audio/mpeg", MEDIA_FORMAT_PCM}}, /* for 2.4 temporary - use ffmpeg instead of maru_aacdec */
+ {MEDIACODEC_AAC_HE_PS, SOFTWARE, {"avdec_aac", "audio/mpeg", MEDIA_FORMAT_PCM}}, /* for 2.4 temporary - use ffmpeg instead of maru_aacdec */
+ {MEDIACODEC_MP3, SOFTWARE, {"avdec_mp3", "audio/mpeg", MEDIA_FORMAT_PCM}},
+ {MEDIACODEC_AMR_NB, SOFTWARE, {"avdec_amrnb", "audio/AMR", MEDIA_FORMAT_PCM}},
+ {MEDIACODEC_AMR_WB, SOFTWARE, {"avdec_amrwb", "audio/AMR-WB", MEDIA_FORMAT_PCM}}
#endif
};
-
#ifdef __cplusplus
}
#endif
CODEC_RET_UNKNOWN_ERR = -100,
} CodecRet;
-typedef struct mc_sem mc_sem;
+typedef struct _mc_sem_t mc_sem_t;
-struct mc_sem
+struct _mc_sem_t
{
- GCond *condition;
- GMutex *mutex;
+ GCond cond;
+ GMutex mutex;
int counter;
};
void *mc_aligned_malloc(int size, int alignment);
void mc_aligned_free(void *mem);
-mc_sem *mc_sem_new();
-void mc_sem_free(mc_sem *sem);
-void mc_sem_down(mc_sem *sem);
-void mc_sem_up(mc_sem *sem);
+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) \
if ( x ) \
Name: capi-media-codec
Summary: A Media Codec library in Tizen Native API
-Version: 0.1.1
+Version: 0.4.0
Release: 0
Group: Multimedia/API
License: Apache-2.0
BuildRequires: pkgconfig(gstreamer-plugins-base-1.0)
BuildRequires: pkgconfig(gstreamer-app-1.0)
BuildRequires: pkgconfig(libdri2)
-
+BuildRequires: pkgconfig(capi-system-info)
+%if "%{?tizen_target_name}"=="Z130H"
+#!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
%description
-A Media Player library in Tizen Native API
+
%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
-%devel_desc
+
%prep
%setup -q
%build
+%if "%{?tizen_target_name}"=="Z130H"
+export CFLAGS="$CFLAGS -DZ130H"
+%endif
%if 0%{?sec_build_binary_debug_enable}
export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
#include <media_codec.h>
#include <media_codec_private.h>
#include <media_codec_port.h>
+#include <system_info.h>
#include <dlog.h>
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 int __mediacodec_check_system_info_feature_supported();
+static gboolean __mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data);
+
/*
* Internal Implementation
return TRUE;
}
+static int __mediacodec_check_system_info_feature_supported()
+{
+ bool bValue = false;
+ int nRetVal = false;
+
+ nRetVal = system_info_get_platform_bool("http://tizen.org/feature/mediacodec", &bValue);
+
+ if ( nRetVal != SYSTEM_INFO_ERROR_NONE )
+ {
+ LOGE("[%s] SYSTEM_INFO_ERROR : ", __FUNCTION__);
+ return false;
+ }
+
+ if ( false == bValue )
+ {
+ LOGI("system_info_get_platform_bool returned Unsupported feature capability\n");
+ }
+ else
+ {
+ LOGI("system_info_get_platform_bool returned Supported status feature\n");
+ }
+
+ return bValue;
+}
+
+/*
+ * Public Implementation
+ */
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;
}
else
{
- //handle->state = MEDIACODEC_STATE_EXCUTE;
return MEDIACODEC_ERROR_NONE;
}
}
}
else
{
- //handle->state = MEDIACODEC_STATE_EXCUTE;
+ return MEDIACODEC_ERROR_NONE;
+ }
+}
+
+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
+ {
+ handle->state = MEDIACODEC_STATE_IDLE;
+ 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;
}
}
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;
+ MEDIACODEC_STATE_CHECK(handle, MEDIACODEC_STATE_IDLE);
+
+ handle->supported_codec_cb = callback;
+ handle->supported_codec_cb_userdata = user_data;
+
+ LOGD("set supported_codec_cb(%p)", callback);
+ _mediacodec_foreach_supported_codec(handle->mc_handle, callback, handle);
+
+ return MEDIACODEC_ERROR_NONE;
+
+}
+
static gboolean __mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data)
{
if(user_data == NULL || pkt == NULL)
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;
+}
+
--- /dev/null
+/*
+* 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;
+}
+
+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 *nal )
+{
+ int nal_length = 0;
+ unsigned char val, zero_count;
+ unsigned char *pNal = data;
+ int i = 0;
+ int index = 0;
+
+ zero_count = 0;
+
+ val = pNal[index++];
+ while (!val)
+ {
+ if ((zero_count == 2 || zero_count == 3) && val == 1)
+ break;
+ zero_count++;
+
+ val = pNal[index++];
+
+ }
+
+ nal[nal_length++] = 0;
+ nal[nal_length++] = 0;
+ nal[nal_length++] = 0;
+ nal[nal_length++] = 1;
+ zero_count = 0;
+
+ while (1)
+ {
+ if (index >= size)
+ return nal_length;
+
+ val = pNal[index++];
+
+ if (!val)
+ zero_count++;
+ else {
+ if ((zero_count == 2 || zero_count == 3 || zero_count == 4) && (val == 1))
+ break;
+ else {
+ for (i = 0; i<zero_count; i++)
+ nal[nal_length++] = 0;
+ nal[nal_length++] = val;
+ zero_count = 0;
+ }
+ }
+
+ }
+
+ return nal_length;
+}
+
+int __mc_decode_sps(mc_bitstream_t *pstream, int *width, int *height)
+{
+ int ret = MC_ERROR_NONE;
+ unsigned int tmp = 0;
+ unsigned int syntax = 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_bytestream (media_packet_h pkt, unsigned char *nal, int byte_length, int *width, int *height)
+{
+ int ret = MC_ERROR_NONE;
+ int stacked_length = 0;
+ int nal_length = 0;
+ unsigned int syntax = 0;
+ unsigned char sps[100];
+ unsigned char pps[100];
+ int sps_size = 0;
+ int pps_size = 0;
+ int idr = 0;
+ unsigned char tmp[1000000];
+
+ mc_bitstream_t pstream;
+
+ while (1)
+ {
+ nal_length = __mc_bytestream_to_nal( nal + stacked_length, byte_length - stacked_length, tmp);
+
+ 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("SPS is found");
+ if( (ret = __mc_decode_sps ( &pstream, NULL, NULL )) != MC_ERROR_NONE)
+ return ret;
+ sps_size = nal_length;
+ break;
+ case NAL_PICTURE_PARAMETER_SET:
+ LOGD("PPS is found");
+ pps_size = nal_length;
+ break;
+ case NAL_SLICE_IDR:
+ LOGD ("IDR is found");
+ idr++;
+ break;
+ default:
+ LOGD ("%x nal_unit_type is detected");
+ break;
+ }
+
+ stacked_length += nal_length;
+
+ if ( stacked_length >= byte_length )
+ break;
+ }
+
+ if ( sps_size > 0 && pps_size > 0 ) {
+ memcpy(tmp, sps, sps_size);
+ memcpy(tmp + sps_size, pps, pps_size);
+ media_packet_set_codec_data( pkt, tmp, sps_size + pps_size);
+ }
+ else {
+ LOGE("doesn't contain codec_data(sps[%d],pps[%d],idr[%d])", sps, pps, idr);
+ ret = MC_INVALID_IN_BUF;
+ }
+
+ return ret;
+}
+
#include <media_codec.h>
#include <media_codec_private.h>
#include <media_codec_port.h>
-//#include <media_codec_port_gst.h> //to avoid build error until this code is not compatible with gstreamer 1.0
+#include <media_codec_port_gst.h>
#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 int sort(gpointer p1, gpointer p2)
+{
+ int a, b;
+
+ a = GPOINTER_TO_INT(p1);
+ b = GPOINTER_TO_INT(p2);
+
+ return (a > b ? 1 : a == b ? 0 : 1);
+}
int mc_create(MMHandleType *mediacodec)
{
mc_handle_t* new_mediacodec = NULL;
int ret = MC_ERROR_NONE;
+ int i;
+ int support_list = sizeof(spec_emul) / sizeof(spec_emul[0]);
+ GList *list = NULL;
/* alloc mediacodec structure */
new_mediacodec = (mc_handle_t*)g_malloc(sizeof(mc_handle_t));
new_mediacodec->is_encoder = false;
new_mediacodec->is_video = false;
new_mediacodec->is_hw = true;
- new_mediacodec->is_codec_config = false;
- new_mediacodec->output_allocated = false;
new_mediacodec->is_prepared = false;
new_mediacodec->codec_id = MEDIACODEC_NONE;
- new_mediacodec->gst_ports[0] = NULL;
- new_mediacodec->gst_ports[1] = NULL;
+ new_mediacodec->ports[0] = NULL;
+ new_mediacodec->ports[1] = NULL;
+
+ new_mediacodec->core = NULL;
+
+ for(i=0; i<support_list; i++)
+ {
+ new_mediacodec->supported_codecs = g_list_append(new_mediacodec->supported_codecs, GINT_TO_POINTER(spec_emul[i].codec_id));
+ }
+ new_mediacodec->supported_codecs = g_list_sort(new_mediacodec->supported_codecs, sort);
+
+ gpointer p1;
+ for(i=0; i<support_list; i++)
+ {
+ p1 = g_list_nth_data(list, i);
+ LOGD("list_sort :%d(%x)",i, GPOINTER_TO_INT(p1));
+ }
- new_mediacodec->gst_core = NULL;
- new_mediacodec->dec_info = NULL;
- new_mediacodec->enc_info = NULL;
- memcpy(new_mediacodec->g_media_codec_spec_emul, spec_emul, sizeof(mc_codec_spec_t)*MC_MAX_NUM_CODEC);
+ g_mutex_init(&new_mediacodec->cmd_lock);
*mediacodec = (MMHandleType)new_mediacodec;
return ret;
- // TO DO
ERROR:
if ( new_mediacodec )
{
- // TO DO
- // If we need destroy and release for others (cmd, mutex..)
free(new_mediacodec);
new_mediacodec = NULL;
- return MC_INVALID_ARG;
}
- return ret;
+ return MC_INVALID_ARG;
}
int mc_destroy(MMHandleType mediacodec)
return MC_INVALID_ARG;
}
- if(mc_handle->gst_core != NULL)
+ MEDIACODEC_CMD_LOCK( mediacodec );
+
+ LOGD("mediacodec : %p", mediacodec);
+
+ if(mc_handle->core != NULL)
{
- #if 0 //to avoid build error until this code is not compatible with gstreamer 1.0
- if(mc_gst_unprepare(mc_handle->gst_core) != MC_ERROR_NONE)
+ if(mc_gst_unprepare(mc_handle) != MC_ERROR_NONE)
{
LOGE("mc_gst_unprepare() failed");
return MC_ERROR;
}
- #endif
- // mc_gst_core_free(mc_handle->gst_core); //to avoid build error until this code is not compatible with gstreamer 1.0
- mc_handle->gst_core = NULL;
}
mc_handle->is_prepared = false;
+ g_list_free(mc_handle->supported_codecs);
- g_free(mc_handle->dec_info);
- g_free(mc_handle->enc_info);
-
+ MEDIACODEC_CMD_UNLOCK( mediacodec );
/* free mediacodec structure */
if(mc_handle) {
{
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]);
+ int i;
if (!mc_handle)
{
return MC_INVALID_ARG;
}
- // Mandatory setting
+ /* Mandatory setting */
if ( !GET_IS_ENCODER(flags) && !GET_IS_DECODER(flags) )
{
LOGE("should be encoder or decoder\n");
return MC_PARAM_ERROR;
}
- if(!_mc_check_is_supported(mc_handle, codec_id, flags))
+ for(i = 0; i < support_list; i++)
+ {
+ if((codec_id == spec_emul[i].codec_id) && (flags == spec_emul[i].codec_type))
+ {
+ break;
+ }
+ }
+
+ LOGD("support_list : %d, i : %d", support_list, i);
+
+ if(i == support_list)
return MC_NOT_SUPPORTED;
+ mc_handle->port_type = spec_emul[i].port_type;
+
mc_handle->is_encoder = GET_IS_ENCODER(flags) ? 1 : 0;
mc_handle->is_hw = GET_IS_HW(flags) ? 1 : 0;
mc_handle->codec_id = codec_id;
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;
}
return MC_PARAM_ERROR;
MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && !mc_handle->is_encoder,
- MC_PARAM_ERROR,"MEDIACODEC_ERROR_INVALID_PARAMETER");
+ MEDIACODEC_ERROR_INVALID_PARAMETER,"MEDIACODEC_ERROR_INVALID_PARAMETER");
- if (mc_handle->dec_info == NULL)
- {
- mc_handle->dec_info = g_new0(mc_decoder_info_t, 1);
- }
-
- mc_handle->dec_info->width = width;
- mc_handle->dec_info->height = height;
+ 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;
}
return MC_PARAM_ERROR;
MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && mc_handle->is_video && mc_handle->is_encoder,
- MC_PARAM_ERROR, "MEDIACODEC_ERROR_INVALID_PARAMETER");
+ MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER");
- if(mc_handle->enc_info == NULL)
- {
- mc_handle->enc_info = g_new0(mc_encoder_info_t, 1);
- }
-
- mc_handle->enc_info->frame_width = width;
- mc_handle->enc_info->frame_height = height;
- mc_handle->enc_info->fps = fps;
- mc_handle->enc_info->bitrate = target_bits;
+ 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;
}
return MC_PARAM_ERROR;
MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && !mc_handle->is_encoder,
- MC_PARAM_ERROR, "MEDIACODEC_ERROR_INVALID_PARAMETER");
-
- if (mc_handle->dec_info == NULL)
- {
- mc_handle->dec_info = g_new0(mc_decoder_info_t, 1);
- }
+ MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER");
- mc_handle->dec_info->samplerate = samplerate;
- mc_handle->dec_info->channel = channel;
- mc_handle->dec_info->bit = bit;
+ mc_handle->info.decoder.samplerate = samplerate;
+ mc_handle->info.decoder.channel = channel;
+ mc_handle->info.decoder.bit = bit;
mc_handle->is_prepared = true;
return MC_PARAM_ERROR;
MEDIACODEC_CHECK_CONDITION(mc_handle->codec_id && !mc_handle->is_video && mc_handle->is_encoder,
- MC_PARAM_ERROR, "MEDIACODEC_ERROR_INVALID_PARAMETER");
-
- if(mc_handle->enc_info == NULL)
- {
- mc_handle->enc_info = g_new0(mc_encoder_info_t, 1);
- }
+ MEDIACODEC_ERROR_INVALID_PARAMETER, "MEDIACODEC_ERROR_INVALID_PARAMETER");
- mc_handle->enc_info->samplerate = samplerate;
- mc_handle->enc_info->channel = channel;
- mc_handle->enc_info->bit = bit;
- mc_handle->enc_info->bitrate = bitrate;
+ mc_handle->info.encoder.samplerate = samplerate;
+ mc_handle->info.encoder.channel = channel;
+ mc_handle->info.encoder.bit = bit;
+ mc_handle->info.encoder.bitrate = bitrate;
mc_handle->is_prepared = true;
int mc_prepare(MMHandleType mediacodec)
{
int ret = MC_ERROR_NONE;
-#if 0 //to avoid build error until this code is not compatible with gstreamer 1.0
mc_handle_t* mc_handle = (mc_handle_t*) mediacodec;
- media_format_mimetype_e mimetype;
if (!mc_handle)
{
if(!mc_handle->is_prepared)
return MC_NOT_INITIALIZED;
+ MEDIACODEC_CMD_LOCK( mediacodec );
+
/* setting core details */
switch ( mc_handle->port_type )
{
case MEDIACODEC_PORT_TYPE_GENERAL:
{
- /*
- //!!!! need to set data to omx/gen core need to seperate
- mc_handle->gen_core->output_fmt = mc_handle->output_fmt;
- mc_handle->gen_core->encoder = mc_handle->is_encoder;
-
- if(mc_handle->is_encoder)
- {
- mc_encoder_info_t *info;
-
- info = mc_handle->enc_info;
- mc_handle->gen_core->enc_info = mc_handle->enc_info;
-
- media_format_set_video_info(mc_handle->output_fmt, mc_handle->mimetype, info->frame_width, info->frame_height, info->bitrate, 0);
- }
- else
- {
- mc_decoder_info_t *info;
-
- info = mc_handle->dec_info;
- mc_handle->gen_core->dec_info = mc_handle->dec_info;
- media_format_set_video_info(mc_handle->output_fmt, mc_handle->mimetype, info->width, info->height, 0, 0);
- }
-
- ret = mc_general_init(mc_handle->gen_core);
- */
}
break;
case MEDIACODEC_PORT_TYPE_OMX:
{
- //et = mc_omx_init(mc_handle);
- //ret = mc_omx_create_handle(mc_handle);
}
break;
case MEDIACODEC_PORT_TYPE_GST:
{
-
- int i;
- int codec_list;
- static const mc_codec_map_t *codec_map;
-
- mc_gst_core_t* new_core = mc_gst_core_new();
- // !!!! null check
-
- new_core->encoder = mc_handle->is_encoder;
- new_core->is_hw = mc_handle->is_hw;
- new_core->video = mc_handle->is_video;
- new_core->codec_id = mc_handle->codec_id;
-
- /* setting internal callbacks */
- for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER ; i++)
- {
- LOGD("copy cb function [%d]", 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]);
- }
- }
-
- if(new_core->output_fmt == NULL)
- {
- if(media_format_create(&new_core->output_fmt) != MEDIA_FORMAT_ERROR_NONE)
- {
- LOGE("media format create failed");
- }
- LOGD("pkt_fmt is allocated");
- }
-
- if(new_core->encoder)
- {
- codec_list = sizeof(encoder_map) / sizeof(encoder_map[0]);
- codec_map = encoder_map;
- }
- else
- {
- codec_list = sizeof(decoder_map) / sizeof(decoder_map[0]);
- codec_map = decoder_map;
- }
-
- for(i = 0; i < codec_list; i++)
- {
- if((new_core->codec_id == codec_map[i].id) && (new_core->is_hw == codec_map[i].hardware))
- break;
- }
-
- new_core->factory_name = codec_map[i].type.factory_name;
-
- mimetype = codec_map[i].type.out_format;
-
- new_core->mime = codec_map[i].type.mime;
-
- LOGD("factory name : %s, output_fmt : %x mime : %s", new_core->factory_name, mimetype, new_core->mime);
-
- if(new_core->factory_name == NULL || mimetype == MEDIA_FORMAT_MAX)
- {
- LOGE("Cannot find output format");
- return MC_NOT_SUPPORTED;
- }
-
- if(mc_handle->is_encoder)
- {
- mc_encoder_info_t *info;
-
- info = mc_handle->enc_info;
- new_core->enc_info = mc_handle->enc_info;
-
- if (new_core->video)
- {
- media_format_set_video_mime(new_core->output_fmt, mimetype);
- media_format_set_video_width(new_core->output_fmt, info->frame_width);
- media_format_set_video_height(new_core->output_fmt, info->frame_height);
- media_format_set_video_avg_bps(new_core->output_fmt, info->bitrate);
- }
- else
- {
- media_format_set_audio_mime(new_core->output_fmt, mimetype);
- media_format_set_audio_channel(new_core->output_fmt, info->channel);
- media_format_set_audio_samplerate(new_core->output_fmt, info->samplerate);
- media_format_set_audio_bit(new_core->output_fmt, info->bit);
- media_format_set_audio_avg_bps(new_core->output_fmt, info->bitrate);
- }
-
- }
- else
- {
- mc_decoder_info_t *info;
-
- info = mc_handle->dec_info;
- new_core->dec_info = mc_handle->dec_info;
- if (new_core->video)
- {
- media_format_set_video_mime(new_core->output_fmt, mimetype);
- media_format_set_video_width(new_core->output_fmt, info->width);
- media_format_set_video_height(new_core->output_fmt, info->height);
- }
- else
- {
- media_format_set_audio_mime(new_core->output_fmt, mimetype);
- media_format_set_audio_channel(new_core->output_fmt, info->channel);
- media_format_set_audio_samplerate(new_core->output_fmt, info->samplerate);
- media_format_set_audio_bit(new_core->output_fmt, info->bit);
- }
-
- }
-
- LOGD("is_encoder (%d) is_video (%d)", new_core->encoder, new_core->video);
- mc_handle->gst_core = new_core;
- //mc_gst_prepare(mc_handle->gst_core); //to avoid build error until this code is not compatible with gstreamer 1.0
-
-
- }
-
+ mc_gst_prepare(mc_handle);
+ }
break;
default:
break;
}
-#endif
+
+ MEDIACODEC_CMD_UNLOCK( mediacodec );
return ret;
}
return MC_INVALID_ARG;
}
+ MEDIACODEC_CMD_LOCK( mediacodec );
+
/* deinit core details */
switch ( mc_handle->port_type )
{
case MEDIACODEC_PORT_TYPE_GENERAL:
{
- //ret = mc_general_deinit(mc_handle->gen_core);
}
break;
case MEDIACODEC_PORT_TYPE_OMX:
{
- //ret = mc_omx_deinit(mc_handle);
}
break;
case MEDIACODEC_PORT_TYPE_GST:
{
- // ret = mc_gst_unprepare(mc_handle->gst_core); //to avoid build error until this code is not compatible with gstreamer 1.0
-
- if(mc_handle->gst_core != NULL)
- {
- // mc_gst_core_free(mc_handle->gst_core); //to avoid build error until this code is not compatible with gstreamer 1.0
- mc_handle->gst_core = NULL;
- }
+ ret = mc_gst_unprepare(mc_handle);
}
break;
break;
}
+ MEDIACODEC_CMD_UNLOCK( mediacodec );
+
return ret;
}
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;
- if (!mc_handle)
- {
+ if (!mc_handle) {
LOGE("fail invaild param\n");
return MC_INVALID_ARG;
}
-
+#if 1
+ if ( mc_handle->is_video) {
+ if ((ret = mc_sniff_bitstream(mc_handle, inbuf)) != MC_ERROR_NONE ) {
+ return MC_INVALID_IN_BUF;
+ }
+ }
+#else
ret = media_packet_get_buffer_size(inbuf, &buf_size);
if (ret != MEDIA_PACKET_ERROR_NONE)
{
LOGE("invaild input buffer");
return MC_INVALID_IN_BUF;
}
+
ret = media_packet_get_buffer_data_ptr(inbuf, &buf_data);
if (ret != MEDIA_PACKET_ERROR_NONE)
{
return MC_INVALID_IN_BUF;
}
- if((buf_data == NULL) || (buf_size == 0))
+ ret = media_packet_is_end_of_stream(inbuf, &eos);
+ if (ret != MEDIA_PACKET_ERROR_NONE)
{
LOGE("invaild input buffer");
return MC_INVALID_IN_BUF;
}
- switch ( mc_handle->port_type )
+ if(!eos)
{
- case MEDIACODEC_PORT_TYPE_GENERAL:
+ if((buf_data == NULL) || (buf_size == 0))
{
- //ret = mc_general_process_input(mc_handle->gen_core, inbuf, timeOutUs);
+ LOGE("invaild input buffer");
+ return MC_INVALID_IN_BUF;
}
+ }
+#endif
+ MEDIACODEC_CMD_LOCK( mediacodec );
+
+ switch ( mc_handle->port_type )
+ {
+ case MEDIACODEC_PORT_TYPE_GENERAL:
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->gst_core, inbuf, timeOutUs); //to avoid build error until this code is not compatible with gstreamer 1.0
+ ret = mc_gst_process_input(mc_handle, inbuf, timeOutUs);
}
break;
break;
}
+ MEDIACODEC_CMD_UNLOCK( mediacodec );
+
return ret;
}
return MC_INVALID_ARG;
}
+ MEDIACODEC_CMD_LOCK( mediacodec );
+
/* setting core details */
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:
+ break;
+
+ case MEDIACODEC_PORT_TYPE_GST:
{
- //ret = mc_omx_get_output(mc_handle, outbuf, timeOutUs);
+ ret = mc_gst_get_output(mc_handle, outbuf, timeOutUs);
}
break;
+ default:
+ break;
+ }
+
+ MEDIACODEC_CMD_UNLOCK( mediacodec );
+
+ return ret;
+}
+
+int mc_flush_buffers(MMHandleType mediacodec)
+{
+ 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;
+ }
+
+ MEDIACODEC_CMD_LOCK( mediacodec );
+
+ /* setting core details */
+ switch ( mc_handle->port_type )
+ {
+ case MEDIACODEC_PORT_TYPE_GENERAL:
+ break;
+
+ case MEDIACODEC_PORT_TYPE_OMX:
+ break;
+
case MEDIACODEC_PORT_TYPE_GST:
{
- //ret = mc_gst_get_output(mc_handle->gst_core, outbuf, timeOutUs); //to avoid build error until this code is not compatible with gstreamer 1.0
+ ret = mc_gst_flush_buffers(mc_handle);
}
break;
break;
}
+ MEDIACODEC_CMD_UNLOCK( mediacodec );
+ return ret;
+}
+
+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;
+ static const mc_codec_map_t *codec_map;
+ int i;
+
+ *support_type = 0;
+
+ if (!mc_handle)
+ {
+ LOGE("fail invaild param\n");
+ return MC_INVALID_ARG;
+ }
+
+ 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(codec_type == codec_map[i].id)
+ {
+ if(codec_map[i].hardware)
+ *support_type |=MEDIACODEC_SUPPORT_TYPE_HW;
+ else
+ *support_type |=MEDIACODEC_SUPPORT_TYPE_SW;
+ }
+
+ }
+
return ret;
}
return ret;
}
+
int mc_unset_empty_buffer_cb(MMHandleType mediacodec)
{
mc_handle_t* mc_handle = (mc_handle_t*) mediacodec;
return ret;
}
+
int mc_unset_fill_buffer_cb(MMHandleType mediacodec)
{
mc_handle_t* mc_handle = (mc_handle_t*) 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)
{
LOGE("fail invaild param\n");
- return FALSE;
+ return MC_INVALID_ARG;
+ }
+
+ 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;
}
- for (i = 0; i < MC_MAX_NUM_CODEC; i++)
+ return ret;
+}
+
+int mc_unset_buffer_status_cb(MMHandleType mediacodec)
+{
+ mc_handle_t* mc_handle = (mc_handle_t*) mediacodec;
+
+ if (!mc_handle)
{
- if (mc_handle->g_media_codec_spec_emul[i].mime == codec_id)
+ 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)\n", 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 MC_ERROR_NONE;
+}
+
+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)
{
- if (mc_handle->g_media_codec_spec_emul[i].codec_type & (flags & 0x3))
+ tmp = g_list_nth_data(mc_handle->supported_codecs, codecs_num -1);
+ if(tmp)
{
- if (mc_handle->g_media_codec_spec_emul[i].support_type & (flags & 0xC))
+ if(!callback(GPOINTER_TO_INT(tmp), user_data))
{
- mc_handle->port_type = mc_handle->g_media_codec_spec_emul[i].port_type;
- LOGD("port type : %d", mc_handle->port_type);
- return TRUE;
+ ret = MEDIACODEC_ERROR_INTERNAL;
+ goto CALLBACK_ERROR;
}
}
+ codecs_num--;
+ }
+ if(!callback(-1, user_data))
+ {
+ ret = MEDIACODEC_ERROR_INTERNAL;
+ goto CALLBACK_ERROR;
}
}
- return FALSE;
+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;
+ 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_bytestream (pkt, buf_data, (int)buf_size, NULL, NULL);
+ }
+
+ return ret;
+}
+
+int mc_sniff_mpeg4_bitstream(mc_handle_t *handle, media_packet_h pkt)
+{
+ int ret = MC_ERROR_NONE;
+ return ret;
+}
+
+int mc_sniff_h263_bitstream(mc_handle_t *handle, media_packet_h pkt)
+{
+ int ret = MC_ERROR_NONE;
+ return ret;
+}
+
+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);
+ }
+
+ 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;
}
--- /dev/null
+/*
+* 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 <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlog.h>
+#include <media_codec_queue.h>
+#include <media_codec_port_gst.h>
+#include <media_codec_util.h>
+
+#include <gst/gst.h>
+#include <gst/gstelement.h>
+#include <gst/app/gstappsrc.h>
+
+#ifdef Z130H
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/ion.h>
+#endif
+
+#define GST_MC_EVENT_CODEC_DATA "GstEventCodecData"
+/*
+* 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_destroy_pipeline(mc_gst_core_t *core);
+static void __mc_gst_buffer_add (GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data);
+static int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data);
+static void _mc_gst_update_caps(mc_gst_core_t *core, media_packet_h pkt, GstCaps **caps);
+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_gstbuffer_to_media_packet(mc_gst_core_t* core, GstBuffer* buffer);
+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 MMVideoBuffer* __mc_gst_make_tbm_buffer(mc_gst_core_t* core, media_packet_h pkt);
+static GstPadProbeReturn event_probe_cb(GstObject *pad, GstPadProbeInfo *info, 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 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 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 Z130H
+static int __tbm_get_physical_addr_bo(tbm_bo_handle tbm_bo_handle_fd_t, int* phy_addr, int* phy_size);
+#endif
+static void _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 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);
+
+/*for test */
+static int count;
+static int input_count;
+#define GST_TYPE_MC_BUFFER (__mc_gst_buffer_get_type())
+
+/* SPRD Decoder */
+int(*vdec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_vdec_caps};
+#ifdef Z130H
+/* SPRD H.264 Decoder */
+int(*vdec_h264_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_packet_with_mm_video_buffer, &__mc_sprddec_caps};
+/* SPRD H.264 Encoder */
+int(*venc_vtable[])() = {&__mc_fill_inbuf_with_bo, &__mc_fill_outbuf_with_packet, &__mc_sprdenc_caps};
+#else
+/* M0 H.264 Decoder */
+int(*vdec_h264_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_packet_with_mm_video_buffer, &__mc_h264dec_caps};
+/* M0 H.264 Encoder */
+int(*venc_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_h264_packet, &__mc_venc_caps};
+#endif
+/* AAC_LC Encoder */
+int(*aenc_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_aenc_caps};
+/* AAC_LC Deocder */
+int(*adec_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_adec_caps};
+int(*adec_aacv12_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_adec_aacv12_caps};
+/* MP3 Deocder */
+int(*adec_mp3_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_adec_mp3_caps};
+/* AMR-NB Deocder */
+int(*adec_amrnb_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_adec_amrnb_caps};
+/* AMR-WB Deocder */
+int(*adec_amrwb_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_adec_amrwb_caps};
+/* AMR-NB Deocder */
+int(*aenc_amrnb_vtable[])() = {&__mc_fill_inbuf_with_packet, &__mc_fill_outbuf_with_packet, &__mc_aenc_amrnb_caps};
+
+
+/*
+ * mc_gst_object functions
+*/
+int __mc_fill_input_buffer(mc_gst_core_t *core, void *buf_data, int buf_size, GstMCBuffer *buff)
+{
+ return core->vtable[fill_inbuf](core, buf_data, buf_size, buff);
+}
+
+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);
+}
+
+int __mc_create_caps(mc_gst_core_t *core, GstCaps **caps)
+{
+ return core->vtable[create_caps](core, caps);
+}
+
+int __mc_fill_inbuf_with_bo(mc_gst_core_t *core, void *buf_data, int buf_size, GstMCBuffer *mc_buffer)
+{
+ int ret = MC_ERROR_NONE;
+
+ MMVideoBuffer *imgb = NULL;
+ guint n;
+
+ mc_buffer->has_imgb = true;
+
+
+ imgb = __mc_gst_make_tbm_buffer(core, mc_buffer->pkt);
+
+ if( imgb != NULL ) {
+ gst_buffer_prepend_memory(mc_buffer->buffer,
+ gst_memory_new_wrapped(GST_MEMORY_FLAG_READONLY, imgb, sizeof(*imgb), 0,
+ sizeof(*imgb), mc_buffer, (GDestroyNotify)gst_mediacodec_buffer_finalize));
+ LOGD("scmn_imgb is appended, %d, %d", sizeof(*imgb), gst_buffer_n_memory(mc_buffer->buffer));
+ }
+
+ 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;
+}
+
+int __mc_fill_inbuf_with_packet(mc_gst_core_t *core, void *buf_data, int buf_size, GstMCBuffer *mc_buffer)
+{
+ int ret = MC_ERROR_NONE;
+
+ mc_buffer->has_imgb = false;
+
+ 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_outbuf_with_bo(mc_gst_core_t *core, void *data, int size, media_packet_h* out_pkt)
+{
+ int i = 0;;
+ int bo_num = 0;
+
+ g_return_val_if_fail (core != NULL, MC_PARAM_ERROR);
+
+ MMVideoBuffer *imgb = NULL;
+ tbm_surface_h tsurf = NULL;
+ mc_decoder_info_t *codec_info = (mc_decoder_info_t *)core->codec_info;
+#ifdef TBM_API_CHANGE
+ tbm_surface_info_s tsurf_info;
+ memset(&tsurf_info, 0x0, sizeof(tbm_surface_info_s));
+#endif
+
+ /* create tbm surface */
+ for (i = 0; i < MM_VIDEO_BUFFER_PLANE_MAX; i++)
+ {
+ if (imgb->handle.bo[i])
+ {
+ bo_num++;
+#ifdef TBM_API_CHANGE
+ tsurf_info.planes[i].stride = imgb->stride_width[i];
+#endif
+ }
+ }
+
+ 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 = imgb->stride_width[i];
+ tsurf_info.planes[i].size = imgb->stride_width[i] * imgb->stride_height[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.size += tsurf_info.planes[i].size;
+ }
+
+ tsurf = tbm_surface_internal_create_with_bos(&tsurf_info, (tbm_bo *)imgb->handle.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 *)imgb->handle.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("!!!! create_gst_buffer = %p", *out_pkt);
+ }
+
+ return MC_ERROR_NONE;
+}
+
+
+int __mc_fill_packet_with_mm_video_buffer(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt)
+{
+ void* pkt_data = NULL;
+ MMVideoBuffer *imgb = NULL;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+ int i;
+ int bo_num = 0;
+ mc_decoder_info_t *codec_info = (mc_decoder_info_t *)core->codec_info;
+
+ g_return_val_if_fail (core != NULL, MC_PARAM_ERROR);
+
+ imgb = (MMVideoBuffer *)data;
+
+ LOGD("buf_share_method %d", imgb->type);
+
+ LOGD("a[0] : %p, a[1] : %p, p[0] : %p, p[1] : %p",
+ imgb->data[0], imgb->data[1], imgb->handle.paddr[0], imgb->handle.paddr[1]);
+ LOGD("s[0]:%d, e[0]:%d, w[0]:%d, h[0]:%d",
+ imgb->stride_width[0],imgb->stride_height[0],imgb->width[0], imgb->height[0]);
+
+ media_packet_create_alloc(core->output_fmt, __mc_output_buffer_finalize_cb, core, out_pkt);
+
+ if ( imgb->type == MM_VIDEO_BUFFER_TYPE_PHYSICAL_ADDRESS ) {
+ media_packet_set_buffer_size(*out_pkt, imgb->width[0]*imgb->height[0]*3/2);
+ media_packet_get_buffer_data_ptr(*out_pkt, &pkt_data);
+
+ __csc_tiled_to_linear_crop(pkt_data, imgb->data[0],
+ imgb->stride_width[0], imgb->stride_height[0], 0,0,0,0);
+ __csc_tiled_to_linear_crop(pkt_data+imgb->stride_width[0]*imgb->stride_height[0],
+ imgb->data[1], imgb->stride_width[0], imgb->stride_height[0]/2, 0,0,0,0);
+ }
+ else if ( imgb->type == MM_VIDEO_BUFFER_TYPE_DMABUF_FD ) {
+ LOGD("FD type");
+ }
+ else if ( imgb->type == MM_VIDEO_BUFFER_TYPE_TBM_BO ) {
+ tbm_surface_h tsurf = NULL;
+
+#ifdef TBM_API_CHANGE
+ tbm_surface_info_s tsurf_info;
+ memset(&tsurf_info, 0x0, sizeof(tbm_surface_info_s));
+#endif
+
+ /* create tbm surface */
+ for (i = 0; i < MM_VIDEO_BUFFER_PLANE_MAX; i++) {
+ if (imgb->handle.bo[i]) {
+ bo_num++;
+#ifdef TBM_API_CHANGE
+ tsurf_info.planes[i].stride = imgb->stride_width[i];
+#endif
+ }
+ }
+
+ 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 = imgb->stride_width[i];
+ tsurf_info.planes[i].size = imgb->stride_width[i] * imgb->stride_height[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.size += tsurf_info.planes[i].size;
+ }
+
+ tsurf = tbm_surface_internal_create_with_bos ( &tsurf_info, (tbm_bo *)imgb->handle.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 *)imgb->handle.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 );
+ }
+ }
+
+DONE:
+
+ return MC_ERROR_NONE;
+}
+
+int __mc_fill_outbuf_with_packet(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt)
+{
+ void* pkt_data = NULL;
+
+ g_return_val_if_fail (core != NULL, MC_PARAM_ERROR);
+
+
+ media_packet_create_alloc(core->output_fmt, __mc_output_buffer_finalize_cb, core, out_pkt);
+
+ 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;
+}
+
+int __mc_fill_outbuf_with_h264_packet(mc_gst_core_t *core, void *data, int size, media_packet_h *out_pkt)
+{
+ void* pkt_data = NULL;
+ int mask = 0xfffffff0;
+
+ g_return_val_if_fail (core != NULL, MC_PARAM_ERROR);
+
+ if ( (core->out_mime & mask) == MEDIA_FORMAT_H264_SP)
+ {
+ _mc_check_out_bytestream(core, (unsigned char*)data, size);
+ }
+
+ if ( core->sps_size > 0 && core->pps_size > 0 ) {
+
+ media_packet_create_alloc(core->output_fmt, __mc_output_buffer_finalize_cb, core, out_pkt);
+ media_packet_set_buffer_size(*out_pkt, size);
+ media_packet_get_buffer_data_ptr(*out_pkt, &pkt_data);
+ memcpy(pkt_data, data, size);
+
+ if ( core->need_codec_data ) {
+ media_packet_set_codec_data(*out_pkt, core->codec_data, core->codec_data_size);
+ }
+
+ }
+
+ return MC_ERROR_NONE;
+}
+
+int __mc_venc_caps(mc_gst_core_t *core, GstCaps **caps)
+{
+ 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("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)
+{
+ 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", 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);
+
+ LOGD("%s, %d, %d, %d", core->format, enc_info->width, enc_info->height, enc_info->fps);
+
+
+ return MC_ERROR_NONE;
+}
+
+int __mc_h264dec_caps(mc_gst_core_t *core, GstCaps **caps)
+{
+ 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_sprddec_caps(mc_gst_core_t *core, GstCaps **caps)
+{
+ 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,
+ "width", G_TYPE_INT, dec_info->width,
+ "height", G_TYPE_INT, dec_info->height,
+ "framerate", GST_TYPE_FRACTION, 30, 1, 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)
+{
+ 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_aenc_caps(mc_gst_core_t *core, GstCaps **caps)
+{
+ 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,
+ "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_amrnb_caps(mc_gst_core_t *core, GstCaps **caps)
+{
+ 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,
+ "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)
+{
+ 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);
+
+ LOGD("mime : %s, samplerate :%d, channel : %d", core->mime, dec_info->samplerate, dec_info->channel);
+ return MC_ERROR_NONE;
+}
+
+int __mc_adec_aacv12_caps(mc_gst_core_t *core, GstCaps **caps)
+{
+ 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",
+ "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_mp3_caps(mc_gst_core_t *core, GstCaps **caps)
+{
+ 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)
+{
+ 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)
+{
+ 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_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)
+ {
+ mc_encoder_info_t *info;
+
+ info = (mc_encoder_info_t*)core->codec_info;
+
+ if (video)
+ {
+ media_format_set_video_mime(core->output_fmt, out_mime);
+ media_format_set_video_width(core->output_fmt, info->width);
+ media_format_set_video_height(core->output_fmt, info->height);
+ media_format_set_video_avg_bps(core->output_fmt, info->bitrate);
+ }
+ 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
+ {
+ mc_decoder_info_t *info;
+
+ info = (mc_decoder_info_t*)core->codec_info;
+
+ if (video)
+ {
+ media_format_set_video_mime(core->output_fmt, out_mime);
+ media_format_set_video_width(core->output_fmt, info->width);
+ media_format_set_video_height(core->output_fmt, info->height);
+ }
+ 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);
+ }
+ }
+ return MC_ERROR_NONE;
+}
+
+/*
+ * mc_gst_core functions
+*/
+mc_gst_core_t *mc_gst_core_new()
+{
+ mc_gst_core_t *core;
+
+ MEDIACODEC_FENTER();
+
+ core = g_new0(mc_gst_core_t, 1);
+
+ /* 0 : input, 1 : output */
+ core->ports[0] = NULL;
+ core->ports[1] = mc_gst_port_new(core);
+ core->ports[1]->index = 1;
+
+ core->available_queue = g_new0(mc_aqueue_t, 1);
+ core->available_queue->input = mc_async_queue_new();
+
+ g_mutex_init(&core->eos_mutex);
+ g_mutex_init(&core->drain_mutex);
+ g_cond_init(&core->eos_cond);
+ g_mutex_init(&core->prepare_lock);
+
+ core->need_feed = false;
+ core->eos = false;
+ core->need_codec_data = false;
+ core->need_sync_flag = false;
+ core->prepare_count = 0;
+ core->idr_count = 0;
+ core->sps_size = 0;
+ core->pps_size = 0;
+
+ if (!g_thread_supported()) {
+ g_thread_init(NULL);
+ LOGD("thread init");
+ }
+ g_atomic_int_set(&core->available_queue->running, 1);
+ core->available_queue->thread = g_thread_new("feed thread", &feed_task, core);
+
+ LOGD("gst_core(%p) is created", core);
+
+ MEDIACODEC_FLEAVE();
+
+ return core;
+}
+
+void mc_gst_core_free(mc_gst_core_t *core)
+{
+ 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);
+
+ g_atomic_int_set(&async_queue->running, 0);
+ g_thread_join(async_queue->thread);
+
+ g_mutex_clear(&core->drain_mutex);
+ g_mutex_clear(&core->eos_mutex);
+ g_mutex_clear(&core->prepare_lock);
+ g_cond_clear(&core->eos_cond);
+
+ mc_async_queue_free(async_queue->input);
+
+ 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();
+}
+
+/*
+ * mc_gst_port functions
+ */
+mc_gst_port_t *mc_gst_port_new(mc_gst_core_t *core)
+{
+ MEDIACODEC_FENTER();
+
+ mc_gst_port_t *port;
+
+ port = g_new0(mc_gst_port_t, 1);
+ port->core = core;
+ port->num_buffers = -1;
+ port->buffer_size = 0;
+ port->is_allocated = 0;
+ port->buffers = NULL;
+
+ g_mutex_init(&port->mutex);
+ g_cond_init(&port->buffer_cond);
+ port->queue = g_queue_new();
+
+ LOGD("gst_port(%p) is created", port);
+
+ MEDIACODEC_FLEAVE();
+ return port;
+}
+
+void mc_gst_port_free(mc_gst_port_t *port)
+{
+ MEDIACODEC_FENTER();
+
+ g_mutex_clear(&port->mutex);
+ g_cond_clear(&port->buffer_cond);
+ g_queue_free(port->queue);
+
+ LOGD("gst_port(%p) is freed", port);
+ g_free(port);
+
+ MEDIACODEC_FLEAVE();
+
+ return;
+}
+
+static void print_pad_capabilities(GstElement *element, gchar *pad_name)
+{
+ GstPad *pad = NULL;
+ GstCaps *caps = NULL;
+ gchar *format_str = NULL;
+ gchar *format_tmp = NULL;
+ GstStructure *structure;
+ int i;
+
+ pad = gst_element_get_static_pad(element, "src");
+
+ if (pad == NULL) {
+ LOGE("null pad");
+ }
+
+ caps = gst_pad_get_pad_template_caps(pad);
+}
+
+static void _mc_gst_update_caps(mc_gst_core_t *core, media_packet_h pkt, GstCaps **caps)
+{
+ //TODO remove is_hw param
+ core->format = __mc_get_gst_input_format(pkt, core->is_hw);
+
+ GstPad *pad = NULL;
+ GstCaps *template_caps;
+
+ pad = gst_element_get_static_pad(core->codec, "src");
+ template_caps = gst_pad_get_pad_template_caps(pad);
+
+ __mc_create_caps(core, caps);
+ g_object_set(core->appsrc, "caps", *caps, NULL);
+
+ if (gst_caps_is_subset(*caps, template_caps)) {
+ LOGD("new caps is subset of template caps");
+ }
+}
+
+static GstPadProbeReturn
+event_probe_cb(GstObject *pad, GstPadProbeInfo *info, gpointer user_data)
+{
+ mc_gst_core_t *core = (mc_gst_core_t*)user_data;
+ GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info);
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_STREAM_START:
+ core->codec_config = true;
+ LOGD("codec_config is set %d, %d", input_count, count);
+ break;
+ default:
+ break;
+ }
+ return GST_PAD_PROBE_OK;
+}
+
+static gpointer feed_task(gpointer 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;
+ 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))
+ {
+ LOGD("waiting for next input....");
+ in_buf = _mc_get_input_buffer(core);
+
+ if(!in_buf)
+ goto LEAVE;
+
+ 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)
+ {
+ LOGE("media_packet_is_end_of_stream failed");
+ goto ERROR;
+ }
+
+ if(codec_config)
+ initiative = true;
+
+ if (initiative) {
+ GstPad *pad;
+
+ _mc_gst_update_caps(core, in_buf, &new_caps);
+
+ pad = gst_element_get_static_pad(core->appsrc, "src");
+ 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)
+ {
+ LOGE("Failed to push gst buffer");
+ g_mutex_unlock(&core->drain_mutex);
+ goto ERROR;
+ }
+ LOGD("after refcount %d", GST_MINI_OBJECT_REFCOUNT_VALUE(buff));
+ LOGD("gst_app_src_get_current_level_bytes :%"G_GUINT64_FORMAT "\n", core->appsrc);
+
+ initiative = false;
+ g_mutex_unlock(&core->drain_mutex);
+
+#if 1
+ if (eos)
+ {
+ GstPad *pad;
+ LOGD("end of stream");
+#if 0
+ pad = gst_element_get_static_pad(core->appsrc, "src");
+ gst_pad_push_event (pad, gst_event_new_eos() );
+ gst_object_unref(pad);
+#else
+ //goto EOS;
+
+ //g_signal_emit_by_name(core->appsrc, "end-of-stream", &ret);
+ gst_app_src_end_of_stream ( core->appsrc );
+#endif
+
+ 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");
+ }
+
+ core->eos = false;
+ initiative = true;
+#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;
+LEAVE:
+ //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)
+ {
+ 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);
+ 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_NEED_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_ENOUGH_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)
+{
+ MEDIACODEC_FENTER();
+
+ g_return_val_if_fail (core != NULL, MC_PARAM_ERROR);
+
+ switch (id)
+ {
+ case MEDIACODEC_AAC:
+ {
+ LOGD("aac lc (adts) vtable");
+ core->vtable = encoder ? aenc_vtable : adec_vtable;
+ break;
+ }
+ case MEDIACODEC_AAC_HE:
+ case MEDIACODEC_AAC_HE_PS:
+ {
+ LOGD("aac he v12 vtable");
+ core->vtable = encoder ? aenc_vtable : adec_aacv12_vtable;
+ if (encoder) {
+ LOGD("[MC_NOT_SUPPORTED] aac encoder is not supported yet!!!");
+ return MC_NOT_SUPPORTED;
+ }
+ break;
+ }
+ case MEDIACODEC_MP3:
+ {
+ 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;
+ break;
+ }
+ case MEDIACODEC_H263:
+ {
+ LOGD("h263 vtable");
+ core->vtable = encoder ? venc_vtable : vdec_vtable;
+ break;
+ }
+ case MEDIACODEC_MPEG4:
+ {
+ LOGD("mpeg4 vtable");
+ core->vtable = encoder ? venc_vtable : vdec_vtable;
+ break;
+ }
+ case MEDIACODEC_H264:
+ {
+ LOGD("h264 vtable");
+ if ( is_hw )
+ core->vtable = encoder ? venc_vtable : vdec_h264_vtable;
+ else
+ core->vtable = encoder ? venc_vtable : vdec_vtable;
+ break;
+ }
+ default:
+ break;
+ }
+
+ return MC_ERROR_NONE;
+}
+
+static int _mc_gst_gstbuffer_to_appsrc(mc_gst_core_t *core, GstMCBuffer *buff)
+{
+ MEDIACODEC_FENTER();
+
+ int ret = MC_ERROR_NONE;
+
+ 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;
+}
+
+media_packet_h _mc_get_input_buffer(mc_gst_core_t *core)
+{
+ LOGD("waiting for input...");
+ return mc_async_queue_pop(core->available_queue->input);
+}
+
+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 i = 0;
+
+ if (!mc_handle)
+ return MC_PARAM_ERROR;
+
+ mediacodec_codec_type_e id;
+ bool video;
+ bool encoder;
+ bool hardware;
+ gchar *factory_name = NULL;
+ static const 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;
+
+ 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))
+ break;
+ }
+
+ if( i == codec_list )
+ 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();
+
+ 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->out_mime = codec_map[i].type.out_format;
+
+ 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", 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)
+ {
+ LOGE("Failed to create output pakcet");
+ return ret;
+ }
+
+ /* link vtable */
+ 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++)
+ {
+ LOGD("copy cb function [%d]", 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]);
+ }
+ }
+
+ mc_handle->core = new_core;
+
+ /* create basic core elements */
+ ret = _mc_gst_create_pipeline(mc_handle->core, factory_name);
+
+ LOGD("initialized...");
+ 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;
+
+ if (!mc_handle)
+ return MC_PARAM_ERROR;
+
+ 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);
+
+ _mc_gst_flush_buffers (core);
+
+ /* unset callback */
+ for (i = 0; i < _MEDIACODEC_EVENT_TYPE_INTERNAL_FILLBUFFER ; i++)
+ {
+ LOGD("unset cb function [%d]", 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);
+
+ if(core != NULL)
+ {
+ mc_gst_core_free(core);
+ mc_handle->core = NULL;
+ }
+ }
+
+ 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);
+ LOGD("input buffer count :%d", input_count);
+
+ g_get_current_time (&nowtv);
+ g_time_val_add (&nowtv, 500 * 1000 ); /* usec */
+/*
+ if (!g_cond_timed_wait(&nowtv)) {
+ }
+*/
+ input_count++;
+
+ if(!core->eos)
+ mc_async_queue_push(core->available_queue->input, inbuf);
+ else
+ ret = MC_INVALID_IN_BUF;
+
+
+
+ MEDIACODEC_FLEAVE();
+
+ return ret;
+}
+
+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;
+
+ if (!mc_handle)
+ return MC_PARAM_ERROR;
+
+ 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))
+ {
+ out_pkt = g_queue_pop_head(core->ports[1]->queue);
+ LOGD("pop from output_queue : %p", out_pkt);
+ }
+ else
+ {
+ ret = MC_OUTPUT_BUFFER_EMPTY;
+ LOGD("output_queue is empty");
+ }
+ *outbuf = out_pkt;
+
+ g_mutex_unlock(&core->ports[1]->mutex);
+
+ MEDIACODEC_FLEAVE();
+
+ return ret;
+}
+
+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;
+ GstPad *pad;
+
+ pad = gst_element_get_static_pad(core->appsrc, "src");
+
+ if (!mc_handle)
+ return MC_PARAM_ERROR;
+
+ core = (mc_gst_core_t*)mc_handle->core;
+ LOGI("@%p v(%d)e(%d) get_output", core, core->video, core->encoder);
+
+ _mc_gst_flush_buffers ( core );
+
+ MEDIACODEC_FLEAVE();
+
+ return ret;
+}
+
+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;
+ GError *err = NULL;
+ int i = 0;
+ int arg_count = 0;
+
+ 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 );
+
+ if ( !argc || !argv || !argv2 )
+ goto ERROR;
+
+ memset( argv, 0, sizeof(gchar*) * max_argc );
+ memset( argv2, 0, sizeof(gchar*) * max_argc );
+
+ /* add initial */
+ *argc = 1;
+ argv[0] = g_strdup( "media codec" );
+
+ /* we would not do fork for scanning plugins */
+ argv[*argc] = g_strdup("--gst-disable-registry-fork");
+ (*argc)++;
+
+ /* check disable registry scan */
+ argv[*argc] = g_strdup("--gst-disable-registry-update");
+ (*argc)++;
+
+ /* check disable segtrap */
+ argv[*argc] = g_strdup("--gst-disable-segtrap");
+ (*argc)++;
+
+ LOGD("initializing gstreamer with following parameter\n");
+ LOGD("argc : %d\n", *argc);
+ arg_count = *argc;
+
+ 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))
+ {
+ LOGE("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
+ if (err)
+ {
+ g_error_free (err);
+ }
+
+ goto ERROR;
+ }
+
+ /* release */
+ for ( i = 0; i < arg_count; i++ )
+ {
+ MC_FREEIF( argv2[i] );
+ }
+
+ MC_FREEIF( argv );
+ MC_FREEIF( argv2 );
+ MC_FREEIF( argc );
+
+ /* done */
+ initialized = TRUE;
+
+ return TRUE;
+
+ERROR:
+
+ /* release */
+ for ( i = 0; i < arg_count; i++ )
+ {
+ LOGD("free[%d] : %s\n", i, argv2[i]);
+ MC_FREEIF( argv2[i] );
+ }
+
+ 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)
+{
+ GstBus *bus = NULL;
+ GstPad *pad = NULL;
+
+ MEDIACODEC_FENTER();
+
+ g_mutex_lock(&core->prepare_lock);
+ if(core->prepare_count == 0)
+ {
+
+ 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");
+ goto ERROR;
+ }
+
+ LOGD("@%p v(%d)e(%d) create_pipeline", core, core->video, core->encoder);
+ MEDIACODEC_ELEMENT_SET_STATE(core->codec, GST_STATE_READY);
+
+ /* create common elements */
+ core->pipeline = gst_pipeline_new(NULL);
+
+ 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");
+ 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");
+ goto ERROR;
+ }
+ g_object_set(core->fakesink, "enable-last-buffer", FALSE, 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->capsfilter, core->codec, core->fakesink, NULL);
+
+ /* 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);
+ 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, 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);
+ core->probe_id =
+ gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
+ (GstPadProbeCallback)event_probe_cb, core, NULL);
+ 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);
+ core->signal_handoff = g_signal_connect(core->fakesink, "handoff", G_CALLBACK(__mc_gst_buffer_add), core);
+
+ /* set state PLAYING */
+ MEDIACODEC_ELEMENT_SET_STATE(GST_ELEMENT_CAST(core->pipeline), GST_STATE_PLAYING);
+
+ }
+ core->prepare_count++;
+ g_mutex_unlock(&core->prepare_lock);
+
+ MEDIACODEC_FLEAVE();
+
+ return MC_ERROR_NONE;
+
+STATE_CHANGE_FAILED:
+ERROR:
+
+ if(core->codec)
+ gst_object_unref(GST_OBJECT(core->codec));
+
+ if(core->pipeline)
+ gst_object_unref(GST_OBJECT(core->pipeline));
+
+ if(core->appsrc)
+ gst_object_unref(GST_OBJECT(core->appsrc));
+
+ 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);
+
+ return MC_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->pipeline)
+ {
+ /* disconnect signal */
+ 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)
+ {
+ GSource *source = NULL;
+ 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_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));
+ }
+ }
+
+ LOGD("@%p v(%d)e(%d) destroy_pipeline : %d ", core, core->video, core->encoder, core->prepare_count);
+ g_mutex_unlock(&core->prepare_lock);
+
+ MEDIACODEC_FLEAVE();
+
+ return ret;
+
+STATE_CHANGE_FAILED:
+ if(core->pipeline)
+ gst_object_unref(GST_OBJECT(core->pipeline));
+
+ LOGD("@%p v(%d)e(%d) destroy_pipeline failed", core, core->video, core->encoder);
+ g_mutex_unlock(&core->prepare_lock);
+
+ return MC_ERROR;
+}
+
+void __mc_gst_append_codec_data(mc_gst_core_t *core, media_packet_h pkt)
+{
+ void* buf_data = NULL;
+ uint64_t buf_size = 0;
+ void *tmp = NULL;
+
+ media_packet_get_buffer_size(pkt, &buf_size);
+ media_packet_get_buffer_data_ptr(pkt, &buf_data);
+
+ tmp = (unsigned char*)malloc(sizeof(unsigned char)*buf_size);
+ memcpy(tmp, buf_data, buf_size);
+ memcpy(buf_data, core->codec_data, core->codec_data_size);
+ memcpy(buf_data + core->codec_data_size, tmp, buf_size);
+ media_packet_set_buffer_size(pkt, buf_size+core->codec_data_size);
+ free(tmp);
+}
+
+void __mc_gst_buffer_add (GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data)
+{
+ mc_gst_core_t* core = (mc_gst_core_t*) data;
+ void* buf_data = NULL;
+ uint64_t buf_size = 0;
+ static gboolean initialized = FALSE;
+ int mask = 0xfffffff0;
+ guint n;
+ GstMemory *mem;
+ MMVideoBuffer *imgb = NULL;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+ media_packet_h out_pkt = NULL;
+
+ MEDIACODEC_FENTER();
+
+ gst_buffer_ref(buffer);
+
+ n = gst_buffer_n_memory(buffer);
+
+ mem = gst_buffer_peek_memory(buffer, n-1);
+
+ gst_memory_map(mem, &map, GST_MAP_READ);
+ LOGD("n : %d, map.data : %p, map.size : %d",n, map.data, map.size);
+
+ out_pkt = __mc_gst_make_media_packet(core, map.data, map.size);
+
+ LOGI("@%p(%d) out_pkt : %p", core, core->encoder, out_pkt);
+ gst_memory_unmap(mem, &map);
+
+
+ if ( out_pkt ) {
+ media_packet_set_extra(out_pkt, buffer);
+ media_packet_set_pts(out_pkt, GST_BUFFER_TIMESTAMP(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);
+
+ count++;
+ LOGD("queued : %d", 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;
+}
+
+int __mc_output_buffer_finalize_cb(media_packet_h packet, int error_code, void *user_data)
+{
+ GstMemory *mem;
+ void* buffer = NULL;
+
+ media_packet_get_extra(packet, &buffer);
+
+ gst_buffer_unref((GstBuffer*)buffer);
+
+ return MEDIA_PACKET_FINALIZE;
+}
+
+gchar *__mc_get_gst_input_format(media_packet_h packet, bool is_hw)
+{
+ gchar *format = NULL;
+ media_format_h fmt = NULL;
+ media_format_mimetype_e mimetype = 0;
+
+ media_packet_get_format(packet, &fmt);
+ media_format_get_video_info(fmt, &mimetype, NULL, NULL, NULL, NULL);
+ LOGD("input packet mimetype : %x", mimetype);
+
+ switch(mimetype)
+ {
+ case MEDIA_FORMAT_I420:
+ format = "I420";
+ break;
+ case MEDIA_FORMAT_NV12:
+ if (is_hw)
+ format = "SN12";
+ else
+ format = "NV12";
+ break;
+ case MEDIA_FORMAT_ARGB:
+ format = "ARGB";
+ break;
+ default:
+ break;
+ }
+ LOGD("input packet format : %s", format);
+ return format;
+}
+
+guint __mc_set_codecdata_buffer(mc_gst_core_t *core, GstCaps **caps, void *buf_data, int buf_size)
+{
+ GstBuffer *codec_data;
+ guint16 codec_data_data;
+ GstMapInfo map;
+ guint codecdata_size;
+
+ LOGD("[LEO] Enable codec_config, So Set caps for codec_data in codec_id (0x%x)", core->codec_id);
+
+ if ( (!core->encoder) &&
+ (core->codec_id == MEDIACODEC_AAC ||core->codec_id == MEDIACODEC_AAC_HE || core->codec_id == MEDIACODEC_AAC_HE_PS))
+ {
+ /*
+ * The codec_data data is according to AudioSpecificConfig,
+ * ISO/IEC 14496-3, 1.6.2.1
+ */
+ codecdata_size = 16; /*AUDIO_CODECDATA_SIZE = 16 (in testsuit)*/
+ codec_data = gst_buffer_new_and_alloc (codecdata_size);
+ gst_buffer_map (codec_data, &map, GST_MAP_WRITE);
+ memcpy (map.data, buf_data, codecdata_size);
+ gst_buffer_unmap (codec_data, &map);
+
+ gst_caps_set_simple (*caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
+ }
+ else
+ {
+ codecdata_size = 0;
+ LOGW("codec data set fail");
+ }
+
+ return codecdata_size;
+}
+
+GstMCBuffer* _mc_gst_media_packet_to_gstbuffer(mc_gst_core_t* core, GstCaps **caps, media_packet_h pkt, bool codec_config)
+{
+ 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;
+ }
+
+ mc_buffer = gst_mediacodec_buffer_new(core, pkt, buf_size);
+ if(mc_buffer->buffer == NULL)
+ {
+ LOGW("failed to create inbuf");
+ return NULL;
+ }
+
+#if 1 //Added code for codec_data
+ if (codec_config)
+ {
+ guint codec_data_size = 0;
+ codec_data_size = __mc_set_codecdata_buffer(core, caps, buf_data, (int)buf_size);
+
+ buf_data += codec_data_size;
+ buf_size -= codec_data_size;
+
+ LOGD("Enable codec_config, returned codec_data_size (%d)", codec_data_size);
+ }
+#endif
+
+ ret = __mc_fill_input_buffer(core, buf_data, (int)buf_size, mc_buffer);
+ if (ret != MC_ERROR_NONE)
+ {
+ LOGW("failed to fill inbuf");
+ return NULL;
+ }
+
+ /* pts */
+ media_packet_get_pts(pkt, &pts);
+ GST_BUFFER_PTS(mc_buffer->buffer) = pts;
+
+ /* duration */
+ media_packet_get_duration(pkt, &dur);
+ GST_BUFFER_DURATION(mc_buffer->buffer) = dur;
+
+ return mc_buffer;
+}
+
+media_packet_h __mc_gst_gstbuffer_to_media_packet(mc_gst_core_t* core, GstBuffer* buff)
+{
+ media_packet_h out_pkt = NULL;
+
+ if (!buff)
+ return NULL;
+
+ //__mc_fill_output_buffer(core, buff, &out_pkt);
+
+ gst_buffer_ref(buff);
+
+ return out_pkt;
+}
+
+media_packet_h __mc_gst_make_media_packet(mc_gst_core_t *core, unsigned char *data, int size)
+{
+ media_packet_h pkt = NULL;
+
+ __mc_fill_output_buffer(core, data, size, &pkt);
+
+ return pkt;
+}
+
+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;
+ LOGD("@%p v(%d)e(%d)", core, core->video, core->encoder);
+
+ switch (GST_MESSAGE_TYPE (msg)) {
+
+ case GST_MESSAGE_EOS:
+ {
+ core->eos = true;
+ g_cond_signal(&core->eos_cond);
+ LOGD("send eos 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]);
+ }
+
+ LOGD ("End of stream\n");
+ }
+ break;
+
+ case GST_MESSAGE_ERROR:
+ {
+ GError* error = NULL;
+
+ gst_message_parse_error (msg, &error, NULL);
+
+ if (!error)
+ {
+ LOGW("GST error message parsing failed");
+ break;
+ }
+
+ LOGW ("Error: %s\n", error->message);
+
+ if(error)
+ {
+ if(error->domain == GST_STREAM_ERROR)
+ {
+ ret = __gst_handle_stream_error(core, error, msg);
+ }
+ else if (error->domain == GST_RESOURCE_ERROR)
+ {
+ ret = __gst_handle_resource_error(core, error->code);
+ }
+ else if (error->domain == GST_LIBRARY_ERROR)
+ {
+ ret = __gst_handle_library_error(core, error->code);
+ }
+ else if (error->domain == GST_CORE_ERROR)
+ {
+ ret = __gst_handle_core_error(core, error->code);
+ }
+ 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);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ //gst_object_unref(msg);
+
+ return TRUE;
+}
+
+static gboolean
+__mc_gst_check_useful_message(mc_gst_core_t *core, GstMessage *msg)
+{
+ gboolean retval = false;
+
+ if(!core->pipeline)
+ {
+ LOGE("mediacodec pipeline handle is null");
+ return true;
+ }
+
+ switch (GST_MESSAGE_TYPE (msg))
+ {
+ case GST_MESSAGE_TAG:
+ case GST_MESSAGE_EOS:
+ case GST_MESSAGE_ERROR:
+ case GST_MESSAGE_WARNING:
+ retval = true;
+ break;
+ default:
+ retval = false;
+ break;
+ }
+
+ return retval;
+}
+
+static GstBusSyncReply
+__mc_gst_bus_sync_callback(GstBus *bus, GstMessage *msg, gpointer data)
+{
+ mc_gst_core_t *core = (mc_gst_core_t*)data;
+ GstBusSyncReply reply = GST_BUS_DROP;
+
+ 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))
+ {
+ gst_message_unref(msg);
+ return GST_BUS_DROP;
+ }
+
+ switch (GST_MESSAGE_TYPE (msg))
+ {
+ case GST_MESSAGE_EOS:
+ case GST_MESSAGE_ERROR:
+ __mc_gst_bus_callback(NULL, msg, core);
+ reply = GST_BUS_DROP;
+ break;
+
+ default:
+ reply = GST_BUS_PASS;
+ break;
+ }
+
+ if( reply == GST_BUS_DROP )
+ gst_message_unref(msg);
+
+ return reply;
+}
+
+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;
+
+ if (!pkt) {
+ LOGE("output is null");
+ return NULL;
+ }
+
+ MMVideoBuffer *imgb = NULL;
+ imgb = (MMVideoBuffer *)malloc(sizeof(MMVideoBuffer));
+ if (!imgb) {
+ LOGE("Failed to alloc MMVideoBuffer");
+ return NULL;
+ }
+ memset(imgb, 0x00, sizeof(MMVideoBuffer));
+
+ media_packet_get_tbm_surface(pkt, &surface);
+ bo = tbm_surface_internal_get_bo(surface, 0);
+
+ tbm_bo_handle handle = tbm_bo_get_handle(bo, TBM_DEVICE_CPU);
+#ifdef Z130H
+ 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)
+ {
+ imgb->handle.paddr[0] = (void*)phy_addr;
+ LOGD("imgb->paddr : %p", imgb->handle.paddr[0]);
+ }
+ LOGD("paddr : %p", phy_addr);
+#endif
+
+ imgb->type = MM_VIDEO_BUFFER_TYPE_TBM_BO;
+ imgb->handle.bo[0] = bo;
+ imgb->data[0] = handle.ptr;
+ imgb->width[0] = enc_info->width;
+ imgb->height[0] = enc_info->height;
+ imgb->stride_width[0] = imgb->width[0];
+ imgb->stride_height[0] = imgb->height[0];
+
+ return imgb;
+}
+
+static void gst_mediacodec_buffer_finalize(GstMCBuffer *mc_buffer)
+{
+ MMVideoBuffer *imgb = NULL;
+ GstMemory *mem = NULL;
+ GstMapInfo map = GST_MAP_INFO_INIT;
+ mc_gst_core_t *core = mc_buffer->core;
+ guint n;
+
+
+
+ n = gst_buffer_n_memory(mc_buffer->buffer);
+
+ mem = gst_buffer_peek_memory(mc_buffer->buffer, n-1);
+
+ gst_memory_map(mem, &map, GST_MAP_READ);
+ LOGD("n : %d, map.data : %p, map.size : %d",n, map.data, map.size);
+
+ gst_memory_unmap(mem, &map);
+
+ LOGD("gst_mediacodec_buffer_finalize()");
+/*
+ if(mc_buffer->has_imgb) {
+
+ mem = gst_buffer_peek_memory(mc_buffer->buffer, 1);
+ gst_memory_map(mem, &map, GST_MAP_READ);
+ imgb = (MMVideoBuffer*)map.data;
+ gst_memory_unmap(mem, &map);
+
+ if(imgb) {
+ free(imgb);
+ imgb = NULL;
+ LOGD("imgb is destroyed");
+ }
+ }
+*/
+
+ 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;
+}
+
+static GstMCBuffer *gst_mediacodec_buffer_new(mc_gst_core_t* core, media_packet_h pkt, uint64_t size)
+{
+ GstMCBuffer *mc_buffer = NULL;
+
+ mc_buffer = (GstMCBuffer *)malloc(sizeof(*mc_buffer));
+ mc_buffer->buffer = gst_buffer_new();
+ mc_buffer->buf_size = size;
+
+ LOGD("creating buffer : %p, %p", mc_buffer, mc_buffer->buffer);
+ mc_buffer->core = core;
+ mc_buffer->pkt = pkt;
+
+ return mc_buffer;
+}
+
+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 )
+ {
+ case GST_CORE_ERROR_MISSING_PLUGIN:
+ return MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT;
+ case GST_CORE_ERROR_STATE_CHANGE:
+ case GST_CORE_ERROR_SEEK:
+ case GST_CORE_ERROR_NOT_IMPLEMENTED:
+ case GST_CORE_ERROR_FAILED:
+ case GST_CORE_ERROR_TOO_LAZY:
+ case GST_CORE_ERROR_PAD:
+ case GST_CORE_ERROR_THREAD:
+ case GST_CORE_ERROR_NEGOTIATION:
+ case GST_CORE_ERROR_EVENT:
+ case GST_CORE_ERROR_CAPS:
+ case GST_CORE_ERROR_TAG:
+ case GST_CORE_ERROR_CLOCK:
+ case GST_CORE_ERROR_DISABLED:
+ default:
+ trans_err = MEDIACODEC_ERROR_INVALID_STREAM;
+ break;
+ }
+
+ return trans_err;
+}
+
+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 )
+ {
+ case GST_LIBRARY_ERROR_FAILED:
+ case GST_LIBRARY_ERROR_TOO_LAZY:
+ case GST_LIBRARY_ERROR_INIT:
+ case GST_LIBRARY_ERROR_SHUTDOWN:
+ case GST_LIBRARY_ERROR_SETTINGS:
+ case GST_LIBRARY_ERROR_ENCODE:
+ default:
+ trans_err = MEDIACODEC_ERROR_INVALID_STREAM;
+ break;
+ }
+
+ return trans_err;
+}
+
+
+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 )
+ {
+ case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
+ trans_err = MEDIACODEC_ERROR_NO_FREE_SPACE;
+ break;
+ case GST_RESOURCE_ERROR_WRITE:
+ case GST_RESOURCE_ERROR_FAILED:
+ case GST_RESOURCE_ERROR_SEEK:
+ case GST_RESOURCE_ERROR_TOO_LAZY:
+ case GST_RESOURCE_ERROR_BUSY:
+ case GST_RESOURCE_ERROR_OPEN_WRITE:
+ case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
+ case GST_RESOURCE_ERROR_CLOSE:
+ case GST_RESOURCE_ERROR_SYNC:
+ case GST_RESOURCE_ERROR_SETTINGS:
+ default:
+ trans_err = MEDIACODEC_ERROR_INTERNAL;
+ break;
+ }
+
+ return trans_err;
+}
+
+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);
+
+ switch ( error->code )
+ {
+ case GST_STREAM_ERROR_FAILED:
+ case GST_STREAM_ERROR_TYPE_NOT_FOUND:
+ case GST_STREAM_ERROR_DECODE:
+ case GST_STREAM_ERROR_WRONG_TYPE:
+ 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 );
+ break;
+
+ case GST_STREAM_ERROR_NOT_IMPLEMENTED:
+ case GST_STREAM_ERROR_TOO_LAZY:
+ case GST_STREAM_ERROR_ENCODE:
+ case GST_STREAM_ERROR_DEMUX:
+ case GST_STREAM_ERROR_MUX:
+ case GST_STREAM_ERROR_FORMAT:
+ default:
+ trans_err = MEDIACODEC_ERROR_INVALID_STREAM;
+ break;
+ }
+
+ return trans_err;
+}
+
+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;
+
+
+ src_element = GST_ELEMENT_CAST(message->src);
+ if ( !src_element )
+ goto INTERNAL_ERROR;
+
+ src_element_name = GST_ELEMENT_NAME(src_element);
+ if ( !src_element_name )
+ goto INTERNAL_ERROR;
+
+ factory = gst_element_get_factory(src_element);
+ if ( !factory )
+ goto INTERNAL_ERROR;
+
+ klass = gst_element_factory_get_klass(factory);
+ 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 )
+ {
+ case GST_STREAM_ERROR_DECODE:
+ return MEDIACODEC_ERROR_INVALID_STREAM;
+ break;
+
+ case GST_STREAM_ERROR_CODEC_NOT_FOUND:
+ case GST_STREAM_ERROR_TYPE_NOT_FOUND:
+ case GST_STREAM_ERROR_WRONG_TYPE:
+ return MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT;
+ break;
+
+ case GST_STREAM_ERROR_FAILED:
+ return MEDIACODEC_ERROR_NOT_SUPPORTED_FORMAT;
+ break;
+
+ default:
+ break;
+ }
+
+ return MEDIACODEC_ERROR_INVALID_STREAM;
+
+INTERNAL_ERROR:
+ return MEDIACODEC_ERROR_INTERNAL;
+}
+
+static void _mc_gst_flush_buffers( mc_gst_core_t *core )
+{
+ GstPad *pad;
+
+ pad = gst_element_get_static_pad(core->appsrc, "src");
+
+ mc_async_queue_disable(core->available_queue->input);
+
+ _mc_gst_set_flush_input ( core );
+ gst_pad_push_event( pad, gst_event_new_flush_start());
+ _mc_gst_set_flush_output ( core );
+ gst_pad_push_event ( pad, gst_event_new_flush_stop (FALSE));
+ gst_object_unref(pad);
+
+ mc_async_queue_enable(core->available_queue->input);
+
+ MEDIACODEC_FLEAVE();
+}
+
+
+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) )
+ {
+ LOGD("%p pkt is poped");
+ 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);
+}
+
+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");
+ g_mutex_lock(&core->ports[1]->mutex);
+
+ if(!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);
+ media_packet_destroy(pkt);
+ }
+ }
+
+ g_mutex_unlock(&core->ports[1]->mutex);
+}
+
+#ifdef Z130H
+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;
+
+ tbm_bo_handle_fd = tbm_bo_handle_fd_t.u32;
+
+ int open_flags = O_RDWR;
+ int ion_fd = -1;
+
+ struct ion_mmu_data mmu_data;
+ struct ion_custom_data custom_data;
+
+ mmu_data.fd_buffer = tbm_bo_handle_fd;
+ 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");
+ }
+
+ 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 (!ret)
+ {
+ *phy_addr = mmu_data.iova_addr;
+ *phy_size = mmu_data.iova_size;
+ }
+ else
+ {
+ *phy_addr = 0;
+ *phy_size = 0;
+ LOGW ("[tbm_get_physical_addr_bo] getting physical address is failed. phy_addr = 0");
+ }
+
+ 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=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=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=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=i+1) {
+ linear_offset = temp1*(i-top);
+ for (j=left; j<(yuv420_width-right); j=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;
+ }
+ }
+ }
+}
+
+int _mc_check_out_bytestream (mc_gst_core_t *core, unsigned char *nal, int byte_length)
+{
+ int ret = MC_ERROR_NONE;
+ int stacked_length = 0;
+ int nal_length = 0;
+ unsigned int syntax = 0;
+ int idr = 0;
+ int nal_unit_type = 0;
+ unsigned char tmp[1000000];
+ unsigned char sps[100];
+ unsigned char pps[100];
+
+ 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, tmp);
+
+ mc_init_bits (&pstream, nal + stacked_length, byte_length - stacked_length );
+ mc_read_bits (&pstream, 32, &syntax);
+ mc_read_bits (&pstream, 8, &syntax);
+
+ LOGD("stacked_length : %d, byte_length : %d, nal_length : %d",
+ stacked_length, byte_length, nal_length);
+
+ switch ( syntax & 0x1F )
+ {
+ case NAL_SEQUENCE_PARAMETER_SET:
+ LOGD("SPS is found : ", nal_length);
+ core->sps_size = nal_length;
+ memcpy(sps, tmp, nal_length);
+ break;
+ case NAL_PICTURE_PARAMETER_SET:
+ LOGD("PPS is found : %d", nal_length);
+ core->pps_size = nal_length;
+ memcpy(pps, tmp, nal_length);
+ break;
+ case NAL_SLICE_IDR:
+ LOGD ("IDR is found");
+ idr++;
+ core->idr_count++;
+ break;
+ default:
+ LOGD ("%x nal_unit_type is detected");
+ break;
+ }
+
+ stacked_length += nal_length;
+
+ if ( stacked_length >= byte_length )
+ break;
+ }
+ if( core->sps_size > 0 && core->pps_size > 0 ) {
+ memcpy (core->codec_data, sps, core->sps_size);
+ memcpy (core->codec_data+core->sps_size, pps, core->pps_size);
+ core->codec_data_size = core->sps_size + core->pps_size;
+ }
+
+ }
+ else if ( nal_unit_type == 0x5 )
+ {
+ if ( !core->idr_count )
+ core->need_codec_data = true;
+ core->idr_count++;
+ LOGD("IDR : %d", core->idr_count);
+ }
+ else
+ {
+ LOGD("nal_unit_type : %x", nal_unit_type);
+ }
+
+ return ret;
+}
async_queue_t *async_queue;
async_queue = g_slice_new0 (async_queue_t);
-#if 0 //to avoid build error until this code is compatible with glib 2.0
- async_queue->condition = g_cond_new ();
- async_queue->mutex = g_mutex_new ();
+
+ g_cond_init (&async_queue->condition);
+ g_mutex_init(&async_queue->mutex);
async_queue->enabled = TRUE;
-#endif
+
return async_queue;
}
void mc_async_queue_free (async_queue_t * async_queue)
{
-#if 0 //to avoid build error until this code is compatible with glib 2.0
-
- g_cond_free (async_queue->condition);
- g_mutex_free (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);
-#endif
}
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);
+ 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 data = NULL;
- g_mutex_lock (async_queue->mutex);
+ g_mutex_lock (&async_queue->mutex);
if (!async_queue->enabled) {
/* g_warning ("not enabled!"); */
}
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) {
}
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 data = NULL;
+
+ g_mutex_lock (&async_queue->mutex);
+
+ if (async_queue->head) {
+ GList *node = async_queue->head;
+ 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);
+ }
+
+ g_mutex_unlock (&async_queue->mutex);
return data;
}
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)
{
- 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)
{
- g_mutex_lock(async_queue->mutex);
+ g_mutex_lock(&async_queue->mutex);
g_list_free(async_queue->head);
async_queue->head = async_queue->tail = NULL;
async_queue->length = 0;
- g_mutex_unlock(async_queue->mutex);
+ g_mutex_unlock(&async_queue->mutex);
}
free(ptr);
}
+
+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;
+
+ return sem;
+}
+
+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);
+}
+
+void mc_sem_down(mc_sem_t *sem)
+{
+ g_mutex_lock(&sem->mutex);
+
+ while(sem->counter == 0)
+ g_cond_wait(&sem->cond, &sem->mutex);
+ sem->counter--;
+
+ g_mutex_unlock(&sem->mutex);
+}
+
+void mc_sem_up(mc_sem_t *sem)
+{
+ g_mutex_lock(&sem->mutex);
+
+ sem->counter++;
+ g_cond_signal(&sem->cond);
+
+ g_mutex_unlock(&sem->mutex);
+
+}
+
+void mc_hex_dump(char *desc, void *addr, int len)
+{
+ int i;
+ unsigned char buff[17];
+ unsigned char *pc = (unsigned char*)addr;
+
+ if (desc != NULL)
+ printf("%s:\n", desc);
+
+ for (i = 0; i < len; i++)
+ {
+
+ if ((i % 16) == 0)
+ {
+ if (i != 0)
+ printf(" %s\n", buff);
+
+ printf(" %04x ", i);
+ }
+
+ printf(" %02x", pc[i]);
+
+ if ((pc[i] < 0x20) || (pc[i] > 0x7e))
+ buff[i % 16] = '.';
+ else
+ buff[i % 16] = pc[i];
+ buff[(i % 16) + 1] = '\0';
+ }
+
+ while ((i % 16) != 0) {
+ printf(" ");
+ i++;
+ }
+ printf(" %s\n", buff);
+}
SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
ENDFOREACH(flag)
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -pie")
aux_source_directory(. sources)
FOREACH(src ${sources})
ADD_EXECUTABLE(${src_name} ${src})
TARGET_LINK_LIBRARIES(${src_name} capi-media-codec ${${fw_test}_LDFLAGS})
ENDFOREACH()
-
#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 : AUDIO_CODECDATA_SIZE is temporal size (16byte) for codec_data
+ */
+#if 1
+ #define HE_AAC_V12_ENABLE 1
+ #define AUDIO_CODECDATA_SIZE 16
+#endif
+
#define DUMP_OUTBUF 1
#define MAX_INPUT_BUF_NUM 20
#define USE_INPUT_QUEUE 1
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;
+//async_queue_t *input_avaliable = NULL;
+GQueue input_available;
-GThread *pa_thread;
-gint pa_running = 0;
uint64_t pts = 0;
static int width = DEFAULT_OUT_BUF_WIDTH;
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;
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)
if(result != read_size)
{
- exit(1);
+ break;
}
val = buffer[0];
}
nal[nal_length++] = 0;
nal[nal_length++] = 1;
zero_count = 0;
+ init = 1;
while(1)
{
if (feof(fd))
result = fread(buffer, 1, read_size, fd);
if(result != read_size)
{
- exit(1);
+ break;
}
val = buffer[0];
+ if(init) {
+ nal_unit_type = val & 0xf;
+ init = 0;
+ }
if (!val)
{
zero_count++;
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;
}
result = fread(buffer, 1,read_size, fd);
if(result != read_size)
{
- exit(1);
+ //exit(1);
+ return -1;
}
memcpy(yuv, buffer, width*height*3/2);
return width*height*3/2;
}
+
+/**
+ * Extract Input data for MP3 decoder
+ * (MPEG-1/2/2.5 layer 3)
+ * As-Is : Extractor code support only mp3 file exclude ID3tag, So mp3 file should start mp3 sync format. (0xffe0)
+ * To-Be : Will support mp3 file include ID3tag (v1,v2)
+ **/
+
+static const guint mp3types_bitrates[2][3][16] = {
+{
+ {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
+ {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
+ {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
+ },
+{
+ {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
+ },
+};
+
+static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
+ {22050, 24000, 16000},
+ {11025, 12000, 8000}
+};
+
+unsigned int extract_input_mp3dec(FILE *fd, unsigned char* mp3data)
+{
+ int readsize;
+ size_t result;
+ unsigned char buffer[1000000];
+ guint header;
+ guint padding, bitrate, lsf, layer, mpg25;
+ guint hdr_bitrate, sf;
+
+ if (feof(fd))
+ return 0;
+
+ result = fread(buffer, 1, 4, fd); //mp3 header
+ if(result != 4) {
+ g_print ("[ERROR] fread size is %d\n", result);
+ return -1;
+ }
+
+ header = GST_READ_UINT32_BE (buffer);
+#if 1 //normal extract code
+ if (header == 0) {
+ g_print ("[ERROR] read header size is 0\n");
+ return -1;
+ }
+
+ /* if it's not a valid sync */
+ if ((header & 0xffe00000) != 0xffe00000) {
+ g_print ("[ERROR] invalid sync\n");
+ return -1;
+ }
+
+ /* if it's an invalid MPEG version */
+ if (((header >> 19) & 3) == 0x1) {
+ g_print ("[ERROR] invalid MPEG version: %d\n", (header >> 19) & 3);
+ return -1;
+ } else {
+ if (header & (1 << 20)) {
+ lsf = (header & (1 << 19)) ? 0 : 1;
+ mpg25 = 0;
+ } else {
+ lsf = 1;
+ mpg25 = 1;
+ }
+ }
+
+ /* if it's an invalid layer */
+ if (!((header >> 17) & 3)) {
+ g_print("[ERROR] invalid layer: %d\n", (header >> 17) & 3);
+ return -1;
+ } else {
+ layer = 4 - ((header >> 17) & 0x3);
+ }
+
+ /* if it's an invalid bitrate */
+ if (((header >> 12) & 0xf) == 0xf) {
+ g_print ("[ERROR] invalid bitrate: %d\n", (header >> 12) & 0xf);
+ return -1;
+ } else {
+ bitrate = (header >> 12) & 0xF;
+ hdr_bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
+ /* The caller has ensured we have a valid header, so bitrate can't be zero here. */
+ if(hdr_bitrate == 0)
+ return -1;
+ }
+
+ /* if it's an invalid samplerate */
+ if (((header >> 10) & 0x3) == 0x3) {
+ g_print ("[ERROR] invalid samplerate: %d\n", (header >> 10) & 0x3);
+ return -4;
+ } else {
+ sf = (header >> 10) & 0x3;
+ sf = mp3types_freqs[lsf + mpg25][sf];
+ }
+
+ padding = (header >> 9) & 0x1;
+
+ switch (layer) {
+ case 1:
+ readsize = 4 * ((hdr_bitrate * 12) / sf + padding);
+ break;
+ case 2:
+ readsize = (hdr_bitrate * 144) / sf + padding;
+ break;
+ default:
+ case 3:
+ readsize = (hdr_bitrate * 144) / (sf << lsf) + padding;
+ break;
+ }
+#else //simple extract code - hard coding test code for supporting only 'test.mp3'
+ readsize = 1044 + ((header >> 9) & 0x1); //only simple test => (1044 + padding)
+#endif
+
+ if (readsize > 0) {
+ result = fread(buffer+4, 1, (readsize - 4), fd);
+ memcpy(mp3data, buffer,readsize);
+ } else {
+ readsize = 0;
+ g_print("[FAIL] Not found mp3 frame sync.....\n");
+ }
+
+ return readsize;
+}
+
+
+/**
+ * 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 hader_size = ADTS_HEADER_SIZE;
+ unsigned char buffer[1000000];
+
+ if (feof(fd))
+ return 0;
+
+ result = fread(buffer, 1, hader_size, fd); //adts header
+ if(result != hader_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 + hader_size, 1,(readsize - hader_size), fd);
+ memcpy(aacdata, buffer, readsize);
+ } else {
+ readsize = 0;
+ g_print("[FAIL] Not found aac frame sync.....\n");
+ }
+
+ return readsize;
+}
+
+#ifdef HE_AAC_V12_ENABLE
+/**
+ * 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 hader_size = ADTS_HEADER_SIZE;
unsigned char buffer[1000000];
+ unsigned char codecdata[AUDIO_CODECDATA_SIZE] = {0,};
if (feof(fd))
return 0;
- result = fread(buffer, 1,6, fd);
- 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
+ /*
+ * 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, AUDIO_CODECDATA_SIZE);
+
+ result = fread(buffer, 1, hader_size, fd); //adts header
+ if(result != hader_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);
+ readsize = readsize -hader_size;
+ result = fread(buffer, 1, readsize, fd); //Make only RAW data, so exclude header 7 bytes
+ memcpy(aacdata+AUDIO_CODECDATA_SIZE, buffer, readsize);
+ }
+
+ g_print( "[example] Insert 'codec_data' in 1st frame buffer size (%d)\n", readsize+AUDIO_CODECDATA_SIZE);
+ return (readsize + AUDIO_CODECDATA_SIZE); //return combination of (codec_data + raw_data)
+ }
+
+ result = fread(buffer, 1, hader_size, fd); //adts header
+ if(result != hader_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 -hader_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
+}
+#endif
+
+
+/**
+ * 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)
+ exit(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)
+ exit(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)
+ exit(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 AAC encoder
+ **/
unsigned int extract_input_aacenc(FILE *fd, unsigned char* rawdata)
{
int readsize;
* This is needed as MediaCodec encoder generates a packet of raw AAC data.
* Note the packetLen must count in the ADTS header itself.
**/
-void add_adts_to_packet(unsigned char *buffer, int packetLen) {
+void add_adts_header_for_aacenc(unsigned char *buffer, int packetLen) {
int profile = 2; //AAC LC (0x01)
int freqIdx = 3; //48KHz (0x03)
int chanCfg = 2; //CPE (0x02)
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)
+ {
+ exit(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);
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);
{
int i = 0;
- if (input_avaliable)
- mc_async_queue_free(input_avaliable);
+ //mc_async_queue_free(input_avaliable);
if (input_buf)
{
}
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
{
#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);
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;
g_print("mediacodec_destroy\n");
- g_atomic_int_set(&pa_running, 0);
- g_thread_join(pa_thread);
-
for (i = 0; i < g_handle_num; i++)
{
if(g_media_codec[i] != NULL)
if (encoder)
{
//input_fmt->mimetype |= MEDIA_FORMAT_RAW;
- //input_fmt->mimetype |= MEDIA_FORMAT_NV12;
+ mimetype |= MEDIA_FORMAT_NV12;
mimetype |= MEDIA_FORMAT_RAW;
- mimetype |= MEDIA_FORMAT_I420;
+ //mimetype |= MEDIA_FORMAT_I420;
}
else
{
}
else
{
- mimetype |= MEDIA_FORMAT_AAC;
+ 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;
}
mimetype |= MEDIA_FORMAT_AUDIO;
- g_print(" [audio test] mimetype (0x%x)\n", mimetype);
+ g_print("[audio test] mimetype (0x%x)\n", mimetype);
}
}
else
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)
return;
}
+//#define AUDIO_EOS_TEST
+#ifdef AUDIO_EOS_TEST
+#define AUDIO_AAC_EOS_TEST 2851 /* test.aac */
+#define AUDIO_AAC_EOS_TEST 51 /* test50f.aac*/
+#define AUDIO_MP3_EOS_TEST 1756
+#endif
int _mediacodec_process_input(void)
{
- g_print("_mediacodec_process_input\n");
+// g_print("_mediacodec_process_input (frame_count :%d)\n", frame_count);
unsigned int buf_size = 0;
#if USE_INPUT_QUEUE
media_packet_h in_buf = NULL;
#endif
void *data = NULL;
int ret = 0;
+ mediacodec_s * handle = NULL;
+ mc_handle_t* mc_handle = NULL;
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 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);
{
if (use_video)
{
+ /*
+ * Video Encoder
+ */
buf_size = bytestream2yuv420(fp_src, data);
media_packet_set_pts (in_buf, pts);
g_print("input pts = %llu\n", pts);
}
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);
}
}
}
{
if (use_video)
{
- if(frame_count == 0)
- ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG);
- else if(frame_count == 1258)
- 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);
buf_size = bytestream2nalunit(fp_src, data);
+
+ if(frame_count == 2)
+ ret = media_packet_set_flags(in_buf, MEDIA_PACKET_CODEC_CONFIG);
+ //mc_hex_dump("nal",data, 16);
}
else
- buf_size = extract_input_aacdec(fp_src, data);
+ {
+ /*
+ * Audio Decoder - AAC_LC (adts) / MP3 / AMR-NB / AMR-WB
+ * - AAC_HE (v1) / AAC_HE_PS (v2)
+ */
+ if (mimetype == MEDIA_FORMAT_AAC_LC)
+ {
+#ifdef AUDIO_EOS_TEST
+ if(frame_count == AUDIO_AAC_EOS_TEST) {
+ ret = media_packet_set_flags(in_buf, MEDIA_PACKET_END_OF_STREAM);
+ g_print("ret (%d) Set MEDIA_PACKET_END_OF_STREAM at frame_count = %d\n", ret, frame_count);
+ }
+#endif
+ buf_size = extract_input_aacdec(fp_src, data);
+ }
+ else if (mimetype == MEDIA_FORMAT_AAC_HE || mimetype == MEDIA_FORMAT_AAC_HE_PS)
+ {
+#ifdef HE_AAC_V12_ENABLE
+ 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);
+#endif
+ }
+ 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
+ {
+ g_print(" [Input process] Not Suppor Audio Decodert!!!!! - mimetype (0x%x) codecid (0x%x)\n", mimetype, mc_handle->codec_id);
+ }
+ }
}
- if (buf_size == 0)
- {
- g_print("input file read failed\n");
- return MEDIACODEC_ERROR_INVALID_PARAMETER;
+
+ if(buf_size > 0) {
+
+ if(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);
+
+ 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;
+ }
+#ifdef AUDIO_EOS_TEST
+ else if(mimetype == MEDIA_FORMAT_AAC_LC && frame_count == AUDIO_AAC_EOS_TEST)
+ {
+ g_print("%s - AAC END : input_buf size = %d frame_count : %d\n",__func__, buf_size, frame_count);
+ return MEDIACODEC_ERROR_INVALID_INBUFFER;
+ }
+ else if(mimetype == MEDIA_FORMAT_MP3 && frame_count == AUDIO_MP3_EOS_TEST)
+ {
+ g_print("%s -MP3 END : input_buf size = %d frame_count : %d\n",__func__, buf_size, frame_count);
+ return MEDIACODEC_ERROR_INVALID_INBUFFER;
+ }
+#endif
}
- 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);
frame_count++;
+
return ret;
}
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)
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)
{
- add_adts_to_packet(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;
+ }
}
}
}
return;
}
-
-int _mediacodec_pa_runcheck(void)
+static gpointer vdec_task(gpointer data)
{
- return pa_running;
+ int i;
+ //TODO extract packets from MediaDemuxer
+ /*
+ for(i=0; demuxer->get_track_count; i++)
+ {
+ }
+ */
+ return NULL;
}
-#if 0 //to avoid build error until this code is not compatible with glib2.0
-static gpointer _feed_pa(gpointer data)
+
+void _mediacodec_process_all(void)
{
- int ret = 0;
+ g_print("_mediacodec_process_all\n");
+ int ret = MEDIACODEC_ERROR_NONE;
+ GThread *vdec_thread, *venc_thread, *adec_thread, *aenc_thread;
- while (1) //FIXME crash g_atomic_int_get(&pa_running)
+ while(1)
{
- if (!_mediacodec_pa_runcheck())
- break;
ret = _mediacodec_process_input();
- if (ret == MEDIACODEC_ERROR_INVALID_PARAMETER)
+
+ if(ret != MEDIACODEC_ERROR_NONE) {
+ g_print ("_mediacodec_process_input ret = %d\n", ret);
break;
-// ret = _mediacodec_get_output();
- usleep(100);
+ }
}
+
/*
- while (1) //FIXME crash g_atomic_int_get(&pa_running)
+ if(use_encoder)
{
- if (!_mediacodec_pa_runcheck())
- break;
- ret = _mediacodec_get_output();
- usleep(100);
+ if(use_video)
+ {
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ if(use_video)
+ {
+ vdec_thread = g_thread_create(vdec_task, NULL, TRUE, NULL);
+
+ g_thread_join(vdec_thread);
+ }
+ else
+ {
+ }
+
}
*/
- g_print("_feed_pa task finished\n");
- return NULL;
-}
-#endif
-void _mediacodec_process_all(void)
-{
- g_print("_mediacodec_process_all\n");
- pa_running = 1;
- // pa_thread = g_thread_create(_feed_pa, GINT_TO_POINTER(1), TRUE, NULL); //to avoid build error until this code is not compatible with glib2.0
return;
}
}
else if (g_menu_state == CURRENT_STATUS_SET_CODEC)
{
+#if 1 //NEW
+ g_print("*** Codec id : Select Codec ID Numbe (e.g. AAC_LC = 96)\n");
+ g_print(" L16 = 16 (0x10)\n");
+ g_print(" ALAW = 32 (0x20)\n");
+ g_print(" ULAW = 48 (0x30)\n");
+ g_print(" AMR_NB = 64 (0x40)\n");
+ g_print(" AMR_WB = 65 (0x41)\n");
+ g_print(" G729 = 80 (0x50)\n");
+ g_print(" AAC_LC = 96 (0x60)\n");
+ g_print(" AAC_HE = 97 (0x61)\n");
+ g_print(" AAC_PS = 98 (0x62)\n");
+ g_print(" MP3 = 112 (0x70)\n");
+ g_print(" VORBIS = 128 (0x80)\n");
+ g_print(" -------------------\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, falgs.\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");
g_print(" MPEG2 = 106\n");
g_print(" MPEG4 = 107\n");
g_print("*** input codec id, falgs.\n");
+#endif
}
else if (g_menu_state == CURRENT_STATUS_SET_VDEC_INFO)
{
}
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)
{
case 0:
tmp = atoi(cmd);
- if(tmp > 100)
+#if 1 //NEW - ToDo : BUG for case of MP3 (112 = 0x70)
+ if(tmp > 100 && tmp != 112 && tmp != 128) //Temporary - exclude MP3 and VORBIS
+#else
+ if(tmp > 100) //orginal
+#endif
{
tmp = strtol(cmd, ptr, 16);
codecid = 0x2000 + ((tmp & 0xFF) << 4);
}
else
{
+#if 1 //NEW
+ codecid = 0x1000 + tmp;
+#else
codecid = 0x1000 + (tmp<<4);
+#endif
}
cnt++;
break;
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");