videoeditor preview code on honeycomb

Change-Id: I9c3c9cb921ea697ab16732973d26ef9035cda2ee
diff --git a/libvideoeditor/lvpp/VideoEditorPreviewController.cpp b/libvideoeditor/lvpp/VideoEditorPreviewController.cpp
new file mode 100755
index 0000000..d862255
--- /dev/null
+++ b/libvideoeditor/lvpp/VideoEditorPreviewController.cpp
@@ -0,0 +1,1303 @@
+/*

+ * Copyright (C) 2011 NXP Software

+ * Copyright (C) 2011 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+#define LOG_NDEBUG 1

+#define LOG_TAG "VideoEditorPreviewController"

+#include "VideoEditorPreviewController.h"

+

+namespace android {

+

+#define PREVIEW_THREAD_STACK_SIZE                           (65536)

+

+VideoEditorPreviewController::VideoEditorPreviewController()

+    : mCurrentPlayer(0),

+      mThreadContext(NULL),

+      mPlayerState(VePlayerIdle),

+      mClipList(NULL),

+      mNumberClipsInStoryBoard(0),

+      mNumberClipsToPreview(0),

+      mStartingClipIndex(0),

+      mPreviewLooping(M4OSA_FALSE),

+      mCallBackAfterFrameCnt(0),

+      mEffectsSettings(NULL),

+      mNumberEffects(0),

+      mCurrentClipNumber(-1),

+      mClipTotalDuration(0),

+      mCurrentVideoEffect(VIDEO_EFFECT_NONE),

+      mTarget(NULL),

+      mJniCookie(NULL),

+      mJniCallback(NULL),

+      mBackgroundAudioSetting(NULL),

+      mAudioMixPCMFileHandle(NULL),

+      mVideoStoryBoardTimeMsUptoFirstPreviewClip(0),

+      mCurrentPlayedDuration(0),

+      mCurrentClipDuration(0),

+      mOutputVideoWidth(0),

+      mOutputVideoHeight(0),

+      bStopThreadInProgress(false),

+      mSemThreadWait(NULL) {

+    LOGV("VideoEditorPreviewController");

+    mRenderingMode = M4xVSS_kBlackBorders;

+    mIsFiftiesEffectStarted = false;

+

+    for (int i=0; i<NBPLAYER_INSTANCES; i++) {

+        mVePlayer[i] = NULL;

+    }

+}

+

+VideoEditorPreviewController::~VideoEditorPreviewController() {

+    M4OSA_UInt32 i = 0;

+    M4OSA_ERR err = M4NO_ERROR;

+    LOGV("~VideoEditorPreviewController");

+

+    // Stop the thread if its still running

+    if(mThreadContext != NULL) {

+        err = M4OSA_threadSyncStop(mThreadContext);

+        if(err != M4NO_ERROR) {

+            LOGV("~VideoEditorPreviewController: error 0x%x \

+            in trying to stop thread", err);

+            // Continue even if error

+        }

+

+        err = M4OSA_threadSyncClose(mThreadContext);

+        if(err != M4NO_ERROR) {

+            LOGE("~VideoEditorPreviewController: error 0x%x \

+            in trying to close thread", err);

+            // Continue even if error

+        }

+

+        mThreadContext = NULL;

+    }

+

+    for (int playerInst=0; playerInst<NBPLAYER_INSTANCES;

+         playerInst++) {

+        if(mVePlayer[playerInst] != NULL) {

+            LOGV("clearing mVePlayer %d", playerInst);

+            mVePlayer[playerInst].clear();

+        }

+    }

+

+    if(mClipList != NULL) {

+        // Clean up

+        for(i=0;i<mNumberClipsInStoryBoard;i++)

+        {

+            if(mClipList[i]->pFile != NULL) {

+                M4OSA_free((M4OSA_MemAddr32)mClipList[i]->pFile);

+                mClipList[i]->pFile = NULL;

+            }

+

+            M4OSA_free((M4OSA_MemAddr32)mClipList[i]);

+        }

+        M4OSA_free((M4OSA_MemAddr32)mClipList);

+        mClipList = NULL;

+    }

+

+    if(mEffectsSettings) {

+        for(i=0;i<mNumberEffects;i++) {

+            if(mEffectsSettings[i].xVSS.pFramingBuffer != NULL) {

+                M4OSA_free(

+                (M4OSA_MemAddr32)mEffectsSettings[i].xVSS.pFramingBuffer->pac_data);

+

+                M4OSA_free(

+                (M4OSA_MemAddr32)mEffectsSettings[i].xVSS.pFramingBuffer);

+

+                mEffectsSettings[i].xVSS.pFramingBuffer = NULL;

+            }

+        }

+        M4OSA_free((M4OSA_MemAddr32)mEffectsSettings);

+        mEffectsSettings = NULL;

+    }

+

+    if(mTarget != NULL) {

+        delete mTarget;

+        mTarget = NULL;

+    }

+

+    LOGV("~VideoEditorPreviewController returns");

+}

+

+M4OSA_ERR VideoEditorPreviewController::loadEditSettings(

+    M4VSS3GPP_EditSettings* pSettings,M4xVSS_AudioMixingSettings* bgmSettings) {

+

+    M4OSA_UInt32 i = 0, iClipDuration = 0, rgbSize = 0;

+    M4VIFI_UInt8 *tmp = NULL;

+    M4OSA_ERR err = M4NO_ERROR;

+

+    LOGV("loadEditSettings");

+    LOGV("loadEditSettings Channels = %d, sampling Freq %d",

+          bgmSettings->uiNbChannels, bgmSettings->uiSamplingFrequency  );

+          bgmSettings->uiSamplingFrequency = 32000;

+

+    LOGV("loadEditSettings Channels = %d, sampling Freq %d",

+          bgmSettings->uiNbChannels, bgmSettings->uiSamplingFrequency  );

+    Mutex::Autolock autoLock(mLock);

+

+    // Clean up any previous Edit settings before loading new ones

+    mCurrentVideoEffect = VIDEO_EFFECT_NONE;

+

+    if(mAudioMixPCMFileHandle) {

+        err = M4OSA_fileReadClose (mAudioMixPCMFileHandle);

+        mAudioMixPCMFileHandle = M4OSA_NULL;

+    }

+

+    if(mBackgroundAudioSetting != NULL) {

+        M4OSA_free((M4OSA_MemAddr32)mBackgroundAudioSetting);

+        mBackgroundAudioSetting = NULL;

+    }

+

+    if(mClipList != NULL) {

+        // Clean up

+        for(i=0;i<mNumberClipsInStoryBoard;i++)

+        {

+            if(mClipList[i]->pFile != NULL) {

+                M4OSA_free((M4OSA_MemAddr32)mClipList[i]->pFile);

+                mClipList[i]->pFile = NULL;

+            }

+

+            M4OSA_free((M4OSA_MemAddr32)mClipList[i]);

+        }

+        M4OSA_free((M4OSA_MemAddr32)mClipList);

+        mClipList = NULL;

+    }

+

+    if(mEffectsSettings) {

+        for(i=0;i<mNumberEffects;i++) {

+            if(mEffectsSettings[i].xVSS.pFramingBuffer != NULL) {

+                M4OSA_free(

+                (M4OSA_MemAddr32)mEffectsSettings[i].xVSS.pFramingBuffer->pac_data);

+

+                M4OSA_free(

+                (M4OSA_MemAddr32)mEffectsSettings[i].xVSS.pFramingBuffer);

+

+                mEffectsSettings[i].xVSS.pFramingBuffer = NULL;

+            }

+        }

+        M4OSA_free((M4OSA_MemAddr32)mEffectsSettings);

+        mEffectsSettings = NULL;

+    }

+

+    if(mClipList == NULL) {

+        mNumberClipsInStoryBoard = pSettings->uiClipNumber;

+        LOGV("loadEditSettings: # of Clips = %d", mNumberClipsInStoryBoard);

+

+        mClipList = (M4VSS3GPP_ClipSettings**)M4OSA_malloc(

+         sizeof(M4VSS3GPP_ClipSettings*)*pSettings->uiClipNumber, M4VS,

+         (M4OSA_Char*)"LvPP, copy of pClipList");

+

+        if(NULL == mClipList) {

+            LOGE("loadEditSettings: Malloc error");

+            return M4ERR_ALLOC;

+        }

+        M4OSA_memset((M4OSA_MemAddr8)mClipList,

+         sizeof(M4VSS3GPP_ClipSettings*)*pSettings->uiClipNumber, 0);

+

+        for(i=0;i<pSettings->uiClipNumber;i++) {

+

+            // Allocate current clip

+            mClipList[i] =

+             (M4VSS3GPP_ClipSettings*)M4OSA_malloc(

+              sizeof(M4VSS3GPP_ClipSettings),M4VS,(M4OSA_Char*)"clip settings");

+

+            if(mClipList[i] == NULL) {

+

+                LOGE("loadEditSettings: Allocation error for mClipList[%d]", i);

+                return M4ERR_ALLOC;

+            }

+            // Copy plain structure

+            M4OSA_memcpy((M4OSA_MemAddr8)mClipList[i],

+             (M4OSA_MemAddr8)pSettings->pClipList[i],

+             sizeof(M4VSS3GPP_ClipSettings));

+

+            if(NULL != pSettings->pClipList[i]->pFile) {

+                mClipList[i]->pFile = (M4OSA_Char*)M4OSA_malloc(

+                pSettings->pClipList[i]->filePathSize, M4VS,

+                (M4OSA_Char*)"pClipSettingsDest->pFile");

+

+                if(NULL == mClipList[i]->pFile)

+                {

+                    LOGE("loadEditSettings : ERROR allocating filename");

+                    return M4ERR_ALLOC;

+                }

+

+                M4OSA_memcpy((M4OSA_MemAddr8)mClipList[i]->pFile,

+                 (M4OSA_MemAddr8)pSettings->pClipList[i]->pFile,

+                 pSettings->pClipList[i]->filePathSize);

+            }

+            else {

+                LOGE("NULL file path");

+                return M4ERR_PARAMETER;

+            }

+

+            // Calculate total duration of all clips

+            iClipDuration = pSettings->pClipList[i]->uiEndCutTime -

+             pSettings->pClipList[i]->uiBeginCutTime;

+

+            mClipTotalDuration = mClipTotalDuration+iClipDuration;

+        }

+    }

+

+    if(mEffectsSettings == NULL) {

+        mNumberEffects = pSettings->nbEffects;

+        LOGV("loadEditSettings: mNumberEffects = %d", mNumberEffects);

+

+        if(mNumberEffects != 0) {

+            mEffectsSettings = (M4VSS3GPP_EffectSettings*)M4OSA_malloc(

+             mNumberEffects*sizeof(M4VSS3GPP_EffectSettings),

+             M4VS, (M4OSA_Char*)"effects settings");

+

+            if(mEffectsSettings == NULL) {

+                LOGE("loadEffectsSettings: Allocation error");

+                return M4ERR_ALLOC;

+            }

+

+            M4OSA_memset((M4OSA_MemAddr8)mEffectsSettings,

+             mNumberEffects*sizeof(M4VSS3GPP_EffectSettings), 0);

+

+            for(i=0;i<mNumberEffects;i++) {

+

+                mEffectsSettings[i].xVSS.pFramingFilePath = NULL;

+                mEffectsSettings[i].xVSS.pFramingBuffer = NULL;

+                mEffectsSettings[i].xVSS.pTextBuffer = NULL;

+

+                M4OSA_memcpy((M4OSA_MemAddr8)&(mEffectsSettings[i]),

+                 (M4OSA_MemAddr8)&(pSettings->Effects[i]),

+                 sizeof(M4VSS3GPP_EffectSettings));

+

+                if(pSettings->Effects[i].VideoEffectType ==

+                 M4xVSS_kVideoEffectType_Framing) {

+                    // Allocate the pFraming RGB buffer

+                    mEffectsSettings[i].xVSS.pFramingBuffer =

+                    (M4VIFI_ImagePlane *)M4OSA_malloc(sizeof(M4VIFI_ImagePlane),

+                     M4VS, (M4OSA_Char*)"lvpp framing buffer");

+

+                    if(mEffectsSettings[i].xVSS.pFramingBuffer == NULL) {

+                        LOGE("loadEffectsSettings:Alloc error for pFramingBuf");

+                        M4OSA_free((M4OSA_MemAddr32)mEffectsSettings);

+                        mEffectsSettings = NULL;

+                        return M4ERR_ALLOC;

+                    }

+

+                    // Allocate the pac_data (RGB)

+                    if(pSettings->Effects[i].xVSS.rgbType == M4VSS3GPP_kRGB565){

+                        rgbSize =

+                         pSettings->Effects[i].xVSS.pFramingBuffer->u_width *

+                         pSettings->Effects[i].xVSS.pFramingBuffer->u_height*2;

+                    }

+                    else if(

+                     pSettings->Effects[i].xVSS.rgbType == M4VSS3GPP_kRGB888) {

+                        rgbSize =

+                         pSettings->Effects[i].xVSS.pFramingBuffer->u_width *

+                         pSettings->Effects[i].xVSS.pFramingBuffer->u_height*3;

+                    }

+                    else {

+                        LOGE("loadEffectsSettings: wrong RGB type");

+                        M4OSA_free((M4OSA_MemAddr32)mEffectsSettings);

+                        mEffectsSettings = NULL;

+                        return M4ERR_PARAMETER;

+                    }

+

+                    tmp = (M4VIFI_UInt8 *)M4OSA_malloc(rgbSize, M4VS,

+                     (M4OSA_Char*)"framing buffer pac_data");

+

+                    if(tmp == NULL) {

+                        LOGE("loadEffectsSettings:Alloc error pFramingBuf pac");

+                        M4OSA_free((M4OSA_MemAddr32)mEffectsSettings);

+                        mEffectsSettings = NULL;

+                        M4OSA_free(

+                        (M4OSA_MemAddr32)mEffectsSettings[i].xVSS.pFramingBuffer);

+

+                        mEffectsSettings[i].xVSS.pFramingBuffer = NULL;

+                        return M4ERR_ALLOC;

+                    }

+                    /* Initialize the pFramingBuffer*/

