关于libyuv格式转换、图像裁剪说明

2023-12-14 18:10

本文主要是介绍关于libyuv格式转换、图像裁剪说明,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

项目源代码https://github.com/liluojun/PlayVideo

关联文章https://blog.csdn.net/hjt505694246/article/details/105046233Android硬编、硬解h264

https://blog.csdn.net/hjt505694246/article/details/105047729FFmpeg解码裸H264数据

         Android相机输出的是yuv数据、yuv数据格式太多了如420p、420sp等,我们经常会需要对yuv数据做处理,最原始的使用java for循环的方式耗时太多不合算,libyuv是由google开源的一个针对yuv数据处理的库,其效率比使用java处理的方式快太多了,故比较推荐使用。

public class NativeMethod {public native void nv21ToI420(byte[] src, byte[] dst, int w, int h, byte[] y, byte[] u, byte[] v);public native void nv21ToNv12(byte[] src, byte[] dst, int w, int h, byte[] y, byte[] u, byte[] v);public native void nv21CutterToI420(byte[] src, byte[] dst, int cutter_w, int cutter_h, int w, int h, byte[] y, byte[] u, byte[] v);public native void nv21CutterToNv12(byte[] src, byte[] dst, int cutter_w, int cutter_h, int w, int h, byte[] y, byte[] u, byte[] v);
}

我在项目中提供了4个方法示例前两个是nv21转420p和420sp,后两个是转的过程中做出裁剪。

参数说明:byte[] src 源数据

                  byte[] dst转换后的输出数据

                  int cutter_w裁剪的宽度

                  int cutter_h裁剪的高度

                  int w原宽度

                  int h原高度

                 byte[] y, byte[] u, byte[] v裁剪后yuv三个分量的数据,由于我用的是yuv渲染故需要这些值,没需求的可以不用理会。

jni层代码

