libcamera: virtual: Speed up test pattern animation
After the initial generation, when a frame is requested, the test pattern generator rotates the image left by 1 column. The current approach has two shortcomings: (1) it allocates a temporary buffer to hold one column; (2) it swaps two columns at a time. The test patterns are simple ARGB images, in row-major order, so doing (2) works against memory prefetching. This can be addressed by doing the rotation one row at a time as that way the image is addressed in a purely linear fashion. Doing so also eliminates the need for a dynamically allocated temporary buffer, as the required buffer now only needs to hold one sample, which is 4 bytes in this case. In an optimized build, this results in about a 2x increase in the number of frames per second as reported by `cam`. In an unoptimized, ASAN and UBSAN intrumented build, the difference is even bigger, which is useful for running lc-compliance in CI in a reasonable time. Signed-off-by: Barnabás Pőcze <pobrn@protonmail.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
This commit is contained in:
parent
fe33e727f2
commit
4f9d8a6301
2 changed files with 23 additions and 38 deletions
|
@ -7,12 +7,34 @@
|
|||
|
||||
#include "test_pattern_generator.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <libcamera/base/log.h>
|
||||
|
||||
#include "libcamera/internal/mapped_framebuffer.h"
|
||||
|
||||
#include <libyuv/convert_from_argb.h>
|
||||
|
||||
namespace {
|
||||
|
||||
template<size_t SampleSize>
|
||||
void rotateLeft1Column(const libcamera::Size &size, uint8_t *image)
|
||||
{
|
||||
if (size.width < 2)
|
||||
return;
|
||||
|
||||
const size_t stride = size.width * SampleSize;
|
||||
uint8_t first[SampleSize];
|
||||
|
||||
for (size_t i = 0; i < size.height; i++, image += stride) {
|
||||
memcpy(first, &image[0], SampleSize);
|
||||
memmove(&image[0], &image[SampleSize], stride - SampleSize);
|
||||
memcpy(&image[stride - SampleSize], first, SampleSize);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace */
|
||||
|
||||
namespace libcamera {
|
||||
|
||||
LOG_DECLARE_CATEGORY(Virtual)
|
||||
|
@ -27,7 +49,7 @@ int TestPatternGenerator::generateFrame(const Size &size,
|
|||
|
||||
const auto &planes = mappedFrameBuffer.planes();
|
||||
|
||||
shiftLeft(size);
|
||||
rotateLeft1Column<kARGBSize>(size, template_.get());
|
||||
|
||||
/* Convert the template_ to the frame buffer */
|
||||
int ret = libyuv::ARGBToNV12(template_.get(), size.width * kARGBSize,
|
||||
|
@ -40,39 +62,6 @@ int TestPatternGenerator::generateFrame(const Size &size,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void TestPatternGenerator::shiftLeft(const Size &size)
|
||||
{
|
||||
/* Store the first column temporarily */
|
||||
auto firstColumn = std::make_unique<uint8_t[]>(size.height * kARGBSize);
|
||||
for (size_t h = 0; h < size.height; h++) {
|
||||
unsigned int index = h * size.width * kARGBSize;
|
||||
unsigned int index1 = h * kARGBSize;
|
||||
firstColumn[index1] = template_[index];
|
||||
firstColumn[index1 + 1] = template_[index + 1];
|
||||
firstColumn[index1 + 2] = template_[index + 2];
|
||||
firstColumn[index1 + 3] = 0x00;
|
||||
}
|
||||
|
||||
/* Overwrite template_ */
|
||||
uint8_t *buf = template_.get();
|
||||
for (size_t h = 0; h < size.height; h++) {
|
||||
for (size_t w = 0; w < size.width - 1; w++) {
|
||||
/* Overwrite with the pixel on the right */
|
||||
unsigned int index = (h * size.width + w + 1) * kARGBSize;
|
||||
*buf++ = template_[index]; /* B */
|
||||
*buf++ = template_[index + 1]; /* G */
|
||||
*buf++ = template_[index + 2]; /* R */
|
||||
*buf++ = 0x00; /* A */
|
||||
}
|
||||
/* Overwrite the new last column with the original first column */
|
||||
unsigned int index1 = h * kARGBSize;
|
||||
*buf++ = firstColumn[index1]; /* B */
|
||||
*buf++ = firstColumn[index1 + 1]; /* G */
|
||||
*buf++ = firstColumn[index1 + 2]; /* R */
|
||||
*buf++ = 0x00; /* A */
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBarsGenerator::configure(const Size &size)
|
||||
{
|
||||
constexpr uint8_t kColorBar[8][3] = {
|
||||
|
|
|
@ -29,10 +29,6 @@ public:
|
|||
protected:
|
||||
/* Buffer of test pattern template */
|
||||
std::unique_ptr<uint8_t[]> template_;
|
||||
|
||||
private:
|
||||
/* Shift the buffer by 1 pixel left each frame */
|
||||
void shiftLeft(const Size &size);
|
||||
};
|
||||
|
||||
class ColorBarsGenerator : public TestPatternGenerator
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue