Skip to content

Commit 4f6c3ba

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 1e88d5d commit 4f6c3ba

File tree

3 files changed

+112
-14
lines changed

3 files changed

+112
-14
lines changed

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

+1
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,
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

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

109119
Config config_;
@@ -218,42 +228,74 @@ bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
218228
int PipelineHandlerVc4::prepareBuffers(Camera *camera)
219229
{
220230
Vc4CameraData *data = cameraData(camera);
221-
unsigned int numRawBuffers = 0;
231+
unsigned int minUnicamBuffers = data->config_.minUnicamBuffers;
232+
unsigned int minTotalUnicamBuffers = data->config_.minTotalUnicamBuffers;
233+
unsigned int numRawBuffers = 0, minIspBuffers = 1;
222234
int ret;
223235

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

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

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

285331
LOG(RPI, Debug) << "Preparing " << numBuffers
@@ -497,6 +543,8 @@ int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &
497543
config_ = {
498544
.minUnicamBuffers = 2,
499545
.minTotalUnicamBuffers = 4,
546+
.rawMandatoryStream = false,
547+
.output0MandatoryStream = false,
500548
};
501549

502550
if (!root)
@@ -520,6 +568,10 @@ int Vc4CameraData::platformPipelineConfigure(const std::unique_ptr<YamlObject> &
520568
phConfig["min_unicam_buffers"].get<unsigned int>(config_.minUnicamBuffers);
521569
config_.minTotalUnicamBuffers =
522570
phConfig["min_total_unicam_buffers"].get<unsigned int>(config_.minTotalUnicamBuffers);
571+
config_.rawMandatoryStream =
572+
phConfig["raw_mandatory_stream"].get<bool>(config_.rawMandatoryStream);
573+
config_.output0MandatoryStream =
574+
phConfig["output0_mandatory_stream"].get<bool>(config_.output0MandatoryStream);
523575

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

0 commit comments

Comments
 (0)