android java 硬编码保存mp4 jni数据转换

目录

java imagereader编码保存

java NV21toYUV420SemiPlanar 编码保存视频用:

imageReader获取nv21

jni NV12toYUV420SemiPlanar函数:


代码来自博客:

【Android Camera2】彻底弄清图像数据YUV420_888转NV21问题/良心教学/避坑必读!_yuv420888转nv21_奔跑的鲁班七号的博客-CSDN博客

java imagereader编码保存

//Planar格式(P)的处理private static ByteBuffer getuvBufferWithoutPaddingP(ByteBuffer uBuffer,ByteBuffer vBuffer, int width, int height, int rowStride, int pixelStride){int pos = 0;byte []byteArray = new byte[height*width/2];for (int row=0; row<height/2; row++) {for (int col=0; col<width/2; col++) {int vuPos = col*pixelStride + row*rowStride;byteArray[pos++] = vBuffer.get(vuPos);byteArray[pos++] = uBuffer.get(vuPos);}}ByteBuffer bufferWithoutPaddings=ByteBuffer.allocate(byteArray.length);// 数组放到buffer中bufferWithoutPaddings.put(byteArray);//重置 limit 和postion 值否则 buffer 读取数据不对bufferWithoutPaddings.flip();return bufferWithoutPaddings;}//Semi-Planar格式(SP)的处理和y通道的数据private static ByteBuffer getBufferWithoutPadding(ByteBuffer buffer, int width, int rowStride, int times,boolean isVbuffer){if(width == rowStride) return buffer;  //没有buffer,不用处理。int bufferPos = buffer.position();int cap = buffer.capacity();byte []byteArray = new byte[times*width];int pos = 0;//对于y平面,要逐行赋值的次数就是height次。对于uv交替的平面,赋值的次数是height/2次for (int i=0;i<times;i++) {buffer.position(bufferPos);//part 1.1 对于u,v通道,会缺失最后一个像u值或者v值,因此需要特殊处理,否则会crashif(isVbuffer && i==times-1){width = width -1;}buffer.get(byteArray, pos, width);bufferPos+= rowStride;pos = pos+width;}//nv21数组转成buffer并返回ByteBuffer bufferWithoutPaddings=ByteBuffer.allocate(byteArray.length);// 数组放到buffer中bufferWithoutPaddings.put(byteArray);//重置 limit 和postion 值否则 buffer 读取数据不对bufferWithoutPaddings.flip();return bufferWithoutPaddings;}private static byte[] YUV_420_888toNV21(Image image) {int width =  image.getWidth();int height = image.getHeight();ByteBuffer yBuffer = getBufferWithoutPadding(image.getPlanes()[0].getBuffer(), image.getWidth(), image.getPlanes()[0].getRowStride(),image.getHeight(),false);ByteBuffer vBuffer;//part1 获得真正的消除padding的ybuffer和ubuffer。需要对P格式和SP格式做不同的处理。如果是P格式的话只能逐像素去做,性能会降低。if(image.getPlanes()[2].getPixelStride()==1){ //如果为true,说明是P格式。vBuffer = getuvBufferWithoutPaddingP(image.getPlanes()[1].getBuffer(), image.getPlanes()[2].getBuffer(),width,height,image.getPlanes()[1].getRowStride(),image.getPlanes()[1].getPixelStride());}else{vBuffer = getBufferWithoutPadding(image.getPlanes()[2].getBuffer(), image.getWidth(), image.getPlanes()[2].getRowStride(),image.getHeight()/2,true);}//part2 将y数据和uv的交替数据(除去最后一个v值)赋值给nv21int ySize = yBuffer.remaining();int vSize = vBuffer.remaining();byte[] nv21;int byteSize = width*height*3/2;nv21 = new byte[byteSize];yBuffer.get(nv21, 0, ySize);vBuffer.get(nv21, ySize, vSize);//part3 最后一个像素值的u值是缺失的,因此需要从u平面取一下。ByteBuffer uPlane = image.getPlanes()[1].getBuffer();byte lastValue = uPlane.get(uPlane.capacity() - 1);nv21[byteSize - 1] = lastValue;return nv21;}

