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

安卓Camera2用ImageReader获取NV21源码分析

以前如何得到Camera预览流回调

  • 可以通过如下方法,得到一路预览回调流 Camera#setPreviewCallbackWithBuffer(Camera.PreviewCallback),
  • 可以通过如下方法,设置回调数据的格式,比如 ImageFormat.NV21 Camera.Parameters#setPreviewForma
  • API21开始,android.hardware.Camera 相关API 已经被谷歌废弃,
    当我们切换到Camera2相关后,如何得到一路NV21回调流呢?

如何使用Camera2得到预览流的回调

一般我们使用的方法如下,

private final ImageReader.OnImageAvailableListener mOnImageAvailableListener = reader -> {Image image = reader.acquireNextImage();// do sth with readerimage.close();
};mImageReader = ImageReader.newInstance(mPreviewSize.getWidth(), mPreviewSize.getHeight(),ImageFormat.YUV_420_888, 1);
mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mCameraHandler);
// 看起来是不是跟Camera2拍照很相似,关键在配流时需要添加如下代码
mPreviewRequestBuilder.addTarget(mImageReader.getSurface());

这样我们就可以通过 Image 读取回调的内容,内容是啥呢?

The order of planes in the array returned by Image#getPlanes() is guaranteed such that plane #0 is always Y, plane #1 is always U (Cb), and plane #2 is always V (Cr).

Image#getPlanes 返回三个数组,plane 0 是Y,plane 1 是U (Cb),plane 2 是 V (Cr)
我们可以把他们转给NV21格式,如何转换呢?
可以参考如下答案
stackoverflow camera2-conversion-from-yuv-420-888-to-nv21

是否可以通过ImageReader直接得到NV21回调呢

上面我们设置的是YUV_420_888,是否可以直接改成NV21呢?
不行,在 ImageReader 我们可以看到如下,会直接闪退

if (format == ImageFormat.NV21) { throw new IllegalArgumentException( "NV21 format is not supported")
}

ImageReader数据流回调的流程源码分析

相关数据流源码分析如下

