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