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