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 #define LOG_NDEBUG 1 17 #define LOG_TAG "VideoEditorMain" 18 #include <dlfcn.h> 19 #include <stdio.h> 20 #include <unistd.h> 21 #include <utils/Log.h> 22 #include <utils/threads.h> 23 #include <VideoEditorClasses.h> 24 #include <VideoEditorJava.h> 25 #include <VideoEditorOsal.h> 26 #include <VideoEditorLogging.h> 27 #include <marker.h> 28 #include <VideoEditorClasses.h> 29 #include <VideoEditorThumbnailMain.h> 30 #include <M4OSA_Debug.h> 31 #include <M4xVSS_Internal.h> 32 #include <surfaceflinger/Surface.h> 33 #include <surfaceflinger/ISurface.h> 34 #include "VideoEditorPreviewController.h" 35 36 #include "VideoEditorMain.h" 37 38 extern "C" { 39 #include <M4OSA_Clock.h> 40 #include <M4OSA_CharStar.h> 41 #include <M4OSA_Error.h> 42 #include <M4OSA_FileCommon.h> 43 #include <M4OSA_FileReader.h> 44 #include <M4OSA_FileWriter.h> 45 #include <M4OSA_Memory.h> 46 #include <M4OSA_Thread.h> 47 #include <M4xVSS_API.h> 48 #include <M4VSS3GPP_ErrorCodes.h> 49 #include <M4MCS_API.h> 50 #include <M4MCS_ErrorCodes.h> 51 #include <M4READER_Common.h> 52 #include <M4WRITER_common.h> 53 }; 54 55 56 using namespace android; 57 58 #define THREAD_STACK_SIZE (65536) 59 60 #define VIDEOEDITOR_VERSION_MAJOR 0 61 #define VIDEOEDITOR_VERSION_MINOR 0 62 #define VIDEOEDITOR_VERSION_REVISION 1 63 64 65 typedef enum 66 { 67 ManualEditState_NOT_INITIALIZED, 68 ManualEditState_INITIALIZED, 69 ManualEditState_ANALYZING, 70 ManualEditState_ANALYZING_ERROR, 71 ManualEditState_OPENED, 72 ManualEditState_SAVING, 73 ManualEditState_SAVING_ERROR, 74 ManualEditState_SAVED, 75 ManualEditState_STOPPING 76 } ManualEditState; 77 78 typedef struct 79 { 80 JavaVM* pVM; 81 jobject engine; 82 jmethodID onCompletionMethodId; 83 jmethodID onErrorMethodId; 84 jmethodID onWarningMethodId; 85 jmethodID onProgressUpdateMethodId; 86 jmethodID onPreviewProgressUpdateMethodId; 87 jmethodID previewFrameEditInfoId; 88 M4xVSS_InitParams initParams; 89 void* pTextRendererHandle; 90 M4xVSS_getTextRgbBufferFct pTextRendererFunction; 91 M4OSA_Context engineContext; 92 ManualEditState state; 93 M4VSS3GPP_EditSettings* pEditSettings; 94 M4OSA_Context threadContext; 95 M4OSA_ERR threadResult; 96 M4OSA_UInt8 threadProgress; 97 VideoEditorPreviewController *mPreviewController; 98 M4xVSS_AudioMixingSettings *mAudioSettings; 99 /* Audio Graph changes */ 100 M4OSA_Context pAudioGraphMCSCtx; 101 M4OSA_Bool bSkipState; 102 jmethodID onAudioGraphProgressUpdateMethodId; 103 Mutex mLock; 104 bool mIsUpdateOverlay; 105 char *mOverlayFileName; 106 int mOverlayRenderingMode; 107 M4DECODER_VideoDecoders* decoders; 108 } ManualEditContext; 109 110 extern "C" M4OSA_ERR M4MCS_open_normalMode( 111 M4MCS_Context pContext, 112 M4OSA_Void* pFileIn, 113 M4VIDEOEDITING_FileType InputFileType, 114 M4OSA_Void* pFileOut, 115 M4OSA_Void* pTempFile); 116 117 static M4OSA_ERR videoEditor_toUTF8Fct( 118 M4OSA_Void* pBufferIn, 119 M4OSA_UInt8* pBufferOut, 120 M4OSA_UInt32* bufferOutSize); 121 122 static M4OSA_ERR videoEditor_fromUTF8Fct( 123 M4OSA_UInt8* pBufferIn, 124 M4OSA_Void* pBufferOut, 125 M4OSA_UInt32* bufferOutSize); 126 127 static M4OSA_ERR videoEditor_getTextRgbBufferFct( 128 M4OSA_Void* pRenderingData, 129 M4OSA_Void* pTextBuffer, 130 M4OSA_UInt32 textBufferSize, 131 M4VIFI_ImagePlane** pOutputPlane); 132 133 static void videoEditor_callOnProgressUpdate( 134 ManualEditContext* pContext, 135 int task, 136 int progress); 137 138 static void videoEditor_freeContext( 139 JNIEnv* pEnv, 140 ManualEditContext** ppContext); 141 142 static M4OSA_ERR videoEditor_threadProc( 143 M4OSA_Void* param); 144 145 static jobject videoEditor_getVersion( 146 JNIEnv* pEnv, 147 jobject thiz); 148 149 static void videoEditor_init( 150 JNIEnv* pEnv, 151 jobject thiz, 152 jstring tempPath, 153 jstring textRendererPath); 154 155 static void videoEditor_loadSettings( 156 JNIEnv* pEnv, 157 jobject thiz, 158 jobject settings); 159 160 static void videoEditor_unloadSettings( 161 JNIEnv* pEnv, 162 jobject thiz); 163 164 165 static void videoEditor_stopEncoding( 166 JNIEnv* pEnv, 167 jobject thiz); 168 169 static void videoEditor_release( 170 JNIEnv* pEnv, 171 jobject thiz); 172 static int videoEditor_getPixels( 173 JNIEnv* env, 174 jobject thiz, 175 jstring path, 176 jintArray pixelArray, 177 M4OSA_UInt32 width, 178 M4OSA_UInt32 height, 179 M4OSA_UInt32 timeMS); 180 static int videoEditor_getPixelsList( 181 JNIEnv* env, 182 jobject thiz, 183 jstring path, 184 jintArray pixelArray, 185 M4OSA_UInt32 width, 186 M4OSA_UInt32 height, 187 M4OSA_UInt32 noOfThumbnails, 188 jlong startTime, 189 jlong endTime, 190 jintArray indexArray, 191 jobject callback); 192 193 static void 194 videoEditor_startPreview( 195 JNIEnv* pEnv, 196 jobject thiz, 197 jobject mSurface, 198 jlong fromMs, 199 jlong toMs, 200 jint callbackInterval, 201 jboolean loop); 202 203 static void 204 videoEditor_populateSettings( 205 JNIEnv* pEnv, 206 jobject thiz, 207 jobject settings, 208 jobject object, 209 jobject audioSettingObject); 210 211 static int videoEditor_stopPreview(JNIEnv* pEnv, 212 jobject thiz); 213 214 static jobject 215 videoEditor_getProperties( 216 JNIEnv* pEnv, 217 jobject thiz, 218 jstring file); 219 220 static int videoEditor_renderPreviewFrame(JNIEnv* pEnv, 221 jobject thiz, 222 jobject mSurface, 223 jlong fromMs, 224 jint surfaceWidth, 225 jint surfaceHeight); 226 227 static int videoEditor_registerManualEditMethods( 228 JNIEnv* pEnv); 229 230 static void jniPreviewProgressCallback(void* cookie, M4OSA_UInt32 msgType, 231 void *argc); 232 233 static int videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv, 234 jobject thiz, 235 jobject mSurface, 236 jstring filePath, 237 jint frameWidth, 238 jint frameHeight, 239 jint surfaceWidth, 240 jint surfaceHeight, 241 jlong fromMs); 242 243 static int videoEditor_generateAudioWaveFormSync ( JNIEnv* pEnv, 244 jobject thiz, 245 jstring pcmfilePath, 246 jstring outGraphfilePath, 247 jint frameDuration, 248 jint channels, 249 jint samplesCount); 250 251 static int videoEditor_generateAudioRawFile(JNIEnv* pEnv, 252 jobject thiz, 253 jstring infilePath, 254 jstring pcmfilePath ); 255 256 M4OSA_ERR videoEditor_generateAudio(JNIEnv* pEnv,ManualEditContext* pContext, 257 M4OSA_Char* infilePath, 258 M4OSA_Char* pcmfilePath ); 259 260 static int 261 videoEditor_generateClip( 262 JNIEnv* pEnv, 263 jobject thiz, 264 jobject settings); 265 266 static void videoEditor_clearSurface(JNIEnv* pEnv, 267 jobject thiz, 268 jobject surface); 269 270 static JNINativeMethod gManualEditMethods[] = { 271 {"getVersion", "()L"VERSION_CLASS_NAME";", 272 (void *)videoEditor_getVersion }, 273 {"_init", "(Ljava/lang/String;Ljava/lang/String;)V", 274 (void *)videoEditor_init }, 275 {"nativeStartPreview", "(Landroid/view/Surface;JJIZ)V", 276 (void *)videoEditor_startPreview }, 277 {"nativePopulateSettings", 278 "(L"EDIT_SETTINGS_CLASS_NAME";L"PREVIEW_PROPERTIES_CLASS_NAME";L" 279 AUDIO_SETTINGS_CLASS_NAME";)V", 280 (void *)videoEditor_populateSettings }, 281 {"nativeRenderPreviewFrame", "(Landroid/view/Surface;JII)I", 282 (int *)videoEditor_renderPreviewFrame }, 283 {"nativeRenderMediaItemPreviewFrame", 284 "(Landroid/view/Surface;Ljava/lang/String;IIIIJ)I", 285 (int *)videoEditor_renderMediaItemPreviewFrame }, 286 {"nativeStopPreview", "()I", 287 (int *)videoEditor_stopPreview }, 288 {"stopEncoding", "()V", 289 (void *)videoEditor_stopEncoding }, 290 {"release", "()V", 291 (void *)videoEditor_release }, 292 {"nativeGetPixels", "(Ljava/lang/String;[IIIJ)I", 293 (void*)videoEditor_getPixels }, 294 {"nativeGetPixelsList", "(Ljava/lang/String;[IIIIJJ[ILandroid/media/videoeditor/MediaArtistNativeHelper$NativeGetPixelsListCallback;)I", 295 (void*)videoEditor_getPixelsList }, 296 {"getMediaProperties", 297 "(Ljava/lang/String;)Landroid/media/videoeditor/MediaArtistNativeHelper$Properties;", 298 (void *)videoEditor_getProperties }, 299 {"nativeGenerateAudioGraph","(Ljava/lang/String;Ljava/lang/String;III)I", 300 (int *)videoEditor_generateAudioWaveFormSync }, 301 {"nativeGenerateRawAudio", "(Ljava/lang/String;Ljava/lang/String;)I", 302 (int *)videoEditor_generateAudioRawFile }, 303 {"nativeGenerateClip", "(L"EDIT_SETTINGS_CLASS_NAME";)I", 304 (void *)videoEditor_generateClip }, 305 {"nativeClearSurface", "(Landroid/view/Surface;)V", 306 (void *)videoEditor_clearSurface }, 307 }; 308 309 // temp file name of VSS out file 310 #define TEMP_MCS_OUT_FILE_PATH "tmpOut.3gp" 311 312 void 313 getClipSetting( 314 JNIEnv* pEnv, 315 jobject object, 316 M4VSS3GPP_ClipSettings* pSettings) 317 { 318 319 jfieldID fid; 320 int field = 0; 321 bool needToBeLoaded = true; 322 jclass clazz = pEnv->FindClass(PROPERTIES_CLASS_NAME); 323 324 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 325 (M4OSA_NULL == clazz), 326 "not initialized"); 327 328 fid = pEnv->GetFieldID(clazz,"duration","I"); 329 pSettings->ClipProperties.uiClipDuration = pEnv->GetIntField(object,fid); 330 M4OSA_TRACE1_1("duration = %d",pSettings->ClipProperties.uiClipDuration); 331 332 fid = pEnv->GetFieldID(clazz,"videoFormat","I"); 333 pSettings->ClipProperties.VideoStreamType = 334 (M4VIDEOEDITING_VideoFormat)pEnv->GetIntField(object,fid); 335 M4OSA_TRACE1_1("videoFormat = %d",pSettings->ClipProperties.VideoStreamType); 336 337 fid = pEnv->GetFieldID(clazz,"videoDuration","I"); 338 pSettings->ClipProperties.uiClipVideoDuration = pEnv->GetIntField(object,fid); 339 M4OSA_TRACE1_1("videoDuration = %d", 340 pSettings->ClipProperties.uiClipVideoDuration); 341 342 fid = pEnv->GetFieldID(clazz,"width","I"); 343 pSettings->ClipProperties.uiVideoWidth = pEnv->GetIntField(object,fid); 344 M4OSA_TRACE1_1("width = %d",pSettings->ClipProperties.uiVideoWidth); 345 346 fid = pEnv->GetFieldID(clazz,"height","I"); 347 pSettings->ClipProperties.uiVideoHeight = pEnv->GetIntField(object,fid); 348 M4OSA_TRACE1_1("height = %d",pSettings->ClipProperties.uiVideoHeight); 349 350 fid = pEnv->GetFieldID(clazz,"audioFormat","I"); 351 pSettings->ClipProperties.AudioStreamType = 352 (M4VIDEOEDITING_AudioFormat)pEnv->GetIntField(object,fid); 353 M4OSA_TRACE1_1("audioFormat = %d",pSettings->ClipProperties.AudioStreamType); 354 355 fid = pEnv->GetFieldID(clazz,"audioDuration","I"); 356 pSettings->ClipProperties.uiClipAudioDuration = pEnv->GetIntField(object,fid); 357 M4OSA_TRACE1_1("audioDuration = %d", 358 pSettings->ClipProperties.uiClipAudioDuration); 359 360 fid = pEnv->GetFieldID(clazz,"audioBitrate","I"); 361 pSettings->ClipProperties.uiAudioBitrate = pEnv->GetIntField(object,fid); 362 M4OSA_TRACE1_1("audioBitrate = %d",pSettings->ClipProperties.uiAudioBitrate); 363 364 fid = pEnv->GetFieldID(clazz,"audioChannels","I"); 365 pSettings->ClipProperties.uiNbChannels = pEnv->GetIntField(object,fid); 366 M4OSA_TRACE1_1("audioChannels = %d",pSettings->ClipProperties.uiNbChannels); 367 368 fid = pEnv->GetFieldID(clazz,"audioSamplingFrequency","I"); 369 pSettings->ClipProperties.uiSamplingFrequency = pEnv->GetIntField(object,fid); 370 M4OSA_TRACE1_1("audioSamplingFrequency = %d", 371 pSettings->ClipProperties.uiSamplingFrequency); 372 373 fid = pEnv->GetFieldID(clazz,"audioVolumeValue","I"); 374 pSettings->ClipProperties.uiClipAudioVolumePercentage = 375 pEnv->GetIntField(object,fid); 376 M4OSA_TRACE1_1("audioVolumeValue = %d", 377 pSettings->ClipProperties.uiClipAudioVolumePercentage); 378 379 fid = pEnv->GetFieldID(clazz,"videoRotation","I"); 380 pSettings->ClipProperties.videoRotationDegrees = 381 pEnv->GetIntField(object,fid); 382 M4OSA_TRACE1_1("videoRotation = %d", 383 pSettings->ClipProperties.videoRotationDegrees); 384 } 385 386 static void jniPreviewProgressCallback (void* cookie, M4OSA_UInt32 msgType, 387 void *argc) 388 { 389 ManualEditContext *pContext = (ManualEditContext *)cookie; 390 JNIEnv* pEnv = NULL; 391 bool isFinished = false; 392 int currentMs = 0; 393 int error = M4NO_ERROR; 394 bool isUpdateOverlay = false; 395 int overlayEffectIndex; 396 char *extPos; 397 bool isSendProgress = true; 398 jstring tmpFileName; 399 VideoEditorCurretEditInfo *pCurrEditInfo; 400 401 // Attach the current thread. 402 pContext->pVM->AttachCurrentThread(&pEnv, NULL); 403 switch(msgType) 404 { 405 case MSG_TYPE_PROGRESS_INDICATION: 406 currentMs = *(int*)argc; 407 break; 408 case MSG_TYPE_PLAYER_ERROR: 409 currentMs = -1; 410 error = *(int*)argc; 411 break; 412 case MSG_TYPE_PREVIEW_END: 413 isFinished = true; 414 break; 415 case MSG_TYPE_OVERLAY_UPDATE: 416 { 417 int overlayFileNameLen = 0; 418 isSendProgress = false; 419 pContext->mIsUpdateOverlay = true; 420 pCurrEditInfo = (VideoEditorCurretEditInfo*)argc; 421 overlayEffectIndex = pCurrEditInfo->overlaySettingsIndex; 422 LOGV("MSG_TYPE_OVERLAY_UPDATE"); 423 424 if (pContext->mOverlayFileName != NULL) { 425 free(pContext->mOverlayFileName); 426 pContext->mOverlayFileName = NULL; 427 } 428 429 overlayFileNameLen = 430 strlen((const char*)pContext->pEditSettings->Effects[overlayEffectIndex].xVSS.pFramingFilePath); 431 432 pContext->mOverlayFileName = 433 (char*)M4OSA_32bitAlignedMalloc(overlayFileNameLen+1, 434 M4VS, (M4OSA_Char*)"videoEdito JNI overlayFile"); 435 if (pContext->mOverlayFileName != NULL) { 436 strncpy (pContext->mOverlayFileName, 437 (const char*)pContext->pEditSettings->\ 438 Effects[overlayEffectIndex].xVSS.pFramingFilePath, overlayFileNameLen); 439 //Change the name to png file 440 extPos = strstr(pContext->mOverlayFileName, ".rgb"); 441 if (extPos != NULL) { 442 *extPos = '\0'; 443 } else { 444 LOGE("ERROR the overlay file is incorrect"); 445 } 446 447 strcat(pContext->mOverlayFileName, ".png"); 448 LOGV("Conv string is %s", pContext->mOverlayFileName); 449 LOGV("Current Clip index = %d", pCurrEditInfo->clipIndex); 450 451 pContext->mOverlayRenderingMode = pContext->pEditSettings->\ 452 pClipList[pCurrEditInfo->clipIndex]->xVSS.MediaRendering; 453 LOGV("rendering mode %d ", pContext->mOverlayRenderingMode); 454 455 } 456 457 break; 458 } 459 460 case MSG_TYPE_OVERLAY_CLEAR: 461 isSendProgress = false; 462 if (pContext->mOverlayFileName != NULL) { 463 free(pContext->mOverlayFileName); 464 pContext->mOverlayFileName = NULL; 465 } 466 467 LOGV("MSG_TYPE_OVERLAY_CLEAR"); 468 //argc is not used 469 pContext->mIsUpdateOverlay = true; 470 break; 471 default: 472 break; 473 } 474 475 if (isSendProgress) { 476 tmpFileName = pEnv->NewStringUTF(pContext->mOverlayFileName); 477 pEnv->CallVoidMethod(pContext->engine, 478 pContext->onPreviewProgressUpdateMethodId, 479 currentMs,isFinished, pContext->mIsUpdateOverlay, 480 tmpFileName, pContext->mOverlayRenderingMode, error); 481 482 if (pContext->mIsUpdateOverlay) { 483 pContext->mIsUpdateOverlay = false; 484 } 485 486 if (tmpFileName) { 487 pEnv->DeleteLocalRef(tmpFileName); 488 } 489 } 490 491 // Detach the current thread. 492 pContext->pVM->DetachCurrentThread(); 493 494 } 495 static M4OSA_ERR checkClipVideoProfileAndLevel(M4DECODER_VideoDecoders *pDecoders, 496 M4OSA_Int32 format, M4OSA_UInt32 profile, M4OSA_UInt32 level){ 497 498 M4OSA_Int32 codec = 0; 499 M4OSA_Bool foundCodec = M4OSA_FALSE; 500 M4OSA_ERR result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE; 501 M4OSA_Bool foundProfile = M4OSA_FALSE; 502 LOGV("checkClipVideoProfileAndLevel format %d profile;%d level:0x%x", 503 format, profile, level); 504 505 switch (format) { 506 case M4VIDEOEDITING_kH263: 507 codec = M4DA_StreamTypeVideoH263; 508 break; 509 case M4VIDEOEDITING_kH264: 510 codec = M4DA_StreamTypeVideoMpeg4Avc; 511 break; 512 case M4VIDEOEDITING_kMPEG4: 513 codec = M4DA_StreamTypeVideoMpeg4; 514 break; 515 case M4VIDEOEDITING_kNoneVideo: 516 case M4VIDEOEDITING_kNullVideo: 517 case M4VIDEOEDITING_kUnsupportedVideo: 518 // For these case we do not check the profile and level 519 return M4NO_ERROR; 520 default : 521 LOGE("checkClipVideoProfileAndLevel unsupport Video format %ld", format); 522 break; 523 } 524 525 if (pDecoders != M4OSA_NULL && pDecoders->decoderNumber > 0) { 526 VideoDecoder *pVideoDecoder = pDecoders->decoder; 527 for(size_t k =0; k < pDecoders->decoderNumber; k++) { 528 if (pVideoDecoder != M4OSA_NULL) { 529 if (pVideoDecoder->codec == codec) { 530 foundCodec = M4OSA_TRUE; 531 break; 532 } 533 } 534 pVideoDecoder++; 535 } 536 537 if (foundCodec) { 538 VideoComponentCapabilities* pComponent = pVideoDecoder->component; 539 for (size_t i = 0; i < pVideoDecoder->componentNumber; i++) { 540 if (pComponent != M4OSA_NULL) { 541 VideoProfileLevel *pProfileLevel = pComponent->profileLevel; 542 for (size_t j =0; j < pComponent->profileNumber; j++) { 543 // Check the profile and level 544 if (pProfileLevel != M4OSA_NULL) { 545 if (profile == pProfileLevel->mProfile) { 546 foundProfile = M4OSA_TRUE; 547 548 if (level <= pProfileLevel->mLevel) { 549 return M4NO_ERROR; 550 } 551 } else { 552 foundProfile = M4OSA_FALSE; 553 } 554 } 555 pProfileLevel++; 556 } 557 } 558 pComponent++; 559 } 560 } 561 } 562 563 if (foundProfile) { 564 result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_LEVEL; 565 } else { 566 result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE; 567 } 568 569 return result; 570 } 571 static int videoEditor_stopPreview(JNIEnv* pEnv, 572 jobject thiz) 573 { 574 ManualEditContext* pContext = M4OSA_NULL; 575 bool needToBeLoaded = true; 576 M4OSA_UInt32 lastProgressTimeMs = 0; 577 578 // Get the context. 579 pContext = 580 (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz); 581 582 // Make sure that the context was set. 583 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 584 (M4OSA_NULL == pContext), 585 "not initialized"); 586 lastProgressTimeMs = pContext->mPreviewController->stopPreview(); 587 588 if (pContext->mOverlayFileName != NULL) { 589 free(pContext->mOverlayFileName); 590 pContext->mOverlayFileName = NULL; 591 } 592 593 return lastProgressTimeMs; 594 } 595 596 static void videoEditor_clearSurface(JNIEnv* pEnv, 597 jobject thiz, 598 jobject surface) 599 { 600 bool needToBeLoaded = true; 601 M4OSA_ERR result = M4NO_ERROR; 602 VideoEditor_renderPreviewFrameStr frameStr; 603 const char* pMessage = NULL; 604 // Let the size be QVGA 605 int width = 320; 606 int height = 240; 607 ManualEditContext* pContext = M4OSA_NULL; 608 609 // Get the context. 610 pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz); 611 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, 612 "VIDEO_EDITOR","pContext = 0x%x",pContext); 613 614 // Make sure that the context was set. 615 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 616 (M4OSA_NULL == pContext), 617 "not initialized"); 618 619 // Make sure that the context was set. 620 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 621 (M4OSA_NULL == pContext->mPreviewController), 622 "not initialized"); 623 624 // Validate the surface parameter. 625 videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv, 626 (NULL == surface), 627 "surface is null"); 628 629 jclass surfaceClass = pEnv->FindClass("android/view/Surface"); 630 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 631 (M4OSA_NULL == surfaceClass), 632 "not initialized"); 633 634 jfieldID surface_native = 635 pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I"); 636 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 637 (M4OSA_NULL == surface_native), 638 "not initialized"); 639 640 Surface* const p = (Surface*)pEnv->GetIntField(surface, surface_native); 641 sp<Surface> previewSurface = sp<Surface>(p); 642 // Validate the mSurface's mNativeSurface field 643 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 644 (NULL == previewSurface.get()), 645 "mNativeSurface is null"); 646 647 frameStr.pBuffer = M4OSA_NULL; 648 frameStr.timeMs = 0; 649 frameStr.uiSurfaceWidth = width; 650 frameStr.uiSurfaceHeight = height; 651 frameStr.uiFrameWidth = width; 652 frameStr.uiFrameHeight = height; 653 frameStr.bApplyEffect = M4OSA_FALSE; 654 frameStr.clipBeginCutTime = 0; 655 frameStr.clipEndCutTime = 0; 656 657 result = pContext->mPreviewController->clearSurface(previewSurface, 658 &frameStr); 659 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 660 (M4NO_ERROR != result), result); 661 662 } 663 664 static int videoEditor_renderPreviewFrame(JNIEnv* pEnv, 665 jobject thiz, 666 jobject mSurface, 667 jlong fromMs, 668 jint surfaceWidth, 669 jint surfaceHeight ) 670 { 671 bool needToBeLoaded = true; 672 M4OSA_ERR result = M4NO_ERROR; 673 M4OSA_UInt32 timeMs = (M4OSA_UInt32)fromMs; 674 M4OSA_UInt32 i=0,tnTimeMs = 0, framesizeYuv =0; 675 M4VIFI_UInt8 *pixelArray = M4OSA_NULL; 676 M4OSA_UInt32 iCurrentClipIndex = 0, uiNumberOfClipsInStoryBoard =0, 677 uiClipDuration = 0, uiTotalClipDuration = 0, 678 iIncrementedDuration = 0; 679 VideoEditor_renderPreviewFrameStr frameStr; 680 M4OSA_Context tnContext = M4OSA_NULL; 681 const char* pMessage = NULL; 682 M4VIFI_ImagePlane *yuvPlane = NULL; 683 VideoEditorCurretEditInfo currEditInfo; 684 685 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, 686 "VIDEO_EDITOR", "surfaceWidth = %d",surfaceWidth); 687 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, 688 "VIDEO_EDITOR", "surfaceHeight = %d",surfaceHeight); 689 ManualEditContext* pContext = M4OSA_NULL; 690 // Get the context. 691 pContext = 692 (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz); 693 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, 694 "VIDEO_EDITOR","pContext = 0x%x",pContext); 695 696 // Make sure that the context was set. 697 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 698 (M4OSA_NULL == pContext), 699 "not initialized"); 700 701 // Make sure that the context was set. 702 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 703 (M4OSA_NULL == pContext->mPreviewController), 704 "not initialized"); 705 706 // Validate the mSurface parameter. 707 videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv, 708 (NULL == mSurface), 709 "mSurface is null"); 710 jclass surfaceClass = pEnv->FindClass("android/view/Surface"); 711 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 712 (M4OSA_NULL == surfaceClass), 713 "not initialized"); 714 715 jfieldID surface_native = 716 pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I"); 717 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 718 (M4OSA_NULL == surface_native), 719 "not initialized"); 720 721 Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native); 722 sp<Surface> previewSurface = sp<Surface>(p); 723 // Validate the mSurface's mNativeSurface field 724 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 725 (NULL == previewSurface.get()), 726 "mNativeSurface is null"); 727 728 /* Determine the total number of clips, total duration*/ 729 uiNumberOfClipsInStoryBoard = pContext->pEditSettings->uiClipNumber; 730 731 for (i = 0; i < uiNumberOfClipsInStoryBoard; i++) { 732 uiClipDuration = pContext->pEditSettings->pClipList[i]->uiEndCutTime - 733 pContext->pEditSettings->pClipList[i]->uiBeginCutTime; 734 uiTotalClipDuration += uiClipDuration; 735 } 736 737 /* determine the clip whose thumbnail needs to be rendered*/ 738 if (timeMs == 0) { 739 iCurrentClipIndex = 0; 740 i=0; 741 } else { 742 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 743 "videoEditor_renderPreviewFrame() timeMs=%d", timeMs); 744 745 if (timeMs > uiTotalClipDuration) { 746 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 747 "videoEditor_renderPreviewFrame() timeMs > uiTotalClipDuration"); 748 pMessage = videoEditJava_getErrorName(M4ERR_PARAMETER); 749 jniThrowException(pEnv, "java/lang/IllegalArgumentException", pMessage); 750 return -1; 751 } 752 753 for (i = 0; i < uiNumberOfClipsInStoryBoard; i++) { 754 if (timeMs <= (iIncrementedDuration + 755 (pContext->pEditSettings->pClipList[i]->uiEndCutTime - 756 pContext->pEditSettings->pClipList[i]->uiBeginCutTime))) 757 { 758 iCurrentClipIndex = i; 759 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 760 "videoEditor_renderPreviewFrame() iCurrentClipIndex=%d for timeMs=%d", 761 iCurrentClipIndex, timeMs); 762 break; 763 } 764 else { 765 iIncrementedDuration = iIncrementedDuration + 766 (pContext->pEditSettings->pClipList[i]->uiEndCutTime - 767 pContext->pEditSettings->pClipList[i]->uiBeginCutTime); 768 } 769 } 770 } 771 /* If timestamp is beyond story board duration, return*/ 772 if (i >= uiNumberOfClipsInStoryBoard) { 773 if (timeMs == iIncrementedDuration) { 774 iCurrentClipIndex = i-1; 775 } else { 776 return -1; 777 } 778 } 779 780 /*+ Handle the image files here */ 781 if (pContext->pEditSettings->pClipList[iCurrentClipIndex]->FileType == 782 /*M4VIDEOEDITING_kFileType_JPG*/ M4VIDEOEDITING_kFileType_ARGB8888 ) { 783 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", " iCurrentClipIndex %d ", iCurrentClipIndex); 784 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 785 " Height = %d", 786 pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoHeight); 787 788 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 789 " Width = %d", 790 pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoWidth); 791 792 LvGetImageThumbNail((const char *)pContext->pEditSettings->\ 793 pClipList[iCurrentClipIndex]->pFile, 794 pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoHeight, 795 pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoWidth, 796 (M4OSA_Void **)&frameStr.pBuffer); 797 tnTimeMs = (M4OSA_UInt32)timeMs; 798 799 frameStr.videoRotationDegree = 0; 800 } else { 801 /* Handle 3gp/mp4 Clips here */ 802 /* get thumbnail*/ 803 result = ThumbnailOpen(&tnContext, 804 (const M4OSA_Char*)pContext->pEditSettings->\ 805 pClipList[iCurrentClipIndex]->pFile, M4OSA_TRUE); 806 if (result != M4NO_ERROR || tnContext == M4OSA_NULL) { 807 return -1; 808 } 809 810 /* timeMs is relative to storyboard; in this api it shud be relative to this clip */ 811 if ((i >= uiNumberOfClipsInStoryBoard) && 812 (timeMs == iIncrementedDuration)) { 813 tnTimeMs = pContext->pEditSettings->\ 814 pClipList[iCurrentClipIndex]->uiEndCutTime; 815 } else { 816 tnTimeMs = pContext->pEditSettings->\ 817 pClipList[iCurrentClipIndex]->uiBeginCutTime 818 + (timeMs - iIncrementedDuration); 819 } 820 821 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", 822 "video width = %d",pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 823 ClipProperties.uiVideoWidth); 824 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", 825 "video height = %d",pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 826 ClipProperties.uiVideoHeight); 827 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", 828 "current clip index = %d",iCurrentClipIndex); 829 830 M4OSA_UInt32 width = pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 831 ClipProperties.uiVideoWidth; 832 M4OSA_UInt32 height = pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 833 ClipProperties.uiVideoHeight; 834 835 framesizeYuv = width * height * 1.5; 836 837 pixelArray = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(framesizeYuv, M4VS, 838 (M4OSA_Char*)"videoEditor pixelArray"); 839 if (pixelArray == M4OSA_NULL) { 840 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 841 "videoEditor_renderPreviewFrame() malloc error"); 842 ThumbnailClose(tnContext); 843 pMessage = videoEditJava_getErrorName(M4ERR_ALLOC); 844 jniThrowException(pEnv, "java/lang/RuntimeException", pMessage); 845 return -1; 846 } 847 848 result = ThumbnailGetPixels16(tnContext, (M4OSA_Int16 *)pixelArray, 849 pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 850 ClipProperties.uiVideoWidth, 851 pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 852 ClipProperties.uiVideoHeight, 853 &tnTimeMs, 0); 854 if (result != M4NO_ERROR) { 855 free(pixelArray); 856 ThumbnailClose(tnContext); 857 return -1; 858 } 859 860 ThumbnailClose(tnContext); 861 tnContext = M4OSA_NULL; 862 863 #ifdef DUMPTOFILE 864 { 865 M4OSA_Context fileContext; 866 M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/FirstRGB565.raw"; 867 remove((const char *)fileName); 868 M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\ 869 M4OSA_kFileWrite|M4OSA_kFileCreate); 870 M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) pixelArray, 871 framesizeYuv); 872 M4OSA_fileWriteClose(fileContext); 873 } 874 #endif 875 876 /** 877 * Allocate output YUV planes 878 */ 879 yuvPlane = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane), M4VS, 880 (M4OSA_Char*)"videoEditor_renderPreviewFrame Output plane YUV"); 881 if (yuvPlane == M4OSA_NULL) { 882 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 883 "videoEditor_renderPreviewFrame() malloc error for yuv plane"); 884 free(pixelArray); 885 pMessage = videoEditJava_getErrorName(M4ERR_ALLOC); 886 jniThrowException(pEnv, "java/lang/RuntimeException", pMessage); 887 return -1; 888 } 889 890 yuvPlane[0].u_width = width; 891 yuvPlane[0].u_height = height; 892 yuvPlane[0].u_topleft = 0; 893 yuvPlane[0].u_stride = width; 894 yuvPlane[0].pac_data = (M4VIFI_UInt8*)pixelArray; 895 896 yuvPlane[1].u_width = width>>1; 897 yuvPlane[1].u_height = height>>1; 898 yuvPlane[1].u_topleft = 0; 899 yuvPlane[1].u_stride = width>>1; 900 yuvPlane[1].pac_data = yuvPlane[0].pac_data 901 + yuvPlane[0].u_width * yuvPlane[0].u_height; 902 yuvPlane[2].u_width = (width)>>1; 903 yuvPlane[2].u_height = (height)>>1; 904 yuvPlane[2].u_topleft = 0; 905 yuvPlane[2].u_stride = (width)>>1; 906 yuvPlane[2].pac_data = yuvPlane[1].pac_data 907 + yuvPlane[1].u_width * yuvPlane[1].u_height; 908 909 #ifdef DUMPTOFILE 910 { 911 M4OSA_Context fileContext; 912 M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/ConvertedYuv.yuv"; 913 remove((const char *)fileName); 914 M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\ 915 M4OSA_kFileWrite|M4OSA_kFileCreate); 916 M4OSA_fileWriteData(fileContext, 917 (M4OSA_MemAddr8) yuvPlane[0].pac_data, framesizeYuv); 918 M4OSA_fileWriteClose(fileContext); 919 } 920 #endif 921 922 /* Fill up the render structure*/ 923 frameStr.pBuffer = (M4OSA_Void*)yuvPlane[0].pac_data; 924 925 frameStr.videoRotationDegree = pContext->pEditSettings->\ 926 pClipList[iCurrentClipIndex]->ClipProperties.videoRotationDegrees; 927 } 928 929 frameStr.timeMs = timeMs; /* timestamp on storyboard*/ 930 frameStr.uiSurfaceWidth = 931 pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 932 ClipProperties.uiVideoWidth; 933 frameStr.uiSurfaceHeight = 934 pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 935 ClipProperties.uiVideoHeight; 936 frameStr.uiFrameWidth = 937 pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 938 ClipProperties.uiVideoWidth; 939 frameStr.uiFrameHeight = 940 pContext->pEditSettings->pClipList[iCurrentClipIndex]->\ 941 ClipProperties.uiVideoHeight; 942 if (pContext->pEditSettings->nbEffects > 0) { 943 frameStr.bApplyEffect = M4OSA_TRUE; 944 } else { 945 frameStr.bApplyEffect = M4OSA_FALSE; 946 } 947 frameStr.clipBeginCutTime = iIncrementedDuration; 948 frameStr.clipEndCutTime = 949 iIncrementedDuration + 950 (pContext->pEditSettings->pClipList[iCurrentClipIndex]->uiEndCutTime -\ 951 pContext->pEditSettings->pClipList[iCurrentClipIndex]->uiBeginCutTime); 952 953 pContext->mPreviewController->setPreviewFrameRenderingMode( 954 pContext->pEditSettings->\ 955 pClipList[iCurrentClipIndex]->xVSS.MediaRendering, 956 pContext->pEditSettings->xVSS.outputVideoSize); 957 result = pContext->mPreviewController->renderPreviewFrame(previewSurface, 958 &frameStr, &currEditInfo); 959 960 if (currEditInfo.overlaySettingsIndex != -1) { 961 char tmpOverlayFilename[100]; 962 char *extPos = NULL; 963 jstring tmpOverlayString; 964 int tmpRenderingMode = 0; 965 966 strncpy (tmpOverlayFilename, 967 (const char*)pContext->pEditSettings->Effects[currEditInfo.overlaySettingsIndex].xVSS.pFramingFilePath, 99); 968 969 //Change the name to png file 970 extPos = strstr(tmpOverlayFilename, ".rgb"); 971 if (extPos != NULL) { 972 *extPos = '\0'; 973 } else { 974 LOGE("ERROR the overlay file is incorrect"); 975 } 976 977 strcat(tmpOverlayFilename, ".png"); 978 979 tmpRenderingMode = pContext->pEditSettings->pClipList[iCurrentClipIndex]->xVSS.MediaRendering; 980 tmpOverlayString = pEnv->NewStringUTF(tmpOverlayFilename); 981 pEnv->CallVoidMethod(pContext->engine, 982 pContext->previewFrameEditInfoId, 983 tmpOverlayString, tmpRenderingMode); 984 985 } 986 987 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 988 (M4NO_ERROR != result), result); 989 990 free(frameStr.pBuffer); 991 if (pContext->pEditSettings->pClipList[iCurrentClipIndex]->FileType != 992 M4VIDEOEDITING_kFileType_ARGB8888) { 993 free(yuvPlane); 994 } 995 996 return tnTimeMs; 997 } 998 999 static int videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv, 1000 jobject thiz, 1001 jobject mSurface, 1002 jstring filePath, 1003 jint frameWidth, 1004 jint frameHeight, 1005 jint surfaceWidth, 1006 jint surfaceHeight, 1007 jlong fromMs) 1008 { 1009 bool needToBeLoaded = true; 1010 M4OSA_ERR result = M4NO_ERROR; 1011 M4OSA_UInt32 timeMs = (M4OSA_UInt32)fromMs; 1012 M4OSA_UInt32 framesizeYuv =0; 1013 M4VIFI_UInt8 *pixelArray = M4OSA_NULL; 1014 VideoEditor_renderPreviewFrameStr frameStr; 1015 M4OSA_Context tnContext = M4OSA_NULL; 1016 const char* pMessage = NULL; 1017 M4VIFI_ImagePlane yuvPlane[3], rgbPlane; 1018 1019 ManualEditContext* pContext = M4OSA_NULL; 1020 // Get the context. 1021 pContext = 1022 (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, 1023 pEnv, thiz); 1024 1025 // Make sure that the context was set. 1026 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1027 (M4OSA_NULL == pContext), 1028 "not initialized"); 1029 1030 // Make sure that the context was set. 1031 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1032 (M4OSA_NULL == pContext->mPreviewController), 1033 "not initialized"); 1034 1035 // Validate the mSurface parameter. 1036 videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv, 1037 (NULL == mSurface), 1038 "mSurface is null"); 1039 jclass surfaceClass = pEnv->FindClass("android/view/Surface"); 1040 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1041 (M4OSA_NULL == surfaceClass), 1042 "not initialized"); 1043 1044 jfieldID surface_native = 1045 pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I"); 1046 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1047 (M4OSA_NULL == surface_native), 1048 "not initialized"); 1049 1050 Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native); 1051 sp<Surface> previewSurface = sp<Surface>(p); 1052 1053 1054 const char *pString = pEnv->GetStringUTFChars(filePath, NULL); 1055 if (pString == M4OSA_NULL) { 1056 if (pEnv != NULL) { 1057 jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null"); 1058 } 1059 } 1060 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 1061 "videoEditor_renderMediaItemPreviewFrame() timeMs=%d", timeMs); 1062 /* get thumbnail*/ 1063 result = ThumbnailOpen(&tnContext,(const M4OSA_Char*)pString, M4OSA_TRUE); 1064 if (result != M4NO_ERROR || tnContext == M4OSA_NULL) { 1065 return timeMs; 1066 } 1067 1068 framesizeYuv = ((frameWidth)*(frameHeight)*1.5); 1069 1070 pixelArray = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(framesizeYuv, M4VS,\ 1071 (M4OSA_Char*)"videoEditor pixelArray"); 1072 if (pixelArray == M4OSA_NULL) { 1073 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 1074 "videoEditor_renderPreviewFrame() malloc error"); 1075 ThumbnailClose(tnContext); 1076 pMessage = videoEditJava_getErrorName(M4ERR_ALLOC); 1077 jniThrowException(pEnv, "java/lang/RuntimeException", pMessage); 1078 return timeMs; 1079 } 1080 1081 result = ThumbnailGetPixels16(tnContext, (M4OSA_Int16 *)pixelArray, 1082 frameWidth, 1083 frameHeight, &timeMs, 0); 1084 if (result != M4NO_ERROR) { 1085 free(pixelArray); 1086 ThumbnailClose(tnContext); 1087 return fromMs; 1088 } 1089 1090 #ifdef DUMPTOFILESYSTEM 1091 { 1092 M4OSA_Context fileContext; 1093 M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/FirstRGB565.rgb"; 1094 M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\ 1095 M4OSA_kFileWrite|M4OSA_kFileCreate); 1096 M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) pixelArray, 1097 framesizeRgb); 1098 M4OSA_fileWriteClose(fileContext); 1099 } 1100 #endif 1101 1102 yuvPlane[0].pac_data = (M4VIFI_UInt8*)pixelArray; 1103 yuvPlane[0].u_height = frameHeight; 1104 yuvPlane[0].u_width = frameWidth; 1105 yuvPlane[0].u_stride = yuvPlane[0].u_width; 1106 yuvPlane[0].u_topleft = 0; 1107 1108 yuvPlane[1].u_height = frameHeight/2; 1109 yuvPlane[1].u_width = frameWidth/2; 1110 yuvPlane[1].u_stride = yuvPlane[1].u_width; 1111 yuvPlane[1].u_topleft = 0; 1112 yuvPlane[1].pac_data = yuvPlane[0].pac_data 1113 + yuvPlane[0].u_width*yuvPlane[0].u_height; 1114 1115 yuvPlane[2].u_height = frameHeight/2; 1116 yuvPlane[2].u_width = frameWidth/2; 1117 yuvPlane[2].u_stride = yuvPlane[2].u_width; 1118 yuvPlane[2].u_topleft = 0; 1119 yuvPlane[2].pac_data = yuvPlane[0].pac_data 1120 + yuvPlane[0].u_width*yuvPlane[0].u_height + \ 1121 (yuvPlane[0].u_width/2)*(yuvPlane[0].u_height/2); 1122 #ifdef DUMPTOFILESYSTEM 1123 { 1124 M4OSA_Context fileContext; 1125 M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/ConvertedYuv.yuv"; 1126 M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\ 1127 M4OSA_kFileWrite|M4OSA_kFileCreate); 1128 M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) yuvPlane[0].pac_data, 1129 framesizeYuv); 1130 M4OSA_fileWriteClose(fileContext); 1131 } 1132 #endif 1133 1134 /* Fill up the render structure*/ 1135 frameStr.pBuffer = (M4OSA_Void*)yuvPlane[0].pac_data; 1136 frameStr.timeMs = timeMs; /* timestamp on storyboard*/ 1137 frameStr.uiSurfaceWidth = frameWidth; 1138 frameStr.uiSurfaceHeight = frameHeight; 1139 frameStr.uiFrameWidth = frameWidth; 1140 frameStr.uiFrameHeight = frameHeight; 1141 frameStr.bApplyEffect = M4OSA_FALSE; 1142 // clip begin cuttime and end cuttime set to 0 1143 // as its only required when effect needs to be applied while rendering 1144 frameStr.clipBeginCutTime = 0; 1145 frameStr.clipEndCutTime = 0; 1146 1147 /* pContext->mPreviewController->setPreviewFrameRenderingMode(M4xVSS_kBlackBorders, 1148 (M4VIDEOEDITING_VideoFrameSize)(M4VIDEOEDITING_kHD960+1));*/ 1149 result 1150 = pContext->mPreviewController->renderPreviewFrame(previewSurface,&frameStr, NULL); 1151 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1152 (M4NO_ERROR != result), result); 1153 1154 /* free the pixelArray and yuvPlane[0].pac_data */ 1155 free(yuvPlane[0].pac_data); 1156 1157 ThumbnailClose(tnContext); 1158 1159 if (pString != NULL) { 1160 pEnv->ReleaseStringUTFChars(filePath, pString); 1161 } 1162 1163 return timeMs; 1164 } 1165 1166 int videoEditor_generateAudioRawFile( JNIEnv* pEnv, 1167 jobject thiz, 1168 jstring infilePath, 1169 jstring pcmfilePath) 1170 { 1171 M4OSA_ERR result = M4NO_ERROR; 1172 bool loaded = true; 1173 ManualEditContext* pContext = M4OSA_NULL; 1174 1175 1176 1177 const char *pInputFile = pEnv->GetStringUTFChars(infilePath, NULL); 1178 if (pInputFile == M4OSA_NULL) { 1179 if (pEnv != NULL) { 1180 jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null"); 1181 } 1182 } 1183 1184 const char *pStringOutPCMFilePath = pEnv->GetStringUTFChars(pcmfilePath, NULL); 1185 if (pStringOutPCMFilePath == M4OSA_NULL) { 1186 if (pEnv != NULL) { 1187 jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null"); 1188 } 1189 } 1190 1191 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, 1192 "VIDEO_EDITOR", "videoEditor_generateAudioRawFile infilePath %s", 1193 pInputFile); 1194 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, 1195 "VIDEO_EDITOR", "videoEditor_generateAudioRawFile pcmfilePath %s", 1196 pStringOutPCMFilePath); 1197 // Get the context. 1198 pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz); 1199 1200 result = videoEditor_generateAudio( pEnv, pContext, (M4OSA_Char*)pInputFile, 1201 (M4OSA_Char*)pStringOutPCMFilePath); 1202 1203 if (pInputFile != NULL) { 1204 pEnv->ReleaseStringUTFChars(infilePath, pInputFile); 1205 } 1206 if (pStringOutPCMFilePath != NULL) { 1207 pEnv->ReleaseStringUTFChars(pcmfilePath, pStringOutPCMFilePath); 1208 } 1209 1210 return result; 1211 } 1212 1213 M4OSA_ERR videoEditor_generateAudio(JNIEnv* pEnv,ManualEditContext* pContext, 1214 M4OSA_Char* infilePath, 1215 M4OSA_Char* pcmfilePath ) 1216 { 1217 bool needToBeLoaded = true; 1218 M4OSA_ERR result = M4NO_ERROR; 1219 M4MCS_Context mcsContext = M4OSA_NULL; 1220 M4OSA_Char* pInputFile = M4OSA_NULL; 1221 M4OSA_Char* pOutputFile = M4OSA_NULL; 1222 M4OSA_Char* pTempPath = M4OSA_NULL; 1223 M4MCS_OutputParams* pOutputParams = M4OSA_NULL; 1224 M4MCS_EncodingParams* pEncodingParams = M4OSA_NULL; 1225 M4OSA_Int32 pInputFileType = 0; 1226 M4OSA_UInt8 threadProgress = 0; 1227 M4OSA_Char* pTemp3gpFilePath = M4OSA_NULL; 1228 1229 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_generateAudio()"); 1230 1231 videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv, 1232 (NULL == pContext), 1233 "ManualEditContext is null"); 1234 1235 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_init()"); 1236 1237 pOutputParams = (M4MCS_OutputParams *)M4OSA_32bitAlignedMalloc( 1238 sizeof(M4MCS_OutputParams),0x00, 1239 (M4OSA_Char *)"M4MCS_OutputParams"); 1240 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1241 (M4OSA_NULL == pOutputParams), 1242 "not initialized"); 1243 if (needToBeLoaded == false) { 1244 return M4ERR_ALLOC; 1245 } 1246 1247 pEncodingParams = (M4MCS_EncodingParams *)M4OSA_32bitAlignedMalloc( 1248 sizeof(M4MCS_EncodingParams),0x00, 1249 (M4OSA_Char *)"M4MCS_EncodingParams"); 1250 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1251 (M4OSA_NULL == pEncodingParams), 1252 "not initialized"); 1253 if (needToBeLoaded == false) { 1254 free(pEncodingParams); 1255 pEncodingParams = M4OSA_NULL; 1256 return M4ERR_ALLOC; 1257 } 1258 1259 // Initialize the MCS library. 1260 result = M4MCS_init(&mcsContext, pContext->initParams.pFileReadPtr, 1261 pContext->initParams.pFileWritePtr); 1262 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,\ 1263 (M4NO_ERROR != result), result); 1264 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1265 (M4OSA_NULL == mcsContext), 1266 "not initialized"); 1267 if(needToBeLoaded == false) { 1268 free(pOutputParams); 1269 pOutputParams = M4OSA_NULL; 1270 free(pEncodingParams); 1271 pEncodingParams = M4OSA_NULL; 1272 return result; 1273 } 1274 1275 // generate the path for temp 3gp output file 1276 pTemp3gpFilePath = (M4OSA_Char*) M4OSA_32bitAlignedMalloc ( 1277 (strlen((const char*)pContext->initParams.pTempPath) 1278 + strlen((const char*)TEMP_MCS_OUT_FILE_PATH)) + 1 /* for null termination */ , 0x0, 1279 (M4OSA_Char*)"Malloc for temp 3gp file"); 1280 if (pTemp3gpFilePath != M4OSA_NULL) 1281 { 1282 memset((void *)pTemp3gpFilePath ,0, 1283 strlen((const char*)pContext->initParams.pTempPath) 1284 + strlen((const char*)TEMP_MCS_OUT_FILE_PATH) + 1); 1285 strncat((char *)pTemp3gpFilePath, 1286 (const char *)pContext->initParams.pTempPath , 1287 (size_t) ((M4OSA_Char*)pContext->initParams.pTempPath)); 1288 strncat((char *)pTemp3gpFilePath , (const char *)TEMP_MCS_OUT_FILE_PATH, 1289 (size_t)strlen ((const char*)TEMP_MCS_OUT_FILE_PATH)); 1290 } 1291 else { 1292 M4MCS_abort(mcsContext); 1293 free(pOutputParams); 1294 pOutputParams = M4OSA_NULL; 1295 free(pEncodingParams); 1296 pEncodingParams = M4OSA_NULL; 1297 return M4ERR_ALLOC; 1298 } 1299 1300 pInputFile = (M4OSA_Char *) infilePath; //pContext->mAudioSettings->pFile; 1301 //Delete this file later 1302 pOutputFile = (M4OSA_Char *) pTemp3gpFilePath; 1303 // Temp folder path for VSS use = ProjectPath 1304 pTempPath = (M4OSA_Char *) pContext->initParams.pTempPath; 1305 pInputFileType = (M4VIDEOEDITING_FileType)pContext->mAudioSettings->fileType; 1306 1307 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "TEMP_MCS_OUT_FILE_PATH len %d", 1308 strlen ((const char*)TEMP_MCS_OUT_FILE_PATH)); 1309 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "pTemp3gpFilePath %s", 1310 pOutputFile); 1311 1312 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_open()"); 1313 1314 result = M4MCS_open(mcsContext, pInputFile, 1315 (M4VIDEOEDITING_FileType)pInputFileType, 1316 pOutputFile, pTempPath); 1317 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1318 (M4NO_ERROR != result), result); 1319 if(needToBeLoaded == false) { 1320 free(pTemp3gpFilePath); 1321 pTemp3gpFilePath = M4OSA_NULL; 1322 M4MCS_abort(mcsContext); 1323 free(pOutputParams); 1324 pOutputParams = M4OSA_NULL; 1325 free(pEncodingParams); 1326 pEncodingParams = M4OSA_NULL; 1327 return result; 1328 } 1329 1330 pOutputParams->OutputFileType 1331 = (M4VIDEOEDITING_FileType)M4VIDEOEDITING_kFileType_3GPP; 1332 // Set the video format. 1333 pOutputParams->OutputVideoFormat = 1334 (M4VIDEOEDITING_VideoFormat)M4VIDEOEDITING_kNoneVideo;//M4VIDEOEDITING_kNoneVideo; 1335 pOutputParams->outputVideoProfile = 1; 1336 pOutputParams->outputVideoLevel = 1; 1337 // Set the frame size. 1338 pOutputParams->OutputVideoFrameSize 1339 = (M4VIDEOEDITING_VideoFrameSize)M4VIDEOEDITING_kQCIF; 1340 // Set the frame rate. 1341 pOutputParams->OutputVideoFrameRate 1342 = (M4VIDEOEDITING_VideoFramerate)M4VIDEOEDITING_k5_FPS; 1343 1344 // Set the audio format. 1345 pOutputParams->OutputAudioFormat 1346 = (M4VIDEOEDITING_AudioFormat)M4VIDEOEDITING_kAAC; 1347 // Set the audio sampling frequency. 1348 pOutputParams->OutputAudioSamplingFrequency = 1349 (M4VIDEOEDITING_AudioSamplingFrequency)M4VIDEOEDITING_k32000_ASF; 1350 // Set the audio mono. 1351 pOutputParams->bAudioMono = false; 1352 // Set the pcm file; null for now. 1353 pOutputParams->pOutputPCMfile = (M4OSA_Char *)pcmfilePath; 1354 //(M4OSA_Char *)"/sdcard/Output/AudioPcm.pcm"; 1355 // Set the audio sampling frequency. 1356 pOutputParams->MediaRendering = (M4MCS_MediaRendering)M4MCS_kCropping; 1357 // new params after integrating MCS 2.0 1358 // Set the number of audio effects; 0 for now. 1359 pOutputParams->nbEffects = 0; 1360 // Set the audio effect; null for now. 1361 pOutputParams->pEffects = NULL; 1362 // Set the audio effect; null for now. 1363 pOutputParams->bDiscardExif = M4OSA_FALSE; 1364 // Set the audio effect; null for now. 1365 pOutputParams->bAdjustOrientation = M4OSA_FALSE; 1366 1367 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_setOutputParams()"); 1368 result = M4MCS_setOutputParams(mcsContext, pOutputParams); 1369 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1370 (M4NO_ERROR != result), result); 1371 if (needToBeLoaded == false) { 1372 free(pTemp3gpFilePath); 1373 pTemp3gpFilePath = M4OSA_NULL; 1374 M4MCS_abort(mcsContext); 1375 free(pOutputParams); 1376 pOutputParams = M4OSA_NULL; 1377 free(pEncodingParams); 1378 pEncodingParams = M4OSA_NULL; 1379 return result; 1380 } 1381 // Set the video bitrate. 1382 pEncodingParams->OutputVideoBitrate = 1383 (M4VIDEOEDITING_Bitrate)M4VIDEOEDITING_kUndefinedBitrate; 1384 // Set the audio bitrate. 1385 pEncodingParams->OutputAudioBitrate 1386 = (M4VIDEOEDITING_Bitrate)M4VIDEOEDITING_k128_KBPS; 1387 // Set the end cut time in milliseconds. 1388 pEncodingParams->BeginCutTime = 0; 1389 // Set the end cut time in milliseconds. 1390 pEncodingParams->EndCutTime = 0; 1391 // Set the output file size in bytes. 1392 pEncodingParams->OutputFileSize = 0; 1393 // Set video time scale. 1394 pEncodingParams->OutputVideoTimescale = 0; 1395 1396 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 1397 "M4MCS_setEncodingParams()"); 1398 result = M4MCS_setEncodingParams(mcsContext, pEncodingParams); 1399 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1400 (M4NO_ERROR != result), result); 1401 if (needToBeLoaded == false) { 1402 free(pTemp3gpFilePath); 1403 pTemp3gpFilePath = M4OSA_NULL; 1404 M4MCS_abort(mcsContext); 1405 free(pOutputParams); 1406 pOutputParams = M4OSA_NULL; 1407 free(pEncodingParams); 1408 pEncodingParams = M4OSA_NULL; 1409 return result; 1410 } 1411 1412 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 1413 "M4MCS_checkParamsAndStart()"); 1414 result = M4MCS_checkParamsAndStart(mcsContext); 1415 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1416 (M4NO_ERROR != result), result); 1417 if (needToBeLoaded == false) { 1418 free(pTemp3gpFilePath); 1419 pTemp3gpFilePath = M4OSA_NULL; 1420 M4MCS_abort(mcsContext); 1421 free(pOutputParams); 1422 pOutputParams = M4OSA_NULL; 1423 free(pEncodingParams); 1424 pEncodingParams = M4OSA_NULL; 1425 return result; 1426 } 1427 1428 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_step()"); 1429 1430 /*+ PROGRESS CB */ 1431 M4OSA_UInt8 curProgress = 0; 1432 int lastProgress = 0; 1433 1434 LOGV("LVME_generateAudio Current progress is =%d", curProgress); 1435 pEnv->CallVoidMethod(pContext->engine, 1436 pContext->onProgressUpdateMethodId, 1/*task status*/, 1437 curProgress/*progress*/); 1438 do { 1439 result = M4MCS_step(mcsContext, &curProgress); 1440 1441 if (result != M4NO_ERROR) { 1442 LOGV("LVME_generateAudio M4MCS_step returned 0x%x",result); 1443 1444 if (result == M4MCS_WAR_TRANSCODING_DONE) { 1445 LOGV("LVME_generateAudio MCS process ended"); 1446 1447 // Send a progress notification. 1448 curProgress = 100; 1449 pEnv->CallVoidMethod(pContext->engine, 1450 pContext->onProgressUpdateMethodId, 1/*task status*/, 1451 curProgress); 1452 LOGV("LVME_generateAudio Current progress is =%d", curProgress); 1453 } 1454 } else { 1455 // Send a progress notification if needed 1456 if (curProgress != lastProgress) { 1457 lastProgress = curProgress; 1458 pEnv->CallVoidMethod(pContext->engine, 1459 pContext->onProgressUpdateMethodId, 0/*task status*/, 1460 curProgress/*progress*/); 1461 LOGV("LVME_generateAudio Current progress is =%d",curProgress); 1462 } 1463 } 1464 } while (result == M4NO_ERROR); 1465 /*- PROGRESS CB */ 1466 1467 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1468 (M4MCS_WAR_TRANSCODING_DONE != result), result); 1469 if (needToBeLoaded == false) { 1470 free(pTemp3gpFilePath); 1471 pTemp3gpFilePath = M4OSA_NULL; 1472 M4MCS_abort(mcsContext); 1473 free(pOutputParams); 1474 pOutputParams = M4OSA_NULL; 1475 free(pEncodingParams); 1476 pEncodingParams = M4OSA_NULL; 1477 return result; 1478 } 1479 1480 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_abort()"); 1481 result = M4MCS_abort(mcsContext); 1482 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1483 (M4NO_ERROR != result), result); 1484 1485 //pContext->mAudioSettings->pFile = pOutputParams->pOutputPCMfile; 1486 remove((const char *) pTemp3gpFilePath); 1487 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_generateAudio() EXIT "); 1488 1489 if (pTemp3gpFilePath != M4OSA_NULL) { 1490 free(pTemp3gpFilePath); 1491 } 1492 if (pOutputParams != M4OSA_NULL) { 1493 free(pOutputParams); 1494 } 1495 if(pEncodingParams != M4OSA_NULL) { 1496 free(pEncodingParams); 1497 } 1498 return result; 1499 } 1500 1501 static int removeAlphafromRGB8888 ( 1502 M4OSA_Char* pFramingFilePath, 1503 M4xVSS_FramingStruct *pFramingCtx) 1504 { 1505 M4OSA_UInt32 frameSize_argb = (pFramingCtx->width * pFramingCtx->height * 4); // aRGB data 1506 M4OSA_Context lImageFileFp = M4OSA_NULL; 1507 M4OSA_ERR err = M4NO_ERROR; 1508 1509 LOGV("removeAlphafromRGB8888: width %d", pFramingCtx->width); 1510 1511 M4OSA_UInt8 *pTmpData = (M4OSA_UInt8*) M4OSA_32bitAlignedMalloc(frameSize_argb, M4VS, (M4OSA_Char*)"Image argb data"); 1512 if (pTmpData == M4OSA_NULL) { 1513 LOGE("Failed to allocate memory for Image clip"); 1514 return M4ERR_ALLOC; 1515 } 1516 1517 /** Read the argb data from the passed file. */ 1518 M4OSA_ERR lerr = M4OSA_fileReadOpen(&lImageFileFp, (M4OSA_Void *) pFramingFilePath, M4OSA_kFileRead); 1519 1520 1521 if ((lerr != M4NO_ERROR) || (lImageFileFp == M4OSA_NULL)) 1522 { 1523 LOGE("removeAlphafromRGB8888: Can not open the file "); 1524 free(pTmpData); 1525 return M4ERR_FILE_NOT_FOUND; 1526 } 1527 1528 1529 lerr = M4OSA_fileReadData(lImageFileFp, (M4OSA_MemAddr8)pTmpData, &frameSize_argb); 1530 if (lerr != M4NO_ERROR) 1531 { 1532 LOGE("removeAlphafromRGB8888: can not read the data "); 1533 M4OSA_fileReadClose(lImageFileFp); 1534 free(pTmpData); 1535 return lerr; 1536 } 1537 M4OSA_fileReadClose(lImageFileFp); 1538 1539 M4OSA_UInt32 frameSize = (pFramingCtx->width * pFramingCtx->height * 3); //Size of RGB 888 data. 1540 1541 pFramingCtx->FramingRgb = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc( 1542 sizeof(M4VIFI_ImagePlane), M4VS, (M4OSA_Char*)"Image clip RGB888 data"); 1543 pFramingCtx->FramingRgb->pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc( 1544 frameSize, M4VS, (M4OSA_Char*)"Image clip RGB888 data"); 1545 1546 if (pFramingCtx->FramingRgb == M4OSA_NULL) 1547 { 1548 LOGE("Failed to allocate memory for Image clip"); 1549 free(pTmpData); 1550 return M4ERR_ALLOC; 1551 } 1552 1553 /** Remove the alpha channel */ 1554 for (size_t i = 0, j = 0; i < frameSize_argb; i++) { 1555 if ((i % 4) == 0) continue; 1556 pFramingCtx->FramingRgb->pac_data[j] = pTmpData[i]; 1557 j++; 1558 } 1559 free(pTmpData); 1560 return M4NO_ERROR; 1561 } 1562 1563 static void 1564 videoEditor_populateSettings( 1565 JNIEnv* pEnv, 1566 jobject thiz, 1567 jobject settings, 1568 jobject object, 1569 jobject audioSettingObject) 1570 { 1571 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 1572 "videoEditor_populateSettings()"); 1573 1574 bool needToBeLoaded = true; 1575 ManualEditContext* pContext = M4OSA_NULL; 1576 M4OSA_ERR result = M4NO_ERROR; 1577 jstring strPath = M4OSA_NULL; 1578 jstring strPCMPath = M4OSA_NULL; 1579 jobjectArray propertiesClipsArray = M4OSA_NULL; 1580 jobject properties = M4OSA_NULL; 1581 jint* bitmapArray = M4OSA_NULL; 1582 jobjectArray effectSettingsArray = M4OSA_NULL; 1583 jobject effectSettings = M4OSA_NULL; 1584 jintArray pixelArray = M4OSA_NULL; 1585 int width = 0; 1586 int height = 0; 1587 int nbOverlays = 0; 1588 int i,j = 0; 1589 int *pOverlayIndex = M4OSA_NULL; 1590 M4OSA_Char* pTempChar = M4OSA_NULL; 1591 1592 // Add a code marker (the condition must always be true). 1593 ADD_CODE_MARKER_FUN(NULL != pEnv) 1594 1595 // Validate the settings parameter. 1596 videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv, 1597 (NULL == settings), 1598 "settings is null"); 1599 // Get the context. 1600 pContext = 1601 (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz); 1602 1603 // Make sure that the context was set. 1604 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1605 (M4OSA_NULL == pContext), 1606 "not initialized"); 1607 // Make sure that the context was set. 1608 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1609 (M4OSA_NULL == pContext->mPreviewController), 1610 "not initialized"); 1611 jclass mPreviewClipPropClazz = pEnv->FindClass(PREVIEW_PROPERTIES_CLASS_NAME); 1612 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1613 (M4OSA_NULL == mPreviewClipPropClazz), 1614 "not initialized"); 1615 1616 jfieldID fid = pEnv->GetFieldID(mPreviewClipPropClazz,"clipProperties", 1617 "[L"PROPERTIES_CLASS_NAME";" ); 1618 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1619 (M4OSA_NULL == fid), 1620 "not initialized"); 1621 1622 propertiesClipsArray = (jobjectArray)pEnv->GetObjectField(object, fid); 1623 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1624 (M4OSA_NULL == propertiesClipsArray), 1625 "not initialized"); 1626 1627 jclass engineClass = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME); 1628 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1629 (M4OSA_NULL == engineClass), 1630 "not initialized"); 1631 1632 pContext->onPreviewProgressUpdateMethodId = pEnv->GetMethodID(engineClass, 1633 "onPreviewProgressUpdate", "(IZZLjava/lang/String;II)V"); 1634 // Check if the context is valid (required because the context is dereferenced). 1635 if (needToBeLoaded) { 1636 // Make sure that we are in a correct state. 1637 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1638 (pContext->state != ManualEditState_INITIALIZED), 1639 "settings already loaded"); 1640 if (needToBeLoaded) { 1641 // Retrieve the edit settings. 1642 if (pContext->pEditSettings != M4OSA_NULL) { 1643 videoEditClasses_freeEditSettings(&pContext->pEditSettings); 1644 pContext->pEditSettings = M4OSA_NULL; 1645 } 1646 videoEditClasses_getEditSettings(&needToBeLoaded, pEnv, 1647 settings, &pContext->pEditSettings,false); 1648 } 1649 } 1650 1651 if (needToBeLoaded == false) { 1652 j = 0; 1653 while (j < pContext->pEditSettings->nbEffects) 1654 { 1655 if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) { 1656 if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer != M4OSA_NULL) { 1657 free(pContext->pEditSettings->\ 1658 Effects[j].xVSS.pFramingBuffer); 1659 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer = M4OSA_NULL; 1660 } 1661 } 1662 j++; 1663 } 1664 return; 1665 } 1666 1667 M4OSA_TRACE1_0("videoEditorC_getEditSettings done"); 1668 1669 pContext->previewFrameEditInfoId = pEnv->GetMethodID(engineClass, 1670 "previewFrameEditInfo", "(Ljava/lang/String;I)V"); 1671 1672 if ( pContext->pEditSettings != NULL ) 1673 { 1674 // Check if the edit settings could be retrieved. 1675 jclass mEditClazz = pEnv->FindClass(EDIT_SETTINGS_CLASS_NAME); 1676 if(mEditClazz == M4OSA_NULL) 1677 { 1678 M4OSA_TRACE1_0("cannot find object field for mEditClazz"); 1679 goto videoEditor_populateSettings_cleanup; 1680 } 1681 jclass mEffectsClazz = pEnv->FindClass(EFFECT_SETTINGS_CLASS_NAME); 1682 if(mEffectsClazz == M4OSA_NULL) 1683 { 1684 M4OSA_TRACE1_0("cannot find object field for mEffectsClazz"); 1685 goto videoEditor_populateSettings_cleanup; 1686 } 1687 fid = pEnv->GetFieldID(mEditClazz,"effectSettingsArray", "[L"EFFECT_SETTINGS_CLASS_NAME";" ); 1688 if(fid == M4OSA_NULL) 1689 { 1690 M4OSA_TRACE1_0("cannot find field for effectSettingsArray Array"); 1691 goto videoEditor_populateSettings_cleanup; 1692 } 1693 effectSettingsArray = (jobjectArray)pEnv->GetObjectField(settings, fid); 1694 if(effectSettingsArray == M4OSA_NULL) 1695 { 1696 M4OSA_TRACE1_0("cannot find object field for effectSettingsArray"); 1697 goto videoEditor_populateSettings_cleanup; 1698 } 1699 1700 //int overlayIndex[pContext->pEditSettings->nbEffects]; 1701 if (pContext->pEditSettings->nbEffects > 0) 1702 { 1703 pOverlayIndex 1704 = (int*) M4OSA_32bitAlignedMalloc(pContext->pEditSettings->nbEffects * sizeof(int), 0, 1705 (M4OSA_Char*)"pOverlayIndex"); 1706 if (pOverlayIndex == M4OSA_NULL) { 1707 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1708 M4OSA_TRUE, M4ERR_ALLOC); 1709 goto videoEditor_populateSettings_cleanup; 1710 } 1711 } 1712 1713 i = 0; 1714 j = 0; 1715 M4OSA_TRACE1_1("no of effects = %d",pContext->pEditSettings->nbEffects); 1716 while (j < pContext->pEditSettings->nbEffects) 1717 { 1718 if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) 1719 { 1720 pOverlayIndex[nbOverlays] = j; 1721 1722 M4xVSS_FramingStruct *aFramingCtx = M4OSA_NULL; 1723 aFramingCtx 1724 = (M4xVSS_FramingStruct*)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingStruct), M4VS, 1725 (M4OSA_Char*)"M4xVSS_internalDecodeGIF: Context of the framing effect"); 1726 if (aFramingCtx == M4OSA_NULL) 1727 { 1728 M4OSA_TRACE1_0("Allocation error in videoEditor_populateSettings"); 1729 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1730 M4OSA_TRUE, M4ERR_ALLOC); 1731 goto videoEditor_populateSettings_cleanup; 1732 } 1733 1734 aFramingCtx->pCurrent = M4OSA_NULL; /* Only used by the first element of the chain */ 1735 aFramingCtx->previousClipTime = -1; 1736 aFramingCtx->FramingYuv = M4OSA_NULL; 1737 aFramingCtx->FramingRgb = M4OSA_NULL; 1738 aFramingCtx->topleft_x 1739 = pContext->pEditSettings->Effects[j].xVSS.topleft_x; 1740 aFramingCtx->topleft_y 1741 = pContext->pEditSettings->Effects[j].xVSS.topleft_y; 1742 1743 1744 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF u_width %d", 1745 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width); 1746 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF u_height() %d", 1747 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height); 1748 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF rgbType() %d", 1749 pContext->pEditSettings->Effects[j].xVSS.rgbType); 1750 1751 aFramingCtx->width = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width; 1752 aFramingCtx->height = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height; 1753 1754 result = M4xVSS_internalConvertARGB888toYUV420_FrammingEffect(pContext->engineContext, 1755 &(pContext->pEditSettings->Effects[j]),aFramingCtx, 1756 pContext->pEditSettings->Effects[j].xVSS.framingScaledSize); 1757 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1758 (M4NO_ERROR != result), result); 1759 if (needToBeLoaded == false) { 1760 M4OSA_TRACE1_1("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect returned 0x%x", result); 1761 if (aFramingCtx != M4OSA_NULL) { 1762 free(aFramingCtx); 1763 aFramingCtx = M4OSA_NULL; 1764 } 1765 goto videoEditor_populateSettings_cleanup; 1766 } 1767 1768 //framing buffers are resized to fit the output video resolution. 1769 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width = 1770 aFramingCtx->FramingRgb->u_width; 1771 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height = 1772 aFramingCtx->FramingRgb->u_height; 1773 1774 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "A framing Context aFramingCtx->width = %d", 1775 aFramingCtx->FramingRgb->u_width); 1776 1777 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "A framing Context aFramingCtx->height = %d", 1778 aFramingCtx->FramingRgb->u_height); 1779 1780 1781 width = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width; 1782 height = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height; 1783 1784 //RGB 565 1785 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_stride = width * 2; 1786 1787 //for RGB565 1788 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_topleft = 0; 1789 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->pac_data = 1790 (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(width*height*2, 1791 0x00,(M4OSA_Char *)"pac_data buffer"); 1792 1793 if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->pac_data == M4OSA_NULL) { 1794 M4OSA_TRACE1_0("Failed to allocate memory for framing buffer"); 1795 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1796 M4OSA_TRUE, M4ERR_ALLOC); 1797 goto videoEditor_populateSettings_cleanup; 1798 } 1799 1800 memcpy((void *)&pContext->pEditSettings->\ 1801 Effects[j].xVSS.pFramingBuffer->\ 1802 pac_data[0],(void *)&aFramingCtx->FramingRgb->pac_data[0],(width*height*2)); 1803 1804 //As of now rgb type is 565 1805 pContext->pEditSettings->Effects[j].xVSS.rgbType = 1806 (M4VSS3GPP_RGBType) M4VSS3GPP_kRGB565; 1807 1808 if (aFramingCtx->FramingYuv != M4OSA_NULL ) 1809 { 1810 if (aFramingCtx->FramingYuv[0].pac_data != M4OSA_NULL) { 1811 free(aFramingCtx->FramingYuv[0].pac_data); 1812 aFramingCtx->FramingYuv[0].pac_data = M4OSA_NULL; 1813 } 1814 if (aFramingCtx->FramingYuv[1].pac_data != M4OSA_NULL) { 1815 free(aFramingCtx->FramingYuv[1].pac_data); 1816 aFramingCtx->FramingYuv[1].pac_data = M4OSA_NULL; 1817 } 1818 if (aFramingCtx->FramingYuv[2].pac_data != M4OSA_NULL) { 1819 free(aFramingCtx->FramingYuv[2].pac_data); 1820 aFramingCtx->FramingYuv[2].pac_data = M4OSA_NULL; 1821 } 1822 1823 free(aFramingCtx->FramingYuv); 1824 aFramingCtx->FramingYuv = M4OSA_NULL; 1825 } 1826 if (aFramingCtx->FramingRgb->pac_data != M4OSA_NULL) { 1827 free(aFramingCtx->FramingRgb->pac_data); 1828 aFramingCtx->FramingRgb->pac_data = M4OSA_NULL; 1829 } 1830 if (aFramingCtx->FramingRgb != M4OSA_NULL) { 1831 free(aFramingCtx->FramingRgb); 1832 aFramingCtx->FramingRgb = M4OSA_NULL; 1833 } 1834 if (aFramingCtx != M4OSA_NULL) { 1835 free(aFramingCtx); 1836 aFramingCtx = M4OSA_NULL; 1837 } 1838 nbOverlays++; 1839 } 1840 j++; 1841 } 1842 1843 // Check if the edit settings could be retrieved. 1844 M4OSA_TRACE1_1("total clips are = %d",pContext->pEditSettings->uiClipNumber); 1845 for (i = 0; i < pContext->pEditSettings->uiClipNumber; i++) { 1846 M4OSA_TRACE1_1("clip no = %d",i); 1847 properties = pEnv->GetObjectArrayElement(propertiesClipsArray, i); 1848 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1849 (M4OSA_NULL == properties), 1850 "not initialized"); 1851 if (needToBeLoaded) { 1852 getClipSetting(pEnv,properties, pContext->pEditSettings->pClipList[i]); 1853 } else { 1854 goto videoEditor_populateSettings_cleanup; 1855 } 1856 } 1857 1858 if (needToBeLoaded) { 1859 // Log the edit settings. 1860 VIDEOEDIT_LOG_EDIT_SETTINGS(pContext->pEditSettings); 1861 } 1862 } 1863 /* free previous allocations , if any */ 1864 if (pContext->mAudioSettings != M4OSA_NULL) { 1865 if (pContext->mAudioSettings->pFile != NULL) { 1866 free(pContext->mAudioSettings->pFile); 1867 pContext->mAudioSettings->pFile = M4OSA_NULL; 1868 } 1869 if (pContext->mAudioSettings->pPCMFilePath != NULL) { 1870 free(pContext->mAudioSettings->pPCMFilePath); 1871 pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL; 1872 } 1873 } 1874 1875 if (audioSettingObject != M4OSA_NULL) { 1876 jclass audioSettingClazz = pEnv->FindClass(AUDIO_SETTINGS_CLASS_NAME); 1877 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1878 (M4OSA_NULL == audioSettingClazz), 1879 "not initialized"); 1880 1881 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 1882 (M4OSA_NULL == pContext->mAudioSettings), 1883 "not initialized"); 1884 1885 if (needToBeLoaded == false) { 1886 goto videoEditor_populateSettings_cleanup; 1887 } 1888 1889 fid = pEnv->GetFieldID(audioSettingClazz,"bRemoveOriginal","Z"); 1890 pContext->mAudioSettings->bRemoveOriginal = 1891 pEnv->GetBooleanField(audioSettingObject,fid); 1892 M4OSA_TRACE1_1("bRemoveOriginal = %d",pContext->mAudioSettings->bRemoveOriginal); 1893 1894 fid = pEnv->GetFieldID(audioSettingClazz,"channels","I"); 1895 pContext->mAudioSettings->uiNbChannels = pEnv->GetIntField(audioSettingObject,fid); 1896 M4OSA_TRACE1_1("uiNbChannels = %d",pContext->mAudioSettings->uiNbChannels); 1897 1898 fid = pEnv->GetFieldID(audioSettingClazz,"Fs","I"); 1899 pContext->mAudioSettings->uiSamplingFrequency = pEnv->GetIntField(audioSettingObject,fid); 1900 M4OSA_TRACE1_1("uiSamplingFrequency = %d",pContext->mAudioSettings->uiSamplingFrequency); 1901 1902 fid = pEnv->GetFieldID(audioSettingClazz,"ExtendedFs","I"); 1903 pContext->mAudioSettings->uiExtendedSamplingFrequency = 1904 pEnv->GetIntField(audioSettingObject,fid); 1905 M4OSA_TRACE1_1("uiExtendedSamplingFrequency = %d", 1906 pContext->mAudioSettings->uiExtendedSamplingFrequency); 1907 1908 fid = pEnv->GetFieldID(audioSettingClazz,"startMs","J"); 1909 pContext->mAudioSettings->uiAddCts 1910 = pEnv->GetLongField(audioSettingObject,fid); 1911 M4OSA_TRACE1_1("uiAddCts = %d",pContext->mAudioSettings->uiAddCts); 1912 1913 fid = pEnv->GetFieldID(audioSettingClazz,"volume","I"); 1914 pContext->mAudioSettings->uiAddVolume 1915 = pEnv->GetIntField(audioSettingObject,fid); 1916 M4OSA_TRACE1_1("uiAddVolume = %d",pContext->mAudioSettings->uiAddVolume); 1917 1918 fid = pEnv->GetFieldID(audioSettingClazz,"loop","Z"); 1919 pContext->mAudioSettings->bLoop 1920 = pEnv->GetBooleanField(audioSettingObject,fid); 1921 M4OSA_TRACE1_1("bLoop = %d",pContext->mAudioSettings->bLoop); 1922 1923 fid = pEnv->GetFieldID(audioSettingClazz,"beginCutTime","J"); 1924 pContext->mAudioSettings->beginCutMs 1925 = pEnv->GetLongField(audioSettingObject,fid); 1926 M4OSA_TRACE1_1("begin cut time = %d",pContext->mAudioSettings->beginCutMs); 1927 1928 fid = pEnv->GetFieldID(audioSettingClazz,"endCutTime","J"); 1929 pContext->mAudioSettings->endCutMs 1930 = pEnv->GetLongField(audioSettingObject,fid); 1931 M4OSA_TRACE1_1("end cut time = %d",pContext->mAudioSettings->endCutMs); 1932 1933 fid = pEnv->GetFieldID(audioSettingClazz,"fileType","I"); 1934 pContext->mAudioSettings->fileType 1935 = pEnv->GetIntField(audioSettingObject,fid); 1936 M4OSA_TRACE1_1("fileType = %d",pContext->mAudioSettings->fileType); 1937 1938 fid = pEnv->GetFieldID(audioSettingClazz,"pFile","Ljava/lang/String;"); 1939 strPath = (jstring)pEnv->GetObjectField(audioSettingObject,fid); 1940 pTempChar = (M4OSA_Char*)pEnv->GetStringUTFChars(strPath, M4OSA_NULL); 1941 if (pTempChar != NULL) { 1942 pContext->mAudioSettings->pFile = (M4OSA_Char*) M4OSA_32bitAlignedMalloc( 1943 (M4OSA_UInt32)(strlen((const char*)pTempChar))+1 /* +1 for NULL termination */, 0, 1944 (M4OSA_Char*)"strPath allocation " ); 1945 if (pContext->mAudioSettings->pFile != M4OSA_NULL) { 1946 memcpy((void *)pContext->mAudioSettings->pFile , 1947 (void *)pTempChar , strlen((const char*)pTempChar)); 1948 ((M4OSA_Int8 *)(pContext->mAudioSettings->pFile))[strlen((const char*)pTempChar)] = '\0'; 1949 pEnv->ReleaseStringUTFChars(strPath,(const char *)pTempChar); 1950 } else { 1951 pEnv->ReleaseStringUTFChars(strPath,(const char *)pTempChar); 1952 VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", 1953 "regenerateAudio() Malloc failed for pContext->mAudioSettings->pFile "); 1954 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1955 M4OSA_TRUE, M4ERR_ALLOC); 1956 goto videoEditor_populateSettings_cleanup; 1957 } 1958 } 1959 M4OSA_TRACE1_1("file name = %s",pContext->mAudioSettings->pFile); 1960 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio() file name = %s",\ 1961 pContext->mAudioSettings->pFile); 1962 1963 fid = pEnv->GetFieldID(audioSettingClazz,"pcmFilePath","Ljava/lang/String;"); 1964 strPCMPath = (jstring)pEnv->GetObjectField(audioSettingObject,fid); 1965 pTempChar = (M4OSA_Char*)pEnv->GetStringUTFChars(strPCMPath, M4OSA_NULL); 1966 if (pTempChar != NULL) { 1967 pContext->mAudioSettings->pPCMFilePath = (M4OSA_Char*) M4OSA_32bitAlignedMalloc( 1968 (M4OSA_UInt32)(strlen((const char*)pTempChar))+1 /* +1 for NULL termination */, 0, 1969 (M4OSA_Char*)"strPCMPath allocation " ); 1970 if (pContext->mAudioSettings->pPCMFilePath != M4OSA_NULL) { 1971 memcpy((void *)pContext->mAudioSettings->pPCMFilePath , 1972 (void *)pTempChar , strlen((const char*)pTempChar)); 1973 ((M4OSA_Int8 *)(pContext->mAudioSettings->pPCMFilePath))[strlen((const char*)pTempChar)] = '\0'; 1974 pEnv->ReleaseStringUTFChars(strPCMPath,(const char *)pTempChar); 1975 } else { 1976 pEnv->ReleaseStringUTFChars(strPCMPath,(const char *)pTempChar); 1977 VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", 1978 "regenerateAudio() Malloc failed for pContext->mAudioSettings->pPCMFilePath "); 1979 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 1980 M4OSA_TRUE, M4ERR_ALLOC); 1981 goto videoEditor_populateSettings_cleanup; 1982 } 1983 } 1984 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "pPCMFilePath -- %s ",\ 1985 pContext->mAudioSettings->pPCMFilePath); 1986 1987 fid = pEnv->GetFieldID(engineClass,"mRegenerateAudio","Z"); 1988 bool regenerateAudio = pEnv->GetBooleanField(thiz,fid); 1989 1990 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio -- %d ",\ 1991 regenerateAudio); 1992 1993 if (regenerateAudio) { 1994 M4OSA_TRACE1_0("Calling Generate Audio now"); 1995 result = videoEditor_generateAudio(pEnv, 1996 pContext, 1997 (M4OSA_Char*)pContext->mAudioSettings->pFile, 1998 (M4OSA_Char*)pContext->mAudioSettings->pPCMFilePath); 1999 2000 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 2001 (M4NO_ERROR != result), result); 2002 if (needToBeLoaded == false) { 2003 goto videoEditor_populateSettings_cleanup; 2004 } 2005 2006 regenerateAudio = false; 2007 pEnv->SetBooleanField(thiz,fid,regenerateAudio); 2008 } 2009 2010 /* Audio mix and duck */ 2011 fid = pEnv->GetFieldID(audioSettingClazz,"ducking_threshold","I"); 2012 pContext->mAudioSettings->uiInDucking_threshold 2013 = pEnv->GetIntField(audioSettingObject,fid); 2014 2015 M4OSA_TRACE1_1("ducking threshold = %d", 2016 pContext->mAudioSettings->uiInDucking_threshold); 2017 2018 fid = pEnv->GetFieldID(audioSettingClazz,"ducking_lowVolume","I"); 2019 pContext->mAudioSettings->uiInDucking_lowVolume 2020 = pEnv->GetIntField(audioSettingObject,fid); 2021 2022 M4OSA_TRACE1_1("ducking lowVolume = %d", 2023 pContext->mAudioSettings->uiInDucking_lowVolume); 2024 2025 fid = pEnv->GetFieldID(audioSettingClazz,"bInDucking_enable","Z"); 2026 pContext->mAudioSettings->bInDucking_enable 2027 = pEnv->GetBooleanField(audioSettingObject,fid); 2028 M4OSA_TRACE1_1("ducking lowVolume = %d", 2029 pContext->mAudioSettings->bInDucking_enable); 2030 2031 } else { 2032 if (pContext->mAudioSettings != M4OSA_NULL) { 2033 pContext->mAudioSettings->pFile = M4OSA_NULL; 2034 pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL; 2035 pContext->mAudioSettings->bRemoveOriginal = 0; 2036 pContext->mAudioSettings->uiNbChannels = 0; 2037 pContext->mAudioSettings->uiSamplingFrequency = 0; 2038 pContext->mAudioSettings->uiExtendedSamplingFrequency = 0; 2039 pContext->mAudioSettings->uiAddCts = 0; 2040 pContext->mAudioSettings->uiAddVolume = 0; 2041 pContext->mAudioSettings->beginCutMs = 0; 2042 pContext->mAudioSettings->endCutMs = 0; 2043 pContext->mAudioSettings->fileType = 0; 2044 pContext->mAudioSettings->bLoop = 0; 2045 pContext->mAudioSettings->uiInDucking_lowVolume = 0; 2046 pContext->mAudioSettings->bInDucking_enable = 0; 2047 pContext->mAudioSettings->uiBTChannelCount = 0; 2048 pContext->mAudioSettings->uiInDucking_threshold = 0; 2049 2050 fid = pEnv->GetFieldID(engineClass,"mRegenerateAudio","Z"); 2051 bool regenerateAudio = pEnv->GetBooleanField(thiz,fid); 2052 if (!regenerateAudio) { 2053 regenerateAudio = true; 2054 pEnv->SetBooleanField(thiz,fid,regenerateAudio); 2055 } 2056 } 2057 } 2058 2059 if (pContext->pEditSettings != NULL) 2060 { 2061 result = pContext->mPreviewController->loadEditSettings(pContext->pEditSettings, 2062 pContext->mAudioSettings); 2063 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 2064 (M4NO_ERROR != result), result); 2065 2066 if (needToBeLoaded) { 2067 pContext->mPreviewController->setJniCallback((void*)pContext, 2068 (jni_progress_callback_fct)jniPreviewProgressCallback); 2069 } 2070 } 2071 2072 videoEditor_populateSettings_cleanup: 2073 j = 0; 2074 while (j < nbOverlays) 2075 { 2076 if (pContext->pEditSettings->Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data != \ 2077 M4OSA_NULL) { 2078 free(pContext->pEditSettings->\ 2079 Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data); 2080 pContext->pEditSettings->\ 2081 Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data = M4OSA_NULL; 2082 } 2083 j++; 2084 } 2085 2086 j = 0; 2087 while (j < pContext->pEditSettings->nbEffects) 2088 { 2089 if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) { 2090 if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer != M4OSA_NULL) { 2091 free(pContext->pEditSettings->\ 2092 Effects[j].xVSS.pFramingBuffer); 2093 pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer = M4OSA_NULL; 2094 } 2095 } 2096 j++; 2097 } 2098 2099 if (pOverlayIndex != M4OSA_NULL) 2100 { 2101 free(pOverlayIndex); 2102 pOverlayIndex = M4OSA_NULL; 2103 } 2104 return; 2105 } 2106 2107 static void 2108 videoEditor_startPreview( 2109 JNIEnv* pEnv, 2110 jobject thiz, 2111 jobject mSurface, 2112 jlong fromMs, 2113 jlong toMs, 2114 jint callbackInterval, 2115 jboolean loop) 2116 { 2117 bool needToBeLoaded = true; 2118 M4OSA_ERR result = M4NO_ERROR; 2119 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_startPreview()"); 2120 2121 ManualEditContext* pContext = M4OSA_NULL; 2122 // Get the context. 2123 pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz); 2124 2125 // Make sure that the context was set. 2126 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 2127 (M4OSA_NULL == pContext), 2128 "not initialized"); 2129 2130 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 2131 (M4OSA_NULL == pContext->mAudioSettings), 2132 "not initialized"); 2133 // Make sure that the context was set. 2134 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 2135 (M4OSA_NULL == pContext->mPreviewController), 2136 "not initialized"); 2137 2138 // Validate the mSurface parameter. 2139 videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv, 2140 (NULL == mSurface), 2141 "mSurface is null"); 2142 2143 jclass surfaceClass = pEnv->FindClass("android/view/Surface"); 2144 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 2145 (M4OSA_NULL == surfaceClass), 2146 "not initialized"); 2147 //jfieldID surface_native = pEnv->GetFieldID(surfaceClass, "mSurface", "I"); 2148 jfieldID surface_native 2149 = pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I"); 2150 2151 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 2152 (M4OSA_NULL == surface_native), 2153 "not initialized"); 2154 2155 Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native); 2156 2157 sp<Surface> previewSurface = sp<Surface>(p); 2158 // Validate the mSurface's mNativeSurface field 2159 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 2160 (NULL == previewSurface.get()), 2161 "mNativeSurface is null"); 2162 2163 result = pContext->mPreviewController->setSurface(previewSurface); 2164 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, 2165 (M4NO_ERROR != result), result); 2166 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "fromMs=%ld, toMs=%ld", 2167 (M4OSA_UInt32)fromMs, (M4OSA_Int32)toMs); 2168 2169 result = pContext->mPreviewController->startPreview((M4OSA_UInt32)fromMs, 2170 (M4OSA_Int32)toMs, 2171 (M4OSA_UInt16)callbackInterval, 2172 (M4OSA_Bool)loop); 2173 videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, (M4NO_ERROR != result), result); 2174 } 2175 2176 2177 static jobject 2178 videoEditor_getProperties( 2179 JNIEnv* pEnv, 2180 jobject thiz, 2181 jstring file) 2182 { 2183 jobject object = M4OSA_NULL; 2184 jclass clazz = pEnv->FindClass(PROPERTIES_CLASS_NAME); 2185 jfieldID fid; 2186 bool needToBeLoaded = true; 2187 ManualEditContext* pContext = M4OSA_NULL; 2188 M4OSA_ERR result = M4NO_ERROR; 2189 int profile = 0; 2190 int level = 0; 2191 int videoFormat = 0; 2192 2193 // Get the context. 2194 pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz); 2195 2196 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 2197 (M4OSA_NULL == clazz), 2198 "not initialized"); 2199 2200 object = videoEditProp_getProperties(pEnv,thiz,file); 2201 2202 if (object != M4OSA_NULL) { 2203 fid = pEnv->GetFieldID(clazz,"profile","I"); 2204 profile = pEnv->GetIntField(object,fid); 2205 fid = pEnv->GetFieldID(clazz,"level","I"); 2206 level = pEnv->GetIntField(object,fid); 2207 fid = pEnv->GetFieldID(clazz,"videoFormat","I"); 2208 videoFormat = pEnv->GetIntField(object,fid); 2209 2210 result = checkClipVideoProfileAndLevel(pContext->decoders, videoFormat, profile, level); 2211 2212 fid = pEnv->GetFieldID(clazz,"profileSupported","Z"); 2213 if (M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE == result) { 2214 pEnv->SetBooleanField(object,fid,false); 2215 } 2216 2217 fid = pEnv->GetFieldID(clazz,"levelSupported","Z"); 2218 if (M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_LEVEL == result) { 2219 pEnv->SetBooleanField(object,fid,false); 2220 } 2221 } 2222 return object; 2223 2224 } 2225 static int videoEditor_getPixels( 2226 JNIEnv* env, 2227 jobject thiz, 2228 jstring path, 2229 jintArray pixelArray, 2230 M4OSA_UInt32 width, 2231 M4OSA_UInt32 height, 2232 M4OSA_UInt32 timeMS) 2233 { 2234 2235 M4OSA_ERR err = M4NO_ERROR; 2236 M4OSA_Context mContext = M4OSA_NULL; 2237 jint* m_dst32 = M4OSA_NULL; 2238 2239 2240 // Add a text marker (the condition must always be true). 2241 ADD_TEXT_MARKER_FUN(NULL != env) 2242 2243 const char *pString = env->GetStringUTFChars(path, NULL); 2244 if (pString == M4OSA_NULL) { 2245 if (env != NULL) { 2246 jniThrowException(env, "java/lang/RuntimeException", "Input string null"); 2247 } 2248 return M4ERR_ALLOC; 2249 } 2250 2251 err = ThumbnailOpen(&mContext,(const M4OSA_Char*)pString, M4OSA_FALSE); 2252 if (err != M4NO_ERROR || mContext == M4OSA_NULL) { 2253 if (pString != NULL) { 2254 env->ReleaseStringUTFChars(path, pString); 2255 } 2256 if (env != NULL) { 2257 jniThrowException(env, "java/lang/RuntimeException", "ThumbnailOpen failed"); 2258 } 2259 } 2260 2261 m_dst32 = env->GetIntArrayElements(pixelArray, NULL); 2262 2263 err = ThumbnailGetPixels32(mContext, (M4OSA_Int32 *)m_dst32, width,height,&timeMS,0); 2264 if (err != M4NO_ERROR ) { 2265 if (env != NULL) { 2266 jniThrowException(env, "java/lang/RuntimeException",\ 2267 "ThumbnailGetPixels32 failed"); 2268 } 2269 } 2270 env->ReleaseIntArrayElements(pixelArray, m_dst32, 0); 2271 2272 ThumbnailClose(mContext); 2273 if (pString != NULL) { 2274 env->ReleaseStringUTFChars(path, pString); 2275 } 2276 2277 return timeMS; 2278 } 2279 2280 static int videoEditor_getPixelsList( 2281 JNIEnv* env, 2282 jobject thiz, 2283 jstring path, 2284 jintArray pixelArray, 2285 M4OSA_UInt32 width, 2286 M4OSA_UInt32 height, 2287 M4OSA_UInt32 noOfThumbnails, 2288 jlong startTime, 2289 jlong endTime, 2290 jintArray indexArray, 2291 jobject callback) 2292 { 2293 2294 M4OSA_ERR err = M4NO_ERROR; 2295 M4OSA_Context mContext = M4OSA_NULL; 2296 2297 const char *pString = env->GetStringUTFChars(path, NULL); 2298 if (pString == M4OSA_NULL) { 2299 jniThrowException(env, "java/lang/RuntimeException", "Input string null"); 2300 return M4ERR_ALLOC; 2301 } 2302 2303 err = ThumbnailOpen(&mContext,(const M4OSA_Char*)pString, M4OSA_FALSE); 2304 if (err != M4NO_ERROR || mContext == M4OSA_NULL) { 2305 jniThrowException(env, "java/lang/RuntimeException", "ThumbnailOpen failed"); 2306 if (pString != NULL) { 2307 env->ReleaseStringUTFChars(path, pString); 2308 } 2309 return err; 2310 } 2311 2312 jlong duration = (endTime - startTime); 2313 M4OSA_UInt32 tolerance = duration / (2 * noOfThumbnails); 2314 jint* m_dst32 = env->GetIntArrayElements(pixelArray, NULL); 2315 jint* indices = env->GetIntArrayElements(indexArray, NULL); 2316 jsize len = env->GetArrayLength(indexArray); 2317 2318 jclass cls = env->GetObjectClass(callback); 2319 jmethodID mid = env->GetMethodID(cls, "onThumbnail", "(I)V"); 2320 2321 for (int i = 0; i < len; i++) { 2322 int k = indices[i]; 2323 M4OSA_UInt32 timeMS = startTime; 2324 timeMS += (2 * k + 1) * duration / (2 * noOfThumbnails); 2325 err = ThumbnailGetPixels32(mContext, ((M4OSA_Int32 *)m_dst32), 2326 width, height, &timeMS, tolerance); 2327 if (err != M4NO_ERROR) { 2328 break; 2329 } 2330 env->CallVoidMethod(callback, mid, (jint)k); 2331 if (env->ExceptionCheck()) { 2332 err = M4ERR_ALLOC; 2333 break; 2334 } 2335 } 2336 2337 env->ReleaseIntArrayElements(pixelArray, m_dst32, 0); 2338 env->ReleaseIntArrayElements(indexArray, indices, 0); 2339 2340 ThumbnailClose(mContext); 2341 if (pString != NULL) { 2342 env->ReleaseStringUTFChars(path, pString); 2343 } 2344 2345 if (err != M4NO_ERROR && !env->ExceptionCheck()) { 2346 jniThrowException(env, "java/lang/RuntimeException",\ 2347 "ThumbnailGetPixels32 failed"); 2348 } 2349 2350 return err; 2351 } 2352 2353 static M4OSA_ERR 2354 videoEditor_toUTF8Fct( 2355 M4OSA_Void* pBufferIn, 2356 M4OSA_UInt8* pBufferOut, 2357 M4OSA_UInt32* bufferOutSize) 2358 { 2359 M4OSA_ERR result = M4NO_ERROR; 2360 M4OSA_UInt32 length = 0; 2361 2362 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_toUTF8Fct()"); 2363 2364 // Determine the length of the input buffer. 2365 if (M4OSA_NULL != pBufferIn) 2366 { 2367 length = strlen((const char *)pBufferIn); 2368 } 2369 2370 // Check if the output buffer is large enough to hold the input buffer. 2371 if ((*bufferOutSize) > length) 2372 { 2373 // Check if the input buffer is not M4OSA_NULL. 2374 if (M4OSA_NULL != pBufferIn) 2375 { 2376 // Copy the temp path, ignore the result. 2377 M4OSA_chrNCopy((M4OSA_Char *)pBufferOut, (M4OSA_Char *)pBufferIn, length); 2378 } 2379 else 2380 { 2381 // Set the output buffer to an empty string. 2382 (*(M4OSA_Char *)pBufferOut) = 0; 2383 } 2384 } 2385 else 2386 { 2387 // The buffer is too small. 2388 result = M4xVSSWAR_BUFFER_OUT_TOO_SMALL; 2389 } 2390 2391 // Return the buffer output size. 2392 (*bufferOutSize) = length + 1; 2393 2394 // Return the result. 2395 return(result); 2396 } 2397 2398 static M4OSA_ERR 2399 videoEditor_fromUTF8Fct( 2400 M4OSA_UInt8* pBufferIn, 2401 M4OSA_Void* pBufferOut, 2402 M4OSA_UInt32* bufferOutSize) 2403 { 2404 M4OSA_ERR result = M4NO_ERROR; 2405 M4OSA_UInt32 length = 0; 2406 2407 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_fromUTF8Fct()"); 2408 2409 // Determine the length of the input buffer. 2410 if (M4OSA_NULL != pBufferIn) 2411 { 2412 length = strlen((const char *)pBufferIn); 2413 } 2414 2415 // Check if the output buffer is large enough to hold the input buffer. 2416 if ((*bufferOutSize) > length) 2417 { 2418 // Check if the input buffer is not M4OSA_NULL. 2419 if (M4OSA_NULL != pBufferIn) 2420 { 2421 // Copy the temp path, ignore the result. 2422 M4OSA_chrNCopy((M4OSA_Char *)pBufferOut, (M4OSA_Char *)pBufferIn, length); 2423 } 2424 else 2425 { 2426 // Set the output buffer to an empty string. 2427 (*(M4OSA_Char *)pBufferOut) = 0; 2428 } 2429 } 2430 else 2431 { 2432 // The buffer is too small. 2433 result = M4xVSSWAR_BUFFER_OUT_TOO_SMALL; 2434 } 2435 2436 // Return the buffer output size. 2437 (*bufferOutSize) = length + 1; 2438 2439 // Return the result. 2440 return(result); 2441 } 2442 2443 static M4OSA_ERR 2444 videoEditor_getTextRgbBufferFct( 2445 M4OSA_Void* pRenderingData, 2446 M4OSA_Void* pTextBuffer, 2447 M4OSA_UInt32 textBufferSize, 2448 M4VIFI_ImagePlane** pOutputPlane) 2449 { 2450 M4OSA_ERR result = M4NO_ERROR; 2451 2452 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getTextRgbBufferFct()"); 2453 2454 // Return the result. 2455 return(result); 2456 } 2457 2458 static void 2459 videoEditor_callOnProgressUpdate( 2460 ManualEditContext* pContext, 2461 int task, 2462 int progress) 2463 { 2464 JNIEnv* pEnv = NULL; 2465 2466 2467 // Attach the current thread. 2468 pContext->pVM->AttachCurrentThread(&pEnv, NULL); 2469 2470 2471 // Call the on completion callback. 2472 pEnv->CallVoidMethod(pContext->engine, pContext->onProgressUpdateMethodId, 2473 videoEditJava_getEngineCToJava(task), progress); 2474 2475 2476 // Detach the current thread. 2477 pContext->pVM->DetachCurrentThread(); 2478 } 2479 2480 static void 2481 videoEditor_freeContext( 2482 JNIEnv* pEnv, 2483 ManualEditContext** ppContext) 2484 { 2485 ManualEditContext* pContext = M4OSA_NULL; 2486 2487 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_freeContext"); 2488 2489 // Set the context pointer. 2490 pContext = (*ppContext); 2491 2492 // Check if the context was set. 2493 if (M4OSA_NULL != pContext) 2494 { 2495 // Check if a global reference to the engine object was set. 2496 if (NULL != pContext->engine) 2497 { 2498 // Free the global reference. 2499 pEnv->DeleteGlobalRef(pContext->engine); 2500 pContext->engine = NULL; 2501 } 2502 2503 // Check if the temp path was set. 2504 if (M4OSA_NULL != pContext->initParams.pTempPath) 2505 { 2506 // Free the memory allocated for the temp path. 2507 videoEditOsal_free(pContext->initParams.pTempPath); 2508 pContext->initParams.pTempPath = M4OSA_NULL; 2509 } 2510 2511 // Check if the file writer was set. 2512 if (M4OSA_NULL != pContext->initParams.pFileWritePtr) 2513 { 2514 // Free the memory allocated for the file writer. 2515 videoEditOsal_free(pContext->initParams.pFileWritePtr); 2516 pContext->initParams.pFileWritePtr = M4OSA_NULL; 2517 } 2518 2519 // Check if the file reader was set. 2520 if (M4OSA_NULL != pContext->initParams.pFileReadPtr) 2521 { 2522 // Free the memory allocated for the file reader. 2523 videoEditOsal_free(pContext->initParams.pFileReadPtr); 2524 pContext->initParams.pFileReadPtr = M4OSA_NULL; 2525 } 2526 2527 // Free the memory allocated for the context. 2528 videoEditOsal_free(pContext); 2529 pContext = M4OSA_NULL; 2530 2531 // Reset the context pointer. 2532 (*ppContext) = M4OSA_NULL; 2533 } 2534 } 2535 2536 static jobject 2537 videoEditor_getVersion( 2538 JNIEnv* pEnv, 2539 jobject thiz) 2540 { 2541 bool isSuccessful = true; 2542 jobject version = NULL; 2543 M4_VersionInfo versionInfo = {0, 0, 0, 0}; 2544 M4OSA_ERR result = M4NO_ERROR; 2545 2546 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getVersion()"); 2547 2548 versionInfo.m_structSize = sizeof(versionInfo); 2549 versionInfo.m_major = VIDEOEDITOR_VERSION_MAJOR; 2550 versionInfo.m_minor = VIDEOEDITOR_VERSION_MINOR; 2551 versionInfo.m_revision = VIDEOEDITOR_VERSION_REVISION; 2552 2553 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getVersion() major %d,\ 2554 minor %d, revision %d", versionInfo.m_major, versionInfo.m_minor, versionInfo.m_revision); 2555 2556 // Create a version object. 2557 videoEditClasses_createVersion(&isSuccessful, pEnv, &versionInfo, &version); 2558 2559 // Return the version object. 2560 return(version); 2561 } 2562 2563 static void 2564 videoEditor_init( 2565 JNIEnv* pEnv, 2566 jobject thiz, 2567 jstring tempPath, 2568 jstring libraryPath) 2569 { 2570 bool initialized = true; 2571 ManualEditContext* pContext = M4OSA_NULL; 2572 VideoEditJava_EngineMethodIds methodIds = {NULL}; 2573 M4OSA_Char* pLibraryPath = M4OSA_NULL; 2574 M4OSA_Char* pTextRendererPath = M4OSA_NULL; 2575 M4OSA_UInt32 textRendererPathLength = 0; 2576 M4OSA_ERR result = M4NO_ERROR; 2577 2578 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_init()"); 2579 2580 // Add a text marker (the condition must always be true). 2581 ADD_TEXT_MARKER_FUN(NULL != pEnv) 2582 2583 // Get the context. 2584 pContext = (ManualEditContext*)videoEditClasses_getContext(&initialized, pEnv, thiz); 2585 2586 // Get the engine method ids. 2587 videoEditJava_getEngineMethodIds(&initialized, pEnv, &methodIds); 2588 2589 // Validate the tempPath parameter. 2590 videoEditJava_checkAndThrowIllegalArgumentException(&initialized, pEnv, 2591 (NULL == tempPath), 2592 "tempPath is null"); 2593 2594 // Make sure that the context was not set already. 2595 videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv, 2596 (M4OSA_NULL != pContext), 2597 "already initialized"); 2598 2599 // Check if the initialization succeeded (required because of dereferencing of psContext, 2600 // and freeing when initialization fails). 2601 if (initialized) 2602 { 2603 // Allocate a new context. 2604 pContext = new ManualEditContext; 2605 2606 // Check if the initialization succeeded (required because of dereferencing of psContext). 2607 //if (initialized) 2608 if (pContext != NULL) 2609 { 2610 // Set the state to not initialized. 2611 pContext->state = ManualEditState_NOT_INITIALIZED; 2612 2613 // Allocate a file read pointer structure. 2614 pContext->initParams.pFileReadPtr = 2615 (M4OSA_FileReadPointer*)videoEditOsal_alloc(&initialized, pEnv, 2616 sizeof(M4OSA_FileReadPointer), "FileReadPointer"); 2617 2618 // Allocate a file write pointer structure. 2619 pContext->initParams.pFileWritePtr = 2620 (M4OSA_FileWriterPointer*)videoEditOsal_alloc(&initialized, pEnv, 2621 sizeof(M4OSA_FileWriterPointer), "FileWriterPointer"); 2622 2623 // Get the temp path. 2624 M4OSA_Char* tmpString = 2625 (M4OSA_Char *)videoEditJava_getString(&initialized, pEnv, tempPath, 2626 NULL, M4OSA_NULL); 2627 pContext->initParams.pTempPath = (M4OSA_Char *) 2628 M4OSA_32bitAlignedMalloc(strlen((const char *)tmpString) + 1, 0x0, 2629 (M4OSA_Char *)"tempPath"); 2630 //initialize the first char. so that strcat works. 2631 M4OSA_Char *ptmpChar = (M4OSA_Char*)pContext->initParams.pTempPath; 2632 ptmpChar[0] = 0x00; 2633 strncat((char *)pContext->initParams.pTempPath, (const char *)tmpString, 2634 (size_t)strlen((const char *)tmpString)); 2635 strncat((char *)pContext->initParams.pTempPath, (const char *)"/", (size_t)1); 2636 free(tmpString); 2637 pContext->mIsUpdateOverlay = false; 2638 pContext->mOverlayFileName = NULL; 2639 pContext->decoders = NULL; 2640 } 2641 2642 // Check if the initialization succeeded 2643 // (required because of dereferencing of pContext, pFileReadPtr and pFileWritePtr). 2644 if (initialized) 2645 { 2646 2647 // Initialize the OSAL file system function pointers. 2648 videoEditOsal_getFilePointers(pContext->initParams.pFileReadPtr , 2649 pContext->initParams.pFileWritePtr); 2650 2651 // Set the UTF8 conversion functions. 2652 pContext->initParams.pConvToUTF8Fct = videoEditor_toUTF8Fct; 2653 pContext->initParams.pConvFromUTF8Fct = videoEditor_fromUTF8Fct; 2654 2655 // Set the callback method ids. 2656 pContext->onProgressUpdateMethodId = methodIds.onProgressUpdate; 2657 2658 // Set the virtual machine. 2659 pEnv->GetJavaVM(&(pContext->pVM)); 2660 2661 // Create a global reference to the engine object. 2662 pContext->engine = pEnv->NewGlobalRef(thiz); 2663 2664 // Check if the global reference could be created. 2665 videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv, 2666 (NULL == pContext->engine), M4NO_ERROR); 2667 } 2668 2669 // Check if the initialization succeeded (required because of dereferencing of pContext). 2670 if (initialized) 2671 { 2672 // Log the API call. 2673 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4xVSS_Init()"); 2674 2675 // Initialize the visual studio library. 2676 result = M4xVSS_Init(&pContext->engineContext, &pContext->initParams); 2677 2678 // Log the result. 2679 VIDEOEDIT_LOG_RESULT(ANDROID_LOG_INFO, "VIDEO_EDITOR", 2680 videoEditOsal_getResultString(result)); 2681 2682 // Check if the library could be initialized. 2683 videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv, 2684 (M4NO_ERROR != result), result); 2685 2686 // Get platform video decoder capablities. 2687 result = M4xVSS_getVideoDecoderCapabilities(&pContext->decoders); 2688 2689 videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv, 2690 (M4NO_ERROR != result), result); 2691 } 2692 2693 if(initialized) 2694 { 2695 pContext->mPreviewController = new VideoEditorPreviewController(); 2696 videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv, 2697 (M4OSA_NULL == pContext->mPreviewController), 2698 "not initialized"); 2699 pContext->mAudioSettings = 2700 (M4xVSS_AudioMixingSettings *) 2701 M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_AudioMixingSettings),0x0, 2702 (M4OSA_Char *)"mAudioSettings"); 2703 videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv, 2704 (M4OSA_NULL == pContext->mAudioSettings), 2705 "not initialized"); 2706 pContext->mAudioSettings->pFile = M4OSA_NULL; 2707 pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL; 2708 pContext->mAudioSettings->bRemoveOriginal = 0; 2709 pContext->mAudioSettings->uiNbChannels = 0; 2710 pContext->mAudioSettings->uiSamplingFrequency = 0; 2711 pContext->mAudioSettings->uiExtendedSamplingFrequency = 0; 2712 pContext->mAudioSettings->uiAddCts = 0; 2713 pContext->mAudioSettings->uiAddVolume = 0; 2714 pContext->mAudioSettings->beginCutMs = 0; 2715 pContext->mAudioSettings->endCutMs = 0; 2716 pContext->mAudioSettings->fileType = 0; 2717 pContext->mAudioSettings->bLoop = 0; 2718 pContext->mAudioSettings->uiInDucking_lowVolume = 0; 2719 pContext->mAudioSettings->bInDucking_enable = 0; 2720 pContext->mAudioSettings->uiBTChannelCount = 0; 2721 pContext->mAudioSettings->uiInDucking_threshold = 0; 2722 } 2723 // Check if the library could be initialized. 2724 if (initialized) 2725 { 2726 // Set the state to initialized. 2727 pContext->state = ManualEditState_INITIALIZED; 2728 } 2729 2730 // Set the context. 2731 videoEditClasses_setContext(&initialized, pEnv, thiz, (void* )pContext); 2732 pLibraryPath = M4OSA_NULL; 2733 2734 pContext->pEditSettings = M4OSA_NULL; 2735 // Cleanup if anything went wrong during initialization. 2736 if (!initialized) 2737 { 2738 // Free the context. 2739 videoEditor_freeContext(pEnv, &pContext); 2740 } 2741 } 2742 } 2743 2744 /*+ PROGRESS CB */ 2745 static 2746 M4OSA_ERR videoEditor_processClip( 2747 JNIEnv* pEnv, 2748 jobject thiz, 2749 int unuseditemID) { 2750 2751 bool loaded = true; 2752 ManualEditContext* pContext = NULL; 2753 M4OSA_UInt8 progress = 0; 2754 M4OSA_UInt8 progressBase = 0; 2755 M4OSA_UInt8 lastProgress = 0; 2756 M4OSA_ERR result = M4NO_ERROR; 2757 2758 // Get the context. 2759 pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz); 2760 2761 // Make sure that the context was set. 2762 videoEditJava_checkAndThrowIllegalStateException(&loaded, pEnv, 2763 (M4OSA_NULL == pContext), 2764 "not initialized"); 2765 2766 // We start in Analyzing state 2767 pContext->state = ManualEditState_INITIALIZED; 2768 M4OSA_ERR completionResult = M4VSS3GPP_WAR_ANALYZING_DONE; 2769 ManualEditState completionState = ManualEditState_OPENED; 2770 ManualEditState errorState = ManualEditState_ANALYZING_ERROR; 2771 2772 // While analyzing progress goes from 0 to 10 (except Kenburn clip 2773 // generation, which goes from 0 to 50) 2774 progressBase = 0; 2775 2776 // Set the text rendering function. 2777 if (M4OSA_NULL != pContext->pTextRendererFunction) 2778 { 2779 // Use the text renderer function in the library. 2780 pContext->pEditSettings->xVSS.pTextRenderingFct = pContext->pTextRendererFunction; 2781 } 2782 else 2783 { 2784 // Use the internal text renderer function. 2785 pContext->pEditSettings->xVSS.pTextRenderingFct = videoEditor_getTextRgbBufferFct; 2786 } 2787 2788 // Send the command. 2789 LOGV("videoEditor_processClip ITEM %d Calling M4xVSS_SendCommand()", unuseditemID); 2790 result = M4xVSS_SendCommand(pContext->engineContext, pContext->pEditSettings); 2791 LOGV("videoEditor_processClip ITEM %d M4xVSS_SendCommand() returned 0x%x", 2792 unuseditemID, (unsigned int) result); 2793 2794 // Remove warnings indications (we only care about errors here) 2795 if ((result == M4VSS3GPP_WAR_TRANSCODING_NECESSARY) 2796 || (result == M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED)) { 2797 result = M4NO_ERROR; 2798 } 2799 2800 // Send the first progress indication (=0) 2801 LOGV("VERY FIRST PROGRESS videoEditor_processClip ITEM %d Progress indication %d", 2802 unuseditemID, progress); 2803 pEnv->CallVoidMethod(pContext->engine, pContext->onProgressUpdateMethodId, 2804 unuseditemID, progress); 2805 2806 // Check if a task is being performed. 2807 // ??? ADD STOPPING MECHANISM 2808 LOGV("videoEditor_processClip Entering processing loop"); 2809 M4OSA_UInt8 prevReportedProgress = 0; 2810 while((result == M4NO_ERROR) 2811 &&(pContext->state!=ManualEditState_SAVED) 2812 &&(pContext->state!=ManualEditState_STOPPING)) { 2813 2814 // Perform the next processing step. 2815 //LOGV("LVME_processClip Entering M4xVSS_Step()"); 2816 result = M4xVSS_Step(pContext->engineContext, &progress); 2817 2818 if (progress != prevReportedProgress) { 2819 prevReportedProgress = progress; 2820 // Log the 1 % .. 100 % progress after processing. 2821 if (M4OSA_TRUE == 2822 pContext->pEditSettings->pClipList[0]->xVSS.isPanZoom) { 2823 // For KenBurn clip generation, return 0 to 50 2824 // for Analysis phase and 50 to 100 for Saving phase 2825 progress = progressBase + progress/2; 2826 } else { 2827 // For export/transition clips, 0 to 10 for Analysis phase 2828 // and 10 to 100 for Saving phase 2829 if (ManualEditState_INITIALIZED == pContext->state) { 2830 progress = 0.1*progress; 2831 } else { 2832 progress = progressBase + 0.9*progress; 2833 } 2834 } 2835 2836 if (progress > lastProgress) 2837 { 2838 // Send a progress notification. 2839 LOGV("videoEditor_processClip ITEM %d Progress indication %d", 2840 unuseditemID, progress); 2841 pEnv->CallVoidMethod(pContext->engine, 2842 pContext->onProgressUpdateMethodId, 2843 unuseditemID, progress); 2844 lastProgress = progress; 2845 } 2846 } 2847 2848 // Check if processing has been completed. 2849 if (result == completionResult) 2850 { 2851 // Set the state to the completions state. 2852 pContext->state = completionState; 2853 LOGV("videoEditor_processClip ITEM %d STATE changed to %d", 2854 unuseditemID, pContext->state); 2855 2856 // Reset progress indication, as we switch to next state 2857 lastProgress = 0; 2858 2859 // Reset error code, as we start a new round of processing 2860 result = M4NO_ERROR; 2861 2862 // Check if we are analyzing input 2863 if (pContext->state == ManualEditState_OPENED) { 2864 // File is opened, we must start saving it 2865 LOGV("videoEditor_processClip Calling M4xVSS_SaveStart()"); 2866 result = M4xVSS_SaveStart(pContext->engineContext, 2867 (M4OSA_Char*)pContext->pEditSettings->pOutputFile, 2868 (M4OSA_UInt32)pContext->pEditSettings->uiOutputPathSize); 2869 LOGV("videoEditor_processClip ITEM %d SaveStart() returned 0x%x", 2870 unuseditemID, (unsigned int) result); 2871 2872 // Set the state to saving. 2873 pContext->state = ManualEditState_SAVING; 2874 completionState = ManualEditState_SAVED; 2875 completionResult = M4VSS3GPP_WAR_SAVING_DONE; 2876 errorState = ManualEditState_SAVING_ERROR; 2877 2878 // While saving, progress goes from 10 to 100 2879 // except for Kenburn clip which goes from 50 to 100 2880 if (M4OSA_TRUE == 2881 pContext->pEditSettings->pClipList[0]->xVSS.isPanZoom) { 2882 progressBase = 50; 2883 } else { 2884 progressBase = 10; 2885 } 2886 } 2887 // Check if we encoding is ongoing 2888 else if (pContext->state == ManualEditState_SAVED) { 2889 2890 // Send a progress notification. 2891 progress = 100; 2892 LOGV("videoEditor_processClip ITEM %d Last progress indication %d", 2893 unuseditemID, progress); 2894 pEnv->CallVoidMethod(pContext->engine, 2895 pContext->onProgressUpdateMethodId, 2896 unuseditemID, progress); 2897 2898 2899 // Stop the encoding. 2900 LOGV("videoEditor_processClip Calling M4xVSS_SaveStop()"); 2901 result = M4xVSS_SaveStop(pContext->engineContext); 2902 LOGV("videoEditor_processClip M4xVSS_SaveStop() returned 0x%x", result); 2903 } 2904 // Other states are unexpected 2905 else { 2906 result = M4ERR_STATE; 2907 LOGE("videoEditor_processClip ITEM %d State ERROR 0x%x", 2908 unuseditemID, (unsigned int) result); 2909 } 2910 } 2911 2912 // Check if an error occurred. 2913 if (result != M4NO_ERROR) 2914 { 2915 // Set the state to the error state. 2916 pContext->state = errorState; 2917 2918 // Log the result. 2919 LOGE("videoEditor_processClip ITEM %d Processing ERROR 0x%x", 2920 unuseditemID, (unsigned int) result); 2921 } 2922 } 2923 2924 // Return the error result 2925 LOGE("videoEditor_processClip ITEM %d END 0x%x", unuseditemID, (unsigned int) result); 2926 return result; 2927 } 2928 /*+ PROGRESS CB */ 2929 2930 static int 2931 videoEditor_generateClip( 2932 JNIEnv* pEnv, 2933 jobject thiz, 2934 jobject settings) { 2935 bool loaded = true; 2936 ManualEditContext* pContext = M4OSA_NULL; 2937 M4OSA_ERR result = M4NO_ERROR; 2938 2939 LOGV("videoEditor_generateClip START"); 2940 2941 // Get the context. 2942 pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz); 2943 2944 Mutex::Autolock autoLock(pContext->mLock); 2945 2946 // Validate the settings parameter. 2947 videoEditJava_checkAndThrowIllegalArgumentException(&loaded, pEnv, 2948 (NULL == settings), 2949 "settings is null"); 2950 2951 // Make sure that the context was set. 2952 videoEditJava_checkAndThrowIllegalStateException(&loaded, pEnv, 2953 (M4OSA_NULL == pContext), 2954 "not initialized"); 2955 2956 // Load the clip settings 2957 LOGV("videoEditor_generateClip Calling videoEditor_loadSettings"); 2958 videoEditor_loadSettings(pEnv, thiz, settings); 2959 LOGV("videoEditor_generateClip videoEditor_loadSettings returned"); 2960 2961 // Generate the clip 2962 LOGV("videoEditor_generateClip Calling LVME_processClip"); 2963 result = videoEditor_processClip(pEnv, thiz, 0 /*item id is unused*/); 2964 LOGV("videoEditor_generateClip videoEditor_processClip returned 0x%x", result); 2965 2966 if (pContext->state != ManualEditState_INITIALIZED) { 2967 // Free up memory (whatever the result) 2968 videoEditor_unloadSettings(pEnv, thiz); 2969 } 2970 2971 LOGV("videoEditor_generateClip END 0x%x", (unsigned int) result); 2972 return result; 2973 } 2974 2975 static void 2976 videoEditor_loadSettings( 2977 JNIEnv* pEnv, 2978 jobject thiz, 2979 jobject settings) 2980 { 2981 bool needToBeLoaded = true; 2982 ManualEditContext* pContext = M4OSA_NULL; 2983 2984 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_loadSettings()"); 2985 2986 // Add a code marker (the condition must always be true). 2987 ADD_CODE_MARKER_FUN(NULL != pEnv) 2988 2989 // Get the context. 2990 pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, 2991 pEnv, thiz); 2992 2993 // Validate the settings parameter. 2994 videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv, 2995 (NULL == settings), 2996 "settings is null"); 2997 2998 // Make sure that the context was set. 2999 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 3000 (M4OSA_NULL == pContext), 3001 "not initialized"); 3002 3003 // Check if the context is valid (required because the context is dereferenced). 3004 if (needToBeLoaded) 3005 { 3006 // Make sure that we are in a correct state. 3007 videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv, 3008 (pContext->state != ManualEditState_INITIALIZED), 3009 "settings already loaded"); 3010 3011 // Retrieve the edit settings. 3012 if(pContext->pEditSettings != M4OSA_NULL) { 3013 videoEditClasses_freeEditSettings(&pContext->pEditSettings); 3014 pContext->pEditSettings = M4OSA_NULL; 3015 } 3016 videoEditClasses_getEditSettings(&needToBeLoaded, pEnv, settings, 3017 &pContext->pEditSettings,true); 3018 } 3019 3020 // Check if the edit settings could be retrieved. 3021 if (needToBeLoaded) 3022 { 3023 // Log the edit settings. 3024 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "inside load settings"); 3025 VIDEOEDIT_LOG_EDIT_SETTINGS(pContext->pEditSettings); 3026 } 3027 LOGV("videoEditor_loadSettings END"); 3028 } 3029 3030 3031 3032 static void 3033 videoEditor_unloadSettings( 3034 JNIEnv* pEnv, 3035 jobject thiz) 3036 { 3037 bool needToBeUnLoaded = true; 3038 ManualEditContext* pContext = M4OSA_NULL; 3039 M4OSA_ERR result = M4NO_ERROR; 3040 3041 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_unloadSettings()"); 3042 3043 // Get the context. 3044 pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeUnLoaded, pEnv, thiz); 3045 3046 // Make sure that the context was set. 3047 videoEditJava_checkAndThrowIllegalStateException(&needToBeUnLoaded, pEnv, 3048 (M4OSA_NULL == pContext), 3049 "not initialized"); 3050 3051 // Check if the context is valid (required because the context is dereferenced). 3052 if (needToBeUnLoaded) 3053 { 3054 LOGV("videoEditor_unloadSettings state %d", pContext->state); 3055 // Make sure that we are in a correct state. 3056 videoEditJava_checkAndThrowIllegalStateException(&needToBeUnLoaded, pEnv, 3057 ((pContext->state != ManualEditState_ANALYZING ) && 3058 (pContext->state != ManualEditState_ANALYZING_ERROR) && 3059 (pContext->state != ManualEditState_OPENED ) && 3060 (pContext->state != ManualEditState_SAVING_ERROR ) && 3061 (pContext->state != ManualEditState_SAVED ) && 3062 (pContext->state != ManualEditState_STOPPING ) ), 3063 "videoEditor_unloadSettings no load settings in progress"); 3064 } 3065 3066 // Check if we are in a correct state. 3067 if (needToBeUnLoaded) 3068 { 3069 // Check if the thread could be stopped. 3070 if (needToBeUnLoaded) 3071 { 3072 // Close the command. 3073 LOGV("videoEditor_unloadSettings Calling M4xVSS_CloseCommand()"); 3074 result = M4xVSS_CloseCommand(pContext->engineContext); 3075 LOGV("videoEditor_unloadSettings M4xVSS_CloseCommand() returned 0x%x", 3076 (unsigned int)result); 3077 3078 // Check if the command could be closed. 3079 videoEditJava_checkAndThrowRuntimeException(&needToBeUnLoaded, pEnv, 3080 (M4NO_ERROR != result), result); 3081 } 3082 3083 // Check if the command could be closed. 3084 if (needToBeUnLoaded) 3085 { 3086 // Free the edit settings. 3087 //videoEditClasses_freeEditSettings(&pContext->pEditSettings); 3088 3089 // Reset the thread result. 3090 pContext->threadResult = M4NO_ERROR; 3091 3092 // Reset the thread progress. 3093 pContext->threadProgress = 0; 3094 3095 // Set the state to initialized. 3096 pContext->state = ManualEditState_INITIALIZED; 3097 } 3098 } 3099 } 3100 3101 static void 3102 videoEditor_stopEncoding( 3103 JNIEnv* pEnv, 3104 jobject thiz) 3105 { 3106 bool stopped = true; 3107 ManualEditContext* pContext = M4OSA_NULL; 3108 M4OSA_ERR result = M4NO_ERROR; 3109 3110 LOGV("videoEditor_stopEncoding START"); 3111 3112 // Get the context. 3113 pContext = (ManualEditContext*)videoEditClasses_getContext(&stopped, pEnv, thiz); 3114 3115 // Change state and get Lock 3116 // This will ensure the generateClip function exits 3117 pContext->state = ManualEditState_STOPPING; 3118 Mutex::Autolock autoLock(pContext->mLock); 3119 3120 // Make sure that the context was set. 3121 videoEditJava_checkAndThrowIllegalStateException(&stopped, pEnv, 3122 (M4OSA_NULL == pContext), 3123 "not initialized"); 3124 3125 if (stopped) { 3126 3127 // Check if the command should be closed. 3128 if (pContext->state != ManualEditState_INITIALIZED) 3129 { 3130 // Close the command. 3131 LOGV("videoEditor_stopEncoding Calling M4xVSS_CloseCommand()"); 3132 result = M4xVSS_CloseCommand(pContext->engineContext); 3133 LOGV("videoEditor_stopEncoding M4xVSS_CloseCommand() returned 0x%x", 3134 (unsigned int)result); 3135 } 3136 3137 // Check if the command could be closed. 3138 videoEditJava_checkAndThrowRuntimeException(&stopped, pEnv, 3139 (M4NO_ERROR != result), result); 3140 3141 // Free the edit settings. 3142 videoEditClasses_freeEditSettings(&pContext->pEditSettings); 3143 3144 // Set the state to initialized. 3145 pContext->state = ManualEditState_INITIALIZED; 3146 } 3147 3148 } 3149 3150 static void 3151 videoEditor_release( 3152 JNIEnv* pEnv, 3153 jobject thiz) 3154 { 3155 bool released = true; 3156 ManualEditContext* pContext = M4OSA_NULL; 3157 M4OSA_ERR result = M4NO_ERROR; 3158 3159 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_release()"); 3160 3161 // Add a text marker (the condition must always be true). 3162 ADD_TEXT_MARKER_FUN(NULL != pEnv) 3163 3164 // Get the context. 3165 pContext = (ManualEditContext*)videoEditClasses_getContext(&released, pEnv, thiz); 3166 3167 // If context is not set, return (we consider release already happened) 3168 if (pContext == NULL) { 3169 LOGV("videoEditor_release Nothing to do, context is aleady NULL"); 3170 return; 3171 } 3172 3173 3174 // Check if the context is valid (required because the context is dereferenced). 3175 if (released) 3176 { 3177 if (pContext->state != ManualEditState_INITIALIZED) 3178 { 3179 // Change state and get Lock 3180 // This will ensure the generateClip function exits if it is running 3181 pContext->state = ManualEditState_STOPPING; 3182 Mutex::Autolock autoLock(pContext->mLock); 3183 } 3184 3185 // Reset the context. 3186 videoEditClasses_setContext(&released, pEnv, thiz, (void *)M4OSA_NULL); 3187 3188 // Check if the command should be closed. 3189 if (pContext->state != ManualEditState_INITIALIZED) 3190 { 3191 // Close the command. 3192 LOGV("videoEditor_release Calling M4xVSS_CloseCommand() state =%d", 3193 pContext->state); 3194 result = M4xVSS_CloseCommand(pContext->engineContext); 3195 LOGV("videoEditor_release M4xVSS_CloseCommand() returned 0x%x", 3196 (unsigned int)result); 3197 3198 // Check if the command could be closed. 3199 videoEditJava_checkAndThrowRuntimeException(&released, pEnv, 3200 (M4NO_ERROR != result), result); 3201 } 3202 3203 // Cleanup the engine. 3204 LOGV("videoEditor_release Calling M4xVSS_CleanUp()"); 3205 result = M4xVSS_CleanUp(pContext->engineContext); 3206 LOGV("videoEditor_release M4xVSS_CleanUp() returned 0x%x", (unsigned int)result); 3207 3208 // Check if the cleanup succeeded. 3209 videoEditJava_checkAndThrowRuntimeException(&released, pEnv, 3210 (M4NO_ERROR != result), result); 3211 3212 // Free the edit settings. 3213 videoEditClasses_freeEditSettings(&pContext->pEditSettings); 3214 pContext->pEditSettings = M4OSA_NULL; 3215 3216 3217 if(pContext->mPreviewController != M4OSA_NULL) 3218 { 3219 delete pContext->mPreviewController; 3220 pContext->mPreviewController = M4OSA_NULL; 3221 } 3222 3223 // Free the mAudioSettings context. 3224 if(pContext->mAudioSettings != M4OSA_NULL) 3225 { 3226 if (pContext->mAudioSettings->pFile != NULL) { 3227 free(pContext->mAudioSettings->pFile); 3228 pContext->mAudioSettings->pFile = M4OSA_NULL; 3229 } 3230 if (pContext->mAudioSettings->pPCMFilePath != NULL) { 3231 free(pContext->mAudioSettings->pPCMFilePath); 3232 pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL; 3233 } 3234 3235 free(pContext->mAudioSettings); 3236 pContext->mAudioSettings = M4OSA_NULL; 3237 } 3238 // Free video Decoders capabilities 3239 if (pContext->decoders != M4OSA_NULL) { 3240 VideoDecoder *pDecoder = NULL; 3241 VideoComponentCapabilities *pComponents = NULL; 3242 int32_t decoderNumber = pContext->decoders->decoderNumber; 3243 if (pContext->decoders->decoder != NULL && 3244 decoderNumber > 0) { 3245 pDecoder = pContext->decoders->decoder; 3246 for (int32_t k = 0; k < decoderNumber; k++) { 3247 // free each component 3248 LOGV("decoder index :%d",k); 3249 if (pDecoder != NULL && 3250 pDecoder->component != NULL && 3251 pDecoder->componentNumber > 0) { 3252 LOGV("component number %d",pDecoder->componentNumber); 3253 int32_t componentNumber = 3254 pDecoder->componentNumber; 3255 3256 pComponents = pDecoder->component; 3257 for (int32_t i = 0; i< componentNumber; i++) { 3258 LOGV("component index :%d",i); 3259 if (pComponents != NULL && 3260 pComponents->profileLevel != NULL) { 3261 free(pComponents->profileLevel); 3262 pComponents->profileLevel = NULL; 3263 } 3264 pComponents++; 3265 } 3266 free(pDecoder->component); 3267 pDecoder->component = NULL; 3268 } 3269 3270 pDecoder++; 3271 } 3272 free(pContext->decoders->decoder); 3273 pContext->decoders->decoder = NULL; 3274 } 3275 free(pContext->decoders); 3276 pContext->decoders = NULL; 3277 } 3278 3279 videoEditor_freeContext(pEnv, &pContext); 3280 } 3281 } 3282 3283 static int 3284 videoEditor_registerManualEditMethods( 3285 JNIEnv* pEnv) 3286 { 3287 int result = -1; 3288 3289 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3290 "videoEditor_registerManualEditMethods()"); 3291 3292 // Look up the engine class 3293 jclass engineClazz = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME); 3294 3295 // Clear any resulting exceptions. 3296 pEnv->ExceptionClear(); 3297 3298 // Check if the engine class was found. 3299 if (NULL != engineClazz) 3300 { 3301 // Register all the methods. 3302 if (pEnv->RegisterNatives(engineClazz, gManualEditMethods, 3303 sizeof(gManualEditMethods) / sizeof(gManualEditMethods[0])) == JNI_OK) 3304 { 3305 // Success. 3306 result = 0; 3307 } 3308 } 3309 3310 // Return the result. 3311 return(result); 3312 } 3313 3314 /*******Audio Graph*******/ 3315 3316 static M4OSA_UInt32 getDecibelSound(M4OSA_UInt32 value) 3317 { 3318 int dbSound = 1; 3319 3320 if (value == 0) return 0; 3321 3322 if (value > 0x4000 && value <= 0x8000) // 32768 3323 dbSound = 90; 3324 else if (value > 0x2000 && value <= 0x4000) // 16384 3325 dbSound = 84; 3326 else if (value > 0x1000 && value <= 0x2000) // 8192 3327 dbSound = 78; 3328 else if (value > 0x0800 && value <= 0x1000) // 4028 3329 dbSound = 72; 3330 else if (value > 0x0400 && value <= 0x0800) // 2048 3331 dbSound = 66; 3332 else if (value > 0x0200 && value <= 0x0400) // 1024 3333 dbSound = 60; 3334 else if (value > 0x0100 && value <= 0x0200) // 512 3335 dbSound = 54; 3336 else if (value > 0x0080 && value <= 0x0100) // 256 3337 dbSound = 48; 3338 else if (value > 0x0040 && value <= 0x0080) // 128 3339 dbSound = 42; 3340 else if (value > 0x0020 && value <= 0x0040) // 64 3341 dbSound = 36; 3342 else if (value > 0x0010 && value <= 0x0020) // 32 3343 dbSound = 30; 3344 else if (value > 0x0008 && value <= 0x0010) //16 3345 dbSound = 24; 3346 else if (value > 0x0007 && value <= 0x0008) //8 3347 dbSound = 24; 3348 else if (value > 0x0003 && value <= 0x0007) // 4 3349 dbSound = 18; 3350 else if (value > 0x0001 && value <= 0x0003) //2 3351 dbSound = 12; 3352 else if (value > 0x000 && value == 0x0001) // 1 3353 dbSound = 6; 3354 else 3355 dbSound = 0; 3356 3357 return dbSound; 3358 } 3359 3360 typedef struct 3361 { 3362 M4OSA_UInt8 *m_dataAddress; 3363 M4OSA_UInt32 m_bufferSize; 3364 } M4AM_Buffer; 3365 3366 3367 M4OSA_UInt8 logLookUp[256] = { 3368 0,120,137,146,154,159,163,167,171,173,176,178,181,182,184,186,188,189,190,192,193, 3369 194,195,196,198,199,199,200,201,202,203,204,205,205,206,207,207,208,209,209,210, 3370 211,211,212,212,213,213,214,215,215,216,216,216,217,217,218,218,219,219,220,220, 3371 220,221,221,222,222,222,223,223,223,224,224,224,225,225,225,226,226,226,227,227, 3372 227,228,228,228,229,229,229,229,230,230,230,230,231,231,231,232,232,232,232,233, 3373 233,233,233,233,234,234,234,234,235,235,235,235,236,236,236,236,236,237,237,237, 3374 237,237,238,238,238,238,238,239,239,239,239,239,240,240,240,240,240,240,241,241, 3375 241,241,241,241,242,242,242,242,242,242,243,243,243,243,243,243,244,244,244,244, 3376 244,244,245,245,245,245,245,245,245,246,246,246,246,246,246,246,247,247,247,247, 3377 247,247,247,247,248,248,248,248,248,248,248,249,249,249,249,249,249,249,249,250, 3378 250,250,250,250,250,250,250,250,251,251,251,251,251,251,251,251,252,252,252,252, 3379 252,252,252,252,252,253,253,253,253,253,253,253,253,253,253,254,254,254,254,254, 3380 254,254,254,254,255,255,255,255,255,255,255,255,255,255,255}; 3381 3382 M4OSA_ERR M4MA_generateAudioGraphFile(JNIEnv* pEnv, M4OSA_Char* pInputFileURL, 3383 M4OSA_Char* pOutFileURL, 3384 M4OSA_UInt32 samplesPerValue, 3385 M4OSA_UInt32 channels, 3386 M4OSA_UInt32 frameDuration, 3387 ManualEditContext* pContext) 3388 { 3389 M4OSA_ERR err; 3390 M4OSA_Context outFileHandle = M4OSA_NULL; 3391 M4OSA_Context inputFileHandle = M4OSA_NULL; 3392 M4AM_Buffer bufferIn = {0, 0}; 3393 M4OSA_UInt32 peakVolumeDbValue = 0; 3394 M4OSA_UInt32 samplesCountInBytes= 0 , numBytesToRead = 0, index = 0; 3395 M4OSA_UInt32 writeCount = 0, samplesCountBigEndian = 0, volumeValuesCount = 0; 3396 M4OSA_Int32 seekPos = 0; 3397 M4OSA_UInt32 fileSize = 0; 3398 M4OSA_UInt32 totalBytesRead = 0; 3399 M4OSA_UInt32 prevProgress = 0; 3400 bool threadStarted = true; 3401 3402 int dbValue = 0; 3403 M4OSA_Int16 *ptr16 ; 3404 3405 jclass engineClass = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME); 3406 videoEditJava_checkAndThrowIllegalStateException(&threadStarted, pEnv, 3407 (M4OSA_NULL == engineClass), 3408 "not initialized"); 3409 3410 /* register the call back function pointer */ 3411 pContext->onAudioGraphProgressUpdateMethodId = 3412 pEnv->GetMethodID(engineClass, "onAudioGraphExtractProgressUpdate", "(IZ)V"); 3413 3414 3415 /* ENTER */ 3416 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "ENTER - M4MA_generateAudioGraphFile"); 3417 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3418 "Audio Graph samplesPerValue %d channels %d", samplesPerValue, channels); 3419 3420 /****************************************************************************** 3421 OPEN INPUT AND OUTPUT FILES 3422 *******************************************************************************/ 3423 err = M4OSA_fileReadOpen (&inputFileHandle, pInputFileURL, M4OSA_kFileRead); 3424 if (inputFileHandle == M4OSA_NULL) { 3425 VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3426 "M4MA_generateAudioGraphFile: Cannot open input file 0x%lx", err); 3427 return err; 3428 } 3429 3430 /* get the file size for progress */ 3431 err = M4OSA_fileReadGetOption(inputFileHandle, M4OSA_kFileReadGetFileSize, 3432 (M4OSA_Void**)&fileSize); 3433 if ( err != M4NO_ERROR) { 3434 //LVMEL_LOG_ERROR("M4MA_generateAudioGraphFile : File write failed \n"); 3435 jniThrowException(pEnv, "java/lang/IOException", "file size get option failed"); 3436 //return -1; 3437 } 3438 3439 err = M4OSA_fileWriteOpen (&outFileHandle,(M4OSA_Char*) pOutFileURL, 3440 M4OSA_kFileCreate | M4OSA_kFileWrite); 3441 if (outFileHandle == M4OSA_NULL) { 3442 if (inputFileHandle != NULL) 3443 { 3444 M4OSA_fileReadClose(inputFileHandle); 3445 } 3446 return err; 3447 } 3448 3449 /****************************************************************************** 3450 PROCESS THE SAMPLES 3451 *******************************************************************************/ 3452 samplesCountInBytes = (samplesPerValue * sizeof(M4OSA_UInt16) * channels); 3453 3454 bufferIn.m_dataAddress = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(samplesCountInBytes*sizeof(M4OSA_UInt16), 0, 3455 (M4OSA_Char*)"AudioGraph" ); 3456 if ( bufferIn.m_dataAddress != M4OSA_NULL) { 3457 bufferIn.m_bufferSize = samplesCountInBytes*sizeof(M4OSA_UInt16); 3458 } else { 3459 VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3460 "M4MA_generateAudioGraphFile: Malloc failed for bufferIn.m_dataAddress 0x%lx", 3461 M4ERR_ALLOC); 3462 return M4ERR_ALLOC; 3463 } 3464 /* sample to be converted to BIG endian ; store the frame duration */ 3465 samplesCountBigEndian = ((frameDuration>>24)&0xff) | // move byte 3 to byte 0 3466 ((frameDuration<<8)&0xff0000) | // move byte 1 to byte 2 3467 ((frameDuration>>8)&0xff00) | // move byte 2 to byte 1 3468 ((frameDuration<<24)&0xff000000); // byte 0 to byte 3 3469 3470 /* write the samples per value supplied to out file */ 3471 err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&samplesCountBigEndian, 3472 sizeof(M4OSA_UInt32) ); 3473 if (err != M4NO_ERROR) { 3474 jniThrowException(pEnv, "java/lang/IOException", "file write failed"); 3475 } 3476 3477 3478 /* write UIn32 value 0 for no of values as place holder */ 3479 samplesCountBigEndian = 0; /* reusing local var */ 3480 err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&samplesCountBigEndian, 3481 sizeof(M4OSA_UInt32) ); 3482 if (err != M4NO_ERROR) { 3483 jniThrowException(pEnv, "java/lang/IOException", "file write failed"); 3484 } 3485 3486 /* loop until EOF */ 3487 do 3488 { 3489 memset((void *)bufferIn.m_dataAddress,0,bufferIn.m_bufferSize); 3490 3491 numBytesToRead = samplesCountInBytes; 3492 3493 err = M4OSA_fileReadData( inputFileHandle, 3494 (M4OSA_MemAddr8)bufferIn.m_dataAddress, 3495 &numBytesToRead ); 3496 3497 if (err != M4NO_ERROR) { 3498 // if out value of bytes-read is 0, break 3499 if ( numBytesToRead == 0) { 3500 VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", "numBytesToRead 0x%lx", 3501 numBytesToRead); 3502 break; /* stop if file is empty or EOF */ 3503 } 3504 } 3505 3506 ptr16 = (M4OSA_Int16*)bufferIn.m_dataAddress; 3507 3508 peakVolumeDbValue = 0; 3509 index = 0; 3510 3511 // loop through half the lenght frame bytes read 'cause its 16 bits samples 3512 while (index < (numBytesToRead / 2)) { 3513 /* absolute values of 16 bit sample */ 3514 if (ptr16[index] < 0) { 3515 ptr16[index] = -(ptr16[index]); 3516 } 3517 peakVolumeDbValue = (peakVolumeDbValue > (M4OSA_UInt32)ptr16[index] ?\ 3518 peakVolumeDbValue : (M4OSA_UInt32)ptr16[index]); 3519 index++; 3520 } 3521 3522 // move 7 bits , ignore sign bit 3523 dbValue = (peakVolumeDbValue >> 7); 3524 dbValue = logLookUp[(M4OSA_UInt8)dbValue]; 3525 3526 err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&dbValue, sizeof(M4OSA_UInt8) ); 3527 if (err != M4NO_ERROR) { 3528 VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3529 "M4MA_generateAudioGraphFile : File write failed"); 3530 break; 3531 } 3532 3533 volumeValuesCount ++; 3534 totalBytesRead += numBytesToRead; 3535 3536 if ((((totalBytesRead*100)/fileSize)) != prevProgress) { 3537 if ( (pContext->threadProgress != prevProgress) && (prevProgress != 0 )) { 3538 //pContext->threadProgress = prevProgress; 3539 //onWveformProgressUpdateMethodId(prevProgress, 0); 3540 //LVME_callAudioGraphOnProgressUpdate(pContext, 0, prevProgress); 3541 pEnv->CallVoidMethod(pContext->engine, 3542 pContext->onAudioGraphProgressUpdateMethodId, 3543 prevProgress, 0); 3544 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "pContext->threadProgress %d", 3545 prevProgress); 3546 } 3547 } 3548 prevProgress = (((totalBytesRead*100)/fileSize)); 3549 3550 } while (numBytesToRead != 0); 3551 3552 VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", "loop 0x%lx", volumeValuesCount); 3553 3554 /* if some error occured in fwrite */ 3555 if (numBytesToRead != 0) { 3556 //err = -1; 3557 jniThrowException(pEnv, "java/lang/IOException", "numBytesToRead != 0 ; file write failed"); 3558 } 3559 3560 /* write the count in place holder after seek */ 3561 seekPos = sizeof(M4OSA_UInt32); 3562 err = M4OSA_fileWriteSeek(outFileHandle, M4OSA_kFileSeekBeginning, 3563 &seekPos /* after samples per value */); 3564 if ( err != M4NO_ERROR) { 3565 jniThrowException(pEnv, "java/lang/IOException", "file seek failed"); 3566 } else { 3567 volumeValuesCount = ((volumeValuesCount>>24)&0xff) | // move byte 3 to byte 0 3568 ((volumeValuesCount<<8)&0xff0000) | // move byte 1 to byte 2 3569 ((volumeValuesCount>>8)&0xff00) | // move byte 2 to byte 1 3570 ((volumeValuesCount<<24)&0xff000000); // byte 0 to byte 3 3571 3572 err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&volumeValuesCount, 3573 sizeof(M4OSA_UInt32) ); 3574 if ( err != M4NO_ERROR) { 3575 jniThrowException(pEnv, "java/lang/IOException", "file write failed"); 3576 } 3577 } 3578 3579 /****************************************************************************** 3580 CLOSE AND FREE ALLOCATIONS 3581 *******************************************************************************/ 3582 free(bufferIn.m_dataAddress); 3583 M4OSA_fileReadClose(inputFileHandle); 3584 M4OSA_fileWriteClose(outFileHandle); 3585 /* final finish callback */ 3586 pEnv->CallVoidMethod(pContext->engine, pContext->onAudioGraphProgressUpdateMethodId, 100, 0); 3587 3588 /* EXIT */ 3589 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "EXIT - M4MA_generateAudioGraphFile"); 3590 3591 return err; 3592 } 3593 3594 static int videoEditor_generateAudioWaveFormSync (JNIEnv* pEnv, jobject thiz, 3595 jstring pcmfilePath, 3596 jstring outGraphfilePath, 3597 jint frameDuration, jint channels, 3598 jint samplesCount) 3599 { 3600 M4OSA_ERR result = M4NO_ERROR; 3601 ManualEditContext* pContext = M4OSA_NULL; 3602 bool needToBeLoaded = true; 3603 const char *pPCMFilePath, *pStringOutAudioGraphFile; 3604 3605 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3606 "videoEditor_generateAudioWaveFormSync() "); 3607 3608 /* Get the context. */ 3609 pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz); 3610 if (pContext == M4OSA_NULL) { 3611 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3612 "videoEditor_generateAudioWaveFormSync() - pContext is NULL "); 3613 } 3614 3615 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3616 "videoEditor_generateAudioWaveFormSync Retrieving pStringOutAudioGraphFile"); 3617 3618 pPCMFilePath = pEnv->GetStringUTFChars(pcmfilePath, NULL); 3619 if (pPCMFilePath == M4OSA_NULL) { 3620 jniThrowException(pEnv, "java/lang/RuntimeException", 3621 "Input string PCMFilePath is null"); 3622 result = M4ERR_PARAMETER; 3623 goto out; 3624 } 3625 3626 pStringOutAudioGraphFile = pEnv->GetStringUTFChars(outGraphfilePath, NULL); 3627 if (pStringOutAudioGraphFile == M4OSA_NULL) { 3628 jniThrowException(pEnv, "java/lang/RuntimeException", 3629 "Input string outGraphfilePath is null"); 3630 result = M4ERR_PARAMETER; 3631 goto out2; 3632 } 3633 3634 VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3635 "videoEditor_generateAudioWaveFormSync Generate the waveform data %s %d %d %d", 3636 pStringOutAudioGraphFile, frameDuration, channels, samplesCount); 3637 3638 /* Generate the waveform */ 3639 result = M4MA_generateAudioGraphFile(pEnv, (M4OSA_Char*) pPCMFilePath, 3640 (M4OSA_Char*) pStringOutAudioGraphFile, 3641 (M4OSA_UInt32) samplesCount, 3642 (M4OSA_UInt32) channels, 3643 (M4OSA_UInt32)frameDuration, 3644 pContext); 3645 3646 pEnv->ReleaseStringUTFChars(outGraphfilePath, pStringOutAudioGraphFile); 3647 3648 out2: 3649 if (pPCMFilePath != NULL) { 3650 pEnv->ReleaseStringUTFChars(pcmfilePath, pPCMFilePath); 3651 } 3652 3653 out: 3654 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", 3655 "videoEditor_generateAudioWaveFormSync pContext->bSkipState "); 3656 3657 return result; 3658 } 3659 3660 /******** End Audio Graph *******/ 3661 jint JNI_OnLoad( 3662 JavaVM* pVm, 3663 void* pReserved) 3664 { 3665 void* pEnv = NULL; 3666 bool needToBeInitialized = true; 3667 jint result = -1; 3668 3669 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "JNI_OnLoad()"); 3670 3671 // Add a text marker (the condition must always be true). 3672 ADD_TEXT_MARKER_FUN(NULL != pVm) 3673 3674 // Check the JNI version. 3675 if (pVm->GetEnv(&pEnv, JNI_VERSION_1_4) == JNI_OK) 3676 { 3677 // Add a code marker (the condition must always be true). 3678 ADD_CODE_MARKER_FUN(NULL != pEnv) 3679 3680 // Register the manual edit JNI methods. 3681 if (videoEditor_registerManualEditMethods((JNIEnv*)pEnv) == 0) 3682 { 3683 // Initialize the classes. 3684 videoEditClasses_init(&needToBeInitialized, (JNIEnv*)pEnv); 3685 if (needToBeInitialized) 3686 { 3687 // Success, return valid version number. 3688 result = JNI_VERSION_1_4; 3689 } 3690 } 3691 } 3692 3693 // Return the result. 3694 return(result); 3695 } 3696 3697