#define  LOGE(...) __android_log_print(ANDROID_LOG_ERROR,"ffmpeg",__VA_ARGS__)
#ifndef _Included_media_jni_NativeMethod
#define _Included_media_jni_NativeMethod
#ifdef __cplusplus
extern "C" {
#include "libyuv.h"
#include <android/log.h>
#include "media_jni_NativeMethod.h"
#endif
void releaseByteArray(JNIEnv *env, jbyteArray array, uint8_t *elems, jint mode) {env->ReleaseByteArrayElements(array, (jbyte *) elems, mode);env->DeleteLocalRef(array);
}
/** Class:     media_jni_NativeMethod* Method:    nv21ToI420* Signature: ([B[BII)V*/
JNIEXPORT void JNICALL Java_media_jni_NativeMethod_nv21ToI420(JNIEnv *env, jobject job, jbyteArray src, jbyteArray dst, jint w, jint h, jbyteArray y,jbyteArray u, jbyteArray v) {uint8_t *srcArray = (uint8_t *) env->GetByteArrayElements(src, NULL);uint8_t *dstArray = (uint8_t *) env->GetByteArrayElements(dst, NULL);uint8_t *yArray = (uint8_t *) env->GetByteArrayElements(y, NULL);uint8_t *uArray = (uint8_t *) env->GetByteArrayElements(u, NULL);uint8_t *vArray = (uint8_t *) env->GetByteArrayElements(v, NULL);jint uvW = w >> 1;jint ySize = w * h;jint uSize = (uvW) * (h >> 1);uint8_t *y_src = srcArray;uint8_t *uv_src = srcArray + ySize;uint8_t *y_dst = dstArray;uint8_t *u_dst = dstArray + ySize;uint8_t *v_dst = dstArray + ySize + uSize;libyuv::NV21ToI420(y_src, w, uv_src, w, y_dst, w, u_dst, uvW, v_dst, uvW, w, h);memcpy(yArray, y_dst, ySize);memcpy(uArray, u_dst, (w * h) >> 2);memcpy(vArray, v_dst, (w * h) >> 2);//I420旋转方法注释但不能删除
//    yuv.libyuv::I420Rotate(y_tran, w, u_tran, w >> 1, v_tran, w >> 1, y_dst, h, u_dst, h >> 1, v_dst,
//                       h >> 1, h, w, yuv.libyuv::kRotate270);releaseByteArray(env, src, srcArray, 0);releaseByteArray(env, dst, dstArray, 0);releaseByteArray(env, y, yArray, 0);releaseByteArray(env, v, vArray, 0);releaseByteArray(env, u, uArray, 0);
} ;/** Class:     media_jni_NativeMethod* Method:    nv21ToNv12* Signature: ([B[BII)V*/
JNIEXPORT void JNICALL Java_media_jni_NativeMethod_nv21ToNv12(JNIEnv *env, jobject job, jbyteArray src, jbyteArray dst, jint w, jint h, jbyteArray y,jbyteArray u, jbyteArray v) {LOGE("111");uint8_t *srcArray = (uint8_t *) env->GetByteArrayElements(src, 0);uint8_t *dstArray = (uint8_t *) env->GetByteArrayElements(dst, 0);LOGE("222");uint8_t *yArray = (uint8_t *) env->GetByteArrayElements(y, NULL);uint8_t *uArray = (uint8_t *) env->GetByteArrayElements(u, NULL);uint8_t *vArray = (uint8_t *) env->GetByteArrayElements(v, NULL);jint ySize = w * h;jint uvSize = (w >> 1) * (h >> 1);uint8_t *y_src = srcArray;uint8_t *uv_src = srcArray + ySize;uint8_t *u_src = srcArray + ySize;uint8_t *v_src = srcArray + ySize + uvSize;uint8_t *y_dst = dstArray;uint8_t *uv_dst = dstArray + ySize;libyuv::NV21ToI420(y_src, w, uv_src, w, yArray, w, uArray, w >> 1, vArray, w >> 1, w,h);libyuv::I420ToNV12(yArray, w, uArray, w >> 1, vArray, w >> 1, y_dst, w, uv_dst, w, w, h);releaseByteArray(env, src, srcArray, 0);releaseByteArray(env, dst, dstArray, 0);releaseByteArray(env, y, yArray, 0);releaseByteArray(env, v, vArray, 0);releaseByteArray(env, u, uArray, 0);
} ;
/** Class:     media_jni_NativeMethod* Method:    nv21CutterToI420* Signature: ([B[BIIII)V*/
JNIEXPORT void JNICALL Java_media_jni_NativeMethod_nv21CutterToI420(JNIEnv *env, jobject job, jbyteArray src, jbyteArray dst, jint cw, jint ch, jint w,jint h, jbyteArray y,jbyteArray u, jbyteArray v) {uint8_t *srcArray = (uint8_t *) env->GetByteArrayElements(src, 0);uint8_t *dstArray = (uint8_t *) env->GetByteArrayElements(dst, 0);jbyteArray transitJbyteArray = env->NewByteArray(w * h * 3 / 2);uint8_t *transitArray = (uint8_t *) env->GetByteArrayElements(transitJbyteArray, 0);uint8_t *yArray = (uint8_t *) env->GetByteArrayElements(y, NULL);uint8_t *uArray = (uint8_t *) env->GetByteArrayElements(u, NULL);uint8_t *vArray = (uint8_t *) env->GetByteArrayElements(v, NULL);jint ySize = w * h;jint startx = (w - cw) / 2;jint starty = (h - ch) / 2;jint uvSize = (w >> 1) * (h >> 1);uint8_t *y_src = srcArray;uint8_t *uv_src = srcArray + ySize;uint8_t *y_transit = transitArray;uint8_t *u_transit = transitArray + ySize;uint8_t *v_transit = transitArray + ySize + uvSize;uint8_t *y_dst = dstArray;uint8_t *u_dst = dstArray + (cw * ch);uint8_t *v_dst = dstArray + (cw * ch) + ((cw * ch) >> 2);libyuv::NV21ToI420(y_src, w, uv_src, w, y_transit, w, u_transit, w >> 1, v_transit, w >> 1, w,h);libyuv::ConvertToI420(transitArray, ySize + uvSize, y_dst, cw, u_dst, cw >> 1,v_dst, cw >> 1,startx, starty, w, h, cw, ch, libyuv::kRotate0, libyuv::FOURCC_I420);memcpy(yArray, y_dst, cw * ch);memcpy(uArray, u_dst, (cw * ch) >> 2);memcpy(vArray, v_dst, (cw * ch) >> 2);releaseByteArray(env, transitJbyteArray, transitArray, 0);releaseByteArray(env, src, srcArray, 0);releaseByteArray(env, dst, dstArray, 0);releaseByteArray(env, y, yArray, 0);releaseByteArray(env, v, vArray, 0);releaseByteArray(env, u, uArray, 0);
} ;/** Class:     media_jni_NativeMethod* Method:    nv21CutterToNv12* Signature: ([B[BIIII)V*/
JNIEXPORT void JNICALL Java_media_jni_NativeMethod_nv21CutterToNv12(JNIEnv *env, jobject job, jbyteArray src, jbyteArray dst, jint cw, jint ch, jint w,jint h, jbyteArray y,jbyteArray u, jbyteArray v) {uint8_t *srcArray = (uint8_t *) env->GetByteArrayElements(src, 0);uint8_t *dstArray = (uint8_t *) env->GetByteArrayElements(dst, 0);uint8_t *yArray = (uint8_t *) env->GetByteArrayElements(y, NULL);uint8_t *uArray = (uint8_t *) env->GetByteArrayElements(u, NULL);uint8_t *vArray = (uint8_t *) env->GetByteArrayElements(v, NULL);jbyteArray transitJbyteArray = env->NewByteArray(w * h * 3 / 2);uint8_t *transitArray = (uint8_t *) env->GetByteArrayElements(transitJbyteArray, 0);jint ySize = w * h;jint startx = (w - cw) / 2;jint starty = (h - ch) / 2;jint uvSize = (w >> 1) * (h >> 1);uint8_t *y_src = srcArray;uint8_t *uv_src = srcArray + ySize;uint8_t *y_transit = transitArray;uint8_t *u_transit = transitArray + ySize;uint8_t *v_transit = transitArray + ySize + uvSize;uint8_t *y_dst = dstArray;uint8_t *uv_dst = dstArray + (cw * ch);libyuv::NV21ToI420(y_src, w, uv_src, w, y_transit, w, u_transit, w >> 1, v_transit, w >> 1, w,h);libyuv::ConvertToI420(transitArray, ySize + uvSize, yArray, cw, uArray, cw >> 1,vArray, cw >> 1,startx, starty, w, h, cw, ch, libyuv::kRotate0, libyuv::FOURCC_I420);libyuv::I420ToNV12(yArray, cw, uArray, cw >> 1, vArray, cw >> 1, y_dst, cw,uv_dst, cw, cw, ch);releaseByteArray(env, transitJbyteArray, transitArray, 0);releaseByteArray(env, src, srcArray, 0);releaseByteArray(env, dst, dstArray, 0);releaseByteArray(env, y, yArray, 0);releaseByteArray(env, v, vArray, 0);releaseByteArray(env, u, uArray, 0);
} ;
#ifdef __cplusplus
}
#endif
#endif以上就是jni层全部的代码基本上只涉及到数据转换和libyuv库的调用没啥太不好理解的地方。里面有注释旋转的代码有兴趣或者需求的童鞋可以恢复过来玩一玩。

