Added new API for configuration via media format
[platform/core/api/mediacodec.git] / test / media_codec_test.c
old mode 100755 (executable)
new mode 100644 (file)
index 67cab1c..505dede
 #include <Elementary.h>
 #include <appcore-efl.h>
 #include <gst/gst.h>
+#include <limits.h>
 
-#include <media_codec.h>
-#include <media_packet.h>
 #include <tbm_surface.h>
 #include <dlog.h>
 #include <time.h>
+#include <camera.h>
+#include <media_codec.h>
+#include <media_packet.h>
+#include <media_packet_internal.h>
+#include <media_packet_pool.h>
+#include <media_codec_internal.h>
+#include <mediademuxer.h>
 
 #define PACKAGE "media_codec_test"
 #define MAX_HANDLE                     4
        ((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);
+}