[Android] 解析 GraphicBuffer 之 Framework 层

android图形框架之surfaceflinger分析(一) 1. 概念 surfaceflinger作用是接受多个来源的图形显示数据,将他们合成,然后发送到显示设备。比如打开应用,常见的有三层显示,顶部的statusbar底部或者侧面的导航栏以及应用的界面,每个层是单独更新和渲染,这些界面都是有surfaceflinger合成一个刷新到硬件显示。在显示过程中使用到了bufferqueue,surfaceflinger作为consumer方,... 阅读详情

[Android] GraphicBuffer之Framework层

一 前言

GraphicBuffer 是 SurfaceFlinger 中一块重要的内容, 它涉及到了我们应用程序的数据是如何和SurfaceFlinger进行传递的。

在介绍 GraphicBuffer 之前,我们先提出这样一个问题:我们应用程序的界面数据,是如何传递给 SurfaceFlinger 进行合成和显示的。是 Binder 吗?显然不是,Binder 传递不了这么大的数据。那么是共享内存吗,早期的界面数据的确是通过这种方式传递的,但是那已经是很早之前了。

前面我们介绍了SurfaceFlinger中的生产者和消费者模型, 在生产者申请 buffer 的时候, 如果拿到的 Slot 没有和 GraphicBuffer 进行绑定, 那么就会先创建一个 GraphicBuffer , 然后进行绑定

从这一篇开始,我们就来探究 GraphicBuffer 的工作原理。

1.1 GraphicBuffer 的创建

在前面介绍 dequeueBuffer 申请缓冲区的时候, 我们还说了一种逻辑, 那就是从 BufferQueue 中拿到的 slot 没有关联的 GraphicBuffer , 那么这种情况下还需要单独创建 GraphicBuffer ,这里我们就来看看 GraphicBuffer 的创建逻辑

[frameworks/native/libs/gui/BufferQueueProducer.cpp]
if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
  	// 如果拿到的缓冲区的 flag 为 BUFFER_NEEDS_REALLOCATION ,就创建一个 GraphicBuffer
    sp<GraphicBuffer> graphicBuffer = new GraphicBuffer(
            width, height, format, BQ_LAYER_COUNT, usage,
            {mConsumerName.string(), mConsumerName.size()});
} 

在之前解读 BufferQueue的时候介绍了 BufferQueue 中的生产者和消费者,以及最重要的四个函数,其中的生产者在生成内容的时候,就会有这么一个过程;

  1. 生产者向 BufferQueue 中申请 slot(缓冲槽)
  2. 生产者拿到 slot,但是 slot 并没有关联对应的 GraphicBuffer(缓冲区)
  3. 生产者创建一个缓冲区,并将它与缓冲槽相关联。

如上代码,就是步骤2中的一个片段。接下来,我们看 GraphicBuffer 创建时的具体流程。

1.2 GraphicBuffer的构造函数

[frameworks/native/libs/ui/GraphicBuffer.cpp]
GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
        PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
    : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage), requestorName)
{
}

GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
                             uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
      : GraphicBuffer() {
    mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
                              std::move(requestorName));
} 

GraphicBuffer 的构造函数非常简单, 它只是调用了一个初始化函数 initWithSize。

1.3 GraphicBuffer::initWithSize

status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,
        PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
        std::string requestorName) {
    // 获取一个 GraphicBufferAllocator 对象, 这个对象是一个单例
    // GraphicBufferAllocator 主要负责 GraphicBuffer 的内存分配
    GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
    uint32_t outStride = 0;
    // 分配一块制定宽高的 GraphicBuffer
    status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
            inUsage, &handle, &outStride, mId,
            std::move(requestorName));
    if (err == NO_ERROR) {
      	// 通过 GraphicBufferMapper 将这块 GraphicBuffer 的参数记录下来
      	// GraphicBufferMapper 负责的是 GraphicBuffer 的内存映射
        mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
	// 初始化参数
        width = static_cast<int>(inWidth);
        height = static_cast<int>(inHeight);
        format = inFormat;
        layerCount = inLayerCount;
        usage = inUsage;
        usage_deprecated = int(usage);
        stride = static_cast<int>(outStride);
    }
    return err;
} 

