Skip to content

Commit bcff329

Browse files
committed
RASPBERRYPI ONLY: Handle mandatory stream flags
Look for the RAW mandatory stream flag in the pipeline handler config file. If this flag is set, it guarantees that the application will provide buffers for Unicam Image, so override the minUnicamBuffers and minTotalUnicamBuffers config parameters in the following way: - If startup drop frames are required, allocate at least 1 internal buffer. - If no startup drop frames are required, do not allocate any internal buffers. Look for the Output 0 mandatory stream flag in in the pipeline handler config file. If this flag is set, it guarantees that the application will provide buffers for the ISP, do not allocate any internal buffers for the device. Add a new rpi_apps.yaml pipeline handler config file that enables both these flags. To use the file, set the following env variable for a custom build: export LIBCAMERA_RPI_CONFIG_FILE=/usr/local/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml or for a packaged install: export LIBCAMERA_RPI_CONFIG_FILE=/usr/share/libcamera/pipeline/rpi/vc4/rpi_apps.yaml Signed-off-by: Naushir Patuck <[email protected]>
1 parent 1d4b1a7 commit bcff329

File tree

3 files changed

+112
-14
lines changed

3 files changed

+112
-14
lines changed

src/libcamera/pipeline/rpi/vc4/data/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
conf_files = files([
44
'example.yaml',
5+
'rpi_apps.yaml',
56
])
67

78
install_data(conf_files,
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"version": 1.0,
3+
"target": "bcm2835",
4+
5+
"pipeline_handler":
6+
{
7+
# The minimum number of internal buffers to be allocated for
8+
# Unicam. This value must be greater than 0, but less than or
9+
# equal to min_total_unicam_buffers.
10+
#
11+
# A larger number of internal buffers can reduce the occurrence
12+
# of frame drops during high CPU loads, but might also cause
13+
# additional latency in the system.
14+
#
15+
# Note that the pipeline handler might override this value and
16+
# not allocate any internal buffers if it knows they will never
17+
# be used. For example if the RAW stream is marked as mandatory
18+
# and there are no dropped frames signalled for algorithm
19+
# convergence.
20+
#
21+
"min_unicam_buffers": 2,
22+
23+
# The minimum total (internal + external) buffer count used for
24+
# Unicam. The number of internal buffers allocated for Unicam is
25+
# given by:
26+
#
27+
# internal buffer count = max(min_unicam_buffers,
28+
# min_total_unicam_buffers - external buffer count)
29+
#
30+
"min_total_unicam_buffers": 4,
31+
32+
# Override any request from the IPA to drop a number of startup
33+
# frames.
34+
#
35+
# "disable_startup_frame_drops": false,
36+
37+
# The application will always provide a request buffer for the
38+
# RAW stream, if it has been configured.
39+
"raw_mandatory_stream": true,
40+
41+
# The application will always provide a request buffer for the
42+
# Output 0 stream, if it has been configured.
43+
"output0_mandatory_stream": true,
44+
}
45+
}

src/libcamera/pipeline/rpi/vc4/vc4.cpp

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,16 @@ class Vc4CameraData final : public RPi::CameraData
105105
* minTotalUnicamBuffers >= minUnicamBuffers
106106
*/
107107
unsigned int minTotalUnicamBuffers;
108+
/*
109+
* The application will always provide a request buffer for the
110+
* RAW stream, if it has been configured.
111+
*/
112+
bool rawMandatoryStream;
113+
/*
114+
* The application will always provide a request buffer for the
115+
* Output 0 stream, if it has been configured.
116+
*/
117+
bool output0MandatoryStream;
108118
};
109119

