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
21namespace android {
22
23#define PREVIEW_THREAD_STACK_SIZE                           (65536)
24
25VideoEditorPreviewController::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
64VideoEditorPreviewController::~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
145M4OSA_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
414M4OSA_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
422M4OSA_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
631M4OSA_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
726M4OSA_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
786M4OSA_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
946M4OSA_Void VideoEditorPreviewController::setJniCallback(void* cookie,
947    jni_progress_callback_fct callbackFct) {
948    //LOGV("setJniCallback");
949    mJniCookie = cookie;
950    mJniCallback = callbackFct;
951}
952
953M4OSA_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
1017M4OSA_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
1145void 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
1295void 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
1369M4OSA_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
1404status_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
1418M4OSA_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