Android用surface直接显示yuv数据(二)

2023-11-18

 研究了一段时间Android的surface系统,一直执着地认为所有在surface或者屏幕上显示的画面,必须要转换成RGB才能显示,yuv数据也要通过颜色空间转换成RGB才能显示。可最近在研究stagefright视频显示时发现,根本找不到omx解码后的yuv是怎么转换成RGB的代码,yuv数据在render之后就找不到去向了,可画面确确实实的显示出来了,这从此颠覆了yuv必须要转换成RGB才能显示的真理了。

    稍微看一下AsomePlayer的代码,不难发现,视频的每一帧是通过调用了SoftwareRenderer来渲染显示的,我也尝试用利用SoftwareRenderer来直接render yuv数据显示,竟然成功了,这是一个很大的突破,比如以后摄像头采集到的yuv,可以直接丢yuv数据到surface显示,无需耗时耗效率的yuv转RGB了。



上一篇文章主要是参照AwesomePlayer直接用SoftwareRenderer类来显示yuv,为了能用到这个类,不惜依赖了libstagefright、libstagefright_color_conversion等动态静态库,从而造成程序具有很高的耦合度,也不便于我们理解yuv数据直接显示的深层次原因。

    于是我开始研究SoftwareRenderer的具体实现,我们来提取SoftwareRenderer的核心代码,自己来实现yuv的显示。

    SoftwareRenderer就只有三个方法,一个构造函数,一个析构函数,还有一个负责显示的render方法。构造方法里有个很重要的地方native_window_set_buffers_geometry这里是配置即将申请的图形缓冲区的宽高和颜色空间,忽略了这个地方,画面将用默认的值显示,将造成显示不正确。render函数里最重要的三个地方,一个的dequeBuffer,一个是mapper,一个是queue_buffer。

[cpp]  view plain  copy   在CODE上查看代码片 派生到我的代码片
  1. native_window_set_buffers_geometry;//设置宽高以及颜色空间yuv420  
  2. native_window_dequeue_buffer_and_wait;//根据以上配置申请图形缓冲区  
  3. mapper.lock(buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));//将申请到的图形缓冲区跨进程映射到用户空间  
  4. memcpy(dst, data, dst_y_size + dst_c_size*2);//填充yuv数据到图形缓冲区  
  5. mNativeWindow->queueBuffer;//显示  

以上五步是surface显示图形必不可少的五步。

有了以上分析,我们直接上代码:(yuv数据下载地址点击打开链接,放到sdcard)

main.cpp

