Android采用OpenCL视频处理

时间:2014-05-16 13:50:11

标签: android opencl video-processing

我正在制作一个Android应用来测试OpenCL和RenderScript之间的差异。现在我正在尝试优化OpenCL的视频处理代码,但我只能处理第一帧而其他所有代码都是黑色的。

我的所有功能都适用于图像,当我在每个视频帧之前回想起初始化然后边缘检测功能时,一切顺利。但是,每当它被激活(当它是相同的内核)时,我需要重建OpenCL程序似乎不是逻辑。

我有一个包含所有OpenCL对象的结构:

struct OpenCLObjects
{
    // Regular OpenCL objects:
    cl_platform_id platform;
    cl_device_id device;
    cl_context context;
    cl_command_queue queue;
    cl_program program;
    cl_kernel kernel;

    // Objects that are specific for this sample.
    bool isInputBufferInitialized;
    cl_mem inputBuffer;
    cl_mem outputBuffer;
};

// Hold all OpenCL objects.
static OpenCLObjects openCLObjects; 

然后我有这个初始化函数:

void initOpenCL
(
        JNIEnv* env,
        jobject thisObject,
        jstring kernelName,
        cl_device_type required_device_type,
        OpenCLObjects& openCLObjects
)
{

    using namespace std;

    openCLObjects.isInputBufferInitialized = false;


    cl_int err = CL_SUCCESS;

    cl_platform_id platform;
    err = clGetPlatformIDs(1, &platform, NULL);
    SAMPLE_CHECK_ERRORS(err);

    cl_uint i = 0;
    size_t platform_name_length = 0;
    err = clGetPlatformInfo(
            platform,
            CL_PLATFORM_NAME,
            0,
            0,
            &platform_name_length
    );
    SAMPLE_CHECK_ERRORS(err);

    openCLObjects.platform = platform;

    cl_context_properties context_props[] = {
            CL_CONTEXT_PLATFORM,
            cl_context_properties(openCLObjects.platform),
            0
    };

    openCLObjects.context =
            clCreateContextFromType
            (
                    context_props,
                    required_device_type,
                    0,
                    0,
                    &err
            );
    SAMPLE_CHECK_ERRORS(err);

    err = clGetContextInfo
            (
                    openCLObjects.context,
                    CL_CONTEXT_DEVICES,
                    sizeof(openCLObjects.device),
                    &openCLObjects.device,
                    0
            );
    SAMPLE_CHECK_ERRORS(err);

    const char* fileName = env->GetStringUTFChars(kernelName, 0);
    std::string fileDir;
    fileDir.append("/data/data/com.denayer.ovsr/app_execdir/");
    fileDir.append(fileName);
    fileDir.append(".cl");
    std::string kernelSource = loadProgram(fileDir);

    const char* kernelSourceChar = kernelSource.c_str();

    openCLObjects.program =
            clCreateProgramWithSource
            (
                    openCLObjects.context,
                    1,
                    &kernelSourceChar,
                    0,
                    &err
            );

    SAMPLE_CHECK_ERRORS(err);

    err = clBuildProgram(openCLObjects.program, 0, 0, "-cl-fast-relaxed-math", 0, 0);
    SAMPLE_CHECK_ERRORS(err);

    /* -----------------------------------------------------------------------
     * Step 6: Extract kernel from the built program.
     */
    fileName = env->GetStringUTFChars(kernelName, 0);
    char result[100];   // array to hold the result.
    std::strcpy(result,fileName); // copy string one into the result.
    std::strcat(result,"Kernel"); // append string two to the result.
    openCLObjects.kernel = clCreateKernel(openCLObjects.program, result, &err);
    SAMPLE_CHECK_ERRORS(err);

    /* -----------------------------------------------------------------------
     * Step 7: Create command queue.
     */

    openCLObjects.queue =
            clCreateCommandQueue
            (
                    openCLObjects.context,
                    openCLObjects.device,
                    0,    
                    &err
            );
    SAMPLE_CHECK_ERRORS(err);

}


