blob: 5ab0da817febcb180ac4c0bd5023c5ec53b2118a [file] [log] [blame] [edit]
/*
* Copyright 2021 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "cros-camera/camera_buffer_utils.h"
#include <hardware/camera3.h>
#include <fstream>
#include <iostream>
#include <base/files/file_util.h>
#include <base/files/memory_mapped_file.h>
#include <drm_fourcc.h>
#include "cros-camera/camera_buffer_manager.h"
#include "cros-camera/common.h"
namespace cros {
bool ReadFileIntoBuffer(buffer_handle_t buffer, base::FilePath file_to_read) {
if (!base::PathExists(file_to_read)) {
LOGF(ERROR) << "File " << file_to_read << " does not exist";
return false;
}
std::ifstream input_file;
input_file.open(file_to_read.value());
if (!input_file.is_open()) {
LOGF(ERROR) << "Failed to load from file: " << file_to_read;
return false;
}
ScopedMapping mapping(buffer);
if (!mapping.is_valid()) {
LOGF(ERROR) << "Failed to mmap buffer";
input_file.close();
return false;
}
size_t total_plane_size = 0;
for (size_t p = 0; p < mapping.num_planes(); ++p) {
total_plane_size += mapping.plane(p).size;
}
input_file.seekg(0, input_file.end);
size_t length = input_file.tellg();
if (length < total_plane_size) {
LOGF(ERROR) << "File " << file_to_read
<< " does not have enough data to fill the buffer";
input_file.close();
return false;
}
size_t offset = 0;
for (size_t p = 0; p < mapping.num_planes(); ++p) {
input_file.seekg(offset, input_file.beg);
auto plane = mapping.plane(p);
input_file.read(reinterpret_cast<char*>(plane.addr), plane.size);
offset += plane.size;
}
input_file.close();
return true;
}
bool WriteBufferIntoFile(buffer_handle_t buffer, base::FilePath file_to_write) {
std::ofstream output_file;
output_file.open(file_to_write.value(), std::ios::binary | std::ios::out);
if (!output_file.is_open()) {
LOGF(ERROR) << "Failed to open output file " << file_to_write;
return false;
}
ScopedMapping mapping(buffer);
if (!mapping.is_valid()) {
LOGF(ERROR) << "Failed to mmap buffer";
output_file.close();
return false;
}
if (mapping.drm_format() == DRM_FORMAT_R8) {
// JPEG blob.
const char* data = reinterpret_cast<const char*>(mapping.plane(0).addr);
const camera3_jpeg_blob_t* jpeg_blob =
reinterpret_cast<const camera3_jpeg_blob_t*>(
data + mapping.plane(0).size - sizeof(camera3_jpeg_blob_t));
CHECK_EQ(jpeg_blob->jpeg_blob_id, CAMERA3_JPEG_BLOB_ID);
output_file.write(data, jpeg_blob->jpeg_size);
} else if (mapping.drm_format() == DRM_FORMAT_NV12) {
for (size_t p = 0; p < mapping.num_planes(); ++p) {
auto plane = mapping.plane(p);
const uint32_t plane_height =
(p == 0) ? mapping.height() : mapping.height() / 2;
for (uint32_t row = 0; row < plane_height; ++row) {
output_file.write(
reinterpret_cast<const char*>(plane.addr + row * plane.stride),
mapping.width());
}
}
} else {
LOGF(ERROR) << "Unsupported buffer format: " << mapping.drm_format();
return false;
}
output_file.close();
return true;
}
} // namespace cros