如何在android framewrok dump camera data

实现dump 函数

实现1

cpp 复制代码
void dumpBufferToFile(buffer_handle_t* buffer, int width, int height, int frameNum) {
    void* data = NULL;
    GraphicBufferMapper::getInstance().lock(*buffer, GRALLOC_USAGE_SW_READ_OFTEN, Rect(width, height), &data);

    char filename[128];
    sprintf(filename, "/data/vendor/camera/frame_%04d.yuv", frameNum);
    FILE* fp = fopen(filename, "wb");
    if (fp && data) {
        fwrite(data, 1, width * height * 3 / 2, fp); // 如果是 NV12/YUV420
        fclose(fp);
    }

    GraphicBufferMapper::getInstance().unlock(*buffer);
}

实现2

cpp 复制代码
#include <stdio.h>
#include <fcntl.h>
#include <string>
#include <sys/mman.h>
#include <hardware/gralloc.h>
#include <ui/GraphicBufferMapper.h>
#include <cutils/native_handle.h>
#include <android/hardware_buffer.h>

using namespace android;

// Camera format types
#define CAMERA_FORMAT_RAW16   0x20
#define CAMERA_FORMAT_RAW10   0x25
#define CAMERA_FORMAT_RAW12   0x26
#define CAMERA_FORMAT_YUV_420_888 0x23
#define CAMERA_FORMAT_JPEG    0x100

// Helper: Get format name
const char* getFormatSuffix(int format) {
    switch (format) {
        case HAL_PIXEL_FORMAT_YCbCr_420_888:
            return ".yuv";
        case HAL_PIXEL_FORMAT_BLOB:
            return ".jpg";
        case HAL_PIXEL_FORMAT_RAW16:
            return ".raw16";
        case HAL_PIXEL_FORMAT_RAW10:
            return ".raw10";
        case HAL_PIXEL_FORMAT_RAW12:
            return ".raw12";
        default:
            return ".bin";
    }
}

void dumpBufferToFile(buffer_handle_t handle, int width, int height, int frameNum, int format) {
    void* data = nullptr;
    uint32_t size = 0;

    // Lock buffer for reading
    GraphicBufferMapper& mapper = GraphicBufferMapper::get();
    android_ycbcr ycbcr = {};
    int usage = GRALLOC_USAGE_SW_READ_OFTEN;

    if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
        if (mapper.lockYCbCr(handle, usage, {0, 0, width, height}, &ycbcr) == OK) {
            data = ycbcr.y;
            size = width * height * 3 / 2;
        }
    } else {
        if (mapper.lock(handle, usage, {0, 0, width, height}, &data) == OK) {
            switch (format) {
                case HAL_PIXEL_FORMAT_RAW16:
                    size = width * height * 2;
                    break;
                case HAL_PIXEL_FORMAT_RAW10:
                    size = width * height * 10 / 8;
                    break;
                case HAL_PIXEL_FORMAT_RAW12:
                    size = width * height * 12 / 8;
                    break;
                case HAL_PIXEL_FORMAT_BLOB:
                    // BLOB: Usually JPEG
                    // You may need to get actual size from metadata, here we assume max
                    size = width * height;
                    break;
                default:
                    size = width * height * 4; // assume RGBA fallback
            }
        }
    }

    if (data == nullptr || size == 0) {
        ALOGE("dumpBufferToFile: failed to lock buffer");
        return;
    }

    // Generate file path
    char path[256];
    snprintf(path, sizeof(path), "/data/vendor/camera/dump_%04d%s", frameNum, getFormatSuffix(format));

    // Dump to file
    FILE* fp = fopen(path, "wb");
    if (fp) {
        fwrite(data, 1, size, fp);
        fclose(fp);
        ALOGI("dumpBufferToFile: dumped frame %d to %s", frameNum, path);
    } else {
        ALOGE("dumpBufferToFile: failed to open file %s", path);
    }

    // Unlock buffer
    mapper.unlock(handle);
}

添加调用位置

推荐位置 1, Camera3OutputStream::queueBufferToConsumer()

复制代码
此函数负责将 HAL 返回的 buffer 通过 ANativeWindow 传给 Surface,因此非常适合 dump。
cpp 复制代码
status_t Camera3OutputStream::queueBufferToConsumer(sp<GraphicBuffer>& buffer, ...)
{
    dumpBufferToFile(buffer->getNativeBuffer()->handle, mWidth, mHeight, mFrameNumber);

    // 原逻辑继续
    res = mConsumer->queueBuffer(...);
}

推荐位置 2,Camera3Device::processCaptureResult()

复制代码
HAL 返回一个 camera3_capture_result_t 结构,这里可以拿到 metadata 和 buffer。
cppvoid 复制代码
    for (size_t i = 0; i < result->num_output_buffers; i++) {
        const camera3_stream_buffer_t &buffer = result->output_buffers[i];
        Camera3OutputStreamInterface* stream = static_cast<Camera3OutputStreamInterface*>(buffer.stream->priv);
        
        // 📌 拿到 buffer 后 dump
        dumpBufferToFile(buffer.buffer, stream->getWidth(), stream->getHeight(), result->frame_number);
    }
}
相关推荐
J2虾虾几秒前
Android支持Java语言的标准
android·java·开发语言
charlee444 分钟前
Unity在安卓端如何调试输出信息
android·unity·adb·游戏引擎·真机调试
法欧特斯卡雷特8 分钟前
从 Kotlin 编译器 API 的变化开始: 2.4.0
android·开源·github
贾艺驰11 分钟前
实战Android Framework: 新增一个系统服务
android·源码
火山上的企鹅13 分钟前
Codex实战:APP远程升级服务搭建(五)App端远程升级接入
android·服务器·远程升级·qgc
BreezeDove39 分钟前
【Android】Flutter3.35项目启动超时问题
android·flutter
故渊at1 小时前
第十四板块:Android 硬件抽象与安全加固 | 第三十四篇:Hardware Composer (HWC) 与 显示安全(HDCP)
android·安全·composer·安全加固·hwc·硬件抽象
KIO no way1 小时前
AI内容编排是什么_聊聊CSDN_AI数字营销背后的分发逻辑
android·人工智能
故渊at1 小时前
第十四板块:Android 硬件抽象与安全加固 | 第三十三篇:Verified Boot 与 硬件信任链(Trusty TEE)
android·安全·信任链·verified
Tangyuewei1 小时前
我用 AI 辅助开发了一个发型 App,然后打包成了 APK
android·人工智能·ai编程