Enhance mix_encode2 test tool to add VP8 encoder option

BZ: 124301

Add VP8 encode option and IVF writer class into mix_encode2.

Change-Id: I2f8faba86a26af61b845ddd9f342a200f3c020f7
Signed-off-by: Liu Bolun <bolun.liu@intel.com>
Reviewed-on: http://android.intel.com:8080/121789
Reviewed-by: Shi, PingX <pingx.shi@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: Shi, PingX <pingx.shi@intel.com>
Reviewed-by: cactus <cactus@intel.com>
Tested-by: cactus <cactus@intel.com>
diff --git a/test/mix_encoder2.cpp b/test/mix_encoder2.cpp
index 2fd2b1c..1d06e37 100755
--- a/test/mix_encoder2.cpp
+++ b/test/mix_encoder2.cpp
@@ -51,6 +51,8 @@
 static const int BOX_WIDTH = 64;
 static const int PRELOAD_FRAME_NUM = 16;
 uint32_t gNumFramesOutput = 0;
+static unsigned int pts;
+
 
 #define CHECK_ENC_STATUS(FUNC)\
     if (ret < ENCODE_SUCCESS) { \
@@ -710,6 +712,8 @@
 static const char *AVC_MIME_TYPE = "video/h264";
 static const char *MPEG4_MIME_TYPE = "video/mpeg4";
 static const char *H263_MIME_TYPE = "video/h263";
+static const char *VP8_MIME_TYPE = "video/x-webm";
+
 
 class MixEncoder : public MediaSource {
 
@@ -730,6 +734,8 @@
             mMixCodec = (char*) MPEG4_MIME_TYPE;
         } else if (strcmp(mime, MEDIA_MIMETYPE_VIDEO_H263) == 0) {
             mMixCodec = (char*) H263_MIME_TYPE;
+        } else if (strcmp(mime, MEDIA_MIMETYPE_VIDEO_VPX) == 0) {
+            mMixCodec = (char*) VP8_MIME_TYPE;
         } else {
             mMixCodec = (char*) AVC_MIME_TYPE;
         }
@@ -939,10 +945,11 @@
         CHECK_STATUS(err);
 
         VideoOutputFormat format;
-        if (mEncodeFrameCount == 2 && (strcasecmp(mMixCodec, H263_MIME_TYPE) != 0)) {
+        if ((mEncodeFrameCount == 2 && (strcasecmp(mMixCodec, H263_MIME_TYPE) != 0))&&
+			(mEncodeFrameCount == 2 && (strcasecmp(mMixCodec, VP8_MIME_TYPE) != 0))){
             format = OUTPUT_CODEC_DATA;
             mFirstFrame = true;
-        }else
+		}else
             format = OUTPUT_EVERYTHING;
 
         err = getoutput(*buffer, format);
@@ -978,7 +985,9 @@
             mEncoderParams.profile = (VAProfile)VAProfileMPEG4Simple;
         } else if (strcmp(mMixCodec, H263_MIME_TYPE) == 0) {
             mEncoderParams.profile = (VAProfile)VAProfileH263Baseline;
-        } else {
+        } else if (strcmp(mMixCodec, VP8_MIME_TYPE) == 0) {
+            mEncoderParams.profile = (VAProfile)VAProfileVP8Version0_3;
+		} else {
             mEncoderParams.profile = (VAProfile)VAProfileH264Baseline;
         }
 
@@ -1045,6 +1054,146 @@
 
 };
 
