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