+                    mEffectsSettings[i].xVSS.pFramingBuffer->pac_data = tmp;

+                    mEffectsSettings[i].xVSS.pFramingBuffer->u_height =

+                     pSettings->Effects[i].xVSS.pFramingBuffer->u_height;

+

+                    mEffectsSettings[i].xVSS.pFramingBuffer->u_width =

+                     pSettings->Effects[i].xVSS.pFramingBuffer->u_width;

+

+                    mEffectsSettings[i].xVSS.pFramingBuffer->u_stride =

+                     pSettings->Effects[i].xVSS.pFramingBuffer->u_stride;

+

+                    mEffectsSettings[i].xVSS.pFramingBuffer->u_topleft =

+                     pSettings->Effects[i].xVSS.pFramingBuffer->u_topleft;

+

+                    mEffectsSettings[i].xVSS.uialphaBlendingStart =

+                     pSettings->Effects[i].xVSS.uialphaBlendingStart;

+

+                    mEffectsSettings[i].xVSS.uialphaBlendingMiddle =

+                     pSettings->Effects[i].xVSS.uialphaBlendingMiddle;

+

+                    mEffectsSettings[i].xVSS.uialphaBlendingEnd =

+                     pSettings->Effects[i].xVSS.uialphaBlendingEnd;