private static void postEventFromNative(Object selfRef) {....if (executor != null && listener != null && isReaderValid) {executor.execute(new Runnable() {@Overridepublic void run() {listener.onImageAvailable(ir);}});}
}// frameworks/base/media/jni/android_media_ImageReader.cpp 中部分源码如下
static struct {jfieldID mNativeContext;jmethodID postEventFromNative;
} gImageReaderClassInfo;
gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID(clazz, "postEventFromNative", "(Ljava/lang/Object;)V");
void JNIImageReaderContext::onFrameAvailable(const BufferItem& /*item*/)
{ALOGV("%s: frame available", __FUNCTION__);bool needsDetach = false;JNIEnv* env = getJNIEnv(&needsDetach);if (env != NULL) {env->CallStaticVoidMethod(mClazz, gImageReaderClassInfo.postEventFromNative, mWeakThiz);} else {ALOGW("onFrameAvailable event will not posted");}if (needsDetach) {detachJNI();}
}// frameworks/native/libs/gui/ConsumerBase.cpp
void ConsumerBase::onFrameAvailable(const BufferItem& item) {CB_LOGV("onFrameAvailable");sp<FrameAvailableListener> listener;{ // scope for the lockMutex::Autolock lock(mFrameAvailableMutex);listener = mFrameAvailableListener.promote();}if (listener != nullptr) {CB_LOGV("actually calling onFrameAvailable");listener->onFrameAvailable(item);}
}// APP 通过 ImageReader 设置 OnImageAvailableListener 回调拿到 android.media.ImageReader
ImageReader.acquireNextImage() 拿到 android.media.Image
public Image acquireNextImage() {// Initialize with reader format, but can be overwritten by native if the image// format is different from the reader format.SurfaceImage si = new SurfaceImage(mFormat);int status = acquireNextSurfaceImage(si);return si;
}
private int acquireNextSurfaceImage(SurfaceImage si) {....status = nativeImageSetup(si);....
}// frameworks.base\media\jni\android_media_ImageReader.cpp
{"nativeImageSetup",       "(Landroid/media/Image;)I",   (void*)ImageReader_imageSetup }static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image){JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer();BufferItem* buffer = ctx->getBufferItem();status_t res = bufferConsumer->acquireBuffer(buffer, 0);ctx->returnBufferItem(buffer);
}List<BufferItem*> mBuffers;
void JNIImageReaderContext::returnBufferItem(BufferItem* buffer) {buffer->mGraphicBuffer = nullptr;mBuffers.push_back(buffer);
}
frameworks/native/libs/gui/include/gui/BufferItem.handroid.media.ImageReader$SurfaceImage
@Override
public Plane[] getPlanes() {throwISEIfImageIsInvalid();if (mPlanes == null) {// mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat);mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat);}// Shallow copy is fine.return mPlanes.clone();
}
{"nativeCreatePlanes",      "(IIJ)[Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",  (void*)Image_createSurfacePlanes },static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,int numPlanes, int readerFormat, uint64_t ndkReaderUsage){jobjectArray surfacePlanes = env->NewObjectArray(numPlanes, gSurfacePlaneClassInfo.clazz, /*initial_element*/NULL);LockedImage lockedImg = LockedImage();    Image_getLockedImage(env, thiz, &lockedImg, ndkReaderUsage); // 把前面的 BufferItem 转为 LockedImagefor (int i = 0; i < numPlanes; i++) {if (!Image_getLockedImageInfo(env, &lockedImg, i, halReaderFormat,&pData, &dataSize, &pixelStride, &rowStride)) {return NULL;}byteBuffer = env->NewDirectByteBuffer(pData, dataSize);// Finally, create this SurfacePlane.jobject surfacePlane = env->NewObject(gSurfacePlaneClassInfo.clazz,gSurfacePlaneClassInfo.ctor, thiz, rowStride, pixelStride, byteBuffer);env->SetObjectArrayElement(surfacePlanes, i, surfacePlane);}}
static void ImageReader_classInit(JNIEnv* env, jclass clazz) {gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>","(Landroid/media/ImageReader$SurfaceImage;IILjava/nio/ByteBuffer;)V");
}static bool Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,int32_t writerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {status_t res = getLockedImageInfo(buffer, idx, writerFormat, base, size,pixelStride, rowStride);if (res != OK) {jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException","Pixel format: 0x%x is unsupported", buffer->flexFormat);return false;}return true;
}// frameworks/base/media/jni/android_media_Utils.cpp
status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,int fenceFd, LockedImage* outputImage) {...status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop,fenceFd, outputImage);...
}
status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,const Rect& rect, int fenceFd, LockedImage* outputImage) {ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);if (buffer == nullptr || outputImage == nullptr) {ALOGE("Input BufferItem or output LockedImage is NULL!");return BAD_VALUE;}if (isFormatOpaque(buffer->getPixelFormat())) {ALOGE("Opaque format buffer is not lockable!");return BAD_VALUE;}void* pData = NULL;android_ycbcr ycbcr = android_ycbcr();status_t res;int format = buffer->getPixelFormat();int flexFormat = format;if (isPossiblyYUV(format)) {res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);if (res != OK) {ALOGW("lockAsyncYCbCr failed with error %d (format = 0x%x)", res, format);}pData = ycbcr.y;flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;}// lockAsyncYCbCr for YUV is unsuccessful.if (pData == NULL) {res = buffer->lockAsync(inUsage, rect, &pData, fenceFd);if (res != OK) {ALOGE("Lock buffer failed!");return res;}if (isPossibly10BitYUV(format)&& OK == extractP010Gralloc4PlaneLayout(buffer, pData, format, outputImage)) {ALOGV("%s: Successfully locked the P010 image", __FUNCTION__);return OK;}}outputImage->data = reinterpret_cast<uint8_t*>(pData);outputImage->width = buffer->getWidth();outputImage->height = buffer->getHeight();outputImage->format = format;outputImage->flexFormat = flexFormat;outputImage->stride =(ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride);outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__);// Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller,// and cann't be set them here.return OK;
}
status_t getLockedImageInfo(LockedImage* buffer, int idx,int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {ALOGV("%s", __FUNCTION__);LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);ALOGV("%s: buffer: %p", __FUNCTION__, buffer);uint32_t dataSize, ySize, cSize, cStride;uint32_t pStride = 0, rStride = 0;uint8_t *cb, *cr;uint8_t *pData = NULL;int bytesPerPixel = 0;dataSize = ySize = cSize = cStride = 0;int32_t fmt = buffer->flexFormat;bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);fmt = applyFormatOverrides(fmt, containerFormat);switch (fmt) {case HAL_PIXEL_FORMAT_YCbCr_420_888:// Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.if (buffer->width % 2 != 0) {ALOGE("YCbCr_420_888: width (%d) should be a multiple of 2", buffer->width);return BAD_VALUE;}if (buffer->height % 2 != 0) {ALOGE("YCbCr_420_888: height (%d) should be a multiple of 2", buffer->height);return BAD_VALUE;}if (buffer->width <= 0) {ALOGE("YCbCr_420_888: width (%d) should be a > 0", buffer->width);return BAD_VALUE;}if (buffer->height <= 0) {ALOGE("YCbCr_420_888: height (%d) should be a > 0", buffer->height);return BAD_VALUE;}pData =(idx == 0) ?buffer->data :(idx == 1) ?buffer->dataCb :buffer->dataCr;// only map until last pixelif (idx == 0) {pStride = 1;rStride = buffer->stride;dataSize = buffer->stride * (buffer->height - 1) + buffer->width;} else {pStride = buffer->chromaStep;rStride = buffer->chromaStride;dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +buffer->chromaStep * (buffer->width / 2 - 1) + 1;}break;// NV21case HAL_PIXEL_FORMAT_YCrCb_420_SP:// Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.if (buffer->width % 2 != 0) {ALOGE("YCrCb_420_SP: width (%d) should be a multiple of 2", buffer->width);return BAD_VALUE;}if (buffer->height % 2 != 0) {ALOGE("YCrCb_420_SP: height (%d) should be a multiple of 2", buffer->height);return BAD_VALUE;}if (buffer->width <= 0) {ALOGE("YCrCb_420_SP: width (%d) should be a > 0", buffer->width);return BAD_VALUE;}if (buffer->height <= 0) {ALOGE("YCrCb_420_SP: height (%d) should be a > 0", buffer->height);return BAD_VALUE;}cr = buffer->data + (buffer->stride * buffer->height);cb = cr + 1;// only map until last pixelySize = buffer->width * (buffer->height - 1) + buffer->width;cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;pData =(idx == 0) ?buffer->data :(idx == 1) ?cb:cr;dataSize = (idx == 0) ? ySize : cSize;pStride = (idx == 0) ? 1 : 2;rStride = buffer->width;break;case HAL_PIXEL_FORMAT_YV12:// Width and height should be multiple of 2. Wrong dataSize would be returned otherwise.if (buffer->width % 2 != 0) {ALOGE("YV12: width (%d) should be a multiple of 2", buffer->width);return BAD_VALUE;}if (buffer->height % 2 != 0) {ALOGE("YV12: height (%d) should be a multiple of 2", buffer->height);return BAD_VALUE;}if (buffer->width <= 0) {ALOGE("YV12: width (%d) should be a > 0", buffer->width);return BAD_VALUE;}if (buffer->height <= 0) {ALOGE("YV12: height (%d) should be a > 0", buffer->height);return BAD_VALUE;}// Y and C stride need to be 16 pixel aligned.LOG_ALWAYS_FATAL_IF(buffer->stride % 16,"Stride is not 16 pixel aligned %d", buffer->stride);ySize = buffer->stride * buffer->height;cStride = ALIGN(buffer->stride / 2, 16);cr = buffer->data + ySize;cSize = cStride * buffer->height / 2;cb = cr + cSize;pData =(idx == 0) ?buffer->data :(idx == 1) ?cb :cr;dataSize = (idx == 0) ? ySize : cSize;pStride = 1;rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);break;case HAL_PIXEL_FORMAT_YCBCR_P010:if (buffer->height % 2 != 0) {ALOGE("YCBCR_P010: height (%d) should be a multiple of 2", buffer->height);return BAD_VALUE;}if (buffer->width <= 0) {ALOGE("YCBCR_P010: width (%d) should be a > 0", buffer->width);return BAD_VALUE;}if (buffer->height <= 0) {ALOGE("YCBCR_P010: height (%d) should be a > 0", buffer->height);return BAD_VALUE;}if (buffer->dataCb && buffer->dataCr) {pData =(idx == 0) ?buffer->data :(idx == 1) ?buffer->dataCb :buffer->dataCr;// only map until last pixelif (idx == 0) {pStride = 2;rStride = buffer->stride;dataSize = buffer->stride * (buffer->height - 1) + buffer->width * 2;} else {pStride = buffer->chromaStep;rStride = buffer->chromaStride;dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +buffer->chromaStep * (buffer->width / 2);}break;}ySize = (buffer->stride * 2) * buffer->height;cSize = ySize / 2;pStride = (idx == 0) ? 2 : 4;cb = buffer->data + ySize;cr = cb + 2;pData = (idx == 0) ?  buffer->data : (idx == 1) ?  cb : cr;dataSize = (idx == 0) ? ySize : cSize;rStride = buffer->stride * 2;break;case HAL_PIXEL_FORMAT_Y8:// Single plane, 8bpp.LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);pData = buffer->data;dataSize = buffer->stride * buffer->height;pStride = 1;rStride = buffer->stride;break;case HAL_PIXEL_FORMAT_Y16:bytesPerPixel = 2;// Single plane, 16bpp, strides are specified in pixels, not in bytesLOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);pData = buffer->data;dataSize = buffer->stride * buffer->height * bytesPerPixel;pStride = bytesPerPixel;rStride = buffer->stride * 2;break;case HAL_PIXEL_FORMAT_BLOB:// Used for JPEG data, height must be 1, width == size, single plane.LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);// When RGBA override is being used, buffer height will be equal to widthif (usingRGBAOverride) {LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,"RGBA override BLOB format buffer should have height == width");} else {LOG_ALWAYS_FATAL_IF(buffer->height != 1,"BLOB format buffer should have height value 1");}pData = buffer->data;dataSize = Image_getBlobSize(buffer, usingRGBAOverride);pStride = 0;rStride = 0;break;case HAL_PIXEL_FORMAT_RAW16:// Single plane 16bpp bayer data.bytesPerPixel = 2;LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);pData = buffer->data;dataSize = buffer->stride * buffer->height * bytesPerPixel;pStride = bytesPerPixel;rStride = buffer->stride * 2;break;case HAL_PIXEL_FORMAT_RAW_OPAQUE:// Used for RAW_OPAQUE data, height must be 1, width == size, single plane.LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);LOG_ALWAYS_FATAL_IF(buffer->height != 1,"RAW_PRIVATE should has height value one but got %d", buffer->height);pData = buffer->data;dataSize = buffer->width;pStride = 0; // RAW OPAQUE doesn't have pixel striderStride = 0; // RAW OPAQUE doesn't have row stridebreak;case HAL_PIXEL_FORMAT_RAW10:// Single plane 10bpp bayer data.LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);LOG_ALWAYS_FATAL_IF(buffer->width % 4,"Width is not multiple of 4 %d", buffer->width);LOG_ALWAYS_FATAL_IF(buffer->height % 2,"Height is not even %d", buffer->height);LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),"stride (%d) should be at least %d",buffer->stride, buffer->width * 10 / 8);pData = buffer->data;dataSize = buffer->stride * buffer->height;pStride = 0;rStride = buffer->stride;break;case HAL_PIXEL_FORMAT_RAW12:// Single plane 10bpp bayer data.LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);LOG_ALWAYS_FATAL_IF(buffer->width % 4,"Width is not multiple of 4 %d", buffer->width);LOG_ALWAYS_FATAL_IF(buffer->height % 2,"Height is not even %d", buffer->height);LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),"stride (%d) should be at least %d",buffer->stride, buffer->width * 12 / 8);pData = buffer->data;dataSize = buffer->stride * buffer->height;pStride = 0;rStride = buffer->stride;break;case HAL_PIXEL_FORMAT_RGBA_8888:case HAL_PIXEL_FORMAT_RGBX_8888:// Single plane, 32bpp.bytesPerPixel = 4;LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);pData = buffer->data;dataSize = buffer->stride * buffer->height * bytesPerPixel;pStride = bytesPerPixel;rStride = buffer->stride * 4;break;case HAL_PIXEL_FORMAT_RGB_565:// Single plane, 16bpp.bytesPerPixel = 2;LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);pData = buffer->data;dataSize = buffer->stride * buffer->height * bytesPerPixel;pStride = bytesPerPixel;rStride = buffer->stride * 2;break;case HAL_PIXEL_FORMAT_RGB_888:// Single plane, 24bpp.bytesPerPixel = 3;LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);pData = buffer->data;dataSize = buffer->stride * buffer->height * bytesPerPixel;pStride = bytesPerPixel;rStride = buffer->stride * 3;break;default:ALOGV("%s: unrecognized format 0x%x", __FUNCTION__, fmt);return BAD_VALUE;}*base = pData;*size = dataSize;*pixelStride = pStride;*rowStride = rStride;return OK;
}

