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