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