android FFmpeg 获取视频帧转 Bitmap

android FFmpeg 获取 视频帧 转 Bitmap

流程可以分为:
1、传入视频文件路径,解封装

2、找到视频流,从流中找到解码器

3、打开解码器,读取第一个完整的AVFrame帧

4、创建bitmap,使用libyuv将yuv转为argb关联给bitmap显示

5、释放资源

获取视频帧

    //封装格式上下文    
    AVFormatContext *ifmt_ctx = NULL;
    //打开输入源
    ret = avformat_open_input(&ifmt_ctx, _path, 0, 0);
    if (ret < 0) {
        logDebug("解封装失败 -- %s", av_err2str(ret));
        return nullptr;
    }
    ret = avformat_find_stream_info(ifmt_ctx, 0);
    int video_stream_index = -1;
    AVStream *pStream = NULL;
    AVCodecParameters *codecpar = NULL;
    //找出视频流
    for (int i = 0; i < ifmt_ctx->nb_streams; ++i) {
        pStream = ifmt_ctx->streams[i];
        if (pStream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            codecpar = pStream->codecpar;
            video_stream_index = i;
        }
    }
    //拷贝parameters 到 编解码器的context
    ret = avcodec_parameters_to_context(codec_ctx, codecpar);
    //打开编解码器
    ret = avcodec_open2(codec_ctx, codec, NULL);
    //申请一个帧结构体
    AVFrame *pFrame = av_frame_alloc();
 
   int frameFinished;
    while (av_read_frame(ifmt_ctx, &pkg) >= 0) {
        if (pkg.stream_index != video_stream_index) {
            continue;
        }
        ret = avcodec_decode_video2(codec_ctx, pFrame, &frameFinished, &pkg);
        if (!frameFinished)
            continue;
    }

jni创建 Bitmap

jobject createBitmap(JNIEnv *env,
                     int width, int height) {
 
    jclass bitmapCls = env->FindClass("android/graphics/Bitmap");
    jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls,
                                                            "createBitmap",
                                                            "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
    jstring configName = env->NewStringUTF("ARGB_8888");
    jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
    jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass,
                                                                   "valueOf",
                                                                   "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
 
    jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass,
                                                       valueOfBitmapConfigFunction,
                                                       configName);
 
    jobject newBitmap = env->CallStaticObjectMethod(bitmapCls,
                                                    createBitmapFunction,
                                                    width, height,
                                                    bitmapConfig);
 
    return newBitmap;
}

使用 LibYUV 转换 RGB 格式

先使用#include <android/bitmap.h>头文件中 AndroidBitmap_lockPixels() 的函数绑定像素指针的地址,使用 libyuv 中的 I420ToABGR() 函数将 yuv420p 转换为 argb,记得最后使用 AndroidBitmap_unlockPixels() 函数回收Bitmap。

    jobject bmp;
    bmp = createBitmap(env, codec_ctx->width, codec_ctx->height);
  
  void *addr_pixels;
    ret = AndroidBitmap_lockPixels(env, bmp, &addr_pixels);
 
    //yuv420p to argb
    int linesize = pFrame->width * 4;
    libyuv::I420ToABGR(pFrame->data[0], pFrame->linesize[0], // Y
                       pFrame->data[1], pFrame->linesize[1], // U
                       pFrame->data[2], pFrame->linesize[2], // V
                       (uint8_t *) addr_pixels, linesize,  // RGBA
                       pFrame->width, pFrame->height);
    AndroidBitmap_unlockPixels(env, bmp);
   

释放资源

``
av_packet_unref(&pkg);
av_free(pFrame);
avcodec_close(codec_ctx);
avformat_close_input(&ifmt_ctx);
env->ReleaseStringUTFChars(path, _path); `

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baoyu45585

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值