X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=test%2Fmedia_codec_test.c;h=505dede7a5b99dca0319b90495742d54a590cb44;hb=989a02973e6a78aafea7553642935baafedffa81;hp=67cab1c4d02d442b1e1468a60cf2550a0d84a129;hpb=748a8b0298821448aec56c5aa3acb28366c1914f;p=platform%2Fcore%2Fapi%2Fmediacodec.git diff --git a/test/media_codec_test.c b/test/media_codec_test.c old mode 100755 new mode 100644 index 67cab1c..505dede --- a/test/media_codec_test.c +++ b/test/media_codec_test.c @@ -20,12 +20,18 @@ #include #include #include +#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include +#include #define PACKAGE "media_codec_test" #define MAX_HANDLE 4 @@ -53,12 +59,8 @@ ((state & (expected_state)) == (expected_state)) #define AAC_CODECDATA_SIZE 16 -static int samplerate = DEFAULT_SAMPPLERATE; -static int channel = DEFAULT_CHANNEL; -static int bit = DEFAULT_BIT; -static int bitrate = DEFAULT_BITRATE; -static int samplebyte = DEFAULT_SAMPLEBYTE; -unsigned char buf_adts[ADTS_HEADER_SIZE]; + +guint8 buf_adts[ADTS_HEADER_SIZE]; enum { MC_EXIST_SPS = 1 << 0, @@ -88,6 +90,7 @@ enum { CURRENT_STATUS_GET_OUTPUT, CURRENT_STATUS_RESET_OUTPUT_BUFFER, CURRENT_STATUS_SET_SIZE, + CURRENT_STATUS_AUTO_TEST, }; typedef enum { @@ -117,25 +120,44 @@ typedef enum { struct _App { GMainLoop *loop; guint sourceid; + guint audio_id; + guint video_id; GMappedFile *file; guint8 *data; - gsize length; - guint64 offset; - guint obj; + gint length; + gint offset; + gint obj; GTimer *timer; - long start; - long finish; - long process_time; - int frame_count; - - int codecid; - int flag; - bool is_video[MAX_HANDLE]; - bool is_encoder[MAX_HANDLE]; - bool hardware; + glong start; + glong finish; + glong process_time; + gint frame_count; + + gint codecid; + gint flag; + gboolean is_video; + gboolean is_encoder; + gboolean hardware; + gboolean enable_dump; + gint frame; type_e type; + camera_h camera_handle; + + GThread *thread; + GCond thread_cond; + GMutex thread_mutex; + GMutex eos_mutex; + GCond eos_cond; + GCond dst_eos_cond; + gint demux_eos; + gint codec_eos; + gint suspend; + gchar filepath[256]; + /* demuxer */ + mediademuxer_h demuxer; + media_format_h format[MAX_HANDLE]; /* video */ mediacodec_h mc_handle[MAX_HANDLE]; guint width; @@ -143,14 +165,15 @@ struct _App { guint fps; guint target_bits; media_format_mimetype_e mime; + gint video_track; /* Audio */ guint samplerate; guint channel; guint bit; guint bitrate; - bool is_amr_nb; - + gboolean is_amr_nb; + gint audio_track; /* Render */ guint w; @@ -161,47 +184,52 @@ struct _App { Ecore_Pipe *pipe; GList *packet_list; GMutex lock; + + gint etb; + gint ftb; + gint ebd; + gint fbd; }; App s_app; -media_format_h aenc_fmt = NULL; -media_format_h adec_fmt = NULL; -media_format_h vdec_fmt = NULL; -media_format_h venc_fmt = NULL; - -#if DUMP_OUTBUF -FILE *fp_out = NULL; -#endif +media_format_h fmt = NULL; +media_packet_pool_h pkt_pool = NULL; /* Internal Functions */ -static int _create_app(void *data); -static int _terminate_app(void *data); -static void displaymenu(void); -static void display_sub_basic(); - +gint _create_app(void *data); +gint _terminate_app(void *data); +void displaymenu(void); +void display_sub_basic(); + +void _mediacodec_unprepare(App *app); +void _mediacodec_destroy(App *app); +void _mediacodec_auto_test(App *app, char *path); +void input_filepath(char *filename, App *app); /* For debugging */ -static void mc_hex_dump(char *desc, void *addr, int len); -static void decoder_output_dump(App *app, media_packet_h pkt); - +void mc_hex_dump(char *desc, void *addr, gint len); +void decoder_output_dump(App *app, media_packet_h pkt); +void output_dump(App *app, media_packet_h pkt); /* */ +const char* codec_type_to_string(mediacodec_codec_type_e media_codec_id); -void (*extractor)(App *app, unsigned char** data, int *size, bool *have_frame); +void (*extractor)(App *app, guint8** data, gint *size, gboolean *have_frame, gboolean *codec_data); -int g_menu_state = CURRENT_STATUS_MAINMENU; +gint g_menu_state = CURRENT_STATUS_MAINMENU; +void demuxer_error_cb(mediademuxer_error_e error, void *user_data); -static int _create_app(void *data) +gint _create_app(void *data) { - printf("My app is going alive!\n"); + g_print("My app is going alive!\n"); App *app = (App*)data; g_mutex_init(&app->lock); return 0; } -static int _terminate_app(void *data) +gint _terminate_app(void *data) { - printf("My app is going gone!\n"); + g_print("My app is going gone!\n"); App *app = (App*)data; g_mutex_clear(&app->lock); @@ -232,20 +260,18 @@ static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000}, {11025, 12000, 8000} }; -void h264_extractor(App *app, unsigned char **data, int *size, bool *have_frame) +void h264_extractor(App *app, guint8 **data, gint *size, gboolean *have_frame, gboolean *codec_data) { - int nal_length = 0; - unsigned char val, zero_count; - unsigned char *pNal = app->data + app->offset; - int max = app->length - app->offset; - int i = 0; - int index = 0; - int nal_unit_type = 0; - bool init; - bool slice; - bool idr; - static int state; - int read; + guint8 val, zero_count; + guint8 *pNal = app->data + app->offset; + gint max = app->length - app->offset; + gint index = 0; + gint nal_unit_type = 0; + gboolean init; + gboolean slice; + gboolean idr; + static gint state; + gint read; zero_count = 0; @@ -331,21 +357,18 @@ DONE: app->offset += read; } -void h263_extractor(App * app, unsigned char **data, int *size, bool * have_frame) +void h263_extractor(App * app, guint8 **data, gint *size, gboolean * have_frame, gboolean *codec_data) { int len = 0; - size_t result; int read_size = 1, state = 1, bStart = 0; - unsigned char val; - unsigned char *pH263 = app->data + app->offset; + guint8 val; + guint8 *pH263 = app->data + app->offset; *data = pH263; int max = app->length - app->offset; - *have_frame = TRUE; while (1) { if (len >= max) { read_size = (len - 1); - *have_frame = FALSE; goto DONE; } val = pH263[len++]; @@ -376,23 +399,22 @@ void h263_extractor(App * app, unsigned char **data, int *size, bool * have_fram DONE: *size = read_size; app->offset += read_size; + *have_frame = TRUE; } -void mpeg4_extractor(App * app, unsigned char **data, int *size, bool * have_frame) +void mpeg4_extractor(App * app, guint8 **data, gint *size, gboolean * have_frame, gboolean *codec_data) { - int static temp; int len = 0; - int result; - int read_size = 1, state = 1, bType = 0, bStart = 0; - unsigned char val; - unsigned char *pMpeg4 = app->data + app->offset; + int result = 0; + int state = 1, bType = 0; + guint8 val; + guint8 *pMpeg4 = app->data + app->offset; *data = pMpeg4; int max = app->length - app->offset; while (1) { if (len >= max) { - read_size = (len - 1); - *have_frame = FALSE; + result = (len - 1); goto DONE; } @@ -410,9 +432,9 @@ void mpeg4_extractor(App * app, unsigned char **data, int *size, bool * have_fra state = 1; break; case 3: - if (val == 0x01) { + if (val == 0x01) state++; - } else + else state = 1; break; case 4: @@ -423,7 +445,7 @@ void mpeg4_extractor(App * app, unsigned char **data, int *size, bool * have_fra goto DONE; } if (!bType) { - if (have_frame && val == 0xB0) + if (val == 0xB0) *have_frame = TRUE; } bType = val; @@ -442,23 +464,21 @@ void mpeg4_extractor(App * app, unsigned char **data, int *size, bool * have_fra * - 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"; +gint write_amr_header = 1; /* write magic number for AMR Header at one time */ +static const gchar AMR_header[] = "#!AMR\n"; +static const gchar 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 }; +static const gint block_size_nb[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 }; +static const gint block_size_wb[16] = { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, -1, -1, -1, -1, 0, 0 }; -int *blocksize_tbl; -void amrdec_extractor(App * app, unsigned char **data, int *size, bool * have_frame) +gint *blocksize_tbl; +void amrdec_extractor(App * app, guint8 **data, gint *size, gboolean * have_frame, gboolean *codec_data) { - int readsize = 0, mode_temp; - size_t result; - unsigned int mime_size = AMR_NB_MIME_HDR_SIZE; - unsigned int fsize, mode; - unsigned char *pAmr = app->data + app->offset; - int max = app->length - app->offset; - //change the below one to frame count + gint readsize = 0, mode_temp; + gint fsize, mode; + guint8 *pAmr = app->data + app->offset; + /* change the below one to frame count */ if (app->offset == 0) { if (!memcmp(pAmr, AMR_header, AMR_NB_MIME_HDR_SIZE)) { blocksize_tbl = (int *)block_size_nb; @@ -467,14 +487,13 @@ void amrdec_extractor(App * app, unsigned char **data, int *size, bool * have_fr app->offset += AMR_NB_MIME_HDR_SIZE; } else { if (!memcmp(pAmr, AMRWB_header, AMR_WB_MIME_HDR_SIZE)) { - mime_size = AMR_WB_MIME_HDR_SIZE; blocksize_tbl = (int *)block_size_wb; mode_temp = pAmr[AMR_WB_MIME_HDR_SIZE]; pAmr = pAmr + AMR_WB_MIME_HDR_SIZE; app->offset += AMR_WB_MIME_HDR_SIZE; } else { g_print("[ERROR] AMR-NB/WB don't detected..\n"); - return 0; + return; } } } @@ -488,17 +507,16 @@ void amrdec_extractor(App * app, unsigned char **data, int *size, bool * have_fr g_print("[FAIL] Not found amr frame sync.....\n"); } - DONE: *size = readsize; app->offset += readsize; *data = pAmr; *have_frame = TRUE; } -void nv12_extractor(App *app, unsigned char **data, int *size, bool *have_frame) +void nv12_extractor(App *app, guint8 **data, gint *size, gboolean *have_frame, gboolean *codec_data) { - int yuv_size; - int offset = app->length - app->offset; + gint yuv_size; + gint offset = app->length - app->offset; yuv_size = app->width * app->height * 3 / 2; @@ -508,16 +526,18 @@ void nv12_extractor(App *app, unsigned char **data, int *size, bool *have_frame) *have_frame = TRUE; *data = app->data + app->offset; - if (offset >= yuv_size) + if (yuv_size >= offset) *size = offset; else *size = yuv_size; + + app->offset += *size; } -void yuv_extractor(App *app, unsigned char **data, int *size, bool *have_frame) +void yuv_extractor(App *app, guint8 **data, int *size, gboolean *have_frame, gboolean *codec_data) { - int yuv_size; - int offset = app->length - app->offset; + gint yuv_size; + gint offset = app->length - app->offset; yuv_size = app->width * app->height * 3 / 2; @@ -533,20 +553,19 @@ void yuv_extractor(App *app, unsigned char **data, int *size, bool *have_frame) *size = yuv_size; app->offset += *size; - } -void aacenc_extractor(App *app, unsigned char **data, int *size, bool *have_frame) +void aacenc_extractor(App *app, guint8 **data, int *size, gboolean *have_frame, gboolean *codec_data) { - int read_size; - int offset = app->length - app->offset; - - read_size = ((samplebyte*app->channel)*(app->bit/8)); + gint read_size; + gint offset = app->length - app->offset; + read_size = ((DEFAULT_SAMPLEBYTE * app->channel)*(app->bit/8) * 2); *have_frame = TRUE; + *data = app->data + app->offset; - if (offset >= read_size) + if (read_size >= offset) *size = offset; else *size = read_size; @@ -554,10 +573,10 @@ void aacenc_extractor(App *app, unsigned char **data, int *size, bool *have_fram app->offset += *size; } -void amrenc_extractor(App *app, unsigned char **data, int *size, bool *have_frame) +void amrenc_extractor(App *app, guint8 **data, int *size, gboolean *have_frame, gboolean *codec_data) { - int read_size; - int offset = app->length - app->offset; + gint read_size; + gint offset = app->length - app->offset; if (app->is_amr_nb) read_size = AMRNB_PCM_INPUT_SIZE; @@ -565,8 +584,9 @@ void amrenc_extractor(App *app, unsigned char **data, int *size, bool *have_fram read_size = AMRWB_PCM_INPUT_SIZE; *have_frame = TRUE; + *data = app->data + app->offset; - if (offset >= read_size) + if (read_size >= offset) *size = offset; else *size = read_size; @@ -579,11 +599,11 @@ void amrenc_extractor(App *app, unsigned char **data, int *size, bool *have_fram * (case of (LC profile) ADTS format) * codec_data : Don't need **/ -void aacdec_extractor(App *app, unsigned char **data, int *size, bool *have_frame) +void aacdec_extractor(App *app, guint8 **data, int *size, gboolean *have_frame, gboolean *codec_data) { int read_size; int offset = app->length - app->offset; - unsigned char *pData = app->data + app->offset; + guint8 *pData = app->data + app->offset; if ((pData != NULL) && (pData[0] == 0xff) && ((pData[1] & 0xf6) == 0xf0)) { read_size = ((pData[3] & 0x03) << 11) | (pData[4] << 3) | ((pData[5] & 0xe0) >> 5); @@ -601,34 +621,36 @@ void aacdec_extractor(App *app, unsigned char **data, int *size, bool *have_fram *size = read_size; app->offset += *size; - } -void mp3dec_extractor(App *app, unsigned char **data, int *size, bool *have_frame) +void mp3dec_extractor(App *app, guint8 **data, int *size, gboolean *have_frame, gboolean *codec_data) { - int read_size; + gint read_size; guint header; - guint padding, bitrate, lsf, layer, mpg25; - guint hdr_bitrate, sf; - int offset = app->length - app->offset; - unsigned char *pData = app->data + app->offset; + guint padding, bitrate, lsf = 0, layer = 0, mpg25 = 0; + guint hdr_bitrate = 0, sf = 0; + gint offset = app->length - app->offset; + guint8 *pData = app->data + app->offset; header = GST_READ_UINT32_BE(pData); if (header == 0) { g_print ("[ERROR] read header size is 0\n"); *have_frame = FALSE; + return; } /* if it's not a valid sync */ if ((header & 0xffe00000) != 0xffe00000) { g_print ("[ERROR] invalid sync\n"); *have_frame = FALSE; + return; } if (((header >> 19) & 3) == 0x1) { g_print ("[ERROR] invalid MPEG version: %d\n", (header >> 19) & 3); *have_frame = FALSE; + return; } else { if (header & (1 << 20)) { lsf = (header & (1 << 19)) ? 0 : 1; @@ -643,6 +665,7 @@ void mp3dec_extractor(App *app, unsigned char **data, int *size, bool *have_fram if (!((header >> 17) & 3)) { g_print("[ERROR] invalid layer: %d\n", (header >> 17) & 3); *have_frame = FALSE; + return; } else { layer = 4 - ((header >> 17) & 0x3); } @@ -651,18 +674,22 @@ void mp3dec_extractor(App *app, unsigned char **data, int *size, bool *have_fram if (((header >> 12) & 0xf) == 0xf) { g_print ("[ERROR] invalid bitrate: %d\n", (header >> 12) & 0xf); *have_frame = FALSE; + return; } 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) + if (hdr_bitrate == 0) { *have_frame = FALSE; + return; + } } /* if it's an invalid samplerate */ if (((header >> 10) & 0x3) == 0x3) { g_print ("[ERROR] invalid samplerate: %d\n", (header >> 10) & 0x3); *have_frame = FALSE; + return; } else { sf = (header >> 10) & 0x3; sf = mp3types_freqs[lsf + mpg25][sf]; @@ -695,111 +722,11 @@ void mp3dec_extractor(App *app, unsigned char **data, int *size, bool *have_fram app->offset += *size; } -#if 1 -void extract_input_aacdec_m4a_test(App * app, unsigned char **data, int *size, bool * have_frame) -{ - int readsize = 0, read_size = 0; - size_t result; - unsigned int header_size = ADTS_HEADER_SIZE; - unsigned char buffer[1000000]; - unsigned char codecdata[AAC_CODECDATA_SIZE] = { 0, }; - int offset = app->length - app->offset; - unsigned char *pData = app->data + app->offset; - /* - * It is not support full parsing MP4 container box. - * So It MUST start as RAW valid frame sequence. - * Testsuit that are not guaranteed to be available on functionality of all General DEMUXER/PARSER. - */ - - //change the below one later - if (app->offset == 0) { - /* - * CAUTION : Codec data is needed only once in first time - * Codec data is made(or extracted) by MP4 demuxer in 'esds' box. - * So I use this data (byte) as hard coding for temporary our testing. - */ -#if 1 - /* - * The codec_data data is according to AudioSpecificConfig, - * ISO/IEC 14496-3, 1.6.2.1 - * - * below example is test for using "test.aac" or "TestSample-AAC-LC.m4a" - * case : M4A - LC profile - * codec_data=(buffer)119056e5000000000000000000000000 - * savs aac decoder get codec_data. size: 16 (Tag size : 5 byte) - * - codec data: profile : 2 - * - codec data: samplrate: 48000 - * - codec data: channels : 2 - */ - /* 2 bytes are mandatory */ - codecdata[0] = 0x11; /* ex) (5bit) 2 (LC) / (4bit) 3 (48khz)*/ - codecdata[1] = 0x90; /* ex) (4bit) 2 (2ch) */ - /* othter bytes are (optional) epconfig information */ - codecdata[2] = 0x56; - codecdata[3] = 0xE5; - codecdata[4] = 0x00; -#else - /* - * below example is test for using "TestSample-EAAC+.m4a" - * - * case : M4A - HE-AAC v1 and v2 profile - * codec_data=(buffer)138856e5a54880000000000000000000 - * savs aac decoder get codec_data. size: 16 (Tag size : 7 byte) - * - codec data: profile : 2 - * - codec data: samplrate: 22050 - * - codec data: channels : 1 - */ - /* 2 bytes are mandatory */ - codecdata[0] = 0x13; /* ex) (5bit) 2 (LC) / (4bit) 9 (22khz) */ - codecdata[1] = 0x88; /* ex) (4bit) 1 (1ch) */ - /* othter bytes are (optional) epconfig information */ - codecdata[2] = 0x56; - codecdata[3] = 0xE5; - codecdata[4] = 0xA5; - codecdata[5] = 0x48; - codecdata[6] = 0x80; -#endif - - memcpy(buffer, codecdata, AAC_CODECDATA_SIZE); - if ((pData != NULL) && (pData[0] == 0xff) && ((pData[1] & 0xf6) == 0xf0)) { - read_size = ((pData[3] & 0x03) << 11) | (pData[4] << 3) | ((pData[5] & 0xe0) >> 5); - } else { - read_size = 0; - g_print("[FAIL] Not found aac frame sync.....\n"); - } - readsize = read_size - header_size; - memcpy(buffer + AAC_CODECDATA_SIZE, pData + 7, readsize); - read_size = readsize + AAC_CODECDATA_SIZE; //return combination of (codec_data + raw_data) - app->offset += header_size + readsize; - goto DONE; - } - - if ((pData != NULL) && (pData[0] == 0xff) && ((pData[1] & 0xf6) == 0xf0)) { - read_size = ((pData[3] & 0x03) << 11) | (pData[4] << 3) | ((pData[5] & 0xe0) >> 5); - readsize = read_size - header_size; - memcpy(buffer, pData + 7, readsize); //Make only RAW data, so exclude header 7 bytes - read_size = readsize; - app->offset += header_size + readsize; - - } else { - read_size = 0; - g_print("[FAIL] Not found aac frame sync. \n"); - } - DONE: - *data = buffer; - *have_frame = TRUE; - if (read_size >= offset) - *size = offset; - else - *size = read_size; -} -#endif - /** * Extract Input data for AAC encoder **/ /* - void aacenc_extractor(App *app, unsigned char **data, int *size, bool *have_frame) + void aacenc_extractor(App *app, guint8 **data, int *size, gboolean *have_frame) { int read_size; int offset = app->length - app->offset; @@ -820,27 +747,20 @@ void extract_input_aacdec_m4a_test(App * app, unsigned char **data, int *size, b app->offset += *size; } */ -static void _mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data) -{ - if (pkt != NULL) { - g_print("Used input buffer = %p\n", pkt); - media_packet_destroy(pkt); - } - return; -} - -int _mediacodec_set_codec(int codecid, int flag, int *hardware) +int _configure(App *app, int codecid, int flag, gboolean *hardware, media_format_mimetype_e *codec_mime) { - bool encoder; - media_format_mimetype_e mime; + gboolean encoder; + media_format_mimetype_e mime = 0; encoder = GET_IS_ENCODER(flag) ? 1 : 0; *hardware = GET_IS_HW(flag) ? 1 : 0; + app->is_encoder = encoder; switch (codecid) { case MEDIACODEC_H264: if (encoder) { extractor = yuv_extractor; mime = *hardware ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420; + *codec_mime = MEDIA_FORMAT_H264_SP; } else { extractor = h264_extractor; mime = MEDIA_FORMAT_H264_SP; @@ -850,6 +770,7 @@ int _mediacodec_set_codec(int codecid, int flag, int *hardware) if (encoder) { extractor = yuv_extractor; mime = *hardware ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420; + *codec_mime = MEDIA_FORMAT_MPEG4_SP; } else { extractor = mpeg4_extractor; mime = MEDIA_FORMAT_MPEG4_SP; @@ -857,17 +778,19 @@ int _mediacodec_set_codec(int codecid, int flag, int *hardware) break; case MEDIACODEC_H263: if (encoder) { - extractor = h263_extractor; + extractor = yuv_extractor; mime = *hardware ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420; + *codec_mime = MEDIA_FORMAT_H263; } else { extractor = h263_extractor; - mime = MEDIA_FORMAT_H263P; + mime = MEDIA_FORMAT_H263; } break; case MEDIACODEC_AAC: if (encoder) { extractor = aacenc_extractor; - mime = MEDIA_FORMAT_PCM; + mime = MEDIA_FORMAT_PCM_F32LE; /* FIXME need to check according to verdor */ + *codec_mime = MEDIA_FORMAT_AAC; } else { extractor = aacdec_extractor; mime = MEDIA_FORMAT_AAC; @@ -876,10 +799,8 @@ int _mediacodec_set_codec(int codecid, int flag, int *hardware) case MEDIACODEC_AAC_HE: if (encoder) { extractor = aacenc_extractor; - mime = MEDIA_FORMAT_PCM; - } else { - extractor = extract_input_aacdec_m4a_test; - mime = MEDIA_FORMAT_AAC_HE; + mime = MEDIA_FORMAT_PCM_F32LE; /* FIXME need to check according to verdor */ + *codec_mime = MEDIA_FORMAT_AAC_HE; } break; case MEDIACODEC_AAC_HE_PS: @@ -901,12 +822,24 @@ int _mediacodec_set_codec(int codecid, int flag, int *hardware) case MEDIACODEC_WMALSL: break; case MEDIACODEC_AMR_NB: - extractor = amrdec_extractor; - mime = MEDIA_FORMAT_AMR_NB; + if (encoder) { + extractor = amrenc_extractor; + mime = MEDIA_FORMAT_PCM_F32LE; /* FIXME need to check according to verdor */ + app->is_amr_nb = TRUE; + } else { + extractor = amrdec_extractor; + mime = MEDIA_FORMAT_AMR_NB; + } break; case MEDIACODEC_AMR_WB: - extractor = amrdec_extractor; - mime = MEDIA_FORMAT_AMR_WB; + if (encoder) { + extractor = amrenc_extractor; + mime = MEDIA_FORMAT_PCM_F32LE; /* FIXME need to check according to verdor */ + app->is_amr_nb = FALSE; + } else { + extractor = amrdec_extractor; + mime = MEDIA_FORMAT_AMR_WB; + } break; default: LOGE("NOT SUPPORTED!!!!"); @@ -915,28 +848,137 @@ int _mediacodec_set_codec(int codecid, int flag, int *hardware) return mime; } -static gboolean read_data(App *app) +void _mediacodec_process_input(App *app) { - guint len; - bool have_frame = FALSE; - int ret; + gint i; + gboolean have_frame = FALSE; + gint ret; static guint64 pts = 0L; void *buf_data_ptr = NULL; media_packet_h pkt = NULL; - unsigned char *tmp; - int read; - int plane_num; - int offset; - int stride_width, stride_height; + guint8 *tmp; + gint read; + gint size; + gint offset; + gint stride_width; + gboolean codec_config = FALSE; + + for (i = 0; i < app->frame; i++) { + g_print("----------read data------------\n"); + + extractor(app, &tmp, &read, &have_frame, &codec_config); + + if (have_frame) { +#ifdef USE_POOL + if (media_packet_pool_acquire_packet(pkt_pool, &pkt, -1) != MEDIA_PACKET_ERROR_NONE) { + g_print("media_packet_pool_aquire_packet failed\n"); + return; + } +#else + if (media_packet_create_alloc(fmt, NULL, NULL, &pkt) != MEDIA_PACKET_ERROR_NONE) { + g_print("media_packet_create_alloc failed\n"); + return; + } +#endif + + if (media_packet_set_pts(pkt, (uint64_t)(pts)) != MEDIA_PACKET_ERROR_NONE) { + g_print("media_packet_set_pts failed\n"); + return; + } + + if (app->type != VIDEO_ENC) { + media_packet_get_buffer_data_ptr(pkt, &buf_data_ptr); + media_packet_set_buffer_size(pkt, (uint64_t)read); + memcpy(buf_data_ptr, tmp, read); + g_print("tmp:%p, read:%d\n", tmp, read); + } else { + /* Y */ + media_packet_get_video_plane_data_ptr(pkt, 0, &buf_data_ptr); + media_packet_get_video_stride_width(pkt, 0, &stride_width); + offset = app->width*app->height; + + for (i = 0; i < app->height; i++) { + memcpy(buf_data_ptr, tmp, app->width); + buf_data_ptr += stride_width; + tmp += app->width; + } + + if (app->hardware == TRUE) { + media_packet_get_video_plane_data_ptr(pkt, 1, &buf_data_ptr); + media_packet_get_video_stride_width(pkt, 1, &stride_width); + size = app->width * app->height / 2; + + for (i = 0; i < app->height / 2; i++) { + memcpy(buf_data_ptr, tmp, app->width); + buf_data_ptr += stride_width; + tmp += app->width; + } + } else { + /* U */ + media_packet_get_video_plane_data_ptr(pkt, 1, &buf_data_ptr); + media_packet_get_video_stride_width(pkt, 1, &stride_width); + size = (app->width>>1) * (app->height>>1); + + for (i = 0; i < app->height/2; i++) { + memcpy(buf_data_ptr, tmp, app->width/2); + buf_data_ptr += stride_width; + tmp += app->width/2; + } + + /* V */ + media_packet_get_video_plane_data_ptr(pkt, 2, &buf_data_ptr); + media_packet_get_video_stride_width(pkt, 2, &stride_width); + offset += size; + + for (i = 0; i < app->height/2; i++) { + memcpy(buf_data_ptr, tmp, app->width/2); + buf_data_ptr += stride_width; + tmp += app->width/2; + } + + } + } + mc_hex_dump("inbuf", tmp, 48); + + ret = mediacodec_process_input(app->mc_handle[0], pkt, 1000); + if (ret != MEDIACODEC_ERROR_NONE) + return; + + pts += ES_DEFAULT_VIDEO_PTS_OFFSET; + } + } +} + +gboolean read_data(App *app) +{ + guint len = 0; + gboolean have_frame = FALSE; + gboolean codec_config = FALSE; + gint ret; + static guint64 pts = 0L; + void *buf_data_ptr = NULL; + media_packet_h pkt = NULL; + guint8 *tmp; + gint i; + gint read; + gint size; + gint offset; + gint stride_width; + + if (app->offset == 0) { + app->frame_count = 0; + app->start = clock(); + } g_print("----------read data------------\n"); - extractor(app, &tmp, &read, &have_frame); + extractor(app, &tmp, &read, &have_frame, &codec_config); - if (app->offset >= app->length - 1) { + if (app->offset >= app->length - 4) { /* EOS */ g_print("EOS\n"); app->finish = clock(); - g_main_loop_quit(app->loop); + g_print("Average FPS = %3.3f\n", ((double)app->frame_count*1000000/(app->finish - app->start))); + g_print("---------------------------\n"); return FALSE; } g_print("length : %d, offset : %d\n", app->length, app->offset); @@ -947,16 +989,23 @@ static gboolean read_data(App *app) g_print("%p, %d, have_frame :%d, read: %d\n", tmp, (int)read, have_frame, read); if (have_frame) { - if (media_packet_create_alloc(vdec_fmt, NULL, NULL, &pkt) != MEDIA_PACKET_ERROR_NONE) { - fprintf(stderr, "media_packet_create_alloc failed\n"); +#ifdef USE_POOL + if (media_packet_pool_acquire_packet(pkt_pool, &pkt, -1) != MEDIA_PACKET_ERROR_NONE) { + g_print("media_packet_pool_aquire_packet failed\n"); return FALSE; } - +#else + if (media_packet_create_alloc(fmt, NULL, NULL, &pkt) != MEDIA_PACKET_ERROR_NONE) { + g_print("media_packet_create_alloc failed\n"); + return FALSE; + } +#endif if (media_packet_set_pts(pkt, (uint64_t)(pts)) != MEDIA_PACKET_ERROR_NONE) { - fprintf(stderr, "media_packet_set_pts failed\n"); + g_print("media_packet_set_pts failed\n"); return FALSE; } + if (app->type != VIDEO_ENC) { media_packet_get_buffer_data_ptr(pkt, &buf_data_ptr); media_packet_set_buffer_size(pkt, (uint64_t)read); @@ -967,28 +1016,48 @@ static gboolean read_data(App *app) /* Y */ media_packet_get_video_plane_data_ptr(pkt, 0, &buf_data_ptr); media_packet_get_video_stride_width(pkt, 0, &stride_width); - media_packet_get_video_stride_height(pkt, 0, &stride_height); + offset = app->width*app->height; + + for (i = 0; i < app->height; i++) { + memcpy(buf_data_ptr, tmp, app->width); + buf_data_ptr += stride_width; + tmp += app->width; + } - offset = stride_width*stride_height; + if (app->hardware == TRUE) { + media_packet_get_video_plane_data_ptr(pkt, 1, &buf_data_ptr); + media_packet_get_video_stride_width(pkt, 1, &stride_width); + size = app->width * app->height>>1; - memcpy(buf_data_ptr, tmp, offset); + for (i = 0; i < app->height>>1; i++) { + memcpy(buf_data_ptr, tmp, app->width); + buf_data_ptr += stride_width; + tmp += app->width; + } - /* UV or U*/ - media_packet_get_video_plane_data_ptr(pkt, 1, &buf_data_ptr); - media_packet_get_video_stride_width(pkt, 1, &stride_width); - media_packet_get_video_stride_height(pkt, 1, &stride_height); - memcpy(buf_data_ptr, tmp + offset, stride_width*stride_height); + } else { + /* U */ + media_packet_get_video_plane_data_ptr(pkt, 1, &buf_data_ptr); + media_packet_get_video_stride_width(pkt, 1, &stride_width); + size = (app->width>>1) * (app->height>>1); + + for (i = 0; i < app->height/2; i++) { + memcpy(buf_data_ptr, tmp, app->width>>1); + buf_data_ptr += stride_width; + tmp += (app->width>>1); + } - if (app->hardware == FALSE) { /* V */ media_packet_get_video_plane_data_ptr(pkt, 2, &buf_data_ptr); media_packet_get_video_stride_width(pkt, 2, &stride_width); - media_packet_get_video_stride_height(pkt, 2, &stride_height); - - offset += stride_width * stride_height; + offset += size; + for (i = 0; i < app->height/2; i++) { + memcpy(buf_data_ptr, tmp, app->width>>1); + buf_data_ptr += stride_width; + tmp += (app->width>>1); + } - memcpy(buf_data_ptr, tmp + offset, stride_width*stride_height); } } mc_hex_dump("inbuf", tmp, 48); @@ -1003,7 +1072,100 @@ static gboolean read_data(App *app) return TRUE; } -static void start_feed(App *app) +void av_feed_suspend(App *app) +{ + g_mutex_lock(&app->thread_mutex); + app->suspend = 1; + g_print("suspend thread\n"); + g_mutex_unlock(&app->thread_mutex); +} + +void av_feed_resume(App *app) +{ + g_mutex_lock(&app->thread_mutex); + app->suspend = 0; + g_print("resume thread\n"); + g_cond_broadcast(&app->thread_cond); + g_mutex_unlock(&app->thread_mutex); +} + +gpointer av_feed_thread(gpointer data) +{ + App *app = (App *)data; + int ret = 0; + gint track = -1; + + media_packet_h packet = NULL; + track = app->audio_track; + + while (1) { + g_mutex_lock(&app->thread_mutex); + + while (app->suspend != 0) g_cond_wait(&app->thread_cond, &app->thread_mutex); + + g_mutex_unlock(&app->thread_mutex); + + if (app->demux_eos == 1) { + g_print("got eos!!!\n"); + break; + } + + ret = mediademuxer_read_sample(app->demuxer, track, &packet); + if (ret != MEDIACODEC_ERROR_NONE) + return NULL; + + ret = mediacodec_process_input(app->mc_handle[track], packet, 0); + if (ret != MEDIACODEC_ERROR_NONE) + return NULL; + + app->etb++; + + } + + return NULL; +} + +gboolean feed_audio(App *app) +{ + gint ret = 0; + gint track = -1; + + media_packet_h packet = NULL; + track = app->audio_track; + + g_print("read audio sample!!!\n"); + ret = mediademuxer_read_sample(app->demuxer, track, &packet); + if (ret != MEDIACODEC_ERROR_NONE) + return FALSE; + + ret = mediacodec_process_input(app->mc_handle[track], packet, 0); + if (ret != MEDIACODEC_ERROR_NONE) + return FALSE; + + return TRUE; +} + +gboolean feed_video(App *app) +{ + gint ret = 0; + gint track = -1; + + media_packet_h packet = NULL; + track = app->video_track; + + g_print("read video sample!!!\n"); + ret = mediademuxer_read_sample(app->demuxer, track, &packet); + if (ret != MEDIACODEC_ERROR_NONE) + return FALSE; + + ret = mediacodec_process_input(app->mc_handle[track], packet, 0); + if (ret != MEDIACODEC_ERROR_NONE) + return FALSE; + + return TRUE; +} + +void start_feed(App *app) { if (app->sourceid == 0) { app->sourceid = g_idle_add((GSourceFunc)read_data, app); @@ -1011,7 +1173,7 @@ static void start_feed(App *app) } } -static void stop_feed(App *app) +void stop_feed(App *app) { if (app->sourceid != 0) { g_source_remove(app->sourceid); @@ -1020,45 +1182,74 @@ static void stop_feed(App *app) } } -static bool _mediacodec_inbuf_used_cb(media_packet_h pkt, void *user_data) +void _mediacodec_inbuf_used_cb(media_packet_h pkt, void *user_data) { + App *app = (App *)user_data; + g_print("_mediacodec_inbuf_used_cb!!!\n"); +#ifdef USE_POOL + media_packet_pool_release_packet(pkt_pool, pkt); +#else media_packet_destroy(pkt); - return TRUE; +#endif + app->ebd++; + + return; } -static bool _mediacodec_outbuf_available_cb(media_packet_h pkt, void *user_data) +void _audio_outbuf_available_cb(media_packet_h pkt, void *user_data) { media_packet_h out_pkt = NULL; int ret; App *app = (App*)user_data; - g_print("_mediacodec_outbuf_available_cb\n"); + g_print("_audio_outbuf_available_cb\n"); g_mutex_lock(&app->lock); - ret = mediacodec_get_output(app->mc_handle[0], &out_pkt, 0); + ret = mediacodec_get_output(app->mc_handle[app->audio_track], &out_pkt, 0); if (ret != MEDIACODEC_ERROR_NONE) g_print("get_output failed\n"); - //decoder_output_dump(app, out_pkt); + if (app->enable_dump) + output_dump(app, out_pkt); -#if DUMP_OUTBUF - void *data; - int buf_size; - int stride_width, stride_height; + app->frame_count++; + app->fbd++; - media_packet_get_buffer_data_ptr(out_pkt, &data); - media_packet_get_buffer_size(out_pkt, &buf_size); - g_print("output data : %p, size %d\n", data, (int)buf_size); - fwrite(data, 1, buf_size, fp_out); + g_mutex_unlock(&app->lock); -#endif + media_packet_destroy(out_pkt); + out_pkt = NULL; + g_print("done\n"); + + return; +} + +void _video_outbuf_available_cb(media_packet_h pkt, void *user_data) +{ + media_packet_h out_pkt = NULL; + int ret; + + App *app = (App*)user_data; + + g_print("_video_outbuf_available_cb\n"); + + g_mutex_lock(&app->lock); + + ret = mediacodec_get_output(app->mc_handle[app->video_track], &out_pkt, 0); + + if (ret != MEDIACODEC_ERROR_NONE) + g_print("get_output failed\n"); + + if (app->enable_dump) + decoder_output_dump(app, out_pkt); app->frame_count++; + app->fbd++; g_mutex_unlock(&app->lock); @@ -1067,10 +1258,46 @@ static bool _mediacodec_outbuf_available_cb(media_packet_h pkt, void *user_data) out_pkt = NULL; g_print("done\n"); - return TRUE; + return; +} + +void _mediacodec_outbuf_available_cb(media_packet_h pkt, void *user_data) +{ + media_packet_h out_pkt = NULL; + int ret; + + App *app = (App*)user_data; + + g_print("_mediacodec_outbuf_available_cb\n"); + + g_mutex_lock(&app->lock); + + ret = mediacodec_get_output(app->mc_handle[0], &out_pkt, 0); + + if (ret != MEDIACODEC_ERROR_NONE) + g_print("get_output failed\n"); + + if (app->enable_dump) { + if (app->type == VIDEO_DEC) + decoder_output_dump(app, out_pkt); + else + output_dump(app, out_pkt); + } + + app->frame_count++; + app->fbd++; + + + g_mutex_unlock(&app->lock); + + media_packet_destroy(out_pkt); + out_pkt = NULL; + g_print("done\n"); + + return; } -static bool _mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data) +void _mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_data) { g_print("_mediacodec_buffer_status_cb %d\n", status); @@ -1081,74 +1308,149 @@ static bool _mediacodec_buffer_status_cb(mediacodec_status_e status, void *user_ else if (status == MEDIACODEC_ENOUGH_DATA) stop_feed(app); - return TRUE; + return; } -static bool _mediacodec_error_cb(mediacodec_error_e error, void *user_data) +void _av_buffer_status_cb(mediacodec_status_e status, void *user_data) { - return TRUE; + g_print("_av_buffer_status_cb %d\n", status); + + App *app = (App*)user_data; + + if (status == MEDIACODEC_NEED_DATA) + av_feed_resume(app); + else if (status == MEDIACODEC_ENOUGH_DATA) + av_feed_suspend(app); + + return; } -static bool _mediacodec_eos_cb(void *user_data) +void _mediacodec_error_cb(mediacodec_error_e error, void *user_data) { + return; +} + +void demuxer_error_cb(mediademuxer_error_e error, void *user_data) +{ + g_print("Got Error %d from Mediademuxer\n", error); + return; +} + +void _mediacodec_eos_cb(void *user_data) +{ + App *app = (App *)user_data; + + g_print("mediacodec eos\n"); + g_mutex_lock(&app->eos_mutex); + app->codec_eos = 1; + g_mutex_unlock(&app->eos_mutex); + g_cond_broadcast(&app->dst_eos_cond); + return; +} + +void _mediademuxer_eos_cb(int track, void *user_data) +{ + App *app = (App *)user_data; + + g_print("eos track : %d\n", track); + av_feed_suspend(app); + g_print("suspended\n"); + app->demux_eos = 1; + av_feed_resume(app); + g_cond_broadcast(&app->eos_cond); + + return; +} + +gboolean _foreach_cb(mediacodec_codec_type_e codec_type, void *user_data) +{ + g_print("codec type : %x %s\n", codec_type, codec_type_to_string(codec_type)); return TRUE; } -static void _mediacodec_prepare(App *app) +void _mediacodec_prepare(App *app, gboolean frame_all) { int ret; - media_format_mimetype_e mime; + media_format_mimetype_e codec_mime; + media_format_h codec_format; + + g_print("supported codec lists -internal-\n"); + mediacodec_foreach_supported_codec_static((mediacodec_supported_codec_cb)_foreach_cb, app); -#if DUMP_OUTBUF - fp_out = fopen("/tmp/codec_dump.out", "wb"); -#endif /* create instance */ ret = mediacodec_create(&app->mc_handle[0]); if (ret != MEDIACODEC_ERROR_NONE) { g_print("mediacodec_create failed\n"); return; } - +#if 0 /* set codec */ ret = mediacodec_set_codec(app->mc_handle[0], app->codecid, app->flag); if (ret != MEDIACODEC_ERROR_NONE) { g_print("mediacodec_set_codec failed\n"); return; } - - - app->mime = _mediacodec_set_codec(app->codecid, app->flag, &app->hardware); +#endif + /* get mime and link to each codec parser */ + app->mime = _configure(app, app->codecid, app->flag, &app->hardware, &codec_mime); /* set codec info */ - ret = media_format_create(&vdec_fmt); + ret = media_format_create(&fmt); switch (app->type) { case VIDEO_DEC: - ret = mediacodec_set_vdec_info(app->mc_handle[0], app->width, app->height); - media_format_set_video_mime(vdec_fmt, app->mime); - media_format_set_video_width(vdec_fmt, app->width); - media_format_set_video_height(vdec_fmt, app->height); + media_format_set_video_mime(fmt, app->mime); + media_format_set_video_width(fmt, app->width); + media_format_set_video_height(fmt, app->height); + + ret = mediacodec_configure_from_media_format(app->mc_handle[0], fmt, app->flag); + if (ret != MEDIACODEC_ERROR_NONE) + g_print("mediacodec_configure failed\n"); break; case VIDEO_ENC: - ret = mediacodec_set_venc_info(app->mc_handle[0], app->width, app->height, app->fps, app->target_bits); - media_format_set_video_mime(vdec_fmt, app->mime); - media_format_set_video_width(vdec_fmt, app->width); - media_format_set_video_height(vdec_fmt, app->height); - media_format_set_video_avg_bps(vdec_fmt, app->target_bits); + media_format_set_video_mime(fmt, app->mime); + media_format_set_video_width(fmt, app->width); + media_format_set_video_height(fmt, app->height); + media_format_set_video_avg_bps(fmt, app->target_bits); + + media_format_create(&codec_format); + media_format_set_video_mime(codec_format, codec_mime); + media_format_set_video_width(codec_format, app->width); + media_format_set_video_height(codec_format, app->height); + media_format_set_video_avg_bps(codec_format, app->target_bits); + media_format_set_video_frame_rate(codec_format, app->fps); + + ret = mediacodec_configure_from_media_format(app->mc_handle[0], codec_format, app->flag); + if (ret != MEDIACODEC_ERROR_NONE) + g_print("mediacodec_configure failed\n"); + media_format_unref(codec_format); break; case AUDIO_DEC: - ret = mediacodec_set_adec_info(app->mc_handle[0], app->samplerate, app->channel, app->bit); - media_format_set_audio_mime(vdec_fmt, app->mime); - media_format_set_audio_channel(vdec_fmt, app->channel); - media_format_set_audio_samplerate(vdec_fmt, app->samplerate); - media_format_set_audio_bit(vdec_fmt, app->bit); + media_format_set_audio_mime(fmt, app->mime); + media_format_set_audio_channel(fmt, app->channel); + media_format_set_audio_samplerate(fmt, app->samplerate); + media_format_set_audio_bit(fmt, app->bit); + + ret = mediacodec_configure_from_media_format(app->mc_handle[0], fmt, app->flag); + if (ret != MEDIACODEC_ERROR_NONE) + g_print("mediacodec_configure failed\n"); break; case AUDIO_ENC: - ret = mediacodec_set_aenc_info(app->mc_handle[0], app->samplerate, app->channel, app->bit, app->bitrate); - media_format_set_audio_mime(vdec_fmt, app->mime); - media_format_set_audio_channel(vdec_fmt, app->channel); - media_format_set_audio_samplerate(vdec_fmt, app->samplerate); - media_format_set_audio_bit(vdec_fmt, app->bit); + media_format_set_audio_mime(fmt, app->mime); + media_format_set_audio_channel(fmt, app->channel); + media_format_set_audio_samplerate(fmt, app->samplerate); + media_format_set_audio_bit(fmt, app->bit); + + media_format_create(&codec_format); + media_format_set_audio_mime(codec_format, codec_mime); + media_format_set_audio_channel(codec_format, app->channel); + media_format_set_audio_samplerate(codec_format, app->samplerate); + media_format_set_audio_bit(codec_format, app->bit); + + ret = mediacodec_configure_from_media_format(app->mc_handle[0], codec_format, app->flag); + if (ret != MEDIACODEC_ERROR_NONE) + g_print("mediacodec_set_configure failed\n"); + media_format_unref(codec_format); break; default: g_print("invaild type\n"); @@ -1161,11 +1463,14 @@ static void _mediacodec_prepare(App *app) } /* set callback */ - mediacodec_set_input_buffer_used_cb(app->mc_handle[0], _mediacodec_inbuf_used_cb, NULL); - mediacodec_set_output_buffer_available_cb(app->mc_handle[0], _mediacodec_outbuf_available_cb, app); - mediacodec_set_buffer_status_cb(app->mc_handle[0], _mediacodec_buffer_status_cb, app); - mediacodec_set_eos_cb(app->mc_handle[0], _mediacodec_eos_cb, NULL); - mediacodec_set_error_cb(app->mc_handle[0], _mediacodec_error_cb, NULL); + g_print("supported codec lists\n"); + mediacodec_foreach_supported_codec(app->mc_handle[0], (mediacodec_supported_codec_cb)_foreach_cb, app); + mediacodec_set_input_buffer_used_cb(app->mc_handle[0], (mediacodec_input_buffer_used_cb)_mediacodec_inbuf_used_cb, app); + mediacodec_set_output_buffer_available_cb(app->mc_handle[0], (mediacodec_output_buffer_available_cb) _mediacodec_outbuf_available_cb, app); + if (frame_all) + mediacodec_set_buffer_status_cb(app->mc_handle[0], (mediacodec_buffer_status_cb) _mediacodec_buffer_status_cb, app); + mediacodec_set_eos_cb(app->mc_handle[0], (mediacodec_eos_cb)_mediacodec_eos_cb, app); + mediacodec_set_error_cb(app->mc_handle[0], (mediacodec_error_cb)_mediacodec_error_cb, NULL); /* prepare */ ret = mediacodec_prepare(app->mc_handle[0]); @@ -1174,18 +1479,363 @@ static void _mediacodec_prepare(App *app) return; } - app->frame_count = 0; + + /* get packet pool instance */ + ret = mediacodec_get_packet_pool(app->mc_handle[0], &pkt_pool); + if (ret != MEDIA_PACKET_ERROR_NONE) { + g_print("mediacodec_get_packet_pool failed\n"); + return; + } + g_print("\n\nmediacodec start\n\n"); + + return; +} + +void _mediacodec_enc_input_buffer_used_cb(media_packet_h pkt, void *user_data) +{ + /* release input raw packet */ + media_packet_destroy(pkt); +} + +/* this callback is called when the input buffer for codec has done to use */ +void _mediacodec_dec_input_buffer_used_cb(media_packet_h pkt, void *user_data) +{ + /* release input encoded packet */ + media_packet_destroy(pkt); +} + +void _mediacodec_enc_output_buffer_available_cb(media_packet_h pkt, void *user_data) +{ + App *app = (App*)user_data; + + mediacodec_h media_codec_handle = app->mc_handle[1]; + media_packet_h output_buf = NULL; + mediacodec_get_output(media_codec_handle, &output_buf, 0); + /* decode encoded camera preview */ + mediacodec_process_input(app->mc_handle[0], output_buf, 0); +} + +void _mediacodec_dec_output_buffer_available_cb(media_packet_h pkt, void *user_data) +{ + App *app = (App*)user_data; + + mediacodec_h media_codec_handle = app->mc_handle[0]; + media_packet_h output_buf = NULL; + + mediacodec_get_output(media_codec_handle, &output_buf, 0); + + if (app->enable_dump) + decoder_output_dump(app, output_buf); + + media_packet_destroy(output_buf); +} + +void _media_packet_preview_cb(media_packet_h packet, void *user_data) +{ + App *app = user_data; + g_mutex_lock(&app->lock); + mediacodec_process_input(app->mc_handle[1], packet, 0); + g_mutex_unlock(&app->lock); + + return; +} + +void _mediacodec_camera_start(App *app) +{ + int default_format = CAMERA_PIXEL_FORMAT_NV12; + app->width = 640; + app->height = 480; + app->hardware = TRUE; + + /*create decoder instance and setup */ + mediacodec_create(&app->mc_handle[0]); + mediacodec_set_codec(app->mc_handle[0], MEDIACODEC_H264, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW); + mediacodec_set_vdec_info(app->mc_handle[0], app->width, app->height); + /* set callback */ + mediacodec_set_input_buffer_used_cb(app->mc_handle[0], _mediacodec_dec_input_buffer_used_cb, NULL); + mediacodec_set_output_buffer_available_cb(app->mc_handle[0], _mediacodec_dec_output_buffer_available_cb, app); + mediacodec_prepare(app->mc_handle[0]); + + /*create encoder instance and setup */ + mediacodec_create(&app->mc_handle[1]); + mediacodec_set_codec(app->mc_handle[1], MEDIACODEC_H264, MEDIACODEC_ENCODER | MEDIACODEC_SUPPORT_TYPE_HW); + mediacodec_set_venc_info(app->mc_handle[1], app->width, app->height, 30, 1000); + /* set callback */ + mediacodec_set_input_buffer_used_cb(app->mc_handle[1], _mediacodec_enc_input_buffer_used_cb, NULL); + mediacodec_set_output_buffer_available_cb(app->mc_handle[1], _mediacodec_enc_output_buffer_available_cb, app); + mediacodec_prepare(app->mc_handle[1]); + + /* create camera instance and setup and then start preview */ + camera_create(CAMERA_DEVICE_CAMERA0, &app->camera_handle); + camera_set_media_packet_preview_cb(app->camera_handle, _media_packet_preview_cb, app); + camera_get_preview_format(app->camera_handle, &default_format); + camera_set_preview_format(app->camera_handle, default_format); + camera_set_preview_resolution(app->camera_handle, app->width, app->height); + camera_set_display(app->camera_handle, CAMERA_DISPLAY_TYPE_NONE, NULL); + camera_start_preview(app->camera_handle); + + return; +} + + +void _mediacodec_camera_stop(App *app) +{ + camera_state_e camera_state = CAMERA_STATE_NONE; + + camera_get_state(app->camera_handle, &camera_state); + camera_stop_preview(app->camera_handle); + camera_destroy(app->camera_handle); + + mediacodec_unprepare(app->mc_handle[0]); + mediacodec_unprepare(app->mc_handle[1]); + mediacodec_destroy(app->mc_handle[0]); + mediacodec_destroy(app->mc_handle[1]); + return; +} + +void _mediacodec_auto_test(App *app, char *path) +{ + gint ret = 0; + gint num_tracks = 0; + gint track = 0; + gint width = 0; + gint height = 0; + gint channel = 0; + gint samplerate = 0; + gint bit = 0; + media_format_type_e formattype; + media_format_mimetype_e video_mime; + media_format_mimetype_e audio_mime; + gint codec_mask = 0xFFF0; + gint codec_id; + app->demux_eos = 0; + app->codec_eos = 0; + app->etb = 0; + app->ebd = 0; + app->ftb = 0; + app->fbd = 0; + + ret = mediademuxer_create(&app->demuxer); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to create demuxer\n"); + return; + } + + ret = mediademuxer_set_data_source(app->demuxer, path); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to mediademuxer_set_data_source\n"); + return; + } + + ret = mediademuxer_set_error_cb(app->demuxer, demuxer_error_cb, app->demuxer); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to mediademuxer_set_error_cb\n"); + return; + } + + mediademuxer_set_eos_cb(app->demuxer, _mediademuxer_eos_cb, app); + + ret = mediademuxer_prepare(app->demuxer); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to prepare\n"); + return; + } + + + ret = mediademuxer_get_track_count(app->demuxer, &num_tracks); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to get track\n"); + return; + } + + for (track = 0; track < num_tracks; track++) { + ret = mediademuxer_get_track_info(app->demuxer, track, &app->format[track]); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to get track info\n"); + return; + } + + media_format_get_type(app->format[track], &formattype); + + if (!app->is_video && formattype == MEDIA_FORMAT_AUDIO) { + app->audio_track = track; + app->type = AUDIO_DEC; + media_format_get_audio_info(app->format[track], &audio_mime, &channel, &samplerate, &bit, NULL); + + mediademuxer_select_track(app->demuxer, track); + + ret = mediacodec_create(&app->mc_handle[track]); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to create mediacocec\n"); + return; + } + + codec_id = audio_mime & codec_mask; + g_print("auido codec_id : %x\n", codec_id); + + ret = mediacodec_set_codec(app->mc_handle[track], codec_id, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_SW); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to set codec\n"); + return; + } + + ret = mediacodec_set_adec_info(app->mc_handle[track], samplerate, channel, bit); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to set adec info\n"); + return; + } + + mediacodec_set_buffer_status_cb(app->mc_handle[track], _av_buffer_status_cb, app); + mediacodec_set_input_buffer_used_cb(app->mc_handle[track], _mediacodec_inbuf_used_cb, app); + mediacodec_set_output_buffer_available_cb(app->mc_handle[track], _audio_outbuf_available_cb, app); + mediacodec_set_eos_cb(app->mc_handle[track], _mediacodec_eos_cb, app); + mediacodec_set_error_cb(app->mc_handle[track], _mediacodec_error_cb, NULL); + + } else if (app->is_video && formattype == MEDIA_FORMAT_VIDEO) { + app->video_track = track; + app->type = VIDEO_DEC; + media_format_get_video_info(app->format[track], &video_mime, &width, &height, NULL, NULL); + + mediademuxer_select_track(app->demuxer, track); + + ret = mediacodec_create(&app->mc_handle[track]); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to create mediacocec\n"); + return; + } + + app->width = width; + app->height = height; + + codec_id = video_mime & codec_mask; + g_print("video codec_id : %x\n", codec_id); + + ret = mediacodec_set_codec(app->mc_handle[track], codec_id, MEDIACODEC_DECODER | MEDIACODEC_SUPPORT_TYPE_HW); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to set codec\n"); + return; + } + + ret = mediacodec_set_vdec_info(app->mc_handle[track], width, height); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to set vdec info\n"); + return; + } + + mediacodec_set_buffer_status_cb(app->mc_handle[track], _av_buffer_status_cb, app); + mediacodec_set_input_buffer_used_cb(app->mc_handle[track], _mediacodec_inbuf_used_cb, app); + mediacodec_set_output_buffer_available_cb(app->mc_handle[track], _video_outbuf_available_cb, app); + mediacodec_set_eos_cb(app->mc_handle[track], _mediacodec_eos_cb, app); + mediacodec_set_error_cb(app->mc_handle[track], _mediacodec_error_cb, NULL); + } + } + + ret = mediademuxer_start(app->demuxer); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to start mediademuxer\n"); + return; + } + + track = app->is_video ? app->video_track : app->audio_track; + ret = mediacodec_prepare(app->mc_handle[track]); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to prepare mediacodec\n"); + return; + } + + g_cond_init(&app->thread_cond); + g_cond_init(&app->eos_cond); + g_cond_init(&app->dst_eos_cond); + g_mutex_init(&app->thread_mutex); + g_mutex_init(&app->eos_mutex); + + app->thread = g_thread_new("feed thread", &av_feed_thread, app); app->start = clock(); - g_main_loop_run(app->loop); - g_print("Average FPS = %3.3f\n", ((double)app->frame_count*1000000/(app->finish - app->start))); + g_mutex_lock(&app->eos_mutex); + while (app->codec_eos != 1) g_cond_wait(&app->dst_eos_cond, &app->eos_mutex); + g_mutex_unlock(&app->eos_mutex); + g_print("now try to destroy thread!!\n"); + g_thread_join(app->thread); + app->finish = clock(); + + ret = mediademuxer_stop(app->demuxer); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to stop mediademuxer\n"); + return; + } + + ret = mediademuxer_unselect_track(app->demuxer, track); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to unselect mediademuxer\n"); + return; + } + + ret = mediacodec_unprepare(app->mc_handle[track]); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to unprepare mediacodec\n"); + return; + } + + ret = mediacodec_destroy(app->mc_handle[track]); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to destroy mediacodec\n"); + return; + } + + ret = mediademuxer_unprepare(app->demuxer); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to unprepare mediademuxer\n"); + return; + } + + ret = mediademuxer_destroy(app->demuxer); + if (ret != MEDIACODEC_ERROR_NONE) { + g_print("failed to destroy mediademuxer\n"); + return; + } + + g_cond_clear(&app->thread_cond); + g_cond_clear(&app->eos_cond); + g_cond_clear(&app->dst_eos_cond); + g_mutex_clear(&app->thread_mutex); + g_mutex_clear(&app->eos_mutex); - g_print("---------------------------\n"); + g_print("resources are released!!!\n\n\n"); + g_print("-----------------------------------------------------\n"); + g_print("Input - queued packets : %d, finalized packets : %d\n", app->etb, app->ebd); + g_print("Output - queued packets : %d, finalized packets : %d\n", app->fbd, app->fbd); + g_print("Average FPS = %3.3f\n", ((double)app->fbd*1000000/(app->finish - app->start))); + g_print("-----------------------------------------------------\n"); return; } -static void input_filepath(char *filename, App *app) +void _mediacodec_unprepare(App *app) +{ + mediacodec_unprepare(app->mc_handle[0]); +} + +void _mediacodec_destroy(App *app) +{ +#ifdef USE_POOL + if (media_packet_pool_deallocate(pkt_pool) != MEDIA_PACKET_ERROR_NONE) { + + g_print("media_packet_pool_deallocatet failed\n"); + return; + } + + if (media_packet_pool_destroy(pkt_pool) != MEDIA_PACKET_ERROR_NONE) { + + g_print(" media_packet_pool_destroy failed\n"); + return; + } + g_print("media packet pool destroyed! \n"); +#endif + mediacodec_destroy(app->mc_handle[0]); +} + +void input_filepath(char *filename, App *app) { GError *error = NULL; @@ -1194,25 +1844,22 @@ static void input_filepath(char *filename, App *app) if (error) { g_print("failed to open file : %s\n", error->message); g_error_free(error); - return -1; + return; } app->length = g_mapped_file_get_length(app->file); app->data = (guint8 *)g_mapped_file_get_contents(app->file); app->offset = 0; - g_print("len : %d, offset : %d, obj : %d", app->length, (int)app->offset, app->obj); + g_print("len : %d, offset : %d, obj : %d", app->length, app->offset, app->obj); return; } -void quit_program() +void quit_program(App *app) { -#if DUMP_OUTBUF - if (fp_out) - fclose(fp_out); -#endif - elm_exit(); - + media_format_unref(fmt); + g_main_loop_quit(app->loop); + exit(0); } void reset_menu_state() @@ -1223,19 +1870,21 @@ void reset_menu_state() void _interpret_main_menu(char *cmd, App *app) { - int len = strlen(cmd); + gint len = strlen(cmd); if (len == 1) { if (strncmp(cmd, "a", 1) == 0) g_menu_state = CURRENT_STATUS_FILENAME; else if (strncmp(cmd, "o", 1) == 0) g_menu_state = CURRENT_STATUS_GET_OUTPUT; else if (strncmp(cmd, "q", 1) == 0) - quit_program(); + quit_program(app); else g_print("unknown menu \n"); } else if (len == 2) { if (strncmp(cmd, "pr", 2) == 0) - _mediacodec_prepare(app); + _mediacodec_prepare(app, 0); + else if (strncmp(cmd, "pa", 2) == 0) + _mediacodec_prepare(app, 1); else if (strncmp(cmd, "sc", 2) == 0) g_menu_state = CURRENT_STATUS_SET_CODEC; else if (strncmp(cmd, "vd", 2) == 0) @@ -1248,7 +1897,25 @@ void _interpret_main_menu(char *cmd, App *app) g_menu_state = CURRENT_STATUS_SET_AENC_INFO; else if (strncmp(cmd, "pi", 2) == 0) g_menu_state = CURRENT_STATUS_PROCESS_INPUT; - else + else if (strncmp(cmd, "un", 2) == 0) + _mediacodec_unprepare(app); + else if (strncmp(cmd, "dt", 2) == 0) + _mediacodec_destroy(app); + else if (strncmp(cmd, "cr", 2) == 0) + _mediacodec_camera_start(app); + else if (strncmp(cmd, "ct", 2) == 0) + _mediacodec_camera_stop(app); + else if (strncmp(cmd, "au", 2) == 0) + g_menu_state = CURRENT_STATUS_AUTO_TEST; + else if (strncmp(cmd, "dp", 2) == 0) { + if (!app->enable_dump) { + app->enable_dump = TRUE; + g_print("dump enabled\n"); + } else { + app->enable_dump = FALSE; + g_print("dump disabled\n"); + } + } else display_sub_basic(); } else { g_print("unknown menu \n"); @@ -1257,7 +1924,7 @@ void _interpret_main_menu(char *cmd, App *app) return; } -static void displaymenu(void) +void displaymenu(void) { if (g_menu_state == CURRENT_STATUS_MAINMENU) { display_sub_basic(); @@ -1306,6 +1973,8 @@ static void displaymenu(void) g_print("*** input dec process number\n"); } else if (g_menu_state == CURRENT_STATUS_GET_OUTPUT) { g_print("*** input get output buffer number\n"); + } else if (g_menu_state == CURRENT_STATUS_AUTO_TEST) { + g_print("*** enter media path and select the track to decode (0 : audio, 1 : video).\n"); } else { g_print("*** unknown status.\n"); } @@ -1318,9 +1987,11 @@ gboolean timeout_menu_display(void* data) return FALSE; } - -static void interpret(char *cmd, App *app) +void interpret(char *cmd) { + App *app = &s_app; + gint tmp = 0; + switch (g_menu_state) { case CURRENT_STATUS_MAINMENU: _interpret_main_menu(cmd, app); @@ -1331,9 +2002,8 @@ static void interpret(char *cmd, App *app) break; case CURRENT_STATUS_SET_CODEC: { - int tmp; - static int cnt = 0; - char **ptr = NULL; + static gint cnt = 0; + gchar **ptr = NULL; switch (cnt) { case 0: tmp = atoi(cmd); @@ -1362,7 +2032,7 @@ static void interpret(char *cmd, App *app) break; case CURRENT_STATUS_SET_VDEC_INFO: { - static int cnt = 0; + static gint cnt = 0; switch (cnt) { case 0: app->width = atoi(cmd); @@ -1382,7 +2052,7 @@ static void interpret(char *cmd, App *app) break; case CURRENT_STATUS_SET_VENC_INFO: { - static int cnt = 0; + static gint cnt = 0; switch (cnt) { case 0: app->width = atoi(cmd); @@ -1410,7 +2080,7 @@ static void interpret(char *cmd, App *app) break; case CURRENT_STATUS_SET_ADEC_INFO: { - static int cnt = 0; + static gint cnt = 0; switch (cnt) { case 0: app->samplerate = atoi(cmd); @@ -1437,20 +2107,48 @@ static void interpret(char *cmd, App *app) static int cnt = 0; switch (cnt) { case 0: - app->samplerate = atoi(cmd); + tmp = atoi(cmd); + + if (tmp <= 0 || tmp > 96000) { + g_print("Invalid value\n"); + reset_menu_state(); + break; + } + app->samplerate = tmp; cnt++; break; case 1: - app->channel = atoi(cmd); + tmp = atoi(cmd); + + if (tmp <= 0 || tmp > 6) { + g_print("Invalid value\n"); + reset_menu_state(); + break; + } + app->channel = tmp; cnt++; break; case 2: - app->bit = atoi(cmd); + tmp = atoi(cmd); + + if (tmp <= 0 || tmp > 32) { + g_print("Invalid value\n"); + reset_menu_state(); + break; + } + app->bit = tmp; cnt++; break; case 3: - app->bitrate = atoi(cmd); + tmp = atoi(cmd); + + if (tmp <= 0 || tmp > INT_MAX) { + g_print(";;Invalid value\n"); + reset_menu_state(); + break; + } app->type = AUDIO_ENC; + app->bitrate = tmp; reset_menu_state(); cnt = 0; @@ -1462,26 +2160,52 @@ static void interpret(char *cmd, App *app) break; case CURRENT_STATUS_PROCESS_INPUT: { - static int num = 0; - num = atoi(cmd); + tmp = atoi(cmd); + + if (tmp <= 0 || tmp > INT_MAX) { + g_print("Invalid value\n"); + reset_menu_state(); + break; + } + app->frame = tmp; + + _mediacodec_process_input(app); reset_menu_state(); } break; case CURRENT_STATUS_GET_OUTPUT: { - static int num = 0; - num = atoi(cmd); reset_menu_state(); } break; - default: - break; + case CURRENT_STATUS_AUTO_TEST: + { + int len; + static int cnt = 0; + switch (cnt) { + case 0: + len = strlen(cmd); + strncpy(app->filepath, cmd, len + 1); + g_print("%s, %d\n", app->filepath, len); + cnt++; + break; + case 1: + app->is_video = atoi(cmd) ? 1 : 0; + _mediacodec_auto_test(app, app->filepath); + reset_menu_state(); + cnt = 0; + break; + default: + break; + } + } + break; } g_timeout_add(100, timeout_menu_display, 0); } -static void display_sub_basic() +void display_sub_basic() { g_print("\n"); g_print("=========================================================================================\n"); @@ -1493,14 +2217,19 @@ static void display_sub_basic() g_print("ve. Set venc info \n"); g_print("ad. Set adec info \t"); g_print("ae. Set aenc info \n"); - g_print("pr. Prepare \t\t"); - g_print("pi. Process input \n"); + g_print("pr. Prepare \t"); + g_print("pa. Prepare and process all\t\t"); + g_print("pi. process input with num\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\t"); g_print("dt. Destroy \t\t"); - g_print("q. quite test suite \t"); + g_print("q. quit test suite \n"); + g_print("dp. enable dump \n"); + g_print("-----------------------------------------------------------------------------------------\n"); + g_print("cr. camera preview -> encoder -> decoder\n"); + g_print("au. interlocking with mediademuxer\n"); + g_print("ct. quit camera test\n"); g_print("\n"); g_print("=========================================================================================\n"); } @@ -1510,58 +2239,34 @@ gboolean input(GIOChannel *channel, GIOCondition cond, gpointer data) gchar buf[MAX_STRING_LEN]; gsize read; GError *error = NULL; - App *context = (App*)data; g_io_channel_read_chars(channel, buf, MAX_STRING_LEN, &read, &error); buf[read] = '\0'; g_strstrip(buf); - interpret(buf, context); + interpret(buf); return TRUE; } -int main(int argc, char *argv[]) -{ - App *app = &s_app; - - GError *error = NULL; - GIOChannel *stdin_channel; - stdin_channel = g_io_channel_unix_new(0); - g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL); - g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)input, app); - - - app->loop = g_main_loop_new(NULL, TRUE); - app->timer = g_timer_new(); - - displaymenu(); - - ops.data = app; - - return appcore_efl_main(PACKAGE, &argc, &argv, &ops); -} - - - -void mc_hex_dump(char *desc, void *addr, int len) +void mc_hex_dump(char *desc, void *addr, gint len) { int i; - unsigned char buff[17]; - unsigned char *pc = (unsigned char *)addr; + guint8 buff[17]; + guint8 *pc = (guint8 *)addr; if (desc != NULL) - printf("%s:\n", desc); + g_print("%s:\n", desc); for (i = 0; i < len; i++) { if ((i % 16) == 0) { if (i != 0) - printf(" %s\n", buff); + g_print(" %s\n", buff); - printf(" %04x ", i); + g_print(" %04x ", i); } - printf(" %02x", pc[i]); + g_print(" %02x", pc[i]); if ((pc[i] < 0x20) || (pc[i] > 0x7e)) buff[i % 16] = '.'; @@ -1571,29 +2276,28 @@ void mc_hex_dump(char *desc, void *addr, int len) } while ((i % 16) != 0) { - printf(" "); + g_print(" "); i++; } - printf(" %s\n", buff); + g_print(" %s\n", buff); } - -static void decoder_output_dump(App *app, media_packet_h pkt) +void decoder_output_dump(App *app, media_packet_h pkt) { - unsigned char *temp; + void *temp; int i = 0; int stride_width, stride_height; - char filename[100] = {0}; + gchar filename[100] = {0}; FILE *fp = NULL; int ret = 0; - sprintf(filename, "/tmp/dec_output_dump_%d_%d.yuv", app->width, app->height); + g_snprintf(filename, MAX_STRING_LEN, "/tmp/dec_output_dump_%d_%d.yuv", app->width, app->height); fp = fopen(filename, "ab"); media_packet_get_video_plane_data_ptr(pkt, 0, &temp); media_packet_get_video_stride_width(pkt, 0, &stride_width); media_packet_get_video_stride_height(pkt, 0, &stride_height); - g_printf("stride : %d, %d\n", stride_width, stride_height); + g_print("stride : %d, %d\n", stride_width, stride_height); for (i = 0; i < app->height; i++) { ret = fwrite(temp, app->width, 1, fp); @@ -1628,3 +2332,157 @@ static void decoder_output_dump(App *app, media_packet_h pkt) } +/** + * Add ADTS header at the beginning of each and every AAC packet. + * 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_header_for_aacenc(App *app, char *buffer, int packetLen) +{ + int profile = 2; /* AAC LC (0x01) */ + int freqIdx = 3; /* 48KHz (0x03) */ + int chanCfg = 2; /* CPE (0x02) */ + + if (app->samplerate == 96000) freqIdx = 0; + else if (app->samplerate == 88200) freqIdx = 1; + else if (app->samplerate == 64000) freqIdx = 2; + else if (app->samplerate == 48000) freqIdx = 3; + else if (app->samplerate == 44100) freqIdx = 4; + else if (app->samplerate == 32000) freqIdx = 5; + else if (app->samplerate == 24000) freqIdx = 6; + else if (app->samplerate == 22050) freqIdx = 7; + else if (app->samplerate == 16000) freqIdx = 8; + else if (app->samplerate == 12000) freqIdx = 9; + else if (app->samplerate == 11025) freqIdx = 10; + else if (app->samplerate == 8000) freqIdx = 11; + + if ((app->channel == 1) || (app->channel == 2)) + chanCfg = app->channel; + + /* fill in ADTS data */ + buffer[0] = (char)0xFF; + buffer[1] = (char)0xF1; + buffer[2] = (char)(((profile-1)<<6) + (freqIdx<<2) +(chanCfg>>2)); + buffer[3] = (char)(((chanCfg&3)<<6) + (packetLen>>11)); + buffer[4] = (char)((packetLen&0x7FF) >> 3); + buffer[5] = (char)(((packetLen&7)<<5) + 0x1F); + buffer[6] = (char)0xFC; +} + +void output_dump(App *app, media_packet_h pkt) +{ + void *temp; + uint64_t buf_size; + gchar filename[100] = {0}; + FILE *fp = NULL; + int ret = 0; + char adts[100] = {0, }; + + g_snprintf(filename, MAX_STRING_LEN, "/tmp/dec_output_dump_%d.out", app->type); + fp = fopen(filename, "ab"); + + media_packet_get_buffer_data_ptr(pkt, &temp); + media_packet_get_buffer_size(pkt, &buf_size); + g_print("output data : %p, size %d\n", temp, (int)buf_size); + + if (app->is_encoder && buf_size > 0 && app->codecid == MEDIACODEC_AAC_LC) { + add_adts_header_for_aacenc(app, adts, (buf_size + ADTS_HEADER_SIZE)); + fwrite(&adts, 1, ADTS_HEADER_SIZE, fp); + g_print("adts appended\n"); + } else if (app->is_encoder && buf_size > 0 && app->codecid == MEDIACODEC_AMR_NB && 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); /* AMR-NB magic number */ + write_amr_header = 0; + } + + fwrite(temp, (int)buf_size, 1, fp); + + g_print("codec dec output dumped!!%d\n", ret); + fclose(fp); + +} + +const char* codec_type_to_string(mediacodec_codec_type_e media_codec_id) +{ + guint media_codec_id_u = (guint)media_codec_id; + + switch (media_codec_id_u) { + case MEDIACODEC_L16: + return "L16"; + case MEDIACODEC_ALAW: + return "ALAW"; + case MEDIACODEC_ULAW: + return "ULAW"; + case MEDIACODEC_AMR_NB: + return "AMR_NB"; + case MEDIACODEC_AMR_WB: + return "AMR_WB"; + case MEDIACODEC_G729: + return "G729"; + case MEDIACODEC_AAC_LC: + return "AAC_LC"; + case MEDIACODEC_AAC_HE: + return "AAC_HE"; + case MEDIACODEC_AAC_HE_PS: + return "AAC_HE_PS"; + case MEDIACODEC_MP3: + return "MP3"; + case MEDIACODEC_VORBIS: + return "VORBIS"; + case MEDIACODEC_FLAC: + return "FLAC"; + case MEDIACODEC_WMAV1: + return "WMAV1"; + case MEDIACODEC_WMAV2: + return "WMAV2"; + case MEDIACODEC_WMAPRO: + return "WMAPRO"; + case MEDIACODEC_WMALSL: + return "WMALSL"; + case MEDIACODEC_H261: + return "H261"; + case MEDIACODEC_H263: + return "H263"; + case MEDIACODEC_H264: + return "H264"; + case MEDIACODEC_MJPEG: + return "MJPEG"; + case MEDIACODEC_MPEG1: + return "MPEG1"; + case MEDIACODEC_MPEG2: + return "MPEG2"; + case MEDIACODEC_MPEG4: + return "MPEG4"; + case MEDIACODEC_HEVC: + return "HEVC"; + case MEDIACODEC_VP8: + return "VP8"; + case MEDIACODEC_VP9: + return "VP9"; + case MEDIACODEC_VC1: + return "VC1"; + default: + return "NONE"; + } + return "NONE"; +} + +int main(int argc, char *argv[]) +{ + GIOChannel *stdin_channel; + stdin_channel = g_io_channel_unix_new(0); + g_io_channel_set_flags(stdin_channel, G_IO_FLAG_NONBLOCK, NULL); + g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)input, NULL); + + App *app = &s_app; + + displaymenu(); + app->loop = g_main_loop_new(NULL, TRUE); + app->timer = g_timer_new(); + g_main_loop_run(app->loop); + + ops.data = app; + + return appcore_efl_main(PACKAGE, &argc, &argv, &ops); +}