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