libmix:enable native buffer in libmix

BZ: 18370

add native buffer support in libmix

Signed-off-by: ywan171 <yi.a.wang@intel.com>

Change-Id: I424d0f11aae17bf9f18590ad7a5193ea966cde5f
Reviewed-on: http://android.intel.com:8080/27897
Reviewed-by: Ding, Haitao <haitao.ding@intel.com>
Tested-by: Ding, Haitao <haitao.ding@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
diff --git a/mix_video/src/mixvideoformat_h264.cpp b/mix_video/src/mixvideoformat_h264.cpp
index a8213a7..7a43869 100755
--- a/mix_video/src/mixvideoformat_h264.cpp
+++ b/mix_video/src/mixvideoformat_h264.cpp
@@ -598,7 +598,7 @@
                this->picture_height,
                VA_RT_FORMAT_YUV420,
                this->va_num_surfaces,
-               this->va_surfaces);
+               this->va_surfaces, NULL, 0);
 
     if (vret != VA_STATUS_SUCCESS) {
         ret = MIX_RESULT_NO_MEMORY; // MIX_RESULT_FAIL;
diff --git a/mix_video/src/mixvideoformat_mp42.cpp b/mix_video/src/mixvideoformat_mp42.cpp
index e8c5fd1..627401e 100644
--- a/mix_video/src/mixvideoformat_mp42.cpp
+++ b/mix_video/src/mixvideoformat_mp42.cpp
@@ -182,7 +182,8 @@
                this->picture_height,
                VA_RT_FORMAT_YUV420,
                this->va_num_surfaces,
-               this->va_surfaces);
+               this->va_surfaces,
+               NULL, 0);
 
     if (vret != VA_STATUS_SUCCESS) {
         ret = MIX_RESULT_FAIL;
diff --git a/mix_video/src/mixvideoformat_vc1.cpp b/mix_video/src/mixvideoformat_vc1.cpp
index cd672d9..82b5a78 100644
--- a/mix_video/src/mixvideoformat_vc1.cpp
+++ b/mix_video/src/mixvideoformat_vc1.cpp
@@ -261,7 +261,7 @@
                this->picture_height,
                VA_RT_FORMAT_YUV420,
                this->va_num_surfaces,
-               this->va_surfaces);
+               this->va_surfaces, NULL , 0);
 
     if (vret != VA_STATUS_SUCCESS) {
         ret = MIX_RESULT_FAIL;
diff --git a/mix_video/src/mixvideoformatenc_h263.cpp b/mix_video/src/mixvideoformatenc_h263.cpp
index 78aec17..a2f9854 100644
--- a/mix_video/src/mixvideoformatenc_h263.cpp
+++ b/mix_video/src/mixvideoformatenc_h263.cpp
@@ -475,7 +475,7 @@
 
     va_status = vaCreateSurfaces(va_display, this->picture_width,
                                  this->picture_height, this->va_format,
-                                 normal_surfaces_cnt, surfaces);
+                                 normal_surfaces_cnt, surfaces, NULL, 0);
 
     if (va_status != VA_STATUS_SUCCESS)
     {
diff --git a/mix_video/src/mixvideoformatenc_h264.cpp b/mix_video/src/mixvideoformatenc_h264.cpp
index 6c2374a..f227c8d 100644
--- a/mix_video/src/mixvideoformatenc_h264.cpp
+++ b/mix_video/src/mixvideoformatenc_h264.cpp
@@ -548,7 +548,7 @@
 
     va_status = vaCreateSurfaces(va_display, this->picture_width,
                                  this->picture_height, this->va_format,
-                                 normal_surfaces_cnt, surfaces);
+                                 normal_surfaces_cnt, surfaces, NULL, 0);
 
     if (va_status != VA_STATUS_SUCCESS)
     {
diff --git a/mix_video/src/mixvideoformatenc_mpeg4.cpp b/mix_video/src/mixvideoformatenc_mpeg4.cpp
index 1f76307..4dcf9c6 100644
--- a/mix_video/src/mixvideoformatenc_mpeg4.cpp
+++ b/mix_video/src/mixvideoformatenc_mpeg4.cpp
@@ -433,7 +433,7 @@
     va_status = vaCreateSurfaces(
                     va_display, this->picture_width,
                     this->picture_height, this->va_format,
-                    normal_surfaces_cnt, surfaces);
+                    normal_surfaces_cnt, surfaces, NULL, 0);
 
     if (va_status != VA_STATUS_SUCCESS) {
         LOG_E("Failed vaCreateSurfaces\n");
diff --git a/mix_video/src/mixvideoformatenc_preview.cpp b/mix_video/src/mixvideoformatenc_preview.cpp
index ae2f7bb..a1cdcbb 100644
--- a/mix_video/src/mixvideoformatenc_preview.cpp
+++ b/mix_video/src/mixvideoformatenc_preview.cpp
@@ -363,7 +363,7 @@
     va_status = vaCreateSurfaces(
                     va_display, this->picture_width,
                     this->picture_height, this->va_format,
-                    normal_surfaces_cnt, surfaces);
+                    normal_surfaces_cnt, surfaces, NULL, 0 );
 
     if (va_status != VA_STATUS_SUCCESS) {
         LOG_E("Failed vaCreateSurfaces\n");
diff --git a/videodecoder/VideoDecoderBase.cpp b/videodecoder/VideoDecoderBase.cpp
index 0a68d68..c71eff6 100644
--- a/videodecoder/VideoDecoderBase.cpp
+++ b/videodecoder/VideoDecoderBase.cpp
@@ -66,18 +66,27 @@
       mOutputHead(NULL),
       mOutputTail(NULL),
       mSurfaces(NULL),
+      mVASurfaceAttrib(NULL),
+      mVAExternalMemoryBuffers(NULL),
       mSurfaceUserPtr(NULL),
       mSurfaceAcquirePos(0),
       mNextOutputPOC(MINIMUM_POC),
       mParserType(type),
-      mParserHandle(NULL) {
+      mParserHandle(NULL),
+      initialized(false),
+      mSignalBufferSize(0){
 
     memset(&mVideoFormatInfo, 0, sizeof(VideoFormatInfo));
     memset(&mConfigBuffer, 0, sizeof(mConfigBuffer));
+    for(int i =0 ; i < MAX_GRAPHIC_NUM ; i++) {
+         mSignalBufferPre[i] = NULL;
+    }
+    pthread_mutex_init(&mLock, NULL);
     mVideoFormatInfo.mimeType = strdup(mimeType);
 }
 
 VideoDecoderBase::~VideoDecoderBase() {
+    pthread_mutex_destroy(&mLock);
     stop();
     free(mVideoFormatInfo.mimeType);
 }
@@ -160,6 +169,7 @@
 
     // initialize surface buffer without resetting mapped/raw data
     initSurfaceBuffer(false);
+
 }
 
 const VideoFormatInfo* VideoDecoderBase::getFormatInfo(void) {
@@ -170,6 +180,7 @@
     if (mVAStarted == false) {
         return NULL;
     }
+    bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
 
     if (draining) {
         // complete decoding the last frame and ignore return
@@ -188,6 +199,9 @@
         if (mOutputHead == NULL) {
             mOutputTail = NULL;
         }
+        if(useGraphicBuffer ) {
+            vaSyncSurface(mVADisplay,outputByPos->renderBuffer.surface);
+        }
         return &(outputByPos->renderBuffer);
     }
 
@@ -232,6 +246,9 @@
             mOutputTail = NULL;
         }
     }