这里的初始化函数中,创建了一个 GraphicBufferAllocator 对象,这个我们申请的 GraphicBuffer 内存,其实是通过 GraphicBufferAllocator 这个对象进行分配的。

从这里开始,就需要注意了,因为在创建 GraphicBuffer 并分配内存的时候,会通过一个个对象不断的调用,从 Framework 层一直到最后的硬件层。

首先我们来看 GraphicBufferAllocator 这个类。

二 GraphicBufferAllocator

GraphicBufferAllocator 它是一个单例,外部使用时可以通过它来为 GraphicBuffer 来分配内存,Android 系统是为了屏蔽不同硬件平台的差异性,所以使用它来为外部提供一个统一的接口。

2.1 GraphicBufferAllocator::allocate

GraphicBufferAllocator::allocate 函数就是分配内存的具体函数, 它又通过调用一个 mAllocator 对象的 allocate 来分配内存, 这个 mAllocator 是一个 GrallocAllocator 的指针对象。GrallocAllocator 定义在frameworks/native/libs/ui/include/ui/Gralloc.h,它有几个实现分别是 定义在 Gralloc3.h 中的 Gralloc3Allocator , 和定义在 Gralloc2.h 中的 Gralloc2Allocator

[frameworks/native/libs/ui/GraphicBufferAllocator.cpp]
status_t GraphicBufferAllocator::allocate(uint32_t width, uint32_t height,
        PixelFormat format, uint32_t layerCount, uint64_t usage,
        buffer_handle_t* handle, uint32_t* stride,
        uint64_t /*graphicBufferId*/, std::string requestorName) {
    // 如果宽或者高为0, 则将宽高设置为1
    if (!width || !height)
        width = height = 1;
    // 如果图层的数量少于1, 则将图层的数量设置为1
    if (layerCount < 1)
        layerCount = 1;
    // 移除调用者中的无效位
    usage &= ~static_cast<uint64_t>((1 << 10) | (1 << 13));
    // 分配内存,使用的是 GrallocAllocator 指针,根据不同的版本有哦不同的实现,
    // 这里我们假设它的实现是 Gralloc3Allocator
    status_t error =
            mAllocator->allocate(width, height, format, layerCount, usage, 1, stride, handle);
    if (error == NO_ERROR) {
        // 初始化参数
        Mutex::Autolock _l(sLock);
        KeyedVector<buffer_handle_t, alloc_rec_t>& list(sAllocList);
        uint32_t bpp = bytesPerPixel(format);
        alloc_rec_t rec;
        rec.width = width;
        rec.height = height;
        rec.stride = *stride;
        rec.format = format;
        rec.layerCount = layerCount;
        rec.usage = usage;
        rec.size = static_cast<size_t>(height * (*stride) * bpp);
        rec.requestorName = std::move(requestorName);
        list.add(*handle, rec);
        return NO_ERROR;
    } else {
        return NO_MEMORY;
    }
} 

GraphicBufferAllocator 有两个实现类, 我们来看它其中的一个实现类 Gralloc3Allocator

2.2 Gralloc3Allocator

GrallocAllocator 有多个实现版本,Gralloc3Allocator 就是实现 Gralloc3 的版本

2.2.1 Gralloc3Allocator的定义

在 Gralloc3Allocator 定义的构造函数中,只有一个参数,就是 Gralloc3Mapper。这个参数在后面做内存分配的时候会用上,接着来看它构造函数具体的实现

[frameworks/native/libs/ui/include/ui/Gralloc3.h]

class Gralloc3Allocator : public GrallocAllocator {
public:
    // Gralloc3Allocator 的构造函数需要传递一个 Gralloc3Mapper,因为分配内存依赖映射器 mapper
    Gralloc3Allocator(const Gralloc3Mapper& mapper);

    bool isLoaded() const override;

    std::string dumpDebugInfo() const override;