extern "C" void Java_com_denayer_ovsr_OpenCL_initOpenCL
(
        JNIEnv* env,
        jobject thisObject,
        jstring kernelName
)
{
    initOpenCL
    (
            env,
            thisObject,
            kernelName,
            CL_DEVICE_TYPE_GPU,
            openCLObjects
    );
}

这是调用边缘检测内核的函数:

void nativeImage2DOpenCL
(
        JNIEnv* env,
        jobject thisObject,
        OpenCLObjects& openCLObjects,
        jobject inputBitmap,
        jobject outputBitmap
)
{ 
    using namespace std;

    AndroidBitmapInfo bitmapInfo;
    AndroidBitmap_getInfo(env, inputBitmap, &bitmapInfo);

    size_t bufferSize = bitmapInfo.height * bitmapInfo.stride;
    cl_uint rowPitch = bitmapInfo.stride / 4;

    cl_int err = CL_SUCCESS;

    if(openCLObjects.isInputBufferInitialized)
    {
        err = clReleaseMemObject(openCLObjects.inputBuffer);
        SAMPLE_CHECK_ERRORS(err);
    }

    void* inputPixels = 0;
    AndroidBitmap_lockPixels(env, inputBitmap, &inputPixels);

    cl_image_format image_format;
    image_format.image_channel_data_type=CL_UNORM_INT8;
    image_format.image_channel_order=CL_RGBA;

    openCLObjects.inputBuffer =
            clCreateImage2D(openCLObjects.context,
                    CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
                    &image_format,
                    bitmapInfo.width,
                    bitmapInfo.height,
                    0,
                    inputPixels,
                    &err);
    SAMPLE_CHECK_ERRORS(err);

    openCLObjects.isInputBufferInitialized = true;

    AndroidBitmap_unlockPixels(env, inputBitmap);

    void* outputPixels = 0;
    AndroidBitmap_lockPixels(env, outputBitmap, &outputPixels);

    cl_mem outputBuffer =
            clCreateImage2D(openCLObjects.context,
                    CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,
                    &image_format,
                    bitmapInfo.width,
                    bitmapInfo.height,
                    0,
                    outputPixels,
                    &err);
    SAMPLE_CHECK_ERRORS(err);
    err = clSetKernelArg(openCLObjects.kernel, 0, sizeof(openCLObjects.inputBuffer), &openCLObjects.inputBuffer);
    SAMPLE_CHECK_ERRORS(err);
    err = clSetKernelArg(openCLObjects.kernel, 1, sizeof(outputBuffer), &outputBuffer);
    SAMPLE_CHECK_ERRORS(err);

    size_t globalSize[2] = { bitmapInfo.width, bitmapInfo.height };

    err = clEnqueueNDRangeKernel
            (
                    openCLObjects.queue,
                    openCLObjects.kernel,
                    2,
                    0,
                    globalSize,
                    0,
                    0, 0, 0
            );
    SAMPLE_CHECK_ERRORS(err);

    err = clFinish(openCLObjects.queue);
    SAMPLE_CHECK_ERRORS(err);

    const size_t origin[3] = {0, 0, 0};
    const size_t region[3] = {bitmapInfo.width, bitmapInfo.height, 1};

    err = clEnqueueReadImage(
            openCLObjects.queue,
            outputBuffer,
            true,
            origin,
            region,
            0,
            0,
            outputPixels,
            0,
            0,
            0);
    SAMPLE_CHECK_ERRORS(err);

    err = clFinish(openCLObjects.queue);
    SAMPLE_CHECK_ERRORS(err);

    err = clReleaseMemObject(outputBuffer);
    SAMPLE_CHECK_ERRORS(err);

    AndroidBitmap_unlockPixels(env, outputBitmap);
}

extern "C" void Java_com_denayer_ovsr_OpenCL_nativeImage2DOpenCL
(
        JNIEnv* env,
        jobject thisObject,
        jobject inputBitmap,
        jobject outputBitmap
)
{
    nativeImage2DOpenCL
    (
            env,
            thisObject,
            openCLObjects,
            inputBitmap,
            outputBitmap
    );
}

0 个答案:

没有答案