+    if(useGraphicBuffer ) {
+         vaSyncSurface(mVADisplay,output->renderBuffer.surface);
+    }
     //VTRACE("Output POC %d for display (pts = %.2f)", output->pictureOrder, output->renderBuffer.timeStamp/1E6);
     return &(output->renderBuffer);
 }
@@ -601,6 +618,9 @@
         return DECODE_SUCCESS;
     }
 
+    if(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER){
+       numSurface = mConfigBuffer.surfaceNumber;
+    }
     // TODO: validate profile
     if (numSurface == 0) {
         return DECODE_FAIL;
@@ -660,14 +680,52 @@
         format |= VA_RT_FORMAT_PROTECTED;
         LOGW("Surface is protected.");
     }
-
-    vaStatus = vaCreateSurfaces(
+    if(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER) {
+        mVASurfaceAttrib = new VASurfaceAttrib;
+        if (mVASurfaceAttrib == NULL) {
+            return DECODE_MEMORY_FAIL;
+        }
+        mVAExternalMemoryBuffers = new VAExternalMemoryBuffers;
+        if (mVAExternalMemoryBuffers == NULL) {
+            return DECODE_MEMORY_FAIL;
+        }
+        mVAExternalMemoryBuffers->buffers= (unsigned int *)malloc(sizeof(unsigned int)*mNumSurfaces);
+        if (mVAExternalMemoryBuffers->buffers == NULL) {
+            return DECODE_MEMORY_FAIL;
+        }
+        mVAExternalMemoryBuffers->count = mNumSurfaces;
+        mVAExternalMemoryBuffers->luma_stride= mConfigBuffer.graphicBufferStride;
+        mVAExternalMemoryBuffers->pixel_format = mConfigBuffer.graphicBufferColorFormat;
+        mVAExternalMemoryBuffers->width = mVideoFormatInfo.width;
+        mVAExternalMemoryBuffers->height = mVideoFormatInfo.height;
+        mVAExternalMemoryBuffers->type = VAExternalMemoryAndroidGrallocBuffer;
+        for(int i=0; i < mNumSurfaces; i++) {
+            mVAExternalMemoryBuffers->buffers[i] = (unsigned int )mConfigBuffer.graphicBufferHandler[i];
+        }
+        mVASurfaceAttrib->flags = VA_SURFACE_ATTRIB_SETTABLE;
+        mVASurfaceAttrib->type = VASurfaceAttribNativeHandle;
+        mVASurfaceAttrib->value.type =VAGenericValueTypePointer;
+        mVASurfaceAttrib->value.value.p_val= (void *)mVAExternalMemoryBuffers;
+        vaStatus = vaCreateSurfaces(
             mVADisplay,
             mVideoFormatInfo.width,
             mVideoFormatInfo.height,
             format,
             mNumSurfaces,
-            mSurfaces);
+            mSurfaces,
+            mVASurfaceAttrib,
+            1);
+    } else {
+        vaStatus = vaCreateSurfaces(
+            mVADisplay,
+            mVideoFormatInfo.width,
+            mVideoFormatInfo.height,
+            format,
+            mNumSurfaces,
+            mSurfaces,
+            NULL,
+            0);
+    }
     CHECK_VA_STATUS("vaCreateSurfaces");
 
     mVideoFormatInfo.surfaceWidth = mVideoFormatInfo.width;