    // 它只有一个函数,就是分配内存
    status_t allocate(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount,
                      uint64_t usage, uint32_t bufferCount, uint32_t* outStride,
                      buffer_handle_t* outBufferHandles) const override;

private:
    const Gralloc3Mapper& mMapper;
    // 真正实现分配内存的则是 mAllocator,这是通过 HAL 调用。
    // HAL 层调用使用的通信方式就是 HIDL,其实和我们使用的 AIDL 是一样的原理。
    sp<hardware::graphics::allocator::V3_0::IAllocator> mAllocator;
}; 
2.2.2 Gralloc3Allocator的构造函数
[frameworks/native/libs/ui/Gralloc3.cpp]
Gralloc3Allocator::Gralloc3Allocator(const Gralloc3Mapper& mapper) : mMapper(mapper) {
    mAllocator = IAllocator::getService();
    if (mAllocator == nullptr) {
        return;
    }
} 

Gralloc3Allocator 的构造函数会传递一个 Gralloc3Mapper 作为参数, 并将它赋值给 mMapper , 当然, 其中最关键的还是通过一个 IAllocator::getService() 获取到了一个 mAllocator 对象, 这个 mAllocator 对象就是 hardware::graphics::allocator::V3_0::IAllocator 的指针。

看到这里,我们大概就能猜到,这和我们常见的进程间获取服务的方式很相似,在我们在应用中使用系统服务时,也是先通过 getService 拿到注册好的服务,然后再通过这个 Bp 对象,调用对应的服务函数。

2.2.3 Gralloc3Allocator的allocate

然后我们看 Gralloc3Allocator 分配内存的函数

status_t Gralloc3Allocator::allocate(uint32_t width, uint32_t height, android::PixelFormat format,
                                     uint32_t layerCount, uint64_t usage, uint32_t bufferCount,
                                     uint32_t* outStride, buffer_handle_t* outBufferHandles) const {

    // 定义一个缓冲区的描述信息 descriptorInfo , 并将缓冲区的相关参数都封装到这个描述信息 descriptorInfo 中
    IMapper::BufferDescriptorInfo descriptorInfo;
    sBufferDescriptorInfo(width, height, format, layerCount, usage, &descriptorInfo);

    BufferDescriptor descriptor;
    // 通过之前构造函数中的 mMapper 对象来创建一个描述信息
    status_t error = mMapper.createDescriptor(static_cast<void*>(&descriptorInfo),
                                              static_cast<void*>(&descriptor));
    if (error != NO_ERROR) {
        return error;
    }

    // 通过 mAllocator 这个 Bp 对象来调用对应的系统服务
    // 调用到 hardware::graphics::allocator::V3_0::IAllocator 的 allocate 函数
    auto ret = mAllocator->allocate(descriptor, bufferCount,
                                    [&](const auto& tmpError, const auto& tmpStride,
                                        const auto& tmpBuffers) {
                                        error = static_cast<status_t>(tmpError);
                                        if (tmpError != Error::NONE) {
                                            return;
                                        }

                                        // import buffers
                                        for (uint32_t i = 0; i < bufferCount; i++) {
                                            error = mMapper.importBuffer(tmpBuffers[i],
                                                                         &outBufferHandles[i]);
                                            if (error != NO_ERROR) {
                                                for (uint32_t j = 0; j < i; j++) {
                                                    mMapper.freeBuffer(outBufferHandles[j]);
                                                    outBufferHandles[j] = nullptr;
                                                }
                                                return;
                                            }
                                        }
                                        *outStride = tmpStride;
                                    });

    // 确保内核驱动程序看到 BC_FREE_BUFFER 并立即关闭fds
    hardware::IPCThreadState::self()->flushCommands();
    return (ret.isOk()) ? error : static_cast<status_t>(kTransactionError);
} 

Gralloc3Allocator 的内存分配主要用到了两个对象,分别是继承自 Gralloc::GraphicBufferMapper 的 mMapper,和继承自 GraphicBufferAllocator 的 mAllocator。

mAllocator 是通过 HAL 创建的对象, 这个 IAllocator 是一个 HIDL 接口, HIDL 其实就是 hardware 层的 AIDL , 它和我们应用层的 AIDL 其实是一样的, 在我们应用层, 如果想使用 AIDL 进行跨进程通信, 需要定义一个 aidl 后缀名的文件, 而在系统的 HAL 层, 如果想使用 HIDL 进行跨进行通信也是类似, 需要定义一个 hal 后缀名的文件.。

例如 IAllocator 这个接口,其实就定义中 hardware/interfaces/graphics/allocator/3.0/ 路径下的 IAllocator.hal 中

