Home | History | Annotate | Download | only in lvpp
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_NDEBUG 1
     18 #define LOG_TAG "VideoEditorPreviewController"
     19 #include "VideoEditorPreviewController.h"
     20 
     21 namespace android {
     22 
     23 #define PREVIEW_THREAD_STACK_SIZE                           (65536)
     24 
     25 VideoEditorPreviewController::VideoEditorPreviewController()
     26     : mCurrentPlayer(0),
     27       mThreadContext(NULL),
     28       mPlayerState(VePlayerIdle),
     29       mPrepareReqest(M4OSA_FALSE),
     30       mClipList(NULL),
     31       mNumberClipsInStoryBoard(0),
     32       mNumberClipsToPreview(0),
     33       mStartingClipIndex(0),
     34       mPreviewLooping(M4OSA_FALSE),
     35       mCallBackAfterFrameCnt(0),
     36       mEffectsSettings(NULL),
     37       mNumberEffects(0),
     38       mCurrentClipNumber(-1),
     39       mClipTotalDuration(0),
     40       mCurrentVideoEffect(VIDEO_EFFECT_NONE),
     41       mBackgroundAudioSetting(NULL),
     42       mAudioMixPCMFileHandle(NULL),
     43       mTarget(NULL),
     44       mJniCookie(NULL),
     45       mJniCallback(NULL),
     46       mCurrentPlayedDuration(0),
     47       mCurrentClipDuration(0),
     48       mVideoStoryBoardTimeMsUptoFirstPreviewClip(0),
     49       mOverlayState(OVERLAY_CLEAR),
     50       mActivePlayerIndex(0),
     51       mOutputVideoWidth(0),
     52       mOutputVideoHeight(0),
     53       bStopThreadInProgress(false),
     54       mSemThreadWait(NULL) {
     55     LOGV("VideoEditorPreviewController");
     56     mRenderingMode = M4xVSS_kBlackBorders;
     57     mIsFiftiesEffectStarted = false;
     58 
     59     for (int i=0; i<NBPLAYER_INSTANCES; i++) {
     60         mVePlayer[i] = NULL;
     61     }
     62 }
     63 
     64 VideoEditorPreviewController::~VideoEditorPreviewController() {
     65     M4OSA_UInt32 i = 0;
     66     M4OSA_ERR err = M4NO_ERROR;
     67     LOGV("~VideoEditorPreviewController");
     68 
     69     // Stop the thread if its still running
     70     if(mThreadContext != NULL) {
     71         err = M4OSA_threadSyncStop(mThreadContext);
     72         if(err != M4NO_ERROR) {
     73             LOGV("~VideoEditorPreviewController: error 0x%x \
     74             in trying to stop thread", err);
     75             // Continue even if error
     76         }
     77 
     78         err = M4OSA_threadSyncClose(mThreadContext);
     79         if(err != M4NO_ERROR) {
     80             LOGE("~VideoEditorPreviewController: error 0x%x \
     81             in trying to close thread", (unsigned int) err);
     82             // Continue even if error
     83         }
     84 
     85         mThreadContext = NULL;
     86     }
     87 
     88     for (int playerInst=0; playerInst<NBPLAYER_INSTANCES;
     89          playerInst++) {
     90         if(mVePlayer[playerInst] != NULL) {
     91             LOGV("clearing mVePlayer %d", playerInst);
     92             mVePlayer[playerInst].clear();
     93         }
     94     }
     95 
     96     if(mClipList != NULL) {
     97         // Clean up
     98         for(i=0;i<mNumberClipsInStoryBoard;i++)
     99         {
    100             if(mClipList[i]->pFile != NULL) {
    101                 free(mClipList[i]->pFile);
    102                 mClipList[i]->pFile = NULL;
    103             }
    104 
    105             free(mClipList[i]);
    106         }
    107         free(mClipList);
    108         mClipList = NULL;
    109     }
    110 
    111     if(mEffectsSettings) {
    112         for(i=0;i<mNumberEffects;i++) {
    113             if(mEffectsSettings[i].xVSS.pFramingBuffer != NULL) {
    114                 free(mEffectsSettings[i].xVSS.pFramingBuffer->pac_data);
    115 
    116                 free(mEffectsSettings[i].xVSS.pFramingBuffer);
    117 
    118                 mEffectsSettings[i].xVSS.pFramingBuffer = NULL;
    119             }
    120         }
    121         free(mEffectsSettings);
    122         mEffectsSettings = NULL;
    123     }
    124 
    125     if (mAudioMixPCMFileHandle) {
    126         err = M4OSA_fileReadClose (mAudioMixPCMFileHandle);
    127         mAudioMixPCMFileHandle = M4OSA_NULL;
    128     }
    129 
    130     if (mBackgroundAudioSetting != NULL) {
    131         free(mBackgroundAudioSetting);
    132         mBackgroundAudioSetting = NULL;
    133     }
    134 
    135     if(mTarget != NULL) {
    136         delete mTarget;
    137         mTarget = NULL;
    138     }
    139 
    140     mOverlayState = OVERLAY_CLEAR;
    141 
    142     LOGV("~VideoEditorPreviewController returns");
    143 }
    144 
    145 M4OSA_ERR VideoEditorPreviewController::loadEditSettings(
    146     M4VSS3GPP_EditSettings* pSettings,M4xVSS_AudioMixingSettings* bgmSettings) {
    147 
    148     M4OSA_UInt32 i = 0, iClipDuration = 0, rgbSize = 0;
    149     M4VIFI_UInt8 *tmp = NULL;
    150     M4OSA_ERR err = M4NO_ERROR;
    151 
    152     LOGV("loadEditSettings");
    153     LOGV("loadEditSettings Channels = %d, sampling Freq %d",
    154           bgmSettings->uiNbChannels, bgmSettings->uiSamplingFrequency  );
    155           bgmSettings->uiSamplingFrequency = 32000;
    156 
    157     LOGV("loadEditSettings Channels = %d, sampling Freq %d",
    158           bgmSettings->uiNbChannels, bgmSettings->uiSamplingFrequency  );
    159     Mutex::Autolock autoLock(mLock);
    160 
    161     // Clean up any previous Edit settings before loading new ones
    162     mCurrentVideoEffect = VIDEO_EFFECT_NONE;
    163 
    164     if(mAudioMixPCMFileHandle) {
    165         err = M4OSA_fileReadClose (mAudioMixPCMFileHandle);
    166         mAudioMixPCMFileHandle = M4OSA_NULL;
    167     }
    168 
    169     if(mBackgroundAudioSetting != NULL) {
    170         free(mBackgroundAudioSetting);
    171         mBackgroundAudioSetting = NULL;
    172     }
    173 
    174     if(mClipList != NULL) {
    175         // Clean up
    176         for(i=0;i<mNumberClipsInStoryBoard;i++)
    177         {
    178             if(mClipList[i]->pFile != NULL) {
    179                 free(mClipList[i]->pFile);
    180                 mClipList[i]->pFile = NULL;
    181             }
    182 
    183             free(mClipList[i]);
    184         }
    185         free(mClipList);
    186         mClipList = NULL;
    187     }
    188 
    189     if(mEffectsSettings) {
    190         for(i=0;i<mNumberEffects;i++) {
    191             if(mEffectsSettings[i].xVSS.pFramingBuffer != NULL) {
    192                 free(mEffectsSettings[i].xVSS.pFramingBuffer->pac_data);
    193 
    194                 free(mEffectsSettings[i].xVSS.pFramingBuffer);
    195 
    196                 mEffectsSettings[i].xVSS.pFramingBuffer = NULL;
    197             }
    198         }
    199         free(mEffectsSettings);
    200         mEffectsSettings = NULL;
    201     }
    202 
    203     if(mClipList == NULL) {
    204         mNumberClipsInStoryBoard = pSettings->uiClipNumber;
    205         LOGV("loadEditSettings: # of Clips = %d", mNumberClipsInStoryBoard);
    206 
    207         mClipList = (M4VSS3GPP_ClipSettings**)M4OSA_32bitAlignedMalloc(
    208          sizeof(M4VSS3GPP_ClipSettings*)*pSettings->uiClipNumber, M4VS,
    209          (M4OSA_Char*)"LvPP, copy of pClipList");
    210 
    211         if(NULL == mClipList) {
    212             LOGE("loadEditSettings: Malloc error");
    213             return M4ERR_ALLOC;
    214         }
    215         memset((void *)mClipList,0,
    216          sizeof(M4VSS3GPP_ClipSettings*)*pSettings->uiClipNumber);
    217 
    218         for(i=0;i<pSettings->uiClipNumber;i++) {
    219 
    220             // Allocate current clip
    221             mClipList[i] =
    222              (M4VSS3GPP_ClipSettings*)M4OSA_32bitAlignedMalloc(
    223               sizeof(M4VSS3GPP_ClipSettings),M4VS,(M4OSA_Char*)"clip settings");
    224 
    225             if(mClipList[i] == NULL) {
    226 
    227                 LOGE("loadEditSettings: Allocation error for mClipList[%d]", (int)i);
    228                 return M4ERR_ALLOC;
    229             }
    230             // Copy plain structure
    231             memcpy((void *)mClipList[i],
    232              (void *)pSettings->pClipList[i],
    233              sizeof(M4VSS3GPP_ClipSettings));
    234 
    235             if(NULL != pSettings->pClipList[i]->pFile) {
    236                 mClipList[i]->pFile = (M4OSA_Char*)M4OSA_32bitAlignedMalloc(
    237                 pSettings->pClipList[i]->filePathSize, M4VS,
    238                 (M4OSA_Char*)"pClipSettingsDest->pFile");
    239 
    240                 if(NULL == mClipList[i]->pFile)
    241                 {
    242                     LOGE("loadEditSettings : ERROR allocating filename");
    243                     return M4ERR_ALLOC;
    244                 }
    245 
    246                 memcpy((void *)mClipList[i]->pFile,
    247                  (void *)pSettings->pClipList[i]->pFile,
    248                  pSettings->pClipList[i]->filePathSize);
    249             }
    250             else {
    251                 LOGE("NULL file path");
    252                 return M4ERR_PARAMETER;
    253             }
    254 
    255             // Calculate total duration of all clips
    256             iClipDuration = pSettings->pClipList[i]->uiEndCutTime -
    257              pSettings->pClipList[i]->uiBeginCutTime;
    258 
    259             mClipTotalDuration = mClipTotalDuration+iClipDuration;
    260         }
    261     }
    262 
    263     if(mEffectsSettings == NULL) {
    264         mNumberEffects = pSettings->nbEffects;
    265         LOGV("loadEditSettings: mNumberEffects = %d", mNumberEffects);
    266 
    267         if(mNumberEffects != 0) {
    268             mEffectsSettings = (M4VSS3GPP_EffectSettings*)M4OSA_32bitAlignedMalloc(
    269              mNumberEffects*sizeof(M4VSS3GPP_EffectSettings),
    270              M4VS, (M4OSA_Char*)"effects settings");
    271 
    272             if(mEffectsSettings == NULL) {
    273                 LOGE("loadEffectsSettings: Allocation error");
    274                 return M4ERR_ALLOC;
    275             }
    276 
    277             memset((void *)mEffectsSettings,0,
    278              mNumberEffects*sizeof(M4VSS3GPP_EffectSettings));
    279 
    280             for(i=0;i<mNumberEffects;i++) {
    281 
    282                 mEffectsSettings[i].xVSS.pFramingFilePath = NULL;
    283                 mEffectsSettings[i].xVSS.pFramingBuffer = NULL;
    284                 mEffectsSettings[i].xVSS.pTextBuffer = NULL;
    285 
    286                 memcpy((void *)&(mEffectsSettings[i]),
    287                  (void *)&(pSettings->Effects[i]),
    288                  sizeof(M4VSS3GPP_EffectSettings));
    289 
    290                 if(pSettings->Effects[i].VideoEffectType ==
    291                  (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
    292                     // Allocate the pFraming RGB buffer
    293                     mEffectsSettings[i].xVSS.pFramingBuffer =
    294                     (M4VIFI_ImagePlane *)M4OSA_32bitAlignedMalloc(sizeof(M4VIFI_ImagePlane),
    295                      M4VS, (M4OSA_Char*)"lvpp framing buffer");
    296 
    297                     if(mEffectsSettings[i].xVSS.pFramingBuffer == NULL) {
    298                         LOGE("loadEffectsSettings:Alloc error for pFramingBuf");
    299                         free(mEffectsSettings);
    300                         mEffectsSettings = NULL;
    301                         return M4ERR_ALLOC;
    302                     }
    303 
    304                     // Allocate the pac_data (RGB)
    305                     if(pSettings->Effects[i].xVSS.rgbType == M4VSS3GPP_kRGB565){
    306                         rgbSize =
    307                          pSettings->Effects[i].xVSS.pFramingBuffer->u_width *
    308                          pSettings->Effects[i].xVSS.pFramingBuffer->u_height*2;
    309                     }
    310                     else if(
    311                      pSettings->Effects[i].xVSS.rgbType == M4VSS3GPP_kRGB888) {
    312                         rgbSize =
    313                          pSettings->Effects[i].xVSS.pFramingBuffer->u_width *
    314                          pSettings->Effects[i].xVSS.pFramingBuffer->u_height*3;
    315                     }
    316                     else {
    317                         LOGE("loadEffectsSettings: wrong RGB type");
    318                         free(mEffectsSettings);
    319                         mEffectsSettings = NULL;
    320                         return M4ERR_PARAMETER;
    321                     }
    322 
    323                     tmp = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(rgbSize, M4VS,
    324                      (M4OSA_Char*)"framing buffer pac_data");
    325 
    326                     if(tmp == NULL) {
    327                         LOGE("loadEffectsSettings:Alloc error pFramingBuf pac");
    328                         free(mEffectsSettings);
    329                         mEffectsSettings = NULL;
    330                         free(mEffectsSettings[i].xVSS.pFramingBuffer);
    331 
    332                         mEffectsSettings[i].xVSS.pFramingBuffer = NULL;
    333                         return M4ERR_ALLOC;
    334                     }
    335                     /* Initialize the pFramingBuffer*/
    336                     mEffectsSettings[i].xVSS.pFramingBuffer->pac_data = tmp;
    337                     mEffectsSettings[i].xVSS.pFramingBuffer->u_height =
    338                      pSettings->Effects[i].xVSS.pFramingBuffer->u_height;
    339 
    340                     mEffectsSettings[i].xVSS.pFramingBuffer->u_width =
    341                      pSettings->Effects[i].xVSS.pFramingBuffer->u_width;
    342 
    343                     mEffectsSettings[i].xVSS.pFramingBuffer->u_stride =
    344                      pSettings->Effects[i].xVSS.pFramingBuffer->u_stride;
    345 
    346                     mEffectsSettings[i].xVSS.pFramingBuffer->u_topleft =
    347                      pSettings->Effects[i].xVSS.pFramingBuffer->u_topleft;
    348 
    349                     mEffectsSettings[i].xVSS.uialphaBlendingStart =
    350                      pSettings->Effects[i].xVSS.uialphaBlendingStart;
    351 
    352                     mEffectsSettings[i].xVSS.uialphaBlendingMiddle =
    353                      pSettings->Effects[i].xVSS.uialphaBlendingMiddle;
    354 
    355                     mEffectsSettings[i].xVSS.uialphaBlendingEnd =
    356                      pSettings->Effects[i].xVSS.uialphaBlendingEnd;
    357 
    358                     mEffectsSettings[i].xVSS.uialphaBlendingFadeInTime =
    359                      pSettings->Effects[i].xVSS.uialphaBlendingFadeInTime;
    360                     mEffectsSettings[i].xVSS.uialphaBlendingFadeOutTime =
    361                      pSettings->Effects[i].xVSS.uialphaBlendingFadeOutTime;
    362 
    363                     // Copy the pFraming data
    364                     memcpy((void *)
    365                     mEffectsSettings[i].xVSS.pFramingBuffer->pac_data,
    366                     (void *)pSettings->Effects[i].xVSS.pFramingBuffer->pac_data,
    367                     rgbSize);
    368 
    369                     mEffectsSettings[i].xVSS.rgbType =
    370                      pSettings->Effects[i].xVSS.rgbType;
    371                 }
    372             }
    373         }
    374     }
    375 
    376     if (mBackgroundAudioSetting == NULL) {
    377 
    378         mBackgroundAudioSetting = (M4xVSS_AudioMixingSettings*)M4OSA_32bitAlignedMalloc(
    379         sizeof(M4xVSS_AudioMixingSettings), M4VS,
    380         (M4OSA_Char*)"LvPP, copy of bgmSettings");
    381 
    382         if(NULL == mBackgroundAudioSetting) {
    383             LOGE("loadEditSettings: mBackgroundAudioSetting Malloc failed");
    384             return M4ERR_ALLOC;
    385         }
    386 
    387         memset((void *)mBackgroundAudioSetting, 0,sizeof(M4xVSS_AudioMixingSettings*));
    388         memcpy((void *)mBackgroundAudioSetting, (void *)bgmSettings, sizeof(M4xVSS_AudioMixingSettings));
    389 
    390         if ( mBackgroundAudioSetting->pFile != M4OSA_NULL ) {
    391 
    392             mBackgroundAudioSetting->pFile = (M4OSA_Void*) bgmSettings->pPCMFilePath;
    393             mBackgroundAudioSetting->uiNbChannels = 2;
    394             mBackgroundAudioSetting->uiSamplingFrequency = 32000;
    395         }
    396 
    397         // Open the BG file
    398         if ( mBackgroundAudioSetting->pFile != M4OSA_NULL ) {
    399             err = M4OSA_fileReadOpen(&mAudioMixPCMFileHandle,
    400              mBackgroundAudioSetting->pFile, M4OSA_kFileRead);
    401 
    402             if (err != M4NO_ERROR) {
    403                 LOGE("loadEditSettings: mBackgroundAudio PCM File open failed");
    404                 return M4ERR_PARAMETER;
    405             }
    406         }
    407     }
    408 
    409     mOutputVideoSize = pSettings->xVSS.outputVideoSize;
    410     mFrameStr.pBuffer = M4OSA_NULL;
    411     return M4NO_ERROR;
    412 }
    413 
    414 M4OSA_ERR VideoEditorPreviewController::setSurface(const sp<Surface> &surface) {
    415     LOGV("setSurface");
    416     Mutex::Autolock autoLock(mLock);
    417 
    418     mSurface = surface;
    419     return M4NO_ERROR;
    420 }
    421 
    422 M4OSA_ERR VideoEditorPreviewController::startPreview(
    423     M4OSA_UInt32 fromMS, M4OSA_Int32 toMs, M4OSA_UInt16 callBackAfterFrameCount,
    424     M4OSA_Bool loop) {
    425 
    426     M4OSA_ERR err = M4NO_ERROR;
    427     M4OSA_UInt32 i = 0, iIncrementedDuration = 0;
    428     LOGV("startPreview");
    429 
    430     if(fromMS > (M4OSA_UInt32)toMs) {
    431         LOGE("startPreview: fromMS > toMs");
    432         return M4ERR_PARAMETER;
    433     }
    434 
    435     if(toMs == 0) {
    436         LOGE("startPreview: toMs is 0");
    437         return M4ERR_PARAMETER;
    438     }
    439 
    440     // If already started, then stop preview first
    441     for(int playerInst=0; playerInst<NBPLAYER_INSTANCES; playerInst++) {
    442         if(mVePlayer[playerInst] != NULL) {
    443             LOGV("startPreview: stopping previously started preview playback");
    444             stopPreview();
    445             break;
    446         }
    447     }
    448 
    449     // If renderPreview was called previously, then delete Renderer object first
    450     if(mTarget != NULL) {
    451         LOGV("startPreview: delete previous PreviewRenderer");
    452         delete mTarget;
    453         mTarget = NULL;
    454     }
    455 
    456     // Create Audio player to be used for entire
    457     // storyboard duration
    458     mVEAudioSink = new VideoEditorPlayer::VeAudioOutput();
    459     mVEAudioPlayer = new VideoEditorAudioPlayer(mVEAudioSink);
    460     mVEAudioPlayer->setAudioMixSettings(mBackgroundAudioSetting);
    461     mVEAudioPlayer->setAudioMixPCMFileHandle(mAudioMixPCMFileHandle);
    462 
    463     // Create Video Renderer to be used for the entire storyboard duration.
    464     uint32_t width, height;
    465     getVideoSizeByResolution(mOutputVideoSize, &width, &height);
    466     mNativeWindowRenderer = new NativeWindowRenderer(mSurface, width, height);
    467 
    468     LOGV("startPreview: loop = %d", loop);
    469     mPreviewLooping = loop;
    470 
    471     LOGV("startPreview: callBackAfterFrameCount = %d", callBackAfterFrameCount);
    472     mCallBackAfterFrameCnt = callBackAfterFrameCount;
    473 
    474     for (int playerInst=0; playerInst<NBPLAYER_INSTANCES; playerInst++) {
    475         mVePlayer[playerInst] = new VideoEditorPlayer(mNativeWindowRenderer);
    476         if(mVePlayer[playerInst] == NULL) {
    477             LOGE("startPreview:Error creating VideoEditorPlayer %d",playerInst);
    478             return M4ERR_ALLOC;
    479         }
    480         LOGV("startPreview: object created");
    481 
    482         mVePlayer[playerInst]->setNotifyCallback(this,(notify_callback_f)notify);
    483         LOGV("startPreview: notify callback set");
    484 
    485         mVePlayer[playerInst]->loadEffectsSettings(mEffectsSettings,
    486          mNumberEffects);
    487         LOGV("startPreview: effects settings loaded");
    488 
    489         mVePlayer[playerInst]->loadAudioMixSettings(mBackgroundAudioSetting);
    490         LOGV("startPreview: AudioMixSettings settings loaded");
    491 
    492         mVePlayer[playerInst]->setAudioMixPCMFileHandle(mAudioMixPCMFileHandle);
    493         LOGV("startPreview: AudioMixPCMFileHandle set");
    494 
    495         mVePlayer[playerInst]->setProgressCallbackInterval(
    496          mCallBackAfterFrameCnt);
    497         LOGV("startPreview: setProgressCallBackInterval");
    498     }
    499 
    500     mPlayerState = VePlayerIdle;
    501     mPrepareReqest = M4OSA_FALSE;
    502 
    503     if(fromMS == 0) {
    504         mCurrentClipNumber = -1;
    505         // Save original value
    506         mFirstPreviewClipBeginTime = mClipList[0]->uiBeginCutTime;
    507         mVideoStoryBoardTimeMsUptoFirstPreviewClip = 0;
    508     }
    509     else {
    510         LOGV("startPreview: fromMS=%d", fromMS);
    511         if(fromMS >= mClipTotalDuration) {
    512             LOGE("startPreview: fromMS >= mClipTotalDuration");
    513             return M4ERR_PARAMETER;
    514         }
    515         for(i=0;i<mNumberClipsInStoryBoard;i++) {
    516             if(fromMS < (iIncrementedDuration + (mClipList[i]->uiEndCutTime -
    517              mClipList[i]->uiBeginCutTime))) {
    518                 // Set to 1 index below,
    519                 // as threadProcess first increments the clip index
    520                 // and then processes clip in thread loop
    521                 mCurrentClipNumber = i-1;
    522                 LOGD("startPreview:mCurrentClipNumber = %d fromMS=%d",i,fromMS);
    523 
    524                 // Save original value
    525                 mFirstPreviewClipBeginTime = mClipList[i]->uiBeginCutTime;
    526 
    527                 // Set correct begin time to start playback
    528                 if((fromMS+mClipList[i]->uiBeginCutTime) >
    529                 (iIncrementedDuration+mClipList[i]->uiBeginCutTime)) {
    530 
    531                     mClipList[i]->uiBeginCutTime =
    532                      mClipList[i]->uiBeginCutTime +
    533                      (fromMS - iIncrementedDuration);
    534                 }
    535                 break;
    536             }
    537             else {
    538                 iIncrementedDuration = iIncrementedDuration +
    539                  (mClipList[i]->uiEndCutTime - mClipList[i]->uiBeginCutTime);
    540             }
    541         }
    542         mVideoStoryBoardTimeMsUptoFirstPreviewClip = iIncrementedDuration;
    543     }
    544 
    545     for (int playerInst=0; playerInst<NBPLAYER_INSTANCES; playerInst++) {
    546         mVePlayer[playerInst]->setAudioMixStoryBoardParam(fromMS,
    547          mFirstPreviewClipBeginTime,
    548          mClipList[i]->ClipProperties.uiClipAudioVolumePercentage);
    549 
    550         LOGV("startPreview:setAudioMixStoryBoardSkimTimeStamp set %d cuttime \
    551          %d", fromMS, mFirstPreviewClipBeginTime);
    552     }
    553 
    554     mStartingClipIndex = mCurrentClipNumber+1;
    555 
    556     // Start playing with player instance 0
    557     mCurrentPlayer = 0;
    558     mActivePlayerIndex = 0;
    559 
    560     if(toMs == -1) {
    561         LOGV("startPreview: Preview till end of storyboard");
    562         mNumberClipsToPreview = mNumberClipsInStoryBoard;
    563         // Save original value
    564         mLastPreviewClipEndTime =
    565          mClipList[mNumberClipsToPreview-1]->uiEndCutTime;
    566     }
    567     else {
    568         LOGV("startPreview: toMs=%d", toMs);
    569         if((M4OSA_UInt32)toMs > mClipTotalDuration) {
    570             LOGE("startPreview: toMs > mClipTotalDuration");
    571             return M4ERR_PARAMETER;
    572         }
    573 
    574         iIncrementedDuration = 0;
    575 
    576         for(i=0;i<mNumberClipsInStoryBoard;i++) {
    577             if((M4OSA_UInt32)toMs <= (iIncrementedDuration +
    578              (mClipList[i]->uiEndCutTime - mClipList[i]->uiBeginCutTime))) {
    579                 // Save original value
    580                 mLastPreviewClipEndTime = mClipList[i]->uiEndCutTime;
    581                 // Set the end cut time of clip index i to toMs
    582                 mClipList[i]->uiEndCutTime = toMs;
    583 
    584                 // Number of clips to be previewed is from index 0 to i
    585                 // increment by 1 as i starts from 0
    586                 mNumberClipsToPreview = i+1;
    587                 break;
    588             }
    589             else {
    590                 iIncrementedDuration = iIncrementedDuration +
    591                  (mClipList[i]->uiEndCutTime - mClipList[i]->uiBeginCutTime);
    592             }
    593         }
    594     }
    595 
    596     // Open the thread semaphore
    597     M4OSA_semaphoreOpen(&mSemThreadWait, 1);
    598 
    599     // Open the preview process thread
    600     err = M4OSA_threadSyncOpen(&mThreadContext, (M4OSA_ThreadDoIt)threadProc);
    601     if (M4NO_ERROR != err) {
    602         LOGE("VideoEditorPreviewController:M4OSA_threadSyncOpen error %d", (int) err);
    603         return err;
    604     }
    605 
    606     // Set the stacksize
    607     err = M4OSA_threadSyncSetOption(mThreadContext, M4OSA_ThreadStackSize,
    608      (M4OSA_DataOption)PREVIEW_THREAD_STACK_SIZE);
    609 
    610     if (M4NO_ERROR != err) {
    611         LOGE("VideoEditorPreviewController: threadSyncSetOption error %d", (int) err);
    612         M4OSA_threadSyncClose(mThreadContext);
    613         mThreadContext = NULL;
    614         return err;
    615     }
    616 
    617      // Start the thread
    618      err = M4OSA_threadSyncStart(mThreadContext, (M4OSA_Void*)this);
    619      if (M4NO_ERROR != err) {
    620         LOGE("VideoEditorPreviewController: threadSyncStart error %d", (int) err);
    621         M4OSA_threadSyncClose(mThreadContext);
    622         mThreadContext = NULL;
    623         return err;
    624     }
    625     bStopThreadInProgress = false;
    626 
    627     LOGV("startPreview: process thread started");
    628     return M4NO_ERROR;
    629 }
    630 
    631 M4OSA_UInt32 VideoEditorPreviewController::stopPreview() {
    632     M4OSA_ERR err = M4NO_ERROR;
    633     uint32_t lastRenderedFrameTimeMs = 0;
    634     LOGV("stopPreview");
    635 
    636     // Stop the thread
    637     if(mThreadContext != NULL) {
    638         bStopThreadInProgress = true;
    639         {
    640             Mutex::Autolock autoLock(mLockSem);
    641             if (mSemThreadWait != NULL) {
    642                 err = M4OSA_semaphorePost(mSemThreadWait);
    643             }
    644         }
    645 
    646         err = M4OSA_threadSyncStop(mThreadContext);
    647         if(err != M4NO_ERROR) {
    648             LOGV("stopPreview: error 0x%x in trying to stop thread", err);
    649             // Continue even if error
    650         }
    651 
    652         err = M4OSA_threadSyncClose(mThreadContext);
    653         if(err != M4NO_ERROR) {
    654             LOGE("stopPreview: error 0x%x in trying to close thread", (unsigned int)err);
    655             // Continue even if error
    656         }
    657 
    658         mThreadContext = NULL;
    659     }
    660 
    661     // Close the semaphore first
    662     {
    663         Mutex::Autolock autoLock(mLockSem);
    664         if(mSemThreadWait != NULL) {
    665             err = M4OSA_semaphoreClose(mSemThreadWait);
    666             LOGV("stopPreview: close semaphore returns 0x%x", err);
    667             mSemThreadWait = NULL;
    668         }
    669     }
    670 
    671     for (int playerInst=0; playerInst<NBPLAYER_INSTANCES; playerInst++) {
    672         if(mVePlayer[playerInst] != NULL) {
    673             if(mVePlayer[playerInst]->isPlaying()) {
    674                 LOGV("stop the player first");
    675                 mVePlayer[playerInst]->stop();
    676             }
    677             if (playerInst == mActivePlayerIndex) {
    678                 // Return the last rendered frame time stamp
    679                 mVePlayer[mActivePlayerIndex]->getLastRenderedTimeMs(&lastRenderedFrameTimeMs);
    680             }
    681 
    682             //This is used to syncronize onStreamDone() in PreviewPlayer and
    683             //stopPreview() in PreviewController
    684             sp<VideoEditorPlayer> temp = mVePlayer[playerInst];
    685             temp->acquireLock();
    686             LOGV("stopPreview: clearing mVePlayer");
    687             mVePlayer[playerInst].clear();
    688             mVePlayer[playerInst] = NULL;
    689             temp->releaseLock();
    690         }
    691     }
    692     LOGV("stopPreview: clear audioSink and audioPlayer");
    693     mVEAudioSink.clear();
    694     if (mVEAudioPlayer) {
    695         delete mVEAudioPlayer;
    696         mVEAudioPlayer = NULL;
    697     }
    698 
    699     delete mNativeWindowRenderer;
    700     mNativeWindowRenderer = NULL;
    701 
    702     // If image file playing, then free the buffer pointer
    703     if(mFrameStr.pBuffer != M4OSA_NULL) {
    704         free(mFrameStr.pBuffer);
    705         mFrameStr.pBuffer = M4OSA_NULL;
    706     }
    707 
    708     // Reset original begin cuttime of first previewed clip*/
    709     mClipList[mStartingClipIndex]->uiBeginCutTime = mFirstPreviewClipBeginTime;
    710     // Reset original end cuttime of last previewed clip*/
    711     mClipList[mNumberClipsToPreview-1]->uiEndCutTime = mLastPreviewClipEndTime;
    712 
    713     mPlayerState = VePlayerIdle;
    714     mPrepareReqest = M4OSA_FALSE;
    715 
    716     mCurrentPlayedDuration = 0;
    717     mCurrentClipDuration = 0;
    718     mRenderingMode = M4xVSS_kBlackBorders;
    719     mOutputVideoWidth = 0;
    720     mOutputVideoHeight = 0;
    721 
    722     LOGV("stopPreview() lastRenderedFrameTimeMs %ld", lastRenderedFrameTimeMs);
    723     return lastRenderedFrameTimeMs;
    724 }
    725 
    726 M4OSA_ERR VideoEditorPreviewController::clearSurface(
    727     const sp<Surface> &surface, VideoEditor_renderPreviewFrameStr* pFrameInfo) {
    728 
    729     M4OSA_ERR err = M4NO_ERROR;
    730     VideoEditor_renderPreviewFrameStr* pFrameStr = pFrameInfo;
    731     M4OSA_UInt32 outputBufferWidth =0, outputBufferHeight=0;
    732     M4VIFI_ImagePlane planeOut[3];
    733     LOGV("Inside preview clear frame");
    734 
    735     Mutex::Autolock autoLock(mLock);
    736 
    737     // Delete previous renderer instance
    738     if(mTarget != NULL) {
    739         delete mTarget;
    740         mTarget = NULL;
    741     }
    742 
    743     outputBufferWidth = pFrameStr->uiFrameWidth;
    744     outputBufferHeight = pFrameStr->uiFrameHeight;
    745 
    746     // Initialize the renderer
    747     if(mTarget == NULL) {
    748 
    749         mTarget = PreviewRenderer::CreatePreviewRenderer(
    750             surface,
    751             outputBufferWidth, outputBufferHeight);
    752 
    753         if(mTarget == NULL) {
    754             LOGE("renderPreviewFrame: cannot create PreviewRenderer");
    755             return M4ERR_ALLOC;
    756         }
    757     }
    758 
    759     // Out plane
    760     uint8_t* outBuffer;
    761     size_t outBufferStride = 0;
    762 
    763     LOGV("doMediaRendering CALL getBuffer()");
    764     mTarget->getBufferYV12(&outBuffer, &outBufferStride);
    765 
    766     // Set the output YUV420 plane to be compatible with YV12 format
    767     //In YV12 format, sizes must be even
    768     M4OSA_UInt32 yv12PlaneWidth = ((outputBufferWidth +1)>>1)<<1;
    769     M4OSA_UInt32 yv12PlaneHeight = ((outputBufferHeight+1)>>1)<<1;
    770 
    771     prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
    772      (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
    773 
    774     /* Fill the surface with black frame */
    775     memset((void *)planeOut[0].pac_data,0x00,planeOut[0].u_width *
    776                             planeOut[0].u_height * 1.5);
    777     memset((void *)planeOut[1].pac_data,128,planeOut[1].u_width *
    778                             planeOut[1].u_height);
    779     memset((void *)planeOut[2].pac_data,128,planeOut[2].u_width *
    780                              planeOut[2].u_height);
    781 
    782     mTarget->renderYV12();
    783     return err;
    784 }
    785 
    786 M4OSA_ERR VideoEditorPreviewController::renderPreviewFrame(
    787             const sp<Surface> &surface,
    788             VideoEditor_renderPreviewFrameStr* pFrameInfo,
    789             VideoEditorCurretEditInfo *pCurrEditInfo) {
    790 
    791     M4OSA_ERR err = M4NO_ERROR;
    792     M4OSA_UInt32 i = 0, iIncrementedDuration = 0, tnTimeMs=0, framesize =0;
    793     VideoEditor_renderPreviewFrameStr* pFrameStr = pFrameInfo;
    794     M4VIFI_UInt8 *pixelArray = NULL;
    795     Mutex::Autolock autoLock(mLock);
    796 
    797     if (pCurrEditInfo != NULL) {
    798         pCurrEditInfo->overlaySettingsIndex = -1;
    799     }
    800     // Delete previous renderer instance
    801     if(mTarget != NULL) {
    802         delete mTarget;
    803         mTarget = NULL;
    804     }
    805 
    806     if(mOutputVideoWidth == 0) {
    807         mOutputVideoWidth = pFrameStr->uiFrameWidth;
    808     }
    809 
    810     if(mOutputVideoHeight == 0) {
    811         mOutputVideoHeight = pFrameStr->uiFrameHeight;
    812     }
    813 
    814     // Initialize the renderer
    815     if(mTarget == NULL) {
    816          mTarget = PreviewRenderer::CreatePreviewRenderer(
    817             surface,
    818             mOutputVideoWidth, mOutputVideoHeight);
    819 
    820         if(mTarget == NULL) {
    821             LOGE("renderPreviewFrame: cannot create PreviewRenderer");
    822             return M4ERR_ALLOC;
    823         }
    824     }
    825 
    826     pixelArray = NULL;
    827 
    828     // Apply rotation if required
    829     if (pFrameStr->videoRotationDegree != 0) {
    830         err = applyVideoRotation((M4OSA_Void *)pFrameStr->pBuffer,
    831                   pFrameStr->uiFrameWidth, pFrameStr->uiFrameHeight,
    832                   pFrameStr->videoRotationDegree);
    833         if (M4NO_ERROR != err) {
    834             LOGE("renderPreviewFrame: cannot rotate video, err 0x%x", (unsigned int)err);
    835             delete mTarget;
    836             mTarget = NULL;
    837             return err;
    838         } else {
    839            // Video rotation done.
    840            // Swap width and height if 90 or 270 degrees
    841            if (pFrameStr->videoRotationDegree != 180) {
    842                int32_t temp = pFrameStr->uiFrameWidth;
    843                pFrameStr->uiFrameWidth = pFrameStr->uiFrameHeight;
    844                pFrameStr->uiFrameHeight = temp;
    845            }
    846         }
    847     }
    848     // Postprocessing (apply video effect)
    849     if(pFrameStr->bApplyEffect == M4OSA_TRUE) {
    850 
    851         for(i=0;i<mNumberEffects;i++) {
    852             // First check if effect starttime matches the clip being previewed
    853             if((mEffectsSettings[i].uiStartTime < pFrameStr->clipBeginCutTime)
    854              ||(mEffectsSettings[i].uiStartTime >= pFrameStr->clipEndCutTime)) {
    855                 // This effect doesn't belong to this clip, check next one
    856                 continue;
    857             }
    858             if((mEffectsSettings[i].uiStartTime <= pFrameStr->timeMs) &&
    859             ((mEffectsSettings[i].uiStartTime+mEffectsSettings[i].uiDuration) >=
    860              pFrameStr->timeMs) && (mEffectsSettings[i].uiDuration != 0)) {
    861                 setVideoEffectType(mEffectsSettings[i].VideoEffectType, TRUE);
    862             }
    863             else {
    864                 setVideoEffectType(mEffectsSettings[i].VideoEffectType, FALSE);
    865             }
    866         }
    867 
    868         //Provide the overlay Update indication when there is an overlay effect
    869         if (mCurrentVideoEffect & VIDEO_EFFECT_FRAMING) {
    870             M4OSA_UInt32 index;
    871             mCurrentVideoEffect &= ~VIDEO_EFFECT_FRAMING; //never apply framing here.
    872 
    873             // Find the effect in effectSettings array
    874             for (index = 0; index < mNumberEffects; index++) {
    875                 if(mEffectsSettings[index].VideoEffectType ==
    876                     (M4VSS3GPP_VideoEffectType)M4xVSS_kVideoEffectType_Framing) {
    877 
    878                     if((mEffectsSettings[index].uiStartTime <= pFrameInfo->timeMs) &&
    879                         ((mEffectsSettings[index].uiStartTime+
    880                         mEffectsSettings[index].uiDuration) >= pFrameInfo->timeMs))
    881                     {
    882                         break;
    883                     }
    884                 }
    885             }
    886             if ((index < mNumberEffects) && (pCurrEditInfo != NULL)) {
    887                 pCurrEditInfo->overlaySettingsIndex = index;
    888                 LOGV("Framing index = %d", index);
    889             } else {
    890                 LOGV("No framing effects found");
    891             }
    892         }
    893 
    894         if(mCurrentVideoEffect != VIDEO_EFFECT_NONE) {
    895             err = applyVideoEffect((M4OSA_Void *)pFrameStr->pBuffer,
    896              OMX_COLOR_FormatYUV420Planar, pFrameStr->uiFrameWidth,
    897              pFrameStr->uiFrameHeight, pFrameStr->timeMs,
    898              (M4OSA_Void *)pixelArray);
    899 
    900             if(err != M4NO_ERROR) {
    901                 LOGE("renderPreviewFrame: applyVideoEffect error 0x%x", (unsigned int)err);
    902                 delete mTarget;
    903                 mTarget = NULL;
    904                 free(pixelArray);
    905                 pixelArray = NULL;
    906                 return err;
    907            }
    908            mCurrentVideoEffect = VIDEO_EFFECT_NONE;
    909         }
    910         else {
    911             // Apply the rendering mode
    912             err = doImageRenderingMode((M4OSA_Void *)pFrameStr->pBuffer,
    913              OMX_COLOR_FormatYUV420Planar, pFrameStr->uiFrameWidth,
    914              pFrameStr->uiFrameHeight, (M4OSA_Void *)pixelArray);
    915 
    916             if(err != M4NO_ERROR) {
    917                 LOGE("renderPreviewFrame:doImageRenderingMode error 0x%x", (unsigned int)err);
    918                 delete mTarget;
    919                 mTarget = NULL;
    920                 free(pixelArray);
    921                 pixelArray = NULL;
    922                 return err;
    923             }
    924         }
    925     }
    926     else {
    927         // Apply the rendering mode
    928         err = doImageRenderingMode((M4OSA_Void *)pFrameStr->pBuffer,
    929          OMX_COLOR_FormatYUV420Planar, pFrameStr->uiFrameWidth,
    930          pFrameStr->uiFrameHeight, (M4OSA_Void *)pixelArray);
    931 
    932         if(err != M4NO_ERROR) {
    933             LOGE("renderPreviewFrame: doImageRenderingMode error 0x%x", (unsigned int)err);
    934             delete mTarget;
    935             mTarget = NULL;
    936             free(pixelArray);
    937             pixelArray = NULL;
    938             return err;
    939         }
    940     }
    941 
    942     mTarget->renderYV12();
    943     return err;
    944 }
    945 
    946 M4OSA_Void VideoEditorPreviewController::setJniCallback(void* cookie,
    947     jni_progress_callback_fct callbackFct) {
    948     //LOGV("setJniCallback");
    949     mJniCookie = cookie;
    950     mJniCallback = callbackFct;
    951 }
    952 
    953 M4OSA_ERR VideoEditorPreviewController::preparePlayer(
    954     void* param, int playerInstance, int index) {
    955 
    956     M4OSA_ERR err = M4NO_ERROR;
    957     VideoEditorPreviewController *pController =
    958      (VideoEditorPreviewController *)param;
    959 
    960     LOGV("preparePlayer: instance %d file %d", playerInstance, index);
    961 
    962     pController->mVePlayer[playerInstance]->setDataSource(
    963     (const char *)pController->mClipList[index]->pFile, NULL);
    964     LOGV("preparePlayer: setDataSource instance %s",
    965      (const char *)pController->mClipList[index]->pFile);
    966 
    967     pController->mVePlayer[playerInstance]->setVideoSurface(
    968      pController->mSurface);
    969     LOGV("preparePlayer: setVideoSurface");
    970 
    971     pController->mVePlayer[playerInstance]->setMediaRenderingMode(
    972      pController->mClipList[index]->xVSS.MediaRendering,
    973      pController->mOutputVideoSize);
    974     LOGV("preparePlayer: setMediaRenderingMode");
    975 
    976     if((M4OSA_UInt32)index == pController->mStartingClipIndex) {
    977         pController->mVePlayer[playerInstance]->setPlaybackBeginTime(
    978         pController->mFirstPreviewClipBeginTime);
    979     }
    980     else {
    981         pController->mVePlayer[playerInstance]->setPlaybackBeginTime(
    982         pController->mClipList[index]->uiBeginCutTime);
    983     }
    984     LOGV("preparePlayer: setPlaybackBeginTime(%d)",
    985      pController->mClipList[index]->uiBeginCutTime);
    986 
    987     pController->mVePlayer[playerInstance]->setPlaybackEndTime(
    988      pController->mClipList[index]->uiEndCutTime);
    989     LOGV("preparePlayer: setPlaybackEndTime(%d)",
    990      pController->mClipList[index]->uiEndCutTime);
    991 
    992     if(pController->mClipList[index]->FileType == M4VIDEOEDITING_kFileType_ARGB8888) {
    993         pController->mVePlayer[playerInstance]->setImageClipProperties(
    994                  pController->mClipList[index]->ClipProperties.uiVideoWidth,
    995                  pController->mClipList[index]->ClipProperties.uiVideoHeight);
    996         LOGV("preparePlayer: setImageClipProperties");
    997     }
    998 
    999     pController->mVePlayer[playerInstance]->prepare();
   1000     LOGV("preparePlayer: prepared");
   1001 
   1002     if(pController->mClipList[index]->uiBeginCutTime > 0) {
   1003         pController->mVePlayer[playerInstance]->seekTo(
   1004          pController->mClipList[index]->uiBeginCutTime);
   1005 
   1006         LOGV("preparePlayer: seekTo(%d)",
   1007          pController->mClipList[index]->uiBeginCutTime);
   1008     }
   1009     pController->mVePlayer[pController->mCurrentPlayer]->setAudioPlayer(pController->mVEAudioPlayer);
   1010 
   1011     pController->mVePlayer[playerInstance]->readFirstVideoFrame();
   1012     LOGV("preparePlayer: readFirstVideoFrame of clip");
   1013 
   1014     return err;
   1015 }
   1016 
   1017 M4OSA_ERR VideoEditorPreviewController::threadProc(M4OSA_Void* param) {
   1018     M4OSA_ERR err = M4NO_ERROR;
   1019     M4OSA_Int32 index = 0;
   1020     VideoEditorPreviewController *pController =
   1021      (VideoEditorPreviewController *)param;
   1022 
   1023     LOGV("inside threadProc");
   1024     if(pController->mPlayerState == VePlayerIdle) {
   1025         (pController->mCurrentClipNumber)++;
   1026 
   1027         LOGD("threadProc: playing file index %d total clips %d",
   1028          pController->mCurrentClipNumber, pController->mNumberClipsToPreview);
   1029 
   1030         if((M4OSA_UInt32)pController->mCurrentClipNumber >=
   1031          pController->mNumberClipsToPreview) {
   1032 
   1033             LOGD("All clips previewed");
   1034 
   1035             pController->mCurrentPlayedDuration = 0;
   1036             pController->mCurrentClipDuration = 0;
   1037             pController->mCurrentPlayer = 0;
   1038 
   1039             if(pController->mPreviewLooping == M4OSA_TRUE) {
   1040                 pController->mCurrentClipNumber =
   1041                  pController->mStartingClipIndex;
   1042 
   1043                 LOGD("Preview looping TRUE, restarting from clip index %d",
   1044                  pController->mCurrentClipNumber);
   1045 
   1046                 // Reset the story board timestamp inside the player
   1047                 for (int playerInst=0; playerInst<NBPLAYER_INSTANCES;
   1048                  playerInst++) {
   1049                     pController->mVePlayer[playerInst]->resetJniCallbackTimeStamp();
   1050                 }
   1051             }
   1052             else {
   1053                 M4OSA_UInt32 endArgs = 0;
   1054                 if(pController->mJniCallback != NULL) {
   1055                     pController->mJniCallback(
   1056                      pController->mJniCookie, MSG_TYPE_PREVIEW_END, &endArgs);
   1057                 }
   1058                 pController->mPlayerState = VePlayerAutoStop;
   1059 
   1060                 // Reset original begin cuttime of first previewed clip
   1061                 pController->mClipList[pController->mStartingClipIndex]->uiBeginCutTime =
   1062                  pController->mFirstPreviewClipBeginTime;
   1063                 // Reset original end cuttime of last previewed clip
   1064                 pController->mClipList[pController->mNumberClipsToPreview-1]->uiEndCutTime =
   1065                  pController->mLastPreviewClipEndTime;
   1066 
   1067                 // Return a warning to M4OSA thread handler
   1068                 // so that thread is moved from executing state to open state
   1069                 return M4WAR_NO_MORE_STREAM;
   1070             }
   1071         }
   1072 
   1073         index=pController->mCurrentClipNumber;
   1074         if((M4OSA_UInt32)pController->mCurrentClipNumber == pController->mStartingClipIndex) {
   1075             pController->mCurrentPlayedDuration +=
   1076              pController->mVideoStoryBoardTimeMsUptoFirstPreviewClip;
   1077 
   1078             pController->mCurrentClipDuration =
   1079              pController->mClipList[pController->mCurrentClipNumber]->uiEndCutTime
   1080               - pController->mFirstPreviewClipBeginTime;
   1081 
   1082             preparePlayer((void*)pController, pController->mCurrentPlayer, index);
   1083         }
   1084         else {
   1085             pController->mCurrentPlayedDuration +=
   1086              pController->mCurrentClipDuration;
   1087 
   1088             pController->mCurrentClipDuration =
   1089              pController->mClipList[pController->mCurrentClipNumber]->uiEndCutTime -
   1090              pController->mClipList[pController->mCurrentClipNumber]->uiBeginCutTime;
   1091         }
   1092 
   1093         pController->mVePlayer[pController->mCurrentPlayer]->setStoryboardStartTime(
   1094          pController->mCurrentPlayedDuration);
   1095         LOGV("threadProc: setStoryboardStartTime");
   1096 
   1097         // Set the next clip duration for Audio mix here
   1098         if((M4OSA_UInt32)pController->mCurrentClipNumber != pController->mStartingClipIndex) {
   1099 
   1100             pController->mVePlayer[pController->mCurrentPlayer]->setAudioMixStoryBoardParam(
   1101              pController->mCurrentPlayedDuration,
   1102              pController->mClipList[index]->uiBeginCutTime,
   1103              pController->mClipList[index]->ClipProperties.uiClipAudioVolumePercentage);
   1104 
   1105             LOGV("threadProc: setAudioMixStoryBoardParam fromMS %d \
   1106              ClipBeginTime %d", pController->mCurrentPlayedDuration +
   1107              pController->mClipList[index]->uiBeginCutTime,
   1108              pController->mClipList[index]->uiBeginCutTime,
   1109              pController->mClipList[index]->ClipProperties.uiClipAudioVolumePercentage);
   1110         }
   1111         // Capture the active player being used
   1112         pController->mActivePlayerIndex = pController->mCurrentPlayer;
   1113 
   1114         pController->mVePlayer[pController->mCurrentPlayer]->start();
   1115         LOGV("threadProc: started");
   1116 
   1117         pController->mPlayerState = VePlayerBusy;
   1118 
   1119     } else if(pController->mPlayerState == VePlayerAutoStop) {
   1120         LOGV("Preview completed..auto stop the player");
   1121     } else if ((pController->mPlayerState == VePlayerBusy) && (pController->mPrepareReqest)) {
   1122         // Prepare the player here
   1123         pController->mPrepareReqest = M4OSA_FALSE;
   1124         preparePlayer((void*)pController, pController->mCurrentPlayer,
   1125             pController->mCurrentClipNumber+1);
   1126         if (pController->mSemThreadWait != NULL) {
   1127             err = M4OSA_semaphoreWait(pController->mSemThreadWait,
   1128                 M4OSA_WAIT_FOREVER);
   1129         }
   1130     } else {
   1131         if (!pController->bStopThreadInProgress) {
   1132             LOGV("threadProc: state busy...wait for sem");
   1133             if (pController->mSemThreadWait != NULL) {
   1134                 err = M4OSA_semaphoreWait(pController->mSemThreadWait,
   1135                  M4OSA_WAIT_FOREVER);
   1136              }
   1137         }
   1138         LOGV("threadProc: sem wait returned err = 0x%x", err);
   1139     }
   1140 
   1141     //Always return M4NO_ERROR to ensure the thread keeps running
   1142     return M4NO_ERROR;
   1143 }
   1144 
   1145 void VideoEditorPreviewController::notify(
   1146     void* cookie, int msg, int ext1, int ext2)
   1147 {
   1148     VideoEditorPreviewController *pController =
   1149      (VideoEditorPreviewController *)cookie;
   1150 
   1151     M4OSA_ERR err = M4NO_ERROR;
   1152     uint32_t clipDuration = 0;
   1153     switch (msg) {
   1154         case MEDIA_NOP: // interface test message
   1155             LOGV("MEDIA_NOP");
   1156             break;
   1157         case MEDIA_PREPARED:
   1158             LOGV("MEDIA_PREPARED");
   1159             break;
   1160         case MEDIA_PLAYBACK_COMPLETE:
   1161         {
   1162             LOGD("notify:MEDIA_PLAYBACK_COMPLETE, mCurrentClipNumber = %d",
   1163                     pController->mCurrentClipNumber);
   1164             pController->mPlayerState = VePlayerIdle;
   1165 
   1166             //send progress callback with last frame timestamp
   1167             if((M4OSA_UInt32)pController->mCurrentClipNumber ==
   1168              pController->mStartingClipIndex) {
   1169                 clipDuration =
   1170                  pController->mClipList[pController->mCurrentClipNumber]->uiEndCutTime
   1171                   - pController->mFirstPreviewClipBeginTime;
   1172             }
   1173             else {
   1174                 clipDuration =
   1175                  pController->mClipList[pController->mCurrentClipNumber]->uiEndCutTime
   1176                   - pController->mClipList[pController->mCurrentClipNumber]->uiBeginCutTime;
   1177             }
   1178 
   1179             M4OSA_UInt32 playedDuration = clipDuration+pController->mCurrentPlayedDuration;
   1180             pController->mJniCallback(
   1181                  pController->mJniCookie, MSG_TYPE_PROGRESS_INDICATION,
   1182                  &playedDuration);
   1183 
   1184             if ((pController->mOverlayState == OVERLAY_UPDATE) &&
   1185                 ((M4OSA_UInt32)pController->mCurrentClipNumber !=
   1186                 (pController->mNumberClipsToPreview-1))) {
   1187                 VideoEditorCurretEditInfo *pEditInfo =
   1188                     (VideoEditorCurretEditInfo*)M4OSA_32bitAlignedMalloc(sizeof(VideoEditorCurretEditInfo),
   1189                     M4VS, (M4OSA_Char*)"Current Edit info");
   1190                 pEditInfo->overlaySettingsIndex = ext2;
   1191                 pEditInfo->clipIndex = pController->mCurrentClipNumber;
   1192                 pController->mOverlayState == OVERLAY_CLEAR;
   1193                 if (pController->mJniCallback != NULL) {
   1194                         pController->mJniCallback(pController->mJniCookie,
   1195                             MSG_TYPE_OVERLAY_CLEAR, pEditInfo);
   1196                 }
   1197                 free(pEditInfo);
   1198             }
   1199             {
   1200                 Mutex::Autolock autoLock(pController->mLockSem);
   1201                 if (pController->mSemThreadWait != NULL) {
   1202                     M4OSA_semaphorePost(pController->mSemThreadWait);
   1203                     return;
   1204                 }
   1205             }
   1206 
   1207             break;
   1208         }
   1209         case MEDIA_ERROR:
   1210         {
   1211             int err_val = ext1;
   1212           // Always log errors.
   1213           // ext1: Media framework error code.
   1214           // ext2: Implementation dependant error code.
   1215             LOGE("MEDIA_ERROR; error (%d, %d)", ext1, ext2);
   1216             if(pController->mJniCallback != NULL) {
   1217                 pController->mJniCallback(pController->mJniCookie,
   1218                  MSG_TYPE_PLAYER_ERROR, &err_val);
   1219             }
   1220             break;
   1221         }
   1222         case MEDIA_INFO:
   1223         {
   1224             int info_val = ext2;
   1225             // ext1: Media framework error code.
   1226             // ext2: Implementation dependant error code.
   1227             //LOGW("MEDIA_INFO; info/warning (%d, %d)", ext1, ext2);
   1228             if(pController->mJniCallback != NULL) {
   1229                 pController->mJniCallback(pController->mJniCookie,
   1230                  MSG_TYPE_PROGRESS_INDICATION, &info_val);
   1231             }
   1232             break;
   1233         }
   1234         case MEDIA_SEEK_COMPLETE:
   1235             LOGV("MEDIA_SEEK_COMPLETE; Received seek complete");
   1236             break;
   1237         case MEDIA_BUFFERING_UPDATE:
   1238             LOGV("MEDIA_BUFFERING_UPDATE; buffering %d", ext1);
   1239             break;
   1240         case MEDIA_SET_VIDEO_SIZE:
   1241             LOGV("MEDIA_SET_VIDEO_SIZE; New video size %d x %d", ext1, ext2);
   1242             break;
   1243         case 0xAAAAAAAA:
   1244             LOGV("VIDEO PLAYBACK ALMOST over, prepare next player");
   1245             // Select next player and prepare it
   1246             // If there is a clip after this one
   1247             if ((M4OSA_UInt32)(pController->mCurrentClipNumber+1) <
   1248              pController->mNumberClipsToPreview) {
   1249                 pController->mPrepareReqest = M4OSA_TRUE;
   1250                 pController->mCurrentPlayer++;
   1251                 if (pController->mCurrentPlayer >= NBPLAYER_INSTANCES) {
   1252                     pController->mCurrentPlayer = 0;
   1253                 }
   1254                 // Prepare the first clip to be played
   1255                 {
   1256                     Mutex::Autolock autoLock(pController->mLockSem);
   1257                     if (pController->mSemThreadWait != NULL) {
   1258                         M4OSA_semaphorePost(pController->mSemThreadWait);
   1259                     }
   1260                 }
   1261             }
   1262             break;
   1263         case 0xBBBBBBBB:
   1264         {
   1265             LOGV("VIDEO PLAYBACK, Update Overlay");
   1266             int overlayIndex = ext2;
   1267             VideoEditorCurretEditInfo *pEditInfo =
   1268                     (VideoEditorCurretEditInfo*)M4OSA_32bitAlignedMalloc(sizeof(VideoEditorCurretEditInfo),
   1269                     M4VS, (M4OSA_Char*)"Current Edit info");
   1270             //ext1 = 1; start the overlay display
   1271             //     = 2; Clear the overlay.
   1272             pEditInfo->overlaySettingsIndex = ext2;
   1273             pEditInfo->clipIndex = pController->mCurrentClipNumber;
   1274             LOGV("pController->mCurrentClipNumber = %d",pController->mCurrentClipNumber);
   1275             if (pController->mJniCallback != NULL) {
   1276                 if (ext1 == 1) {
   1277                     pController->mOverlayState = OVERLAY_UPDATE;
   1278                     pController->mJniCallback(pController->mJniCookie,
   1279                         MSG_TYPE_OVERLAY_UPDATE, pEditInfo);
   1280                 } else {
   1281                     pController->mOverlayState = OVERLAY_CLEAR;
   1282                     pController->mJniCallback(pController->mJniCookie,
   1283                         MSG_TYPE_OVERLAY_CLEAR, pEditInfo);
   1284                 }
   1285             }
   1286             free(pEditInfo);
   1287             break;
   1288         }
   1289         default:
   1290             LOGV("unrecognized message: (%d, %d, %d)", msg, ext1, ext2);
   1291             break;
   1292     }
   1293 }
   1294 
   1295 void VideoEditorPreviewController::setVideoEffectType(
   1296     M4VSS3GPP_VideoEffectType type, M4OSA_Bool enable) {
   1297 
   1298     M4OSA_UInt32 effect = VIDEO_EFFECT_NONE;
   1299 
   1300     // map M4VSS3GPP_VideoEffectType to local enum
   1301     switch(type) {
   1302         case M4VSS3GPP_kVideoEffectType_FadeFromBlack:
   1303             effect = VIDEO_EFFECT_FADEFROMBLACK;
   1304             break;
   1305 
   1306         case M4VSS3GPP_kVideoEffectType_FadeToBlack:
   1307             effect = VIDEO_EFFECT_FADETOBLACK;
   1308             break;
   1309 
   1310         case M4xVSS_kVideoEffectType_BlackAndWhite:
   1311             effect = VIDEO_EFFECT_BLACKANDWHITE;
   1312             break;
   1313 
   1314         case M4xVSS_kVideoEffectType_Pink:
   1315             effect = VIDEO_EFFECT_PINK;
   1316             break;
   1317 
   1318         case M4xVSS_kVideoEffectType_Green:
   1319             effect = VIDEO_EFFECT_GREEN;
   1320             break;
   1321 
   1322         case M4xVSS_kVideoEffectType_Sepia:
   1323             effect = VIDEO_EFFECT_SEPIA;
   1324             break;
   1325 
   1326         case M4xVSS_kVideoEffectType_Negative:
   1327             effect = VIDEO_EFFECT_NEGATIVE;
   1328             break;
   1329 
   1330         case M4xVSS_kVideoEffectType_Framing:
   1331             effect = VIDEO_EFFECT_FRAMING;
   1332             break;
   1333 
   1334         case M4xVSS_kVideoEffectType_Fifties:
   1335             effect = VIDEO_EFFECT_FIFTIES;
   1336             break;
   1337 
   1338         case M4xVSS_kVideoEffectType_ColorRGB16:
   1339             effect = VIDEO_EFFECT_COLOR_RGB16;
   1340             break;
   1341 
   1342         case M4xVSS_kVideoEffectType_Gradient:
   1343             effect = VIDEO_EFFECT_GRADIENT;
   1344             break;
   1345 
   1346         default:
   1347             effect = VIDEO_EFFECT_NONE;
   1348             break;
   1349     }
   1350 
   1351     if(enable == M4OSA_TRUE) {
   1352         // If already set, then no need to set again
   1353         if(!(mCurrentVideoEffect & effect))
   1354             mCurrentVideoEffect |= effect;
   1355             if(effect == VIDEO_EFFECT_FIFTIES) {
   1356                 mIsFiftiesEffectStarted = true;
   1357             }
   1358     }
   1359     else  {
   1360         // Reset only if already set
   1361         if(mCurrentVideoEffect & effect)
   1362             mCurrentVideoEffect &= ~effect;
   1363     }
   1364 
   1365     return;
   1366 }
   1367 
   1368 
   1369 M4OSA_ERR VideoEditorPreviewController::applyVideoEffect(
   1370     M4OSA_Void * dataPtr, M4OSA_UInt32 colorFormat, M4OSA_UInt32 videoWidth,
   1371     M4OSA_UInt32 videoHeight, M4OSA_UInt32 timeMs, M4OSA_Void* outPtr) {
   1372 
   1373     M4OSA_ERR err = M4NO_ERROR;
   1374     vePostProcessParams postProcessParams;
   1375 
   1376     postProcessParams.vidBuffer = (M4VIFI_UInt8*)dataPtr;
   1377     postProcessParams.videoWidth = videoWidth;
   1378     postProcessParams.videoHeight = videoHeight;
   1379     postProcessParams.timeMs = timeMs;
   1380     postProcessParams.timeOffset = 0; //Since timeMS already takes care of offset in this case
   1381     postProcessParams.effectsSettings = mEffectsSettings;
   1382     postProcessParams.numberEffects = mNumberEffects;
   1383     postProcessParams.outVideoWidth = mOutputVideoWidth;
   1384     postProcessParams.outVideoHeight = mOutputVideoHeight;
   1385     postProcessParams.currentVideoEffect = mCurrentVideoEffect;
   1386     postProcessParams.renderingMode = mRenderingMode;
   1387     if(mIsFiftiesEffectStarted == M4OSA_TRUE) {
   1388         postProcessParams.isFiftiesEffectStarted = M4OSA_TRUE;
   1389         mIsFiftiesEffectStarted = M4OSA_FALSE;
   1390     }
   1391     else {
   1392        postProcessParams.isFiftiesEffectStarted = M4OSA_FALSE;
   1393     }
   1394     //postProcessParams.renderer = mTarget;
   1395     postProcessParams.overlayFrameRGBBuffer = NULL;
   1396     postProcessParams.overlayFrameYUVBuffer = NULL;
   1397 
   1398     mTarget->getBufferYV12(&(postProcessParams.pOutBuffer), &(postProcessParams.outBufferStride));
   1399 
   1400     err = applyEffectsAndRenderingMode(&postProcessParams, videoWidth, videoHeight);
   1401     return err;
   1402 }
   1403 
   1404 status_t VideoEditorPreviewController::setPreviewFrameRenderingMode(
   1405     M4xVSS_MediaRendering mode, M4VIDEOEDITING_VideoFrameSize outputVideoSize) {
   1406 
   1407     LOGV("setMediaRenderingMode: outputVideoSize = %d", outputVideoSize);
   1408     mRenderingMode = mode;
   1409 
   1410     status_t err = OK;
   1411     /* get the video width and height by resolution */
   1412     err = getVideoSizeByResolution(outputVideoSize,
   1413               &mOutputVideoWidth, &mOutputVideoHeight);
   1414 
   1415     return err;
   1416 }
   1417 
   1418 M4OSA_ERR VideoEditorPreviewController::doImageRenderingMode(
   1419     M4OSA_Void * dataPtr, M4OSA_UInt32 colorFormat, M4OSA_UInt32 videoWidth,
   1420     M4OSA_UInt32 videoHeight, M4OSA_Void* outPtr) {
   1421 
   1422     M4OSA_ERR err = M4NO_ERROR;
   1423     M4VIFI_ImagePlane planeIn[3], planeOut[3];
   1424     M4VIFI_UInt8 *inBuffer = M4OSA_NULL;
   1425     M4OSA_UInt32 outputBufferWidth =0, outputBufferHeight=0;
   1426 
   1427     //frameSize = (videoWidth*videoHeight*3) >> 1;
   1428     inBuffer = (M4OSA_UInt8 *)dataPtr;
   1429 
   1430     // In plane
   1431     prepareYUV420ImagePlane(planeIn, videoWidth,
   1432       videoHeight, (M4VIFI_UInt8 *)inBuffer, videoWidth, videoHeight);
   1433 
   1434     outputBufferWidth = mOutputVideoWidth;
   1435     outputBufferHeight = mOutputVideoHeight;
   1436 
   1437     // Out plane
   1438     uint8_t* outBuffer;
   1439     size_t outBufferStride = 0;
   1440 
   1441     LOGV("doMediaRendering CALL getBuffer()");
   1442     mTarget->getBufferYV12(&outBuffer, &outBufferStride);
   1443 
   1444     // Set the output YUV420 plane to be compatible with YV12 format
   1445     //In YV12 format, sizes must be even
   1446     M4OSA_UInt32 yv12PlaneWidth = ((mOutputVideoWidth +1)>>1)<<1;
   1447     M4OSA_UInt32 yv12PlaneHeight = ((mOutputVideoHeight+1)>>1)<<1;
   1448 
   1449     prepareYV12ImagePlane(planeOut, yv12PlaneWidth, yv12PlaneHeight,
   1450      (M4OSA_UInt32)outBufferStride, (M4VIFI_UInt8 *)outBuffer);
   1451 
   1452     err = applyRenderingMode(planeIn, planeOut, mRenderingMode);
   1453     if(err != M4NO_ERROR) {
   1454         LOGE("doImageRenderingMode: applyRenderingMode returned err=0x%x", (unsigned int)err);
   1455     }
   1456     return err;
   1457 }
   1458 
   1459 } //namespace android
   1460