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