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