+

+                    mEffectsSettings[i].xVSS.uialphaBlendingFadeInTime =

+                     pSettings->Effects[i].xVSS.uialphaBlendingFadeInTime;

+                    mEffectsSettings[i].xVSS.uialphaBlendingFadeOutTime =

+                     pSettings->Effects[i].xVSS.uialphaBlendingFadeOutTime;

+

+                    // Copy the pFraming data

+                    M4OSA_memcpy((M4OSA_MemAddr8)

+                    mEffectsSettings[i].xVSS.pFramingBuffer->pac_data,

+                    (M4OSA_MemAddr8)pSettings->Effects[i].xVSS.pFramingBuffer->pac_data,

+                    rgbSize);

+

+                    mEffectsSettings[i].xVSS.rgbType =

+                     pSettings->Effects[i].xVSS.rgbType;

+                }

+            }

+        }

+    }

+

+    if (mBackgroundAudioSetting == NULL) {

+

+        mBackgroundAudioSetting = (M4xVSS_AudioMixingSettings*)M4OSA_malloc(

+        sizeof(M4xVSS_AudioMixingSettings), M4VS,

+        (M4OSA_Char*)"LvPP, copy of bgmSettings");

+

+        if(NULL == mBackgroundAudioSetting) {

+            LOGE("loadEditSettings: mBackgroundAudioSetting Malloc failed");

+            return M4ERR_ALLOC;

+        }

+

+        M4OSA_memset((M4OSA_MemAddr8)mBackgroundAudioSetting, sizeof(M4xVSS_AudioMixingSettings*), 0);

+        M4OSA_memcpy((M4OSA_MemAddr8)mBackgroundAudioSetting, (M4OSA_MemAddr8)bgmSettings, sizeof(M4xVSS_AudioMixingSettings));

+

+        if ( mBackgroundAudioSetting->pFile != M4OSA_NULL ) {

+

+            mBackgroundAudioSetting->pFile = (M4OSA_Void*) bgmSettings->pPCMFilePath;

+            mBackgroundAudioSetting->uiNbChannels = 2;

+            mBackgroundAudioSetting->uiSamplingFrequency = 32000;

+        }

+

+        // Open the BG file

+        if ( mBackgroundAudioSetting->pFile != M4OSA_NULL ) {

+            err = M4OSA_fileReadOpen(&mAudioMixPCMFileHandle,

+             mBackgroundAudioSetting->pFile, M4OSA_kFileRead);

+

+            if (err != M4NO_ERROR) {

+                LOGE("loadEditSettings: mBackgroundAudio PCM File open failed");

+                return M4ERR_PARAMETER;

+            }

+        }

+    }

+

+    mOutputVideoSize = pSettings->xVSS.outputVideoSize;

+    mFrameStr.pBuffer = M4OSA_NULL;

+    return M4NO_ERROR;

+}

+

+M4OSA_ERR VideoEditorPreviewController::setSurface(const sp<Surface> &surface) {

+    LOGV("setSurface");

+    Mutex::Autolock autoLock(mLock);

+

+    mSurface = surface;

+    mISurface = surface->getISurface();

+    LOGV("setSurface: mISurface = %p", mISurface.get());

+    return M4NO_ERROR;

+}

+

