这是我参加8月更文应战的第1天,活动概略检查:8月更文应战

一直对安卓音视频开发有点稠密的爱好,怎样办没有体系的学过相应的知识,只能苦苦的研讨一下rtc是什么意思,借这个更文活动记载一下自己的一点根究。

数组的界说视频根本需求把握的知识点

  • ffmpeg 强壮的音视频处理库,(cpu软编等)
  • me数组函数的使用方法diaCodec 安卓sdk自带的编解码器,(硬编)
  • op人头攒动engles 运用gpu进行图画处理
  • h264,h265 图画编码紧缩算法
  • yuv420p ,nv21 ,yuv_420_888,I420 需求了解的视频编android电子市场码格局
  • yuv和rgb的互相转矩阵
  • pcm,acc 需求了解的音频编码格局
  • camerax,mediaRecorder,audioRecorder 搜集相关的api

音视频人头攒动的读音在安卓中一般就有2种表现形式,一种是播映在线或许本地视频(录制和播映),另一种是直播(推流和拉流),下面咱们首先从视频的搜集到播映全进程来做一下具体的根究。

视频的搜集

  • Camerax的运用

camerax是jetpack中新加的一个相机库,规划的非常好人头攒动的读音,不必像之前camera1和cam数组排序era2运用那么的繁琐,并且是和生命周期绑定,便当开发者处理生命周期。

  1. 增加依托
    implementation "androidx.camera:c矩阵天王amera-camera人体肠道结构图部位称号2:$camerax_version"
implementation "androidx.camera:camera-lifecycle:$camerax_version"
implementation "androandroid手机idx.camera:camera-view:1.0.0-alpha10"
  1. 创立预览布局
    <androidandroid平板电脑价格x.camera.vandroid是什么手机牌子iew.Pffmpeggultool下载reviewVie矩阵的迹w
android:id="@+id/view矩阵等价Finder"
app:layout_con矩阵相乘怎样算straintTop_toTopOf="parent"
app:layout_constrain闰土刺猹图片tBottom_tffmpeg羞耻柱事情oTopOf="@+id/camera_capt数组排序ure_button"
android:layout_矩阵类似width="match_parent"
android:layout_height="0dp"/>

3.获取相机权限(略)
4.翻开相机,获取预览

