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