VideoEditorPropertiesMain.cpp revision 69e868dcabeb14c27251334fc33a5cad0982d379
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 videoEditJava_checkAndThrowIllegalArgumentException(&gotten, pEnv, 126 (M4NO_ERROR != result), "file not found"); 127 if(M4NO_ERROR != result) 128 return(properties); 129 result = M4OSA_fileReadClose(context); 130 context = M4OSA_NULL; 131 132 // Check if the file path is valid. 133 if (gotten) 134 { 135 // Retrieve the extension. 136 result = M4OSA_chrReverseFindChar(pFile, '.', &pExtension); 137 if ((M4NO_ERROR == result) && (M4OSA_NULL != pExtension)) 138 { 139 // Skip the dot. 140 pExtension++; 141 142 // Get the file type and Media type from extension 143 getFileAndMediaTypeFromExtension( 144 pExtension ,&fileType, &clipType); 145 } 146 } 147 148 // Check if the file type could be determined. 149 videoEditJava_checkAndThrowIllegalArgumentException( 150 &gotten, pEnv, 151 (VideoEditClasses_kFileType_Unsupported == fileType), 152 "file type is not supported"); 153 154 // Allocate a new properties structure. 155 pProperties = (VideoEditPropClass_Properties*)videoEditOsal_alloc( 156 &gotten, pEnv, 157 sizeof(VideoEditPropClass_Properties), "Properties"); 158 159 // Check if the context is valid and allocation succeeded 160 // (required because of dereferencing of pProperties). 161 if (gotten) 162 { 163 // Check if this type of file needs to be analyzed using MCS. 164 if ((VideoEditClasses_kFileType_MP3 == fileType) || 165 (VideoEditClasses_kFileType_MP4 == fileType) || 166 (VideoEditClasses_kFileType_3GPP == fileType) || 167 (VideoEditClasses_kFileType_AMR == fileType) || 168 (VideoEditClasses_kFileType_PCM == fileType) || 169 (VideoEditClasses_kFileType_M4V == fileType)) 170 { 171 // Allocate a new clip properties structure. 172 pClipProperties = 173 (M4VIDEOEDITING_ClipProperties*)videoEditOsal_alloc( 174 &gotten, pEnv, 175 sizeof(M4VIDEOEDITING_ClipProperties), "ClipProperties"); 176 177 // Check if allocation succeeded (required because of 178 // dereferencing of pClipProperties). 179 if (gotten) 180 { 181 // Add a code marker (the condition must always be true). 182 ADD_CODE_MARKER_FUN(NULL != pClipProperties) 183 184 // Log the API call. 185 VIDEOEDIT_LOG_API( 186 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", 187 "getClipProperties"); 188 189 // Get Video clip properties 190 result = getClipProperties( 191 pEnv, thiz, pFile, clipType, pClipProperties); 192 193 // Check if the creation succeeded. 194 videoEditJava_checkAndThrowIllegalArgumentException( 195 &gotten, pEnv,(M4NO_ERROR != result), 196 "Invalid File or File not found"); 197 198 /** 199 * Max resolution supported is 1280 x 720. 200 */ 201 if ( (pClipProperties->uiVideoWidth > 1280) 202 || (pClipProperties->uiVideoHeight > 720) ) 203 { 204 result = M4MCS_ERR_INVALID_INPUT_VIDEO_FRAME_SIZE; 205 videoEditJava_checkAndThrowIllegalArgumentException( 206 &gotten, pEnv, (M4NO_ERROR != result), 207 "Unsupported input video frame size"); 208 } 209 210#ifdef USE_SOFTWARE_DECODER 211 /** 212 * Input clip with non-multiples of 16 is not supported. 213 */ 214 if ( (pClipProperties->uiVideoWidth %16) 215 || (pClipProperties->uiVideoHeight %16) ) 216 { 217 result = M4MCS_ERR_INPUT_VIDEO_SIZE_NON_X16; 218 videoEditJava_checkAndThrowIllegalArgumentException( 219 &gotten, pEnv, (M4NO_ERROR != result), 220 "non x16 input video frame size is not supported"); 221 } 222#endif /* USE_SOFTWARE_DECODER */ 223 } 224 225 // Check if the properties could be retrieved. 226 if (gotten) 227 { 228 // Set the properties. 229 pProperties->uiClipDuration = pClipProperties->uiClipDuration; 230 if (M4VIDEOEDITING_kFileType_Unsupported == pClipProperties->FileType) 231 { 232 pProperties->FileType = VideoEditClasses_kFileType_Unsupported; 233 } 234 else 235 { 236 pProperties->FileType = fileType; 237 } 238 pProperties->VideoStreamType = pClipProperties->VideoStreamType; 239 pProperties->uiClipVideoDuration = pClipProperties->uiClipVideoDuration; 240 pProperties->uiVideoBitrate = pClipProperties->uiVideoBitrate; 241 pProperties->uiVideoWidth = pClipProperties->uiVideoWidth; 242 pProperties->uiVideoHeight = pClipProperties->uiVideoHeight; 243 pProperties->fAverageFrameRate = pClipProperties->fAverageFrameRate; 244 pProperties->ProfileAndLevel = pClipProperties->ProfileAndLevel; 245 pProperties->AudioStreamType = pClipProperties->AudioStreamType; 246 pProperties->uiClipAudioDuration = pClipProperties->uiClipAudioDuration; 247 pProperties->uiAudioBitrate = pClipProperties->uiAudioBitrate; 248 pProperties->uiNbChannels = pClipProperties->uiNbChannels; 249 pProperties->uiSamplingFrequency = pClipProperties->uiSamplingFrequency; 250 } 251 252 // Free the clip properties. 253 videoEditOsal_free(pClipProperties); 254 pClipProperties = M4OSA_NULL; 255 } 256 else if ((VideoEditClasses_kFileType_JPG == fileType) || 257 (VideoEditClasses_kFileType_GIF == fileType) || 258 (VideoEditClasses_kFileType_PNG == fileType)) 259 { 260 pProperties->uiClipDuration = 0; 261 pProperties->FileType = fileType; 262 pProperties->VideoStreamType = M4VIDEOEDITING_kNoneVideo; 263 pProperties->uiClipVideoDuration = 0; 264 pProperties->uiVideoBitrate = 0; 265 pProperties->uiVideoWidth = width; 266 pProperties->uiVideoHeight = height; 267 pProperties->fAverageFrameRate = 0.0f; 268 pProperties->ProfileAndLevel = M4VIDEOEDITING_kProfile_and_Level_Out_Of_Range; 269 pProperties->AudioStreamType = M4VIDEOEDITING_kNoneAudio; 270 pProperties->uiClipAudioDuration = 0; 271 pProperties->uiAudioBitrate = 0; 272 pProperties->uiNbChannels = 0; 273 pProperties->uiSamplingFrequency = 0; 274 275 // Added for Handling invalid paths and non existent image files 276 // Open the file for reading. 277 result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead); 278 if (M4NO_ERROR != result) 279 { 280 pProperties->FileType = VideoEditClasses_kFileType_Unsupported; 281 } 282 result = M4OSA_fileReadClose(context); 283 context = M4OSA_NULL; 284 } 285 } 286 287 // Create a properties object. 288 videoEditPropClass_createProperties(&gotten, pEnv, pProperties, &properties); 289 290 // Log the properties. 291 VIDEOEDIT_PROP_LOG_PROPERTIES(pProperties); 292 293 // Free the properties. 294 videoEditOsal_free(pProperties); 295 pProperties = M4OSA_NULL; 296 297 // Free the file path. 298 videoEditOsal_free(pFile); 299 pFile = M4OSA_NULL; 300 301 // Add a text marker (the condition must always be true). 302 ADD_TEXT_MARKER_FUN(NULL != pEnv) 303 304 // Return the Properties object. 305 return(properties); 306} 307 308static void getFileAndMediaTypeFromExtension ( 309 M4OSA_Char *pExtension, 310 VideoEditClasses_FileType *pFileType, 311 M4VIDEOEDITING_FileType *pClipType) 312{ 313 M4OSA_Char extension[5] = {0, 0, 0, 0, 0}; 314 VideoEditClasses_FileType fileType = 315 VideoEditClasses_kFileType_Unsupported; 316 317 M4VIDEOEDITING_FileType clipType = 318 M4VIDEOEDITING_kFileType_Unsupported; 319 320 M4OSA_UInt32 index = 0; 321 M4OSA_ERR result = M4NO_ERROR; 322 M4OSA_Int32 cmpResult = 0; 323 M4OSA_UInt32 extLength = M4OSA_chrLength(pExtension); 324 325 // Assign default 326 *pFileType = VideoEditClasses_kFileType_Unsupported; 327 *pClipType = M4VIDEOEDITING_kFileType_Unsupported; 328 329 // Check if the length of the extension is valid. 330 if ((3 == extLength) || (4 == extLength)) 331 { 332 // Convert the extension to lowercase. 333 for (index = 0; index < extLength ; index++) 334 { 335 extension[index] = M4OSA_chrToLower(pExtension[index]); 336 } 337 338 // Check if the extension is ".mp3". 339 if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp3", &cmpResult))) 340 { 341 *pFileType = VideoEditClasses_kFileType_MP3; 342 *pClipType = M4VIDEOEDITING_kFileType_MP3; 343 } 344 // Check if the extension is ".mp4". 345 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp4", &cmpResult))) 346 { 347 *pFileType = VideoEditClasses_kFileType_MP4; 348 *pClipType = M4VIDEOEDITING_kFileType_MP4; 349 } 350 // Check if the extension is ".3gp". 351 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gp", &cmpResult))) 352 { 353 *pFileType = VideoEditClasses_kFileType_3GPP; 354 *pClipType = M4VIDEOEDITING_kFileType_3GPP; 355 } 356 // Check if the extension is ".m4a". 357 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4a", &cmpResult))) 358 { 359 *pFileType = VideoEditClasses_kFileType_3GPP; 360 *pClipType = M4VIDEOEDITING_kFileType_3GPP; 361 } 362 // Check if the extension is ".3gpp". 363 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gpp", &cmpResult))) 364 { 365 *pFileType = VideoEditClasses_kFileType_3GPP; 366 *pClipType = M4VIDEOEDITING_kFileType_3GPP; 367 } 368 // Check if the extension is ".amr". 369 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"amr", &cmpResult))) 370 { 371 *pFileType = VideoEditClasses_kFileType_AMR; 372 *pClipType = M4VIDEOEDITING_kFileType_AMR; 373 } 374 // Check if the extension is ".pcm". 375 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"pcm", &cmpResult))) 376 { 377 *pFileType = VideoEditClasses_kFileType_PCM; 378 *pClipType = M4VIDEOEDITING_kFileType_PCM; 379 } 380 // Check if the extension is ".jpg". 381 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpg", &cmpResult))) 382 { 383 *pFileType = VideoEditClasses_kFileType_JPG; 384 } 385 // Check if the extension is ".jpeg". 386 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpeg", &cmpResult))) 387 { 388 *pFileType = VideoEditClasses_kFileType_JPG; 389 } 390 // Check if the extension is ".gif". 391 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"gif", &cmpResult))) 392 { 393 *pFileType = VideoEditClasses_kFileType_GIF; 394 } 395 // Check if the extension is ".png". 396 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"png", &cmpResult))) 397 { 398 *pFileType = VideoEditClasses_kFileType_PNG; 399 } 400 // Check if the extension is ".m4v". 401 else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4v", &cmpResult))) 402 { 403 *pFileType = VideoEditClasses_kFileType_M4V; 404 *pClipType = M4VIDEOEDITING_kFileType_M4V; 405 } 406 } 407} 408 409static M4OSA_ERR getClipProperties( 410 JNIEnv* pEnv, 411 jobject thiz, 412 M4OSA_Char* pFile, 413 M4VIDEOEDITING_FileType clipType, 414 M4VIDEOEDITING_ClipProperties* pClipProperties) 415{ 416 bool gotten = true; 417 M4OSA_ERR result = M4NO_ERROR; 418 M4OSA_ERR resultAbort = M4NO_ERROR; 419 M4MCS_Context context = M4OSA_NULL; 420 421 M4OSA_FileReadPointer fileReadPtr = 422 { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL, 423 M4OSA_NULL, M4OSA_NULL, M4OSA_NULL }; 424 425 M4OSA_FileWriterPointer fileWritePtr = 426 { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL, 427 M4OSA_NULL, M4OSA_NULL, M4OSA_NULL, M4OSA_NULL }; 428 429 // Initialize the OSAL file system function pointers. 430 videoEditOsal_getFilePointers(&fileReadPtr , &fileWritePtr); 431 432 // Log the API call. 433 VIDEOEDIT_LOG_API( 434 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",\ 435 "getClipProperties - M4MCS_init()"); 436 437 // Initialize the MCS context. 438 result = M4MCS_init(&context, &fileReadPtr, &fileWritePtr); 439 440 // Log the result. 441 VIDEOEDIT_PROP_LOG_RESULT( 442 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s", 443 videoEditOsal_getResultString(result)); 444 445 // Check if the creation succeeded. 446 videoEditJava_checkAndThrowRuntimeException( 447 &gotten, pEnv, (M4NO_ERROR != result), result); 448 449 // Check if opening the MCS context succeeded. 450 if (gotten) 451 { 452 // Log the API call. 453 VIDEOEDIT_LOG_API( 454 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", 455 "getClipProperties - M4MCS_open_normalMode()"); 456 457 // Open the MCS in the normal opening mode to 458 // retrieve the exact duration 459 result = M4MCS_open_normalMode( 460 context, pFile, clipType, M4OSA_NULL, M4OSA_NULL); 461 462 // Log the result. 463 VIDEOEDIT_PROP_LOG_RESULT( 464 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s", 465 videoEditOsal_getResultString(result)); 466 467 // Check if the creation succeeded. 468 videoEditJava_checkAndThrowRuntimeException( 469 &gotten, pEnv, (M4NO_ERROR != result), result); 470 471 // Check if the MCS could be opened. 472 if (gotten) 473 { 474 // Log the API call. 475 VIDEOEDIT_LOG_API( 476 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", 477 "getClipProperties - M4MCS_getInputFileProperties()"); 478 479 // Get the properties. 480 result = M4MCS_getInputFileProperties(context, pClipProperties); 481 482 // Log the result. 483 VIDEOEDIT_PROP_LOG_RESULT( 484 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s", 485 videoEditOsal_getResultString(result)); 486 487 // Check if the creation succeeded. 488 videoEditJava_checkAndThrowRuntimeException( 489 &gotten, pEnv, (M4NO_ERROR != result), result); 490 } 491 492 // Log the API call. 493 VIDEOEDIT_LOG_API( 494 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", 495 "getClipProperties - M4MCS_abort()"); 496 497 // Close the MCS session. 498 resultAbort = M4MCS_abort(context); 499 500 if (result == M4NO_ERROR) { 501 // Log the result. 502 VIDEOEDIT_PROP_LOG_RESULT( 503 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s", 504 videoEditOsal_getResultString(resultAbort)); 505 506 // Check if the abort succeeded. 507 videoEditJava_checkAndThrowRuntimeException( 508 &gotten, pEnv, (M4NO_ERROR != resultAbort), resultAbort); 509 result = resultAbort; 510 } 511 } 512 513 return result; 514} 515 516M4OSA_UInt32 517VideoEdit_chrCompare(M4OSA_Char* pStrIn1, 518 M4OSA_Char* pStrIn2, 519 M4OSA_Int32* pCmpResult) 520{ 521 M4OSA_chrCompare(pStrIn1, pStrIn2, pCmpResult); 522 return *pCmpResult; 523} 524 525 526