1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.mediaframeworktest;
18
19import java.io.File;
20import java.io.FileInputStream;
21import java.io.IOException;
22import java.text.SimpleDateFormat;
23import java.util.Date;
24import java.util.Random;
25
26import junit.framework.Assert;
27import android.graphics.Bitmap;
28import android.graphics.BitmapFactory;
29import android.media.videoeditor.AudioTrack;
30import android.media.videoeditor.EffectColor;
31import android.media.videoeditor.MediaImageItem;
32import android.media.videoeditor.MediaItem;
33import android.media.videoeditor.MediaVideoItem;
34import android.media.videoeditor.OverlayFrame;
35import android.media.videoeditor.TransitionAlpha;
36import android.media.videoeditor.TransitionCrossfade;
37import android.media.videoeditor.TransitionFadeBlack;
38import android.media.videoeditor.TransitionSliding;
39import android.media.videoeditor.VideoEditor;
40import android.media.videoeditor.VideoEditorFactory;
41import android.util.Log;
42import android.os.Environment;
43
44/**
45 * This class has the names of the all the activity name and variables in the
46 * instrumentation test.
47 */
48public class VideoEditorHelper extends Assert {
49
50    private final String TAG = "VideoEditorMediaNames";
51
52    public VideoEditorHelper() {
53
54    }
55
56    public static final String PROJECT_LOCATION_COMMON =
57        Environment.getExternalStorageDirectory().toString() + "/";
58
59    public static final String INPUT_FILE_PATH_COMMON = PROJECT_LOCATION_COMMON +
60        "media_api/videoeditor/";
61
62    // -----------------------------------------------------------------
63    // HELPER METHODS
64    // -----------------------------------------------------------------
65
66    /**
67     * This method creates an object of VideoEditor
68     *
69     * @param projectPath the directory where all files related to project will
70     *            be stored
71     * @param className The class which implements the VideoEditor Class
72     * @return the object of VideoEditor
73     */
74    public VideoEditor createVideoEditor(String projectPath) {
75        VideoEditor mVideoEditor = null;
76        try {
77            mVideoEditor = VideoEditorFactory.create(projectPath);
78            assertNotNull("VideoEditor", mVideoEditor);
79        } catch (Exception e) {
80            fail("Unable to create Video Editor");
81        }
82        return mVideoEditor;
83    }
84
85    /**
86     *This method deletes the VideoEditor object created using
87     * createVideoEditor method
88     *
89     * @param videoEditor the VideoEditor object which needs to be cleaned up
90     */
91    public void destroyVideoEditor(VideoEditor videoEditor) {
92        // Release VideoEditor
93        if (videoEditor != null) {
94            try {
95                videoEditor.release();
96            } catch (Exception e) {
97                fail("Unable to destory Video Editor");
98            }
99        }
100    }
101
102    /**
103     *This Method checks the Range in "RangePercent" (say 10)
104     *
105     * @param int Expected data
106     * @param actual data
107     * @return boolean flag which confirms the range matching
108     */
109    public boolean checkRange(long expected, long actual, long rangePercent) {
110        long range = 0;
111        range = (100 * actual) / expected;
112
113        Log.i("checkRange", "Range = " + range);
114        if ((range > (100 - rangePercent)) && (range < (100 + rangePercent))) {
115            return true;
116        } else {
117            return false;
118        }
119    }
120
121    /**
122     *This Method Creates a Bitmap with the given input file
123     *
124     * @param file the Input whose Bitmap has top be extracted
125     * @return an Object of EffectColor
126     */
127    public Bitmap getBitmap(String file, int width, int height) throws IOException {
128        assertNotNull("Bitmap File is Null", file);
129        FileInputStream inputStream = null;
130        Bitmap overlayBmp = null;
131        if (!new File(file).exists())
132            throw new IOException("File not Found " + file);
133        try {
134            final BitmapFactory.Options dbo = new BitmapFactory.Options();
135            dbo.inJustDecodeBounds = true;
136            dbo.outWidth = width;
137            dbo.outHeight = height;
138            File flPtr = new File(file);
139            inputStream = new FileInputStream(flPtr);
140            final Bitmap srcBitmap = BitmapFactory.decodeStream(inputStream);
141            overlayBmp = Bitmap.createBitmap(srcBitmap);
142            assertNotNull("Bitmap 1", srcBitmap);
143            assertNotNull("Bitmap 2", overlayBmp);
144            inputStream.close();
145        } catch (IOException e) {
146            e.printStackTrace();
147        }
148        return overlayBmp;
149    }
150
151    /**
152     *This Method Create a Media Video Item with the specified params
153     *
154     * @return an Object of MediaVideoItem
155     */
156    public MediaVideoItem createMediaItem(VideoEditor videoEditor,
157        String MediaId, String filename, int renderingMode) {
158        MediaVideoItem mvi = null;
159        try {
160            mvi = new MediaVideoItem(videoEditor, MediaId, filename,
161                renderingMode);
162            assertNotNull("Can not create an object of MediaVideoItem", mvi);
163        } catch (IllegalArgumentException e) {
164            throw new IllegalArgumentException
165                ("Can not create an object of Media Video Item with file name = "
166                    + filename + " Issue = " + e.toString());
167        } catch (IOException e) {
168            assertTrue
169                ("Can not create an object of Media Video Item with file name = "
170                    + filename + " Issue = " + e.toString(), false);
171        }
172        return mvi;
173    }
174
175    /**
176     *This Method Create a Media Image Item with the specified params
177     *
178     * @return an Object of MediaImageItem
179     */
180    public MediaImageItem createMediaItem(VideoEditor videoEditor,
181        String MediaId, String filename, long duration, int renderingMode) {
182        MediaImageItem mii = null;
183        try {
184            mii = new MediaImageItem(videoEditor, MediaId, filename, duration,
185                renderingMode);
186            assertNotNull("Can not create an object of MediaImageItem", mii);
187
188        } catch (IllegalArgumentException e) {
189            assertTrue("Can not create an object of Media Image with file name = "
190                + filename + " Issue = " + e.toString(), false);
191        } catch (IOException e) {
192            assertTrue("Can not create an object of Media Image with file name = "
193                + filename + " Issue = " + e.toString(), false);
194        }
195        return mii;
196    }
197
198    /**
199     *This Method Create a Effect with the specified params
200     *
201     * @return an Object of EffectColor
202     */
203    public EffectColor createEffectItem(MediaItem mediaItem, String effectId,
204        long startTime, long duration, int effectType, int colorType) {
205        EffectColor effectonMVI = null;
206        effectonMVI = new EffectColor(mediaItem, effectId, startTime,
207            duration, effectType, colorType);
208        return effectonMVI;
209    }
210
211    /**
212     *This Method creates object of Type Transition Cross fade
213     *
214     * @return TransitionCrossfade object
215     */
216    public TransitionCrossfade createTCrossFade(String transitionId,
217        MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
218        int behavior) {
219        Log.i("TransitionCrossfade Details === ", "Transid ID = " + transitionId +
220            " Duration= " + durationMs + " Behaviour " + behavior);
221
222        TransitionCrossfade transitionCF = null;
223            transitionCF = new TransitionCrossfade(transitionId, afterMediaItem,
224                beforeMediaItem, durationMs, behavior);
225        return transitionCF;
226    }
227
228    /**
229     *This Method creates object of Type TransitionFadeBlack
230     *
231     * @return TransitionFadeBlack object
232     */
233    public TransitionFadeBlack createTFadeBlack(String transitionId,
234        MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
235        int behavior) {
236        TransitionFadeBlack transitionFB = null;
237
238        transitionFB = new TransitionFadeBlack(transitionId, afterMediaItem,
239            beforeMediaItem, durationMs, behavior);
240        return transitionFB;
241    }
242
243    /**
244     *This Method creates object of Type TransitionSliding
245     *
246     * @return TransitionSliding object
247     */
248    public TransitionSliding createTSliding(String transitionId,
249        MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
250        int behavior, int direction) {
251        TransitionSliding transSlide = null;
252            transSlide = new TransitionSliding(transitionId, afterMediaItem,
253                beforeMediaItem, durationMs, behavior, direction);
254        return transSlide;
255    }
256
257    /**
258     *This Method creates object of Type TranistionAlpha
259     *
260     * @return TranistionAlpha object
261     */
262
263    public TransitionAlpha createTAlpha(String transitionId,
264        MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
265        int behavior, String maskFilename, int blendingPercent, boolean invert) {
266        TransitionAlpha transA = null;
267            transA = new TransitionAlpha(transitionId, afterMediaItem,
268                beforeMediaItem, durationMs, behavior, maskFilename,
269                blendingPercent, invert);
270        return transA;
271    }
272
273    /**
274     *This Method creates object of Type OverlayFrame
275     *
276     * @return OverlayFrame object
277     */
278
279    public OverlayFrame createOverlay(MediaItem mediaItem, String overlayId,
280        Bitmap bitmap, long startTimeMs, long durationMs) {
281        OverlayFrame overLayFrame = null;
282        overLayFrame = new OverlayFrame(mediaItem, overlayId, bitmap,
283                startTimeMs, durationMs);
284        return overLayFrame;
285    }
286
287    /**
288     *This Method creates object of Type AudioTrack
289     *
290     * @return OverlayFrame object
291     */
292    public AudioTrack createAudio(VideoEditor videoEditor, String audioTrackId,
293        String filename) {
294        AudioTrack audio = null;
295        try {
296            audio = new AudioTrack(videoEditor, audioTrackId, filename);
297            assertNotNull("Cant not create an object of an  AudioTrack " +
298                audioTrackId, audio);
299        } catch (IllegalArgumentException e) {
300            assertTrue("Can not create object of an AudioTrack " +
301                audioTrackId + " Issue = " + e.toString(), false);
302        } catch (IOException e) {
303            assertTrue("Can not create object of an AudioTrack " +
304                audioTrackId + " Issue = " + e.toString(), false);
305        }
306        return audio;
307    }
308
309    /**
310     *This Method validates the Exported Movie,as per the specified params
311     * during Export
312     */
313
314    public void validateExport(VideoEditor videoEditor, String fileName,
315        int export_height, int startTime, long endTime, int vCodec, int aCodec) {
316        File tempFile = new File(fileName);
317        assertEquals("Exported FileName", tempFile.exists(), true);
318        final MediaVideoItem mvi = createMediaItem(videoEditor, "m1", fileName,
319            MediaItem.RENDERING_MODE_BLACK_BORDER);
320
321        Log.i(TAG, "VideoCodec for file = " + fileName +
322            "\tExpected Video Codec = " + vCodec + "\tActual Video Codec = " +
323            mvi.getVideoType());
324        assertEquals("Export: Video Codec Mismatch for file = " + fileName +
325            "\t<expected> " + vCodec + "\t<actual> " + mvi.getVideoType(),
326            vCodec, mvi.getVideoType());
327
328        Log.i(TAG, "Height for file = " + fileName + "\tExpected Height = " +
329            export_height + "\tActual VideoHeight = " + mvi.getHeight());
330        assertEquals("Export height Mismatch for file " + fileName +
331            "\t<expected> " + export_height + "\t<actual> " + mvi.getHeight(),
332             export_height, mvi.getHeight());
333        if (startTime == 0) {
334            if (endTime != 0) {
335                Log.i(TAG, "TimeLine Expected = " + (startTime + endTime) +
336                    "\t VideoTime= " + mvi.getTimelineDuration());
337                assertTrue("Timeline Duration Mismatch for file " + fileName +
338                    "<expected> " + (startTime + endTime) + "\t<actual> " +
339                    mvi.getTimelineDuration(), checkRange((startTime +
340                        endTime), mvi.getTimelineDuration(), 10));
341            }
342        } else {
343            Log.i(TAG, "TimeLine Expected = " + (endTime - startTime) +
344                "\t VideoTime= " + mvi.getTimelineDuration());
345            assertTrue("Timeline Duration Mismatch for file " + fileName +
346                "<expected> " + (endTime - startTime) + "\t<actual> " +
347                mvi.getTimelineDuration(), checkRange((endTime -
348                    startTime), (int)mvi.getTimelineDuration(), 10));
349        }
350    }
351
352    /**
353     * @param videoEditor
354     * @param fileName
355     * @param export_bitrate
356     * @param export_height
357     * @param startTime
358     * @param endTime
359     * @param vCodec
360     * @param aCodec
361     */
362    public void validateExport(VideoEditor videoEditor, String fileName,
363        int export_height, int startTime, int endTime, int vCodec, int aCodec) {
364        File tempFile = new File(fileName);
365        assertEquals("Exported FileName", tempFile.exists(), true);
366        final MediaVideoItem mvi = createMediaItem(videoEditor, "m1", fileName,
367            MediaItem.RENDERING_MODE_BLACK_BORDER);
368        Log.i(TAG, "VideoCodec for file = " + fileName +
369            "\tExpected Video Codec = " + vCodec + "\tActual Video Codec = " +
370            mvi.getVideoType());
371        assertEquals("Export: Video Codec Mismatch for file = " + fileName +
372            "\t<expected> " + vCodec + "\t<actual> " + mvi.getVideoType(),
373            vCodec, mvi.getVideoType());
374
375        Log.i(TAG, "AudioCodec for file = " + fileName +
376            "\tExpected Audio Codec = " + aCodec + "\tActual Audio Codec = " +
377            mvi.getAudioType());
378        assertEquals("Export: Audio Codec Mismatch for file = " + fileName +
379            "\t<expected> " + aCodec + "\t<actual> " + mvi.getAudioType(),
380            aCodec, mvi.getAudioType());
381
382        Log.i(TAG, "Height for file = " + fileName + "\tExpected Height = " +
383            export_height + "\tActual VideoHeight = " + mvi.getHeight());
384        assertEquals("Export: height Mismatch for file " + fileName +
385            "\t<expected> " + export_height + "\t<actual> " + mvi.getHeight(),
386            export_height, mvi.getHeight());
387        if (startTime == 0) {
388            if (endTime != 0) {
389                Log.i(TAG, "TimeLine Expected = " + (startTime + endTime) +
390                    "\t VideoTime= " + mvi.getTimelineDuration());
391                assertTrue("Export :Timeline Duration Mismatch for file " +
392                    fileName + "<expected> " + (startTime + endTime) +
393                    "\t<actual> " + mvi.getTimelineDuration(),
394                    checkRange((startTime + endTime), mvi.getTimelineDuration(), 10));
395            }
396        } else {
397            Log.i(TAG, "TimeLine Expected = " + (endTime-startTime) +
398                "\t VideoTime= " + mvi.getTimelineDuration());
399            assertTrue("Timeline Duration Mismatch for file " + fileName +
400                "<expected> " + (endTime - startTime) + "\t<actual> " +
401                mvi.getTimelineDuration(), checkRange((endTime -
402                    startTime), mvi.getTimelineDuration(), 10));
403        }
404    }
405
406    /**
407     * Check file and deletes it.
408     *
409     * @param filename
410     */
411    public void checkDeleteExistingFile(String filename) {
412        Log.i(TAG, ">>>>>>>>>>>>>>>>>>checkDeleteExistingFile  = " + filename);
413        if (filename != null) {
414            File temp = new File(filename);
415            if (temp != null && temp.exists()) {
416                temp.delete();
417            }
418        }
419    }
420
421    /**
422     * This method creates a Directory and filename
423     *
424     * @param location This is path where the file is to be created
425     *            "/sdcard/Output/"
426     * @return Path in form of /sdcard/Output/200910100000
427     */
428    public String createRandomFile(String location) {
429        Random randomGenerator = new Random();
430        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssS");
431        Date date = new Date();
432        final String filePath = location + dateFormat.format(date) +
433            randomGenerator.nextInt(10);
434        Log.i(TAG, ">>>>>>>>>>>>>>>>createRandomFile  Location= " + location +
435            "\t FilePath = " + filePath);
436        return filePath;
437    }
438
439    /**
440     * This method recursively deletes all the file and directory
441     *
442     * @param directory where the files are located Example = "/sdcard/Input"
443     * @return boolean True if deletion is successful else False
444     */
445    public boolean deleteProject(File directory) {
446        Log.i(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>deleteProject  directory= " +
447            directory.toString());
448        if (directory.isDirectory()) {
449            String[] filesInDirecory = directory.list();
450            for (int i = 0; i < filesInDirecory.length; i++) {
451                boolean success = deleteProject(new File(directory,
452                    filesInDirecory[i]));
453                if (!success) {
454                    return false;
455                }
456            }
457        }
458        return directory.delete();
459    }
460
461    /**
462     * This method compares the array of Integer from 0 - 100
463     *
464     * @param data set of integer values received as progress
465     * @return true if sucess else false
466     */
467    public boolean checkProgressCBValues(int[] data) {
468        boolean retFlag = false;
469        for (int i = 0; i < 100; i++) {
470            if (data[i] == 100) {
471                retFlag = true;
472                break;
473            } else {
474                retFlag = false;
475            }
476        }
477        return retFlag;
478    }
479}
480