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