[cpp]  view plain  copy   在CODE上查看代码片 派生到我的代码片
  1. #include <cutils/memory.h>  
  2.   
  3. #include <unistd.h>  
  4. #include <utils/Log.h>  
  5.   
  6. #include <binder/IPCThreadState.h>  
  7. #include <binder/ProcessState.h>  
  8. #include <binder/IServiceManager.h>  
  9. #include <media/stagefright/foundation/ADebug.h>  
  10. #include <gui/Surface.h>  
  11. #include <gui/SurfaceComposerClient.h>  
  12. #include <gui/ISurfaceComposer.h>  
  13. #include <ui/DisplayInfo.h>  
  14. #include <android/native_window.h>  
  15. #include <system/window.h>  
  16. #include <ui/GraphicBufferMapper.h>  
  17. //ANativeWindow 就是surface,对应surface.cpp里的code  
  18. using namespace android;  
  19.   
  20. //将x规整为y的倍数,也就是将x按y对齐  
  21. static int ALIGN(int x, int y) {  
  22.     // y must be a power of 2.  
  23.     return (x + y - 1) & ~(y - 1);  
  24. }  
  25.   
  26. void render(  
  27.         const void *data, size_t size, const sp<ANativeWindow> &nativeWindow,int width,int height) {  
  28.     sp<ANativeWindow> mNativeWindow = nativeWindow;  
  29.     int err;  
  30.     int mCropWidth = width;  
  31.     int mCropHeight = height;  
  32.       
  33.     int halFormat = HAL_PIXEL_FORMAT_YV12;//颜色空间  
  34.     int bufWidth = (mCropWidth + 1) & ~1;//按2对齐  
  35.     int bufHeight = (mCropHeight + 1) & ~1;  
  36.       
  37.     CHECK_EQ(0,  
  38.             native_window_set_usage(  
  39.             mNativeWindow.get(),  
  40.             GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN  
  41.             | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));  
  42.   
  43.     CHECK_EQ(0,  
  44.             native_window_set_scaling_mode(  
  45.             mNativeWindow.get(),  
  46.             NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));  
  47.   
  48.     // Width must be multiple of 32???  
  49.     //很重要,配置宽高和和指定颜色空间yuv420  
  50.     //如果这里不配置好,下面deque_buffer只能去申请一个默认宽高的图形缓冲区  
  51.     CHECK_EQ(0, native_window_set_buffers_geometry(  
  52.                 mNativeWindow.get(),  
  53.                 bufWidth,  
  54.                 bufHeight,  
  55.                 halFormat));  
  56.       
  57.       
  58.     ANativeWindowBuffer *buf;//描述buffer  
  59.     //申请一块空闲的图形缓冲区  
  60.     if ((err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(),  
  61.             &buf)) != 0) {  
  62.         ALOGW("Surface::dequeueBuffer returned error %d", err);  
  63.         return;  
  64.     }  
  65.   
  66.     GraphicBufferMapper &mapper = GraphicBufferMapper::get();  
  67.   
  68.     Rect bounds(mCropWidth, mCropHeight);  
  69.   
  70.     void *dst;  
  71.     CHECK_EQ(0, mapper.lock(//用来锁定一个图形缓冲区并将缓冲区映射到用户进程  
  72.                 buf->handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));//dst就指向图形缓冲区首地址  
  73.   
  74.     if (true){  
  75.         size_t dst_y_size = buf->stride * buf->height;  
  76.         size_t dst_c_stride = ALIGN(buf->stride / 2, 16);//1行v/u的大小  
  77.         size_t dst_c_size = dst_c_stride * buf->height / 2;//u/v的大小  
  78.           
  79.         memcpy(dst, data, dst_y_size + dst_c_size*2);//将yuv数据copy到图形缓冲区  
  80.     }  
  81.   
  82.     CHECK_EQ(0, mapper.unlock(buf->handle));  
  83.   
  84.     if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf,  
  85.             -1)) != 0) {  
  86.         ALOGW("Surface::queueBuffer returned error %d", err);  
  87.     }  
  88.     buf = NULL;  
  89. }  
  90.   
  91. bool getYV12Data(const char *path,unsigned char * pYUVData,int size){  
  92.     FILE *fp = fopen(path,"rb");  
  93.     if(fp == NULL){  
  94.         printf("read %s fail !!!!!!!!!!!!!!!!!!!\n",path);  
  95.         return false;  
  96.     }  
  97.     fread(pYUVData,size,1,fp);  
  98.     fclose(fp);  
  99.     return true;  
  100. }  
  101.   
  102. int main(void){  
  103.     // set up the thread-pool  
  104.     sp<ProcessState> proc(ProcessState::self());  
  105.     ProcessState::self()->startThreadPool();  
  106.       
  107.     // create a client to surfaceflinger  
  108.     sp<SurfaceComposerClient> client = new SurfaceComposerClient();  
  109.     sp<IBinder> dtoken(SurfaceComposerClient::getBuiltInDisplay(  
  110.             ISurfaceComposer::eDisplayIdMain));  
  111.     DisplayInfo dinfo;  
  112.     //获取屏幕的宽高等信息  
  113.     status_t status = SurfaceComposerClient::getDisplayInfo(dtoken, &dinfo);  
  114.     printf("w=%d,h=%d,xdpi=%f,ydpi=%f,fps=%f,ds=%f\n",   
  115.         dinfo.w, dinfo.h, dinfo.xdpi, dinfo.ydpi, dinfo.fps, dinfo.density);  
  116.     if (status)  
  117.         return -1;  
  118.     //创建surface  
  119.     sp<SurfaceControl> surfaceControl = client->createSurface(String8("testsurface"),  
  120.             dinfo.w, dinfo.h, PIXEL_FORMAT_RGBA_8888, 0);  
  121.               
  122. /*************************get yuv data from file;****************************************/            
  123.     printf("[%s][%d]\n",__FILE__,__LINE__);  
  124.     int width,height;  
  125.     width = 320;  
  126.     height = 240;  
  127.     int size = width * height * 3/2;  
  128.     unsigned char *data = new unsigned char[size];  
  129.     const char *path = "/mnt/sdcard/yuv_320_240.yuv";  
  130.     getYV12Data(path,data,size);//get yuv data from file;  
  131.       
  132. /*********************配置surface*******************************************************************/  
  133.     SurfaceComposerClient::openGlobalTransaction();  
  134.     surfaceControl->setLayer(100000);//设定Z坐标  
  135.     surfaceControl->setPosition(100, 100);//以左上角为(0,0)设定显示位置  
  136.     surfaceControl->setSize(width, height);//设定视频显示大小  
  137.     SurfaceComposerClient::closeGlobalTransaction();  
  138.     sp<Surface> surface = surfaceControl->getSurface();  
  139.     printf("[%s][%d]\n",__FILE__,__LINE__);  
  140.       
  141. /**********************显示yuv数据******************************************************************/     
  142.     render(data,size,surface,width,height);  
  143.     printf("[%s][%d]\n",__FILE__,__LINE__);  
  144.       
  145.     IPCThreadState::self()->joinThreadPool();//可以保证画面一直显示,否则瞬间消失  
  146.     IPCThreadState::self()->stopProcess();  
  147.     return 0;  
  148. }  