+class IVFWriter : public MediaWriter {
+
+public:
+    const char* mFile;
+    FILE* mFilehandle;
+    sp<MediaSource> mSource;
+    pthread_t mThread;
+    bool mRunning;
+    bool mEOS;
+	char vp8_file_header[32];
+	
+public:
+    IVFWriter(char* file) {
+        mFile = file;
+        mRunning = false;
+    }
+
+    status_t addSource(const sp<MediaSource> &source) {
+        mSource = source;
+        return OK;
+    }
+
+    bool reachedEOS() {
+        return mEOS;
+    }
+
+    status_t start(MetaData *params = NULL) {
+
+        mSource->start();
+
+        mRunning = true;
+        mEOS = false;
+
+        mFilehandle = fopen(mFile, "w+");
+        if (mFilehandle == NULL)
+            return errno;
+
+		write_ivf_file_header(params);
+
+        pthread_attr_t attr;
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+        pthread_create(&mThread, &attr, IVFWriter::ThreadFunc, this);
+        pthread_attr_destroy(&attr);
+
+        return OK;
+    }
+
+    status_t stop() {
+        mRunning = false;
+        void *dummy;
+        pthread_join(mThread, &dummy);
+        fclose(mFilehandle);
+        return OK;
+    }
+
+    status_t pause() {
+        return OK;
+    }
+
+	
+	static void mem_put_le16(char *mem, unsigned int val)
+	{
+		mem[0] = val;
+		mem[1] = val>>8;
+	}
+	
+	static void mem_put_le32(char *mem, unsigned int val)
+	{
+		mem[0] = val;
+		mem[1] = val>>8;
+		mem[2] = val>>16;
+		mem[3] = val>>24;
+	}
+
+	void write_ivf_file_header(MetaData *params)	{
+
+    int width,height,framerate; 
+	params->findInt32(kKeyWidth, &width);
+    params->findInt32(kKeyHeight, &height);
+    params->findInt32(kKeyFrameRate, &framerate);
+     /* write ivf header */
+    vp8_file_header[0] = 'D';
+    vp8_file_header[1] = 'K';
+    vp8_file_header[2] = 'I';
+    vp8_file_header[3] = 'F';
+    mem_put_le16(vp8_file_header+4,  0);                     /* version */
+    mem_put_le16(vp8_file_header+6,  32);                    /* headersize */
+    mem_put_le32(vp8_file_header+8,  0x30385056);            /* headersize */
+    mem_put_le16(vp8_file_header+12, width);           /* width */
+    mem_put_le16(vp8_file_header+14, height);          /* height */
+    mem_put_le32(vp8_file_header+16, framerate);       /* rate default at 30 */
+    mem_put_le32(vp8_file_header+20, 1);                     /* scale */
+    mem_put_le32(vp8_file_header+24, 50);           /* length just hardcode to 50*/
+    mem_put_le32(vp8_file_header+28, 0);                     /* unused */
+    fwrite(vp8_file_header, 1, 32, mFilehandle);
+
+	}
+
+private:
+
+    static void *ThreadFunc(void *me) {
+        IVFWriter *writer = static_cast<IVFWriter *>(me);
+
+        status_t err = OK;
+		char vp8_frame_header[12];
+		unsigned int vp8_frame_length;
+
+
+        while (writer->mRunning) {
+            MediaBuffer* buffer;
+            err = writer->mSource->read(&buffer, NULL);
+
+            if (err == OK) {
+				vp8_frame_length = buffer->range_length();
+				mem_put_le32(vp8_frame_header, vp8_frame_length);
+				mem_put_le32(vp8_frame_header+4, pts&0xFFFFFFFF);
+				mem_put_le32(vp8_frame_header+8, pts >> 32);
+				fwrite(vp8_frame_header, 1, 12, writer->mFilehandle);
+				pts++;
+                fwrite(buffer->data()+buffer->range_offset(), 1, buffer->range_length(), writer->mFilehandle);
+				buffer->release();
+                continue;
+            }else {
+                if (err != ERROR_END_OF_STREAM)
+                    LOG("RawWriter::threadfunc err=%d\n", err);
+                writer->mEOS = true;
+                writer->mRunning = false;
+                fflush(writer->mFilehandle);
+                return NULL;
+            }
+        }
+
+        return NULL;
+    }
+
+};
+
+
 class RawWriter : public MediaWriter {
 public:
     RawWriter(char* file) {
@@ -1138,7 +1287,7 @@
     printf("Usage: mix_encoder2 [options]\n\n");
     printf(" -a/--initQP <qp>					set initQP, default 0\n");
     printf(" -b/--bitrate <Bitrate>				set bitrate bps, default 10M\n");
-    printf(" -c/--codec <Codec>				select codec, like H264(default), MPEG4, H263\n");
+    printf(" -c/--codec <Codec>				select codec, like H264(default), MPEG4, H263, VP8\n");
     printf(" -d/--intraPeriod <period>			set IntraPeriod, default 30\n");
     printf(" -e/--encoder	 <encoder>			select encoder, like MIX(default), OMXCODEC\n");
     printf(" -f <output file>				set output file name\n");
@@ -1148,7 +1297,7 @@
     printf(" -l/--idrInterval					set IdrInterval, default 1\n");
     printf(" -m/--disableMetadata				disable Metadata Mode(default enabled)\n");
     printf(" -n/--count <number>				set source frame number, default 30\n");
-    printf(" -o/--outputformat <format>			set output file format, like MP4(default), RAW\n");
+    printf(" -o/--outputformat <format>			set output file format, like MP4(default), RAW, IVF(only for VP8)\n");
     printf(" -p/--fps <Bitrate>				set frame rate, default 30\n");
     printf(" -q/--minQP <qp>					set minQP, default 0\n");
     printf(" -r/--rcMode <Mode>				set rc mode, like VBR(default), CBR, VCM, NO_RC\n");
@@ -1220,9 +1369,9 @@
     const char *SRCTYPE[] = {"MALLOC", "VASURFACE", "GFX", "GRALLOC",
 						"CAMERASOURCE", "SURFACEMEDIASOURCE", "MEMHEAP", NULL};
     const char *ENCTYPE[] = {"MIX", "OMXCODEC", NULL};
-    const char *CODEC[] = {"H264", "MPEG4", "H263", NULL};
+    const char *CODEC[] = {"H264", "MPEG4", "H263", "VP8",NULL};
     const char *RCMODE[] = {"VBR", "CBR", "VCM", "NO_RC", NULL};
-    const char *OUTFORMAT[] = {"MP4", "RAW", NULL};
+    const char *OUTFORMAT[] = {"MP4", "RAW", "IVF", NULL};
 
     while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL) ) != EOF) {
         switch (c) {
@@ -1401,7 +1550,7 @@
 			SrcFps, MetadataMode, Yuvfile);
     }
 
-    printf("Setup Encoder\n");
+    printf("Setup Encoder EncCodec is %d\n",EncCodec);
     //setup encoder
     sp<MetaData> enc_meta = new MetaData;
     switch (EncCodec) {
@@ -1411,6 +1560,9 @@
         case 2:
             enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
             break;
+		case 3: 
+			enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VPX);
+			break;
         default:
             enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
             break;
@@ -1456,15 +1608,17 @@
 
     if (OutFormat == 0)
         writer = new MPEG4Writer(OutFileName);
-    else
+    else if (OutFormat == 1)
         writer = new RawWriter(OutFileName);
+	else 
+		writer = new IVFWriter(OutFileName);
 
     writer->addSource(encoder);
 
     printf("Start encoding\n");
 
     int64_t start = systemTime();
-    CHECK_EQ((status_t)OK, writer->start());
+    CHECK_EQ((status_t)OK, writer->start(enc_meta.get()));
     while (!writer->reachedEOS()) {
         usleep(100000);
     }