Home | History | Annotate | Download | only in mediaeditor
      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 #define LOG_TAG "VideoEditorPropertiesMain"
     18 
     19 #include <dlfcn.h>
     20 #include <stdio.h>
     21 #include <unistd.h>
     22 #include <utils/Log.h>
     23 #include <utils/threads.h>
     24 #include <VideoEditorClasses.h>
     25 #include <VideoEditorJava.h>
     26 #include <VideoEditorOsal.h>
     27 #include <VideoEditorLogging.h>
     28 #include <VideoEditorOsal.h>
     29 #include <marker.h>
     30 
     31 extern "C" {
     32 #include <M4OSA_Clock.h>
     33 #include <M4OSA_CharStar.h>
     34 #include <M4OSA_Error.h>
     35 #include <M4OSA_FileCommon.h>
     36 #include <M4OSA_FileReader.h>
     37 #include <M4OSA_FileWriter.h>
     38 #include <M4OSA_Memory.h>
     39 #include <M4OSA_Thread.h>
     40 #include <M4VSS3GPP_API.h>
     41 #include <M4VSS3GPP_ErrorCodes.h>
     42 #include <M4MCS_API.h>
     43 #include <M4MCS_ErrorCodes.h>
     44 #include <M4READER_Common.h>
     45 #include <M4WRITER_common.h>
     46 #include <M4DECODER_Common.h>
     47 #include <M4AD_Common.h>
     48 };
     49 
     50 extern "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 
     57 jobject videoEditProp_getProperties(
     58                 JNIEnv*                             pEnv,
     59                 jobject                             thiz,
     60                 jstring                             file);
     61 
     62 static void
     63 getFileAndMediaTypeFromExtension (
     64                 M4OSA_Char* pExtension,
     65                 VideoEditClasses_FileType   *pFileType,
     66                 M4VIDEOEDITING_FileType       *pClipType);
     67 
     68 static M4OSA_ERR
     69 getClipProperties(  JNIEnv*                         pEnv,
     70                     jobject                         thiz,
     71                     M4OSA_Char*                     pFile,
     72                     M4VIDEOEDITING_FileType         clipType,
     73                     M4VIDEOEDITING_ClipProperties*  pClipProperties);
     74 
     75 M4OSA_UInt32
     76 VideoEdit_chrCompare(M4OSA_Char* pStrIn1,
     77                      M4OSA_Char* pStrIn2,
     78                      M4OSA_Int32* pCmpResult);
     79 
     80 jobject 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 #ifdef USE_SOFTWARE_DECODER
    220                 /**
    221                  * Input clip with non-multiples of 16 is not supported.
    222                  */
    223                 if ( (pClipProperties->uiVideoWidth %16)
    224                     || (pClipProperties->uiVideoHeight %16) )
    225                 {
    226                     result = M4MCS_ERR_INPUT_VIDEO_SIZE_NON_X16;
    227                     videoEditJava_checkAndThrowIllegalArgumentException(
    228                             &gotten, pEnv, (M4NO_ERROR != result),
    229                             "non x16 input video frame size is not supported");
    230                 }
    231 #endif /* USE_SOFTWARE_DECODER */
    232             }
    233 
    234             // Check if the properties could be retrieved.
    235             if (gotten)
    236             {
    237                 // Set the properties.
    238                 pProperties->uiClipDuration = pClipProperties->uiClipDuration;
    239                 if (M4VIDEOEDITING_kFileType_Unsupported == pClipProperties->FileType)
    240                 {
    241                     pProperties->FileType        = VideoEditClasses_kFileType_Unsupported;
    242                 }
    243                 else
    244                 {
    245                     pProperties->FileType        = fileType;
    246                 }
    247                 pProperties->VideoStreamType     = pClipProperties->VideoStreamType;
    248                 pProperties->uiClipVideoDuration = pClipProperties->uiClipVideoDuration;
    249                 pProperties->uiVideoBitrate      = pClipProperties->uiVideoBitrate;
    250                 pProperties->uiVideoWidth        = pClipProperties->uiVideoWidth;
    251                 pProperties->uiVideoHeight       = pClipProperties->uiVideoHeight;
    252                 pProperties->fAverageFrameRate   = pClipProperties->fAverageFrameRate;
    253                 pProperties->uiVideoProfile      = pClipProperties->uiVideoProfile;
    254                 pProperties->uiVideoLevel        = pClipProperties->uiVideoLevel;
    255                 // Set profile and level support to TRUE, pending check
    256                 pProperties->bProfileSupported   = M4OSA_TRUE;
    257                 pProperties->bLevelSupported     = M4OSA_TRUE;
    258                 pProperties->AudioStreamType     = pClipProperties->AudioStreamType;
    259                 pProperties->uiClipAudioDuration = pClipProperties->uiClipAudioDuration;
    260                 pProperties->uiAudioBitrate      = pClipProperties->uiAudioBitrate;
    261                 pProperties->uiNbChannels        = pClipProperties->uiNbChannels;
    262                 pProperties->uiSamplingFrequency = pClipProperties->uiSamplingFrequency;
    263                 pProperties->uiRotation          = pClipProperties->videoRotationDegrees;
    264 
    265             }
    266 
    267             // Free the clip properties.
    268             videoEditOsal_free(pClipProperties);
    269             pClipProperties = M4OSA_NULL;
    270         }
    271         else if ((VideoEditClasses_kFileType_JPG == fileType) ||
    272             (VideoEditClasses_kFileType_GIF == fileType) ||
    273             (VideoEditClasses_kFileType_PNG == fileType))
    274         {
    275             pProperties->uiClipDuration      = 0;
    276             pProperties->FileType            = fileType;
    277             pProperties->VideoStreamType     = M4VIDEOEDITING_kNoneVideo;
    278             pProperties->uiClipVideoDuration = 0;
    279             pProperties->uiVideoBitrate      = 0;
    280             pProperties->uiVideoWidth        = width;
    281             pProperties->uiVideoHeight       = height;
    282             pProperties->fAverageFrameRate   = 0.0f;
    283             pProperties->uiVideoProfile = M4VIDEOEDITING_VIDEO_UNKNOWN_PROFILE;
    284             pProperties->uiVideoLevel = M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL;
    285             pProperties->AudioStreamType     = M4VIDEOEDITING_kNoneAudio;
    286             pProperties->uiClipAudioDuration = 0;
    287             pProperties->uiAudioBitrate      = 0;
    288             pProperties->uiNbChannels        = 0;
    289             pProperties->uiSamplingFrequency = 0;
    290 
    291             // Added for Handling invalid paths and non existent image files
    292             // Open the file for reading.
    293             result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead);
    294             if (M4NO_ERROR != result)
    295             {
    296                 pProperties->FileType = VideoEditClasses_kFileType_Unsupported;
    297             }
    298             result = M4OSA_fileReadClose(context);
    299             context = M4OSA_NULL;
    300         }
    301     }
    302 
    303     if (M4NO_ERROR == result) {
    304         // Create a properties object.
    305         videoEditPropClass_createProperties(&gotten, pEnv, pProperties, &properties);
    306 
    307         // Log the properties.
    308         VIDEOEDIT_PROP_LOG_PROPERTIES(pProperties);
    309     }
    310 
    311     // Free the properties.
    312     videoEditOsal_free(pProperties);
    313     pProperties = M4OSA_NULL;
    314 
    315     // Free the file path.
    316     videoEditOsal_free(pFile);
    317     pFile = M4OSA_NULL;
    318 
    319     // Add a text marker (the condition must always be true).
    320     ADD_TEXT_MARKER_FUN(NULL != pEnv)
    321 
    322     // Return the Properties object.
    323     return(properties);
    324 }
    325 
    326 static void getFileAndMediaTypeFromExtension (
    327         M4OSA_Char *pExtension,
    328         VideoEditClasses_FileType *pFileType,
    329         M4VIDEOEDITING_FileType *pClipType)
    330 {
    331     M4OSA_Char extension[5] = {0, 0, 0, 0, 0};
    332     VideoEditClasses_FileType fileType =
    333             VideoEditClasses_kFileType_Unsupported;
    334 
    335     M4VIDEOEDITING_FileType clipType =
    336             M4VIDEOEDITING_kFileType_Unsupported;
    337 
    338     M4OSA_UInt32 index = 0;
    339     M4OSA_ERR result = M4NO_ERROR;
    340     M4OSA_Int32 cmpResult = 0;
    341     M4OSA_UInt32  extLength = strlen((const char *)pExtension);
    342 
    343     // Assign default
    344     *pFileType = VideoEditClasses_kFileType_Unsupported;
    345     *pClipType = M4VIDEOEDITING_kFileType_Unsupported;
    346 
    347     // Check if the length of the extension is valid.
    348     if ((3 == extLength) || (4 == extLength))
    349     {
    350         // Convert the extension to lowercase.
    351         for (index = 0; index < extLength ; index++)
    352         {
    353             extension[index] = tolower((int)pExtension[index]);
    354         }
    355 
    356         // Check if the extension is ".mp3".
    357         if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp3", &cmpResult)))
    358         {
    359             *pFileType = VideoEditClasses_kFileType_MP3;
    360             *pClipType = M4VIDEOEDITING_kFileType_MP3;
    361         }
    362         // Check if the extension is ".mp4".
    363         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp4", &cmpResult)))
    364         {
    365             *pFileType = VideoEditClasses_kFileType_MP4;
    366             *pClipType = M4VIDEOEDITING_kFileType_MP4;
    367         }
    368         // Check if the extension is ".3gp".
    369         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gp", &cmpResult)))
    370         {
    371             *pFileType = VideoEditClasses_kFileType_3GPP;
    372             *pClipType = M4VIDEOEDITING_kFileType_3GPP;
    373         }
    374         // Check if the extension is ".m4a".
    375         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4a", &cmpResult)))
    376         {
    377             *pFileType = VideoEditClasses_kFileType_3GPP;
    378             *pClipType = M4VIDEOEDITING_kFileType_3GPP;
    379         }
    380         // Check if the extension is ".3gpp".
    381         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gpp", &cmpResult)))
    382         {
    383             *pFileType = VideoEditClasses_kFileType_3GPP;
    384             *pClipType = M4VIDEOEDITING_kFileType_3GPP;
    385         }
    386         // Check if the extension is ".amr".
    387         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"amr", &cmpResult)))
    388         {
    389             *pFileType = VideoEditClasses_kFileType_AMR;
    390             *pClipType = M4VIDEOEDITING_kFileType_AMR;
    391         }
    392         // Check if the extension is ".pcm".
    393         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"pcm", &cmpResult)))
    394         {
    395             *pFileType = VideoEditClasses_kFileType_PCM;
    396             *pClipType = M4VIDEOEDITING_kFileType_PCM;
    397         }
    398         // Check if the extension is ".jpg".
    399         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpg", &cmpResult)))
    400         {
    401             *pFileType = VideoEditClasses_kFileType_JPG;
    402         }
    403         // Check if the extension is ".jpeg".
    404         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpeg", &cmpResult)))
    405         {
    406             *pFileType = VideoEditClasses_kFileType_JPG;
    407         }
    408         // Check if the extension is ".gif".
    409         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"gif", &cmpResult)))
    410         {
    411             *pFileType = VideoEditClasses_kFileType_GIF;
    412         }
    413         // Check if the extension is ".png".
    414         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"png", &cmpResult)))
    415         {
    416             *pFileType = VideoEditClasses_kFileType_PNG;
    417         }
    418         // Check if the extension is ".m4v".
    419         else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4v", &cmpResult)))
    420         {
    421             *pFileType = VideoEditClasses_kFileType_M4V;
    422             *pClipType = M4VIDEOEDITING_kFileType_M4V;
    423         }
    424     }
    425 }
    426 
    427 static M4OSA_ERR getClipProperties(
    428         JNIEnv* pEnv,
    429         jobject thiz,
    430         M4OSA_Char* pFile,
    431         M4VIDEOEDITING_FileType clipType,
    432         M4VIDEOEDITING_ClipProperties* pClipProperties)
    433 {
    434     bool                      gotten          = true;
    435     M4OSA_ERR                 result          = M4NO_ERROR;
    436     M4OSA_ERR                 resultAbort     = M4NO_ERROR;
    437     M4MCS_Context             context         = M4OSA_NULL;
    438 
    439     M4OSA_FileReadPointer fileReadPtr =
    440             { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL,
    441               M4OSA_NULL, M4OSA_NULL, M4OSA_NULL };
    442 
    443     M4OSA_FileWriterPointer fileWritePtr =
    444             { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL,
    445               M4OSA_NULL, M4OSA_NULL, M4OSA_NULL, M4OSA_NULL };
    446 
    447     // Initialize the OSAL file system function pointers.
    448     videoEditOsal_getFilePointers(&fileReadPtr , &fileWritePtr);
    449 
    450     // Log the API call.
    451     VIDEOEDIT_LOG_API(
    452             ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",\
    453             "getClipProperties - M4MCS_init()");
    454 
    455     // Initialize the MCS context.
    456     result = M4MCS_init(&context, &fileReadPtr, &fileWritePtr);
    457 
    458     // Log the result.
    459     VIDEOEDIT_PROP_LOG_RESULT(
    460             ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
    461             videoEditOsal_getResultString(result));
    462 
    463     // Check if the creation succeeded.
    464     videoEditJava_checkAndThrowRuntimeException(
    465             &gotten, pEnv, (M4NO_ERROR != result), result);
    466 
    467     // Check if opening the MCS context succeeded.
    468     if (gotten)
    469     {
    470         // Log the API call.
    471         VIDEOEDIT_LOG_API(
    472                 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
    473                 "getClipProperties - M4MCS_open_normalMode()");
    474 
    475         // Open the MCS in the normal opening mode to
    476         // retrieve the exact duration
    477         result = M4MCS_open_normalMode(
    478                 context, pFile, clipType, M4OSA_NULL, M4OSA_NULL);
    479 
    480         // Log the result.
    481         VIDEOEDIT_PROP_LOG_RESULT(
    482                 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
    483                 videoEditOsal_getResultString(result));
    484 
    485         // Check if the creation succeeded.
    486         videoEditJava_checkAndThrowRuntimeException(
    487                 &gotten, pEnv, (M4NO_ERROR != result), result);
    488 
    489         // Check if the MCS could be opened.
    490         if (gotten)
    491         {
    492             // Log the API call.
    493             VIDEOEDIT_LOG_API(
    494                     ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
    495                     "getClipProperties - M4MCS_getInputFileProperties()");
    496 
    497             // Get the properties.
    498             result = M4MCS_getInputFileProperties(context, pClipProperties);
    499 
    500             // Log the result.
    501             VIDEOEDIT_PROP_LOG_RESULT(
    502                     ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
    503                     videoEditOsal_getResultString(result));
    504 
    505             // Check if the creation succeeded.
    506             videoEditJava_checkAndThrowRuntimeException(
    507                     &gotten, pEnv, (M4NO_ERROR != result), result);
    508         }
    509 
    510         // Log the API call.
    511         VIDEOEDIT_LOG_API(
    512                 ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
    513                 "getClipProperties - M4MCS_abort()");
    514 
    515         // Close the MCS session.
    516         resultAbort = M4MCS_abort(context);
    517 
    518        if (result == M4NO_ERROR) {
    519             // Log the result.
    520             VIDEOEDIT_PROP_LOG_RESULT(
    521                     ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
    522                     videoEditOsal_getResultString(resultAbort));
    523 
    524             // Check if the abort succeeded.
    525             videoEditJava_checkAndThrowRuntimeException(
    526                     &gotten, pEnv, (M4NO_ERROR != resultAbort), resultAbort);
    527             result = resultAbort;
    528         }
    529     }
    530 
    531     return result;
    532 }
    533 
    534 M4OSA_UInt32
    535 VideoEdit_chrCompare(M4OSA_Char* pStrIn1,
    536                      M4OSA_Char* pStrIn2,
    537                       M4OSA_Int32* pCmpResult)
    538 {
    539     *pCmpResult = strcmp((const char *)pStrIn1, (const char *)pStrIn2);
    540     return *pCmpResult;
    541 }
    542 
    543 
    544