1/*
2 * Copyright (C) 2010 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
17package android.media.videoeditor;
18
19import java.io.File;
20import java.io.IOException;
21import java.math.BigDecimal;
22import java.nio.IntBuffer;
23import java.util.Iterator;
24import java.util.List;
25import java.util.concurrent.Semaphore;
26
27import android.graphics.Bitmap;
28import android.graphics.BitmapFactory;
29import android.graphics.Canvas;
30import android.graphics.Paint;
31import android.graphics.Rect;
32import android.graphics.Matrix;
33import android.media.videoeditor.VideoEditor.ExportProgressListener;
34import android.media.videoeditor.VideoEditor.PreviewProgressListener;
35import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
36import android.util.Log;
37import android.util.Pair;
38import android.view.Surface;
39
40/**
41 *This class provide Native methods to be used by MediaArtist {@hide}
42 */
43class MediaArtistNativeHelper {
44    private static final String TAG = "MediaArtistNativeHelper";
45
46    static {
47        System.loadLibrary("videoeditor_jni");
48    }
49
50    private static final int MAX_THUMBNAIL_PERMITTED = 8;
51
52    public static final int TASK_LOADING_SETTINGS = 1;
53    public static final int TASK_ENCODING = 2;
54
55    /**
56     *  The resize paint
57     */
58    private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
59
60    private final VideoEditor mVideoEditor;
61    /*
62     *  Semaphore to control preview calls
63     */
64    private final Semaphore mLock;
65
66    private EditSettings mStoryBoardSettings;
67
68    private String mOutputFilename;
69
70    private PreviewClipProperties mClipProperties = null;
71
72    private EditSettings mPreviewEditSettings;
73
74    private AudioSettings mAudioSettings = null;
75
76    private AudioTrack mAudioTrack = null;
77
78    private boolean mInvalidatePreviewArray = true;
79
80    private boolean mRegenerateAudio = true;
81
82    private String mExportFilename = null;
83    private int mExportVideoCodec = 0;
84    private int mExportAudioCodec = 0;
85    private int mProgressToApp;
86
87    private String mRenderPreviewOverlayFile;
88    private int mRenderPreviewRenderingMode;
89
90    private boolean mIsFirstProgress;
91
92    private static final String AUDIO_TRACK_PCM_FILE = "AudioPcm.pcm";
93
94    // Processing indication
95    public static final int PROCESSING_NONE          = 0;
96    public static final int PROCESSING_AUDIO_PCM     = 1;
97    public static final int PROCESSING_TRANSITION    = 2;
98    public static final int PROCESSING_KENBURNS      = 3;
99    public static final int PROCESSING_INTERMEDIATE1 = 11;
100    public static final int PROCESSING_INTERMEDIATE2 = 12;
101    public static final int PROCESSING_INTERMEDIATE3 = 13;
102    public static final int PROCESSING_EXPORT        = 20;
103
104    private int mProcessingState;
105    private Object mProcessingObject;
106    private PreviewProgressListener mPreviewProgressListener;
107    private ExportProgressListener mExportProgressListener;
108    private ExtractAudioWaveformProgressListener mExtractAudioWaveformProgressListener;
109    private MediaProcessingProgressListener mMediaProcessingProgressListener;
110    private final String mProjectPath;
111
112    private long mPreviewProgress;
113
114    private String mAudioTrackPCMFilePath;
115
116    private int mTotalClips = 0;
117
118    private boolean mErrorFlagSet = false;
119
120    @SuppressWarnings("unused")
121    private int mManualEditContext;
122
123    /* Listeners */
124
125    /**
126     * Interface definition for a listener to be invoked when there is an update
127     * in a running task.
128     */
129    public interface OnProgressUpdateListener {
130        /**
131         * Called when there is an update.
132         *
133         * @param taskId id of the task reporting an update.
134         * @param progress progress of the task [0..100].
135         * @see BasicEdit#TASK_ENCODING
136         */
137        public void OnProgressUpdate(int taskId, int progress);
138    }
139
140    /** Defines the version. */
141    public final class Version {
142
143        /** Major version number */
144        public int major;
145
146        /** Minor version number */
147        public int minor;
148
149        /** Revision number */
150        public int revision;
151
152        /** VIDEOEDITOR major version number */
153        private static final int VIDEOEDITOR_MAJOR_VERSION = 0;
154
155        /** VIDEOEDITOR minor version number */
156        private static final int VIDEOEDITOR_MINOR_VERSION = 0;
157
158        /** VIDEOEDITOR revision number */
159        private static final int VIDEOEDITOR_REVISION_VERSION = 1;
160
161        /** Method which returns the current VIDEOEDITOR version */
162        public Version getVersion() {
163            Version version = new Version();
164
165            version.major = Version.VIDEOEDITOR_MAJOR_VERSION;
166            version.minor = Version.VIDEOEDITOR_MINOR_VERSION;
167            version.revision = Version.VIDEOEDITOR_REVISION_VERSION;
168
169            return version;
170        }
171    }
172
173    /**
174     * Defines output audio formats.
175     */
176    public final class AudioFormat {
177        /** No audio present in output clip. Used to generate video only clip */
178        public static final int NO_AUDIO = 0;
179
180        /** AMR Narrow Band. */
181        public static final int AMR_NB = 1;
182
183        /** Advanced Audio Coding (AAC). */
184        public static final int AAC = 2;
185
186        /** Advanced Audio Codec Plus (HE-AAC v1). */
187        public static final int AAC_PLUS = 3;
188
189        /** Advanced Audio Codec Plus (HE-AAC v2). */
190        public static final int ENHANCED_AAC_PLUS = 4;
191
192        /** MPEG layer 3 (MP3). */
193        public static final int MP3 = 5;
194
195        /** Enhanced Variable RateCodec (EVRC). */
196        public static final int EVRC = 6;
197
198        /** PCM (PCM). */
199        public static final int PCM = 7;
200
201        /** No transcoding. Output audio format is same as input audio format */
202        public static final int NULL_AUDIO = 254;
203
204        /** Unsupported audio format. */
205        public static final int UNSUPPORTED_AUDIO = 255;
206    }
207
208    /**
209     * Defines audio sampling frequencies.
210     */
211    public final class AudioSamplingFrequency {
212        /**
213         * Default sampling frequency. Uses the default frequency for a specific
214         * audio format. For AAC the only supported (and thus default) sampling
215         * frequency is 16 kHz. For this audio format the sampling frequency in
216         * the OutputParams.
217         **/
218        public static final int FREQ_DEFAULT = 0;
219
220        /** Audio sampling frequency of 8000 Hz. */
221        public static final int FREQ_8000 = 8000;
222
223        /** Audio sampling frequency of 11025 Hz. */
224        public static final int FREQ_11025 = 11025;
225
226        /** Audio sampling frequency of 12000 Hz. */
227        public static final int FREQ_12000 = 12000;
228
229        /** Audio sampling frequency of 16000 Hz. */
230        public static final int FREQ_16000 = 16000;
231
232        /** Audio sampling frequency of 22050 Hz. */
233        public static final int FREQ_22050 = 22050;
234
235        /** Audio sampling frequency of 24000 Hz. */
236        public static final int FREQ_24000 = 24000;
237
238        /** Audio sampling frequency of 32000 Hz. */
239        public static final int FREQ_32000 = 32000;
240
241        /** Audio sampling frequency of 44100 Hz. */
242        public static final int FREQ_44100 = 44100;
243
244        /** Audio sampling frequency of 48000 Hz. Not available for output file. */
245        public static final int FREQ_48000 = 48000;
246    }
247
248    /**
249     * Defines the supported fixed audio and video bitrates. These values are
250     * for output audio video only.
251     */
252    public final class Bitrate {
253        /** Variable bitrate. Means no bitrate regulation */
254        public static final int VARIABLE = -1;
255
256        /** An undefined bitrate. */
257        public static final int UNDEFINED = 0;
258
259        /** A bitrate of 9.2 kbits/s. */
260        public static final int BR_9_2_KBPS = 9200;
261
262        /** A bitrate of 12.2 kbits/s. */
263        public static final int BR_12_2_KBPS = 12200;
264
265        /** A bitrate of 16 kbits/s. */
266        public static final int BR_16_KBPS = 16000;
267
268        /** A bitrate of 24 kbits/s. */
269        public static final int BR_24_KBPS = 24000;
270
271        /** A bitrate of 32 kbits/s. */
272        public static final int BR_32_KBPS = 32000;
273
274        /** A bitrate of 48 kbits/s. */
275        public static final int BR_48_KBPS = 48000;
276
277        /** A bitrate of 64 kbits/s. */
278        public static final int BR_64_KBPS = 64000;
279
280        /** A bitrate of 96 kbits/s. */
281        public static final int BR_96_KBPS = 96000;
282
283        /** A bitrate of 128 kbits/s. */
284        public static final int BR_128_KBPS = 128000;
285
286        /** A bitrate of 192 kbits/s. */
287        public static final int BR_192_KBPS = 192000;
288
289        /** A bitrate of 256 kbits/s. */
290        public static final int BR_256_KBPS = 256000;
291
292        /** A bitrate of 288 kbits/s. */
293        public static final int BR_288_KBPS = 288000;
294
295        /** A bitrate of 384 kbits/s. */
296        public static final int BR_384_KBPS = 384000;
297
298        /** A bitrate of 512 kbits/s. */
299        public static final int BR_512_KBPS = 512000;
300
301        /** A bitrate of 800 kbits/s. */
302        public static final int BR_800_KBPS = 800000;
303
304        /** A bitrate of 2 Mbits/s. */
305        public static final int BR_2_MBPS = 2000000;
306
307        /** A bitrate of 5 Mbits/s. */
308        public static final int BR_5_MBPS = 5000000;
309
310        /** A bitrate of 8 Mbits/s. */
311        public static final int BR_8_MBPS = 8000000;
312    }
313
314    /**
315     * Defines all supported file types.
316     */
317    public final class FileType {
318        /** 3GPP file type. */
319        public static final int THREE_GPP = 0;
320
321        /** MP4 file type. */
322        public static final int MP4 = 1;
323
324        /** AMR file type. */
325        public static final int AMR = 2;
326
327        /** MP3 audio file type. */
328        public static final int MP3 = 3;
329
330        /** PCM audio file type. */
331        public static final int PCM = 4;
332
333        /** JPEG image file type. */
334        public static final int JPG = 5;
335
336        /** GIF image file type. */
337        public static final int GIF = 7;
338
339        /** PNG image file type. */
340        public static final int PNG = 8;
341
342        /** M4V file type. */
343        public static final int M4V = 10;
344
345        /** Unsupported file type. */
346        public static final int UNSUPPORTED = 255;
347    }
348
349    /**
350     * Defines rendering types. Rendering can only be applied to files
351     * containing video streams.
352     **/
353    public final class MediaRendering {
354        /**
355         * Resize to fit the output video with changing the aspect ratio if
356         * needed.
357         */
358        public static final int RESIZING = 0;
359
360        /**
361         * Crop the input video to fit it with the output video resolution.
362         **/
363        public static final int CROPPING = 1;
364
365        /**
366         * Resize to fit the output video resolution but maintain the aspect
367         * ratio. This framing type adds black borders if needed.
368         */
369        public static final int BLACK_BORDERS = 2;
370    }
371
372    /**
373     * Defines the results.
374     */
375    public final class Result {
376        /** No error. result OK */
377        public static final int NO_ERROR = 0;
378
379        /** File not found */
380        public static final int ERR_FILE_NOT_FOUND = 1;
381
382        /**
383         * In case of UTF8 conversion, the size of the converted path will be
384         * more than the corresponding allocated buffer.
385         */
386        public static final int ERR_BUFFER_OUT_TOO_SMALL = 2;
387
388        /** Invalid file type. */
389        public static final int ERR_INVALID_FILE_TYPE = 3;
390
391        /** Invalid effect kind. */
392        public static final int ERR_INVALID_EFFECT_KIND = 4;
393
394        /** Invalid video effect. */
395        public static final int ERR_INVALID_VIDEO_EFFECT_TYPE = 5;
396
397        /** Invalid audio effect. */
398        public static final int ERR_INVALID_AUDIO_EFFECT_TYPE = 6;
399
400        /** Invalid video transition. */
401        public static final int ERR_INVALID_VIDEO_TRANSITION_TYPE = 7;
402
403        /** Invalid audio transition. */
404        public static final int ERR_INVALID_AUDIO_TRANSITION_TYPE = 8;
405
406        /** Invalid encoding frame rate. */
407        public static final int ERR_INVALID_VIDEO_ENCODING_FRAME_RATE = 9;
408
409        /** External effect is called but this function is not set. */
410        public static final int ERR_EXTERNAL_EFFECT_NULL = 10;
411
412        /** External transition is called but this function is not set. */
413        public static final int ERR_EXTERNAL_TRANSITION_NULL = 11;
414
415        /** Begin time cut is larger than the video clip duration. */
416        public static final int ERR_BEGIN_CUT_LARGER_THAN_DURATION = 12;
417
418        /** Begin cut time is larger or equal than end cut. */
419        public static final int ERR_BEGIN_CUT_LARGER_THAN_END_CUT = 13;
420
421        /** Two consecutive transitions are overlapping on one clip. */
422        public static final int ERR_OVERLAPPING_TRANSITIONS = 14;
423
424        /** Internal error, type size mismatch. */
425        public static final int ERR_ANALYSIS_DATA_SIZE_TOO_SMALL = 15;
426
427        /** An input 3GPP file is invalid/corrupted. */
428        public static final int ERR_INVALID_3GPP_FILE = 16;
429
430        /** A file contains an unsupported video format. */
431        public static final int ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT = 17;
432
433        /** A file contains an unsupported audio format. */
434        public static final int ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT = 18;
435
436        /** A file format is not supported. */
437        public static final int ERR_AMR_EDITING_UNSUPPORTED = 19;
438
439        /** An input clip has an unexpectedly large Video AU. */
440        public static final int ERR_INPUT_VIDEO_AU_TOO_LARGE = 20;
441
442        /** An input clip has an unexpectedly large Audio AU. */
443        public static final int ERR_INPUT_AUDIO_AU_TOO_LARGE = 21;
444
445        /** An input clip has a corrupted Audio AU. */
446        public static final int ERR_INPUT_AUDIO_CORRUPTED_AU = 22;
447
448        /** The video encoder encountered an Access Unit error. */
449        public static final int ERR_ENCODER_ACCES_UNIT_ERROR = 23;
450
451        /** Unsupported video format for Video Editing. */
452        public static final int ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT = 24;
453
454        /** Unsupported H263 profile for Video Editing. */
455        public static final int ERR_EDITING_UNSUPPORTED_H263_PROFILE = 25;
456
457        /** Unsupported MPEG-4 profile for Video Editing. */
458        public static final int ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE = 26;
459
460        /** Unsupported MPEG-4 RVLC tool for Video Editing. */
461        public static final int ERR_EDITING_UNSUPPORTED_MPEG4_RVLC = 27;
462
463        /** Unsupported audio format for Video Editing. */
464        public static final int ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT = 28;
465
466        /** File contains no supported stream. */
467        public static final int ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE = 29;
468
469        /** File contains no video stream or an unsupported video stream. */
470        public static final int ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE = 30;
471
472        /** Internal error, clip analysis version mismatch. */
473        public static final int ERR_INVALID_CLIP_ANALYSIS_VERSION = 31;
474
475        /**
476         * At least one of the clip analysis has been generated on another
477         * platform (WIN32, ARM, etc.).
478         */
479        public static final int ERR_INVALID_CLIP_ANALYSIS_PLATFORM = 32;
480
481        /** Clips don't have the same video format (H263 or MPEG4). */
482        public static final int ERR_INCOMPATIBLE_VIDEO_FORMAT = 33;
483
484        /** Clips don't have the same frame size. */
485        public static final int ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE = 34;
486
487        /** Clips don't have the same MPEG-4 time scale. */
488        public static final int ERR_INCOMPATIBLE_VIDEO_TIME_SCALE = 35;
489
490        /** Clips don't have the same use of MPEG-4 data partitioning. */
491        public static final int ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING = 36;
492
493        /** MP3 clips can't be assembled. */
494        public static final int ERR_UNSUPPORTED_MP3_ASSEMBLY = 37;
495
496        /**
497         * The input 3GPP file does not contain any supported audio or video
498         * track.
499         */
500        public static final int ERR_NO_SUPPORTED_STREAM_IN_FILE = 38;
501
502        /**
503         * The Volume of the added audio track (AddVolume) must be strictly
504         * superior than zero.
505         */
506        public static final int ERR_ADDVOLUME_EQUALS_ZERO = 39;
507
508        /**
509         * The time at which an audio track is added can't be higher than the
510         * input video track duration..
511         */
512        public static final int ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION = 40;
513
514        /** The audio track file format setting is undefined. */
515        public static final int ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT = 41;
516
517        /** The added audio track stream has an unsupported format. */
518        public static final int ERR_UNSUPPORTED_ADDED_AUDIO_STREAM = 42;
519
520        /** The audio mixing feature doesn't support the audio track type. */
521        public static final int ERR_AUDIO_MIXING_UNSUPPORTED = 43;
522
523        /** The audio mixing feature doesn't support MP3 audio tracks. */
524        public static final int ERR_AUDIO_MIXING_MP3_UNSUPPORTED = 44;
525
526        /**
527         * An added audio track limits the available features: uiAddCts must be
528         * 0 and bRemoveOriginal must be true.
529         */
530        public static final int ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK = 45;
531
532        /**
533         * An added audio track limits the available features: uiAddCts must be
534         * 0 and bRemoveOriginal must be true.
535         */
536        public static final int ERR_FEATURE_UNSUPPORTED_WITH_AAC = 46;
537
538        /** Input audio track is not of a type that can be mixed with output. */
539        public static final int ERR_AUDIO_CANNOT_BE_MIXED = 47;
540
541        /** Input audio track is not AMR-NB, so it can't be mixed with output. */
542        public static final int ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED = 48;
543
544        /**
545         * An added EVRC audio track limit the available features: uiAddCts must
546         * be 0 and bRemoveOriginal must be true.
547         */
548        public static final int ERR_FEATURE_UNSUPPORTED_WITH_EVRC = 49;
549
550        /** H263 profiles other than 0 are not supported. */
551        public static final int ERR_H263_PROFILE_NOT_SUPPORTED = 51;
552
553        /** File contains no video stream or an unsupported video stream. */
554        public static final int ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE = 52;
555
556        /** Transcoding of the input file(s) is necessary. */
557        public static final int WAR_TRANSCODING_NECESSARY = 53;
558
559        /**
560         * The size of the output file will exceed the maximum configured value.
561         */
562        public static final int WAR_MAX_OUTPUT_SIZE_EXCEEDED = 54;
563
564        /** The time scale is too big. */
565        public static final int WAR_TIMESCALE_TOO_BIG = 55;
566
567        /** The year is out of range */
568        public static final int ERR_CLOCK_BAD_REF_YEAR = 56;
569
570        /** The directory could not be opened */
571        public static final int ERR_DIR_OPEN_FAILED = 57;
572
573        /** The directory could not be read */
574        public static final int ERR_DIR_READ_FAILED = 58;
575
576        /** There are no more entries in the current directory */
577        public static final int ERR_DIR_NO_MORE_ENTRY = 59;
578
579        /** The input parameter/s has error */
580        public static final int ERR_PARAMETER = 60;
581
582        /** There is a state machine error */
583        public static final int ERR_STATE = 61;
584
585        /** Memory allocation failed */
586        public static final int ERR_ALLOC = 62;
587
588        /** Context is invalid */
589        public static final int ERR_BAD_CONTEXT = 63;
590
591        /** Context creation failed */
592        public static final int ERR_CONTEXT_FAILED = 64;
593
594        /** Invalid stream ID */
595        public static final int ERR_BAD_STREAM_ID = 65;
596
597        /** Invalid option ID */
598        public static final int ERR_BAD_OPTION_ID = 66;
599
600        /** The option is write only */
601        public static final int ERR_WRITE_ONLY = 67;
602
603        /** The option is read only */
604        public static final int ERR_READ_ONLY = 68;
605
606        /** The feature is not implemented in this version */
607        public static final int ERR_NOT_IMPLEMENTED = 69;
608
609        /** The media type is not supported */
610        public static final int ERR_UNSUPPORTED_MEDIA_TYPE = 70;
611
612        /** No data to be encoded */
613        public static final int WAR_NO_DATA_YET = 71;
614
615        /** No data to be decoded */
616        public static final int WAR_NO_MORE_STREAM = 72;
617
618        /** Time stamp is invalid */
619        public static final int WAR_INVALID_TIME = 73;
620
621        /** No more data to be decoded */
622        public static final int WAR_NO_MORE_AU = 74;
623
624        /** Semaphore timed out */
625        public static final int WAR_TIME_OUT = 75;
626
627        /** Memory buffer is full */
628        public static final int WAR_BUFFER_FULL = 76;
629
630        /** Server has asked for redirection */
631        public static final int WAR_REDIRECT = 77;
632
633        /** Too many streams in input */
634        public static final int WAR_TOO_MUCH_STREAMS = 78;
635
636        /** The file cannot be opened/ written into as it is locked */
637        public static final int ERR_FILE_LOCKED = 79;
638
639        /** The file access mode is invalid */
640        public static final int ERR_FILE_BAD_MODE_ACCESS = 80;
641
642        /** The file pointer points to an invalid location */
643        public static final int ERR_FILE_INVALID_POSITION = 81;
644
645        /** Invalid string */
646        public static final int ERR_STR_BAD_STRING = 94;
647
648        /** The input string cannot be converted */
649        public static final int ERR_STR_CONV_FAILED = 95;
650
651        /** The string size is too large */
652        public static final int ERR_STR_OVERFLOW = 96;
653
654        /** Bad string arguments */
655        public static final int ERR_STR_BAD_ARGS = 97;
656
657        /** The string value is larger than maximum size allowed */
658        public static final int WAR_STR_OVERFLOW = 98;
659
660        /** The string value is not present in this comparison operation */
661        public static final int WAR_STR_NOT_FOUND = 99;
662
663        /** The thread is not started */
664        public static final int ERR_THREAD_NOT_STARTED = 100;
665
666        /** Trancoding done warning */
667        public static final int WAR_TRANSCODING_DONE = 101;
668
669        /** Unsupported mediatype */
670        public static final int WAR_MEDIATYPE_NOT_SUPPORTED = 102;
671
672        /** Input file contains invalid/unsupported streams */
673        public static final int ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM = 103;
674
675        /** Invalid input file */
676        public static final int ERR_INVALID_INPUT_FILE = 104;
677
678        /** Invalid output video format */
679        public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT = 105;
680
681        /** Invalid output video frame size */
682        public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE = 106;
683
684        /** Invalid output video frame rate */
685        public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE = 107;
686
687        /** Invalid output audio format */
688        public static final int ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT = 108;
689
690        /** Invalid video frame size for H.263 */
691        public static final int ERR_INVALID_VIDEO_FRAME_SIZE_FOR_H263 = 109;
692
693        /** Invalid video frame rate for H.263 */
694        public static final int ERR_INVALID_VIDEO_FRAME_RATE_FOR_H263 = 110;
695
696        /** invalid playback duration */
697        public static final int ERR_DURATION_IS_NULL = 111;
698
699        /** Invalid H.263 profile in file */
700        public static final int ERR_H263_FORBIDDEN_IN_MP4_FILE = 112;
701
702        /** Invalid AAC sampling frequency */
703        public static final int ERR_INVALID_AAC_SAMPLING_FREQUENCY = 113;
704
705        /** Audio conversion failure */
706        public static final int ERR_AUDIO_CONVERSION_FAILED = 114;
707
708        /** Invalid trim start and end times */
709        public static final int ERR_BEGIN_CUT_EQUALS_END_CUT = 115;
710
711        /** End time smaller than start time for trim */
712        public static final int ERR_END_CUT_SMALLER_THAN_BEGIN_CUT = 116;
713
714        /** Output file size is small */
715        public static final int ERR_MAXFILESIZE_TOO_SMALL = 117;
716
717        /** Output video bitrate is too low */
718        public static final int ERR_VIDEOBITRATE_TOO_LOW = 118;
719
720        /** Output audio bitrate is too low */
721        public static final int ERR_AUDIOBITRATE_TOO_LOW = 119;
722
723        /** Output video bitrate is too high */
724        public static final int ERR_VIDEOBITRATE_TOO_HIGH = 120;
725
726        /** Output audio bitrate is too high */
727        public static final int ERR_AUDIOBITRATE_TOO_HIGH = 121;
728
729        /** Output file size is too small */
730        public static final int ERR_OUTPUT_FILE_SIZE_TOO_SMALL = 122;
731
732        /** Unknown stream type */
733        public static final int ERR_READER_UNKNOWN_STREAM_TYPE = 123;
734
735        /** Invalid metadata in input stream */
736        public static final int WAR_READER_NO_METADATA = 124;
737
738        /** Invalid file reader info warning */
739        public static final int WAR_READER_INFORMATION_NOT_PRESENT = 125;
740
741        /** Warning to indicate the the writer is being stopped */
742        public static final int WAR_WRITER_STOP_REQ = 131;
743
744        /** Video decoder failed to provide frame for transcoding */
745        public static final int WAR_VIDEORENDERER_NO_NEW_FRAME = 132;
746
747        /** Video deblocking filter is not implemented */
748        public static final int WAR_DEBLOCKING_FILTER_NOT_IMPLEMENTED = 133;
749
750        /** H.263 decoder profile not supported */
751        public static final int ERR_DECODER_H263_PROFILE_NOT_SUPPORTED = 134;
752
753        /** The input file contains unsupported H.263 profile */
754        public static final int ERR_DECODER_H263_NOT_BASELINE = 135;
755
756        /** There is no more space to store the output file */
757        public static final int ERR_NOMORE_SPACE_FOR_FILE = 136;
758
759        /** Internal error. */
760        public static final int ERR_INTERNAL = 255;
761    }
762
763    /**
764     * Defines output video formats.
765     */
766    public final class VideoFormat {
767        /** No video present in output clip. Used to generate audio only clip */
768        public static final int NO_VIDEO = 0;
769
770        /** H263 video format. */
771        public static final int H263 = 1;
772
773        /** H264 video */
774        public static final int H264 = 2;
775
776        /** MPEG4 video format. */
777        public static final int MPEG4 = 3;
778
779        /** No transcoding. Output video format is same as input video format */
780        public static final int NULL_VIDEO = 254;
781
782        /** Unsupported video format. */
783        public static final int UNSUPPORTED = 255;
784    }
785
786    /** Defines video frame sizes. */
787    public final class VideoFrameSize {
788
789        public static final int SIZE_UNDEFINED = -1;
790
791        /** SQCIF 128 x 96 pixels. */
792        public static final int SQCIF = 0;
793
794        /** QQVGA 160 x 120 pixels. */
795        public static final int QQVGA = 1;
796
797        /** QCIF 176 x 144 pixels. */
798        public static final int QCIF = 2;
799
800        /** QVGA 320 x 240 pixels. */
801        public static final int QVGA = 3;
802
803        /** CIF 352 x 288 pixels. */
804        public static final int CIF = 4;
805
806        /** VGA 640 x 480 pixels. */
807        public static final int VGA = 5;
808
809        /** WVGA 800 X 480 pixels */
810        public static final int WVGA = 6;
811
812        /** NTSC 720 X 480 pixels */
813        public static final int NTSC = 7;
814
815        /** 640 x 360 */
816        public static final int nHD = 8;
817
818        /** 854 x 480 */
819        public static final int WVGA16x9 = 9;
820
821        /** 720p 1280 X 720 */
822        public static final int V720p = 10;
823
824        /** W720p 1080 x 720 */
825        public static final int W720p = 11;
826
827        /** S720p 960 x 720 */
828        public static final int S720p = 12;
829
830        /** 1080p 1920 x 1080 */
831        public static final int V1080p = 13;
832    }
833
834    /**
835     * Defines output video frame rates.
836     */
837    public final class VideoFrameRate {
838        /** Frame rate of 5 frames per second. */
839        public static final int FR_5_FPS = 0;
840
841        /** Frame rate of 7.5 frames per second. */
842        public static final int FR_7_5_FPS = 1;
843
844        /** Frame rate of 10 frames per second. */
845        public static final int FR_10_FPS = 2;
846
847        /** Frame rate of 12.5 frames per second. */
848        public static final int FR_12_5_FPS = 3;
849
850        /** Frame rate of 15 frames per second. */
851        public static final int FR_15_FPS = 4;
852
853        /** Frame rate of 20 frames per second. */
854        public static final int FR_20_FPS = 5;
855
856        /** Frame rate of 25 frames per second. */
857        public static final int FR_25_FPS = 6;
858
859        /** Frame rate of 30 frames per second. */
860        public static final int FR_30_FPS = 7;
861    }
862
863    /**
864     * Defines Video Effect Types.
865     */
866    public static class VideoEffect {
867
868        public static final int NONE = 0;
869
870        public static final int FADE_FROM_BLACK = 8;
871
872        public static final int FADE_TO_BLACK = 16;
873
874        public static final int EXTERNAL = 256;
875
876        public static final int BLACK_AND_WHITE = 257;
877
878        public static final int PINK = 258;
879
880        public static final int GREEN = 259;
881
882        public static final int SEPIA = 260;
883
884        public static final int NEGATIVE = 261;
885
886        public static final int FRAMING = 262;
887
888        public static final int TEXT = 263;
889
890        public static final int ZOOM_IN = 264;
891
892        public static final int ZOOM_OUT = 265;
893
894        public static final int FIFTIES = 266;
895
896        public static final int COLORRGB16 = 267;
897
898        public static final int GRADIENT = 268;
899    }
900
901    /**
902     * Defines the video transitions.
903     */
904    public static class VideoTransition {
905        /** No transition */
906        public static final int NONE = 0;
907
908        /** Cross fade transition */
909        public static final int CROSS_FADE = 1;
910
911        /** External transition. Currently not available. */
912        public static final int EXTERNAL = 256;
913
914        /** AlphaMagic transition. */
915        public static final int ALPHA_MAGIC = 257;
916
917        /** Slide transition. */
918        public static final int SLIDE_TRANSITION = 258;
919
920        /** Fade to black transition. */
921        public static final int FADE_BLACK = 259;
922    }
923
924    /**
925     * Defines settings for the AlphaMagic transition
926     */
927    public static class AlphaMagicSettings {
928        /** Name of the alpha file (JPEG file). */
929        public String file;
930
931        /** Blending percentage [0..100] 0 = no blending. */
932        public int blendingPercent;
933
934        /** Invert the default rotation direction of the AlphaMagic effect. */
935        public boolean invertRotation;
936
937        public int rgbWidth;
938        public int rgbHeight;
939    }
940
941    /** Defines the direction of the Slide transition. */
942    public static final class SlideDirection {
943
944        /** Right out left in. */
945        public static final int RIGHT_OUT_LEFT_IN = 0;
946
947        /** Left out right in. */
948        public static final int LEFT_OUT_RIGTH_IN = 1;
949
950        /** Top out bottom in. */
951        public static final int TOP_OUT_BOTTOM_IN = 2;
952
953        /** Bottom out top in */
954        public static final int BOTTOM_OUT_TOP_IN = 3;
955    }
956
957    /** Defines the Slide transition settings. */
958    public static class SlideTransitionSettings {
959        /**
960         * Direction of the slide transition. See {@link SlideDirection
961         * SlideDirection} for valid values.
962         */
963        public int direction;
964    }
965
966    /**
967     * Defines the settings of a single clip.
968     */
969    public static class ClipSettings {
970
971        /**
972         * The path to the clip file.
973         * <p>
974         * File format of the clip, it can be:
975         * <ul>
976         * <li>3GP file containing MPEG4/H263/H264 video and AAC/AMR audio
977         * <li>JPG file
978         * </ul>
979         */
980
981        public String clipPath;
982
983        /**
984         * The path of the decoded file. This is used only for image files.
985         */
986        public String clipDecodedPath;
987
988        /**
989         * The path of the Original file. This is used only for image files.
990         */
991        public String clipOriginalPath;
992
993        /**
994         * File type of the clip. See {@link FileType FileType} for valid
995         * values.
996         */
997        public int fileType;
998
999        /** Begin of the cut in the clip in milliseconds. */
1000        public int beginCutTime;
1001
1002        /**
1003         * End of the cut in the clip in milliseconds. Set both
1004         * <code>beginCutTime</code> and <code>endCutTime</code> to
1005         * <code>0</code> to get the full length of the clip without a cut. In
1006         * case of JPG clip, this is the duration of the JPEG file.
1007         */
1008        public int endCutTime;
1009
1010        /**
1011         * Begin of the cut in the clip in percentage of the file duration.
1012         */
1013        public int beginCutPercent;
1014
1015        /**
1016         * End of the cut in the clip in percentage of the file duration. Set
1017         * both <code>beginCutPercent</code> and <code>endCutPercent</code> to
1018         * <code>0</code> to get the full length of the clip without a cut.
1019         */
1020        public int endCutPercent;
1021
1022        /** Enable panning and zooming. */
1023        public boolean panZoomEnabled;
1024
1025        /** Zoom percentage at start of clip. 0 = no zoom, 100 = full zoom */
1026        public int panZoomPercentStart;
1027
1028        /** Top left X coordinate at start of clip. */
1029        public int panZoomTopLeftXStart;
1030
1031        /** Top left Y coordinate at start of clip. */
1032        public int panZoomTopLeftYStart;
1033
1034        /** Zoom percentage at start of clip. 0 = no zoom, 100 = full zoom */
1035        public int panZoomPercentEnd;
1036
1037        /** Top left X coordinate at end of clip. */
1038        public int panZoomTopLeftXEnd;
1039
1040        /** Top left Y coordinate at end of clip. */
1041        public int panZoomTopLeftYEnd;
1042
1043        /**
1044         * Set The media rendering. See {@link MediaRendering MediaRendering}
1045         * for valid values.
1046         */
1047        public int mediaRendering;
1048
1049        /**
1050         * RGB width and Height
1051         */
1052         public int rgbWidth;
1053         public int rgbHeight;
1054         /**
1055         * Video rotation degree.
1056         */
1057         public int rotationDegree;
1058    }
1059
1060    /**
1061     * Defines settings for a transition.
1062     */
1063    public static class TransitionSettings {
1064
1065        /** Duration of the transition in msec. */
1066        public int duration;
1067
1068        /**
1069         * Transition type for video. See {@link VideoTransition
1070         * VideoTransition} for valid values.
1071         */
1072        public int videoTransitionType;
1073
1074        /**
1075         * Transition type for audio. See {@link AudioTransition
1076         * AudioTransition} for valid values.
1077         */
1078        public int audioTransitionType;
1079
1080        /**
1081         * Transition behaviour. See {@link TransitionBehaviour
1082         * TransitionBehaviour} for valid values.
1083         */
1084        public int transitionBehaviour;
1085
1086        /**
1087         * Settings for AlphaMagic transition. Only needs to be set if
1088         * <code>videoTransitionType</code> is set to
1089         * <code>VideoTransition.ALPHA_MAGIC</code>. See
1090         * {@link AlphaMagicSettings AlphaMagicSettings}.
1091         */
1092        public AlphaMagicSettings alphaSettings;
1093
1094        /**
1095         * Settings for the Slide transition. See
1096         * {@link SlideTransitionSettings SlideTransitionSettings}.
1097         */
1098        public SlideTransitionSettings slideSettings;
1099    }
1100
1101    public static final class AudioTransition {
1102        /** No audio transition. */
1103        public static final int NONE = 0;
1104
1105        /** Cross-fade audio transition. */
1106        public static final int CROSS_FADE = 1;
1107    }
1108
1109    /**
1110     * Defines transition behaviors.
1111     */
1112    public static final class TransitionBehaviour {
1113
1114        /** The transition uses an increasing speed. */
1115        public static final int SPEED_UP = 0;
1116
1117        /** The transition uses a linear (constant) speed. */
1118        public static final int LINEAR = 1;
1119
1120        /** The transition uses a decreasing speed. */
1121        public static final int SPEED_DOWN = 2;
1122
1123        /**
1124         * The transition uses a constant speed, but slows down in the middle
1125         * section.
1126         */
1127        public static final int SLOW_MIDDLE = 3;
1128
1129        /**
1130         * The transition uses a constant speed, but increases speed in the
1131         * middle section.
1132         */
1133        public static final int FAST_MIDDLE = 4;
1134    }
1135
1136    /**
1137     * Defines settings for the background music.
1138     */
1139    public static class BackgroundMusicSettings {
1140
1141        /** Background music file. */
1142        public String file;
1143
1144        /** File type. See {@link FileType FileType} for valid values. */
1145        public int fileType;
1146
1147        /**
1148         * Insertion time in milliseconds, in the output video where the
1149         * background music must be inserted.
1150         */
1151        public long insertionTime;
1152
1153        /**
1154         * Volume, as a percentage of the background music track, to use. If
1155         * this field is set to 100, the background music will replace the audio
1156         * from the video input file(s).
1157         */
1158        public int volumePercent;
1159
1160        /**
1161         * Start time in milliseconds in the background muisc file from where
1162         * the background music should loop. Set both <code>beginLoop</code> and
1163         * <code>endLoop</code> to <code>0</code> to disable looping.
1164         */
1165        public long beginLoop;
1166
1167        /**
1168         * End time in milliseconds in the background music file to where the
1169         * background music should loop. Set both <code>beginLoop</code> and
1170         * <code>endLoop</code> to <code>0</code> to disable looping.
1171         */
1172        public long endLoop;
1173
1174        public boolean enableDucking;
1175
1176        public int duckingThreshold;
1177
1178        public int lowVolume;
1179
1180        public boolean isLooping;
1181    }
1182
1183    /** Defines settings for an effect. */
1184    public static class AudioEffect {
1185        /** No audio effect. */
1186        public static final int NONE = 0;
1187
1188        /** Fade-in effect. */
1189        public static final int FADE_IN = 8;
1190
1191        /** Fade-out effect. */
1192        public static final int FADE_OUT = 16;
1193    }
1194
1195    /** Defines the effect settings. */
1196    public static class EffectSettings {
1197
1198        /** Start time of the effect in milliseconds. */
1199        public int startTime;
1200
1201        /** Duration of the effect in milliseconds. */
1202        public int duration;
1203
1204        /**
1205         * Video effect type. See {@link VideoEffect VideoEffect} for valid
1206         * values.
1207         */
1208        public int videoEffectType;
1209
1210        /**
1211         * Audio effect type. See {@link AudioEffect AudioEffect} for valid
1212         * values.
1213         */
1214        public int audioEffectType;
1215
1216        /**
1217         * Start time of the effect in percents of the duration of the clip. A
1218         * value of 0 percent means start time is from the beginning of the
1219         * clip.
1220         */
1221        public int startPercent;
1222
1223        /**
1224         * Duration of the effect in percents of the duration of the clip.
1225         */
1226        public int durationPercent;
1227
1228        /**
1229         * Framing file.
1230         * <p>
1231         * This field is only used when the field <code>videoEffectType</code>
1232         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
1233         * this field is ignored.
1234         */
1235        public String framingFile;
1236
1237        /**
1238         * Framing buffer.
1239         * <p>
1240         * This field is only used when the field <code>videoEffectType</code>
1241         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
1242         * this field is ignored.
1243         */
1244        public int[] framingBuffer;
1245
1246        /**
1247         * Bitmap type Can be from RGB_565 (4), ARGB_4444 (5), ARGB_8888 (6);
1248         **/
1249
1250        public int bitmapType;
1251
1252        public int width;
1253
1254        public int height;
1255
1256        /**
1257         * Top left x coordinate. This coordinate is used to set the x
1258         * coordinate of the picture in the framing file when the framing file
1259         * is selected. The x coordinate is also used to set the location of the
1260         * text in the text effect.
1261         * <p>
1262         * This field is only used when the field <code>videoEffectType</code>
1263         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING} or
1264         * {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this field is
1265         * ignored.
1266         */
1267        public int topLeftX;
1268
1269        /**
1270         * Top left y coordinate. This coordinate is used to set the y
1271         * coordinate of the picture in the framing file when the framing file
1272         * is selected. The y coordinate is also used to set the location of the
1273         * text in the text effect.
1274         * <p>
1275         * This field is only used when the field <code>videoEffectType</code>
1276         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING} or
1277         * {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this field is
1278         * ignored.
1279         */
1280        public int topLeftY;
1281
1282        /**
1283         * Should the frame be resized or not. If this field is set to
1284         * <link>true</code> then the frame size is matched with the output
1285         * video size.
1286         * <p>
1287         * This field is only used when the field <code>videoEffectType</code>
1288         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
1289         * this field is ignored.
1290         */
1291        public boolean framingResize;
1292
1293        /**
1294         * Size to which the framing buffer needs to be resized to
1295         * This is valid only if framingResize is true
1296         */
1297        public int framingScaledSize;
1298        /**
1299         * Text to insert in the video.
1300         * <p>
1301         * This field is only used when the field <code>videoEffectType</code>
1302         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this
1303         * field is ignored.
1304         */
1305        public String text;
1306
1307        /**
1308         * Text attributes for the text to insert in the video.
1309         * <p>
1310         * This field is only used when the field <code>videoEffectType</code>
1311         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this
1312         * field is ignored. For more details about this field see the
1313         * integration guide.
1314         */
1315        public String textRenderingData;
1316
1317        /** Width of the text buffer in pixels. */
1318        public int textBufferWidth;
1319
1320        /** Height of the text buffer in pixels. */
1321        public int textBufferHeight;
1322
1323        /**
1324         * Processing rate for the fifties effect. A high value (e.g. 30)
1325         * results in high effect strength.
1326         * <p>
1327         * This field is only used when the field <code>videoEffectType</code>
1328         * is set to {@link VideoEffect#FIFTIES VideoEffect.FIFTIES}. Otherwise
1329         * this field is ignored.
1330         */
1331        public int fiftiesFrameRate;
1332
1333        /**
1334         * RGB 16 color of the RGB16 and gradient color effect.
1335         * <p>
1336         * This field is only used when the field <code>videoEffectType</code>
1337         * is set to {@link VideoEffect#COLORRGB16 VideoEffect.COLORRGB16} or
1338         * {@link VideoEffect#GRADIENT VideoEffect.GRADIENT}. Otherwise this
1339         * field is ignored.
1340         */
1341        public int rgb16InputColor;
1342
1343        /**
1344         * Start alpha blending percentage.
1345         * <p>
1346         * This field is only used when the field <code>videoEffectType</code>
1347         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
1348         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
1349         * is ignored.
1350         */
1351        public int alphaBlendingStartPercent;
1352
1353        /**
1354         * Middle alpha blending percentage.
1355         * <p>
1356         * This field is only used when the field <code>videoEffectType</code>
1357         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
1358         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
1359         * is ignored.
1360         */
1361        public int alphaBlendingMiddlePercent;
1362
1363        /**
1364         * End alpha blending percentage.
1365         * <p>
1366         * This field is only used when the field <code>videoEffectType</code>
1367         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
1368         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
1369         * is ignored.
1370         */
1371        public int alphaBlendingEndPercent;
1372
1373        /**
1374         * Duration, in percentage of effect duration of the fade-in phase.
1375         * <p>
1376         * This field is only used when the field <code>videoEffectType</code>
1377         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
1378         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
1379         * is ignored.
1380         */
1381        public int alphaBlendingFadeInTimePercent;
1382
1383        /**
1384         * Duration, in percentage of effect duration of the fade-out phase.
1385         * <p>
1386         * This field is only used when the field <code>videoEffectType</code>
1387         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
1388         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
1389         * is ignored.
1390         */
1391        public int alphaBlendingFadeOutTimePercent;
1392    }
1393
1394    /** Defines the clip properties for preview */
1395    public static class PreviewClips {
1396
1397        /**
1398         * The path to the clip file.
1399         * <p>
1400         * File format of the clip, it can be:
1401         * <ul>
1402         * <li>3GP file containing MPEG4/H263 video and AAC/AMR audio
1403         * <li>JPG file
1404         * </ul>
1405         */
1406
1407        public String clipPath;
1408
1409        /**
1410         * File type of the clip. See {@link FileType FileType} for valid
1411         * values.
1412         */
1413        public int fileType;
1414
1415        /** Begin of the cut in the clip in milliseconds. */
1416        public long beginPlayTime;
1417
1418        public long endPlayTime;
1419
1420        /**
1421         * Set The media rendering. See {@link MediaRendering MediaRendering}
1422         * for valid values.
1423         */
1424        public int mediaRendering;
1425
1426    }
1427
1428    /** Defines the audio settings. */
1429    public static class AudioSettings {
1430
1431        String pFile;
1432
1433        /** < PCM file path */
1434        String Id;
1435
1436        boolean bRemoveOriginal;
1437
1438        /** < If true, the original audio track is not taken into account */
1439        int channels;
1440
1441        /** < Number of channels (1=mono, 2=stereo) of BGM clip */
1442        int Fs;
1443
1444        /**
1445         * < Sampling audio frequency (8000 for amr, 16000 or more for aac) of
1446         * BGM clip
1447         */
1448        int ExtendedFs;
1449
1450        /** < Extended frequency for AAC+, eAAC+ streams of BGM clip */
1451        long startMs;
1452
1453        /** < Time, in milliseconds, at which the added audio track is inserted */
1454        long beginCutTime;
1455
1456        long endCutTime;
1457
1458        int fileType;
1459
1460        int volume;
1461
1462        /** < Volume, in percentage, of the added audio track */
1463        boolean loop;
1464
1465        /** < Looping on/off > **/
1466
1467        /** Audio mix and Duck **/
1468        int ducking_threshold;
1469
1470        int ducking_lowVolume;
1471
1472        boolean bInDucking_enable;
1473
1474        String pcmFilePath;
1475    }
1476
1477    /** Encapsulates preview clips and effect settings */
1478    public static class PreviewSettings {
1479
1480        public PreviewClips[] previewClipsArray;
1481
1482        /** The effect settings. */
1483        public EffectSettings[] effectSettingsArray;
1484
1485    }
1486
1487    /** Encapsulates clip properties */
1488    public static class PreviewClipProperties {
1489
1490        public Properties[] clipProperties;
1491
1492    }
1493
1494    /** Defines the editing settings. */
1495    public static class EditSettings {
1496
1497        /**
1498         * Array of clip settings. There is one <code>clipSetting</code> for
1499         * each clip.
1500         */
1501        public ClipSettings[] clipSettingsArray;
1502
1503        /**
1504         * Array of transition settings. If there are n clips (and thus n
1505         * <code>clipSettings</code>) then there are (n-1) transitions and (n-1)
1506         * <code>transistionSettings</code> in
1507         * <code>transistionSettingsArray</code>.
1508         */
1509        public TransitionSettings[] transitionSettingsArray;
1510
1511        /** The effect settings. */
1512        public EffectSettings[] effectSettingsArray;
1513
1514        /**
1515         * Video frame rate of the output clip. See {@link VideoFrameRate
1516         * VideoFrameRate} for valid values.
1517         */
1518        public int videoFrameRate;
1519
1520        /** Output file name. Must be an absolute path. */
1521        public String outputFile;
1522
1523        /**
1524         * Size of the video frames in the output clip. See
1525         * {@link VideoFrameSize VideoFrameSize} for valid values.
1526         */
1527        public int videoFrameSize;
1528
1529        /**
1530         * Format of the video stream in the output clip. See
1531         * {@link VideoFormat VideoFormat} for valid values.
1532         */
1533        public int videoFormat;
1534
1535        /**
1536         * Profile of the video stream in the output clip.
1537         */
1538        public int videoProfile;
1539
1540        /**
1541         * Level of the video stream in the output clip.
1542         */
1543        public int videoLevel;
1544
1545        /**
1546         * Format of the audio stream in the output clip. See
1547         * {@link AudioFormat AudioFormat} for valid values.
1548         */
1549        public int audioFormat;
1550
1551        /**
1552         * Sampling frequency of the audio stream in the output clip. See
1553         * {@link AudioSamplingFrequency AudioSamplingFrequency} for valid
1554         * values.
1555         */
1556        public int audioSamplingFreq;
1557
1558        /**
1559         * Maximum file size. By setting this you can set the maximum size of
1560         * the output clip. Set it to <code>0</code> to let the class ignore
1561         * this filed.
1562         */
1563        public int maxFileSize;
1564
1565        /**
1566         * Number of audio channels in output clip. Use <code>0</code> for none,
1567         * <code>1</code> for mono or <code>2</code> for stereo. None is only
1568         * allowed when the <code>audioFormat</code> field is set to
1569         * {@link AudioFormat#NO_AUDIO AudioFormat.NO_AUDIO} or
1570         * {@link AudioFormat#NULL_AUDIO AudioFormat.NULL_AUDIO} Mono is only
1571         * allowed when the <code>audioFormat</code> field is set to
1572         * {@link AudioFormat#AAC AudioFormat.AAC}
1573         */
1574        public int audioChannels;
1575
1576        /** Video bitrate. See {@link Bitrate Bitrate} for valid values. */
1577        public int videoBitrate;
1578
1579        /** Audio bitrate. See {@link Bitrate Bitrate} for valid values. */
1580        public int audioBitrate;
1581
1582        /**
1583         * Background music settings. See {@link BackgroundMusicSettings
1584         * BackgroundMusicSettings} for valid values.
1585         */
1586        public BackgroundMusicSettings backgroundMusicSettings;
1587
1588        public int primaryTrackVolume;
1589
1590    }
1591
1592    /**
1593     * Defines the media properties.
1594     **/
1595
1596    public static class Properties {
1597
1598        /**
1599         * Duration of the media in milliseconds.
1600         */
1601
1602        public int duration;
1603
1604        /**
1605         * File type.
1606         */
1607
1608        public int fileType;
1609
1610        /**
1611         * Video format.
1612         */
1613
1614        public int videoFormat;
1615
1616        /**
1617         * Duration of the video stream of the media in milliseconds.
1618         */
1619
1620        public int videoDuration;
1621
1622        /**
1623         * Bitrate of the video stream of the media.
1624         */
1625
1626        public int videoBitrate;
1627
1628        /**
1629         * Width of the video frames or the width of the still picture in
1630         * pixels.
1631         */
1632
1633        public int width;
1634
1635        /**
1636         * Height of the video frames or the height of the still picture in
1637         * pixels.
1638         */
1639
1640        public int height;
1641
1642        /**
1643         * Average frame rate of video in the media in frames per second.
1644         */
1645
1646        public float averageFrameRate;
1647
1648        /**
1649         * Profile of the video in the media.
1650         */
1651
1652        public int profile;
1653
1654        /**
1655         * Level of the video in the media.
1656         */
1657
1658        public int level;
1659
1660        /**
1661         * Is Video Profile supported.
1662         */
1663
1664        public boolean profileSupported;
1665
1666        /**
1667         * Is Video Level supported.
1668         */
1669
1670        public boolean levelSupported;
1671
1672        /**
1673         * Audio format.
1674         */
1675
1676        public int audioFormat;
1677
1678        /**
1679         * Duration of the audio stream of the media in milliseconds.
1680         */
1681
1682        public int audioDuration;
1683
1684        /**
1685         * Bitrate of the audio stream of the media.
1686         */
1687
1688        public int audioBitrate;
1689
1690        /**
1691         * Number of audio channels in the media.
1692         */
1693
1694        public int audioChannels;
1695
1696        /**
1697         * Sampling frequency of the audio stream in the media in samples per
1698         * second.
1699         */
1700
1701        public int audioSamplingFrequency;
1702
1703        /**
1704         * Volume value of the audio track as percentage.
1705         */
1706        public int audioVolumeValue;
1707
1708        /**
1709         * Video rotation degree.
1710         */
1711        public int videoRotation;
1712
1713        public String Id;
1714    }
1715
1716    /**
1717     * Constructor
1718     *
1719     * @param projectPath The path where the VideoEditor stores all files
1720     *        related to the project
1721     * @param lock The semaphore
1722     * @param veObj The video editor reference
1723     */
1724    public MediaArtistNativeHelper(String projectPath, Semaphore lock, VideoEditor veObj) {
1725        mProjectPath = projectPath;
1726        if (veObj != null) {
1727            mVideoEditor = veObj;
1728        } else {
1729            mVideoEditor = null;
1730            throw new IllegalArgumentException("video editor object is null");
1731        }
1732        if (mStoryBoardSettings == null) {
1733            mStoryBoardSettings = new EditSettings();
1734        }
1735
1736        mLock = lock;
1737
1738        _init(mProjectPath, "null");
1739        mAudioTrackPCMFilePath = null;
1740    }
1741
1742    /**
1743     * @return The project path
1744     */
1745    String getProjectPath() {
1746        return mProjectPath;
1747    }
1748
1749    /**
1750     * @return The Audio Track PCM file path
1751     */
1752    String getProjectAudioTrackPCMFilePath() {
1753        return mAudioTrackPCMFilePath;
1754    }
1755
1756    /**
1757     * Invalidates the PCM file
1758     */
1759    void invalidatePcmFile() {
1760        if (mAudioTrackPCMFilePath != null) {
1761            new File(mAudioTrackPCMFilePath).delete();
1762            mAudioTrackPCMFilePath = null;
1763        }
1764    }
1765
1766    @SuppressWarnings("unused")
1767    private void onProgressUpdate(int taskId, int progress) {
1768        if (mProcessingState == PROCESSING_EXPORT) {
1769            if (mExportProgressListener != null) {
1770                if (mProgressToApp < progress) {
1771                    mExportProgressListener.onProgress(mVideoEditor, mOutputFilename, progress);
1772                    /* record previous progress */
1773                    mProgressToApp = progress;
1774                }
1775            }
1776        }
1777        else {
1778            // Adapt progress depending on current state
1779            int actualProgress = 0;
1780            int action = 0;
1781
1782            if (mProcessingState == PROCESSING_AUDIO_PCM) {
1783                action = MediaProcessingProgressListener.ACTION_DECODE;
1784            } else {
1785                action = MediaProcessingProgressListener.ACTION_ENCODE;
1786            }
1787
1788            switch (mProcessingState) {
1789                case PROCESSING_AUDIO_PCM:
1790                    actualProgress = progress;
1791                    break;
1792                case PROCESSING_TRANSITION:
1793                    actualProgress = progress;
1794                    break;
1795                case PROCESSING_KENBURNS:
1796                    actualProgress = progress;
1797                    break;
1798                case PROCESSING_INTERMEDIATE1:
1799                    if ((progress == 0) && (mProgressToApp != 0)) {
1800                        mProgressToApp = 0;
1801                    }
1802                    if ((progress != 0) || (mProgressToApp != 0)) {
1803                        actualProgress = progress/4;
1804                    }
1805                    break;
1806                case PROCESSING_INTERMEDIATE2:
1807                    if ((progress != 0) || (mProgressToApp != 0)) {
1808                        actualProgress = 25 + progress/4;
1809                    }
1810                    break;
1811                case PROCESSING_INTERMEDIATE3:
1812                    if ((progress != 0) || (mProgressToApp != 0)) {
1813                        actualProgress = 50 + progress/2;
1814                    }
1815                    break;
1816                case PROCESSING_NONE:
1817
1818                default:
1819                    Log.e(TAG, "ERROR unexpected State=" + mProcessingState);
1820                    return;
1821            }
1822            if ((mProgressToApp != actualProgress) && (actualProgress != 0)) {
1823
1824                mProgressToApp = actualProgress;
1825
1826                if (mMediaProcessingProgressListener != null) {
1827                    // Send the progress indication
1828                    mMediaProcessingProgressListener.onProgress(mProcessingObject, action,
1829                                                                actualProgress);
1830                }
1831            }
1832            /* avoid 0 in next intermediate call */
1833            if (mProgressToApp == 0) {
1834                if (mMediaProcessingProgressListener != null) {
1835                    /*
1836                     *  Send the progress indication
1837                     */
1838                    mMediaProcessingProgressListener.onProgress(mProcessingObject, action,
1839                                                                actualProgress);
1840                }
1841                mProgressToApp = 1;
1842            }
1843        }
1844    }
1845
1846    @SuppressWarnings("unused")
1847    private void onPreviewProgressUpdate(int progress, boolean isFinished,
1848                  boolean updateOverlay, String filename, int renderingMode, int error) {
1849        if (mPreviewProgressListener != null) {
1850            if (mIsFirstProgress) {
1851                mPreviewProgressListener.onStart(mVideoEditor);
1852                mIsFirstProgress = false;
1853            }
1854
1855            final VideoEditor.OverlayData overlayData;
1856            if (updateOverlay) {
1857                overlayData = new VideoEditor.OverlayData();
1858                if (filename != null) {
1859                    overlayData.set(BitmapFactory.decodeFile(filename), renderingMode);
1860                } else {
1861                    overlayData.setClear();
1862                }
1863            } else {
1864                overlayData = null;
1865            }
1866
1867            if (progress != 0) {
1868                mPreviewProgress = progress;
1869            }
1870
1871            if (isFinished) {
1872                mPreviewProgressListener.onStop(mVideoEditor);
1873            } else if (error != 0) {
1874                mPreviewProgressListener.onError(mVideoEditor, error);
1875            } else {
1876                mPreviewProgressListener.onProgress(mVideoEditor, progress, overlayData);
1877            }
1878        }
1879    }
1880
1881    /**
1882     * Release the native helper object
1883     */
1884    void releaseNativeHelper() throws InterruptedException {
1885        release();
1886    }
1887
1888    /**
1889     * Release the native helper to end the Audio Graph process
1890     */
1891    @SuppressWarnings("unused")
1892    private void onAudioGraphExtractProgressUpdate(int progress, boolean isVideo) {
1893        if ((mExtractAudioWaveformProgressListener != null) && (progress > 0)) {
1894            mExtractAudioWaveformProgressListener.onProgress(progress);
1895        }
1896    }
1897
1898    /**
1899     * Populates the Effect Settings in EffectSettings
1900     *
1901     * @param effects The reference of EffectColor
1902     *
1903     * @return The populated effect settings in EffectSettings reference
1904     */
1905    EffectSettings getEffectSettings(EffectColor effects) {
1906        EffectSettings effectSettings = new EffectSettings();
1907        effectSettings.startTime = (int)effects.getStartTime();
1908        effectSettings.duration = (int)effects.getDuration();
1909        effectSettings.videoEffectType = getEffectColorType(effects);
1910        effectSettings.audioEffectType = 0;
1911        effectSettings.startPercent = 0;
1912        effectSettings.durationPercent = 0;
1913        effectSettings.framingFile = null;
1914        effectSettings.topLeftX = 0;
1915        effectSettings.topLeftY = 0;
1916        effectSettings.framingResize = false;
1917        effectSettings.text = null;
1918        effectSettings.textRenderingData = null;
1919        effectSettings.textBufferWidth = 0;
1920        effectSettings.textBufferHeight = 0;
1921        if (effects.getType() == EffectColor.TYPE_FIFTIES) {
1922            effectSettings.fiftiesFrameRate = 15;
1923        } else {
1924            effectSettings.fiftiesFrameRate = 0;
1925        }
1926
1927        if ((effectSettings.videoEffectType == VideoEffect.COLORRGB16)
1928                || (effectSettings.videoEffectType == VideoEffect.GRADIENT)) {
1929            effectSettings.rgb16InputColor = effects.getColor();
1930        }
1931
1932        effectSettings.alphaBlendingStartPercent = 0;
1933        effectSettings.alphaBlendingMiddlePercent = 0;
1934        effectSettings.alphaBlendingEndPercent = 0;
1935        effectSettings.alphaBlendingFadeInTimePercent = 0;
1936        effectSettings.alphaBlendingFadeOutTimePercent = 0;
1937        return effectSettings;
1938    }
1939
1940    /**
1941     * Populates the Overlay Settings in EffectSettings
1942     *
1943     * @param overlay The reference of OverlayFrame
1944     *
1945     * @return The populated overlay settings in EffectSettings reference
1946     */
1947    EffectSettings getOverlaySettings(OverlayFrame overlay) {
1948        EffectSettings effectSettings = new EffectSettings();
1949        Bitmap bitmap = null;
1950
1951        effectSettings.startTime = (int)overlay.getStartTime();
1952        effectSettings.duration = (int)overlay.getDuration();
1953        effectSettings.videoEffectType = VideoEffect.FRAMING;
1954        effectSettings.audioEffectType = 0;
1955        effectSettings.startPercent = 0;
1956        effectSettings.durationPercent = 0;
1957        effectSettings.framingFile = null;
1958
1959        if ((bitmap = overlay.getBitmap()) != null) {
1960            effectSettings.framingFile = overlay.getFilename();
1961
1962            if (effectSettings.framingFile == null) {
1963                try {
1964                    (overlay).save(mProjectPath);
1965                } catch (IOException e) {
1966                    Log.e(TAG, "getOverlaySettings : File not found");
1967                }
1968                effectSettings.framingFile = overlay.getFilename();
1969            }
1970            if (bitmap.getConfig() == Bitmap.Config.ARGB_8888)
1971                effectSettings.bitmapType = 6;
1972            else if (bitmap.getConfig() == Bitmap.Config.ARGB_4444)
1973                effectSettings.bitmapType = 5;
1974            else if (bitmap.getConfig() == Bitmap.Config.RGB_565)
1975                effectSettings.bitmapType = 4;
1976            else if (bitmap.getConfig() == Bitmap.Config.ALPHA_8)
1977                throw new RuntimeException("Bitmap config not supported");
1978
1979            effectSettings.width = bitmap.getWidth();
1980            effectSettings.height = bitmap.getHeight();
1981            effectSettings.framingBuffer = new int[effectSettings.width];
1982            int tmp = 0;
1983            short maxAlpha = 0;
1984            short minAlpha = (short)0xFF;
1985            short alpha = 0;
1986            while (tmp < effectSettings.height) {
1987                bitmap.getPixels(effectSettings.framingBuffer, 0,
1988                                 effectSettings.width, 0, tmp,
1989                                 effectSettings.width, 1);
1990                for (int i = 0; i < effectSettings.width; i++) {
1991                    alpha = (short)((effectSettings.framingBuffer[i] >> 24) & 0xFF);
1992                    if (alpha > maxAlpha) {
1993                        maxAlpha = alpha;
1994                    }
1995                    if (alpha < minAlpha) {
1996                        minAlpha = alpha;
1997                    }
1998                }
1999                tmp += 1;
2000            }
2001            alpha = (short)((maxAlpha + minAlpha) / 2);
2002            alpha = (short)((alpha * 100) / 256);
2003            effectSettings.alphaBlendingEndPercent = alpha;
2004            effectSettings.alphaBlendingMiddlePercent = alpha;
2005            effectSettings.alphaBlendingStartPercent = alpha;
2006            effectSettings.alphaBlendingFadeInTimePercent = 100;
2007            effectSettings.alphaBlendingFadeOutTimePercent = 100;
2008            effectSettings.framingBuffer = null;
2009
2010            /*
2011             * Set the resized RGB file dimensions
2012             */
2013            effectSettings.width = overlay.getResizedRGBSizeWidth();
2014            if(effectSettings.width == 0) {
2015                effectSettings.width = bitmap.getWidth();
2016            }
2017
2018            effectSettings.height = overlay.getResizedRGBSizeHeight();
2019            if(effectSettings.height == 0) {
2020                effectSettings.height = bitmap.getHeight();
2021            }
2022
2023        }
2024
2025        effectSettings.topLeftX = 0;
2026        effectSettings.topLeftY = 0;
2027
2028        effectSettings.framingResize = true;
2029        effectSettings.text = null;
2030        effectSettings.textRenderingData = null;
2031        effectSettings.textBufferWidth = 0;
2032        effectSettings.textBufferHeight = 0;
2033        effectSettings.fiftiesFrameRate = 0;
2034        effectSettings.rgb16InputColor = 0;
2035        int mediaItemHeight;
2036        int aspectRatio;
2037        if (overlay.getMediaItem() instanceof MediaImageItem) {
2038            if (((MediaImageItem)overlay.getMediaItem()).getGeneratedImageClip() != null) {
2039                // Ken Burns was applied
2040                mediaItemHeight = ((MediaImageItem)overlay.getMediaItem()).getGeneratedClipHeight();
2041                aspectRatio = getAspectRatio(
2042                    ((MediaImageItem)overlay.getMediaItem()).getGeneratedClipWidth()
2043                    , mediaItemHeight);
2044            } else {
2045                //For image get the scaled height. Aspect ratio would remain the same
2046                mediaItemHeight = ((MediaImageItem)overlay.getMediaItem()).getScaledHeight();
2047                aspectRatio = overlay.getMediaItem().getAspectRatio();
2048            }
2049        } else {
2050            aspectRatio = overlay.getMediaItem().getAspectRatio();
2051            mediaItemHeight = overlay.getMediaItem().getHeight();
2052        }
2053        effectSettings.framingScaledSize = findVideoResolution(aspectRatio, mediaItemHeight);
2054        return effectSettings;
2055    }
2056
2057     /* get Video Editor aspect ratio */
2058    int nativeHelperGetAspectRatio() {
2059        return mVideoEditor.getAspectRatio();
2060    }
2061
2062    /**
2063     * Sets the export audio codec
2064     *
2065     * @param export audio codec
2066     *
2067     */
2068    void setAudioCodec(int codec) {
2069        mExportAudioCodec = codec;
2070    }
2071    /**
2072     * Sets the export video codec
2073     *
2074     * @param export video codec
2075     *
2076     */
2077    void setVideoCodec(int codec) {
2078        mExportVideoCodec = codec;
2079    }
2080
2081    /**
2082     * Sets the audio regenerate flag
2083     *
2084     * @param flag The boolean to set the audio regenerate flag
2085     *
2086     */
2087    void setAudioflag(boolean flag) {
2088        //check if the file exists.
2089        if (!(new File(String.format(mProjectPath + "/" + AUDIO_TRACK_PCM_FILE)).exists())) {
2090            flag = true;
2091        }
2092        mRegenerateAudio = flag;
2093    }
2094
2095    /**
2096     * Gets the audio regenerate flag
2097     *
2098     * @param return The boolean to get the audio regenerate flag
2099     *
2100     */
2101    boolean getAudioflag() {
2102        return mRegenerateAudio;
2103    }
2104
2105    /**
2106     * Maps the average frame rate to one of the defined enum values
2107     *
2108     * @param averageFrameRate The average frame rate of video item
2109     *
2110     * @return The frame rate from one of the defined enum values
2111     */
2112    int GetClosestVideoFrameRate(int averageFrameRate) {
2113        if (averageFrameRate >= 25) {
2114            return VideoFrameRate.FR_30_FPS;
2115        } else if (averageFrameRate >= 20) {
2116            return VideoFrameRate.FR_25_FPS;
2117        } else if (averageFrameRate >= 15) {
2118            return VideoFrameRate.FR_20_FPS;
2119        } else if (averageFrameRate >= 12) {
2120            return VideoFrameRate.FR_15_FPS;
2121        } else if (averageFrameRate >= 10) {
2122            return VideoFrameRate.FR_12_5_FPS;
2123        } else if (averageFrameRate >= 7) {
2124            return VideoFrameRate.FR_10_FPS;
2125        } else if (averageFrameRate >= 5) {
2126            return VideoFrameRate.FR_7_5_FPS;
2127        } else {
2128            return -1;
2129        }
2130    }
2131
2132    /**
2133     * Helper function to adjust the effect or overlay start time
2134     * depending on the begin and end boundary time of meddia item
2135     */
2136    public void adjustEffectsStartTimeAndDuration(EffectSettings lEffect, int beginCutTime,
2137                                                  int endCutTime) {
2138
2139        int effectStartTime = 0;
2140        int effectDuration = 0;
2141
2142        /**
2143         * cbct -> clip begin cut time
2144         * cect -> clip end cut time
2145         ****************************************
2146         *  |                                 |
2147         *  |         cbct        cect        |
2148         *  | <-1-->   |           |          |
2149         *  |       <--|-2->       |          |
2150         *  |          | <---3---> |          |
2151         *  |          |        <--|-4--->    |
2152         *  |          |           | <--5-->  |
2153         *  |      <---|------6----|---->     |
2154         *  |                                 |
2155         *  < : effectStart
2156         *  > : effectStart + effectDuration
2157         ****************************************
2158         **/
2159
2160        /** 1 & 5 */
2161        /**
2162         * Effect falls out side the trim duration. In such a case effects shall
2163         * not be applied.
2164         */
2165        if ((lEffect.startTime > endCutTime)
2166                || ((lEffect.startTime + lEffect.duration) <= beginCutTime)) {
2167
2168            effectStartTime = 0;
2169            effectDuration = 0;
2170
2171            lEffect.startTime = effectStartTime;
2172            lEffect.duration = effectDuration;
2173            return;
2174        }
2175
2176        /** 2 */
2177        if ((lEffect.startTime < beginCutTime)
2178                && ((lEffect.startTime + lEffect.duration) > beginCutTime)
2179                && ((lEffect.startTime + lEffect.duration) <= endCutTime)) {
2180            effectStartTime = 0;
2181            effectDuration = lEffect.duration;
2182
2183            effectDuration -= (beginCutTime - lEffect.startTime);
2184            lEffect.startTime = effectStartTime;
2185            lEffect.duration = effectDuration;
2186            return;
2187        }
2188
2189        /** 3 */
2190        if ((lEffect.startTime >= beginCutTime)
2191                && ((lEffect.startTime + lEffect.duration) <= endCutTime)) {
2192            effectStartTime = lEffect.startTime - beginCutTime;
2193            lEffect.startTime = effectStartTime;
2194            lEffect.duration = lEffect.duration;
2195            return;
2196        }
2197
2198        /** 4 */
2199        if ((lEffect.startTime >= beginCutTime)
2200                && ((lEffect.startTime + lEffect.duration) > endCutTime)) {
2201            effectStartTime = lEffect.startTime - beginCutTime;
2202            effectDuration = endCutTime - lEffect.startTime;
2203            lEffect.startTime = effectStartTime;
2204            lEffect.duration = effectDuration;
2205            return;
2206        }
2207
2208        /** 6 */
2209        if ((lEffect.startTime < beginCutTime)
2210                && ((lEffect.startTime + lEffect.duration) > endCutTime)) {
2211            effectStartTime = 0;
2212            effectDuration = endCutTime - beginCutTime;
2213            lEffect.startTime = effectStartTime;
2214            lEffect.duration = effectDuration;
2215            return;
2216        }
2217
2218    }
2219
2220    /**
2221     * Generates the clip for preview or export
2222     *
2223     * @param editSettings The EditSettings reference for generating
2224     * a clip for preview or export
2225     *
2226     * @return error value
2227     */
2228    public int generateClip(EditSettings editSettings) {
2229        int err = 0;
2230
2231        try {
2232            err = nativeGenerateClip(editSettings);
2233        } catch (IllegalArgumentException ex) {
2234            Log.e(TAG, "Illegal Argument exception in load settings");
2235            return -1;
2236        } catch (IllegalStateException ex) {
2237            Log.e(TAG, "Illegal state exception in load settings");
2238            return -1;
2239        } catch (RuntimeException ex) {
2240            Log.e(TAG, "Runtime exception in load settings");
2241            return -1;
2242        }
2243        return err;
2244    }
2245
2246    /**
2247     * Init function to initialiZe the  ClipSettings reference to
2248     * default values
2249     *
2250     * @param lclipSettings The ClipSettings reference
2251     */
2252    void initClipSettings(ClipSettings lclipSettings) {
2253        lclipSettings.clipPath = null;
2254        lclipSettings.clipDecodedPath = null;
2255        lclipSettings.clipOriginalPath = null;
2256        lclipSettings.fileType = 0;
2257        lclipSettings.endCutTime = 0;
2258        lclipSettings.beginCutTime = 0;
2259        lclipSettings.beginCutPercent = 0;
2260        lclipSettings.endCutPercent = 0;
2261        lclipSettings.panZoomEnabled = false;
2262        lclipSettings.panZoomPercentStart = 0;
2263        lclipSettings.panZoomTopLeftXStart = 0;
2264        lclipSettings.panZoomTopLeftYStart = 0;
2265        lclipSettings.panZoomPercentEnd = 0;
2266        lclipSettings.panZoomTopLeftXEnd = 0;
2267        lclipSettings.panZoomTopLeftYEnd = 0;
2268        lclipSettings.mediaRendering = 0;
2269        lclipSettings.rotationDegree = 0;
2270    }
2271
2272
2273    /**
2274     * Populates the settings for generating an effect clip
2275     *
2276     * @param lMediaItem The media item for which the effect clip
2277     * needs to be generated
2278     * @param lclipSettings The ClipSettings reference containing
2279     * clips data
2280     * @param e The EditSettings reference containing effect specific data
2281     * @param uniqueId The unique id used in the name of the output clip
2282     * @param clipNo Used for internal purpose
2283     *
2284     * @return The name and path of generated clip
2285     */
2286    String generateEffectClip(MediaItem lMediaItem, ClipSettings lclipSettings,
2287            EditSettings e,String uniqueId,int clipNo) {
2288        int err = 0;
2289        EditSettings editSettings = null;
2290        String EffectClipPath = null;
2291        int outVideoProfile = 0;
2292        int outVideoLevel = 0;
2293        editSettings = new EditSettings();
2294
2295        editSettings.clipSettingsArray = new ClipSettings[1];
2296        editSettings.clipSettingsArray[0] = lclipSettings;
2297
2298        editSettings.backgroundMusicSettings = null;
2299        editSettings.transitionSettingsArray = null;
2300        editSettings.effectSettingsArray = e.effectSettingsArray;
2301
2302        EffectClipPath = String.format(mProjectPath + "/" + "ClipEffectIntermediate" + "_"
2303                + lMediaItem.getId() + uniqueId + ".3gp");
2304
2305        File tmpFile = new File(EffectClipPath);
2306        if (tmpFile.exists()) {
2307            tmpFile.delete();
2308        }
2309
2310        outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
2311        outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
2312        editSettings.videoProfile = outVideoProfile;
2313        editSettings.videoLevel= outVideoLevel;
2314
2315        if (lMediaItem instanceof MediaVideoItem) {
2316            MediaVideoItem m = (MediaVideoItem)lMediaItem;
2317
2318            editSettings.audioFormat = AudioFormat.AAC;
2319            editSettings.audioChannels = 2;
2320            editSettings.audioBitrate = Bitrate.BR_64_KBPS;
2321            editSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
2322
2323            editSettings.videoFormat = VideoFormat.H264;
2324            editSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
2325            editSettings.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
2326                    m.getHeight());
2327            editSettings.videoBitrate = findVideoBitrate(editSettings.videoFrameSize);
2328        } else {
2329            MediaImageItem m = (MediaImageItem)lMediaItem;
2330            editSettings.audioBitrate = Bitrate.BR_64_KBPS;
2331            editSettings.audioChannels = 2;
2332            editSettings.audioFormat = AudioFormat.AAC;
2333            editSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
2334
2335            editSettings.videoFormat = VideoFormat.H264;
2336            editSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
2337            editSettings.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
2338                    m.getScaledHeight());
2339            editSettings.videoBitrate = findVideoBitrate(editSettings.videoFrameSize);
2340        }
2341
2342        editSettings.outputFile = EffectClipPath;
2343
2344        if (clipNo == 1) {
2345            mProcessingState  = PROCESSING_INTERMEDIATE1;
2346        } else if (clipNo == 2) {
2347            mProcessingState  = PROCESSING_INTERMEDIATE2;
2348        }
2349        mProcessingObject = lMediaItem;
2350        err = generateClip(editSettings);
2351        mProcessingState  = PROCESSING_NONE;
2352
2353        if (err == 0) {
2354            lclipSettings.clipPath = EffectClipPath;
2355            lclipSettings.fileType = FileType.THREE_GPP;
2356            return EffectClipPath;
2357        } else {
2358            throw new RuntimeException("preview generation cannot be completed");
2359        }
2360    }
2361
2362
2363    /**
2364     * Populates the settings for generating a Ken Burn effect clip
2365     *
2366     * @param m The media image item for which the Ken Burn effect clip
2367     * needs to be generated
2368     * @param e The EditSettings reference clip specific data
2369     *
2370     * @return The name and path of generated clip
2371     */
2372    String generateKenBurnsClip(EditSettings e, MediaImageItem m) {
2373        String output = null;
2374        int err = 0;
2375        int outVideoProfile = 0;
2376        int outVideoLevel = 0;
2377
2378        e.backgroundMusicSettings = null;
2379        e.transitionSettingsArray = null;
2380        e.effectSettingsArray = null;
2381        output = String.format(mProjectPath + "/" + "ImageClip-" + m.getId() + ".3gp");
2382
2383        File tmpFile = new File(output);
2384        if (tmpFile.exists()) {
2385            tmpFile.delete();
2386        }
2387
2388        outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
2389        outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
2390        e.videoProfile = outVideoProfile;
2391        e.videoLevel = outVideoLevel;
2392
2393        e.outputFile = output;
2394        e.audioBitrate = Bitrate.BR_64_KBPS;
2395        e.audioChannels = 2;
2396        e.audioFormat = AudioFormat.AAC;
2397        e.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
2398
2399        e.videoFormat = VideoFormat.H264;
2400        e.videoFrameRate = VideoFrameRate.FR_30_FPS;
2401        e.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
2402                                                           m.getScaledHeight());
2403        e.videoBitrate = findVideoBitrate(e.videoFrameSize);
2404
2405        mProcessingState  = PROCESSING_KENBURNS;
2406        mProcessingObject = m;
2407        err = generateClip(e);
2408        // Reset the processing state and check for errors
2409        mProcessingState  = PROCESSING_NONE;
2410        if (err != 0) {
2411            throw new RuntimeException("preview generation cannot be completed");
2412        }
2413        return output;
2414    }
2415
2416
2417    /**
2418     * Calculates the output resolution for transition clip
2419     *
2420     * @param m1 First media item associated with transition
2421     * @param m2 Second media item associated with transition
2422     *
2423     * @return The transition resolution
2424     */
2425    private int getTransitionResolution(MediaItem m1, MediaItem m2) {
2426        int clip1Height = 0;
2427        int clip2Height = 0;
2428        int videoSize = 0;
2429
2430        if (m1 != null && m2 != null) {
2431            if (m1 instanceof MediaVideoItem) {
2432                clip1Height = m1.getHeight();
2433            } else if (m1 instanceof MediaImageItem) {
2434                clip1Height = ((MediaImageItem)m1).getScaledHeight();
2435            }
2436            if (m2 instanceof MediaVideoItem) {
2437                clip2Height = m2.getHeight();
2438            } else if (m2 instanceof MediaImageItem) {
2439                clip2Height = ((MediaImageItem)m2).getScaledHeight();
2440            }
2441            if (clip1Height > clip2Height) {
2442                videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip1Height);
2443            } else {
2444                videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip2Height);
2445            }
2446        } else if (m1 == null && m2 != null) {
2447            if (m2 instanceof MediaVideoItem) {
2448                clip2Height = m2.getHeight();
2449            } else if (m2 instanceof MediaImageItem) {
2450                clip2Height = ((MediaImageItem)m2).getScaledHeight();
2451            }
2452            videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip2Height);
2453        } else if (m1 != null && m2 == null) {
2454            if (m1 instanceof MediaVideoItem) {
2455                clip1Height = m1.getHeight();
2456            } else if (m1 instanceof MediaImageItem) {
2457                clip1Height = ((MediaImageItem)m1).getScaledHeight();
2458            }
2459            videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip1Height);
2460        }
2461        return videoSize;
2462    }
2463
2464    /**
2465     * Populates the settings for generating an transition clip
2466     *
2467     * @param m1 First media item associated with transition
2468     * @param m2 Second media item associated with transition
2469     * @param e The EditSettings reference containing
2470     * clip specific data
2471     * @param uniqueId The unique id used in the name of the output clip
2472     * @param t The Transition specific data
2473     *
2474     * @return The name and path of generated clip
2475     */
2476    String generateTransitionClip(EditSettings e, String uniqueId,
2477            MediaItem m1, MediaItem m2,Transition t) {
2478        String outputFilename = null;
2479        int err = 0;
2480        int outVideoProfile = 0;
2481        int outVideoLevel = 0;
2482        outputFilename = String.format(mProjectPath + "/" + uniqueId + ".3gp");
2483
2484        outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
2485        outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
2486        e.videoProfile = outVideoProfile;
2487        e.videoLevel = outVideoLevel;
2488
2489        e.outputFile = outputFilename;
2490        e.audioBitrate = Bitrate.BR_64_KBPS;
2491        e.audioChannels = 2;
2492        e.audioFormat = AudioFormat.AAC;
2493        e.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
2494
2495        e.videoFormat = VideoFormat.H264;
2496        e.videoFrameRate = VideoFrameRate.FR_30_FPS;
2497        e.videoFrameSize = getTransitionResolution(m1, m2);
2498        e.videoBitrate = findVideoBitrate(e.videoFrameSize);
2499
2500        if (new File(outputFilename).exists()) {
2501            new File(outputFilename).delete();
2502        }
2503        mProcessingState  = PROCESSING_INTERMEDIATE3;
2504        mProcessingObject = t;
2505        err = generateClip(e);
2506        // Reset the processing state and check for errors
2507        mProcessingState  = PROCESSING_NONE;
2508        if (err != 0) {
2509            throw new RuntimeException("preview generation cannot be completed");
2510        }
2511        return outputFilename;
2512    }
2513
2514    /**
2515     * Populates effects and overlays in EffectSettings structure
2516     * and also adjust the start time and duration of effects and overlays
2517     * w.r.t to total story board time
2518     *
2519     * @param m1 Media item associated with effect
2520     * @param effectSettings The EffectSettings reference containing
2521     *      effect specific data
2522     * @param beginCutTime The begin cut time of the clip associated with effect
2523     * @param endCutTime The end cut time of the clip associated with effect
2524     * @param storyBoardTime The current story board time
2525     *
2526     * @return The updated index
2527     */
2528    private int populateEffects(MediaItem m, EffectSettings[] effectSettings, int i,
2529            int beginCutTime, int endCutTime, int storyBoardTime) {
2530
2531        if (m.getBeginTransition() != null && m.getBeginTransition().getDuration() > 0
2532                && m.getEndTransition() != null && m.getEndTransition().getDuration() > 0) {
2533            beginCutTime += m.getBeginTransition().getDuration();
2534            endCutTime -= m.getEndTransition().getDuration();
2535        } else if (m.getBeginTransition() == null && m.getEndTransition() != null
2536                && m.getEndTransition().getDuration() > 0) {
2537            endCutTime -= m.getEndTransition().getDuration();
2538        } else if (m.getEndTransition() == null && m.getBeginTransition() != null
2539                && m.getBeginTransition().getDuration() > 0) {
2540            beginCutTime += m.getBeginTransition().getDuration();
2541        }
2542
2543        final List<Effect> effects = m.getAllEffects();
2544        final List<Overlay> overlays = m.getAllOverlays();
2545
2546        for (Overlay overlay : overlays) {
2547            effectSettings[i] = getOverlaySettings((OverlayFrame)overlay);
2548            adjustEffectsStartTimeAndDuration(effectSettings[i], beginCutTime, endCutTime);
2549            effectSettings[i].startTime += storyBoardTime;
2550            i++;
2551        }
2552
2553        for (Effect effect : effects) {
2554            if (effect instanceof EffectColor) {
2555                effectSettings[i] = getEffectSettings((EffectColor)effect);
2556                adjustEffectsStartTimeAndDuration(effectSettings[i], beginCutTime, endCutTime);
2557                effectSettings[i].startTime += storyBoardTime;
2558                i++;
2559            }
2560        }
2561
2562        return i;
2563    }
2564
2565    /**
2566     * Adjusts the media item boundaries for use in export or preview
2567     *
2568     * @param clipSettings The ClipSettings reference
2569     * @param clipProperties The Properties reference
2570     * @param m The media item
2571     */
2572    private void adjustMediaItemBoundary(ClipSettings clipSettings,
2573                                         Properties clipProperties, MediaItem m) {
2574        if (m.getBeginTransition() != null && m.getBeginTransition().getDuration() > 0
2575                && m.getEndTransition() != null && m.getEndTransition().getDuration() > 0) {
2576            clipSettings.beginCutTime += m.getBeginTransition().getDuration();
2577            clipSettings.endCutTime -= m.getEndTransition().getDuration();
2578        } else if (m.getBeginTransition() == null && m.getEndTransition() != null
2579                && m.getEndTransition().getDuration() > 0) {
2580            clipSettings.endCutTime -= m.getEndTransition().getDuration();
2581        } else if (m.getEndTransition() == null && m.getBeginTransition() != null
2582                && m.getBeginTransition().getDuration() > 0) {
2583            clipSettings.beginCutTime += m.getBeginTransition().getDuration();
2584        }
2585
2586        clipProperties.duration = clipSettings.endCutTime - clipSettings.beginCutTime;
2587
2588        if (clipProperties.videoDuration != 0) {
2589            clipProperties.videoDuration = clipSettings.endCutTime - clipSettings.beginCutTime;
2590        }
2591
2592        if (clipProperties.audioDuration != 0) {
2593            clipProperties.audioDuration = clipSettings.endCutTime - clipSettings.beginCutTime;
2594        }
2595    }
2596
2597    /**
2598     * Generates the transition if transition is present
2599     * and is in invalidated state
2600     *
2601     * @param transition The Transition reference
2602     * @param editSettings The EditSettings reference
2603     * @param clipPropertiesArray The clip Properties array
2604     * @param i The index in clip Properties array for current clip
2605     */
2606    private void generateTransition(Transition transition, EditSettings editSettings,
2607            PreviewClipProperties clipPropertiesArray, int index) {
2608        if (!(transition.isGenerated())) {
2609            transition.generate();
2610        }
2611        editSettings.clipSettingsArray[index] = new ClipSettings();
2612        editSettings.clipSettingsArray[index].clipPath = transition.getFilename();
2613        editSettings.clipSettingsArray[index].fileType = FileType.THREE_GPP;
2614        editSettings.clipSettingsArray[index].beginCutTime = 0;
2615        editSettings.clipSettingsArray[index].endCutTime = (int)transition.getDuration();
2616        editSettings.clipSettingsArray[index].mediaRendering = MediaRendering.BLACK_BORDERS;
2617
2618        try {
2619            clipPropertiesArray.clipProperties[index] =
2620                getMediaProperties(transition.getFilename());
2621        } catch (Exception e) {
2622            throw new IllegalArgumentException("Unsupported file or file not found");
2623        }
2624
2625        clipPropertiesArray.clipProperties[index].Id = null;
2626        clipPropertiesArray.clipProperties[index].audioVolumeValue = 100;
2627        clipPropertiesArray.clipProperties[index].duration = (int)transition.getDuration();
2628        if (clipPropertiesArray.clipProperties[index].videoDuration != 0) {
2629            clipPropertiesArray.clipProperties[index].videoDuration = (int)transition.getDuration();
2630        }
2631
2632        if (clipPropertiesArray.clipProperties[index].audioDuration != 0) {
2633            clipPropertiesArray.clipProperties[index].audioDuration = (int)transition.getDuration();
2634        }
2635    }
2636
2637    /**
2638     * Sets the volume for current media item in clip properties array
2639     *
2640     * @param m The media item
2641     * @param clipProperties The clip properties array reference
2642     * @param i The index in clip Properties array for current clip
2643     */
2644    private void adjustVolume(MediaItem m, PreviewClipProperties clipProperties,
2645                              int index) {
2646        if (m instanceof MediaVideoItem) {
2647            final boolean videoMuted = ((MediaVideoItem)m).isMuted();
2648            if (videoMuted == false) {
2649                mClipProperties.clipProperties[index].audioVolumeValue =
2650                    ((MediaVideoItem)m).getVolume();
2651            } else {
2652                mClipProperties.clipProperties[index].audioVolumeValue = 0;
2653            }
2654        } else if (m instanceof MediaImageItem) {
2655            mClipProperties.clipProperties[index].audioVolumeValue = 0;
2656        }
2657    }
2658
2659    /**
2660     * Checks for odd size image width and height
2661     *
2662     * @param m The media item
2663     * @param clipProperties The clip properties array reference
2664     * @param i The index in clip Properties array for current clip
2665     */
2666    private void checkOddSizeImage(MediaItem m, PreviewClipProperties clipProperties, int index) {
2667        if (m instanceof MediaImageItem) {
2668            int width = mClipProperties.clipProperties[index].width;
2669            int height = mClipProperties.clipProperties[index].height;
2670
2671            if ((width % 2) != 0) {
2672                width -= 1;
2673            }
2674            if ((height % 2) != 0) {
2675                height -= 1;
2676            }
2677            mClipProperties.clipProperties[index].width = width;
2678            mClipProperties.clipProperties[index].height = height;
2679        }
2680    }
2681
2682    /**
2683     * Populates the media item properties and calculates the maximum
2684     * height among all the clips
2685     *
2686     * @param m The media item
2687     * @param i The index in clip Properties array for current clip
2688     * @param maxHeight The max height from the clip properties
2689     *
2690     * @return Updates the max height if current clip's height is greater
2691     * than all previous clips height
2692     */
2693    private int populateMediaItemProperties(MediaItem m, int index, int maxHeight) {
2694        mPreviewEditSettings.clipSettingsArray[index] = new ClipSettings();
2695        if (m instanceof MediaVideoItem) {
2696            mPreviewEditSettings.clipSettingsArray[index] =
2697                ((MediaVideoItem)m).getVideoClipProperties();
2698            if (((MediaVideoItem)m).getHeight() > maxHeight) {
2699                maxHeight = ((MediaVideoItem)m).getHeight();
2700            }
2701        } else if (m instanceof MediaImageItem) {
2702            mPreviewEditSettings.clipSettingsArray[index] =
2703                ((MediaImageItem)m).getImageClipProperties();
2704            if (((MediaImageItem)m).getScaledHeight() > maxHeight) {
2705                maxHeight = ((MediaImageItem)m).getScaledHeight();
2706            }
2707        }
2708        /** + Handle the image files here */
2709        if (mPreviewEditSettings.clipSettingsArray[index].fileType == FileType.JPG) {
2710            mPreviewEditSettings.clipSettingsArray[index].clipDecodedPath =
2711                ((MediaImageItem)m).getDecodedImageFileName();
2712
2713            mPreviewEditSettings.clipSettingsArray[index].clipOriginalPath =
2714                         mPreviewEditSettings.clipSettingsArray[index].clipPath;
2715        }
2716        return maxHeight;
2717    }
2718
2719    /**
2720     * Populates the background music track properties
2721     *
2722     * @param mediaBGMList The background music list
2723     *
2724     */
2725    private void populateBackgroundMusicProperties(List<AudioTrack> mediaBGMList) {
2726
2727        if (mediaBGMList.size() == 1) {
2728            mAudioTrack = mediaBGMList.get(0);
2729        } else {
2730            mAudioTrack = null;
2731        }
2732
2733        if (mAudioTrack != null) {
2734            mAudioSettings = new AudioSettings();
2735            Properties mAudioProperties = new Properties();
2736            mAudioSettings.pFile = null;
2737            mAudioSettings.Id = mAudioTrack.getId();
2738            try {
2739                mAudioProperties = getMediaProperties(mAudioTrack.getFilename());
2740            } catch (Exception e) {
2741               throw new IllegalArgumentException("Unsupported file or file not found");
2742            }
2743            mAudioSettings.bRemoveOriginal = false;
2744            mAudioSettings.channels = mAudioProperties.audioChannels;
2745            mAudioSettings.Fs = mAudioProperties.audioSamplingFrequency;
2746            mAudioSettings.loop = mAudioTrack.isLooping();
2747            mAudioSettings.ExtendedFs = 0;
2748            mAudioSettings.pFile = mAudioTrack.getFilename();
2749            mAudioSettings.startMs = mAudioTrack.getStartTime();
2750            mAudioSettings.beginCutTime = mAudioTrack.getBoundaryBeginTime();
2751            mAudioSettings.endCutTime = mAudioTrack.getBoundaryEndTime();
2752            if (mAudioTrack.isMuted()) {
2753                mAudioSettings.volume = 0;
2754            } else {
2755                mAudioSettings.volume = mAudioTrack.getVolume();
2756            }
2757            mAudioSettings.fileType = mAudioProperties.fileType;
2758            mAudioSettings.ducking_lowVolume = mAudioTrack.getDuckedTrackVolume();
2759            mAudioSettings.ducking_threshold = mAudioTrack.getDuckingThreshhold();
2760            mAudioSettings.bInDucking_enable = mAudioTrack.isDuckingEnabled();
2761            mAudioTrackPCMFilePath = String.format(mProjectPath + "/" + AUDIO_TRACK_PCM_FILE);
2762            mAudioSettings.pcmFilePath = mAudioTrackPCMFilePath;
2763
2764            mPreviewEditSettings.backgroundMusicSettings = new BackgroundMusicSettings();
2765            mPreviewEditSettings.backgroundMusicSettings.file = mAudioTrackPCMFilePath;
2766            mPreviewEditSettings.backgroundMusicSettings.fileType = mAudioProperties.fileType;
2767            mPreviewEditSettings.backgroundMusicSettings.insertionTime =
2768                mAudioTrack.getStartTime();
2769            mPreviewEditSettings.backgroundMusicSettings.volumePercent = mAudioTrack.getVolume();
2770            mPreviewEditSettings.backgroundMusicSettings.beginLoop =
2771                mAudioTrack.getBoundaryBeginTime();
2772            mPreviewEditSettings.backgroundMusicSettings.endLoop =
2773                                               mAudioTrack.getBoundaryEndTime();
2774            mPreviewEditSettings.backgroundMusicSettings.enableDucking =
2775                mAudioTrack.isDuckingEnabled();
2776            mPreviewEditSettings.backgroundMusicSettings.duckingThreshold =
2777                mAudioTrack.getDuckingThreshhold();
2778            mPreviewEditSettings.backgroundMusicSettings.lowVolume =
2779                mAudioTrack.getDuckedTrackVolume();
2780            mPreviewEditSettings.backgroundMusicSettings.isLooping = mAudioTrack.isLooping();
2781            mPreviewEditSettings.primaryTrackVolume = 100;
2782            mProcessingState  = PROCESSING_AUDIO_PCM;
2783            mProcessingObject = mAudioTrack;
2784        } else {
2785            mAudioSettings = null;
2786            mPreviewEditSettings.backgroundMusicSettings = null;
2787            mAudioTrackPCMFilePath = null;
2788        }
2789    }
2790
2791    /**
2792     * Calculates all the effects in all the media items
2793     * in media items list
2794     *
2795     * @param mediaItemsList The media item list
2796     *
2797     * @return The total number of effects
2798     *
2799     */
2800    private int getTotalEffects(List<MediaItem> mediaItemsList) {
2801        int totalEffects = 0;
2802        final Iterator<MediaItem> it = mediaItemsList.iterator();
2803        while (it.hasNext()) {
2804            final MediaItem t = it.next();
2805            totalEffects += t.getAllEffects().size();
2806            totalEffects += t.getAllOverlays().size();
2807            final Iterator<Effect> ef = t.getAllEffects().iterator();
2808            while (ef.hasNext()) {
2809                final Effect e = ef.next();
2810                if (e instanceof EffectKenBurns) {
2811                    totalEffects--;
2812                }
2813            }
2814        }
2815        return totalEffects;
2816    }
2817
2818    /**
2819     * This function is responsible for forming clip settings
2820     * array and clip properties array including transition clips
2821     * and effect settings for preview purpose or export.
2822     *
2823     *
2824     * @param mediaItemsList The media item list
2825     * @param mediaTransitionList The transitions list
2826     * @param mediaBGMList The background music list
2827     * @param listener The MediaProcessingProgressListener
2828     *
2829     */
2830    void previewStoryBoard(List<MediaItem> mediaItemsList,
2831            List<Transition> mediaTransitionList, List<AudioTrack> mediaBGMList,
2832            MediaProcessingProgressListener listener) {
2833        if (mInvalidatePreviewArray) {
2834            int previewIndex = 0;
2835            int totalEffects = 0;
2836            int storyBoardTime = 0;
2837            int maxHeight = 0;
2838            int beginCutTime = 0;
2839            int endCutTime = 0;
2840            int effectIndex = 0;
2841            Transition lTransition = null;
2842            MediaItem lMediaItem = null;
2843            mPreviewEditSettings = new EditSettings();
2844            mClipProperties = new PreviewClipProperties();
2845            mTotalClips = 0;
2846
2847            mTotalClips = mediaItemsList.size();
2848            for (Transition transition : mediaTransitionList) {
2849                if (transition.getDuration() > 0) {
2850                    mTotalClips++;
2851                }
2852            }
2853
2854            totalEffects = getTotalEffects(mediaItemsList);
2855
2856            mPreviewEditSettings.clipSettingsArray = new ClipSettings[mTotalClips];
2857            mPreviewEditSettings.effectSettingsArray = new EffectSettings[totalEffects];
2858            mClipProperties.clipProperties = new Properties[mTotalClips];
2859
2860            /** record the call back progress listener */
2861            mMediaProcessingProgressListener = listener;
2862            mProgressToApp = 0;
2863
2864            if (mediaItemsList.size() > 0) {
2865                for (int i = 0; i < mediaItemsList.size(); i++) {
2866                    /* Get the Media Item from the list */
2867                    lMediaItem = mediaItemsList.get(i);
2868                    if (lMediaItem instanceof MediaVideoItem) {
2869                        beginCutTime = (int)((MediaVideoItem)lMediaItem).getBoundaryBeginTime();
2870                        endCutTime = (int)((MediaVideoItem)lMediaItem).getBoundaryEndTime();
2871                    } else if (lMediaItem instanceof MediaImageItem) {
2872                        beginCutTime = 0;
2873                        endCutTime = (int)((MediaImageItem)lMediaItem).getTimelineDuration();
2874                    }
2875                    /* Get the transition associated with Media Item */
2876                    lTransition = lMediaItem.getBeginTransition();
2877                    if (lTransition != null && (lTransition.getDuration() > 0)) {
2878                        /* generate transition clip */
2879                        generateTransition(lTransition, mPreviewEditSettings,
2880                                           mClipProperties, previewIndex);
2881                        storyBoardTime += mClipProperties.clipProperties[previewIndex].duration;
2882                        previewIndex++;
2883                    }
2884                    /* Populate media item properties */
2885                    maxHeight = populateMediaItemProperties(lMediaItem, previewIndex, maxHeight);
2886                    /* Get the clip properties of the media item. */
2887                    if (lMediaItem instanceof MediaImageItem) {
2888                        int tmpCnt = 0;
2889                        boolean bEffectKbPresent = false;
2890                        final List<Effect> effectList = lMediaItem.getAllEffects();
2891                        /**
2892                         * Check if Ken Burns effect is present
2893                         */
2894                        while (tmpCnt < effectList.size()) {
2895                            if (effectList.get(tmpCnt) instanceof EffectKenBurns) {
2896                                bEffectKbPresent = true;
2897                                break;
2898                            }
2899                            tmpCnt++;
2900                        }
2901
2902                        if (bEffectKbPresent) {
2903                            try {
2904                                  if(((MediaImageItem)lMediaItem).getGeneratedImageClip() != null) {
2905                                     mClipProperties.clipProperties[previewIndex]
2906                                        = getMediaProperties(((MediaImageItem)lMediaItem).
2907                                                             getGeneratedImageClip());
2908                                  }
2909                                  else {
2910                                   mClipProperties.clipProperties[previewIndex]
2911                                      = getMediaProperties(((MediaImageItem)lMediaItem).
2912                                                             getScaledImageFileName());
2913                                   mClipProperties.clipProperties[previewIndex].width =
2914                                             ((MediaImageItem)lMediaItem).getScaledWidth();
2915                                   mClipProperties.clipProperties[previewIndex].height =
2916                                             ((MediaImageItem)lMediaItem).getScaledHeight();
2917                                  }
2918                                } catch (Exception e) {
2919                                   throw new IllegalArgumentException("Unsupported file or file not found");
2920                                }
2921                         } else {
2922                              try {
2923                                  mClipProperties.clipProperties[previewIndex]
2924                                      = getMediaProperties(((MediaImageItem)lMediaItem).
2925                                                               getScaledImageFileName());
2926                              } catch (Exception e) {
2927                                throw new IllegalArgumentException("Unsupported file or file not found");
2928                              }
2929                            mClipProperties.clipProperties[previewIndex].width =
2930                                        ((MediaImageItem)lMediaItem).getScaledWidth();
2931                            mClipProperties.clipProperties[previewIndex].height =
2932                                        ((MediaImageItem)lMediaItem).getScaledHeight();
2933                        }
2934                    } else {
2935                        try {
2936                            mClipProperties.clipProperties[previewIndex]
2937                                 = getMediaProperties(lMediaItem.getFilename());
2938                            } catch (Exception e) {
2939                              throw new IllegalArgumentException("Unsupported file or file not found");
2940                          }
2941                    }
2942                    mClipProperties.clipProperties[previewIndex].Id = lMediaItem.getId();
2943                    checkOddSizeImage(lMediaItem, mClipProperties, previewIndex);
2944                    adjustVolume(lMediaItem, mClipProperties, previewIndex);
2945
2946                    /*
2947                     * Adjust media item start time and end time w.r.t to begin
2948                     * and end transitions associated with media item
2949                     */
2950
2951                    adjustMediaItemBoundary(mPreviewEditSettings.clipSettingsArray[previewIndex],
2952                            mClipProperties.clipProperties[previewIndex], lMediaItem);
2953
2954                    /*
2955                     * Get all the effects and overlays for that media item and
2956                     * adjust start time and duration of effects
2957                     */
2958
2959                    effectIndex = populateEffects(lMediaItem,
2960                            mPreviewEditSettings.effectSettingsArray, effectIndex, beginCutTime,
2961                            endCutTime, storyBoardTime);
2962                    storyBoardTime += mClipProperties.clipProperties[previewIndex].duration;
2963                    previewIndex++;
2964
2965                    /* Check if there is any end transition at last media item */
2966
2967                    if (i == (mediaItemsList.size() - 1)) {
2968                        lTransition = lMediaItem.getEndTransition();
2969                        if (lTransition != null && (lTransition.getDuration() > 0)) {
2970                            generateTransition(lTransition, mPreviewEditSettings, mClipProperties,
2971                                    previewIndex);
2972                            break;
2973                        }
2974                    }
2975                }
2976
2977                if (!mErrorFlagSet) {
2978                    mPreviewEditSettings.videoFrameSize = findVideoResolution(mVideoEditor
2979                            .getAspectRatio(), maxHeight);
2980                    populateBackgroundMusicProperties(mediaBGMList);
2981
2982                    /** call to native populate settings */
2983                    try {
2984                        nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
2985                    } catch (IllegalArgumentException ex) {
2986                        Log.e(TAG, "Illegal argument exception in nativePopulateSettings");
2987                        throw ex;
2988                    } catch (IllegalStateException ex) {
2989                        Log.e(TAG, "Illegal state exception in nativePopulateSettings");
2990                        throw ex;
2991                    } catch (RuntimeException ex) {
2992                        Log.e(TAG, "Runtime exception in nativePopulateSettings");
2993                        throw ex;
2994                    }
2995                    mInvalidatePreviewArray = false;
2996                    mProcessingState  = PROCESSING_NONE;
2997                }
2998            }
2999            if (mErrorFlagSet) {
3000                mErrorFlagSet = false;
3001                throw new RuntimeException("preview generation cannot be completed");
3002            }
3003        }
3004    } /* END of previewStoryBoard */
3005
3006    /**
3007     * This function is responsible for starting the preview
3008     *
3009     *
3010     * @param surface The surface on which preview has to be displayed
3011     * @param fromMs The time in ms from which preview has to be started
3012     * @param toMs The time in ms till preview has to be played
3013     * @param loop To loop the preview or not
3014     * @param callbackAfterFrameCount INdicated after how many frames
3015     * the callback is needed
3016     * @param listener The PreviewProgressListener
3017     */
3018    void doPreview(Surface surface, long fromMs, long toMs, boolean loop,
3019            int callbackAfterFrameCount, PreviewProgressListener listener) {
3020        mPreviewProgress = fromMs;
3021        mIsFirstProgress = true;
3022        mPreviewProgressListener = listener;
3023
3024        if (!mInvalidatePreviewArray) {
3025            try {
3026                /** Modify the image files names to rgb image files. */
3027                for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length;
3028                    clipCnt++) {
3029                    if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
3030                        mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
3031                            mPreviewEditSettings.clipSettingsArray[clipCnt].clipDecodedPath;
3032                    }
3033                }
3034                nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
3035                nativeStartPreview(surface, fromMs, toMs, callbackAfterFrameCount, loop);
3036            } catch (IllegalArgumentException ex) {
3037                Log.e(TAG, "Illegal argument exception in nativeStartPreview");
3038                throw ex;
3039            } catch (IllegalStateException ex) {
3040                Log.e(TAG, "Illegal state exception in nativeStartPreview");
3041                throw ex;
3042            } catch (RuntimeException ex) {
3043                Log.e(TAG, "Runtime exception in nativeStartPreview");
3044                throw ex;
3045            }
3046        } else {
3047            throw new IllegalStateException("generatePreview is in progress");
3048        }
3049    }
3050
3051    /**
3052     * This function is responsible for stopping the preview
3053     */
3054    long stopPreview() {
3055        return nativeStopPreview();
3056    }
3057
3058    /**
3059     * This function is responsible for rendering a single frame
3060     * from the complete story board on the surface
3061     *
3062     * @param surface The surface on which frame has to be rendered
3063     * @param time The time in ms at which the frame has to be rendered
3064     * @param surfaceWidth The surface width
3065     * @param surfaceHeight The surface height
3066     * @param overlayData The overlay data
3067     *
3068     * @return The actual time from the story board at which the  frame was extracted
3069     * and rendered
3070     */
3071    long renderPreviewFrame(Surface surface, long time, int surfaceWidth,
3072            int surfaceHeight, VideoEditor.OverlayData overlayData) {
3073        if (mInvalidatePreviewArray) {
3074            if (Log.isLoggable(TAG, Log.DEBUG)) {
3075                Log.d(TAG, "Call generate preview first");
3076            }
3077            throw new IllegalStateException("Call generate preview first");
3078        }
3079
3080        long timeMs = 0;
3081        try {
3082            for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length;
3083                  clipCnt++) {
3084                if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
3085                    mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
3086                        mPreviewEditSettings.clipSettingsArray[clipCnt].clipDecodedPath;
3087                }
3088            }
3089
3090            // Reset the render preview frame params that shall be set by native.
3091            mRenderPreviewOverlayFile = null;
3092            mRenderPreviewRenderingMode = MediaRendering.RESIZING;
3093
3094            nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
3095
3096            timeMs = (long)nativeRenderPreviewFrame(surface, time, surfaceWidth, surfaceHeight);
3097
3098            if (mRenderPreviewOverlayFile != null) {
3099                overlayData.set(BitmapFactory.decodeFile(mRenderPreviewOverlayFile),
3100                        mRenderPreviewRenderingMode);
3101            } else {
3102                overlayData.setClear();
3103            }
3104        } catch (IllegalArgumentException ex) {
3105            Log.e(TAG, "Illegal Argument exception in nativeRenderPreviewFrame");
3106            throw ex;
3107        } catch (IllegalStateException ex) {
3108            Log.e(TAG, "Illegal state exception in nativeRenderPreviewFrame");
3109            throw ex;
3110        } catch (RuntimeException ex) {
3111            Log.e(TAG, "Runtime exception in nativeRenderPreviewFrame");
3112            throw ex;
3113        }
3114
3115        return timeMs;
3116    }
3117
3118    private void previewFrameEditInfo(String filename, int renderingMode) {
3119        mRenderPreviewOverlayFile = filename;
3120        mRenderPreviewRenderingMode = renderingMode;
3121    }
3122
3123
3124    /**
3125     * This function is responsible for rendering a single frame
3126     * from a single media item on the surface
3127     *
3128     * @param surface The surface on which frame has to be rendered
3129     * @param filepath The file path for which the frame needs to be displayed
3130     * @param time The time in ms at which the frame has to be rendered
3131     * @param framewidth The frame width
3132     * @param framewidth The frame height
3133     *
3134     * @return The actual time from media item at which the  frame was extracted
3135     * and rendered
3136     */
3137    long renderMediaItemPreviewFrame(Surface surface, String filepath,
3138                                            long time, int framewidth, int frameheight) {
3139        long timeMs = 0;
3140        try {
3141            timeMs = (long)nativeRenderMediaItemPreviewFrame(surface, filepath, framewidth,
3142                    frameheight, 0, 0, time);
3143        } catch (IllegalArgumentException ex) {
3144            Log.e(TAG, "Illegal Argument exception in renderMediaItemPreviewFrame");
3145            throw ex;
3146        } catch (IllegalStateException ex) {
3147            Log.e(TAG, "Illegal state exception in renderMediaItemPreviewFrame");
3148            throw ex;
3149        } catch (RuntimeException ex) {
3150            Log.e(TAG, "Runtime exception in renderMediaItemPreviewFrame");
3151            throw ex;
3152        }
3153
3154        return timeMs;
3155    }
3156
3157    /**
3158     * This function sets the flag to invalidate the preview array
3159     * and for generating the preview again
3160     */
3161    void setGeneratePreview(boolean isRequired) {
3162        boolean semAcquiredDone = false;
3163        try {
3164            lock();
3165            semAcquiredDone = true;
3166            mInvalidatePreviewArray = isRequired;
3167        } catch (InterruptedException ex) {
3168            Log.e(TAG, "Runtime exception in renderMediaItemPreviewFrame");
3169        } finally {
3170            if (semAcquiredDone) {
3171                unlock();
3172            }
3173        }
3174    }
3175
3176    /**
3177     * @return Returns the current status of preview invalidation
3178     * flag
3179     */
3180    boolean getGeneratePreview() {
3181        return mInvalidatePreviewArray;
3182    }
3183
3184    /**
3185     * Calculates the aspect ratio from widht and height
3186     *
3187     * @param w The width of media item
3188     * @param h The height of media item
3189     *
3190     * @return The calculated aspect ratio
3191     */
3192    int getAspectRatio(int w, int h) {
3193        double apRatio = (double)(w) / (double)(h);
3194        BigDecimal bd = new BigDecimal(apRatio);
3195        bd = bd.setScale(3, BigDecimal.ROUND_HALF_UP);
3196        apRatio = bd.doubleValue();
3197        int var = MediaProperties.ASPECT_RATIO_16_9;
3198        if (apRatio >= 1.7) {
3199            var = MediaProperties.ASPECT_RATIO_16_9;
3200        } else if (apRatio >= 1.6) {
3201            var = MediaProperties.ASPECT_RATIO_5_3;
3202        } else if (apRatio >= 1.5) {
3203            var = MediaProperties.ASPECT_RATIO_3_2;
3204        } else if (apRatio > 1.3) {
3205            var = MediaProperties.ASPECT_RATIO_4_3;
3206        } else if (apRatio >= 1.2) {
3207            var = MediaProperties.ASPECT_RATIO_11_9;
3208        }
3209        return var;
3210    }
3211
3212    /**
3213     * Maps the file type used in native layer
3214     * to file type used in JAVA layer
3215     *
3216     * @param fileType The file type in native layer
3217     *
3218     * @return The File type in JAVA layer
3219     */
3220    int getFileType(int fileType) {
3221        int retValue = -1;
3222        switch (fileType) {
3223            case FileType.UNSUPPORTED:
3224                retValue = MediaProperties.FILE_UNSUPPORTED;
3225                break;
3226            case FileType.THREE_GPP:
3227                retValue = MediaProperties.FILE_3GP;
3228                break;
3229            case FileType.MP4:
3230                retValue = MediaProperties.FILE_MP4;
3231                break;
3232            case FileType.JPG:
3233                retValue = MediaProperties.FILE_JPEG;
3234                break;
3235            case FileType.PNG:
3236                retValue = MediaProperties.FILE_PNG;
3237                break;
3238            case FileType.MP3:
3239                retValue = MediaProperties.FILE_MP3;
3240                break;
3241            case FileType.M4V:
3242                retValue = MediaProperties.FILE_M4V;
3243                break;
3244            case FileType.AMR:
3245                retValue = MediaProperties.FILE_AMR;
3246                break;
3247
3248            default:
3249                retValue = -1;
3250        }
3251        return retValue;
3252    }
3253
3254    /**
3255     * Maps the video codec type used in native layer
3256     * to video codec type used in JAVA layer
3257     *
3258     * @param codecType The video codec type in native layer
3259     *
3260     * @return The video codec type in JAVA layer
3261     */
3262    int getVideoCodecType(int codecType) {
3263        int retValue = -1;
3264        switch (codecType) {
3265            case VideoFormat.H263:
3266                retValue = MediaProperties.VCODEC_H263;
3267                break;
3268            case VideoFormat.H264:
3269                retValue = MediaProperties.VCODEC_H264;
3270                break;
3271            case VideoFormat.MPEG4:
3272                retValue = MediaProperties.VCODEC_MPEG4;
3273                break;
3274            case VideoFormat.UNSUPPORTED:
3275
3276            default:
3277                retValue = -1;
3278        }
3279        return retValue;
3280    }
3281
3282    /**
3283     * Maps the audio codec type used in native layer
3284     * to audio codec type used in JAVA layer
3285     *
3286     * @param audioType The audio codec type in native layer
3287     *
3288     * @return The audio codec type in JAVA layer
3289     */
3290    int getAudioCodecType(int codecType) {
3291        int retValue = -1;
3292        switch (codecType) {
3293            case AudioFormat.AMR_NB:
3294                retValue = MediaProperties.ACODEC_AMRNB;
3295                break;
3296            case AudioFormat.AAC:
3297                retValue = MediaProperties.ACODEC_AAC_LC;
3298                break;
3299            case AudioFormat.MP3:
3300                retValue = MediaProperties.ACODEC_MP3;
3301                break;
3302
3303            default:
3304                retValue = -1;
3305        }
3306        return retValue;
3307    }
3308
3309    /**
3310     * Returns the frame rate as integer
3311     *
3312     * @param fps The fps as enum
3313     *
3314     * @return The frame rate as integer
3315     */
3316    int getFrameRate(int fps) {
3317        int retValue = -1;
3318        switch (fps) {
3319            case VideoFrameRate.FR_5_FPS:
3320                retValue = 5;
3321                break;
3322            case VideoFrameRate.FR_7_5_FPS:
3323                retValue = 8;
3324                break;
3325            case VideoFrameRate.FR_10_FPS:
3326                retValue = 10;
3327                break;
3328            case VideoFrameRate.FR_12_5_FPS:
3329                retValue = 13;
3330                break;
3331            case VideoFrameRate.FR_15_FPS:
3332                retValue = 15;
3333                break;
3334            case VideoFrameRate.FR_20_FPS:
3335                retValue = 20;
3336                break;
3337            case VideoFrameRate.FR_25_FPS:
3338                retValue = 25;
3339                break;
3340            case VideoFrameRate.FR_30_FPS:
3341                retValue = 30;
3342                break;
3343
3344            default:
3345                retValue = -1;
3346        }
3347        return retValue;
3348    }
3349
3350    /**
3351     * Maps the file type used in JAVA layer
3352     * to file type used in native layer
3353     *
3354     * @param fileType The file type in JAVA layer
3355     *
3356     * @return The File type in native layer
3357     */
3358    int getMediaItemFileType(int fileType) {
3359        int retValue = -1;
3360
3361        switch (fileType) {
3362            case MediaProperties.FILE_UNSUPPORTED:
3363                retValue = FileType.UNSUPPORTED;
3364                break;
3365            case MediaProperties.FILE_3GP:
3366                retValue = FileType.THREE_GPP;
3367                break;
3368            case MediaProperties.FILE_MP4:
3369                retValue = FileType.MP4;
3370                break;
3371            case MediaProperties.FILE_JPEG:
3372                retValue = FileType.JPG;
3373                break;
3374            case MediaProperties.FILE_PNG:
3375                retValue = FileType.PNG;
3376                break;
3377            case MediaProperties.FILE_M4V:
3378                retValue = FileType.M4V;
3379                break;
3380
3381            default:
3382                retValue = -1;
3383        }
3384        return retValue;
3385
3386    }
3387
3388    /**
3389     * Maps the rendering mode used in native layer
3390     * to rendering mode used in JAVA layer
3391     *
3392     * @param renderingMode The rendering mode in JAVA layer
3393     *
3394     * @return The rendering mode in native layer
3395     */
3396    int getMediaItemRenderingMode(int renderingMode) {
3397        int retValue = -1;
3398        switch (renderingMode) {
3399            case MediaItem.RENDERING_MODE_BLACK_BORDER:
3400                retValue = MediaRendering.BLACK_BORDERS;
3401                break;
3402            case MediaItem.RENDERING_MODE_STRETCH:
3403                retValue = MediaRendering.RESIZING;
3404                break;
3405            case MediaItem.RENDERING_MODE_CROPPING:
3406                retValue = MediaRendering.CROPPING;
3407                break;
3408
3409            default:
3410                retValue = -1;
3411        }
3412        return retValue;
3413    }
3414
3415    /**
3416     * Maps the transition behavior used in JAVA layer
3417     * to transition behavior used in native layer
3418     *
3419     * @param transitionType The transition behavior in JAVA layer
3420     *
3421     * @return The transition behavior in native layer
3422     */
3423    int getVideoTransitionBehaviour(int transitionType) {
3424        int retValue = -1;
3425        switch (transitionType) {
3426            case Transition.BEHAVIOR_SPEED_UP:
3427                retValue = TransitionBehaviour.SPEED_UP;
3428                break;
3429            case Transition.BEHAVIOR_SPEED_DOWN:
3430                retValue = TransitionBehaviour.SPEED_DOWN;
3431                break;
3432            case Transition.BEHAVIOR_LINEAR:
3433                retValue = TransitionBehaviour.LINEAR;
3434                break;
3435            case Transition.BEHAVIOR_MIDDLE_SLOW:
3436                retValue = TransitionBehaviour.SLOW_MIDDLE;
3437                break;
3438            case Transition.BEHAVIOR_MIDDLE_FAST:
3439                retValue = TransitionBehaviour.FAST_MIDDLE;
3440                break;
3441
3442            default:
3443                retValue = -1;
3444        }
3445        return retValue;
3446    }
3447
3448    /**
3449     * Maps the transition slide direction used in JAVA layer
3450     * to transition slide direction used in native layer
3451     *
3452     * @param slideDirection The transition slide direction
3453     * in JAVA layer
3454     *
3455     * @return The transition slide direction in native layer
3456     */
3457    int getSlideSettingsDirection(int slideDirection) {
3458        int retValue = -1;
3459        switch (slideDirection) {
3460            case TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN:
3461                retValue = SlideDirection.RIGHT_OUT_LEFT_IN;
3462                break;
3463            case TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN:
3464                retValue = SlideDirection.LEFT_OUT_RIGTH_IN;
3465                break;
3466            case TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN:
3467                retValue = SlideDirection.TOP_OUT_BOTTOM_IN;
3468                break;
3469            case TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN:
3470                retValue = SlideDirection.BOTTOM_OUT_TOP_IN;
3471                break;
3472
3473            default:
3474                retValue = -1;
3475        }
3476        return retValue;
3477    }
3478
3479    /**
3480     * Maps the effect color type used in JAVA layer
3481     * to effect color type used in native layer
3482     *
3483     * @param effect The EffectColor reference
3484     *
3485     * @return The color effect value from native layer
3486     */
3487    private int getEffectColorType(EffectColor effect) {
3488        int retValue = -1;
3489        switch (effect.getType()) {
3490            case EffectColor.TYPE_COLOR:
3491                if (effect.getColor() == EffectColor.GREEN) {
3492                    retValue = VideoEffect.GREEN;
3493                } else if (effect.getColor() == EffectColor.PINK) {
3494                    retValue = VideoEffect.PINK;
3495                } else if (effect.getColor() == EffectColor.GRAY) {
3496                    retValue = VideoEffect.BLACK_AND_WHITE;
3497                } else {
3498                    retValue = VideoEffect.COLORRGB16;
3499                }
3500                break;
3501            case EffectColor.TYPE_GRADIENT:
3502                retValue = VideoEffect.GRADIENT;
3503                break;
3504            case EffectColor.TYPE_SEPIA:
3505                retValue = VideoEffect.SEPIA;
3506                break;
3507            case EffectColor.TYPE_NEGATIVE:
3508                retValue = VideoEffect.NEGATIVE;
3509                break;
3510            case EffectColor.TYPE_FIFTIES:
3511                retValue = VideoEffect.FIFTIES;
3512                break;
3513
3514            default:
3515                retValue = -1;
3516        }
3517        return retValue;
3518    }
3519
3520    /**
3521     * Calculates video resolution for output clip
3522     * based on clip's height and aspect ratio of storyboard
3523     *
3524     * @param aspectRatio The aspect ratio of story board
3525     * @param height The height of clip
3526     *
3527     * @return The video resolution
3528     */
3529    private int findVideoResolution(int aspectRatio, int height) {
3530        final Pair<Integer, Integer>[] resolutions;
3531        final Pair<Integer, Integer> maxResolution;
3532        int retValue = VideoFrameSize.SIZE_UNDEFINED;
3533        switch (aspectRatio) {
3534            case MediaProperties.ASPECT_RATIO_3_2:
3535                if (height == MediaProperties.HEIGHT_480)
3536                    retValue = VideoFrameSize.NTSC;
3537                else if (height == MediaProperties.HEIGHT_720)
3538                    retValue = VideoFrameSize.W720p;
3539                break;
3540            case MediaProperties.ASPECT_RATIO_16_9:
3541                if (height == MediaProperties.HEIGHT_480)
3542                    retValue = VideoFrameSize.WVGA16x9;
3543                else if (height == MediaProperties.HEIGHT_720)
3544                    retValue = VideoFrameSize.V720p;
3545                else if (height == MediaProperties.HEIGHT_1080)
3546                    retValue = VideoFrameSize.V1080p;
3547                break;
3548            case MediaProperties.ASPECT_RATIO_4_3:
3549                if (height == MediaProperties.HEIGHT_480)
3550                    retValue = VideoFrameSize.VGA;
3551                else if (height == MediaProperties.HEIGHT_720)
3552                    retValue = VideoFrameSize.S720p;
3553                break;
3554            case MediaProperties.ASPECT_RATIO_5_3:
3555                if (height == MediaProperties.HEIGHT_480)
3556                    retValue = VideoFrameSize.WVGA;
3557                break;
3558            case MediaProperties.ASPECT_RATIO_11_9:
3559                if (height == MediaProperties.HEIGHT_144)
3560                    retValue = VideoFrameSize.QCIF;
3561                else if (height == MediaProperties.HEIGHT_288)
3562                    retValue = VideoFrameSize.CIF;
3563                break;
3564        }
3565        if (retValue == VideoFrameSize.SIZE_UNDEFINED) {
3566            resolutions = MediaProperties.getSupportedResolutions(mVideoEditor.getAspectRatio());
3567            // Get the highest resolution
3568            maxResolution = resolutions[resolutions.length - 1];
3569            retValue = findVideoResolution(mVideoEditor.getAspectRatio(), maxResolution.second);
3570        }
3571
3572        return retValue;
3573    }
3574
3575    /**
3576     *  Calculate a reasonable bitrate for generating intermediate clips.
3577     */
3578    private int findVideoBitrate(int videoFrameSize) {
3579        switch (videoFrameSize) {
3580            case VideoFrameSize.SQCIF:
3581            case VideoFrameSize.QQVGA:
3582            case VideoFrameSize.QCIF:
3583                return Bitrate.BR_128_KBPS;
3584            case VideoFrameSize.QVGA:
3585            case VideoFrameSize.CIF:
3586                return Bitrate.BR_384_KBPS;
3587            case VideoFrameSize.VGA:
3588            case VideoFrameSize.WVGA:
3589            case VideoFrameSize.NTSC:
3590            case VideoFrameSize.nHD:
3591            case VideoFrameSize.WVGA16x9:
3592                return Bitrate.BR_2_MBPS;
3593            case VideoFrameSize.V720p:
3594            case VideoFrameSize.W720p:
3595            case VideoFrameSize.S720p:
3596                return Bitrate.BR_5_MBPS;
3597            case VideoFrameSize.V1080p:
3598            default:
3599                return Bitrate.BR_8_MBPS;
3600        }
3601    }
3602
3603    /**
3604     * This method is responsible for exporting a movie
3605     *
3606     * @param filePath The output file path
3607     * @param projectDir The output project directory
3608     * @param height The height of clip
3609     * @param bitrate The bitrate at which the movie should be exported
3610     * @param mediaItemsList The media items list
3611     * @param mediaTransitionList The transitions list
3612     * @param mediaBGMList The background track list
3613     * @param listener The ExportProgressListener
3614     *
3615     */
3616    void export(String filePath, String projectDir, int height, int bitrate,
3617            List<MediaItem> mediaItemsList, List<Transition> mediaTransitionList,
3618            List<AudioTrack> mediaBGMList, ExportProgressListener listener) {
3619
3620        int outBitrate = 0;
3621        mExportFilename = filePath;
3622        previewStoryBoard(mediaItemsList, mediaTransitionList, mediaBGMList,null);
3623        mExportProgressListener = listener;
3624        int outVideoProfile = 0;
3625        int outVideoLevel = 0;
3626
3627        /** Check the platform specific maximum export resolution */
3628        VideoEditorProfile veProfile = VideoEditorProfile.get();
3629        if (veProfile == null) {
3630            throw new RuntimeException("Can't get the video editor profile");
3631        }
3632        final int maxOutputHeight = veProfile.maxOutputVideoFrameHeight;
3633        final int maxOutputWidth = veProfile.maxOutputVideoFrameWidth;
3634        if (height > maxOutputHeight) {
3635            throw new IllegalArgumentException(
3636                    "Unsupported export resolution. Supported maximum width:" +
3637                    maxOutputWidth + " height:" + maxOutputHeight +
3638                    " current height:" + height);
3639        }
3640        outVideoProfile = VideoEditorProfile.getExportProfile(mExportVideoCodec);
3641        outVideoLevel = VideoEditorProfile.getExportLevel(mExportVideoCodec);
3642
3643        mProgressToApp = 0;
3644
3645        switch (bitrate) {
3646            case MediaProperties.BITRATE_28K:
3647                outBitrate = Bitrate.BR_32_KBPS;
3648                break;
3649            case MediaProperties.BITRATE_40K:
3650                outBitrate = Bitrate.BR_48_KBPS;
3651                break;
3652            case MediaProperties.BITRATE_64K:
3653                outBitrate = Bitrate.BR_64_KBPS;
3654                break;
3655            case MediaProperties.BITRATE_96K:
3656                outBitrate = Bitrate.BR_96_KBPS;
3657                break;
3658            case MediaProperties.BITRATE_128K:
3659                outBitrate = Bitrate.BR_128_KBPS;
3660                break;
3661            case MediaProperties.BITRATE_192K:
3662                outBitrate = Bitrate.BR_192_KBPS;
3663                break;
3664            case MediaProperties.BITRATE_256K:
3665                outBitrate = Bitrate.BR_256_KBPS;
3666                break;
3667            case MediaProperties.BITRATE_384K:
3668                outBitrate = Bitrate.BR_384_KBPS;
3669                break;
3670            case MediaProperties.BITRATE_512K:
3671                outBitrate = Bitrate.BR_512_KBPS;
3672                break;
3673            case MediaProperties.BITRATE_800K:
3674                outBitrate = Bitrate.BR_800_KBPS;
3675                break;
3676            case MediaProperties.BITRATE_2M:
3677                outBitrate = Bitrate.BR_2_MBPS;
3678                break;
3679            case MediaProperties.BITRATE_5M:
3680                outBitrate = Bitrate.BR_5_MBPS;
3681                break;
3682            case MediaProperties.BITRATE_8M:
3683                outBitrate = Bitrate.BR_8_MBPS;
3684                break;
3685
3686            default:
3687                throw new IllegalArgumentException("Argument Bitrate incorrect");
3688        }
3689        mPreviewEditSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
3690        mPreviewEditSettings.outputFile = mOutputFilename = filePath;
3691
3692        int aspectRatio = mVideoEditor.getAspectRatio();
3693        mPreviewEditSettings.videoFrameSize = findVideoResolution(aspectRatio, height);
3694        mPreviewEditSettings.videoFormat = mExportVideoCodec;
3695        mPreviewEditSettings.audioFormat = mExportAudioCodec;
3696        mPreviewEditSettings.videoProfile = outVideoProfile;
3697        mPreviewEditSettings.videoLevel = outVideoLevel;
3698        mPreviewEditSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
3699        mPreviewEditSettings.maxFileSize = 0;
3700        mPreviewEditSettings.audioChannels = 2;
3701        mPreviewEditSettings.videoBitrate = outBitrate;
3702        mPreviewEditSettings.audioBitrate = Bitrate.BR_96_KBPS;
3703
3704        mPreviewEditSettings.transitionSettingsArray = new TransitionSettings[mTotalClips - 1];
3705        for (int index = 0; index < mTotalClips - 1; index++) {
3706            mPreviewEditSettings.transitionSettingsArray[index] = new TransitionSettings();
3707            mPreviewEditSettings.transitionSettingsArray[index].videoTransitionType =
3708                VideoTransition.NONE;
3709            mPreviewEditSettings.transitionSettingsArray[index].audioTransitionType =
3710                AudioTransition.NONE;
3711        }
3712
3713        for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length; clipCnt++) {
3714            if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
3715                mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
3716                mPreviewEditSettings.clipSettingsArray[clipCnt].clipOriginalPath;
3717            }
3718        }
3719        nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
3720
3721        int err = 0;
3722        try {
3723            mProcessingState  = PROCESSING_EXPORT;
3724            mProcessingObject = null;
3725            err = generateClip(mPreviewEditSettings);
3726            mProcessingState  = PROCESSING_NONE;
3727        } catch (IllegalArgumentException ex) {
3728            Log.e(TAG, "IllegalArgument for generateClip");
3729            throw ex;
3730        } catch (IllegalStateException ex) {
3731            Log.e(TAG, "IllegalStateExceptiont for generateClip");
3732            throw ex;
3733        } catch (RuntimeException ex) {
3734            Log.e(TAG, "RuntimeException for generateClip");
3735            throw ex;
3736        }
3737
3738        if (err != 0) {
3739            Log.e(TAG, "RuntimeException for generateClip");
3740            throw new RuntimeException("generateClip failed with error=" + err);
3741        }
3742
3743        mExportProgressListener = null;
3744    }
3745
3746    /**
3747     * This methods takes care of stopping the Export process
3748     *
3749     * @param The input file name for which export has to be stopped
3750     */
3751    void stop(String filename) {
3752        try {
3753            stopEncoding();
3754            new File(mExportFilename).delete();
3755        } catch (IllegalStateException ex) {
3756            Log.e(TAG, "Illegal state exception in unload settings");
3757            throw ex;
3758        } catch (RuntimeException ex) {
3759            Log.e(TAG, "Runtime exception in unload settings");
3760            throw ex;
3761        }
3762    }
3763
3764    /**
3765     * This method extracts a frame from the input file
3766     * and returns the frame as a bitmap. See getPixelsList() for more information.
3767     */
3768    Bitmap getPixels(String filename, int width, int height, long timeMs,
3769            int videoRotation) {
3770        final Bitmap result[] = new Bitmap[1];
3771        getPixelsList(filename, width, height, timeMs, timeMs, 1, new int[] {0},
3772                new MediaItem.GetThumbnailListCallback() {
3773            public void onThumbnail(Bitmap bitmap, int index) {
3774                result[0] = bitmap;
3775            }
3776        }, videoRotation);
3777        return result[0];
3778    }
3779
3780    /**
3781     * This method extracts a list of frame from the
3782     * input file and returns the frame in bitmap array
3783     *
3784     * @param filename The input file name
3785     * @param width The width of the output frame, before rotation
3786     * @param height The height of the output frame, before rotation
3787     * @param startMs The starting time in ms
3788     * @param endMs The end time in ms
3789     * @param thumbnailCount The number of frames to be extracted
3790     * @param indices The indices of thumbnails wanted
3791     * @param callback The callback used to pass back the bitmaps
3792     * @param videoRotation The rotation degree need to be done for the bitmap
3793     *
3794     * @return The frames as bitmaps in bitmap array
3795     **/
3796    void getPixelsList(String filename, final int width, final int height,
3797            long startMs, long endMs, int thumbnailCount, int[] indices,
3798            final MediaItem.GetThumbnailListCallback callback,
3799            final int videoRotation) {
3800
3801        // The decoder needs output width and height as even
3802        final int decWidth = (width + 1) & 0xFFFFFFFE;
3803        final int decHeight = (height + 1) & 0xFFFFFFFE;
3804        final int thumbnailSize = decWidth * decHeight;
3805
3806        // We convert the decoder output (in int[]) to a bitmap by first
3807        // copy it into an IntBuffer, then use Bitmap.copyPixelsFromBuffer to
3808        // copy it to the bitmap.
3809        final int[] decArray = new int[thumbnailSize];
3810        final IntBuffer decBuffer = IntBuffer.allocate(thumbnailSize);
3811
3812        // If we need to resize and/or rotate the decoder output, we need a
3813        // temporary bitmap to hold the decoded output.
3814        final boolean needToMassage =
3815                (decWidth != width || decHeight != height || videoRotation != 0);
3816        final Bitmap tmpBitmap = needToMassage
3817                ? Bitmap.createBitmap(decWidth, decHeight, Bitmap.Config.ARGB_8888)
3818                : null;
3819
3820        // The final output bitmap width/height may swap because of rotation.
3821        final boolean needToSwapWH = (videoRotation == 90 || videoRotation == 270);
3822        final int outWidth = needToSwapWH ? height : width;
3823        final int outHeight = needToSwapWH ? width : height;
3824
3825        nativeGetPixelsList(filename, decArray, decWidth, decHeight,
3826                thumbnailCount, startMs, endMs, indices,
3827                new NativeGetPixelsListCallback() {
3828            public void onThumbnail(int index) {
3829                // This is the bitmap we will output to the client
3830                Bitmap outBitmap = Bitmap.createBitmap(
3831                        outWidth, outHeight, Bitmap.Config.ARGB_8888);
3832
3833                // Copy int[] to IntBuffer
3834                decBuffer.put(decArray, 0, thumbnailSize);
3835                decBuffer.rewind();
3836
3837                if (!needToMassage) {
3838                    // We can directly read the decoded result to output bitmap
3839                    outBitmap.copyPixelsFromBuffer(decBuffer);
3840                } else {
3841                    // Copy the decoded result to an intermediate bitmap first
3842                    tmpBitmap.copyPixelsFromBuffer(decBuffer);
3843
3844                    // Create a canvas to resize/rotate the bitmap
3845                    // First scale the decoded bitmap to (0,0)-(1,1), rotate it
3846                    // with (0.5, 0.5) as center, then scale it to
3847                    // (outWidth, outHeight).
3848                    final Canvas canvas = new Canvas(outBitmap);
3849                    Matrix m = new Matrix();
3850                    float sx = 1f / decWidth;
3851                    float sy = 1f / decHeight;
3852                    m.postScale(sx, sy);
3853                    m.postRotate(videoRotation, 0.5f, 0.5f);
3854                    m.postScale(outWidth, outHeight);
3855                    canvas.drawBitmap(tmpBitmap, m, sResizePaint);
3856                }
3857                callback.onThumbnail(outBitmap, index);
3858            }
3859        });
3860
3861        if (tmpBitmap != null) {
3862            tmpBitmap.recycle();
3863        }
3864    }
3865
3866    interface NativeGetPixelsListCallback {
3867        public void onThumbnail(int index);
3868    }
3869
3870    /**
3871     * This method generates the audio graph
3872     *
3873     * @param uniqueId The unique id
3874     * @param inFileName The inputFile
3875     * @param OutAudiGraphFileName output filename
3876     * @param frameDuration The each frame duration
3877     * @param audioChannels The number of audio channels
3878     * @param samplesCount Total number of samples count
3879     * @param listener ExtractAudioWaveformProgressListener reference
3880     * @param isVideo The flag to indicate if the file is video file or not
3881     *
3882     **/
3883    void generateAudioGraph(String uniqueId, String inFileName, String OutAudiGraphFileName,
3884            int frameDuration, int audioChannels, int samplesCount,
3885            ExtractAudioWaveformProgressListener listener, boolean isVideo) {
3886        String tempPCMFileName;
3887
3888        mExtractAudioWaveformProgressListener = listener;
3889
3890        /**
3891         * In case of Video, first call will generate the PCM file to make the
3892         * audio graph
3893         */
3894        if (isVideo) {
3895            tempPCMFileName = String.format(mProjectPath + "/" + uniqueId + ".pcm");
3896        } else {
3897            tempPCMFileName = mAudioTrackPCMFilePath;
3898        }
3899
3900        /**
3901         * For Video item, generate the PCM
3902         */
3903        if (isVideo) {
3904            nativeGenerateRawAudio(inFileName, tempPCMFileName);
3905        }
3906
3907        nativeGenerateAudioGraph(tempPCMFileName, OutAudiGraphFileName, frameDuration,
3908                audioChannels, samplesCount);
3909
3910        /**
3911         * Once the audio graph file is generated, delete the pcm file
3912         */
3913        if (isVideo) {
3914            new File(tempPCMFileName).delete();
3915        }
3916    }
3917
3918    void clearPreviewSurface(Surface surface) {
3919        nativeClearSurface(surface);
3920    }
3921
3922    /**
3923     * Grab the semaphore which arbitrates access to the editor
3924     *
3925     * @throws InterruptedException
3926     */
3927    private void lock() throws InterruptedException {
3928        if (Log.isLoggable(TAG, Log.DEBUG)) {
3929            Log.d(TAG, "lock: grabbing semaphore", new Throwable());
3930        }
3931        mLock.acquire();
3932        if (Log.isLoggable(TAG, Log.DEBUG)) {
3933            Log.d(TAG, "lock: grabbed semaphore");
3934        }
3935    }
3936
3937    /**
3938     * Release the semaphore which arbitrates access to the editor
3939     */
3940    private void unlock() {
3941        if (Log.isLoggable(TAG, Log.DEBUG)) {
3942            Log.d(TAG, "unlock: releasing semaphore");
3943        }
3944        mLock.release();
3945    }
3946
3947    /**     Native Methods        */
3948    native Properties getMediaProperties(String file) throws IllegalArgumentException,
3949            IllegalStateException, RuntimeException, Exception;
3950
3951    /**
3952     * Get the version of ManualEdit.
3953     *
3954     * @return version of ManualEdit
3955     * @throws RuntimeException if an error occurred
3956     * @see Version
3957     */
3958    private static native Version getVersion() throws RuntimeException;
3959
3960    /**
3961     * Returns the video thumbnail in an array of integers. Output format is
3962     * ARGB8888.
3963     *
3964     * @param pixelArray the array that receives the pixel values
3965     * @param width width of the video thumbnail
3966     * @param height height of the video thumbnail
3967     * @param timeMS desired time of the thumbnail in ms
3968     * @return actual time in ms of the thumbnail generated
3969     * @throws IllegalStateException if the class has not been initialized
3970     * @throws IllegalArgumentException if the pixelArray is not available or
3971     *             one of the dimensions is negative or zero or the time is
3972     *             negative
3973     * @throws RuntimeException on runtime errors in native code
3974     */
3975    private native int nativeGetPixels(String fileName, int[] pixelArray, int width, int height,
3976            long timeMS);
3977
3978    private native int nativeGetPixelsList(String fileName, int[] pixelArray,
3979            int width, int height, int nosofTN, long startTimeMs,
3980            long endTimeMs, int[] indices, NativeGetPixelsListCallback callback);
3981
3982    /**
3983     * Releases the JNI and cleans up the core native module.. Should be called
3984     * only after init( )
3985     *
3986     * @throws IllegalStateException if the method could not be called
3987     */
3988    private native void release() throws IllegalStateException, RuntimeException;
3989
3990    /*
3991     * Clear the preview surface
3992     */
3993    private native void nativeClearSurface(Surface surface);
3994
3995    /**
3996     * Stops the encoding. This method should only be called after encoding has
3997     * started using method <code> startEncoding</code>
3998     *
3999     * @throws IllegalStateException if the method could not be called
4000     */
4001    private native void stopEncoding() throws IllegalStateException, RuntimeException;
4002
4003
4004    private native void _init(String tempPath, String libraryPath)
4005            throws IllegalArgumentException, IllegalStateException, RuntimeException;
4006
4007    private native void nativeStartPreview(Surface mSurface, long fromMs, long toMs,
4008            int callbackAfterFrameCount, boolean loop) throws IllegalArgumentException,
4009            IllegalStateException, RuntimeException;
4010
4011    private native void nativePopulateSettings(EditSettings editSettings,
4012            PreviewClipProperties mProperties, AudioSettings mAudioSettings)
4013    throws IllegalArgumentException, IllegalStateException, RuntimeException;
4014
4015    private native int nativeRenderPreviewFrame(Surface mSurface, long timeMs,
4016                                                 int surfaceWidth, int surfaceHeight)
4017                                                 throws IllegalArgumentException,
4018                                                 IllegalStateException, RuntimeException;
4019
4020    private native int nativeRenderMediaItemPreviewFrame(Surface mSurface, String filepath,
4021            int framewidth, int frameheight, int surfacewidth, int surfaceheight, long timeMs)
4022    throws IllegalArgumentException, IllegalStateException, RuntimeException;
4023
4024    private native int nativeStopPreview();
4025
4026    private native int nativeGenerateAudioGraph(String pcmFilePath, String outGraphPath,
4027            int frameDuration, int channels, int sampleCount);
4028
4029    private native int nativeGenerateRawAudio(String InFileName, String PCMFileName);
4030
4031    private native int nativeGenerateClip(EditSettings editSettings)
4032    throws IllegalArgumentException, IllegalStateException, RuntimeException;
4033
4034}
4035