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