cam: file_sink: Add support for DNG output

Add support for outputting buffers in DNG format. It reuses the DNG
writer that we had previously in qcam.

Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
Paul Elder 2022-10-17 20:33:23 +09:00
parent bb394442ab
commit 6404b163bc
5 changed files with 43 additions and 10 deletions

View file

@ -207,10 +207,10 @@ int CameraSession::start()
if (options_.isSet(OptFile)) { if (options_.isSet(OptFile)) {
if (!options_[OptFile].toString().empty()) if (!options_[OptFile].toString().empty())
sink_ = std::make_unique<FileSink>(streamNames_, sink_ = std::make_unique<FileSink>(camera_.get(), streamNames_,
options_[OptFile]); options_[OptFile]);
else else
sink_ = std::make_unique<FileSink>(streamNames_); sink_ = std::make_unique<FileSink>(camera_.get(), streamNames_);
} }
if (sink_) { if (sink_) {

View file

@ -15,14 +15,16 @@
#include <libcamera/camera.h> #include <libcamera/camera.h>
#include "dng_writer.h"
#include "file_sink.h" #include "file_sink.h"
#include "image.h" #include "image.h"
using namespace libcamera; using namespace libcamera;
FileSink::FileSink(const std::map<const libcamera::Stream *, std::string> &streamNames, FileSink::FileSink(const libcamera::Camera *camera,
const std::map<const libcamera::Stream *, std::string> &streamNames,
const std::string &pattern) const std::string &pattern)
: streamNames_(streamNames), pattern_(pattern) : camera_(camera), streamNames_(streamNames), pattern_(pattern)
{ {
} }
@ -51,12 +53,13 @@ void FileSink::mapBuffer(FrameBuffer *buffer)
bool FileSink::processRequest(Request *request) bool FileSink::processRequest(Request *request)
{ {
for (auto [stream, buffer] : request->buffers()) for (auto [stream, buffer] : request->buffers())
writeBuffer(stream, buffer); writeBuffer(stream, buffer, request->metadata());
return true; return true;
} }
void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer) void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer,
[[maybe_unused]] const ControlList &metadata)
{ {
std::string filename; std::string filename;
size_t pos; size_t pos;
@ -65,6 +68,10 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer)
if (!pattern_.empty()) if (!pattern_.empty())
filename = pattern_; filename = pattern_;
#ifdef HAVE_TIFF
bool dng = filename.find(".dng", filename.size() - 4) != std::string::npos;
#endif /* HAVE_TIFF */
if (filename.empty() || filename.back() == '/') if (filename.empty() || filename.back() == '/')
filename += "frame-#.bin"; filename += "frame-#.bin";
@ -76,6 +83,21 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer)
filename.replace(pos, 1, ss.str()); filename.replace(pos, 1, ss.str());
} }
Image *image = mappedBuffers_[buffer].get();
#ifdef HAVE_TIFF
if (dng) {
ret = DNGWriter::write(filename.c_str(), camera_,
stream->configuration(), metadata,
buffer, image->data(0).data());
if (ret < 0)
std::cerr << "failed to write DNG file `" << filename
<< "'" << std::endl;
return;
}
#endif /* HAVE_TIFF */
fd = open(filename.c_str(), O_CREAT | O_WRONLY | fd = open(filename.c_str(), O_CREAT | O_WRONLY |
(pos == std::string::npos ? O_APPEND : O_TRUNC), (pos == std::string::npos ? O_APPEND : O_TRUNC),
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
@ -86,8 +108,6 @@ void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer)
return; return;
} }
Image *image = mappedBuffers_[buffer].get();
for (unsigned int i = 0; i < buffer->planes().size(); ++i) { for (unsigned int i = 0; i < buffer->planes().size(); ++i) {
const FrameMetadata::Plane &meta = buffer->metadata().planes()[i]; const FrameMetadata::Plane &meta = buffer->metadata().planes()[i];

View file

@ -20,7 +20,8 @@ class Image;
class FileSink : public FrameSink class FileSink : public FrameSink
{ {
public: public:
FileSink(const std::map<const libcamera::Stream *, std::string> &streamNames, FileSink(const libcamera::Camera *camera,
const std::map<const libcamera::Stream *, std::string> &streamNames,
const std::string &pattern = ""); const std::string &pattern = "");
~FileSink(); ~FileSink();
@ -32,8 +33,10 @@ public:
private: private:
void writeBuffer(const libcamera::Stream *stream, void writeBuffer(const libcamera::Stream *stream,
libcamera::FrameBuffer *buffer); libcamera::FrameBuffer *buffer,
const libcamera::ControlList &metadata);
const libcamera::Camera *camera_;
std::map<const libcamera::Stream *, std::string> streamNames_; std::map<const libcamera::Stream *, std::string> streamNames_;
std::string pattern_; std::string pattern_;
std::map<libcamera::FrameBuffer *, std::unique_ptr<Image>> mappedBuffers_; std::map<libcamera::FrameBuffer *, std::unique_ptr<Image>> mappedBuffers_;

View file

@ -144,6 +144,8 @@ int CamApp::parseOptions(int argc, char *argv[])
"to write files, using the default file name. Otherwise it sets the\n" "to write files, using the default file name. Otherwise it sets the\n"
"full file path and name. The first '#' character in the file name\n" "full file path and name. The first '#' character in the file name\n"
"is expanded to the camera index, stream name and frame sequence number.\n" "is expanded to the camera index, stream name and frame sequence number.\n"
"If the file name ends with '.dng', then the frame will be written to\n"
"the output file(s) in DNG format.\n"
"The default file name is 'frame-#.bin'.", "The default file name is 'frame-#.bin'.",
"file", ArgumentOptional, "filename", false, "file", ArgumentOptional, "filename", false,
OptCamera); OptCamera);

View file

@ -52,6 +52,13 @@ if libsdl2.found()
endif endif
endif endif
if libtiff.found()
cam_cpp_args += ['-DHAVE_TIFF']
cam_sources += files([
'dng_writer.cpp',
])
endif
cam = executable('cam', cam_sources, cam = executable('cam', cam_sources,
dependencies : [ dependencies : [
libatomic, libatomic,
@ -60,6 +67,7 @@ cam = executable('cam', cam_sources,
libevent, libevent,
libjpeg, libjpeg,
libsdl2, libsdl2,
libtiff,
libyaml, libyaml,
], ],
cpp_args : cam_cpp_args, cpp_args : cam_cpp_args,