关于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

相关文章

C#实现将Excel表格转换为图片(JPG/ PNG)

《C#实现将Excel表格转换为图片(JPG/PNG)》Excel表格可能会因为不同设备或字体缺失等问题,导致格式错乱或数据显示异常,转换为图片后,能确保数据的排版等保持一致,下面我们看看如何使用C... 目录通过C# 转换Excel工作表到图片通过C# 转换指定单元格区域到图片知识扩展C# 将 Excel

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

Python实现AVIF图片与其他图片格式间的批量转换

《Python实现AVIF图片与其他图片格式间的批量转换》这篇文章主要为大家详细介绍了如何使用Pillow库实现AVIF与其他格式的相互转换,即将AVIF转换为常见的格式,比如JPG或PNG,需要的小... 目录环境配置1.将单个 AVIF 图片转换为 JPG 和 PNG2.批量转换目录下所有 AVIF 图

详解如何通过Python批量转换图片为PDF

《详解如何通过Python批量转换图片为PDF》:本文主要介绍如何基于Python+Tkinter开发的图片批量转PDF工具,可以支持批量添加图片,拖拽等操作,感兴趣的小伙伴可以参考一下... 目录1. 概述2. 功能亮点2.1 主要功能2.2 界面设计3. 使用指南3.1 运行环境3.2 使用步骤4. 核

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

Tomcat版本与Java版本的关系及说明

《Tomcat版本与Java版本的关系及说明》:本文主要介绍Tomcat版本与Java版本的关系及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat版本与Java版本的关系Tomcat历史版本对应的Java版本Tomcat支持哪些版本的pythonJ