VideoEditorPropertiesMain.cpp revision 7743fa64b11e9747d3ba8065a08a33ee9d90938f
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <dlfcn.h>
18#include <stdio.h>
19#include <unistd.h>
20#include <utils/Log.h>
21#include <utils/threads.h>
22#include <VideoEditorClasses.h>
23#include <VideoEditorJava.h>
24#include <VideoEditorOsal.h>
25#include <VideoEditorLogging.h>
26#include <VideoEditorOsal.h>
27#include <marker.h>
28
29extern "C" {
30#include <M4OSA_Clock.h>
31#include <M4OSA_CharStar.h>
32#include <M4OSA_Error.h>
33#include <M4OSA_FileCommon.h>
34#include <M4OSA_FileReader.h>
35#include <M4OSA_FileWriter.h>
36#include <M4OSA_Memory.h>
37#include <M4OSA_String.h>
38#include <M4OSA_Thread.h>
39#include <M4VSS3GPP_API.h>
40#include <M4VSS3GPP_ErrorCodes.h>
41#include <M4MCS_API.h>
42#include <M4MCS_ErrorCodes.h>
43#include <M4MDP_API.h>
44#include <M4READER_Common.h>
45#include <M4WRITER_common.h>
46#include <M4DECODER_Common.h>
47#include <M4AD_Common.h>
48};
49
50extern "C" M4OSA_ERR M4MCS_open_normalMode(
51                M4MCS_Context                       pContext,
52                M4OSA_Void*                         pFileIn,
53                M4VIDEOEDITING_FileType             InputFileType,
54                M4OSA_Void*                         pFileOut,
55                M4OSA_Void*                         pTempFile);
56
57jobject videoEditProp_getProperties(
58                JNIEnv*                             pEnv,
59                jobject                             thiz,
60                jstring                             file);
61
62static void
63getFileAndMediaTypeFromExtension (
64                M4OSA_Char* pExtension,
65                VideoEditClasses_FileType   *pFileType,
66                M4VIDEOEDITING_FileType       *pClipType);
67
68static M4OSA_ERR
69getClipProperties(  JNIEnv*                         pEnv,
70                    jobject                         thiz,
71                    M4OSA_Char*                     pFile,
72                    M4VIDEOEDITING_FileType         clipType,
73                    M4VIDEOEDITING_ClipProperties*  pClipProperties);
74
75M4OSA_UInt32
76VideoEdit_chrCompare(M4OSA_Char* pStrIn1,
77                     M4OSA_Char* pStrIn2,
78                     M4OSA_Int32* pCmpResult);
79
80jobject videoEditProp_getProperties(
81        JNIEnv* pEnv,
82        jobject thiz,
83        jstring file)
84{
85    bool                           gotten          = true;
86    M4OSA_Char*                    pFile           = M4OSA_NULL;
87    M4OSA_Char*                    pExtension      = M4OSA_NULL;
88    M4OSA_UInt32                   index           = 0;
89    M4OSA_Int32                    cmpResult       = 0;
90    VideoEditPropClass_Properties* pProperties     = M4OSA_NULL;
91    M4VIDEOEDITING_ClipProperties* pClipProperties = M4OSA_NULL;
92    M4OSA_ERR                      result          = M4NO_ERROR;
93    M4MCS_Context                  context         = M4OSA_NULL;
94    M4OSA_FilePosition             size            = 0;
95    M4OSA_UInt32                   width           = 0;
96    M4OSA_UInt32                   height          = 0;
97    jobject                        properties      = NULL;
98    M4OSA_Context                  pOMXContext     = M4OSA_NULL;
99    M4DECODER_VideoInterface*      pOMXVidDecoderInterface = M4OSA_NULL;
100    M4AD_Interface*                pOMXAudDecoderInterface = M4OSA_NULL;
101
102    bool  initialized = true;
103    VideoEditClasses_FileType fileType = VideoEditClasses_kFileType_Unsupported;
104    M4VIDEOEDITING_FileType clipType = M4VIDEOEDITING_kFileType_Unsupported;
105
106    VIDEOEDIT_LOG_API(
107            ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
108            "videoEditProp_getProperties()");
109
110    // Add a text marker (the condition must always be true).
111    ADD_TEXT_MARKER_FUN(NULL != pEnv)
112
113    // Initialize the classes.
114    videoEditPropClass_init(&initialized, (JNIEnv*)pEnv);
115
116    // Validate the tempPath parameter.
117    videoEditJava_checkAndThrowIllegalArgumentException(
118            &gotten, pEnv, (NULL == file), "file is null");
119
120    // Get the file path.
121    pFile = (M4OSA_Char *)videoEditJava_getString(
122            &gotten, pEnv, file, NULL, M4OSA_NULL);
123
124    result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead);
125
126    if(M4NO_ERROR != result) {
127        // Free the file path.
128        videoEditOsal_free(pFile);
129        pFile = M4OSA_NULL;
130    }
131
132    videoEditJava_checkAndThrowIllegalArgumentException(&gotten, pEnv,
133        (M4NO_ERROR != result), "file not found");
134
135    // Close the file and free the file context
136    if (context != NULL) {
137        result = M4OSA_fileReadClose(context);
138        context = M4OSA_NULL;
139    }
140
141    // Return if Error
142    if (M4NO_ERROR != result) {
143        return (properties); // NULL
144    }
145
146    // Check if the file path is valid.
147    if (gotten)
148    {
149        // Retrieve the extension.
150        pExtension = (M4OSA_Char *)strrchr((const char *)pFile, (int)'.');
151        if (M4OSA_NULL != pExtension)
152        {
153            // Skip the dot.
154            pExtension++;
155
156            // Get the file type and Media type from extension
157            getFileAndMediaTypeFromExtension(
158                    pExtension ,&fileType, &clipType);
159        }
160    }
161
162    // Check if the file type could be determined.
163    videoEditJava_checkAndThrowIllegalArgumentException(
164            &gotten, pEnv,
165            (VideoEditClasses_kFileType_Unsupported == fileType),
166            "file type is not supported");
167
168    // Allocate a new properties structure.
169    pProperties = (VideoEditPropClass_Properties*)videoEditOsal_alloc(
170            &gotten, pEnv,
171            sizeof(VideoEditPropClass_Properties), "Properties");
172
173    // Check if the context is valid and allocation succeeded
174    // (required because of dereferencing of pProperties).
175    if (gotten)
176    {
177        // Check if this type of file needs to be analyzed using MCS.
178        if ((VideoEditClasses_kFileType_MP3  == fileType) ||
179            (VideoEditClasses_kFileType_MP4  == fileType) ||
180            (VideoEditClasses_kFileType_3GPP == fileType) ||
181            (VideoEditClasses_kFileType_AMR  == fileType) ||
182            (VideoEditClasses_kFileType_PCM  == fileType) ||
183            (VideoEditClasses_kFileType_M4V  == fileType))
184        {
185            // Allocate a new clip properties structure.
186            pClipProperties =
187                (M4VIDEOEDITING_ClipProperties*)videoEditOsal_alloc(
188                    &gotten, pEnv,
189                    sizeof(M4VIDEOEDITING_ClipProperties), "ClipProperties");
190
191            // Check if allocation succeeded (required because of
192            // dereferencing of pClipProperties).
193            if (gotten)
194            {
195                // Add a code marker (the condition must always be true).
196                ADD_CODE_MARKER_FUN(NULL != pClipProperties)
197
198                // Log the API call.
199                VIDEOEDIT_LOG_API(
200                        ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
201                        "getClipProperties");
202
203                // Get Video clip properties
204                result = getClipProperties(
205                        pEnv, thiz, pFile, clipType, pClipProperties);
206
207                if (M4MCS_ERR_FILE_DRM_PROTECTED == result) {
208                    // Check if the creation succeeded.
209                    videoEditJava_checkAndThrowIllegalArgumentException(
210                            &gotten, pEnv,(M4NO_ERROR != result),
211                            "Invalid File - DRM Protected ");
212                } else {
213                    // Check if the creation succeeded.
214                    videoEditJava_checkAndThrowIllegalArgumentException(
215                            &gotten, pEnv,(M4NO_ERROR != result),
216                            "Invalid File or File not found ");
217                }
218
219                /**
220                 * Max resolution supported is 1280 x 720.
221                 */
222                if ( (pClipProperties->uiVideoWidth > 1280)
223                    || (pClipProperties->uiVideoHeight > 720) )
224                {
225                    result = M4MCS_ERR_INVALID_INPUT_VIDEO_FRAME_SIZE;
226                    videoEditJava_checkAndThrowIllegalArgumentException(
227                            &gotten, pEnv, (M4NO_ERROR != result),
228                            "Unsupported input video frame size");
229                }
230
231#ifdef USE_SOFTWARE_DECODER
232                /**
233                 * Input clip with non-multiples of 16 is not supported.
234                 */
235                if ( (pClipProperties->uiVideoWidth %16)
236                    || (pClipProperties->uiVideoHeight %16) )
237                {
238                    result = M4MCS_ERR_INPUT_VIDEO_SIZE_NON_X16;
239                    videoEditJava_checkAndThrowIllegalArgumentException(
240                            &gotten, pEnv, (M4NO_ERROR != result),
241                            "non x16 input video frame size is not supported");
242                }
243#endif /* USE_SOFTWARE_DECODER */
244            }
245
246            // Check if the properties could be retrieved.
247            if (gotten)
248            {
249                // Set the properties.
250                pProperties->uiClipDuration = pClipProperties->uiClipDuration;
251                if (M4VIDEOEDITING_kFileType_Unsupported == pClipProperties->FileType)
252                {
253                    pProperties->FileType        = VideoEditClasses_kFileType_Unsupported;
254                }
255                else
256                {
257                    pProperties->FileType        = fileType;
258                }
259                pProperties->VideoStreamType     = pClipProperties->VideoStreamType;
260                pProperties->uiClipVideoDuration = pClipProperties->uiClipVideoDuration;
261                pProperties->uiVideoBitrate      = pClipProperties->uiVideoBitrate;
262                pProperties->uiVideoWidth        = pClipProperties->uiVideoWidth;
263                pProperties->uiVideoHeight       = pClipProperties->uiVideoHeight;
264                pProperties->fAverageFrameRate   = pClipProperties->fAverageFrameRate;
265                pProperties->ProfileAndLevel     = pClipProperties->ProfileAndLevel;
266                pProperties->AudioStreamType     = pClipProperties->AudioStreamType;
267                pProperties->uiClipAudioDuration = pClipProperties->uiClipAudioDuration;
268                pProperties->uiAudioBitrate      = pClipProperties->uiAudioBitrate;
269                pProperties->uiNbChannels        = pClipProperties->uiNbChannels;
270                pProperties->uiSamplingFrequency = pClipProperties->uiSamplingFrequency;
271            }
272
273            // Free the clip properties.
274            videoEditOsal_free(pClipProperties);
275            pClipProperties = M4OSA_NULL;
276        }
277        else if ((VideoEditClasses_kFileType_JPG == fileType) ||
278            (VideoEditClasses_kFileType_GIF == fileType) ||
279            (VideoEditClasses_kFileType_PNG == fileType))
280        {
281            pProperties->uiClipDuration      = 0;
282            pProperties->FileType            = fileType;
283            pProperties->VideoStreamType     = M4VIDEOEDITING_kNoneVideo;
284            pProperties->uiClipVideoDuration = 0;
285            pProperties->uiVideoBitrate      = 0;
286            pProperties->uiVideoWidth        = width;
287            pProperties->uiVideoHeight       = height;
288            pProperties->fAverageFrameRate   = 0.0f;
289            pProperties->ProfileAndLevel     = M4VIDEOEDITING_kProfile_and_Level_Out_Of_Range;
290            pProperties->AudioStreamType     = M4VIDEOEDITING_kNoneAudio;
291            pProperties->uiClipAudioDuration = 0;
292            pProperties->uiAudioBitrate      = 0;
293            pProperties->uiNbChannels        = 0;
294            pProperties->uiSamplingFrequency = 0;
295
296            // Added for Handling invalid paths and non existent image files
297            // Open the file for reading.
298            result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead);
299            if (M4NO_ERROR != result)
300            {
301                pProperties->FileType = VideoEditClasses_kFileType_Unsupported;
302            }
303            result = M4OSA_fileReadClose(context);
304            context = M4OSA_NULL;
305        }
306    }
307
308    // Create a properties object.
309    videoEditPropClass_createProperties(&gotten, pEnv, pProperties, &properties);
310
311    // Log the properties.
312    VIDEOEDIT_PROP_LOG_PROPERTIES(pProperties);
313
314    // Free the properties.
315    videoEditOsal_free(pProperties);
316    pProperties = M4OSA_NULL;
317
318    // Free the file path.
319    videoEditOsal_free(pFile);
320    pFile = M4OSA_NULL;
321
322    // Add a text marker (the condition must always be true).
323    ADD_TEXT_MARKER_FUN(NULL != pEnv)
324
325    // Return the Properties object.
326    return(properties);
327}
328
329static void getFileAndMediaTypeFromExtension (
330        M4OSA_Char *pExtension,
331        VideoEditClasses_FileType *pFileType,
332        M4VIDEOEDITING_FileType *pClipType)
333{
334    M4OSA_Char extension[5] = {0, 0, 0, 0, 0};
335    VideoEditClasses_FileType fileType =
336            VideoEditClasses_kFileType_Unsupported;
337
338    M4VIDEOEDITING_FileType clipType =
339            M4VIDEOEDITING_kFileType_Unsupported;
340
341    M4OSA_UInt32 index = 0;
342    M4OSA_ERR result = M4NO_ERROR;
343    M4OSA_Int32 cmpResult = 0;
344    M4OSA_UInt32  extLength = strlen((const char *)pExtension);
345
346    // Assign default
347    *pFileType = VideoEditClasses_kFileType_Unsupported;
348    *pClipType = M4VIDEOEDITING_kFileType_Unsupported;
349
350    // Check if the length of the extension is valid.
351    if ((3 == extLength) || (4 == extLength))
352    {
353        // Convert the extension to lowercase.
354        for (index = 0; index < extLength ; index++)
355        {
356            extension[index] = tolower((int)pExtension[index]);
357        }
358
359        // Check if the extension is ".mp3".
360        if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp3", &cmpResult)))
361        {
362            *pFileType = VideoEditClasses_kFileType_MP3;
363            *pClipType = M4VIDEOEDITING_kFileType_MP3;
364        }
365        // Check if the extension is ".mp4".
366        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp4", &cmpResult)))
367        {
368            *pFileType = VideoEditClasses_kFileType_MP4;
369            *pClipType = M4VIDEOEDITING_kFileType_MP4;
370        }
371        // Check if the extension is ".3gp".
372        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gp", &cmpResult)))
373        {
374            *pFileType = VideoEditClasses_kFileType_3GPP;
375            *pClipType = M4VIDEOEDITING_kFileType_3GPP;
376        }
377        // Check if the extension is ".m4a".
378        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4a", &cmpResult)))
379        {
380            *pFileType = VideoEditClasses_kFileType_3GPP;
381            *pClipType = M4VIDEOEDITING_kFileType_3GPP;
382        }
383        // Check if the extension is ".3gpp".
384        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gpp", &cmpResult)))
385        {
386            *pFileType = VideoEditClasses_kFileType_3GPP;
387            *pClipType = M4VIDEOEDITING_kFileType_3GPP;
388        }
389        // Check if the extension is ".amr".
390        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"amr", &cmpResult)))
391        {
392            *pFileType = VideoEditClasses_kFileType_AMR;
393            *pClipType = M4VIDEOEDITING_kFileType_AMR;
394        }
395        // Check if the extension is ".pcm".
396        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"pcm", &cmpResult)))
397        {
398            *pFileType = VideoEditClasses_kFileType_PCM;
399            *pClipType = M4VIDEOEDITING_kFileType_PCM;
400        }
401        // Check if the extension is ".jpg".
402        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpg", &cmpResult)))
403        {
404            *pFileType = VideoEditClasses_kFileType_JPG;
405        }
406        // Check if the extension is ".jpeg".
407        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpeg", &cmpResult)))
408        {
409            *pFileType = VideoEditClasses_kFileType_JPG;
410        }
411        // Check if the extension is ".gif".
412        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"gif", &cmpResult)))
413        {
414            *pFileType = VideoEditClasses_kFileType_GIF;
415        }
416        // Check if the extension is ".png".
417        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"png", &cmpResult)))
418        {
419            *pFileType = VideoEditClasses_kFileType_PNG;
420        }
421        // Check if the extension is ".m4v".
422        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4v", &cmpResult)))
423        {
424            *pFileType = VideoEditClasses_kFileType_M4V;
425            *pClipType = M4VIDEOEDITING_kFileType_M4V;
426        }
427    }
428}
429
430static M4OSA_ERR getClipProperties(
431        JNIEnv* pEnv,
432        jobject thiz,
433        M4OSA_Char* pFile,
434        M4VIDEOEDITING_FileType clipType,
435        M4VIDEOEDITING_ClipProperties* pClipProperties)
436{
437    bool                      gotten          = true;
438    M4OSA_ERR                 result          = M4NO_ERROR;
439    M4OSA_ERR                 resultAbort     = M4NO_ERROR;
440    M4MCS_Context             context         = M4OSA_NULL;
441
442    M4OSA_FileReadPointer fileReadPtr =
443            { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL,
444              M4OSA_NULL, M4OSA_NULL, M4OSA_NULL };
445
446    M4OSA_FileWriterPointer fileWritePtr =
447            { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL,
448              M4OSA_NULL, M4OSA_NULL, M4OSA_NULL, M4OSA_NULL };
449
450    // Initialize the OSAL file system function pointers.
451    videoEditOsal_getFilePointers(&fileReadPtr , &fileWritePtr);
452
453    // Log the API call.
454    VIDEOEDIT_LOG_API(
455            ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",\
456            "getClipProperties - M4MCS_init()");
457
458    // Initialize the MCS context.
459    result = M4MCS_init(&context, &fileReadPtr, &fileWritePtr);
460
461    // Log the result.
462    VIDEOEDIT_PROP_LOG_RESULT(
463            ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
464            videoEditOsal_getResultString(result));
465
466    // Check if the creation succeeded.
467    videoEditJava_checkAndThrowRuntimeException(
468            &gotten, pEnv, (M4NO_ERROR != result), result);
469
470    // Check if opening the MCS context succeeded.
471    if (gotten)
472    {
473        // Log the API call.
474        VIDEOEDIT_LOG_API(
475                ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
476                "getClipProperties - M4MCS_open_normalMode()");
477
478        // Open the MCS in the normal opening mode to
479        // retrieve the exact duration
480        result = M4MCS_open_normalMode(
481                context, pFile, clipType, M4OSA_NULL, M4OSA_NULL);
482
483        // Log the result.
484        VIDEOEDIT_PROP_LOG_RESULT(
485                ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
486                videoEditOsal_getResultString(result));
487
488        // Check if the creation succeeded.
489        videoEditJava_checkAndThrowRuntimeException(
490                &gotten, pEnv, (M4NO_ERROR != result), result);
491
492        // Check if the MCS could be opened.
493        if (gotten)
494        {
495            // Log the API call.
496            VIDEOEDIT_LOG_API(
497                    ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
498                    "getClipProperties - M4MCS_getInputFileProperties()");
499
500            // Get the properties.
501            result = M4MCS_getInputFileProperties(context, pClipProperties);
502
503            // Log the result.
504            VIDEOEDIT_PROP_LOG_RESULT(
505                    ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
506                    videoEditOsal_getResultString(result));
507
508            // Check if the creation succeeded.
509            videoEditJava_checkAndThrowRuntimeException(
510                    &gotten, pEnv, (M4NO_ERROR != result), result);
511        }
512
513        // Log the API call.
514        VIDEOEDIT_LOG_API(
515                ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
516                "getClipProperties - M4MCS_abort()");
517
518        // Close the MCS session.
519        resultAbort = M4MCS_abort(context);
520
521       if (result == M4NO_ERROR) {
522            // Log the result.
523            VIDEOEDIT_PROP_LOG_RESULT(
524                    ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
525                    videoEditOsal_getResultString(resultAbort));
526
527            // Check if the abort succeeded.
528            videoEditJava_checkAndThrowRuntimeException(
529                    &gotten, pEnv, (M4NO_ERROR != resultAbort), resultAbort);
530            result = resultAbort;
531        }
532    }
533
534    return result;
535}
536
537M4OSA_UInt32
538VideoEdit_chrCompare(M4OSA_Char* pStrIn1,
539                     M4OSA_Char* pStrIn2,
540                      M4OSA_Int32* pCmpResult)
541{
542    *pCmpResult = strcmp((const char *)pStrIn1, (const char *)pStrIn2);
543    return *pCmpResult;
544}
545
546
547