110120
Config config_;
@@ -219,42 +229,74 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
219229
int PipelineHandlerVc4::prepareBuffers(Camera *camera)
220230
{
221231
Vc4CameraData *data = cameraData(camera);
222-
unsigned int numRawBuffers = 0;
232+
unsigned int minUnicamBuffers = data->config_.minUnicamBuffers;
233+
unsigned int minTotalUnicamBuffers = data->config_.minTotalUnicamBuffers;
234+
unsigned int numRawBuffers = 0, minIspBuffers = 1;
223235
int ret;
224236

225-
for (Stream *s : camera->streams()) {
226-
if (BayerFormat::fromPixelFormat(s->configuration().pixelFormat).isValid()) {
227-
numRawBuffers = s->configuration().bufferCount;
228-
break;
237+
if (data->unicam_[Unicam::Image].getFlags() & StreamFlag::External) {
238+
numRawBuffers = data->unicam_[Unicam::Image].getBuffers().size();
239+
/*
240+
* If the application provides a guarantees that Unicam
241+
* image buffers will always be provided for the RAW stream
242+
* in a Request, we need:
243+
* - at least 1 internal Unicam buffer to handle startup frame drops,
244+
* - no internal Unicam buffers if there are no startup frame drops.
245+
*/
246+
if (data->config_.rawMandatoryStream) {
247+
if (data->dropFrameCount_) {
248+
minUnicamBuffers = 2;
249+
minTotalUnicamBuffers = 2;
250+
} else {
251+
minUnicamBuffers = 0;
252+
minTotalUnicamBuffers = 0;
253+
}
229254
}
230255
}
231256

257+
if (data->isp_[Isp::Output0].getFlags() & StreamFlag::External) {
258+
/*
259+
* Since the ISP runs synchronous with the IPA and requests,
260+
* we only ever need a maximum of one internal buffer. Any
261+
* buffers the application wants to hold onto will already
262+
* be exported through PipelineHandlerRPi::exportFrameBuffers().
263+
*
264+
* However, as above, if the application provides a guarantee
265+
* that the buffer will always be provided for the ISP Output0
266+
* stream in a Request, we don't need any internal buffers
267+
* allocated.
268+
*/
269+
if (!data->dropFrameCount_ && data->config_.output0MandatoryStream)
270+
minIspBuffers = 0;
271+
}
272+
232273
/* Decide how many internal buffers to allocate. */
233274
for (auto const stream : data->streams_) {
234275
unsigned int numBuffers;
235276
/*
236277
* For Unicam, allocate a minimum number of buffers for internal
237278
* use as we want to avoid any frame drops.
238279
*/
239-
const unsigned int minBuffers = data->config_.minTotalUnicamBuffers;
240280
if (stream == &data->unicam_[Unicam::Image]) {
241281
/*
242282
* If an application has configured a RAW stream, allocate
243283
* additional buffers to make up the minimum, but ensure
244284
* we have at least minUnicamBuffers of internal buffers
245285
* to use to minimise frame drops.
246286
*/
247-
numBuffers = std::max<int>(data->config_.minUnicamBuffers,
248-
minBuffers - numRawBuffers);
287+
numBuffers = std::max<int>(minUnicamBuffers,
288+
minTotalUnicamBuffers - numRawBuffers);
289+
LOG(RPI, Debug) << "Unicam::Image numBuffers " << numBuffers;
249290
} else if (stream == &data->isp_[Isp::Input]) {
250291
/*
251292
* ISP input buffers are imported from Unicam, so follow
252293
* similar logic as above to count all the RAW buffers
253294
* available.
254295
*/
255296
numBuffers = numRawBuffers +
256-
std::max<int>(data->config_.minUnicamBuffers,
257-
minBuffers - numRawBuffers);
297+
std::max<int>(minUnicamBuffers,
298+
minTotalUnicamBuffers - numRawBuffers);
299+
LOG(RPI, Debug) << "Isp::Input numBuffers " << numBuffers;
258300

259301
} else if (stream == &data->unicam_[Unicam::Embedded]) {
260302
/*
@@ -273,14 +315,18 @@ int PipelineHandlerVc4::prepareBuffers(Camera *camera)
273315
* buffers, as these will be recycled quicker.
274316
*/
275317
numBuffers = 12;
318+
} else if (stream == &data->isp_[Isp::Output0]) {
319+
/* Buffer count for this is handled in the earlier loop above. */
320+
numBuffers = minIspBuffers;
321+
LOG(RPI, Debug) << "Isp::Output0 numBuffers " << numBuffers;
276322
} else {
277323
/*
278-
* Since the ISP runs synchronous with the IPA and requests,
279-
* we only ever need one set of internal buffers. Any buffers
280-
* the application wants to hold onto will already be exported
281-
* through PipelineHandlerRPi::exportFrameBuffers().
324+
* Same reasoning as for ISP Output 0, we only ever need
325+
* a maximum of one internal buffer for Output1 (required
326+
* for colour denoise) and ISP statistics.
282327
*/
283328
numBuffers = 1;
329+
LOG(RPI, Debug) << "Other numBuffers " << numBuffers;
284330
}
285331

286332
LOG(RPI, Debug) << "Preparing " << numBuffers
@@ -487,6 +533,8 @@ int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &
487533
config_ = {
488534
.minUnicamBuffers = 2,
489535
.minTotalUnicamBuffers = 4,
536+
.rawMandatoryStream = false,
537+
.output0MandatoryStream = false,
490538
};
491539

492540
if (!root)
@@ -510,6 +558,10 @@ int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &
510558
phConfig["min_unicam_buffers"].get<unsigned int>(config_.minUnicamBuffers);
511559
config_.minTotalUnicamBuffers =
512560
phConfig["min_total_unicam_buffers"].get<unsigned int>(config_.minTotalUnicamBuffers);
561+
config_.rawMandatoryStream =
562+
phConfig["raw_mandatory_stream"].get<bool>(config_.rawMandatoryStream);
563+
config_.output0MandatoryStream =
564+
phConfig["output0_mandatory_stream"].get<bool>(config_.output0MandatoryStream);
513565

514566
if (config_.minTotalUnicamBuffers < config_.minUnicamBuffers) {
515567
LOG(RPI, Error) << "Invalid configuration: min_total_unicam_buffers must be >= min_unicam_buffers";

0 commit comments

Comments
 (0)