[hardware/interfaces/graphics/allocator/3.0/IAllocator.hal]
package android.hardware.graphics.allocator@3.0;
import android.hardware.graphics.mapper@3.0;

// 这是一个接口
interface IAllocator {
    // 调试相关的方法,不关心
    dumpDebugInfo() generates (string debugInfo);

    // 按照描述符的属性分配缓冲区
    allocate(BufferDescriptor descriptor, uint32_t count)
        generates (Error error,
                   uint32_t stride,
                   vec<handle> buffers);
}; 

IAllocator.hal 定义的方法很简单, 它只有一个 allocate 函数,这个就是我们用来分配内存的函数。我们会拿到 Bp 对象来进行调用,具体的实现则是在 Bn 中。

它实际上就是调用到了 HAL 部分的 allocate,这其实就有些像我们调用系统函数时的过程,也是通过 AIDL 完成的,只不过这里就是通过 HIDL 完成的。接下来我们需要知道这个 HAL 是如何完成工作的。

注意, 我们之前通过 IAllocator 调用了两个函数, 其中还有一个函数是 getService ,而这里的 hal 文件中我们并没有看到这个函数, 那么这个函数是哪里来的呢 其实在编译的时候, 还会生成一个文件 AllocatorAll.cpp , 这个文件就包含了我们之前调用的 getService

2.2.4 getService
[out/soong/.intermediates/hardware/interfaces/graphics/allocator/3.0/android.hardware.graphics.allocator@3.0_genc++/gen/android/hardware/graphics/allocator/3.0/AllocatorAll.cpp]
::android::sp<IAllocator> IAllocator::getService(const std::string &serviceName, const bool getStub) {
    return ::android::hardware::details::getServiceInternal<BpHwAllocator>(serviceName, true, getStub);
} 

到此,Framework 部分的内容就全部介绍完了,还是比较简单的,因为真正的工作都是发生在 HAL 层和硬件层。

最后,如果大伙有什么好的学习方法或建议欢迎大家在评论中积极留言哈,希望大家能够共同学习、共同努力、共同进步。

小编在这里祝小伙伴们在未来的日子里都可以 升职加薪,当上总经理,出任CEO,迎娶白富美,走上人生巅峰!!

不论遇到什么困难,都不应该成为我们放弃的理由!

很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,需要一份小编整理出来的学习资料的**关注我主页或者点击扫描下方二维码免费领取~

这里是关于我自己的Android 学习,面试文档,视频收集大整理,有兴趣的伙伴们可以看看~

如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言,一定会认真查询,修正不足,谢谢。

Android显示系统-GraphicBuffer和Gralloc分析 BufferQueue中的Buffer对象,我们用的都是GraphicBuffer,那么GraphicBuffer是怎么来的呢?接下里我们具体来看这里的流程。 Surface是Andorid窗口的描述,是ANativeWindow的实现;同样GraphicBuffer是Android中图形Buffer的描述,是ANativeWindowBuffer的实现。而一个窗口,可以有几个Buffer。... 阅读详情

相关推荐

空间配置器allocator

空间配置器的作用是在底层为上层的各种容器提供存储空间,需要多少分配多少,一般分配的比你需要的更多。打个不恰当的比喻,空间配置器和容器之间的关系,相当于将军和粮草的关系。当然了,容器相当于将军,它在阵前杀敌,冲锋陷阵,处理各种事情;而空间配置器就相当于粮草,给前阵提供源源不断的供给;如果一个将军想打胜仗,那必须后方粮草充足才行。 为了进一步提高内存的使用率和使用效率。主要是从以下两方面来考虑的: 1.小块内存会带来内存碎片问题 如果任由STL中的容器自行通过malloc分配内存,那么频繁的分配和释放内存

qq_41078889的博客 1008

\[Android禅修之路\] 解读 GraphicBuffer 之 Framework 层

[Android禅修之路] 解读 GraphicBuffer 之 Framework 层 一 前言 GraphicBuffer 是 SurfaceFlinger 中一块重要的内容, 它涉及到了我们应用程序的数据是如何和SurfaceFlinger进行传递的。 在介绍 GraphicBuffer 之前,我们先提出这样一个问题:我们应用程序的界面数据,是如何传递给 SurfaceFlinger 进行合成和显示的。是 Binder 吗?显然不是,Binder 传递不了这么大的数据。那么是共享内存吗,早期的界面数据