+M4OSA_ERR VideoEditorPreviewController::startPreview(

+    M4OSA_UInt32 fromMS, M4OSA_Int32 toMs, M4OSA_UInt16 callBackAfterFrameCount,

+    M4OSA_Bool loop) {

+

+    M4OSA_ERR err = M4NO_ERROR;

+    M4OSA_UInt32 i = 0, iIncrementedDuration = 0;

+    LOGV("startPreview");

+

+    if(fromMS > toMs) {

+        LOGE("startPreview: fromMS > toMs");

+        return M4ERR_PARAMETER;

+    }

+

+    if(toMs == 0) {

+        LOGE("startPreview: toMs is 0");

+        return M4ERR_PARAMETER;

+    }

+

+    // If already started, then stop preview first

+    for(int playerInst=0; playerInst<NBPLAYER_INSTANCES; playerInst++) {

+        if(mVePlayer[playerInst] != NULL) {

+            LOGV("startPreview: stopping previously started preview playback");

+            stopPreview();

+            break;

+        }

+    }

+

+    // If renderPreview was called previously, then delete Renderer object first

+    if(mTarget != NULL) {

+        LOGV("startPreview: delete previous PreviewRenderer");

+        delete mTarget;

+        mTarget = NULL;

+    }

+

+    LOGV("startPreview: loop = %d", loop);

+    mPreviewLooping = loop;

+

+    LOGV("startPreview: callBackAfterFrameCount = %d", callBackAfterFrameCount);

+    mCallBackAfterFrameCnt = callBackAfterFrameCount;

+

+    for (int playerInst=0; playerInst<NBPLAYER_INSTANCES; playerInst++) {

+        mVePlayer[playerInst] = new VideoEditorPlayer();

+        if(mVePlayer[playerInst] == NULL) {

+            LOGE("startPreview:Error creating VideoEditorPlayer %d",playerInst);

+            return M4ERR_ALLOC;

+        }

+        LOGV("startPreview: object created");

+

+        mVePlayer[playerInst]->setNotifyCallback(this,(notify_callback_f)notify);

+        LOGV("startPreview: notify callback set");

+

+        mVePlayer[playerInst]->loadEffectsSettings(mEffectsSettings,

+         mNumberEffects);

+        LOGV("startPreview: effects settings loaded");

+

+        mVePlayer[playerInst]->loadAudioMixSettings(mBackgroundAudioSetting);

+        LOGV("startPreview: AudioMixSettings settings loaded");

+

+        mVePlayer[playerInst]->setAudioMixPCMFileHandle(mAudioMixPCMFileHandle);

+        LOGV("startPreview: AudioMixPCMFileHandle set");

+

+        mVePlayer[playerInst]->setProgressCallbackInterval(

+         mCallBackAfterFrameCnt);

+        LOGV("startPreview: setProgressCallBackInterval");

+    }

+

+    mPlayerState = VePlayerIdle;

+

+    if(fromMS == 0) {

+        mCurrentClipNumber = -1;

+        // Save original value

+        mFirstPreviewClipBeginTime = mClipList[0]->uiBeginCutTime;

+        mVideoStoryBoardTimeMsUptoFirstPreviewClip = 0;

+    }

+    else {

+        LOGV("startPreview: fromMS=%d", fromMS);

+        if(fromMS >= mClipTotalDuration) {

+            LOGE("startPreview: fromMS >= mClipTotalDuration");

+            return M4ERR_PARAMETER;

+        }

+        for(i=0;i<mNumberClipsInStoryBoard;i++) {

+            if(fromMS < (iIncrementedDuration + (mClipList[i]->uiEndCutTime -

+             mClipList[i]->uiBeginCutTime))) {

+                // Set to 1 index below,

+                // as threadProcess first increments the clip index

+                // and then processes clip in thread loop

+                mCurrentClipNumber = i-1;

+                LOGV("startPreview:mCurrentClipNumber = %d fromMS=%d",i,fromMS);

+

+                // Save original value

+                mFirstPreviewClipBeginTime = mClipList[i]->uiBeginCutTime;

+

+                // Set correct begin time to start playback

+                if((fromMS+mClipList[i]->uiBeginCutTime) >

+                (iIncrementedDuration+mClipList[i]->uiBeginCutTime)) {

+

+                    mClipList[i]->uiBeginCutTime =

+                     mClipList[i]->uiBeginCutTime +

+                     (fromMS - iIncrementedDuration);

+                }

+                break;

+            }

+            else {

+                iIncrementedDuration = iIncrementedDuration +

+                 (mClipList[i]->uiEndCutTime - mClipList[i]->uiBeginCutTime);

+            }

+        }

+        mVideoStoryBoardTimeMsUptoFirstPreviewClip = iIncrementedDuration;

+    }

+

+    for (int playerInst=0; playerInst<NBPLAYER_INSTANCES; playerInst++) {

+        mVePlayer[playerInst]->setAudioMixStoryBoardParam(fromMS,

+         mFirstPreviewClipBeginTime,

+         mClipList[i]->ClipProperties.uiClipAudioVolumePercentage);

+

+        LOGV("startPreview:setAudioMixStoryBoardSkimTimeStamp set %d cuttime \

+         %d", fromMS, mFirstPreviewClipBeginTime);

+    }

+

+    mStartingClipIndex = mCurrentClipNumber+1;

+

+    // Start playing with player instance 0

+    mCurrentPlayer = 0;

+

+    if(toMs == -1) {

+        LOGV("startPreview: Preview till end of storyboard");

+        mNumberClipsToPreview = mNumberClipsInStoryBoard;

+        // Save original value

+        mLastPreviewClipEndTime =

+         mClipList[mNumberClipsToPreview-1]->uiEndCutTime;

+    }

+    else {

+        LOGV("startPreview: toMs=%d", toMs);

+        if(toMs > mClipTotalDuration) {

+            LOGE("startPreview: toMs > mClipTotalDuration");

+            return M4ERR_PARAMETER;

+        }

+

+        iIncrementedDuration = 0;

+

+        for(i=0;i<mNumberClipsInStoryBoard;i++) {

+            if(toMs <= (iIncrementedDuration +

+             (mClipList[i]->uiEndCutTime - mClipList[i]->uiBeginCutTime))) {

+                // Save original value

+                mLastPreviewClipEndTime = mClipList[i]->uiEndCutTime;

+                // Set the end cut time of clip index i to toMs

+                mClipList[i]->uiEndCutTime = toMs;

+

+                // Number of clips to be previewed is from index 0 to i

+                // increment by 1 as i starts from 0

+                mNumberClipsToPreview = i+1;

+                break;

+            }

+            else {

+                iIncrementedDuration = iIncrementedDuration +

+                 (mClipList[i]->uiEndCutTime - mClipList[i]->uiBeginCutTime);

+            }

+        }

+    }

+

+    // Open the thread semaphore

+    M4OSA_semaphoreOpen(&mSemThreadWait, 1);

+

+    // Open the preview process thread

+    err = M4OSA_threadSyncOpen(&mThreadContext, (M4OSA_ThreadDoIt)threadProc);

+    if (M4NO_ERROR != err) {

+        LOGE("VideoEditorPreviewController:M4OSA_threadSyncOpen error %d", err);

+        return err;

+    }

+

+    // Set the stacksize

+    err = M4OSA_threadSyncSetOption(mThreadContext, M4OSA_ThreadStackSize,

+     (M4OSA_DataOption)PREVIEW_THREAD_STACK_SIZE);

+

+    if (M4NO_ERROR != err) {

+        LOGE("VideoEditorPreviewController: threadSyncSetOption error %d", err);

+        M4OSA_threadSyncClose(mThreadContext);

+        mThreadContext = NULL;

+        return err;

+    }

+

+     // Start the thread

+     err = M4OSA_threadSyncStart(mThreadContext, (M4OSA_Void*)this);

+     if (M4NO_ERROR != err) {

+        LOGE("VideoEditorPreviewController: threadSyncStart error %d", err);

+        M4OSA_threadSyncClose(mThreadContext);

+        mThreadContext = NULL;

+        return err;

+    }

+    bStopThreadInProgress = false;

+

+    LOGV("startPreview: process thread started");

+    return M4NO_ERROR;

+}

+

+M4OSA_ERR VideoEditorPreviewController::stopPreview() {

+    M4OSA_ERR err = M4NO_ERROR;

+    LOGV("stopPreview");

+

+    // Stop the thread

+    if(mThreadContext != NULL) {

+        bStopThreadInProgress = true;

+        err = M4OSA_semaphorePost(mSemThreadWait);

+

+        err = M4OSA_threadSyncStop(mThreadContext);

+        if(err != M4NO_ERROR) {

+            LOGV("stopPreview: error 0x%x in trying to stop thread", err);

+            // Continue even if error

+        }

+

+        err = M4OSA_threadSyncClose(mThreadContext);

+        if(err != M4NO_ERROR) {

+            LOGE("stopPreview: error 0x%x in trying to close thread", err);

+            // Continue even if error

+        }

+

+        mThreadContext = NULL;

+    }

+

+    // Close the semaphore first

+    if(mSemThreadWait != NULL) {

+        err = M4OSA_semaphoreClose(mSemThreadWait);

+        LOGV("stopPreview: close semaphore returns 0x%x", err);

+    }

+

+    for (int playerInst=0; playerInst<NBPLAYER_INSTANCES; playerInst++) {

+        if(mVePlayer[playerInst] != NULL) {

+            if(mVePlayer[playerInst]->isPlaying()) {

+                LOGV("stop the player first");

+                mVePlayer[playerInst]->stop();

+            }

+

+            LOGV("stopPreview: clearing mVePlayer");

+            mVePlayer[playerInst].clear();

+            mVePlayer[playerInst] = NULL;

+        }

+    }

+

+    // If image file playing, then free the buffer pointer

+    if(mFrameStr.pBuffer != M4OSA_NULL) {

+        M4OSA_free((M4OSA_MemAddr32)mFrameStr.pBuffer);

+        mFrameStr.pBuffer = M4OSA_NULL;

+    }

+

+    // Reset original begin cuttime of first previewed clip*/

+    mClipList[mStartingClipIndex]->uiBeginCutTime = mFirstPreviewClipBeginTime;

+    // Reset original end cuttime of last previewed clip*/

+    mClipList[mNumberClipsToPreview-1]->uiEndCutTime = mLastPreviewClipEndTime;

+

+    mPlayerState = VePlayerIdle;

+

+    mCurrentPlayedDuration = 0;

+    mCurrentClipDuration = 0;

+    mRenderingMode = M4xVSS_kBlackBorders;

+    mOutputVideoWidth = 0;

+    mOutputVideoHeight = 0;

+

+    return M4NO_ERROR;

+}

+

+M4OSA_ERR VideoEditorPreviewController::renderPreviewFrame(

+    const sp<Surface> &surface, VideoEditor_renderPreviewFrameStr* pFrameInfo) {

+

+    M4OSA_ERR err = M4NO_ERROR;

+    M4OSA_UInt32 i = 0, iIncrementedDuration = 0, tnTimeMs=0, framesize =0;

+    VideoEditor_renderPreviewFrameStr* pFrameStr = pFrameInfo;

+    M4VIFI_UInt8 *pixelArray = NULL;

+

+    Mutex::Autolock autoLock(mLock);

+

+    // Get the Isurface to be passed to renderer

+    mISurface = surface->getISurface();

+

+    // Delete previous renderer instance

+    if(mTarget != NULL) {

+        delete mTarget;

+        mTarget = NULL;

+    }

+

+    if(mOutputVideoWidth == 0) {

+        mOutputVideoWidth = pFrameStr->uiFrameWidth;

+    }

+    if(mOutputVideoHeight == 0) {

+        mOutputVideoHeight = pFrameStr->uiFrameHeight;

+    }

+

+    // Initialize the renderer

+    if(mTarget == NULL) {

+        mTarget = new PreviewRenderer(

+            OMX_COLOR_FormatYUV420Planar, surface, mOutputVideoWidth, mOutputVideoHeight,

+            mOutputVideoWidth, mOutputVideoHeight, 0);

+        if(mTarget == NULL) {

+            LOGE("renderPreviewFrame: cannot create PreviewRenderer");

+            return M4ERR_ALLOC;

+        }

+    }

+

+    pixelArray = NULL;

+

+    // Postprocessing (apply video effect)

+    if(pFrameStr->bApplyEffect == M4OSA_TRUE) {

+

+        for(i=0;i<mNumberEffects;i++) {

+            // First check if effect starttime matches the clip being previewed

+            if((mEffectsSettings[i].uiStartTime < pFrameStr->clipBeginCutTime)

+             ||(mEffectsSettings[i].uiStartTime >= pFrameStr->clipEndCutTime)) {

+                // This effect doesn't belong to this clip, check next one

+                continue;

+            }

+            if((mEffectsSettings[i].uiStartTime <= pFrameStr->timeMs) &&

+            ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=

+             pFrameStr->timeMs) && (mEffectsSettings[i].uiDuration != 0)) {

+                setVideoEffectType(mEffectsSettings[i].VideoEffectType, TRUE);

+            }

+            else {

+                setVideoEffectType(mEffectsSettings[i].VideoEffectType, FALSE);

+            }

+        }

+

+        if(mCurrentVideoEffect != VIDEO_EFFECT_NONE) {

+            err = applyVideoEffect((M4OSA_Void *)pFrameStr->pBuffer,

+             OMX_COLOR_FormatYUV420Planar, pFrameStr->uiFrameWidth,

+             pFrameStr->uiFrameHeight, pFrameStr->timeMs,

+             (M4OSA_Void *)pixelArray);

+

+            if(err != M4NO_ERROR) {

+                LOGE("renderPreviewFrame: applyVideoEffect error 0x%x", err);

+                delete mTarget;

+                mTarget = NULL;

+                M4OSA_free((M4OSA_MemAddr32)pixelArray);

+                pixelArray = NULL;

+                return err;

+           }

+           mCurrentVideoEffect = VIDEO_EFFECT_NONE;

+        }

+        else {

+            // Apply the rendering mode

+            err = doImageRenderingMode((M4OSA_Void *)pFrameStr->pBuffer,

+             OMX_COLOR_FormatYUV420Planar, pFrameStr->uiFrameWidth,

+             pFrameStr->uiFrameHeight, (M4OSA_Void *)pixelArray);

+

+            if(err != M4NO_ERROR) {

+                LOGE("renderPreviewFrame:doImageRenderingMode error 0x%x", err);

+                delete mTarget;

+                mTarget = NULL;

+                M4OSA_free((M4OSA_MemAddr32)pixelArray);

+                pixelArray = NULL;

+                return err;

+            }

+        }

+    }

+    else {

+        // Apply the rendering mode

+        err = doImageRenderingMode((M4OSA_Void *)pFrameStr->pBuffer,

+         OMX_COLOR_FormatYUV420Planar, pFrameStr->uiFrameWidth,

+         pFrameStr->uiFrameHeight, (M4OSA_Void *)pixelArray);

+

+        if(err != M4NO_ERROR) {

+            LOGE("renderPreviewFrame: doImageRenderingMode error 0x%x", err);

+            delete mTarget;

+            mTarget = NULL;

+            M4OSA_free((M4OSA_MemAddr32)pixelArray);

+            pixelArray = NULL;

+            return err;

+        }

+    }

+

+    mTarget->renderYV12();

+    return err;

+}

