@@ -392,6 +392,31 @@ void do16BitEndianSwap([[maybe_unused]] void *mem, [[maybe_unused]] unsigned int
392
392
#endif
393
393
}
394
394
395
+ void do14bitUnpack (void *mem, unsigned int width, unsigned int height,
396
+ unsigned int stride)
397
+ {
398
+ std::vector<uint8_t > cache (stride);
399
+
400
+ for (unsigned int j = 0 ; j < height; j++) {
401
+ const uint8_t *in = ((uint8_t *)mem) + j * stride;
402
+ uint8_t *out = ((uint8_t *)mem) + j * stride;
403
+ uint8_t *p = cache.data ();
404
+
405
+ std::memcpy (p, in, stride);
406
+ for (unsigned int i = 0 ; i < width; i += 4 , p += 7 ) {
407
+ uint16_t p0 = (p[0 ] << 8 ) | ((p[4 ] & 0x3f ) << 2 );
408
+ uint16_t p1 = (p[1 ] << 8 ) | ((p[4 ] & 0xc0 ) >> 4 ) | ((p[5 ] & 0x0f ) << 4 );
409
+ uint16_t p2 = (p[2 ] << 8 ) | ((p[5 ] & 0xf0 ) >> 2 ) | ((p[6 ] & 0x03 ) << 6 );
410
+ uint16_t p3 = (p[3 ] << 8 ) | (p[6 ] & 0xfc );
411
+
412
+ *(uint16_t *)(out + i * 2 + 0 ) = p0;
413
+ *(uint16_t *)(out + i * 2 + 2 ) = p1;
414
+ *(uint16_t *)(out + i * 2 + 4 ) = p2;
415
+ *(uint16_t *)(out + i * 2 + 6 ) = p3;
416
+ }
417
+ }
418
+ }
419
+
395
420
void downscaleInterleaved3 (void *mem, unsigned int height, unsigned int src_width,
396
421
unsigned int stride)
397
422
{
@@ -1433,6 +1458,15 @@ int PiSPCameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConf
1433
1458
<< " will not be correct. You must use manual camera settings." ;
1434
1459
}
1435
1460
1461
+ /* Ditto for the 14-bit unpacking. */
1462
+ cfe_[Cfe::Output0].clearFlags (StreamFlag::Needs14bitUnpack);
1463
+ if (MediaBusFormatInfo::info (rpiConfig->sensorFormat_ .code ).bitsPerPixel == 14 ) {
1464
+ cfe_[Cfe::Output0].setFlags (StreamFlag::Needs14bitUnpack);
1465
+ LOG (RPI, Warning)
1466
+ << " The sensor is configured for a 14-bit output, statistics"
1467
+ << " will not be correct. You must use manual camera settings." ;
1468
+ }
1469
+
1436
1470
ret = cfe->setFormat (&cfeFormat);
1437
1471
if (ret)
1438
1472
return ret;
@@ -1682,8 +1716,9 @@ void PiSPCameraData::cfeBufferDequeue(FrameBuffer *buffer)
1682
1716
job.buffers [stream] = buffer;
1683
1717
1684
1718
if (stream == &cfe_[Cfe::Output0]) {
1685
- /* Do an endian swap if needed. */
1686
- if (stream->getFlags () & StreamFlag::Needs16bitEndianSwap) {
1719
+ /* Do an endian swap or 14-bit unpacking if needed. */
1720
+ if (stream->getFlags () & StreamFlag::Needs16bitEndianSwap ||
1721
+ stream->getFlags () & StreamFlag::Needs14bitUnpack) {
1687
1722
const unsigned int stride = stream->configuration ().stride ;
1688
1723
const unsigned int width = stream->configuration ().size .width ;
1689
1724
const unsigned int height = stream->configuration ().size .height ;
@@ -1693,7 +1728,12 @@ void PiSPCameraData::cfeBufferDequeue(FrameBuffer *buffer)
1693
1728
void *mem = b.mapped ->planes ()[0 ].data ();
1694
1729
1695
1730
dmabufSyncStart (buffer->planes ()[0 ].fd );
1696
- do16BitEndianSwap (mem, width, height, stride);
1731
+
1732
+ if (stream->getFlags () & StreamFlag::Needs16bitEndianSwap)
1733
+ do16BitEndianSwap (mem, width, height, stride);
1734
+ else
1735
+ do14bitUnpack (mem, width, height, stride);
1736
+
1697
1737
dmabufSyncEnd (buffer->planes ()[0 ].fd );
1698
1738
}
1699
1739
@@ -1861,6 +1901,10 @@ int PiSPCameraData::configureCfe()
1861
1901
pisp_image_format_config image = toPiSPImageFormat (cfeFormat);
1862
1902
pisp_fe_input_config input = {};
1863
1903
1904
+ /* 14-bit bodge */
1905
+ if (cfe_[Cfe::Output0].getFlags () & StreamFlag::Needs14bitUnpack)
1906
+ image.width = image.width * 14 / 16 ;
1907
+
1864
1908
input.streaming = 1 ;
1865
1909
input.format = image;
1866
1910
input.format .format = PISP_IMAGE_FORMAT_BPS_16;
0 commit comments