Android.mk (这次依赖的库少了很多)

[cpp]  view plain  copy   在CODE上查看代码片 派生到我的代码片
  1. LOCAL_PATH:= $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3.   
  4. LOCAL_SRC_FILES:= \  
  5.     main.cpp  
  6.       
  7. LOCAL_SHARED_LIBRARIES := \  
  8.     libcutils \  
  9.     libutils \  
  10.     libbinder \  
  11.     libui \  
  12.     libgui \  
  13.     libstagefright_foundation  
  14.       
  15. LOCAL_MODULE:= MyShowYUV  
  16.   
  17. LOCAL_MODULE_TAGS := tests  
  18.   
  19. include $(BUILD_EXECUTABLE)  

转载请注明出处http://blog.csdn.net/tung214/article/details/37651825

感谢这篇文章总结:http://blog.csdn.net/crazyman2010/article/details/41750623


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android用surface直接显示yuv数据(二) 的相关文章

  • 合并空间上接近的路径/线段的算法

    我正在寻找一种用于街道地图制图概括的几何算法 名称 在我的地图数据中 我有许多路径 点的有序列表 由线段连接 这些路径彼此靠近且几乎平行 我如何 1 识别这些 相邻路径 即如何找到比某个阈值更接近的路径 以及 2 将它们合并成一条路径 即如
  • 如何在ggplot2中使用希腊符号?

    我的类别需要用希腊字母命名 我在用ggplot2 并且它与数据配合得很好 不幸的是 我无法弄清楚如何将这些希腊符号放在 x 轴上 在刻度线处 并使它们出现在图例中 有什么办法可以做到吗 更新 我看了一下link https github c
  • 将四元数旋转转换为旋转矩阵?

    基本上 给定一个四元数 qx qy qz qw 我如何将其转换为OpenGL旋转矩阵 我也对哪个矩阵行是 向上 向右 向前 等感兴趣 我有一个四元数的相机旋转 我需要在向量中 以下代码基于四元数 qw qx qy qz 其中顺序基于 Boo
  • 如何使用双重调度来分析图形基元的交集?

    我正在分析图形基元 矩形 直线 圆形等 的交互并计算重叠 相对方向 合并等 这被引用为双重调度的一个主要示例 例如维基百科 http en wikipedia org wiki Double dispatch 自适应碰撞算法通常要求 不同的
  • 为什么这个 R ggplot2 代码会显示一个空白的显示设备?

    虽然 SO 通常不用于帮助解决错误 但这个显示了特别简单且特别烦人的行为 如果你是一个ggplot2用户 您可以在 10 秒或更短的时间内重现它 正如这个 GitHub 问题 ggplot gtable 创建空白显示 https githu
  • 测量以指定宽度包裹的文本高度

    如何计算渲染以指定宽度包裹的文本所需的高度 我在中找到了以下方法Graphics graphicsObj MeasureString text font width 但它需要一个实例Graphics当时我还没有图形实例 事实上 我更喜欢使用
  • 重新创建窗口而不破坏上下文

    这个问题是关于使用 OpenGL 的图形应用程序 当时我正在使用 GLFW 框架 但我考虑更改它 我的目标是让用户 尽可能 在全屏模式和窗口模式之间不断切换 此过程应该花费不到一秒的时间 并且可以在运行时发生 例如 看看游戏 我的世界 用户
  • 帧缓冲区/颜色缓冲区?

    有人可以指出我两者是否相同吗 我的意思是我一直在阅读有关它的信息 这里的红皮书说 颜色缓冲区本身可以由多个子缓冲区组成 系统上的帧缓冲区包含所有这些缓冲区 here http glprogramming com red chapter10
  • 为什么 OpenGL 有远裁剪平面,以及使用什么惯用法来处理这个问题?

    我一直在学习 OpenGL 持续困扰我的一个话题是远裁剪平面 虽然我可以理解近剪裁平面和侧剪裁平面 它们永远不会产生任何实际效果 因为它们之外的对象无论如何都不会被渲染 背后的推理 但远剪裁平面似乎只是一个烦恼 由于 OpenGL 背后的人
  • 如何使用 Java2D 创建硬件加速图像?

    我正在尝试创建一个快速图像生成器 它可以执行大量 2d 转换和形状渲染 因此我尝试使用 BufferedImage 然后获取 Graphics2D 对象来执行所有绘图 我现在主要关心的是 make 速度非常快 所以我创建一个像这样的 Buf
  • 有什么方法可以禁用 PDF/Postscript 输出中的“减号破解”吗?

    在 R 中 将绘图保存到 PDF 或 Postscript 文件时 轴标签中的连字符会变成减号 显然 这是设计使然 根据 postscript 设备的文档 正常编码规则 有一个例外 字符 45 始终设置为负号 其在 Adob e ISOLa
  • GL_COLOR_ATTACHMENT 有什么作用?

    我现在正在学习帧缓冲区 但我只是不明白颜色附件的作用 我了解帧缓冲区 第二个参数的意义是什么 glFramebufferTexture2D GL FRAMEBUFFER GL COLOR ATTACHMENT0 GL TEXTURE 2D
  • Python 中漂亮的图形和图表 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在.net中创建一个圆形头像图像

    我想创建一个默认头像图像 它是一个带有缩写的圆圈 我想在服务器端以 png 格式执行此操作 使用 net 图形库可以实现这一点吗 我最终这样做了 感谢您为我指明了正确的方向 TaW public ActionResult Avatar us
  • 从主模块访问动态功能模块的可绘制文件夹中的图形

    我正在尝试动态模块拆分 API 交付 以便将我的游戏应用程序分解为即时版本和可安装版本 我一直在关注这里的 Codelabs 教程https codelabs developers google com codelabs on demand
  • 在 3d 网格中转发(绘制)线

    我需要类似 Bresenham 算法的东西 但是 对于 3d 网格空间来说不完全是这样 我需要 3d 单元网格 边缘尺寸 1 0 从 S 点开始 前进到 K 点 接触 该线接触的所有单元格 即使只有边缘 点被触摸我需要触摸所有 8 个单元
  • 如何在 R 中导入并绘制三角形网格?

    我想在 R 中绘制我的模型输出 它是格式为的三角形网格 x1 y1 z1 x2 y2 z2 x3 y3 z3 value 每行代表一个三角形 我想用以下方法绘制这些三角形value作为规模 mymesh lt structure c 0 9
  • 定点数学比浮点运算快吗?

    多年前 即 20 世纪 90 年代初期 我构建了图形软件包 该软件包基于定点算术和预先计算的 cos sin 表格以及使用牛顿近似方法进行 sqrt 和对数近似的缩放方程来优化计算 这些先进技术似乎已经成为图形和内置数学处理器的一部分 大约
  • 自动跟踪算法

    我正在尝试写一个simple跟踪例程来跟踪电影中的某些点 本质上我有一系列 100 帧长的电影 在黑暗背景上显示一些亮点 我每帧有大约 100 150 个点 它们在电影的过程中移动 我想跟踪它们 所以我正在寻找一些有效的 但可能不会过度实施
  • Java制作一条有向线并使其移动

    我想画一条有向线并让它移动 我能够绘制一条有向线并移动该线 但当我移动该线时箭头会移位 这是我的绘画方法 Line2D Double line new Line2D Double startX startY endX endY g2d dr