+

+M4OSA_Void VideoEditorPreviewController::setJniCallback(void* cookie,

+    jni_progress_callback_fct callbackFct) {

+    //LOGV("setJniCallback");

+    mJniCookie = cookie;

+    mJniCallback = callbackFct;

+}

+

+M4OSA_ERR VideoEditorPreviewController::preparePlayer(

+    void* param, int playerInstance, int index) {

+

+    M4OSA_ERR err = M4NO_ERROR;

+    VideoEditorPreviewController *pController =

+     (VideoEditorPreviewController *)param;

+

+    LOGV("preparePlayer: instance %d file %d", playerInstance, index);

+

+    pController->mVePlayer[playerInstance]->setDataSource(

+    (const char *)pController->mClipList[index]->pFile, NULL);

+    LOGV("preparePlayer: setDataSource instance %s",

+     (const char *)pController->mClipList[index]->pFile);

+

+    pController->mVePlayer[playerInstance]->setVideoISurface(

+     pController->mISurface);

+    LOGV("preparePlayer: setVideoISurface");

+

+    pController->mVePlayer[playerInstance]->setVideoSurface(

+     pController->mSurface);

+    LOGV("preparePlayer: setVideoSurface");

+

+    pController->mVePlayer[playerInstance]->setMediaRenderingMode(

+     pController->mClipList[index]->xVSS.MediaRendering,

+     pController->mOutputVideoSize);

+    LOGV("preparePlayer: setMediaRenderingMode");

+

+    if(index == pController->mStartingClipIndex) {

+        pController->mVePlayer[playerInstance]->setPlaybackBeginTime(

+        pController->mFirstPreviewClipBeginTime);

+    }

+    else {

+        pController->mVePlayer[playerInstance]->setPlaybackBeginTime(

+        pController->mClipList[index]->uiBeginCutTime);

+    }

+    LOGV("preparePlayer: setPlaybackBeginTime(%d)",

+     pController->mClipList[index]->uiBeginCutTime);

+

+    pController->mVePlayer[playerInstance]->setPlaybackEndTime(

+     pController->mClipList[index]->uiEndCutTime);

+    LOGV("preparePlayer: setPlaybackEndTime(%d)",

+     pController->mClipList[index]->uiEndCutTime);

+

+    if(pController->mClipList[index]->FileType == M4VIDEOEDITING_kFileType_ARGB8888) {

+        pController->mVePlayer[playerInstance]->setImageClipProperties(

+                 pController->mClipList[index]->ClipProperties.uiVideoWidth,

+                 pController->mClipList[index]->ClipProperties.uiVideoHeight);

+        LOGV("preparePlayer: setImageClipProperties");

+    }

+

+    pController->mVePlayer[playerInstance]->prepare();

+    LOGV("preparePlayer: prepared");

+

+    if(pController->mClipList[index]->uiBeginCutTime > 0) {

+        pController->mVePlayer[playerInstance]->seekTo(

+         pController->mClipList[index]->uiBeginCutTime);

+

+        LOGV("preparePlayer: seekTo(%d)",

+         pController->mClipList[index]->uiBeginCutTime);

+    }

+

+    pController->mVePlayer[playerInstance]->readFirstVideoFrame();

+    LOGV("preparePlayer: readFirstVideoFrame of clip");

+

+    return err;

+}

