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 #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 
     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 
    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 
    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
    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