这是yuv jni的目录。

这篇关于关于libyuv格式转换、图像裁剪说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/493507

相关文章

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

log4j2相关配置说明以及${sys:catalina.home}应用

${sys:catalina.home} 等价于 System.getProperty("catalina.home") 就是Tomcat的根目录:  C:\apache-tomcat-7.0.77 <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n" /> 2017-08-10

android应用中res目录说明

Android应用的res目录是一个特殊的项目,该项目里存放了Android应用所用的全部资源,包括图片、字符串、颜色、尺寸、样式等,类似于web开发中的public目录,js、css、image、style。。。。 Android按照约定,将不同的资源放在不同的文件夹中,这样可以方便的让AAPT(即Android Asset Packaging Tool , 在SDK的build-tools目

easyui同时验证账户格式和ajax是否存在

accountName: {validator: function (value, param) {if (!/^[a-zA-Z][a-zA-Z0-9_]{3,15}$/i.test(value)) {$.fn.validatebox.defaults.rules.accountName.message = '账户名称不合法(字母开头,允许4-16字节,允许字母数字下划线)';return fal

PDF 软件如何帮助您编辑、转换和保护文件。

如何找到最好的 PDF 编辑器。 无论您是在为您的企业寻找更高效的 PDF 解决方案,还是尝试组织和编辑主文档,PDF 编辑器都可以在一个地方提供您需要的所有工具。市面上有很多 PDF 编辑器 — 在决定哪个最适合您时,请考虑这些因素。 1. 确定您的 PDF 文档软件需求。 不同的 PDF 文档软件程序可以具有不同的功能,因此在决定哪个是最适合您的 PDF 软件之前,请花点时间评估您的

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };

Verybot之OpenCV应用一:安装与图像采集测试

在Verybot上安装OpenCV是很简单的,只需要执行:         sudo apt-get update         sudo apt-get install libopencv-dev         sudo apt-get install python-opencv         下面就对安装好的OpenCV进行一下测试,编写一个通过USB摄像头采

Adblock Plus官方规则Easylist China说明与反馈贴(2015.12.15)

-------------------------------特别说明--------------------------------------- 视频广告问题:因Adblock Plus的局限,存在以下现象,优酷、搜狐、17173黑屏并倒数;乐视、爱奇艺播放广告。因为这些视频网站的Flash播放器被植入了检测代码,而Adblock Plus无法修改播放器。 如需同时使用ads