+

+M4OSA_ERR VideoEditorPreviewController::threadProc(M4OSA_Void* param) {

+    M4OSA_ERR err = M4NO_ERROR;

+    M4OSA_Int32 index = 0;

+    VideoEditorPreviewController *pController =

+     (VideoEditorPreviewController *)param;

+

+    LOGV("inside threadProc");

+    if(pController->mPlayerState == VePlayerIdle) {

+        (pController->mCurrentClipNumber)++;

+

+        LOGV("threadProc: playing file index %d total clips %d",

+         pController->mCurrentClipNumber, pController->mNumberClipsToPreview);

+

+        if(pController->mCurrentClipNumber >=

+         pController->mNumberClipsToPreview) {

+

+            LOGV("All clips previewed");

+

+            pController->mCurrentPlayedDuration = 0;

+            pController->mCurrentClipDuration = 0;

+            pController->mCurrentPlayer = 0;

+

+            if(pController->mPreviewLooping == M4OSA_TRUE) {

+                pController->mCurrentClipNumber =

+                 pController->mStartingClipIndex;

+

+                LOGV("Preview looping TRUE, restarting from clip index %d",

+                 pController->mCurrentClipNumber);

+

+                // Reset the story board timestamp inside the player

+                for (int playerInst=0; playerInst<NBPLAYER_INSTANCES;

+                 playerInst++) {

+                    pController->mVePlayer[playerInst]->resetJniCallbackTimeStamp();

+                }

+            }

+            else {

+                if(pController->mJniCallback != NULL) {

+                    pController->mJniCallback(

+                     pController->mJniCookie, MSG_TYPE_PREVIEW_END, 0);

+                }

+                pController->mPlayerState = VePlayerAutoStop;

+

+                // Reset original begin cuttime of first previewed clip

+                pController->mClipList[pController->mStartingClipIndex]->uiBeginCutTime =

+                 pController->mFirstPreviewClipBeginTime;

+                // Reset original end cuttime of last previewed clip

+                pController->mClipList[pController->mNumberClipsToPreview-1]->uiEndCutTime =

+                 pController->mLastPreviewClipEndTime;

+

+                // Return a warning to M4OSA thread handler

+                // so that thread is moved from executing state to open state

+                return M4WAR_NO_MORE_STREAM;

+            }

+        }

+

+        index=pController->mCurrentClipNumber;

+        if(pController->mCurrentClipNumber == pController->mStartingClipIndex) {

+            pController->mCurrentPlayedDuration +=

+             pController->mVideoStoryBoardTimeMsUptoFirstPreviewClip;

+

+            pController->mCurrentClipDuration =

+             pController->mClipList[pController->mCurrentClipNumber]->uiEndCutTime

+              - pController->mFirstPreviewClipBeginTime;

+

+            preparePlayer((void*)pController, pController->mCurrentPlayer, index);

+        }

+        else {

+            pController->mCurrentPlayedDuration +=

+             pController->mCurrentClipDuration;

+

+            pController->mCurrentClipDuration =

+             pController->mClipList[pController->mCurrentClipNumber]->uiEndCutTime -

+             pController->mClipList[pController->mCurrentClipNumber]->uiBeginCutTime;

+        }

+

+        pController->mVePlayer[pController->mCurrentPlayer]->setStoryboardStartTime(

+         pController->mCurrentPlayedDuration);

+        LOGV("threadProc: setStoryboardStartTime");

+

+        // Set the next clip duration for Audio mix here

+        if(pController->mCurrentClipNumber != pController->mStartingClipIndex) {

+

+            pController->mVePlayer[pController->mCurrentPlayer]->setAudioMixStoryBoardParam(

+             pController->mCurrentPlayedDuration,

+             pController->mClipList[index]->uiBeginCutTime,

+             pController->mClipList[index]->ClipProperties.uiClipAudioVolumePercentage);

+

+            LOGV("threadProc: setAudioMixStoryBoardParam fromMS %d \

+             ClipBeginTime %d", pController->mCurrentPlayedDuration +

+             pController->mClipList[index]->uiBeginCutTime,

+             pController->mClipList[index]->uiBeginCutTime,

+             pController->mClipList[index]->ClipProperties.uiClipAudioVolumePercentage);

+        }

+

+        pController->mVePlayer[pController->mCurrentPlayer]->start();

+        LOGV("threadProc: started");

+

+        pController->mPlayerState = VePlayerBusy;

+

+    }

+    else if(pController->mPlayerState == VePlayerAutoStop) {

+        LOGV("Preview completed..auto stop the player");

+    }

+    else {

+        if(!pController->bStopThreadInProgress) {

+            LOGV("threadProc: state busy...wait for sem");

+            err = M4OSA_semaphoreWait(pController->mSemThreadWait,

+             M4OSA_WAIT_FOREVER);

+        }

+        LOGV("threadProc: sem wait returned err = 0x%x", err);

+    }

+

+    //Always return M4NO_ERROR to ensure the thread keeps running

+    return M4NO_ERROR;

+}