以上部分注释待添加,待完善整理


相关文章:

安卓Camera2用ImageReader获取NV21源码分析

以前如何得到Camera预览流回调 可以通过如下方法&#xff0c;得到一路预览回调流 Camera#setPreviewCallbackWithBuffer(Camera.PreviewCallback)&#xff0c;可以通过如下方法&#xff0c;设置回调数据的格式&#xff0c;比如 ImageFormat.NV21 Camera.Parameters#setPreview…...

24. 两两交换链表中的节点

文章目录题目描述迭代法递归法参考文献题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 示例 1&#xff1a; 输入&a…...

linux006之帮助命令

linux帮助命令简介&#xff1a; linux的命令是非常多的&#xff0c;光靠人是记不住的&#xff0c;在工作中一般都会去网上查&#xff0c;这是有外网的情况下&#xff0c;如果项目中不允许访问外网&#xff0c;那么linux的帮助命令就可以派上用场了&#xff0c; linux帮助命令是…...

【C++初阶】十三、模板进阶(总)|非类型模板参数|模板的特化|模板分离编译|模板总结(优缺点)

目录 一、非类型模板参数 二、模板的特化 2.1 模板特化概念 2.2 函数模板特化 2.3 类模板特化 2.3.1 全特化 2.3.2 偏特化 三、模板分离编译 四、模板总结&#xff08;优缺点&#xff09; 前言&#xff1a;之前模板初阶并没有把 C模板讲完&#xff0c;因为当时没有接触…...

