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