获取视频AVFrame的YUV数据

电脑杂谈  发布时间:2020-01-03 02:02:44  来源:网络整理

电脑版wifi万能解锁器_万能播放器java版_mac版万能解锁器wifi下载

YUV420是指:Y : UV = 4 : 1

YUV420P是指:YUV的排列方法,先将Y排列完,再将U排列完,最后将

V排列完。如:

mac版万能解锁器wifi下载_万能播放器java版_电脑版wifi万能解锁器

YYYYYYYYYYYYYYYY UUUU VVVV

FFmpeg解码出来的视频YUV数据是存储在AVFrame中的data里面,我们以

YUV420P为视频数据帮OPenGL渲染。

电脑版wifi万能解锁器_mac版万能解锁器wifi下载_万能播放器java版

Y分量:frame->data[0]

U分量:frame->data[1]

V分量:frame->data[2]

电脑版wifi万能解锁器_mac版万能解锁器wifi下载_万能播放器java版

绝大多数视频都是YUV420P格式的,对于不是YUV420P格式的万能播放器java版,我们先将

其转换(sws_scale)为YUV420P后再帮OPenGL ES渲染万能播放器java版,所以C++层要调用Java的OpenGL ES渲染YUV数据。

Java层

万能播放器java版_mac版万能解锁器wifi下载_电脑版wifi万能解锁器

/**
 *JfPlayer.java
 * @param width
 * @param height
 * @param y
 * @param u
 * @param v
 */
public void onCallRenderYUV(int width,int height,byte[] y,byte[] u,byte[] v){
    JfLog.d("获取到视频的数据");
}

C++层

jmid_renderyuv = env->GetMethodID(jlz, "onCallRenderYUV", "(II[B[B[B)V");
void WlCallJava::onCallRenderYUV(int width, int height, uint8_t *fy, uint8_t *fu, uint8_t *fv) {
    JNIEnv *jniEnv;
    if(javaVM->AttachCurrentThread(&jniEnv, 0) != JNI_OK)
    {
        if(LOG_DEBUG)
        {
            LOGE("call onCallComplete worng");
        }
        return;
    }
    jbyteArray y = jniEnv->NewByteArray(width * height);
    jniEnv->SetByteArrayRegion(y, 0, width * height, reinterpret_cast<const jbyte *>(fy));
    jbyteArray u = jniEnv->NewByteArray(width * height / 4);
    jniEnv->SetByteArrayRegion(u, 0, width * height / 4, reinterpret_cast<const jbyte *>(fu));
    jbyteArray v = jniEnv->NewByteArray(width * height / 4);
    jniEnv->SetByteArrayRegion(v, 0, width * height / 4, reinterpret_cast<const jbyte *>(fv));
    jniEnv->CallVoidMethod(jobj, jmid_renderyuv, width, height, y, u, v);
    jniEnv->DeleteLocalRef(y);
    jniEnv->DeleteLocalRef(u);
    jniEnv->DeleteLocalRef(v);
    javaVM->DetachCurrentThread();
}

格式转换后渲染

if (avFrame->format == AV_PIX_FMT_YUV420P){
    //直接渲染
    LOGD("YUV420P");
    video->callJava->onCallRenderYUV(
            CHILD_THREAD,
            video->pVCodecCtx->width,
            video->pVCodecCtx->height,
            avFrame->data[0],
            avFrame->data[1],
            avFrame->data[2]);
} else {
    //转成YUV420P
    AVFrame *pFrameYUV420P = av_frame_alloc();
    int num = av_image_get_buffer_size(AV_PIX_FMT_YUV420P,video->pVCodecCtx->width,video->pVCodecCtx->height,1);
    uint8_t *buffer = (uint8_t *)(av_malloc(num * sizeof(uint8_t)));
    av_image_fill_arrays(
            pFrameYUV420P->data,
            pFrameYUV420P->linesize,
            buffer,
            AV_PIX_FMT_YUV420P,
            video->pVCodecCtx->width,
            video->pVCodecCtx->height,
            1);
    SwsContext *sws_ctx = sws_getContext(
            video->pVCodecCtx->width,
            video->pVCodecCtx->height,
            video->pVCodecCtx->pix_fmt,
            video->pVCodecCtx->width,
            video->pVCodecCtx->height,
            AV_PIX_FMT_YUV420P,
            SWS_BICUBIC,
            NULL,NULL,NULL
            );
    if (!sws_ctx){
        av_frame_free(&pFrameYUV420P);
        av_free(pFrameYUV420P);
        av_free(buffer);
        continue;
    }
    sws_scale(
            sws_ctx,
            avFrame->data,
            avFrame->linesize,
            0,
            avFrame->height,
            pFrameYUV420P->data,
            pFrameYUV420P->linesize);//这里得到YUV数据
    LOGD("NO_YUV420P");
    //渲染
    video->callJava->onCallRenderYUV(
            CHILD_THREAD,
            video->pVCodecCtx->width,
            video->pVCodecCtx->height,
            pFrameYUV420P->data[0],
            pFrameYUV420P->data[1],
            pFrameYUV420P->data[2]);
    av_frame_free(&pFrameYUV420P);
    av_free(pFrameYUV420P);
    av_free(buffer);
    sws_freeContext(sws_ctx);
}

到此处就早已受到YUV数据了!


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/bofangqi/article-135615-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...