Message ID | 20200731153320.58107-14-jacopo@jmondi.org |
---|---|
State | Accepted |
Headers | show |
Series |
|
Related | show |
Hi Jacopo, Thanks for your work. On 2020-07-31 17:33:14 +0200, Jacopo Mondi wrote: > Remove the adjustStream() and assignStream() methods, and perform stream > adjustment and assignment while iterating the StreamConfiguration > items. > > The adjustStream() implementation had some arbitrary assumption, like > the main output having to be as large as the sensor resolution, and did > not take into account the different alignment requirements between the > main output and the viewfinder output. > > The assignStream() implementation also assumes only full-size streams > can be produced by the main output, and having it as a separate function > prevents adjusting streams according to which output they are assigned. > > Blend the two implementation in a single loop and perform the required > stream adjustment and assignment in one go. > > As streams are now assigned at validate() time, remove the same > operation from the configure() function. > > Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> > --- > src/libcamera/pipeline/ipu3/ipu3.cpp | 251 ++++++++++++--------------- > 1 file changed, 112 insertions(+), 139 deletions(-) > > diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp > index 22baacf98545..0701fa55381f 100644 > --- a/src/libcamera/pipeline/ipu3/ipu3.cpp > +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp > @@ -70,9 +70,6 @@ public: > const std::vector<const Stream *> &streams() { return streams_; } > > private: > - void assignStreams(); > - void adjustStream(StreamConfiguration &cfg, bool scale); > - > /* > * The IPU3CameraData instance is guaranteed to be valid as long as the > * corresponding Camera instance is valid. In order to borrow a > @@ -137,96 +134,6 @@ IPU3CameraConfiguration::IPU3CameraConfiguration(Camera *camera, > data_ = data; > } > > -void IPU3CameraConfiguration::assignStreams() > -{ > - /* > - * Verify and update all configuration entries, and assign a stream to > - * each of them. The viewfinder stream can scale, while the output > - * stream can crop only, so select the output stream when the requested > - * resolution is equal to the sensor resolution, and the viewfinder > - * stream otherwise. > - */ > - std::set<const Stream *> availableStreams = { > - &data_->outStream_, > - &data_->vfStream_, > - &data_->rawStream_, > - }; > - > - /* > - * The caller is responsible to limit the number of requested streams > - * to a number supported by the pipeline before calling this function. > - */ > - ASSERT(availableStreams.size() >= config_.size()); > - > - streams_.clear(); > - streams_.reserve(config_.size()); > - > - for (const StreamConfiguration &cfg : config_) { > - const PixelFormatInfo &info = > - PixelFormatInfo::info(cfg.pixelFormat); > - const Stream *stream; > - > - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) > - stream = &data_->rawStream_; > - else if (cfg.size == cio2Configuration_.size) > - stream = &data_->outStream_; > - else > - stream = &data_->vfStream_; > - > - if (availableStreams.find(stream) == availableStreams.end()) > - stream = *availableStreams.begin(); > - > - streams_.push_back(stream); > - availableStreams.erase(stream); > - } > -} > - > -void IPU3CameraConfiguration::adjustStream(StreamConfiguration &cfg, bool scale) > -{ > - /* The only pixel format the driver supports is NV12. */ > - cfg.pixelFormat = formats::NV12; > - > - if (scale) { > - /* > - * Provide a suitable default that matches the sensor aspect > - * ratio. > - */ > - if (cfg.size.isNull()) { > - cfg.size.width = 1280; > - cfg.size.height = 1280 * cio2Configuration_.size.height > - / cio2Configuration_.size.width; > - } > - > - /* > - * \todo: Clamp the size to the hardware bounds when we will > - * figure them out. > - * > - * \todo: Handle the scaler (BDS) restrictions. The BDS can > - * only scale with the same factor in both directions, and the > - * scaling factor is limited to a multiple of 1/32. At the > - * moment the ImgU driver hides these constraints by applying > - * additional cropping, this should be fixed on the driver > - * side, and cropping should be exposed to us. > - */ > - } else { > - /* > - * \todo: Properly support cropping when the ImgU driver > - * interface will be cleaned up. > - */ > - cfg.size = cio2Configuration_.size; > - } > - > - /* > - * Clamp the size to match the ImgU alignment constraints. The width > - * shall be a multiple of 8 pixels and the height a multiple of 4 > - * pixels. > - */ > - if (cfg.size.width % 8 || cfg.size.height % 4) { > - cfg.size.width &= ~7; > - cfg.size.height &= ~3; > - } > -} > - > CameraConfiguration::Status IPU3CameraConfiguration::validate() > { > Status status = Valid; > @@ -242,27 +149,27 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() > > /* > * Validate the requested stream configuration and select the sensor > - * format by collecting the maximum width and height and picking the > - * closest larger match, as the IPU3 can downscale only. If no > - * resolution is requested for any stream, or if no sensor resolution is > - * large enough, pick the largest one. > + * format by collecting the maximum RAW stream width and height and > + * picking the closest larger match, as the IPU3 can downscale only. If > + * no resolution is requested for the RAW stream, use the one from the > + * largest YUV stream, plus margins pixels for the IF and BDS to scale. > + * If no resolution is requested for any stream, pick the largest one. > */ > unsigned int rawCount = 0; > unsigned int yuvCount = 0; > - Size size; > + Size maxYuvSize; > + Size maxRawSize; > > for (const StreamConfiguration &cfg : config_) { > const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); > > - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) > + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { > rawCount++; > - else > + maxRawSize.expandTo(cfg.size); > + } else { > yuvCount++; > - > - if (cfg.size.width > size.width) > - size.width = cfg.size.width; > - if (cfg.size.height > size.height) > - size.height = cfg.size.height; > + maxYuvSize.expandTo(cfg.size); > + } > } > > if (rawCount > 1 || yuvCount > 2) { > @@ -270,43 +177,114 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() > return Invalid; > } > > - /* Generate raw configuration from CIO2. */ > - cio2Configuration_ = data_->cio2_.generateConfiguration(size); > + if (maxRawSize.isNull()) > + maxRawSize = maxYuvSize.alignedUpTo(IMGU_OUTPUT_WIDTH_MARGIN, > + IMGU_OUTPUT_HEIGHT_MARGIN) > + .boundedTo(data_->cio2_.sensor()->resolution()); > + > + /* > + * Generate raw configuration from CIO2. > + * > + * The output YUV streams will be limited in size to the maximum > + * frame size requested for the RAW stream. > + */ > + cio2Configuration_ = data_->cio2_.generateConfiguration(maxRawSize); > if (!cio2Configuration_.pixelFormat.isValid()) > return Invalid; > > - /* Assign streams to each configuration entry. */ > - assignStreams(); > + LOG(IPU3, Debug) << "CIO2 configuration: " << cio2Configuration_.toString(); > > - /* Verify and adjust configuration if needed. */ > + /* > + * Adjust the configurations if needed and assign streams while > + * iterating them. > + */ > + bool mainOutputAvailable = true; > for (unsigned int i = 0; i < config_.size(); ++i) { > - StreamConfiguration &cfg = config_[i]; > - const StreamConfiguration oldCfg = cfg; > - const Stream *stream = streams_[i]; > - > - if (stream == &data_->rawStream_) { > - cfg.size = cio2Configuration_.size; > - cfg.pixelFormat = cio2Configuration_.pixelFormat; > - cfg.bufferCount = cio2Configuration_.bufferCount; > + const PixelFormatInfo &info = PixelFormatInfo::info(config_[i].pixelFormat); > + const StreamConfiguration originalCfg = config_[i]; > + StreamConfiguration *cfg = &config_[i]; > + > + LOG(IPU3, Debug) << "Validating stream: " << config_[i].toString(); > + > + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { > + /* Initialize the RAW stream with the CIO2 configuration. */ > + cfg->size = cio2Configuration_.size; > + cfg->pixelFormat = cio2Configuration_.pixelFormat; > + cfg->bufferCount = cio2Configuration_.bufferCount; > + cfg->stride = info.stride(cfg->size.width, 0, 64); > + cfg->frameSize = info.frameSize(cfg->size, 64); > + cfg->setStream(const_cast<Stream *>(&data_->rawStream_)); > + > + LOG(IPU3, Debug) << "Assigned " << cfg->toString() > + << " to the raw stream"; > } else { > - bool scale = stream == &data_->vfStream_; > - adjustStream(config_[i], scale); > - cfg.bufferCount = IPU3_BUFFER_COUNT; > + /* Assign and configure the main and viewfinder outputs. */ > + > + /* > + * Clamp the size to match the ImgU size limits and the > + * margins from the CIO2 output frame size. > + * > + * The ImgU outputs needs to be strictly smaller than > + * the CIO2 output frame and rounded down to 64 pixels > + * in width and 32 pixels in height. This assumption > + * comes from inspecting the pipe configuration script > + * results and the available suggested configurations in > + * the ChromeOS BSP .xml camera tuning files and shall > + * be validated. > + * > + * \todo Clarify what are the hardware constraints > + * that require this alignements, if any. It might > + * depend on the BDS scaling factor of 1/32, as the main > + * output has no YUV scaler as the viewfinder output has. > + */ > + unsigned int limit; > + limit = utils::alignDown(cio2Configuration_.size.width - 1, > + IMGU_OUTPUT_WIDTH_MARGIN); > + cfg->size.width = utils::clamp(cfg->size.width, > + IMGU_OUTPUT_MIN_SIZE.width, > + limit); > + > + limit = utils::alignDown(cio2Configuration_.size.height - 1, > + IMGU_OUTPUT_HEIGHT_MARGIN); > + cfg->size.height = utils::clamp(cfg->size.height, > + IMGU_OUTPUT_MIN_SIZE.height, > + limit); > + > + cfg->size.alignDownTo(IMGU_OUTPUT_WIDTH_ALIGN, > + IMGU_OUTPUT_HEIGHT_ALIGN); > + > + cfg->pixelFormat = formats::NV12; > + cfg->bufferCount = IPU3_BUFFER_COUNT; > + cfg->stride = info.stride(cfg->size.width, 0, 1); > + cfg->frameSize = info.frameSize(cfg->size, 1); > + > + /* > + * Use the main output stream in case only one stream is > + * requested or if the current configuration is the one > + * with the maximum YUV output size. > + */ > + if (mainOutputAvailable && > + (originalCfg.size == maxYuvSize || yuvCount == 1)) { > + cfg->setStream(const_cast<Stream *>(&data_->outStream_)); > + mainOutputAvailable = false; > + > + LOG(IPU3, Debug) << "Assigned " << cfg->toString() > + << " to the main output"; > + } else { > + cfg->setStream(const_cast<Stream *>(&data_->vfStream_)); > + > + LOG(IPU3, Debug) << "Assigned " << cfg->toString() > + << " to the viewfinder output"; > + } > } > > - if (cfg.pixelFormat != oldCfg.pixelFormat || > - cfg.size != oldCfg.size) { > + if (cfg->pixelFormat != originalCfg.pixelFormat || > + cfg->size != originalCfg.size) { > LOG(IPU3, Debug) > << "Stream " << i << " configuration adjusted to " > - << cfg.toString(); > + << cfg->toString(); > status = Adjusted; > } > - > - const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); > - bool packedRaw = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW; > - > - cfg.stride = info.stride(cfg.size.width, 0, packedRaw ? 64 : 1); > - cfg.frameSize = info.frameSize(cfg.size, packedRaw ? 64 : 1); > } > > return status; > @@ -340,6 +318,9 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, > * strictly smaller than the sensor resolution (limited > * to the ImgU maximum output size) and aligned down to > * the required frame margin. > + * > + * \todo Clarify the alignment constraints as exaplained > + * in validate() > */ > size = sensorResolution.boundedTo(IMGU_OUTPUT_MAX_SIZE); > size.width = utils::alignDown(size.width - 1, > @@ -476,16 +457,8 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) > bool vfActive = false; > > for (unsigned int i = 0; i < config->size(); ++i) { > - /* > - * Use a const_cast<> here instead of storing a mutable stream > - * pointer in the configuration to let the compiler catch > - * unwanted modifications of camera data in the configuration > - * validate() implementation. > - */ > - Stream *stream = const_cast<Stream *>(config->streams()[i]); > StreamConfiguration &cfg = (*config)[i]; > - > - cfg.setStream(stream); > + Stream *stream = cfg.stream(); > > if (stream == outStream) { > ret = imgu->configureOutput(cfg, &outputFormat); > -- > 2.27.0 > > _______________________________________________ > libcamera-devel mailing list > libcamera-devel@lists.libcamera.org > https://lists.libcamera.org/listinfo/libcamera-devel
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index 22baacf98545..0701fa55381f 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -70,9 +70,6 @@ public: const std::vector<const Stream *> &streams() { return streams_; } private: - void assignStreams(); - void adjustStream(StreamConfiguration &cfg, bool scale); - /* * The IPU3CameraData instance is guaranteed to be valid as long as the * corresponding Camera instance is valid. In order to borrow a @@ -137,96 +134,6 @@ IPU3CameraConfiguration::IPU3CameraConfiguration(Camera *camera, data_ = data; } -void IPU3CameraConfiguration::assignStreams() -{ - /* - * Verify and update all configuration entries, and assign a stream to - * each of them. The viewfinder stream can scale, while the output - * stream can crop only, so select the output stream when the requested - * resolution is equal to the sensor resolution, and the viewfinder - * stream otherwise. - */ - std::set<const Stream *> availableStreams = { - &data_->outStream_, - &data_->vfStream_, - &data_->rawStream_, - }; - - /* - * The caller is responsible to limit the number of requested streams - * to a number supported by the pipeline before calling this function. - */ - ASSERT(availableStreams.size() >= config_.size()); - - streams_.clear(); - streams_.reserve(config_.size()); - - for (const StreamConfiguration &cfg : config_) { - const PixelFormatInfo &info = - PixelFormatInfo::info(cfg.pixelFormat); - const Stream *stream; - - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) - stream = &data_->rawStream_; - else if (cfg.size == cio2Configuration_.size) - stream = &data_->outStream_; - else - stream = &data_->vfStream_; - - if (availableStreams.find(stream) == availableStreams.end()) - stream = *availableStreams.begin(); - - streams_.push_back(stream); - availableStreams.erase(stream); - } -} - -void IPU3CameraConfiguration::adjustStream(StreamConfiguration &cfg, bool scale) -{ - /* The only pixel format the driver supports is NV12. */ - cfg.pixelFormat = formats::NV12; - - if (scale) { - /* - * Provide a suitable default that matches the sensor aspect - * ratio. - */ - if (cfg.size.isNull()) { - cfg.size.width = 1280; - cfg.size.height = 1280 * cio2Configuration_.size.height - / cio2Configuration_.size.width; - } - - /* - * \todo: Clamp the size to the hardware bounds when we will - * figure them out. - * - * \todo: Handle the scaler (BDS) restrictions. The BDS can - * only scale with the same factor in both directions, and the - * scaling factor is limited to a multiple of 1/32. At the - * moment the ImgU driver hides these constraints by applying - * additional cropping, this should be fixed on the driver - * side, and cropping should be exposed to us. - */ - } else { - /* - * \todo: Properly support cropping when the ImgU driver - * interface will be cleaned up. - */ - cfg.size = cio2Configuration_.size; - } - - /* - * Clamp the size to match the ImgU alignment constraints. The width - * shall be a multiple of 8 pixels and the height a multiple of 4 - * pixels. - */ - if (cfg.size.width % 8 || cfg.size.height % 4) { - cfg.size.width &= ~7; - cfg.size.height &= ~3; - } -} - CameraConfiguration::Status IPU3CameraConfiguration::validate() { Status status = Valid; @@ -242,27 +149,27 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() /* * Validate the requested stream configuration and select the sensor - * format by collecting the maximum width and height and picking the - * closest larger match, as the IPU3 can downscale only. If no - * resolution is requested for any stream, or if no sensor resolution is - * large enough, pick the largest one. + * format by collecting the maximum RAW stream width and height and + * picking the closest larger match, as the IPU3 can downscale only. If + * no resolution is requested for the RAW stream, use the one from the + * largest YUV stream, plus margins pixels for the IF and BDS to scale. + * If no resolution is requested for any stream, pick the largest one. */ unsigned int rawCount = 0; unsigned int yuvCount = 0; - Size size; + Size maxYuvSize; + Size maxRawSize; for (const StreamConfiguration &cfg : config_) { const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); - if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { rawCount++; - else + maxRawSize.expandTo(cfg.size); + } else { yuvCount++; - - if (cfg.size.width > size.width) - size.width = cfg.size.width; - if (cfg.size.height > size.height) - size.height = cfg.size.height; + maxYuvSize.expandTo(cfg.size); + } } if (rawCount > 1 || yuvCount > 2) { @@ -270,43 +177,114 @@ CameraConfiguration::Status IPU3CameraConfiguration::validate() return Invalid; } - /* Generate raw configuration from CIO2. */ - cio2Configuration_ = data_->cio2_.generateConfiguration(size); + if (maxRawSize.isNull()) + maxRawSize = maxYuvSize.alignedUpTo(IMGU_OUTPUT_WIDTH_MARGIN, + IMGU_OUTPUT_HEIGHT_MARGIN) + .boundedTo(data_->cio2_.sensor()->resolution()); + + /* + * Generate raw configuration from CIO2. + * + * The output YUV streams will be limited in size to the maximum + * frame size requested for the RAW stream. + */ + cio2Configuration_ = data_->cio2_.generateConfiguration(maxRawSize); if (!cio2Configuration_.pixelFormat.isValid()) return Invalid; - /* Assign streams to each configuration entry. */ - assignStreams(); + LOG(IPU3, Debug) << "CIO2 configuration: " << cio2Configuration_.toString(); - /* Verify and adjust configuration if needed. */ + /* + * Adjust the configurations if needed and assign streams while + * iterating them. + */ + bool mainOutputAvailable = true; for (unsigned int i = 0; i < config_.size(); ++i) { - StreamConfiguration &cfg = config_[i]; - const StreamConfiguration oldCfg = cfg; - const Stream *stream = streams_[i]; - - if (stream == &data_->rawStream_) { - cfg.size = cio2Configuration_.size; - cfg.pixelFormat = cio2Configuration_.pixelFormat; - cfg.bufferCount = cio2Configuration_.bufferCount; + const PixelFormatInfo &info = PixelFormatInfo::info(config_[i].pixelFormat); + const StreamConfiguration originalCfg = config_[i]; + StreamConfiguration *cfg = &config_[i]; + + LOG(IPU3, Debug) << "Validating stream: " << config_[i].toString(); + + if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW) { + /* Initialize the RAW stream with the CIO2 configuration. */ + cfg->size = cio2Configuration_.size; + cfg->pixelFormat = cio2Configuration_.pixelFormat; + cfg->bufferCount = cio2Configuration_.bufferCount; + cfg->stride = info.stride(cfg->size.width, 0, 64); + cfg->frameSize = info.frameSize(cfg->size, 64); + cfg->setStream(const_cast<Stream *>(&data_->rawStream_)); + + LOG(IPU3, Debug) << "Assigned " << cfg->toString() + << " to the raw stream"; } else { - bool scale = stream == &data_->vfStream_; - adjustStream(config_[i], scale); - cfg.bufferCount = IPU3_BUFFER_COUNT; + /* Assign and configure the main and viewfinder outputs. */ + + /* + * Clamp the size to match the ImgU size limits and the + * margins from the CIO2 output frame size. + * + * The ImgU outputs needs to be strictly smaller than + * the CIO2 output frame and rounded down to 64 pixels + * in width and 32 pixels in height. This assumption + * comes from inspecting the pipe configuration script + * results and the available suggested configurations in + * the ChromeOS BSP .xml camera tuning files and shall + * be validated. + * + * \todo Clarify what are the hardware constraints + * that require this alignements, if any. It might + * depend on the BDS scaling factor of 1/32, as the main + * output has no YUV scaler as the viewfinder output has. + */ + unsigned int limit; + limit = utils::alignDown(cio2Configuration_.size.width - 1, + IMGU_OUTPUT_WIDTH_MARGIN); + cfg->size.width = utils::clamp(cfg->size.width, + IMGU_OUTPUT_MIN_SIZE.width, + limit); + + limit = utils::alignDown(cio2Configuration_.size.height - 1, + IMGU_OUTPUT_HEIGHT_MARGIN); + cfg->size.height = utils::clamp(cfg->size.height, + IMGU_OUTPUT_MIN_SIZE.height, + limit); + + cfg->size.alignDownTo(IMGU_OUTPUT_WIDTH_ALIGN, + IMGU_OUTPUT_HEIGHT_ALIGN); + + cfg->pixelFormat = formats::NV12; + cfg->bufferCount = IPU3_BUFFER_COUNT; + cfg->stride = info.stride(cfg->size.width, 0, 1); + cfg->frameSize = info.frameSize(cfg->size, 1); + + /* + * Use the main output stream in case only one stream is + * requested or if the current configuration is the one + * with the maximum YUV output size. + */ + if (mainOutputAvailable && + (originalCfg.size == maxYuvSize || yuvCount == 1)) { + cfg->setStream(const_cast<Stream *>(&data_->outStream_)); + mainOutputAvailable = false; + + LOG(IPU3, Debug) << "Assigned " << cfg->toString() + << " to the main output"; + } else { + cfg->setStream(const_cast<Stream *>(&data_->vfStream_)); + + LOG(IPU3, Debug) << "Assigned " << cfg->toString() + << " to the viewfinder output"; + } } - if (cfg.pixelFormat != oldCfg.pixelFormat || - cfg.size != oldCfg.size) { + if (cfg->pixelFormat != originalCfg.pixelFormat || + cfg->size != originalCfg.size) { LOG(IPU3, Debug) << "Stream " << i << " configuration adjusted to " - << cfg.toString(); + << cfg->toString(); status = Adjusted; } - - const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat); - bool packedRaw = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW; - - cfg.stride = info.stride(cfg.size.width, 0, packedRaw ? 64 : 1); - cfg.frameSize = info.frameSize(cfg.size, packedRaw ? 64 : 1); } return status; @@ -340,6 +318,9 @@ CameraConfiguration *PipelineHandlerIPU3::generateConfiguration(Camera *camera, * strictly smaller than the sensor resolution (limited * to the ImgU maximum output size) and aligned down to * the required frame margin. + * + * \todo Clarify the alignment constraints as exaplained + * in validate() */ size = sensorResolution.boundedTo(IMGU_OUTPUT_MAX_SIZE); size.width = utils::alignDown(size.width - 1, @@ -476,16 +457,8 @@ int PipelineHandlerIPU3::configure(Camera *camera, CameraConfiguration *c) bool vfActive = false; for (unsigned int i = 0; i < config->size(); ++i) { - /* - * Use a const_cast<> here instead of storing a mutable stream - * pointer in the configuration to let the compiler catch - * unwanted modifications of camera data in the configuration - * validate() implementation. - */ - Stream *stream = const_cast<Stream *>(config->streams()[i]); StreamConfiguration &cfg = (*config)[i]; - - cfg.setStream(stream); + Stream *stream = cfg.stream(); if (stream == outStream) { ret = imgu->configureOutput(cfg, &outputFormat);