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