@@ -722,6 +780,22 @@
         mSurfaceBuffers = NULL;
     }
 
+
+    if(mVAExternalMemoryBuffers) {
+        if(mVAExternalMemoryBuffers->buffers) {
+            free(mVAExternalMemoryBuffers->buffers);
+            mVAExternalMemoryBuffers->buffers= NULL;
+        }
+        delete mVAExternalMemoryBuffers;
+        mVAExternalMemoryBuffers =  NULL;
+    }
+
+    if(mVASurfaceAttrib) {
+        delete mVASurfaceAttrib;
+        mVASurfaceAttrib = NULL;
+    }
+
+
     if (mSurfaceUserPtr) {
         delete [] mSurfaceUserPtr;
         mSurfaceUserPtr = NULL;
@@ -931,13 +1005,16 @@
 }
 
 void VideoDecoderBase::initSurfaceBuffer(bool reset) {
+    bool useGraphicBuffer = mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER;
+    if(useGraphicBuffer && reset){
+        pthread_mutex_lock(&mLock);
+     }
     for (int32_t i = 0; i < mNumSurfaces; i++) {
         mSurfaceBuffers[i].renderBuffer.display = mVADisplay;
         mSurfaceBuffers[i].renderBuffer.surface = VA_INVALID_SURFACE;  // set in acquireSurfaceBuffer
         mSurfaceBuffers[i].renderBuffer.flag = 0;
         mSurfaceBuffers[i].renderBuffer.scanFormat = VA_FRAME_PICTURE;
         mSurfaceBuffers[i].renderBuffer.timeStamp = 0;
-        mSurfaceBuffers[i].renderBuffer.renderDone = true;
         mSurfaceBuffers[i].referenceFrame = false;
         mSurfaceBuffers[i].asReferernce= false;
         mSurfaceBuffers[i].pictureOrder = 0;
@@ -946,6 +1023,93 @@
             mSurfaceBuffers[i].renderBuffer.rawData = NULL;
             mSurfaceBuffers[i].mappedData = NULL;
         }
+        if (useGraphicBuffer){
+            if(reset){
+               mSurfaceBuffers[i].renderBuffer.graphicBufferHandle = mConfigBuffer.graphicBufferHandler[i];
+               mSurfaceBuffers[i].renderBuffer.renderDone = false; //default false
+               for(int j =0; j < mSignalBufferSize; j++){
+                   if(mSignalBufferPre[j] != NULL && mSignalBufferPre[j] == mSurfaceBuffers[i].renderBuffer.graphicBufferHandle){
+                      mSurfaceBuffers[i].renderBuffer.renderDone = true;
+                      VTRACE("initSurfaceBuffer set renderDone = true index=%d",i);
+                      mSignalBufferPre[j] = NULL;
+                      break;
+                   }
+               }
+            }
+            else{
+               mSurfaceBuffers[i].renderBuffer.renderDone = false;
+            }
+
+        } else {
+            mSurfaceBuffers[i].renderBuffer.graphicBufferHandle= NULL;
+            mSurfaceBuffers[i].renderBuffer.renderDone = true;
+        }
+        mSurfaceBuffers[i].renderBuffer.acquirePos = i;
+    }
+
+    if(useGraphicBuffer && reset){
+        initialized = true;
+        mSignalBufferSize = 0;
+        pthread_mutex_unlock(&mLock);
     }
 }
 