java NV21toYUV420SemiPlanar 编码保存视频用:

        public byte[] NV21toYUV420SemiPlanar(byte[] nv21, int width, int height) {byte[] yuv420sp = new byte[width * height * 3 / 2];int frameSize = width * height;int i, j;System.arraycopy(nv21, 0, yuv420sp, 0, frameSize); // Y分量直接复制for (i = 0; i < frameSize / 4; i++) {j = i * 2;// NV21的UV分量交替排列,转为NV12需要调换U和V的位置yuv420sp[frameSize + j] = nv21[frameSize + j + 1]; // U分量yuv420sp[frameSize + j + 1] = nv21[frameSize + j]; // V分量}return yuv420sp;}

imageReader获取nv21

plane[0] + plane[2] =NV21;; plane[0] + plane[1] =NV12

Image image = reader.acquireLatestImage();
if (image == null) {return;
}Image.Plane[] planes = image.getPlanes();ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
int ySize = yBuffer.remaining();ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
int vSize = vBuffer.remaining();byte[] nv21_s = new byte[WIDTH*HEIGHT * 3 / 2];try {yBuffer.get(nv21_s, 0, yBuffer.remaining());vBuffer.get(nv21_s, ySize, vBuffer.remaining());imageQueue.put(nv21_s);
} catch (Exception e) {throw new RuntimeException(e);
}image.close();

注:

1.这种方式会缺最后一个像素的U分量或V分量,如果追求完美,对NV21,可以从plane[1]中取出最后的值追加到末尾;对NV12则是在plane[2]中取出最后的值追加到末尾;

2.只适用于图像宽度为8的整数倍的情况,否则因为需要做内存对齐,后面会补0,,导致image.getWidth()< plane.getRowStride(),这就需要对每一行舍去后面多余的0,然后再拼接,效率会低很多。

jni NV12toYUV420SemiPlanar函数:

    public  native byte[] NV12toYUV420SemiPlanar(byte[] data, int w, int h);
extern "C"JNIEXPORT jbyteArray JNICALL Java_com_sandstar_ai_objectdetector_ObjectDetector_NV12toYUV420SemiPlanar(JNIEnv* env, jobject, jbyteArray nv12, jint width, jint height) {jbyte* nv12_bytes = env->GetByteArrayElements(nv12, NULL);jsize nv21_length = env->GetArrayLength(nv12);int frameSize = width * height;std::vector<uint8_t> yuv420sp(nv21_length);std::memcpy(yuv420sp.data(), nv12_bytes, frameSize); // copy Yfor (int i = 0; i < frameSize / 4; ++i) {int j = i * 2;yuv420sp[frameSize + j] = nv12_bytes[frameSize + j + 1]; // copy Vyuv420sp[frameSize + j + 1] = nv12_bytes[frameSize + j]; // copy U}env->ReleaseByteArrayElements(nv12, nv12_bytes, 0);// Create a new byte array and put the data into itjbyteArray result = env->NewByteArray(nv21_length);env->SetByteArrayRegion(result, 0, nv21_length, reinterpret_cast<jbyte*>(yuv420sp.data()));return result;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/59924.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

windows安装Scala

Windows安装Scala 下载地址&#xff1a;https://downloads.lightbend.com/scala/2.11.11/scala-2.11.11.zip 解压完成之后 配置环境变量

《Understanding Black-box Predictions via Influence Functions》笔记

[1] 通过升权&#xff08; 2.1 \S 2.1 2.1&#xff09;、扰动&#xff08; 2.2 \S 2.2 2.2&#xff09;两种方式研究某个 training point z ( x , y ) z(x,y) z(x,y) 对&#xff08;优化后的&#xff09;模型参数 θ ^ \hat\theta θ^、模型在某个 test point z test ( …

kafka+Kraft模式集群+安全认证

Kraft模式安全认证 前章内容聊到了Kafka的Kraft集群的配置及使用。本篇再来说说kafka的安全认证方面的配置&#xff0c;。 Kafka提供了多种方式来进行安全认证&#xff0c;包括身份认证、授权和加密传输。一些常用的Kafka安全认证方式&#xff1a; SSL/TLS&#xff1a;使用S…

Docker技术--Docker镜像管理

1.Docker镜像特性 ①.镜像创建容器的特点 Docker在创建容器的时候需要指定镜像,每一个镜像都有唯一的标识:image_id,也可也使用镜像名称和版本号做唯一的标识,如果不指定版本号,那么默认使用的是最新的版本标签(laster)。 ②.镜像分层机制 Docker镜像是分层构建的,并通过…

科学干、科学管、科学抓质量讲座笔记

讲座来源&#xff1a;任占勇老师分享 航空工业技术研究所 文章目录 1. 质量的发展质量发展的阶段&#xff1a;2. 质量问题的类型3. 设计和制造的关系4. 质量谁负责&#xff1f;5. 质量&#xff1f;6.抓、干、管&#xff1f;6.1 抓&#xff1a;全员的质量保证能力建设&#xff0…

【UniApp开发小程序】小程序首页完善(滑到底部数据翻页、回到顶端、基于回溯算法的两列数据高宽比平衡)【后端基于若依管理系统开发】

文章目录 说明细节一&#xff1a;首页滑动到底部&#xff0c;需要查询下一页的商品界面预览页面实现 细节二&#xff1a;当页面滑动到下方&#xff0c;出现一个回到顶端的悬浮按钮细节三&#xff1a;商品分列说明优化前后效果对比使用回溯算法实现ControllerService回溯算法 优…

使用 Netty 实现群聊功能的步骤和注意事项

文章目录 前言声明功能说明实现步骤WebSocket 服务启动Channel 初始化HTTP 请求处理HTTP 页面内容WebSocket 请求处理 效果展示总结 前言 通过之前的文章介绍&#xff0c;我们可以深刻认识到Netty在网络编程领域的卓越表现和强大实力。这篇文章将介绍如何利用 Netty 框架开发一…

LeetCode——回溯篇(二)

刷题顺序及思路来源于代码随想录&#xff0c;网站地址&#xff1a;https://programmercarl.com 目录 131. 分割回文串 93. 复原 IP 地址 78. 子集 90. 子集 II 491. 递增子序列 131. 分割回文串 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个…

基于非洲秃鹫算法优化的BP神经网络(预测应用) - 附代码

基于非洲秃鹫算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于非洲秃鹫算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.非洲秃鹫优化BP神经网络2.1 BP神经网络参数设置2.2 非洲秃鹫算法应用 4.测试结果&#xff1a;5…

实现带头双向循环链表

&#x1f308;带头双向循环链表 描述&#xff1a;一个节点内包含两个指针&#xff0c;一个指向上一个节点&#xff0c;另一个指向下一个节点。哨兵位指向的下一个节点为头节点&#xff0c;哨兵位的上一个指向尾节点。 结构优势&#xff1a;高效率找尾节点&#xff1b;高效率插入…

度矩阵、邻接矩阵

度矩阵&#xff08;degree matrix&#xff09; 度矩阵是对角阵&#xff0c;对角上的元素为各个顶点的度&#xff0c;顶点vi的度表示和该顶点相关联的变得数量。 在无向图中&#xff0c;顶点vi的度d(vi)N(i)&#xff08;即与顶点相连的边的数目&#xff09;有向图中&#xff0…

【力扣】55、跳跃游戏

var canJump function(nums){let cover 0;for(let i0;i<nums.length;i){if(i<cover){cover Math.max(nums[i]i,cover);if(cover >nums.length-1){return true;}}}}

stm32之DS18B20

DS18B20与stm32之间也是通过单总线进行数据的传输的。单总线协议在DHT11中已经介绍过。虽说这两者外设都是单总线&#xff0c;但时序电路却很不一样&#xff0c;DS18B20是更为麻烦一点的。 DS18B20 举例&#xff08;原码补码反码转换_原码反码补码转换_王小小鸭的博客-CSDN博客…

打开软件报错mfc100u.dll缺失是什么意思?简单式修复mfc100u.dll问题

首先&#xff0c;我们需要了解什么是MFC100U.dll文件以及它的作用。MFC100U.dll是一个Microsoft Foundation Class (MFC)库文件&#xff0c;它是Visual C应用程序开发的一部分。MFC库提供了许多通用的功能&#xff0c;如窗口管理、消息处理等&#xff0c;可以帮助开发者更快速地…

js的es6的特性

ES6特性 类 lass Person{constructor(name) {this.name 小明;}console() {console.log(this.name);} } const man new Man(小明); man.console(); // 小明 模块化 js代码 // 模块 变量 export let a 3; // 模块 方法 export function b(){console.log("hello"…

C++中前置++和后置++的详细讲解

参考链接&#xff08;链接讲的很全&#xff09;&#xff1a;C前置和后置的区别 对于迭代器和其他模板对象使用前缀形式 (i) 的自增, 自减运算符.&#xff0c;理由是 前置自增 (i) 通常要比后置自增 (i) 效率更高。 class Age { public: Age& operator() //前置 {…

fastjson-1.2.24-rce(CVE-2017-18349)fastjson-1.2.47-rce(CNVD-2019-22238)

一.fastjson 1.2.24 反序列化导致任意命令执行漏洞(CVE-2017-18349) fastjson在解析json的过程中&#xff0c;支持使用autoType来实例化某一个具体的类&#xff0c;并调用该类的set/get方法来访问属性。通过查找代码中相关的方法&#xff0c;即可构造出一些恶意利用链 影响范围…

Ansible学习笔记2

Ansible是Python开发的自动化运维工具&#xff0c;集合了众多运维工具&#xff08;Puppet、cfengine、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置&#xff0c;批量程序部署、批量运行命令等功能。 特点&#xff1a; 1&#xff09;部署简单&#xff…

基于金枪鱼群算法优化的BP神经网络(预测应用) - 附代码

基于金枪鱼群算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码 文章目录 基于金枪鱼群算法优化的BP神经网络&#xff08;预测应用&#xff09; - 附代码1.数据介绍2.金枪鱼群优化BP神经网络2.1 BP神经网络参数设置2.2 金枪鱼群算法应用 4.测试结果&#xff1a;5…

【Java基础增强】Stream流

1.Stream流 1.1体验Stream流【理解】 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素 把集合中所有以"张"开头的元素存储到一个新的集合 把"张"开头的集合中的长度为3的元素存储到一个新的集合 遍历上一步得…