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
29namespace android {
30
31
32VideoEditorPreviewController::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
71VideoEditorPreviewController::~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
152M4OSA_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
421M4OSA_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
429M4OSA_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
638M4OSA_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
733M4OSA_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
793M4OSA_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
953M4OSA_Void VideoEditorPreviewController::setJniCallback(void* cookie,
954    jni_progress_callback_fct callbackFct) {
955    //ALOGV("setJniCallback");
956    mJniCookie = cookie;
957    mJniCallback = callbackFct;
958}
959
960M4OSA_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
1025M4OSA_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
1153void 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
1303void 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
1377M4OSA_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
1412status_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
1426M4OSA_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