From f37b1cb110a8677b5e0c9774149aa82b9fa17eae Mon Sep 17 00:00:00 2001
From: Tomasz Figa <tfiga@chromium.org>
Date: Mon, 23 Feb 2015 15:32:42 +0900
Subject: [PATCH] Rockchip: Implement keyframe requests correctly

Currently, when rk_vepu_update_param() is called with keyframe request
the codingType field in EncoderParameters structure is set to intra
frame. However, every frame, frame counter is evaluated and this field
is overwritten with frame type determined automatically, which results
in ignoring keyframe requests.

To fix this, store keyframe request flag in a separate field and then
use it as additional factor for code determining frame type for next
frame.

BUG=chrome-os-partner:37203
TEST=video_encode_accelerator_unittest (after 4fc28962e2da8b3f278b952c55fefe10487db952); apprtc

Change-Id: I8acd8c5bfa6aded4b2139082b26b773828fc0dc8
Reviewed-on: https://chromium-review.googlesource.com/251970
Reviewed-by: Wu-cheng Li <wuchengli@chromium.org>
Commit-Queue: Tomasz Figa <tfiga@chromium.org>
Tested-by: Tomasz Figa <tfiga@chromium.org>
---
 libv4l-rockchip/libv4l-encplugin-rockchip.c   |  7 ++---
 libv4l-rockchip/libvpu/rk_vepu_interface.h    |  1 -
 libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c | 26 +++++++------------
 libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h    |  2 +-
 4 files changed, 13 insertions(+), 23 deletions(-)

diff --git a/libv4l-rockchip/libv4l-encplugin-rockchip.c b/libv4l-rockchip/libv4l-encplugin-rockchip.c
index 4a7be00..120beb0 100644
--- a/libv4l-rockchip/libv4l-encplugin-rockchip.c
+++ b/libv4l-rockchip/libv4l-encplugin-rockchip.c
@@ -422,11 +422,8 @@ static int ioctl_s_ext_ctrls_locked(struct encoder_context *ctx, int fd,
 		switch (ext_ctrls->controls[i].id) {
 		case V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE:
 			if (ext_ctrls->controls[i].value ==
-					V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED)
-				break;
-			runtime_param_ptr->keyframe_request = true;
-			runtime_param_ptr->keyframe_value = (ext_ctrls->controls[i].value ==
-					V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME);
+					V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME)
+				runtime_param_ptr->keyframe_request = true;
 			break;
 		case V4L2_CID_MPEG_VIDEO_BITRATE:
 			runtime_param_ptr->bitrate = ext_ctrls->controls[i].value;
diff --git a/libv4l-rockchip/libvpu/rk_vepu_interface.h b/libv4l-rockchip/libvpu/rk_vepu_interface.h
index e40812e..b9d93ee 100644
--- a/libv4l-rockchip/libvpu/rk_vepu_interface.h
+++ b/libv4l-rockchip/libvpu/rk_vepu_interface.h
@@ -39,7 +39,6 @@ struct rk_vepu_runtime_param {
   int32_t framerate_denom;
   int32_t bitrate; /* bits per second */
   bool keyframe_request; /* have keyframe request */
-  bool keyframe_value; /* keyframe */
 };
 
 /**
diff --git a/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c b/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c
index ed3cc6e..c14df08 100644
--- a/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c
+++ b/libv4l-rockchip/libvpu/vp8_enc/rk_vp8encapi.c
@@ -129,8 +129,7 @@ static void rk_vp8_encoder_setconfig(struct rk_vp8_encoder *enc,
   enc->cmdl.frameCntTotal = 0;
 
   if (param->keyframe_request) {
-    enc->encIn.codingType =
-      param->keyframe_value ? VP8ENC_INTRA_FRAME : VP8ENC_PREDICTED_FRAME;
+    enc->cmdl.keyframeRequest = true;
   }
 }
 
@@ -213,26 +212,23 @@ static int rk_vp8_encoder_before_encode(struct rk_vp8_encoder *enc) {
     return -1;
   }
 
-  /* Select frame type */
-  if ((cml->intraPicRate != 0) && (enc->intraPeriodCnt >= cml->intraPicRate))
+  /* Code keyframe according to intra period counter
+   * or if requested by client. */
+  if (cml->keyframeRequest ||
+      (cml->intraPicRate != 0 &&
+       enc->intraPeriodCnt >= cml->intraPicRate)) {
     enc->encIn.codingType = VP8ENC_INTRA_FRAME;
-  else
-    enc->encIn.codingType = VP8ENC_PREDICTED_FRAME;
-
-  if (enc->encIn.codingType == VP8ENC_INTRA_FRAME)
     enc->intraPeriodCnt = 0;
+    cml->keyframeRequest = false;
+  } else {
+    enc->encIn.codingType = VP8ENC_PREDICTED_FRAME;
+  }
 
   /* This applies for PREDICTED frames only. By default always predict
    * from the previous frame only. */
   enc->encIn.ipf = VP8ENC_REFERENCE_AND_REFRESH;
   enc->encIn.grf = enc->encIn.arf = VP8ENC_REFERENCE;
 
-  /* Force odd frames to be coded as droppable. */
-  if (cml->droppable && cml->frameCnt & 1) {
-    enc->encIn.codingType = VP8ENC_PREDICTED_FRAME;
-    enc->encIn.ipf = enc->encIn.grf = enc->encIn.arf = VP8ENC_REFERENCE;
-  }
-
   /* Encode one frame */
   ret = VP8EncStrmEncode(enc->encoder, &enc->encIn, &cml->encOut, cml);
   if (ret < 0) {
@@ -602,8 +598,6 @@ void SetDefaultParameter(EncoderParameters* cml) {
   cml->intra16Favor       = 0;
   /* Penalty value for intra mode in intra/inter */
   cml->intraPenalty       = 0;
-  /* Code all odd frames as droppable */
-  cml->droppable          = 0;
 }
 
 void PrintTitle(EncoderParameters* cml) {
diff --git a/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h b/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h
index d37d474..7d5ce70 100644
--- a/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h
+++ b/libv4l-rockchip/libvpu/vp8_enc/vp8encapi.h
@@ -385,7 +385,6 @@ typedef struct
 
   int32_t printPsnr;
   int32_t mvOutput;
-  int32_t droppable;
 
   int32_t intra16Favor;
   int32_t intraPenalty;
@@ -402,6 +401,7 @@ typedef struct
   ma_s ma;            /* Calculate moving average of bitrate */
   uint32_t psnrSum;        /* Calculate average PSNR over encoded frames */
   uint32_t psnrCnt;
+  uint32_t keyframeRequest;
 
   int32_t frameCnt;       /* Frame counter of input file */
   uint64_t frameCntTotal;  /* Frame counter of all frames */
-- 
GitLab