void
videoEditJava_getArray(
                bool*                               pResult,
                JNIEnv*                             pEnv,
                jobject                             object,
                jfieldID                            arrayFieldId,
                jobjectArray*                       pArray,
                jsize*                              pArraySize)
{
    // Only retrieve the array object and size if the previous action succeeded.
    if (*pResult)
    {
        // Log the function call.
        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA", "videoEditJava_getArray()");

        // Retrieve the array object.
        jobjectArray array     = (jobjectArray)pEnv->GetObjectField(object, arrayFieldId);
        jsize        arraySize = 0;

        // Clear any resulting exceptions.
        pEnv->ExceptionClear();

        // Check if the array could be retrieved.
        if (NULL != array)
        {
            // Retrieve the array size.
            arraySize = pEnv->GetArrayLength(array);
        }

        // Return the array and its size.
        (*pArray)     = array;
        (*pArraySize) = arraySize;
    }
}
void
videoEditJava_getStaticIntField(
                bool*                               pResult,
                JNIEnv*                             pEnv,
                jclass                              clazz,
                const char*                         pName,
                int*                                pValue)
{
    // Only look for the class if locating the previous action succeeded.
    if (*pResult)
    {
        // Log the function call.
        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
                "videoEditJava_getStaticIntField(%s)", pName);

        // Look up the field id.
        jfieldID fieldId = pEnv->GetStaticFieldID(clazz, pName, "I");

        // Clear any resulting exceptions.
        pEnv->ExceptionClear();

        // Check if the field could be located.
        if (NULL != fieldId)
        {
            // Retrieve the field value.
            (*pValue) = pEnv->GetStaticIntField(clazz, fieldId);

            // Log the value.
            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
                    "videoEditJava_getStaticIntField, %s = %d", pName, (*pValue));
        }
        else
        {
            // Reset the result flag.
            (*pResult) = false;

            // Log the error.
            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
                    "videoEditJava_getStaticIntField, error: unable to locate field %s", pName);

            // Throw an exception.
            jniThrowException(pEnv, "java/lang/NoSuchFieldException",
                    "unable to locate static field");
        }
    }
}
void
videoEditJava_initMethodClass(
                bool*                               pResult,
                JNIEnv*                             pEnv,
                VideoEditJava_MethodsClass*                 pClass)
{
    bool   gotten = true;
    jclass clazz  = NULL;
    int    index  = 0;

    // Check if the previous action succeeded.
    if (*pResult)
    {
        // Log the function call.
        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
                "videoEditJava_initMethodClass(%s)", pClass->pName);

        // Only initialize the class once.
        if (!pClass->initialized)
        {
            // Look up the class.
            videoEditJava_getClass(pResult, pEnv, pClass->pName, &clazz);

            // Loop over the methods.
            for (index = 0; index < pClass->count; index++)
            {
                // Look up the method id.
                videoEditJava_getMethodId(
                        pResult,
                        pEnv,
                        clazz,
                        pClass->pMethods[index].pName,
                        pClass->pMethods[index].pType,
                        &pClass->pMethods[index].methodId);
            }

            // Check if all methods could be located.
            if (*pResult)
            {
                // Set the initialized flag.
                pClass->initialized = true;
            }
        }
    }
}
void
videoEditJava_getMethodId(
                bool*                               pResult,
                JNIEnv*                             pEnv,
                jclass                              clazz,
                const char*                         pName,
                const char*                         pType,
                jmethodID*                          pMethodId)
{
    // Only look for the class if locating the previous action succeeded.
    if (*pResult)
    {
        // Log the function call.
        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
                "videoEditJava_getMethodId(%s,%s)", pName, pType);

        // Look up the method id.
        jmethodID methodId = pEnv->GetMethodID(clazz, pName, pType);

        // Clear any resulting exceptions.
        pEnv->ExceptionClear();

        // Check if the method could be located.
        if (NULL != methodId)
        {
            // Return the method id.
            (*pMethodId) = methodId;
        }
        else
        {
            // Reset the result flag.
            (*pResult) = false;

            // Log the error.
            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
                    "videoEditJava_getMethodId, error: unable to locate method %s with type %s",
                    pName, pType);

            // Throw an exception.
            jniThrowException(pEnv, "java/lang/NoSuchMethodException", "unable to locate method");
        }
    }
}
void
videoEditJava_getClass(
                bool*                               pResult,
                JNIEnv*                             pEnv,
                const char*                         pName,
                jclass*                             pClazz)
{
    // Only look for the class if locating the previous action succeeded.
    if (*pResult)
    {
        // Log the function call.
        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
                "videoEditJava_getClass(%s)", pName);

        // Look up the class.
        jclass clazz = pEnv->FindClass(pName);

        // Clear any resulting exceptions.
        pEnv->ExceptionClear();

        // Check if the class could be located.
        if (NULL != clazz)
        {
            // Return the class.
            (*pClazz) = clazz;
        }
        else
        {
            // Reset the result flag.
            (*pResult) = false;

            // Log the error.
            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
                    "videoEditJava_getClass, error: unable to locate class %s", pName);

            // Throw an exception.
            jniThrowException(pEnv, "java/lang/ClassNotFoundException",
                    "unable to locate class");
        }
    }
}
void
videoEditJava_getObject(
                bool*                               pResult,
                JNIEnv*                             pEnv,
                jobject                             object,
                jfieldID                            objectFieldId,
                jobject*                            pObject)
{
    // Only retrieve the array object and size if the previous action succeeded.
    if (*pResult)
    {
        // Log the function call.
        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
            "videoEditJava_getObject()");

        // Retrieve the object.
        (*pObject) = pEnv->GetObjectField(object, objectFieldId);

        // Clear any resulting exceptions.
        pEnv->ExceptionClear();
    }
}
void
videoEditOsal_free(
                void*                               pData)
{
    // Check if memory was allocated.
    if (M4OSA_NULL != pData)
    {
        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_OSAL", "videoEditOsal_free()");

        // Log the API call.
        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR_OSAL", "free");

        // Free the memory.
        free(pData);
#ifdef OSAL_MEM_LEAK_DEBUG
        // Update the allocated block count.
        gAllocatedBlockCount--;

        // Log the number of allocated blocks.
        VIDEOEDIT_LOG_ALLOCATION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_OSAL", "allocated, %d blocks",\
         gAllocatedBlockCount);
#endif
    }
}
void*
videoEditJava_getString(
                bool*                               pResult,
                JNIEnv*                             pEnv,
                jobject                             object,
                jfieldID                            stringFieldId,
                M4OSA_UInt32*                       pLength)
{
    void*        pString = M4OSA_NULL;
    jstring      string  = NULL;
    M4OSA_UInt32 length  = 0;
    M4OSA_Char*  pLocal  = M4OSA_NULL;
    M4OSA_ERR    result  = M4NO_ERROR;

    // Check if the previous action succeeded.
    if (*pResult)
    {
        // Log the function call.
        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA", "videoEditJava_getString()");

        // Check if an object containing a string was specified.
        if (NULL != stringFieldId)
        {
            // Retrieve the string object.
            string = (jstring)pEnv->GetObjectField(object, stringFieldId);

            // Clear any resulting exceptions.
            pEnv->ExceptionClear();
        }
        else
        {
            // The string itself was specified.
            string = (jstring)object;
        }

        // Check if the string could be retrieved.
        if (NULL != string)
        {
            // Get a local copy of the string.
            pLocal = (M4OSA_Char*)pEnv->GetStringUTFChars(string, M4OSA_NULL);
            if (M4OSA_NULL != pLocal)
            {
                // Determine the length of the path
                // (add one extra character for the zero terminator).
                length = strlen((const char *)pLocal) + 1;

                // Allocate memory for the string.
                pString = videoEditOsal_alloc(pResult, pEnv, length, "String");
                if (*pResult)
                {
                    // Copy the string.
                    result = M4OSA_chrNCopy((M4OSA_Char*)pString, pLocal, length);

                    // Check if the copy succeeded.
                    videoEditJava_checkAndThrowRuntimeException(pResult, pEnv,
                     (M4NO_ERROR != result), result);

                    // Check if the string could not be copied.
                    if (!(*pResult))
                    {
                        // Free the allocated memory.
                        videoEditOsal_free(pString);
                        pString = M4OSA_NULL;
                    }
                }

                // Release the local copy of the string.
                pEnv->ReleaseStringUTFChars(string, (const char *)pLocal);
            }
        }

        // Check if the string was empty or could be copied.
        if (*pResult)
        {
            // Check if the length was requested.
            if (M4OSA_NULL != pLength)
            {
                // Return the length.
                (*pLength) = length;
            }
        }
    }

    // Return the string.
    return(pString);
}