crosvm: Apply framerate requested on OUTPUT queue to CAPTURE queue.

Currently only the framerate requested on the CAPTURE queue is used to
configure the Chrome encoder's framerate. But according to the V4L2
standard setting the framerate on the OUTPUT queue should also set the
framerate on the CAPTURE queue to the same value.

BUG=b:173668157
TEST=android.media.cts.MediaRecorderTest#testProfileAvcBaselineLevel1

Change-Id: I0753d10d73d52ce4f17fd9bc230d4fa2f06a1b30
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2570833
Reviewed-by: Alexandre Courbot <acourbot@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Tested-by: David Staessens <dstaessens@chromium.org>
Commit-Queue: David Staessens <dstaessens@chromium.org>
diff --git a/devices/src/virtio/video/encoder/encoder.rs b/devices/src/virtio/video/encoder/encoder.rs
index d613f51..a37e8e2 100644
--- a/devices/src/virtio/video/encoder/encoder.rs
+++ b/devices/src/virtio/video/encoder/encoder.rs
@@ -72,6 +72,7 @@
     pub dst_profile: Profile,
     pub dst_bitrate: u32,
     pub dst_h264_level: Option<Level>,
+    pub frame_rate: u32,
 }
 
 #[derive(Debug)]
@@ -181,7 +182,6 @@
         dst_params: &mut Params,
         desired_format: Format,
         buffer_size: u32,
-        frame_rate: u32,
     ) -> Result<()> {
         // TODO(alexlau): Should the first be the default?
         let format_desc = self
@@ -201,7 +201,6 @@
             plane_size: buffer_size,
             stride: 0,
         }];
-        dst_params.frame_rate = frame_rate;
         Ok(())
     }
 
diff --git a/devices/src/virtio/video/encoder/libvda_encoder.rs b/devices/src/virtio/video/encoder/libvda_encoder.rs
index c2b2b48..f8d9898 100644
--- a/devices/src/virtio/video/encoder/libvda_encoder.rs
+++ b/devices/src/virtio/video/encoder/libvda_encoder.rs
@@ -208,10 +208,10 @@
             input_visible_height: config.src_params.frame_height,
             output_profile,
             initial_bitrate: config.dst_bitrate,
-            initial_framerate: if config.dst_params.frame_rate == 0 {
+            initial_framerate: if config.frame_rate == 0 {
                 None
             } else {
-                Some(config.dst_params.frame_rate)
+                Some(config.frame_rate)
             },
             h264_output_level: config.dst_h264_level.map(|level| {
                 // This value is aligned to the H264 standard definition of SPS.level_idc.
diff --git a/devices/src/virtio/video/encoder/mod.rs b/devices/src/virtio/video/encoder/mod.rs
index 7a607af..29dcbd1 100644
--- a/devices/src/virtio/video/encoder/mod.rs
+++ b/devices/src/virtio/video/encoder/mod.rs
@@ -77,6 +77,7 @@
     dst_bitrate: u32,
     dst_profile: Profile,
     dst_h264_level: Option<Level>,
+    frame_rate: u32,
 
     encoder_session: Option<T>,
     received_input_buffers_event: bool,
@@ -129,12 +130,7 @@
         // rate, because VEA's request_encoding_params_change requires both framerate and
         // bitrate to be specified.
         cros_capabilities
-            .populate_dst_params(
-                &mut dst_params,
-                desired_format,
-                DEFAULT_BUFFER_SIZE,
-                /* fps= */ DEFAULT_FPS,
-            )
+            .populate_dst_params(&mut dst_params, desired_format, DEFAULT_BUFFER_SIZE)
             .map_err(|_| VideoError::InvalidArgument)?;
         // `format` is an Option since for the decoder, it is not populated until decoding has
         // started. for encoder, format should always be populated.
@@ -157,6 +153,7 @@
             dst_bitrate: DEFAULT_BITRATE,
             dst_profile,
             dst_h264_level,
+            frame_rate: DEFAULT_FPS,
             encoder_session: None,
             received_input_buffers_event: false,
             src_resources: Default::default(),
@@ -192,6 +189,7 @@
                 dst_profile: self.dst_profile,
                 dst_bitrate: self.dst_bitrate,
                 dst_h264_level: self.dst_h264_level.clone(),
+                frame_rate: self.frame_rate,
             })
             .map_err(|_| VideoError::InvalidOperation)?;
 
@@ -975,6 +973,12 @@
                         plane_formats[0].stride,
                     )
                     .map_err(VideoError::EncoderImpl)?;
+
+                // Following the V4L2 standard the framerate requested on the
+                // input queue should also be applied to the output queue.
+                if frame_rate > 0 {
+                    stream.frame_rate = frame_rate;
+                }
             }
             QueueType::Output => {
                 let desired_format = format.or(stream.dst_params.format).unwrap_or(Format::H264);
@@ -989,10 +993,13 @@
                         &mut stream.dst_params,
                         desired_format,
                         plane_formats[0].plane_size,
-                        frame_rate,
                     )
                     .map_err(VideoError::EncoderImpl)?;
 
+                if frame_rate > 0 {
+                    stream.frame_rate = frame_rate;
+                }
+
                 // Format is always populated for encoder.
                 let new_format = stream
                     .dst_params
@@ -1110,8 +1117,8 @@
         match ctrl_val {
             CtrlVal::Bitrate(bitrate) => {
                 if let Some(ref mut encoder_session) = stream.encoder_session {
-                    if let Err(e) = encoder_session
-                        .request_encoding_params_change(bitrate, stream.dst_params.frame_rate)
+                    if let Err(e) =
+                        encoder_session.request_encoding_params_change(bitrate, stream.frame_rate)
                     {
                         error!(
                             "failed to dynamically request encoding params change: {}",