Android_XG的博客 677

Android GrallocBuffer架构理解2

Android Gralloc Buffer 设计与实现摘要 Gralloc是Android图形子系统的内存管理层,负责图形缓冲区的分配、映射和跨进程传输。其架构采用Allocator/Mapper分离设计,支持版本自适应(Gralloc 5-2),通过单例模式管理。核心类包括: GraphicBuffer - 图形缓冲区对象,继承自ANativeWindowBuffer,支持多种构造方式、锁定API和跨进程序列化(Flattenable协议) GraphicBufferAllocator - 缓冲区分配器

DU_YULIN的博客 310

Android GraphicBuffer分配过程

Android系统定义GraphicBuffer数据类型来描述一块图形buffer,该对象可以跨进程传输。 IGraphicBufferAlloc是专门用于分配GraphicBuffer对象的工具类,该类是基于Binder进程间通信机制框架设计的,其类继承关系如下: 由于IGraphicBufferAlloc是基于Binder进程间通信框架设计的,因此该类的实现分客户端进程和服

深入剖析Android系统 2万+

Android GraphicBuffer框架及底层调用理解

本文深入分析了Android图形缓冲区的底层管理机制,主要包含以下内容: 系统架构分层设计: 上层应用通过GraphicBufferMapper/Allocator与底层交互 中间层包含GrallocMapper/Allocator抽象接口 底层支持Gralloc 2-5多个HAL版本实现 核心组件职责: GraphicBufferMapper负责缓冲区的映射、锁定和元数据管理 GraphicBufferAllocator专门处理缓冲区的分配和释放 版本选择机制: 系统根据设备API级别自动选择最高可用的G

DU_YULIN的博客 368

Android MediaRecorder框架深度解析:从API调用到底层硬件编码

在Android音视频开发中,录制功能是核心需求之一,其背后依赖的多媒体框架涉及复杂的层级结构与数据流。理解其工作原理需要从基础概念切入:Android系统通过分层架构(应用层、Native框架层、服务与硬件抽象层)来管理多媒体任务,其中OMX(OpenMAX Integration Layer)组件是实现硬件加速编解码的关键接口。这一设计使得应用能够高效利用芯片厂商提供的硬件编码器,显著提升性能并降低功耗。在工程实践中,开发者通过MediaRecorder API进行录制,数据会经历采集、编码、复用等流程

weixin_34357436的博客 281

【Android FrameWork】第三十天:Surface创建流程解析

Android Surface创建流程涉及应用进程、SystemServer(WMS)和SurfaceFlinger三方跨进程协作。核心步骤包括:1)应用进程通过ViewRootImpl发起Surface申请;2)WMS校验窗口属性后,通过JNI调用Native层;3)SurfaceFlinger创建BufferQueue并返回Producer端;4)WMS将结果回传给应用进程。整个流程中,Java层负责请求封装和结果处理,核心的BufferQueue创建和显存管理由C++层的SurfaceFlinger实

u012739527的博客 1343

从SurfaceFlinger到HAL:Android冻屏与黑屏问题的全链路解析

本文系统解析了Android设备常见的冻屏与黑屏问题,从图形显示核心SurfaceFlinger的图层合成机制入手,深入追踪至HAL层与硬件交互的全链路。文章提供了从应用层、系统服务层到驱动层的可实操排查框架,结合日志分析、代码注入与调试命令,帮助开发者定位图层隐藏、HWC合成失败、GPU回退及硬件驱动等根本原因,是解决Android图形显示系统疑难杂症的实用指南。

weixin_29281941的博客 559

【Android FrameWork】延伸阅读:IGraphicBufferProducer驱动UI绘制过程

本文分析了Android UI绘制流程中IGraphicBufferProducer的关键作用。当Surface持有IGraphicBufferProducer后,XML定义的UI通过"onDraw触发绘制→GBP申请显存→写入绘制指令→提交缓冲区→SurfaceFlinger合成"的闭环显示在屏幕上。文章从XML布局解析开始,详细拆解了UI绘制全流程,重点剖析了C++层IGraphicBufferProducer作为应用进程与SurfaceFlinger核心接口的实现逻辑,揭示了UI数

