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