实现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);
}
}