pipeline: simple: Take the capture Bayer order from the reported media bus code When the media bus code that reaches the video node differs from the one the pipeline was enumerated with, the simple pipeline handler recomputes the Bayer order for the capture device by applying the configured transform to the sensor's native order. That assumes the sensor's flip controls mirror the pixel array and nothing else, so that the order after flipping is the mirror of the order before it. The OV13858 on the Microsoft Surface Pro 12in breaks that assumption. It reports V4L2_CTRL_FLAG_MODIFY_LAYOUT on V4L2_CID_HFLIP, so libcamera treats flips as altering the Bayer order, and the sensor is mounted upside down (camera_sensor_rotation is 180), so libcamera flips it to compensate. The driver, however, keeps reporting SRGGB10_1X10 in every flip state, and measurements off the CAMSS RDI video node with the sensor's own colour bar pattern show that the flipped sensor really does emit RGGB, while the derived order is GBRG: flips 0/0: greens on (0,0)/(1,1), i.e. GBRG emitted, SRGGB10 reported flips 1/1: greens on (0,1)/(1,0), i.e. RGGB emitted, SRGGB10 reported The capture device is therefore configured as GBRG while every subdev along the pipeline reports RGGB. camss validates exactly that pair in its video_check_format(), so VIDIOC_STREAMON fails and the camera never produces a frame: ERROR V4L2 v4l2_videodevice.cpp:1998 /dev/video2[57:cap]: Failed to start streaming: Broken pipe Derive the order from the code the pipeline actually reports instead. For a sensor whose driver does change its code on flip the two are identical, so nothing changes there, and for a driver that compensates the flip internally the capture device now agrees with the subdev it is fed from. --- a/src/libcamera/pipeline/simple/simple.cpp +++ b/src/libcamera/pipeline/simple/simple.cpp @@ -1529,12 +1529,19 @@ videoFormat = video->toV4L2PixelFormat(pipeConfig->captureFormat); } else { /* - * Bayer pattern has changed because of the transform that was applied on - * the sensor. Get the V4L2PixelFormat corresponding to the configured Bayer - * pattern. + * The media bus code reaching the video node is not the one the + * pipeline was enumerated with, which for a Bayer sensor means + * the pattern changed, typically because a transform was + * applied to the sensor. + * + * Take the order from the code the pipeline actually reports + * rather than deriving it from the transform. A driver is free + * to compensate a flip internally, in which case the derived + * order and the reported one disagree, and it is the reported + * one that the capture device is validated against. */ BayerFormat cfgBayer = BayerFormat::fromPixelFormat(pipeConfig->captureFormat); - cfgBayer.order = data->sensor_->bayerOrder(config->combinedTransform()); + cfgBayer.order = BayerFormat::fromMbusCode(format.code).order; videoFormat = cfgBayer.toV4L2PixelFormat(); }