Linux之文本搜索命令

文本搜索命令学习目标能够知道文本搜索使用的命令1. grep命令的使用命令说明grep文本搜索grep命令效果图:2. grep命令选项的使用命令选项说明-i忽略大小写-n显示匹配行号-v显示不包含匹配文本的所有行-i命令选项效果图:-n命令选项效果图:-v命令选项效果图:3. grep命令结合正则表…...

微信小程序Springboot 校园拼车自助服务系统java

系统管理员&#xff1a; 管理员账户管理&#xff1a;在线对管理员的账户信息进行管理&#xff0c;包括对管理员信息的增加修改以及密码的修改等。 站内新闻管理&#xff1a;在后台对站内新闻信息进行发布&#xff0c;并能够对站内新闻信息进行删除修改等。 论坛版块管理&#x…...

【Unity3D 常用插件】Haste插件

一&#xff0c;Haste介绍 Haste插件是一款针对 Unity 3D 的 Everthing软件&#xff0c;可以实现基于名称快速定位对象的功能。Unity 3D 编辑器也自带了搜索功能&#xff0c;但是在 project视图 和 Hierarchy视图 中的对象需要分别查找&#xff0c;不支持模糊匹配。Haste插件就…...

【c++面试问答】全局变量和局部变量的区别

问题 C中的全局变量和局部变量有什么区别&#xff1f; 注&#xff1a;内容全部参考自文末的参考资料 全局变量和局部变量的区别 可以从以下4个角度来区分&#xff1a; 区别全局变量局部变量作用域全局作用域局部作用域内存分配全局变量在静态数据区静态局部变量在静态数据区…...