+Decode_Status VideoDecoderBase::SignalRenderDoneFlag(void * graphichandler) {
+
+    if (graphichandler == NULL) {
+        return DECODE_SUCCESS;
+    }
+    pthread_mutex_lock(&mLock);
+    int i = 0;
+    if(!initialized){
+       mSignalBufferPre[mSignalBufferSize++] = graphichandler;
+       VTRACE("SignalRenderDoneFlag initialized = false graphichandler = %p, mSignalBufferSize=%d",graphichandler,mSignalBufferSize);
+       if(mSignalBufferSize > MAX_GRAPHIC_NUM)
+         return DECODE_INVALID_DATA;
+    }
+    else{
+        if (!(mConfigBuffer.flag & USE_NATIVE_GRAPHIC_BUFFER)) {
+            return DECODE_SUCCESS;
+        }
+        for (i = 0; i < mNumSurfaces; i++) {
+           if (mSurfaceBuffers[i].renderBuffer.graphicBufferHandle== graphichandler) {
+               mSurfaceBuffers[i].renderBuffer.renderDone = true;
+               VTRACE("SignalRenderDoneFlag initialized = true index =%d",i);
+               break;
+           }
+        }
+    }
+    pthread_mutex_unlock(&mLock);
+
+    return DECODE_SUCCESS;
+
+}
+
+Decode_Status VideoDecoderBase::GetNativeBufferStatus(void * graphichandler, bool* used) {
+    bool inuse = false;
+    if(!initialized) {
+        *used == false;
+        return DECODE_NOT_STARTED;
+    }
+
+    for (int32_t i = 0; i < mNumSurfaces; i++) {
+        if (mSurfaceBuffers[i].renderBuffer.graphicBufferHandle == graphichandler) {
+            if (mSurfaceBuffers[i].asReferernce == true ||mSurfaceBuffers + i == mAcquiredBuffer ) {
+                    inuse = true;
+            }
+            break;
+        }
+    }
+    VideoSurfaceBuffer *p = mOutputHead;
+
+    while (p!=NULL) {
+        if(p ->renderBuffer.graphicBufferHandle == graphichandler) {
+            inuse = true;
+            break;
+        }
+        p = p->next;
+    }
+
+    *used = inuse;
+    return DECODE_SUCCESS;
+}
diff --git a/videodecoder/VideoDecoderBase.h b/videodecoder/VideoDecoderBase.h
index da1a655..3df3e3f 100644
--- a/videodecoder/VideoDecoderBase.h
+++ b/videodecoder/VideoDecoderBase.h
@@ -28,6 +28,8 @@
 #include <va/va.h>
 #include "VideoDecoderDefs.h"
 #include "VideoDecoderInterface.h"
