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