当前位置: 首页 > news >正文

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;
}

相关文章:

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

目录 java imagereader编码保存 java NV21toYUV420SemiPlanar 编码保存视频用&#xff1a; imageReader获取nv21 jni NV12toYUV420SemiPlanar函数&#xff1a; 代码来自博客&#xff1a; 【Android Camera2】彻底弄清图像数据YUV420_888转NV21问题/良心教学/避坑必读!_yuv…...

那些你不得不知道的HTML知识点

目录 1、行内元素有哪些&#xff1f;块级元素有哪些&#xff1f; 空(void)元素有哪些&#xff1f;2、页面导入样式时&#xff0c;使用link和import有什么区别&#xff1f;3、title与h1的区别、b与strong的区别、i与em的区别&#xff1f;3.1 title与h1的区别&#xff1a;3.2 b与…...

如何复制主播的性格(此乃广告文)

上面这份ppt写于Fay开源之前。当然&#xff0c;以现在的认知再去评价当时的设计&#xff0c;会发现有诸多的不严谨&#xff0c;甚至缺憾。比如&#xff0c;以单层的网络结构肯定无法拟合人性这个复杂的东西&#xff0c;人性也不是只受已知的几个参数所作用。但我现在想说的是&a…...

【ES6】—【新特性】—Symbol详情

一、一种新的原始数据类型 定义&#xff1a;独一无二的字符串 二、 声明方式 1. 无描述声明 let s1 Symbol() let s2 Symbol() console.log(s1, s2) // Symbol() Symbol() console.log(s1 s2) // falsePS: Symbol 声明的值是独一无二的 2. 有描述的声明 let s1 Symb…...

openresty安装与网站发布

文章目录 安装依赖下载安装包解压安装包安装启动nginx配置环境变量配置开机启动发布静态网站 OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台&#xff0c;其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动…...

创建延时队列、springboot配置多个rabbitmq