+

+void VideoEditorPreviewController::notify(

+    void* cookie, int msg, int ext1, int ext2)

+{

+    VideoEditorPreviewController *pController =

+     (VideoEditorPreviewController *)cookie;

+

+    M4OSA_ERR err = M4NO_ERROR;

+    uint32_t clipDuration = 0;

+    switch (msg) {

+        case MEDIA_NOP: // interface test message

+            LOGV("MEDIA_NOP");

+            break;

+        case MEDIA_PREPARED:

+            LOGV("MEDIA_PREPARED");

+            break;

+        case MEDIA_PLAYBACK_COMPLETE:

+            LOGV("notify:MEDIA_PLAYBACK_COMPLETE");

+            pController->mPlayerState = VePlayerIdle;

+

+            //send progress callback with last frame timestamp

+            if(pController->mCurrentClipNumber ==

+             pController->mStartingClipIndex) {

+                clipDuration =

+                 pController->mClipList[pController->mCurrentClipNumber]->uiEndCutTime

+                  - pController->mFirstPreviewClipBeginTime;

+            }

+            else {

+                clipDuration =

+                 pController->mClipList[pController->mCurrentClipNumber]->uiEndCutTime

+                  - pController->mClipList[pController->mCurrentClipNumber]->uiBeginCutTime;

+            }

+            pController->mJniCallback(

+             pController->mJniCookie, MSG_TYPE_PROGRESS_INDICATION,

+             (clipDuration+pController->mCurrentPlayedDuration));

+

+            M4OSA_semaphorePost(pController->mSemThreadWait);

+            break;

+         case MEDIA_ERROR:

+          // Always log errors.

+          // ext1: Media framework error code.

+          // ext2: Implementation dependant error code.

+            LOGE("MEDIA_ERROR; error (%d, %d)", ext1, ext2);

+            if(pController->mJniCallback != NULL) {

+                pController->mJniCallback(pController->mJniCookie,

+                 MSG_TYPE_PLAYER_ERROR, ext1);

+            }

+            break;

+        case MEDIA_INFO:

+            // ext1: Media framework error code.

+            // ext2: Implementation dependant error code.

+            //LOGW("MEDIA_INFO; info/warning (%d, %d)", ext1, ext2);

+            if(pController->mJniCallback != NULL) {

+                pController->mJniCallback(pController->mJniCookie,

+                 MSG_TYPE_PROGRESS_INDICATION, ext2);

+            }

+            break;

+        case MEDIA_SEEK_COMPLETE:

+            LOGV("MEDIA_SEEK_COMPLETE; Received seek complete");

+            break;

+        case MEDIA_BUFFERING_UPDATE:

+            LOGV("MEDIA_BUFFERING_UPDATE; buffering %d", ext1);

+            break;

+        case MEDIA_SET_VIDEO_SIZE:

+            LOGV("MEDIA_SET_VIDEO_SIZE; New video size %d x %d", ext1, ext2);

+            break;

+        case 0xAAAAAAAA:

+            LOGV("VIDEO PLAYBACK ALMOST over, prepare next player");

+

+            // Select next player and prepare it

+            // If there is a clip after this one

+            if ((pController->mCurrentClipNumber+1) <

+             pController->mNumberClipsToPreview) {

+

+                pController->mCurrentPlayer++;

+                if (pController->mCurrentPlayer >= NBPLAYER_INSTANCES) {

+                    pController->mCurrentPlayer = 0;

+                }

+                // Prepare the first clip to be played

+                preparePlayer((void*)pController, pController->mCurrentPlayer,

+                    pController->mCurrentClipNumber+1);

+            }

+            break;

+        default:

+            LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);

+            break;

+    }

+}

+

