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