如何在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);
    }
}
相关推荐
阿华的代码王国2 小时前
【Android】卡片式布局 && 滚动容器ScrollView
android·xml·java·前端·后端·卡片布局·滚动容器
风起云涌~2 小时前
【Android】桌面小组件开发
android·gitee
双鱼大猫4 小时前
从传统播放器到AI智能体:Xplayer 2.0的技术革新之路
android
CYRUS_STUDIO4 小时前
动态篡改 so 函数返回值:一篇带你玩转 Android Hook 技术!
android·c++·逆向
xzkyd outpaper5 小时前
Android中主线程、ActivityThread、ApplicationThread的区别
android·面试
就叫飞六吧6 小时前
mysql全量备份、全量恢复demo
android·mysql·adb
PenguinLetsGo6 小时前
关于 Android16 MOPS 函数指令非法问题
android
xzkyd outpaper8 小时前
Kotlin中Flow
android·开发语言·kotlin
byte轻骑兵8 小时前
【Bluedroid】bta_av_sink_media_callback(BTA_AV_SINK_MEDIA_CFG_EVT)流程源码分析
android·c++·bluedroid
鹏多多.9 小时前
flutter-完美解决键盘弹出遮挡输入框的问题
android·flutter·ios·前端框架