+void VideoEditorPreviewController::setVideoEffectType(

+    M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {

+

+    M4OSA_UInt32 effect = VIDEO_EFFECT_NONE;

+

+    // map M4VSS3GPP_VideoEffectType to local enum

+    switch(type) {

+        case M4VSS3GPP_kVideoEffectType_FadeFromBlack:

+            effect = VIDEO_EFFECT_FADEFROMBLACK;

+            break;

+

+        case M4VSS3GPP_kVideoEffectType_FadeToBlack:

+            effect = VIDEO_EFFECT_FADETOBLACK;

+            break;

+

+        case M4VSS3GPP_kVideoEffectType_CurtainOpening:

+            effect = VIDEO_EFFECT_CURTAINOPEN;

+            break;

+

+        case M4VSS3GPP_kVideoEffectType_CurtainClosing:

+            effect = VIDEO_EFFECT_CURTAINCLOSE;

+            break;

+

+        case M4xVSS_kVideoEffectType_BlackAndWhite:

+            effect = VIDEO_EFFECT_BLACKANDWHITE;

+            break;

+

+        case M4xVSS_kVideoEffectType_Pink:

+            effect = VIDEO_EFFECT_PINK;

+            break;

+

+        case M4xVSS_kVideoEffectType_Green:

+            effect = VIDEO_EFFECT_GREEN;

+            break;

+

+        case M4xVSS_kVideoEffectType_Sepia:

+            effect = VIDEO_EFFECT_SEPIA;

+            break;

+

+        case M4xVSS_kVideoEffectType_Negative:

+            effect = VIDEO_EFFECT_NEGATIVE;

+            break;

+

+        case M4xVSS_kVideoEffectType_Framing:

+            effect = VIDEO_EFFECT_FRAMING;

+            break;

+

+        case M4xVSS_kVideoEffectType_Fifties:

+            effect = VIDEO_EFFECT_FIFTIES;

+            break;

+

+        case M4xVSS_kVideoEffectType_ColorRGB16:

+            effect = VIDEO_EFFECT_COLOR_RGB16;

+            break;

+

+        case M4xVSS_kVideoEffectType_Gradient:

+            effect = VIDEO_EFFECT_GRADIENT;

+            break;

+

+        default:

+            effect = VIDEO_EFFECT_NONE;

+            break;

+    }

+

+    if(enable == M4OSA_TRUE) {

+        // If already set, then no need to set again

+        if(!(mCurrentVideoEffect & effect))

+            mCurrentVideoEffect |= effect;

+            if(effect == VIDEO_EFFECT_FIFTIES) {

+                mIsFiftiesEffectStarted = true;

+            }

+    }

+    else  {

+        // Reset only if already set

+        if(mCurrentVideoEffect & effect)

+            mCurrentVideoEffect &= ~effect;

+    }

+

+    return;

+}

+

+

+M4OSA_ERR VideoEditorPreviewController::applyVideoEffect(

+    M4OSA_Void * dataPtr, M4OSA_UInt32 colorFormat, M4OSA_UInt32 videoWidth,

+    M4OSA_UInt32 videoHeight, M4OSA_UInt32 timeMs, M4OSA_Void* outPtr) {

+

+    M4OSA_ERR err = M4NO_ERROR;

+    vePostProcessParams postProcessParams;

+

+    postProcessParams.vidBuffer = (M4VIFI_UInt8*)dataPtr;

+    postProcessParams.videoWidth = videoWidth;

+    postProcessParams.videoHeight = videoHeight;

+    postProcessParams.timeMs = timeMs;

+    postProcessParams.timeOffset = 0; //Since timeMS already takes care of offset in this case

+    postProcessParams.effectsSettings = mEffectsSettings;

+    postProcessParams.numberEffects = mNumberEffects;

+    postProcessParams.outVideoWidth = mOutputVideoWidth;

+    postProcessParams.outVideoHeight = mOutputVideoHeight;

+    postProcessParams.currentVideoEffect = mCurrentVideoEffect;

+    postProcessParams.renderingMode = mRenderingMode;

+    if(mIsFiftiesEffectStarted == M4OSA_TRUE) {

+        postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;

+        mIsFiftiesEffectStarted = M4OSA_FALSE;

+    }

+    else {

+       postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;

+    }

+    //postProcessParams.renderer = mTarget;

+    postProcessParams.overlayFrameRGBBuffer = NULL;

+    postProcessParams.overlayFrameYUVBuffer = NULL;

+

+    mTarget->getBufferYV12(&(postProcessParams.pOutBuffer), &(postProcessParams.outBufferStride));

+

+    err = applyEffectsAndRenderingMode(&postProcessParams);

+    return err;

+}

+

+M4OSA_ERR VideoEditorPreviewController::setPreviewFrameRenderingMode(

+    M4xVSS_MediaRendering mode, M4VIDEOEDITING_VideoFrameSize outputVideoSize) {

+

+    //LOGV("setMediaRenderingMode: outputVideoSize = %d", outputVideoSize);

+    mRenderingMode = mode;

+

+    switch(outputVideoSize) {

+        case M4VIDEOEDITING_kSQCIF:

+            mOutputVideoWidth = 128;

+            mOutputVideoHeight = 96;

+            break;

+

+        case M4VIDEOEDITING_kQQVGA:

+            mOutputVideoWidth = 160;

+            mOutputVideoHeight = 120;

+            break;

+

+        case M4VIDEOEDITING_kQCIF:

+            mOutputVideoWidth = 176;

+            mOutputVideoHeight = 144;

+            break;

+

+        case M4VIDEOEDITING_kQVGA:

+            mOutputVideoWidth = 320;

+            mOutputVideoHeight = 240;

+            break;

+

+        case M4VIDEOEDITING_kCIF:

+            mOutputVideoWidth = 352;

+            mOutputVideoHeight = 288;

+            break;

+

+        case M4VIDEOEDITING_kVGA:

+            mOutputVideoWidth = 640;

+            mOutputVideoHeight = 480;

+            break;

+

+        case M4VIDEOEDITING_kWVGA:

+            mOutputVideoWidth = 800;

+            mOutputVideoHeight = 480;

+            break;

+

+        case M4VIDEOEDITING_kNTSC:

+            mOutputVideoWidth = 720;

+            mOutputVideoHeight = 480;

+            break;

+

+        case M4VIDEOEDITING_k640_360:

+            mOutputVideoWidth = 640;

+            mOutputVideoHeight = 360;

+            break;

+

+        case M4VIDEOEDITING_k854_480:

+            mOutputVideoWidth = 854;

+            mOutputVideoHeight = 480;

+            break;

+

+        case M4VIDEOEDITING_kHD1280:

+            mOutputVideoWidth = 1280;

+            mOutputVideoHeight = 720;

+            break;

+

+        case M4VIDEOEDITING_kHD1080:

+            mOutputVideoWidth = 1080;

+            mOutputVideoHeight = 720;

+            break;

+

+        case M4VIDEOEDITING_kHD960:

+            mOutputVideoWidth = 960;

+            mOutputVideoHeight = 720;

+            break;

+

+        default:

+            mOutputVideoWidth = 0;

+            mOutputVideoHeight = 0;

+            break;

+    }

+

+    return OK;

+}

+

+M4OSA_ERR VideoEditorPreviewController::doImageRenderingMode(

+    M4OSA_Void * dataPtr, M4OSA_UInt32 colorFormat, M4OSA_UInt32 videoWidth,

+    M4OSA_UInt32 videoHeight, M4OSA_Void* outPtr) {

+

+    M4OSA_ERR err = M4NO_ERROR;

+    M4VIFI_ImagePlane planeIn[3], planeOut[3];

+    M4VIFI_UInt8 *inBuffer = M4OSA_NULL;

+    M4OSA_UInt32 outputBufferWidth =0, outputBufferHeight=0;

+

+    //frameSize = (videoWidth*videoHeight*3) >> 1;

+    inBuffer = (M4OSA_UInt8 *)dataPtr;

+

+    // In plane

+    prepareYUV420ImagePlane(planeIn, videoWidth,

+      videoHeight, (M4VIFI_UInt8 *)inBuffer);

+

+    outputBufferWidth = mOutputVideoWidth;

+    outputBufferHeight = mOutputVideoHeight;

+

+    // Out plane

+    uint8_t* outBuffer;

+    size_t outBufferStride = 0;

+

+    LOGV("doMediaRendering CALL getBuffer()");

+    mTarget->getBufferYV12(&outBuffer, &outBufferStride);

+

+    // Set the output YUV420 plane to be compatible with YV12 format

+    //In YV12 format, sizes must be even

+    M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;

+    M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;

+

+    prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,

+     (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);

+

+    err = applyRenderingMode(planeIn, planeOut, mRenderingMode);

+    if(err != M4NO_ERROR) {

+        LOGE("doImageRenderingMode: applyRenderingMode returned err=0x%x", err);

+    }

+    return err;

+}

+

+} //namespace android