+#include <pthread.h>
+
 
 extern "C" {
 #include "vbp_loader.h"
@@ -48,6 +50,8 @@
     //virtual Decode_Status decode(VideoDecodeBuffer *buffer);
     virtual void flush(void);
     virtual const VideoRenderBuffer* getOutput(bool draining = false);
+    virtual Decode_Status SignalRenderDoneFlag(void * graphichandler);
+    virtual Decode_Status GetNativeBufferStatus(void * graphichandler, bool* used);
     virtual const VideoFormatInfo* getFormatInfo(void);
 
 protected:
@@ -75,6 +79,10 @@
     Decode_Status getRawDataFromSurface(void);
     void initSurfaceBuffer(bool reset);
 
+    bool initialized;
+    pthread_mutex_t mLock;
+
+
 protected:
     VideoFormatInfo mVideoFormatInfo;
     Display *mDisplay;
@@ -120,11 +128,15 @@
     VideoSurfaceBuffer *mOutputHead; // head of output buffer list
     VideoSurfaceBuffer *mOutputTail;  // tail of output buffer list
     VASurfaceID *mSurfaces; // surfaces array
+    VASurfaceAttrib *mVASurfaceAttrib;
+    VAExternalMemoryBuffers *mVAExternalMemoryBuffers;
     uint8_t **mSurfaceUserPtr; // mapped user space pointer
     int32_t mSurfaceAcquirePos; // position of surface to start acquiring
     int32_t mNextOutputPOC; // Picture order count of next output
     _vbp_parser_type mParserType;
     void *mParserHandle;
+    void *mSignalBufferPre[MAX_GRAPHIC_NUM];
+    uint32 mSignalBufferSize;
 
 protected:
     void ManageReference(bool enable) {mManageReference = enable;}
diff --git a/videodecoder/VideoDecoderDefs.h b/videodecoder/VideoDecoderDefs.h
index a715d7c..5f1eac4 100644
--- a/videodecoder/VideoDecoderDefs.h
+++ b/videodecoder/VideoDecoderDefs.h
@@ -85,6 +85,9 @@
     // indicates if buffer contains codec data
     HAS_CODECDATA = 0x1000,
 
+    // indicate if it use graphic buffer.
+    USE_NATIVE_GRAPHIC_BUFFER = 0x2000,
+
 } VIDEO_BUFFER_FLAG;
 
 struct VideoDecodeBuffer {
@@ -96,6 +99,8 @@
 };
 
 
+#define MAX_GRAPHIC_NUM 16+1+6 // max DPB +1+AVC_EXTRA_NUM
+
 struct VideoConfigBuffer {
     uint8_t *data;
     int32_t size;
@@ -104,6 +109,9 @@
     int32_t surfaceNumber;
     VAProfile profile;
     uint32_t flag;
+    void *graphicBufferHandler[ MAX_GRAPHIC_NUM ];
+    uint32_t graphicBufferStride;
+    uint32_t graphicBufferColorFormat;
     VideoFormatSpecificData *ext;
 };
 
@@ -114,6 +122,8 @@
     int64_t timeStamp;  // presentation time stamp
     mutable volatile bool renderDone;  // indicated whether frame is rendered, this must be set to false by the client of this library once
                                         // surface is rendered. Not setting this flag will lead to DECODE_NO_SURFACE error.
+    void * graphicBufferHandle;
+    int32_t acquirePos;  //the acquirepos in graphichandle array
     uint32_t flag;
     VideoFrameRawData *rawData;
 };
diff --git a/videodecoder/VideoDecoderInterface.h b/videodecoder/VideoDecoderInterface.h
index eb2d171..6b54deb 100644
--- a/videodecoder/VideoDecoderInterface.h
+++ b/videodecoder/VideoDecoderInterface.h
@@ -37,6 +37,9 @@
     virtual Decode_Status decode(VideoDecodeBuffer *buffer) = 0;
     virtual const VideoRenderBuffer* getOutput(bool draining = false) = 0;
     virtual const VideoFormatInfo* getFormatInfo(void) = 0;
+    virtual Decode_Status SignalRenderDoneFlag(void * graphichandler) = 0;
+    virtual Decode_Status GetNativeBufferStatus(void * graphichandler, bool* used) = 0;
+
 };
 
 #endif /* VIDEO_DECODER_INTERFACE_H_ */
diff --git a/videoencoder/VideoEncoderBase.cpp b/videoencoder/VideoEncoderBase.cpp
index 5fe041b..0378af6 100644
--- a/videoencoder/VideoEncoderBase.cpp
+++ b/videoencoder/VideoEncoderBase.cpp
@@ -212,7 +212,7 @@
 
     vaStatus = vaCreateSurfaces(mVADisplay, mComParams.resolution.width,
             mComParams.resolution.height, VA_RT_FORMAT_YUV420,
-            normalSurfacesCnt, surfaces);
+            normalSurfacesCnt, surfaces, NULL , 0);
     CHECK_VA_STATUS_GOTO_CLEANUP("vaCreateSurfaces");
 
     switch (mBufferMode) {