Java List集合

6 List集合 List系列集合&#xff1a;添加的元素是有序&#xff0c;可重复&#xff0c;有索引 ArrayList: 添加的元素是有序&#xff0c;可重复&#xff0c;有索引LinkedList: 添加的元素是有序&#xff0c;可重复&#xff0c;有索引Vector &#xff1a;是线程安全的&#xff…...

linux服务器挂载硬盘/磁盘

1. 查看机器所挂硬盘个数及分区情况&#xff1a;fdisk -l可以看出来目前/dev/vda 目前有300G可用.内部有两个分区&#xff08;/dev/vda1,/dev/vda2&#xff09;。2. 格式化磁盘格式化磁盘命令为【mkfs.磁盘类型格式 目录路径组成】查看磁盘文件格式&#xff1a;df -T格式化磁盘…...

Java 抽象类

文章目录1、抽象方法和抽象类2、抽象类的作用当编写一个类时&#xff0c;常常会为该类定义一些方法&#xff0c;用于描述该类的行为方式&#xff0c;这些方法都有具体的方法体。但在某些情况下&#xff0c;某个基类只是知道其子类应该包含那些方法&#xff0c;但不知道子类是如…...

OpenPPL PPQ量化(5):执行引擎 源码剖析

目录 PPQ Graph Executor(PPQ 执行引擎) PPQ Backend Functions(PPQ 算子库) PPQ Executor(PPQ 执行引擎) Quantize Delegate (量化代理函数) Usage (用法示例) Hook (执行钩子函数) 前面四篇博客其实就讲了下面两行代码&#xff1a; ppq_ir load_onnx_graph(onnx_impor…...