u012739527的博客 957

Android 系统渲染架构知识图谱

一份系统级 Android 渲染架构全景图谱:从 App 层的 View 绘制、DisplayList 录制,到 Framework 层的 WMS/SurfaceFlinger/HWUI,再到底层的 Gralloc/HWC/DRM-KMS 完整链路。涵盖 BufferQueue 机制、VSync 调度、Triple Buffering、合成策略演进、性能指标与调试工具链。一张图串联触摸到像素的全流程。

gyuong的专栏 42

POI 写word,添加标题,表格,图片,自动生成目录,合并单元格

工程地址:https://github.com/zheng-chang-wei/word package com.example.demo1.poi; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.File; import java.io.FileOutputStream; public class ...

zheng_chang_wei的博客 6155

Android Framework源码解析(七):BootAnimation 启动流程解析——开机动画是如何显示出来的?

上一篇我们完整梳理了 Launcher3 桌面启动全流程,理解系统如何拉起桌面应用并渲染 UI。

gxgldyh的专栏 280

EEG/ERP新手必看:5本神经科学入门书籍推荐(附高清PDF下载)

本文为EEG/ERP研究新手推荐5本神经科学入门书籍,涵盖认知神经科学、数据分析、ERP技术等核心内容。特别推荐《认知神经科学—关于心智的生物学》和《事件相关电位基础》,这些书籍不仅提供理论框架,还包含实用案例和MATLAB代码,帮助研究者快速掌握脑电研究技术。附高清PDF下载,适合实验室小组学习。

weixin_29210727的博客 445

Android framework 面试复盘

就是单纯来记录面试被问到的问题1.车机的流量有限,但是要确保系统里几个很重要的服务要优先有网络,这个内容应该怎么修改2.内存泄漏的检查逻辑3.ANR 那种可以通过 traces 能直接看到死锁的,这种好改,如果看到那种看不到死锁的,怎么去定位第一个问题其实我脑子里就是在想networkrequest 然后给到 ConnectivityService后,再去做修改,但是总觉得面试官就是在给我下陷阱,肯定要留意别的修改点,想了想估计要路由,但是路由表我本来就是不太会写,直接露馅第二个问题。

weixin_44096373的博客 208

Xilinx DMA IP核心配置与实战解析

本文介绍了Xilinx DMA IP核在直接寄存器模式下的配置与工作流程。DMA通过AXI4-Lite接口接收指令,实现内存与数据流之间的高速传输,无需CPU介入。文章详细说明了开发环境配置、IP参数设置(包括地址位宽、数据宽度等关键参数)以及寄存器操作流程。通过仿真分析,展示了读操作中AXI4接口的突发传输机制,包括地址、长度和突发大小的配置。文中还提供了寄存器地址映射表、信号定义等关键信息,为DMA IP核的应用开发提供了实用参考。

weixin_37688766的博客 884

基于深度学习的大豆病害检测识别系统:YOLOv10 + UI界面 + 数据集

YOLOv10是一种高效的目标检测算法,能够在保持高精度的同时,提供较快的检测速度。YOLOv10使用了改进的卷积神经网络架构,并在多个计算机视觉任务中表现出色。在本项目中,我们将使用YOLOv10进行大豆病害的检测和分类。本系统利用YOLOv10算法,实现了大豆病害的实时检测和分类。通过结合深度学习和图像处理技术,可以帮助农业领域的专业人员更加高效地识别和诊断大豆病害,提高农作物的生产力与质量。

YOLO 699

【Android FrameWork】第二十五天:视频流获取与底层Buffer交互

本文详细解析了Android视频流获取与底层Buffer交互的技术链路。主要内容包括: APP层实现方案: 使用SurfaceView作为独立绘图缓冲区避免UI阻塞 通过Camera2框架实现精细化相机控制 完整流程包括Surface初始化、相机权限申请、设备打开、捕获会话创建等关键步骤 核心组件: SurfaceView/SurfaceHolder提供显示容器 CameraManager/CameraDevice管理相机设备 CameraCaptureSession连接相机与输出目标 技术要点: 需动态申

