安卓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预览流回调 可以通过如下方法,得到一路预览回调流 Camera#setPreviewCallbackWithBuffer(Camera.PreviewCallback),可以通过如下方法,设置回调数据的格式,比如 ImageFormat.NV21 Camera.Parameters#setPreview…...

24. 两两交换链表中的节点
文章目录题目描述迭代法递归法参考文献题目描述 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1: 输入&a…...
linux006之帮助命令
linux帮助命令简介: linux的命令是非常多的,光靠人是记不住的,在工作中一般都会去网上查,这是有外网的情况下,如果项目中不允许访问外网,那么linux的帮助命令就可以派上用场了, linux帮助命令是…...

【C++初阶】十三、模板进阶(总)|非类型模板参数|模板的特化|模板分离编译|模板总结(优缺点)
目录 一、非类型模板参数 二、模板的特化 2.1 模板特化概念 2.2 函数模板特化 2.3 类模板特化 2.3.1 全特化 2.3.2 偏特化 三、模板分离编译 四、模板总结(优缺点) 前言:之前模板初阶并没有把 C模板讲完,因为当时没有接触…...

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

微信小程序Springboot 校园拼车自助服务系统java
系统管理员: 管理员账户管理:在线对管理员的账户信息进行管理,包括对管理员信息的增加修改以及密码的修改等。 站内新闻管理:在后台对站内新闻信息进行发布,并能够对站内新闻信息进行删除修改等。 论坛版块管理&#x…...

【Unity3D 常用插件】Haste插件
一,Haste介绍 Haste插件是一款针对 Unity 3D 的 Everthing软件,可以实现基于名称快速定位对象的功能。Unity 3D 编辑器也自带了搜索功能,但是在 project视图 和 Hierarchy视图 中的对象需要分别查找,不支持模糊匹配。Haste插件就…...
【c++面试问答】全局变量和局部变量的区别
问题 C中的全局变量和局部变量有什么区别? 注:内容全部参考自文末的参考资料 全局变量和局部变量的区别 可以从以下4个角度来区分: 区别全局变量局部变量作用域全局作用域局部作用域内存分配全局变量在静态数据区静态局部变量在静态数据区…...

Java List集合
6 List集合 List系列集合:添加的元素是有序,可重复,有索引 ArrayList: 添加的元素是有序,可重复,有索引LinkedList: 添加的元素是有序,可重复,有索引Vector :是线程安全的ÿ…...

linux服务器挂载硬盘/磁盘
1. 查看机器所挂硬盘个数及分区情况:fdisk -l可以看出来目前/dev/vda 目前有300G可用.内部有两个分区(/dev/vda1,/dev/vda2)。2. 格式化磁盘格式化磁盘命令为【mkfs.磁盘类型格式 目录路径组成】查看磁盘文件格式:df -T格式化磁盘…...
Java 抽象类
文章目录1、抽象方法和抽象类2、抽象类的作用当编写一个类时,常常会为该类定义一些方法,用于描述该类的行为方式,这些方法都有具体的方法体。但在某些情况下,某个基类只是知道其子类应该包含那些方法,但不知道子类是如…...

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

【脚本开发】运维人员必备技能图谱
脚本(Script)语言是一种动态的、解释性的语言,依据一定的格式编写的可执行文件,又称作宏或批处理文件。脚本语言具有小巧便捷、快速开发的特点;常见的脚本语言有Windows批处理脚本bat、Linux脚本语言shell以及python、…...

N字形变换-力扣6-java
一、题目描述将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。比如输入字符串为 "PAYPALISHIRING" 行数为 3 时,排列如下:P A H NA P L S I I GY I R之后,你的输出需要从左往右逐行读…...
概论_第5章_中心极限定理1__定理2(棣莫弗-拉普拉斯中心极限定理)
在概率论中, 把有关论证随机变量和的极限分布为正态分布的一类定理称为中心极限定理称为中心极限定理称为中心极限定理。 本文介绍独立同分布序列的中心极限定理。 一 独立同分布序列的中心极限定理 定理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吗? 例如,您可能会收到消息,如503服务不可…...

【前端vue2面试题】2023前端最新版vue模块,高频17问(上)
🥳博 主:初映CY的前说(前端领域) 🌞个人信条:想要变成得到,中间还有做到! 🤘本文核心:博主收集的关于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,即多版本并发控制…...

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的逆向⼯程
目录 一:MyBatis的逆向⼯程 1. 逆向⼯程配置与⽣成 2. 测试生成的逆向⼯程 一:MyBatis的逆向⼯程 (1)所谓的逆向⼯程是:根据数据库表逆向⽣成Java的pojo类,SqlMapper.xml⽂件,以及Mapper接⼝…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...

李沐--动手学深度学习--GRU
1.GRU从零开始实现 #9.1.2GRU从零开始实现 import torch from torch import nn from d2l import torch as d2l#首先读取 8.5节中使用的时间机器数据集 batch_size,num_steps 32,35 train_iter,vocab d2l.load_data_time_machine(batch_size,num_steps) #初始化模型参数 def …...
计算机系统结构复习-名词解释2
1.定向:在某条指令产生计算结果之前,其他指令并不真正立即需要该计算结果,如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方,那么就可以避免停顿。 2.多级存储层次:由若干个采用不同实现技术的存储…...
Docker、Wsl 打包迁移环境
电脑需要开启wsl2 可以使用wsl -v 查看当前的版本 wsl -v WSL 版本: 2.2.4.0 内核版本: 5.15.153.1-2 WSLg 版本: 1.0.61 MSRDC 版本: 1.2.5326 Direct3D 版本: 1.611.1-81528511 DXCore 版本: 10.0.2609…...