【脚本开发】运维人员必备技能图谱

脚本&#xff08;Script&#xff09;语言是一种动态的、解释性的语言&#xff0c;依据一定的格式编写的可执行文件&#xff0c;又称作宏或批处理文件。脚本语言具有小巧便捷、快速开发的特点&#xff1b;常见的脚本语言有Windows批处理脚本bat、Linux脚本语言shell以及python、…...

N字形变换-力扣6-java

一、题目描述将一个给定字符串 s 根据给定的行数 numRows &#xff0c;以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时&#xff0c;排列如下&#xff1a;P A H NA P L S I I GY I R之后&#xff0c;你的输出需要从左往右逐行读…...

概论_第5章_中心极限定理1__定理2(棣莫弗-拉普拉斯中心极限定理)

在概率论中&#xff0c; 把有关论证随机变量和的极限分布为正态分布的一类定理称为中心极限定理称为中心极限定理称为中心极限定理。 本文介绍独立同分布序列的中心极限定理。 一 独立同分布序列的中心极限定理 定理1 设X1,X2,...Xn,...X_1, X_2, ...X_n,...X1​,X2​,...Xn…...

详细解读503服务不可用的错误以及如何解决503服务不可用

文章目录1. 问题引言2. 什么是503服务不可用错误3 尝试解决问题3.1 重新加载页面3.2 检查该站点是否为其他人关闭3.3 重新启动设备3.3 联系网站4. 其他解决问的方法1. 问题引言 你以前遇到过错误503吗&#xff1f; 例如&#xff0c;您可能会收到消息&#xff0c;如503服务不可…...

【前端vue2面试题】2023前端最新版vue模块,高频17问(上)

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;博主收集的关于vue2面试题(上) 目录 vue2面试题 1、$route 和 $router的区别 2、一个…...

数据库(三):多版本并发控制MVCC,行锁的衍生版本,记录锁,间隙锁, Next-Key锁(邻键锁)

文章目录前言一、MVCC以及MVCC的缺点1.1 MVCC可以为数据库解决什么问题1.2 MVCC的基本思想1.3 版本号1.4 Undo日志1.5 ReadView1.6 快照读和当前读1.6.1 快照读1.6.2 当前读二、记录锁三、间隙锁四、邻键锁总结前言 一、MVCC以及MVCC的缺点 MVCC&#xff0c;即多版本并发控制…...

c# 自定义隐式转换与运算符重载

用户定义的显式和隐式转换运算符 参考代码 用户定义的显式和隐式转换运算符 - 提供对不同类型的转换 | Microsoft Learn 代码例程 using System;public readonly struct Digit {private readonly byte digit;public Digit(byte digit){if (digit > 9){throw new Argumen…...

【MyBatis】| MyBatis的逆向⼯程

目录 一&#xff1a;MyBatis的逆向⼯程 1. 逆向⼯程配置与⽣成 2. 测试生成的逆向⼯程 一&#xff1a;MyBatis的逆向⼯程 &#xff08;1&#xff09;所谓的逆向⼯程是&#xff1a;根据数据库表逆向⽣成Java的pojo类&#xff0c;SqlMapper.xml⽂件&#xff0c;以及Mapper接⼝…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

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

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

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...