Message ID | 20230619060242.37020-1-umang.jain@ideasonboard.com |
---|---|
State | Superseded |
Headers | show |
Series |
|
Related | show |
Hi John, Lee, Quoting Umang Jain via libcamera-devel (2023-06-19 07:02:42) > From: john <john@arducam.com> > > Adds the PDAF support for IMX519 camera module by Arducam. > > Signed-off-by: Umang Jain <umang.jain@ideasonboard.com> > Tested-by: Umang Jain <umang.jain@ideasonboard.com> > --- > Changes in v2: > - Add author's Name "john <john@arducam.com>" To be able to integrate support for the IMX519 in libcamera we need to be able to certify the origin of the code, as we document here: https://libcamera.org/contributing.html#developer-s-certificate-of-origin This follows the https://developercertificate.org/ and ensures that we can legally attibute the authorship of every line of code within the project and that the code has been contributed to open source and protects against issues of copyright claims. Could we get a fully formed Signed-off-by: tag for this code from Arducam please? This should be in the following form: Signed-off-by: Legal Name <valid@email.address> For example, I would sign with: Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Providing this for the code can be done simply by replying to this mail/patch with the tag specified to state that the code supplied below was authored by you, and is suitable for integration. Regards -- Kieran > - Add Tested-by: tag > > Question: S-o-B by author is still missing on origin commit, should I > externally add it? > --- > src/ipa/rpi/cam_helper/cam_helper_imx519.cpp | 50 ++++++++++++++++++++ > src/ipa/rpi/vc4/data/imx519.json | 40 ++++++++++++++++ > 2 files changed, 90 insertions(+) > > diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp > index c7262aa0..6d032082 100644 > --- a/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp > +++ b/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp > @@ -15,9 +15,13 @@ > > #include <libcamera/base/log.h> > > +#include "controller/pdaf_data.h" > + > #include "cam_helper.h" > #include "md_parser.h" > > +#define ALIGN_UP(x, a) (((x) + (a)-1) & ~(a - 1)) > + > using namespace RPiController; > using namespace libcamera; > using libcamera::utils::Duration; > @@ -66,8 +70,13 @@ private: > /* Largest long exposure scale factor given as a left shift on the frame length. */ > static constexpr int longExposureShiftMax = 7; > > + static constexpr int pdafStatsRows = 12; > + static constexpr int pdafStatsCols = 16; > + > void populateMetadata(const MdParser::RegisterMap ®isters, > Metadata &metadata) const override; > + static bool parsePdafData(const uint8_t *ptr, size_t len, unsigned bpp, > + PdafRegions &pdaf); > }; > > CamHelperImx519::CamHelperImx519() > @@ -90,6 +99,11 @@ void CamHelperImx519::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m > MdParser::RegisterMap registers; > DeviceStatus deviceStatus; > > + LOG(IPARPI, Debug) << "Embedded buffer size: " << buffer.size(); > + > + size_t bytesPerLine = (mode_.width * mode_.bitdepth) >> 3; > + bytesPerLine = ALIGN_UP(bytesPerLine, 16); > + > if (metadata.get("device.status", deviceStatus)) { > LOG(IPARPI, Error) << "DeviceStatus not found from DelayedControls"; > return; > @@ -97,6 +111,14 @@ void CamHelperImx519::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m > > parseEmbeddedData(buffer, metadata); > > + if (buffer.size() > 2 * bytesPerLine) { > + PdafRegions pdaf; > + parsePdafData(&buffer[2 * bytesPerLine], > + buffer.size() - 2 * bytesPerLine, > + mode_.bitdepth, pdaf); > + metadata.set("pdaf.data", pdaf); > + } > + > /* > * The DeviceStatus struct is first populated with values obtained from > * DelayedControls. If this reports frame length is > frameLengthMax, > @@ -188,6 +210,34 @@ void CamHelperImx519::populateMetadata(const MdParser::RegisterMap ®isters, > metadata.set("device.status", deviceStatus); > } > > +bool CamHelperImx519::parsePdafData(const uint8_t *ptr, size_t len, > + unsigned bpp, PdafRegions &pdaf) > +{ > + size_t step = bpp >> 1; /* bytes per PDAF grid entry */ > + > + if (bpp < 10 || bpp > 12 || len < 194 * step || ptr[0] != 0 || ptr[1] >= 0x40) { > + LOG(IPARPI, Error) << "PDAF data in unsupported format"; > + return false; > + } > + > + pdaf.init({ pdafStatsCols, pdafStatsRows }); > + > + ptr += 2 * step; > + for (unsigned i = 0; i < pdafStatsRows; ++i) { > + for (unsigned j = 0; j < pdafStatsCols; ++j) { > + unsigned c = (ptr[0] << 3) | (ptr[1] >> 5); > + int p = (((ptr[1] & 0x0F) - (ptr[1] & 0x10)) << 6) | (ptr[2] >> 2); > + PdafData pdafData; > + pdafData.conf = c; > + pdafData.phase = c ? p : 0; > + pdaf.set(libcamera::Point(j, i), { pdafData, 1, 0 }); > + ptr += step; > + } > + } > + > + return true; > +} > + > static CamHelper *create() > { > return new CamHelperImx519(); > diff --git a/src/ipa/rpi/vc4/data/imx519.json b/src/ipa/rpi/vc4/data/imx519.json > index 1b0a7747..0733d97e 100644 > --- a/src/ipa/rpi/vc4/data/imx519.json > +++ b/src/ipa/rpi/vc4/data/imx519.json > @@ -350,6 +350,46 @@ > ] > } > }, > + { > + "rpi.af": > + { > + "ranges": > + { > + "normal": > + { > + "min": 0.0, > + "max": 12.0, > + "default": 1.0 > + }, > + "macro": > + { > + "min": 3.0, > + "max": 15.0, > + "default": 4.0 > + } > + }, > + "speeds": > + { > + "normal": > + { > + "step_coarse": 1.0, > + "step_fine": 0.25, > + "contrast_ratio": 0.75, > + "pdaf_gain": -0.02, > + "pdaf_squelch": 0.125, > + "max_slew": 2.0, > + "pdaf_frames": 20, > + "dropout_frames": 6, > + "step_frames": 4 > + } > + }, > + "conf_epsilon": 8, > + "conf_thresh": 16, > + "conf_clip": 512, > + "skip_frames": 5, > + "map": [ 0.0, 0.0, 15.0, 4095 ] > + } > + }, > { > "rpi.ccm": > { > -- > 2.39.1 >
diff --git a/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp b/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp index c7262aa0..6d032082 100644 --- a/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp +++ b/src/ipa/rpi/cam_helper/cam_helper_imx519.cpp @@ -15,9 +15,13 @@ #include <libcamera/base/log.h> +#include "controller/pdaf_data.h" + #include "cam_helper.h" #include "md_parser.h" +#define ALIGN_UP(x, a) (((x) + (a)-1) & ~(a - 1)) + using namespace RPiController; using namespace libcamera; using libcamera::utils::Duration; @@ -66,8 +70,13 @@ private: /* Largest long exposure scale factor given as a left shift on the frame length. */ static constexpr int longExposureShiftMax = 7; + static constexpr int pdafStatsRows = 12; + static constexpr int pdafStatsCols = 16; + void populateMetadata(const MdParser::RegisterMap ®isters, Metadata &metadata) const override; + static bool parsePdafData(const uint8_t *ptr, size_t len, unsigned bpp, + PdafRegions &pdaf); }; CamHelperImx519::CamHelperImx519() @@ -90,6 +99,11 @@ void CamHelperImx519::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m MdParser::RegisterMap registers; DeviceStatus deviceStatus; + LOG(IPARPI, Debug) << "Embedded buffer size: " << buffer.size(); + + size_t bytesPerLine = (mode_.width * mode_.bitdepth) >> 3; + bytesPerLine = ALIGN_UP(bytesPerLine, 16); + if (metadata.get("device.status", deviceStatus)) { LOG(IPARPI, Error) << "DeviceStatus not found from DelayedControls"; return; @@ -97,6 +111,14 @@ void CamHelperImx519::prepare(libcamera::Span<const uint8_t> buffer, Metadata &m parseEmbeddedData(buffer, metadata); + if (buffer.size() > 2 * bytesPerLine) { + PdafRegions pdaf; + parsePdafData(&buffer[2 * bytesPerLine], + buffer.size() - 2 * bytesPerLine, + mode_.bitdepth, pdaf); + metadata.set("pdaf.data", pdaf); + } + /* * The DeviceStatus struct is first populated with values obtained from * DelayedControls. If this reports frame length is > frameLengthMax, @@ -188,6 +210,34 @@ void CamHelperImx519::populateMetadata(const MdParser::RegisterMap ®isters, metadata.set("device.status", deviceStatus); } +bool CamHelperImx519::parsePdafData(const uint8_t *ptr, size_t len, + unsigned bpp, PdafRegions &pdaf) +{ + size_t step = bpp >> 1; /* bytes per PDAF grid entry */ + + if (bpp < 10 || bpp > 12 || len < 194 * step || ptr[0] != 0 || ptr[1] >= 0x40) { + LOG(IPARPI, Error) << "PDAF data in unsupported format"; + return false; + } + + pdaf.init({ pdafStatsCols, pdafStatsRows }); + + ptr += 2 * step; + for (unsigned i = 0; i < pdafStatsRows; ++i) { + for (unsigned j = 0; j < pdafStatsCols; ++j) { + unsigned c = (ptr[0] << 3) | (ptr[1] >> 5); + int p = (((ptr[1] & 0x0F) - (ptr[1] & 0x10)) << 6) | (ptr[2] >> 2); + PdafData pdafData; + pdafData.conf = c; + pdafData.phase = c ? p : 0; + pdaf.set(libcamera::Point(j, i), { pdafData, 1, 0 }); + ptr += step; + } + } + + return true; +} + static CamHelper *create() { return new CamHelperImx519(); diff --git a/src/ipa/rpi/vc4/data/imx519.json b/src/ipa/rpi/vc4/data/imx519.json index 1b0a7747..0733d97e 100644 --- a/src/ipa/rpi/vc4/data/imx519.json +++ b/src/ipa/rpi/vc4/data/imx519.json @@ -350,6 +350,46 @@ ] } }, + { + "rpi.af": + { + "ranges": + { + "normal": + { + "min": 0.0, + "max": 12.0, + "default": 1.0 + }, + "macro": + { + "min": 3.0, + "max": 15.0, + "default": 4.0 + } + }, + "speeds": + { + "normal": + { + "step_coarse": 1.0, + "step_fine": 0.25, + "contrast_ratio": 0.75, + "pdaf_gain": -0.02, + "pdaf_squelch": 0.125, + "max_slew": 2.0, + "pdaf_frames": 20, + "dropout_frames": 6, + "step_frames": 4 + } + }, + "conf_epsilon": 8, + "conf_thresh": 16, + "conf_clip": 512, + "skip_frames": 5, + "map": [ 0.0, 0.0, 15.0, 4095 ] + } + }, { "rpi.ccm": {