创建延时队列 queue.file_delay_destroy x-dead-letter-exchange: exchange.file_delay_destroy x-message-ttl: 259200000 259200000为3天,1000为1秒创建普通队列 queue.file_destroy创建普通交换机 exchange.file_delay_destroytype选择fanout 交换机绑定普通队列 (图中…...

在kaggle中用GPU使用CGAN生成指定mnist手写数字

文章目录 1项目介绍2参考文章3代码的实现过程及对代码的详细解析独热编码定义生成器定义判别器打印我们的引导信息模型训练迭代过程中生成的图片损失函数的变化 4总结5 模型相关的文件 1项目介绍 在GAN的基础上进行有条件的引导生成图片cgan 2参考文章 GAN实战之Pytorch 使用…...

【NI USRP】哪些 USRP 设备支持全双工,哪些支持半双工?

译者 东枫电子科技 设备构成 NI USRPEttus USRPUSRP-2900B200USRP-2901B210USRP-2920N210 WBXUSRP-2921N210 XCVR 2450USRP-2922N210 SBXUSRP-2930N210 WBX GPSDOUSRP-2932N210 SBX GPSDOUSRP-2940RX310 WBX (x2)USRP-2942RX310 SBX (x2)USRP-2943RX310 CBX (x2)U…...

不拼花哨,只拼实用:unittest指南,干货为王!

Python为开发者提供了内置的单元测试框架 unittest&#xff0c;它是一种强大的工具&#xff0c;能够有效地编写和执行单元测试。unittest 提供了完整的测试结构&#xff0c;支持自动化测试的执行&#xff0c;能够对测试用例进行组织&#xff0c;并且提供了丰富的断言方法。最终…...

mysql 获取json数组中某个字段根据下标

MySQL获取JSON数组中某个字段根据下标 在MySQL中&#xff0c;JSON数据类型可以方便地存储、操作和查询包含复杂结构的数据。当我们需要从JSON数组中获取某个字段时&#xff0c;可以使用MySQL的JSON函数来实现。 1. JSON数据类型简介 JSON&#xff08;JavaScript Object Nota…...

深入理解Redis缓存穿透、击穿、雪崩及解决方案

深入理解Redis缓存穿透、击穿、雪崩及解决方案 一、简介Redis 简介缓存作用与优化 二、缓存问题的分类缓存穿透缓存击穿缓存雪崩 三、缓存穿透的解决方案布隆过滤器缓存空对象接口层校验 四、缓存击穿的解决方案互斥锁热点数据提前加载 五、缓存雪崩的解决方案增加缓存容错能力…...

java八股文面试[java基础]——字节码

字节码技术应用 字节码技术的应用场景包括但不限于AOP&#xff0c;动态生成代码&#xff0c;接下来讲一下字节码技术相关的第三方类库&#xff0c;第三方框架的讲解是为了帮助大家了解字节码技术的应用方向&#xff0c;文档并没有对框架机制进行详细分析&#xff0c;有兴趣的可…...

新能源汽车技术的最新进展和未来趋势

文章目录 电池技术的进步智能驾驶与自动驾驶技术充电基础设施建设新能源汽车共享和智能交通未来趋势展望结论 &#x1f389;欢迎来到AIGC人工智能专栏~探索新能源汽车技术的最新进展和未来趋势 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客…...

知虾shopee数据分析工具:shopee出单的商机利器

当今数字化时代&#xff0c;数据已经成为商业成功的关键要素之一。而Shopee作为东南亚最大的电商平台之一&#xff0c;其强大的数据分析工具正为商家提供了宝贵的市场洞察和决策支持。本文将深入探讨Shopee数据分析工具如何帮助商家抓住商机并取得成功。 洞察消费者需求&#x…...

python——ydata-profiling介绍与使用

ydata-profiling介绍与使用 ydata-profiling的作用ydata-profiling的安装与简单使用ydata-profiling的结果结构 ydata-profiling的实际应用场景1. 数据集比较2. 时间序列报告3. 对大型数据集进行概要分析4. 处理敏感数据5. 自定义报告的外观 ydata-profiling的作用 ydata-prof…...

(纯c)数据结构之------>链表(详解)

目录 一. 链表的定义 1.链表的结构. 2.为啥要存在链表及链表的优势. 二. 无头单向链表的常用接口 1.头插\尾插 2.头删\尾删 3.销毁链表/打印链表 4.在pos位置后插入一个值 5.消除pos位置后的值 6.查找链表中的值并且返回它的地址 7.创建一个动态开辟的结点 三.顺序表与链表…...

postman接口自动化测试框架实战!

什么是自动化测试 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试&#xff0c;模拟人去操作软件界面&#xff0c;把人从简单重复的劳动中解放出来。 本质是用代码去测试另一段代码&#xff0c;属于一种软件开发工作&#xff0c;已经开发完成的用…...

Apache Doris 入门教程35:多源数据目录

概述 多源数据目录&#xff08;Multi-Catalog&#xff09;功能&#xff0c;旨在能够更方便对接外部数据目录&#xff0c;以增强Doris的数据湖分析和联邦数据查询能力。 在之前的 Doris 版本中&#xff0c;用户数据只有两个层级&#xff1a;Database 和 Table。当我们需要连接…...

响应式web-PC端web与移动端web(H5)兼容适配 选型方案

背景 项目需要&#xff0c;公司已经有一套PC端web&#xff0c;需要做一套手机端浏览器可用的&#xff0c;但是又想兼容pc端&#xff0c;适配的web项目。 以下是查阅到响应布局现成的开源模版。根据自己技术栈&#xff0c;vue2,js来搜索相关的开源项目。 RuoYi 使用若依快速…...

Redis持久化之RDB解读

目录 什么是RDB 配置位置参数解读 如何使用 自动触发 手动触发 save bgsave RDBRDB持久化文件的恢复 正常恢复 恢复失败处理方法 RDB优势 RDB 缺点 redis是一个内存数据库,当redis服务器重启,获取电脑重启,数据会丢失,我们可以将redis内存中的数据持久化保存到硬盘…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

中医有效性探讨

文章目录 西医是如何发展到以生物化学为药理基础的现代医学&#xff1f;传统医学奠基期&#xff08;远古 - 17 世纪&#xff09;近代医学转型期&#xff08;17 世纪 - 19 世纪末&#xff09;​现代医学成熟期&#xff08;20世纪至今&#xff09; 中医的源远流长和一脉相承远古至…...