当前位置: 首页 > 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接⼝…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...

高防服务器价格高原因分析

高防服务器的价格较高&#xff0c;主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因&#xff1a; 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器&#xff0c;因此…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践

01技术背景与业务挑战 某短视频点播企业深耕国内用户市场&#xff0c;但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大&#xff0c;传统架构已较难满足当前企业发展的需求&#xff0c;企业面临着三重挑战&#xff1a; ① 业务&#xff1a;国内用户访问海外服…...