u012739527的博客 1400

反光柱定位算法实战03:VEnus代码解析和纯反光柱定位中的可改进方向

本文深入解析了开源框架VEnus的反光柱定位与建图实现流程,包括强度提取、聚类、数据关联、位姿优化等核心模块。同时指出其三大局限:匹配质量脆弱性、单一传感器依赖和地图扩展逻辑缺失,并提出改进方向:融合里程计/IMU数据、引入图优化后端、建立动态地图维护机制。该分析为基于反光柱的定位系统优化提供了实用参考,有助于提升工业场景下的定位鲁棒性和精确性。

Studying…… 520

Android 15 显示子系统深度解析(一):显示框架总览与SurfaceFlinger核心机制

深入解析Android 15显示系统的完整架构,从应用层绘制到屏幕显示的全链路,重点剖析SurfaceFlinger核心服务的启动、Surface管理和合成流程机制

Cheson的专栏 2163

CloudCompare 和 PCL:点云网格化分析与处理

点云网格化是将点云数据转化为规则网格的过程,其主要思想是将离散的点云投影到一个平面上,然后对该平面进行划分,形成一系列小区域。在点云网格化方面,PCL 提供了各种算法和工具,可以实现高效的点云网格化操作。以上示例代码中,首先加载了输入的点云数据,然后通过设置合适的网格化算法参数,如搜索半径和最大三角形边长等,执行了网格化操作,最后将网格化结果保存到输出文件中。以上示例代码中,首先加载了输入的点云数据,然后通过设置合适的网格化参数,如分辨率等,执行了网格化操作,最后将网格化结果保存到输出文件中。

TechPulseZ的博客 1291

Transformer实战(1)——词嵌入技术详解

词嵌入的核心思想是,通过将词语表示为稠密的向量,使得计算机可以更有效地处理和理解文本中的语义关系。在本节中,我们学习了单词分布式表示的概念及其实现,包括静态嵌入和动态嵌入,实现了 Word2Vec 和 GloVe 模型,并介绍了如何使用 Gensim API 探索嵌入空间。

盼小辉丶的博客 1万+

framework之深入surface系统

一个Activity的显示: 创建Activity a:performLaunchActivity:根据类名通过java反射机制创建一个Activity。 调用Instrumentation的newActivity,调用attach函数: PolicyManager的makeNewWindow,创建window对象,返回的mWindow是一个PhoneWindow对象。 windowMa

ahjxly的专栏 2515

在Simulink中构建感应电机的时滞补偿控制模型,并通过仿真验证不同补偿策略的有效性

核心优势Smith预估器可有效补偿已知时滞,提升系统稳定性。动态PID调整适用于时变时滞的初步补偿。扩展方向自适应时滞估计:结合Luenberger观测器实时估计时滞。鲁棒控制:引入H∞控制或滑模控制抑制参数不确定性。网络化时滞补偿:结合知识库[2]的网络延迟模型,实现端到端补偿。

amy_mhd的博客 189

安卓HWUI学习

今天去面试安卓驱动工程师的岗位,首先他问了我安卓hwui,当时有点懵,以下是常见的framework总结。

m0_73991989的博客 259

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Android Window的添加和显示过程

文章目录1. Android Window2. Window的添加流程3. Surface 和 Layer1. Surface绘图 本文基于Android N; 1. Android Window Android中的Window是一个抽象概念,并不是真正的window,而是一个用于对真正的图形显示组件(Surface)做管理的 “虚拟窗口概念”。 我们在开发过程中的意识上可以认为Window...

Nothing_Blog 3549

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

图像显示框架九——Surface/SurfaceControl基础概念(基于Android15源码分析)

代码位置:framework/native/libs/nativewindow/include/system/window.h// 构造函数:初始化 magic number、版本号及各类窗口属性默认值// 魔术字,用于类型验证// 结构体版本// 保留字段置零// 以下两个函数实现了引用计数功能,使 ANativeWindow 可由 sp<> (强指针) 自动管理生命周期#endif。

龚礼鹏的博客 1810

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: 「Android - SoundPool使用」
下一篇: Android Memory(二) -- 应用内存占用分析
网络安全-XG
博客等级 码龄5年 1万+粉丝 2752原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值