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