X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=test%2Fmedia_codec_test.c;h=67f0f68d2630339eea343005ad8eae8307907cbc;hb=48b40d4ffd885b8a9444fa9e1b2140cd4c9b2a30;hp=f4e2917268dc3aa93c56db348be99c9ede44c1aa;hpb=c9610a054ba4dc879b502b2cae7beb6abb75573b;p=platform%2Fcore%2Fapi%2Fmediacodec.git diff --git a/test/media_codec_test.c b/test/media_codec_test.c index f4e2917..67f0f68 100755 --- a/test/media_codec_test.c +++ b/test/media_codec_test.c @@ -21,11 +21,14 @@ #include #include -#include -#include #include #include #include +#include +#include +#include +#include +#include #define PACKAGE "media_codec_test" #define MAX_HANDLE 4 @@ -53,8 +56,8 @@ ((state & (expected_state)) == (expected_state)) #define AAC_CODECDATA_SIZE 16 +#define USE_POOL 1 -static int samplebyte = DEFAULT_SAMPLEBYTE; unsigned char buf_adts[ADTS_HEADER_SIZE]; enum { @@ -117,9 +120,9 @@ struct _App { GMappedFile *file; guint8 *data; - gsize length; - guint64 offset; - guint obj; + gint length; + gint offset; + gint obj; GTimer *timer; long start; @@ -129,10 +132,13 @@ struct _App { int codecid; int flag; - bool is_video[MAX_HANDLE]; - bool is_encoder[MAX_HANDLE]; + bool is_video; + bool is_encoder; bool hardware; + bool enable_dump; + int frame; type_e type; + camera_h camera_handle; /* video */ mediacodec_h mc_handle[MAX_HANDLE]; guint width; @@ -162,14 +168,8 @@ struct _App { 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); @@ -177,12 +177,13 @@ static int _terminate_app(void *data); static void displaymenu(void); static void display_sub_basic(); +static void _mediacodec_unprepare(App *app); /* For debugging */ static void mc_hex_dump(char *desc, void *addr, int len); -#if DUMP_OUTBUF static void decoder_output_dump(App *app, media_packet_h pkt); -#endif +static 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); @@ -190,7 +191,7 @@ int g_menu_state = CURRENT_STATUS_MAINMENU; static int _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); @@ -199,7 +200,7 @@ static int _create_app(void *data) static int _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); @@ -335,12 +336,10 @@ void h263_extractor(App * app, unsigned char **data, int *size, bool * have_fram unsigned char *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++]; @@ -371,6 +370,7 @@ 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) @@ -385,7 +385,7 @@ void mpeg4_extractor(App * app, unsigned char **data, int *size, bool * have_fra while (1) { if (len >= max) { - *have_frame = FALSE; + result = (len - 1); goto DONE; } @@ -403,9 +403,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: @@ -416,7 +416,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; @@ -435,6 +435,7 @@ 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 **/ +int write_amr_header = 1; /* write magic number for AMR Header at one time */ static const char AMR_header[] = "#!AMR\n"; static const char AMRWB_header[] = "#!AMR-WB\n"; #define AMR_NB_MIME_HDR_SIZE 6 @@ -448,7 +449,7 @@ void amrdec_extractor(App * app, unsigned char **data, int *size, bool * have_fr int readsize = 0, mode_temp; unsigned int fsize, mode; unsigned char *pAmr = app->data + app->offset; - //change the below one to frame count + /* 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; @@ -529,12 +530,12 @@ void aacenc_extractor(App *app, unsigned char **data, int *size, bool *have_fram int read_size; int offset = app->length - app->offset; - read_size = ((samplebyte*app->channel)*(app->bit/8)); - + 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; @@ -553,8 +554,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; @@ -596,8 +598,8 @@ void mp3dec_extractor(App *app, unsigned char **data, int *size, bool *have_fram { int read_size; guint header; - guint padding, bitrate, lsf=0, layer = 0, mpg25=0; - guint hdr_bitrate=0, sf=0; + guint padding, bitrate, lsf = 0, layer = 0, mpg25 = 0; + guint hdr_bitrate = 0, sf = 0; int offset = app->length - app->offset; unsigned char *pData = app->data + app->offset; @@ -606,17 +608,20 @@ void mp3dec_extractor(App *app, unsigned char **data, int *size, bool *have_fram 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; @@ -631,6 +636,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); } @@ -639,12 +645,15 @@ 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 */ @@ -699,7 +708,7 @@ void extract_input_aacdec_m4a_test(App * app, unsigned char **data, int *size, b * Testsuit that are not guaranteed to be available on functionality of all General DEMUXER/PARSER. */ - //change the below one later + /* change the below one later */ if (app->offset == 0) { /* * CAUTION : Codec data is needed only once in first time @@ -757,7 +766,7 @@ void extract_input_aacdec_m4a_test(App * app, unsigned char **data, int *size, b } 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) + read_size = readsize + AAC_CODECDATA_SIZE; /* return combination of (codec_data + raw_data) */ app->offset += header_size + readsize; goto DONE; } @@ -765,10 +774,17 @@ void extract_input_aacdec_m4a_test(App * app, unsigned char **data, int *size, b 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 + memcpy(buffer, pData + 7, readsize); /* Make only RAW data, so exclude header 7 bytes */ read_size = readsize; app->offset += header_size + readsize; + if (app->offset > app->length) { + read_size = 0; + *have_frame = FALSE; + g_print("[FAIL] offset error \n"); + return; + } + } else { read_size = 0; g_print("[FAIL] Not found aac frame sync. \n"); @@ -818,12 +834,13 @@ static void _mediacodec_empty_buffer_cb(media_packet_h pkt, void *user_data) return; } #endif -int _mediacodec_set_codec(int codecid, int flag, bool *hardware) +int _mediacodec_set_codec(App *app, int codecid, int flag, bool *hardware) { bool 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: @@ -846,7 +863,7 @@ int _mediacodec_set_codec(int codecid, int flag, bool *hardware) break; case MEDIACODEC_H263: if (encoder) { - extractor = h263_extractor; + extractor = yuv_extractor; mime = *hardware ? MEDIA_FORMAT_NV12 : MEDIA_FORMAT_I420; } else { extractor = h263_extractor; @@ -856,7 +873,7 @@ int _mediacodec_set_codec(int codecid, int flag, bool *hardware) case MEDIACODEC_AAC: if (encoder) { extractor = aacenc_extractor; - mime = MEDIA_FORMAT_PCM; + mime = MEDIA_FORMAT_PCM_F32LE; /* FIXME need to check according to verdor */ } else { extractor = aacdec_extractor; mime = MEDIA_FORMAT_AAC; @@ -865,7 +882,7 @@ int _mediacodec_set_codec(int codecid, int flag, bool *hardware) case MEDIACODEC_AAC_HE: if (encoder) { extractor = aacenc_extractor; - mime = MEDIA_FORMAT_PCM; + mime = MEDIA_FORMAT_PCM_F32LE; /* FIXME need to check according to verdor */ } else { extractor = extract_input_aacdec_m4a_test; mime = MEDIA_FORMAT_AAC_HE; @@ -890,12 +907,24 @@ int _mediacodec_set_codec(int codecid, int flag, bool *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!!!!"); @@ -904,6 +933,107 @@ int _mediacodec_set_codec(int codecid, int flag, bool *hardware) return mime; } +static void _mediacodec_process_input(App *app) +{ + int i; + bool have_frame = FALSE; + int ret; + static guint64 pts = 0L; + void *buf_data_ptr = NULL; + media_packet_h pkt = NULL; + unsigned char *tmp; + int read; + int size; + int offset; + int stride_width; + + for (i = 0; i < app->frame; i++) { + g_print("----------read data------------\n"); + + extractor(app, &tmp, &read, &have_frame); + + 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; + } + } +} + static gboolean read_data(App *app) { guint len = 0; @@ -913,21 +1043,29 @@ static gboolean read_data(App *app) void *buf_data_ptr = NULL; media_packet_h pkt = NULL; unsigned char *tmp; + int i; int read; + int size; int offset; - int stride_width, stride_height; + int stride_width; + + if (app->offset == 0) { + app->frame_count = 0; + app->start = clock(); + } g_print("----------read data------------\n"); extractor(app, &tmp, &read, &have_frame); - 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", (int)app->length, (int)app->offset); + g_print("length : %d, offset : %d\n", app->length, app->offset); if (app->offset + len > app->length) len = app->length - app->offset; @@ -935,16 +1073,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); @@ -955,28 +1100,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; - offset = stride_width*stride_height; + for (i = 0; i < app->height; i++) { + memcpy(buf_data_ptr, tmp, app->width); + buf_data_ptr += stride_width; + tmp += app->width; + } - memcpy(buf_data_ptr, tmp, offset); + 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; - /* 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); + for (i = 0; i < app->height>>1; 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>>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); @@ -1011,7 +1176,12 @@ static void stop_feed(App *app) static gboolean _mediacodec_inbuf_used_cb(media_packet_h pkt, void *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); +#endif + return TRUE; } @@ -1031,19 +1201,12 @@ static bool _mediacodec_outbuf_available_cb(media_packet_h pkt, void *user_data) if (ret != MEDIACODEC_ERROR_NONE) g_print("get_output failed\n"); -#if DUMP_OUTBUF - void *data; - int buf_size; - int stride_width, stride_height; - - decoder_output_dump(app, out_pkt); - 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); - -#endif + if (app->enable_dump) { + if (app->type == VIDEO_DEC) + decoder_output_dump(app, out_pkt); + else + output_dump(app, out_pkt); + } app->frame_count++; @@ -1081,13 +1244,19 @@ static bool _mediacodec_eos_cb(void *user_data) return TRUE; } -static void _mediacodec_prepare(App *app) +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, bool frame_all) { int ret; -#if DUMP_OUTBUF - fp_out = fopen("/tmp/codec_dump.out", "wb"); -#endif + g_print("supported codec lists -internal-\n"); + mediacodec_foreach_supported_codec_static((mediacodec_supported_codec_cb)_foreach_cb, app); + /* create instance */ ret = mediacodec_create(&app->mc_handle[0]); if (ret != MEDIACODEC_ERROR_NONE) { @@ -1102,39 +1271,38 @@ static void _mediacodec_prepare(App *app) return; } - - app->mime = _mediacodec_set_codec(app->codecid, app->flag, &app->hardware); + app->mime = _mediacodec_set_codec(app, app->codecid, app->flag, &app->hardware); /* 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); 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); 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); 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); break; default: g_print("invaild type\n"); @@ -1147,9 +1315,12 @@ static void _mediacodec_prepare(App *app) } /* set callback */ + 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, NULL); mediacodec_set_output_buffer_available_cb(app->mc_handle[0], (mediacodec_output_buffer_available_cb) _mediacodec_outbuf_available_cb, app); - mediacodec_set_buffer_status_cb(app->mc_handle[0], (mediacodec_buffer_status_cb) _mediacodec_buffer_status_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, NULL); mediacodec_set_error_cb(app->mc_handle[0], (mediacodec_error_cb)_mediacodec_error_cb, NULL); @@ -1160,17 +1331,144 @@ static void _mediacodec_prepare(App *app) return; } - app->frame_count = 0; - 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))); +/* 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; +} + +static 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 */ +static void _mediacodec_dec_input_buffer_used_cb(media_packet_h pkt, void *user_data) +{ + /* release input encoded packet */ + media_packet_destroy(pkt); +} + +static 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); +} + +static void _mediacodec_dec_output_buffer_available_cb(media_packet_h pkt, void *user_data) +{ + App *app = (App*)user_data; - g_print("---------------------------\n"); + 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); +} + +static 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; +} + +static 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; } + +static 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; +} + +static void _mediacodec_unprepare(App *app) +{ + mediacodec_unprepare(app->mc_handle[0]); +} + +static 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]); +} + static void input_filepath(char *filename, App *app) { GError *error = NULL; @@ -1186,17 +1484,15 @@ static void input_filepath(char *filename, App *app) 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 + media_format_unref(fmt); + g_main_loop_quit(app->loop); elm_exit(); } @@ -1216,12 +1512,14 @@ void _interpret_main_menu(char *cmd, App *app) 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) @@ -1234,7 +1532,23 @@ 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, "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"); @@ -1448,6 +1762,10 @@ static void interpret(char *cmd, App *app) break; case CURRENT_STATUS_PROCESS_INPUT: { + app->frame = atoi(cmd); + + if (app->frame > 0 && app->frame < 10) + _mediacodec_process_input(app); reset_menu_state(); } break; @@ -1475,14 +1793,18 @@ 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("ct. quit camera test\n"); g_print("\n"); g_print("=========================================================================================\n"); } @@ -1512,10 +1834,12 @@ int main(int argc, char *argv[]) g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)input, app); + displaymenu(); app->loop = g_main_loop_new(NULL, TRUE); app->timer = g_timer_new(); + g_main_loop_run(app->loop); + - displaymenu(); ops.data = app; @@ -1531,18 +1855,18 @@ void mc_hex_dump(char *desc, void *addr, int len) unsigned char *pc = (unsigned char *)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] = '.'; @@ -1552,29 +1876,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); } -#if DUMP_OUTBUF static void decoder_output_dump(App *app, media_packet_h pkt) { 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); - 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); @@ -1608,4 +1931,139 @@ static void decoder_output_dump(App *app, media_packet_h pkt) fclose(fp); } -#endif + +/** + * 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; +} + +static 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"; + } +} +