如何在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);
    }
}
相关推荐
拥小抱9 小时前
Compose 知识点
android
文章永久免费只为良心10 小时前
Web应用安全与防护_第三章_日志文件包含_从一道 CTFshow 题目讲透「日志投毒型 LFI → RCE」:原理、时序陷阱与全变种攻防手册
android·网络安全·渗透测试·漏洞危害·漏洞描述·日志投毒·红队指南
AIsoft_868910 小时前
学术讲座录音如何整理?录音APP可行吗
android·iphone
Patrick在香港12 小时前
一个斜杠,把毫秒变成十几秒
android·数据库·python·性能优化·正则表达式·回溯·redos
海雅达手持终端PDA14 小时前
工业手持终端的“去手机化”演进:看海雅达如何以“同轴扫摄”终结工程妥协,重塑工业PDA新范式
android·物联网·智能手机·硬件工程·能源·制造·iot
booboosui15 小时前
删掉一个住在本机的 agent:8 处要清,顺序不能反
android
hcgeng15 小时前
Android获取崩溃日志
android
aqi0015 小时前
AI编程让鸿蒙开发电子书APP更加快捷
android·华为·harmonyos·鸿蒙·harmony
GY-9315 小时前
【Android】Android Studio 中的协程
android