@SuppressLint("RestrictedApi")
private fun startCamera() {
initMediaCodec(480,640,20)
val cameraProviderFuture =矩阵相乘怎样算 ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runna人体成分剖析ble {
bi闰土刺猹ndImage(cameraProviderFuture)
}, ContextCompat.getMainExeRTCcutor(this))
}
private fun bindImage(cameraProviderFuture:ListenableFutu数组函数的使用方法re<Proces矩阵等价sCameraProvider>)闰土刺猹 {
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
preview = Preview.Builder().让天秤倒追的星座build()
va矩阵游戏l cameraSelecto矩阵类似r =CameraSelector.Builder().requireLensFacingffmpeg装置(CameraSelec数组的界说tor.LENS_FACING_BACK).build()
val imageAnalysis = Imag矩阵类似eAnalysis.Builder()
.setTargetResolution(Size(1280, 720))
.setBackpresffmpeggultool下载sureStrategy数组初始化(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
imageAnalysis.setAnalyzer(cameraExecutor, ImageAnalysis.Analyzer { image ->
Thread {
val data =ImageUtils.getDataFromImage2(image,ImageUtils.COLffmpeg指令详解OR_FormatI420)
val out = FileOutputStream(File(Environment.getExternalS闰土刺猹图片torageDirectory(),"hhh.yuv"ffmpeggultool下载))
o矩阵天王ut.write(data)
imageffmpeg.dll找不到是什么状况.close();
}.start()矩阵的秩
})
try {
camRTCeraProvi让天秤倒追的星座der.unbindAll()
camera =android/yunos cameraProvider.bindToLifecycle(this, cameraSelector, imFFmpegageAnalysis, preview)
previeandroid体系w?人头攒动的读音.setSurfaceProvider(viewFinder矩阵天王.creaAndroidteSurfaceProvider(camera?.cameraInfo))
} catch (exc: Exception) {
Log.eFFmpeg(TAG, "Use case binding failed",FFmpeg exc)
}
}

5.获取视频录制数据
运用ImageAnandroid的drawable类alysi人体成分剖析s的setAnalyzer方法能够获取到录制的视频原始数据,默许的视频数据格局是
yuv_420_888,这种数据格局是不能直接运用ffmepeg或许mediacodec编码的,需求转成i420格局,
对此我花了矩阵乘法九牛二虎之力去研讨了一下这种视频格局。

yuv_420_888是YCbCr的泛化格局,能够标明任何4:2:0的平面和半平面格局,每个重量用8 bits 标明。带有这种格局的图画运用3个独立的Buffe闰土刺猹r标明,每一个Buffer标明一个颜色平面(矩阵的逆Plane),除了Buffer外,它还供给rowStride、pixelStride来描绘对应的Plane。

按照官方的说法,第一个平数组面满是y数据,第2个平面包含一切的u数据,第3个平面包含一切的v数据,咱们只需求解分出原始数据中的yuv重量在按照i420的摆放和比例就能够得到咱们究竟能够运用的数据了,但是实际解析进程中我发现了原始数据中有比较多的填充数据,android手机按照网上的说法是用作对齐处理,这里我也没有深化了解,假设有知道的老铁能够在谈论区奉告一下。我依Android照这个思路大致写了一个转化的东西类。

public cl矩阵工厂怎样开ass ImageUti矩阵ls {
private static final boolean VERBOSE = true;
private static final String TAG = "ImageUtils";
public static final in数组公式t COLOR_Form人体成分剖析atI420 = 1;
public static final int COLOR_FormatNV21 = 2;
public static boolean isImageFormatSupffmpeg.dll找不到是什么状况ported(ImageProxy imFFmpegage) {
int format = image.getFormat(android的drawable类);
switch (format) {
case ImageFormat.YUV_420_888:
case ImageFormat.NV21:
case ImageFormat.YV12:数组函数的使用方法
return true;
}
return false;
}
public stat矩阵天王ic byte[]数组的界说 getDataFromImage2(ImageProxy image, int colorFormat) {
if (colorFormat != COLOR_FormatI420 &aandroid是什么手机牌子mp;& colorFormat != COffmpeg安卓版别下载LOR_FormatNV21) {
throw new IllegalArgumentException("only support COLOR_FormatI420 " + "and COL人头攒动的读音OR_FormatNV21");
}
if (!isImageFormatSupported(image)) {
throw new RuntimeException("can't convert Image to byte array, format " + image.getFormffmpeg是什么意思at());
}
Rect crop = image.getCropRect();
inffmpeg从入门到通晓t format = iandroid手机mage.getFormat()人体肠道结构图部位称号;// 888
int width = crop.width();
in矩阵天王t height = crop.height();
ImageProxy.PlaneProxy[] planes = image.getPlanes();
int yRe = planes[0].getBuffer().remaining();
int uvRe = planes[1].getBuffer().remaining();
int vuRe = planes[2].getBuffer().reandroid手机mainin人头攒动的读音g();
int yStride = planes[0].getRowStride();矩阵乘法
int uvStride = planes[1].getRowStride();
int vuStride = planes[2].getRowStride();
int yLength = yRe - (yStride-width)*(heigffmpeg安卓版别下载ht-1);
int uvLength = uvRe - (数组指针uvStride-width)*(height/2-1);
int vuLength数组函数的使用方法 = vuRe - (vuStride-width人头攒动的近义词)*(height/2-1);
byte[] data = new byte[width * height * 12 /8];
byte[] yData = new byte[yLength];
byte[] uData = new byte[uvLength/2+1];
by矩阵类似te[] vData = new byte[vuLength/2 + 1];
//uv 占 2分之1
byte[] uvData = new byt人体成分剖析e[uvLength];
/ffmpeg羞耻柱事情/vu 占 2分之1
byte[ffmpeg安卓版别下载] vuData = new byte[vuLength];
byte[] rowData = new byte[planes[0].getRowStride()];
for (int数组指针 i = 0; i < planes.length; i++) {
ImageProxy.PlaneProxy p数组的界说lane = planes[i];
ByteBuffer人头攒动的近义词 buffer = plane.getBuffer();
int offset = 0;
Log.e("getDataFromImage",plane.getPixelStride() + "");
buffrtc是什么意思e矩阵天王r.position(0);
int col = height /人体成分剖析 plane.getPixelSt矩阵的迹ride();
if(plane.getPixelStride() == 1){ //原矩阵是人体肠道结构图部位称号i420
for (int j = 0; j < col; j++) {
if(i == 0){ffmpeg从入门到通晓 //y
if(j < height/plane.getPixelStride() -1){
buffer.get(yData,offset,width);
}else {
buffer.矩阵天王get(yData,offset,yRe - (plane.getRowStride() * (heffmpeg从入门到通晓ight-1)));
}
offset +=width;
if(j < height/planandroid下载装置e.getPixelStride()-1){
buffer.position(buffer.position()+ plane.getR人头攒动owStandroid下载ride() - width);
}
}else if(i == 1){ //ffmpeg羞耻柱事情uv
buffer.get(uData,offset,width);
offset人头攒动 +=width;
if(j < height/plane.getPixelStride() -1){
buffer.position(buffer.position()+ plane.getRowStride() - width);
}
}else { // vu
buffer.get(vData,offset,width);矩阵的迹
offset +=android电子市场width;
if(j < height/plane.getPixelStride()-1){ffmpeg羞耻柱事情
buff数组初始化er.position(buffer.position()+ plane.getRowStride() - wFFmpegidth);
}
}
}
}else { // 原矩阵是 nv12 或许 nv21
for (iffmpeg装置nt j = 0; j < col; j+闰土刺猹图片+) {
if(i == 0){ //y
if(j < height/plane.getPixelStride()矩阵的迹 -1){
buf人体承受的最大电压fer.get(yData,offse人体肠道结构图部位称号t,width);
}else {
buffer.get(yDataRTC,offset,yRe - (plane.getRowStride() * ( height/plane.getPixelStride() -1)));
}
offset +=width;
if(j < h闰土刺猹eight/plane.getPixelStride() -1){
buffer.position(buffer.position()+ plane.getRowStride() - width);
}
}else if(i == 1){ //uv
if(j < heig数组指针ht/plane.getPixelStride() -1){
buffer.get(uvData,offset,width);
}else {
buffer.get(uvData,offse人头攒动的读音t,uvRe - (plane.getRowStridffmpeg的装置和使用教程e() * (height/plane.getPixelStride()-1)));
}
offset +=width;
if(j < height/p人头攒动lane.getPixelStride() -1){
buandroid平板电脑价格ffer.position(buffer.position()+ plane.getRowStride() - width);
}
}else { // vu
if(j < height/p闰土刺猹lane.getPixelStride() -1){
buffer.get(vuData,offs矩阵游戏et,w矩阵天王idth);
}else {
buffer.get(vuData,offset,vuRe - (plane.getRowStride() * (height/plane.getPixelStride()-1)));
}
offset +=widthandroid/yunos;
if(j < heigandroid体系ht/plane.getPixelStride()-1){
buffer.position(buffer.position()+ plane.getRowStride() - width);
}
}
}
}
}
boolean isI420 = image.getPlanes()[1].getPixelStride() == 1;
//ydata矩阵天王 uvdata vudata
//提取 u ,v
if(!isI420){
//
for (int i = 0; i < uvData.length; i+=2) {
uData[i/2] = uvData[i];
}
for (int i = 0; i < vuData.length; i+=2) {
vData[i/2] = uvData[i];
}
Log.e("getDataFromImage",uData.length + "");
Log.e("getDataFromImage",vData.length + "");
}android体系
//拼装 i420
System.arraycopy(yData,0,data,0,yData.length);
Syste矩阵等价m.arraycopy(uData,0,data,yData.人头攒动的读音length,uData.l矩阵的秩ength);
System.arraycopy(vData,0,data,yData.length + uData.length ,vData.length);
return data;
}
}

究竟的效果,解析了一帧,方向和视点能够自己调度一下,色值如同有点问题,明日在研讨一下

android音视频学习开篇

假设播映出现下面的问题,或许就是yuv读写数据出现了问题,需求检查一下byte数组长度

android音视频学习开篇

后边的篇幅再去记载一下学习的进人头攒动的近义词程,再次致敬一下雷神

`