随机推荐

  • Window XP驱动开发(二十四) 电源管理

    转载自 http blog csdn net xxxluozhen article details 5023703 一 电源管理 1 WDM电源管理模型 在Windows 2000和Windows 98中 操作系统接管了大部分电源管理工作
  • (数据结构)1.实现图的邻接矩阵和邻接表的存储 2.实现图的遍历算法

    实验内容 1 编写一个程序graph cpp 设计带权图的邻接矩阵与邻接表的创建和输出运算 并在此基础上设计一个主程序exp8 1 cpp完成以下功能 1 建立如图8 54所示的有向图G的邻接矩阵 并输出之 2 建立如图8 54所示的有向图
  • 力扣:70. 爬楼梯

    假设你正在爬楼梯 需要 n 阶你才能到达楼顶 每次你可以爬 1 或 2 个台阶 你有多少种不同的方法可以爬到楼顶呢 示例 1 输入 n 2 输出 2 解释 有两种方法可以爬到楼顶 1 1 阶 1 阶 2 2 阶 示例 2 输入 n 3 输出
  • Boot与APP的Hex合并

    软件准备 使用的软件是srec cat软件 下载地址 合并脚本编写 ECHO OFF 如果存在上一次的hex文件就删除 if exist BootJoinAPP CCP APP hex del BootJoinAPP CCP APP hex
  • C# 远程唤醒(远程开机)

    C 远程唤醒 远程开机 近日 小白要用到远程开机的功能 网上大多介绍的是Magic Packet的工具 实际上 此Magic Packet是AMD公司开发的 请在google cn中搜索Magic Packet Technology 原理上
  • Mysql递归查询

    SELECT IFNULL CONCAT GROUP CONCAT CONCAT catId t id catName t name ch catLevel t level AS companyCategories FROM SELECT
  • 微服务实践--微服务方法论00

    思想 在接收到一个新的新项目时 架构师的职责是建立项目的业务与技术实现之间的桥梁 在翻译业务到技术实现的过程中需要进行业务建模 技术设计等方面的工作 业务建模和技术设计过程中都有各自领域的知识体系 基本上每个知识体系都是由上层的理论 概念和
  • python判断素数的函数_python判断是否为素数

    质数 prime number 又称素数 指在一个大于1的自然数中 除了1和此整数自身外 不能被其他自然数整除的数 素数在数论中有着很重要的地位 比1大但不是素数的数称为合数 1和0既非素数也非合数 素数是与合数相对立的两个概念 二者构成了
  • C++实现栈的顺序存储与链式存储

    栈是一种特殊的数据结构 栈中数据先进后出 且栈中数据只能从头部出栈 能直接访问的数据也仅为栈的头部数据 要想访问下面的数据则需要将前面的数据逐个出栈后才可访问 下面通过一个word撤销的案例来解释 我们用word写paper时 首先需要创建
  • 国内首部

    当前 税务和发票等财税数据作为财务关联性强 欺诈难度大 覆盖率最高的优质数据 正成为数字普惠金融不可或缺的 硬核 力量 全面提升相关数据理论与实战能力正逢其时 8月8日 在金蝶2023年全球创见者大会 企业数字信用平行论坛 现场 金蝶征信
  • java使用MD5生成摘要

    对value进行hash处理 return hash处理结果 public static String digest String input int length 32 try MessageDigest md MessageDigest
  • openGL之API学习(六十八)core profile、compatibility profile、forward compatibility

    在OpenGL的发展历程中 总是兼顾向下兼容的特性 但是到了一定的程度之后 这些旧有的OpenGL API不再适应时代的需要 还有一些扩展并不是驱动一定要实现的扩展 这些被统一划入可选的Compatibility Profile 而由Ope
  • 信号的时域相位、频域相位

    文章目录 傅里叶变换的时移性质 matlab代码 单点频信号 线调信号 时域相位 频域相位 傅里叶变换的时移性质 信号增加线性相位时 是所有的频率分量对应的相位都有变化 matlab代码 清空一切 clc clear all close a
  • 翻译:《实用的Python编程》01_07_Functions

    目录 上一节 1 6 文件 下一节 2 0 处理数据 1 7 函数 随着程序开始变大 我们会想要有条理地组织这些程序 本节简要介绍函数 库模块以及带有异常的错误处理 自定义函数 对你要重用的代码使用函数 下面是函数的定义方式 def sum
  • 数据结构--图的学习(基础概念)

    目录 图的定义 图的逻辑结构应用 无向图 有向图 编辑 简单图 多重图 顶点的度 入读 出度 顶点 顶点的关系描述 连通图和强连通图 子图 1 无向图的子图 编辑 2 有向图的子图 连通分量 强连通分量 生成树 生成森林 边的权 带权图 网
  • 2014年3月7日星期五(DEMO8-4,实体三角形着色)

    这个例子比较大 任重而道远 理论草草看了下 光记住索引和RGB各项求最小距离了 为简单起见 拷贝7 6过来 并把8 3封装到的引擎代码拷贝替换 逐行来看 各个击破 先换成800 600视口 define SCREEN WIDTH 800 d
  • mysql之基础查询,条件查询测试题07

    1 基础查询 条件查询测试题 看图 结果 1 SELECT salary last name FROM employees WHERE commission pct IS NULL AND salary lt 18000 2 SELECT
  • STM32F407 CAN1 CAN2

    注意CAN1可以单独使用 CAN2要开启CAN1时钟才能使用 u8 CAN1 Mode Init u8 mode GPIO InitTypeDef GPIO InitStructure CAN InitTypeDef CAN InitStr
  • DBeaver 如何配置离线驱动

    1 打开已经下载过DBeaver驱动的软件 点击 数据库 驱动管理器 进入 2 选中 MySQL 点击右侧的 编辑 进入 3 点击页签 库 打开列表内容 选中 mysql connector java 8 0 17 jar 点击 类路径 4
  • Android用surface直接显示yuv数据(二)

    研究了一段时间Android的surface系统 一直执着地认为所有在surface或者屏幕上显示的画面 必须要转换成RGB才能显示 yuv数据也要通过颜色空间转换成RGB才能显示 可最近在研究stagefright视频显示时发现 根本找不