音视频实践学习

  • android全平台编译ffmpeg以及x264与fdk-aac实践
  • ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器
  • android全平台编译ffmpeg合并为单个库实践
  • android-studio使用cmake编译ffmpeg实践
  • android全平台编译ffmpeg视频解码器实践
  • android全平台编译ffmpeg支持命令行实践
  • android全平台编译ffmpeg视频推流实践
  • android平台下音频编码之编译LAME库转码PCM为MP3
  • ubuntu平台下编译vlc-android视频播放器实践
  • 图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别
  • 图解RGB565、RGB555、RGB16、RGB24、RGB32、ARGB32等格式的区别
  • YUV420P、YUV420SP、NV12、NV21和RGB互相转换并存储为JPEG以及PNG图片
  • android全平台编译libyuv库实现YUV和RGB的转换

概述

libyuv是Google开源的实现各种YUV与RGB之间相互转换、旋转、缩放的库。它是跨平台的,可在Windows、Linux、Mac、Android等操作系统,x86、x64、arm架构上进行编译运行,支持SSE、AVX、NEON等SIMD指令加速。

环境配置

操作系统:ubuntu 16.05
ndk版本:android-ndk-r16b

开始编译

第一步:先克隆出最新的libyuv版本

git clone git@github.com:lemenkov/libyuv.git

第二步:重命名libyuvjni,编辑Android.mk文件,注释掉JPEG相关的配置

android全平台编译libyuv库实现YUV和RGB的转换_第1张图片

android全平台编译libyuv库实现YUV和RGB的转换_第2张图片

第三步:新建Application.mk文件

APP_ABI := armeabi-v7a x86 x86_64APP_PLATFORM := android-16APP_STL := stlport_static  APP_CPPFLAGS += -fno-rtti  

开始编译ndk-build

android全平台编译libyuv库实现YUV和RGB的转换_第3张图片

工程实践

还是基于之前的graphic4android工程,新建native-libyuv工程,配置可以参考之前的配置:

enum Type {    TYPE_YUV420P_TO_RGB24 = 0,    TYPE_NV12_TO_RGB24 = 1,    TYPE_NV21_TO_RGB24 = 2};/** * I420就是YUV420P * @param yuvData * @param rgb24 * @param width * @param height */void I420_TO_RGB24(unsigned char *yuvData, unsigned char *rgb24, int width, int height) {    unsigned char *ybase = yuvData;    unsigned char *ubase = &yuvData[width * height];    unsigned char *vbase = &yuvData[width * height * 5 / 4];    //YUV420P转RGB24    libyuv::I420ToRGB24(ybase, width, ubase, width / 2, vbase, width / 2,                        rgb24,                        width * 3, width, height);}/** * NV12属于YUV420SP * @param yuvData * @param rgb24 * @param width * @param height */void NV12_TO_RGB24(unsigned char *yuvData, unsigned char *rgb24, int width, int height) {    unsigned char *ybase = yuvData;    unsigned char *uvbase = &yuvData[width * height];    //NV12转RGB24    libyuv::NV12ToRGB24(ybase, width, uvbase, width,                        rgb24,                        width * 3, width, height);}/** * NV21属于YUV420SP * @param yuvData * @param rgb24 * @param width * @param height */void NV21_TO_RGB24(unsigned char *yuvData, unsigned char *rgb24, int width, int height) {    unsigned char *ybase = yuvData;    unsigned char *vubase = &yuvData[width * height];    //NV21转RGB24    libyuv::NV21ToRGB24(ybase, width, vubase, width,                        rgb24,                        width * 3, width, height);}void drawYUV(const char *path, int type, int width, int height, ANativeWindow_Buffer buffer) {    FILE *file = fopen(path, "rb");    int frameSize = width * height * 3 / 2;    unsigned char *yuvData = new unsigned char[frameSize];    fread(yuvData, 1, frameSize, file);    unsigned char *rgb24 = new unsigned char[width * height * 3];    //YUV转RGB24    switch (type) {        case TYPE_YUV420P_TO_RGB24:            //YUV420P转RGB24            I420_TO_RGB24(yuvData, rgb24, width, height);            break;        case TYPE_NV12_TO_RGB24:            //YUV420SP转RGB24            NV12_TO_RGB24(yuvData, rgb24, width, height);            break;        case TYPE_NV21_TO_RGB24:            //YUV420SP转RGB24            NV21_TO_RGB24(yuvData, rgb24, width, height);            break;    }    uint32_t *line = (uint32_t *) buffer.bits;    for (int y = 0; y < height; y++) {        for (int x = 0; x < width; x++) {            int index = y * width + x;            line[x] = rgb24[index * 3] << 16                      | rgb24[index * 3 + 1] << 8                      | rgb24[index * 3 + 2];        }        line = line + buffer.stride;    }    //释放内存    delete[] yuvData;    delete[] rgb24;    //关闭文件句柄    fclose(file);}void yuv2rgb(JNIEnv *env, jobject obj, jstring yuvPath, jint type, jint width, jint height,             jobject surface) {    const char *path = env->GetStringUTFChars(yuvPath, 0);    //获取目标surface    ANativeWindow *window = ANativeWindow_fromSurface(env, surface);    if (NULL == window) {        ThrowException(env, "java/lang/RuntimeException", "unable to get native window");        return;    }    //默认的是RGB_565    int32_t result = ANativeWindow_setBuffersGeometry(window, 0, 0, WINDOW_FORMAT_RGBA_8888);    if (result < 0) {        ThrowException(env, "java/lang/RuntimeException", "unable to set buffers geometry");        //释放窗口        ANativeWindow_release(window);        window = NULL;        return;    }    ANativeWindow_acquire(window);    ANativeWindow_Buffer buffer;    //锁定窗口的绘图表面    if (ANativeWindow_lock(window, &buffer, NULL) < 0) {        ThrowException(env, "java/lang/RuntimeException", "unable to lock native window");        //释放窗口        ANativeWindow_release(window);        window = NULL;        return;    }    //绘制YUV420P    drawYUV(path, type, width, height, buffer);    //解锁窗口的绘图表面    if (ANativeWindow_unlockAndPost(window) < 0) {        ThrowException(env, "java/lang/RuntimeException",                       "unable to unlock and post to native window");    }    env->ReleaseStringUTFChars(yuvPath, path);    //释放    ANativeWindow_release(window);}

直接调用libyuv库里的函数即可完成转换过程

android全平台编译libyuv库实现YUV和RGB的转换_第4张图片

项目地址:native-libyuv
https://github.com/byhook/graphic4android

更多相关文章

  1. Android动态加载外部jar包及jar包中图片等资源文件
  2. 浅谈android中的图片处理之基本绘图(一)
  3. Android 内置图片
  4. android 悬浮窗口
  5. Android Fresco图片处理库用法API英文原文文档4(Facebook开源Andr
  6. android 自定义弹出窗口
  7. Android 实现图片轮播的三种方法
  8. 短视频平台源码android四种不同的事件实现

随机推荐

  1. Android之如何判断定位是否开启及定位模
  2. 【Android 内存优化】Bitmap 硬盘缓存 (
  3. 4.1 Android如何访问资源
  4. Android多媒体分析(一)MediaScanner
  5. Android.自定义控件的实现
  6. android 广播机制
  7. android usb挂载分析--ntfs-3g移植
  8. Android一套代码适配不同Android版本终极
  9. 用c/c++混合编程方式为ios/android实现一
  10. 2019零基础学Android第0课——零基础怎么