使用FFMPEG调整视频帧大小

时间:2015-04-24 14:48:56

标签: android c ffmpeg java-native-interface

我需要使用ffmpeg调整相机预览框的大小。我编写了ffmpeg代码和相关的java代码,我正在做的是将byte []发送到本机代码并在其他byte []中获取输出但是我总是在我的本机代码中获得输出缓冲区零。

这是我的原生代码:

jint Java_com_sample_FfmpegNdk_resizeRawImage( JNIEnv *env, jobject thiz, jbyteArray input_array, jarray output_array, jint width, jint height) {
    jbyte *data;
    jsize array_size = (*env)->GetArrayLength(env, input_array);

    data = (*env)->GetByteArrayElements(env, input_array, NULL);

    LOGD_CUSTOM(env, "Data Length: (%d)", strlen(data));
    LOGD_CUSTOM(env, "Array Length: (%d)", array_size);

    AVFrame *frame1 = av_frame_alloc();
    avpicture_fill((AVPicture*)frame1, data, AV_PIX_FMT_NV12, 720, 480);

    struct SwsContext *resize;
    resize = sws_getContext(720, 480, AV_PIX_FMT_NV12, width, height, AV_PIX_FMT_NV12, SWS_BICUBIC, NULL, NULL, NULL);

    AVFrame* frame2 = av_frame_alloc();

    int num_bytes = avpicture_get_size(AV_PIX_FMT_NV12, width, height);

    uint8_t* frame2_buffer = (uint8_t *)av_malloc(num_bytes);

    avpicture_fill((AVPicture*)frame2, frame2_buffer, AV_PIX_FMT_NV12, width, height);

    LOGD_CUSTOM(env, "Frame1 Data: (%d)", strlen(frame1->data));

    sws_scale(resize, frame1->data, frame1->linesize, 0, height, frame2->data, frame2->linesize);

    LOGD_CUSTOM(env, "Frame2 Data: (%d)", strlen(frame2->data));

    (*env)->ReleaseByteArrayElements(env, output_array, (jbyte*)frame2->data, JNI_ABORT);

    jsize array_size_s = (*env)->GetArrayLength(env, output_array);

    LOGD_CUSTOM(env, "Array Length After: (%d)", array_size_s);

    sws_freeContext(resize);

    free(data);

    return 0;
 }

这是我的代码,我正在进行相机预览

myCamera.setPreviewCallback(new Camera.PreviewCallback() {
    @Override
    public void onPreviewFrame(final byte[] data, Camera camera) {
        if (data != null) { 
            byte[] new_data = new byte[1024];
            Log.e("lenght", "IIp lenght : " + data.length);
            FfmpegNdk.resizeRawImage(data, new_data, 480, 270);
            Log.e("lenght", "oIp lenght : " + new_data.length);             
        }
    }
});

1 个答案:

答案 0 :(得分:0)

我认为JNI_ABORT就是这个原因,该标志阻止JVM将数据复制回客户端。

尝试更改此行

(*env)->ReleaseByteArrayElements(env, output_array, (jbyte*)frame2->data, JNI_ABORT);

(*env)->ReleaseByteArrayElements(env, output_array, (jbyte*)frame2->data, JNI_COMMIT);

JNI_COMMIT将复制数据,您需要使用

释放帧缓冲区
av_frame_free(&frame2)

了解更多信息,请检查 http://developer.android.com/training/articles/perf-jni.html#arrays