[x264-devel] commit: Smarter QPRD (Jason Garrett-Glaser )

git version control git at videolan.org
Mon Feb 15 10:07:46 CET 2010


x264 | branch: master | Jason Garrett-Glaser <darkshikari at gmail.com> | Wed Feb  3 20:01:16 2010 -0800| [346165169775c5884a9e964afc253561bb11e2ca] | committer: Jason Garrett-Glaser 

Smarter QPRD
Catch some cases in which RD checks can be avoided; reduces QPRD RD calls by 10-20%.

> http://git.videolan.org/gitweb.cgi/x264.git/?a=commit;h=346165169775c5884a9e964afc253561bb11e2ca
---

 encoder/analyse.c |   42 ++++++++++++++++++++++++++++++++++++++----
 1 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/encoder/analyse.c b/encoder/analyse.c
index c15bf8f..1d48b7d 100644
--- a/encoder/analyse.c
+++ b/encoder/analyse.c
@@ -2307,9 +2307,10 @@ static inline void x264_mb_analyse_qp_rd( x264_t *h, x264_mb_analysis_t *a )
     int orig_qp = h->mb.i_qp, bqp = h->mb.i_qp;
     int last_qp_tried = 0;
     origcost = bcost = x264_rd_cost_mb( h, a->i_lambda2 );
+    int origcbp = h->mb.cbp[h->mb.i_mb_xy];
 
     /* If CBP is already zero, don't raise the quantizer any higher. */
-    for( direction = h->mb.cbp[h->mb.i_mb_xy] ? 1 : -1; direction >= -1; direction-=2 )
+    for( direction = origcbp ? 1 : -1; direction >= -1; direction-=2 )
     {
         /* Without psy-RD, require monotonicity when moving quant away from previous
          * macroblock's quant; allow 1 failure when moving quant towards previous quant.
@@ -2324,14 +2325,47 @@ static inline void x264_mb_analyse_qp_rd( x264_t *h, x264_mb_analysis_t *a )
         h->mb.i_qp = orig_qp;
         failures = 0;
         prevcost = origcost;
+
+        /* If the current QP results in an empty CBP, it's highly likely that lower QPs
+         * (up to a point) will too.  So, jump down to where the threshold will kick in
+         * and check the QP there.  If the CBP is still empty, skip the main loop.
+         * If it isn't empty, we would have ended up having to check this QP anyways,
+         * so as long as we store it for later lookup, we lose nothing. */
+        int already_checked_qp = -1;
+        int already_checked_cost = COST_MAX;
+        if( direction == -1 )
+        {
+            if( !origcbp )
+            {
+                h->mb.i_qp = X264_MAX( h->mb.i_qp - threshold - 1, h->param.rc.i_qp_min );
+                h->mb.i_chroma_qp = h->chroma_qp_table[h->mb.i_qp];
+                already_checked_cost = x264_rd_cost_mb( h, a->i_lambda2 );
+                if( !h->mb.cbp[h->mb.i_mb_xy] )
+                {
+                    /* If our empty-CBP block is lower QP than the last QP,
+                     * the last QP almost surely doesn't have a CBP either. */
+                    if( h->mb.i_last_qp > h->mb.i_qp )
+                        last_qp_tried = 1;
+                    break;
+                }
+                already_checked_qp = h->mb.i_qp;
+                h->mb.i_qp = orig_qp;
+            }
+        }
+
         h->mb.i_qp += direction;
         while( h->mb.i_qp >= h->param.rc.i_qp_min && h->mb.i_qp <= h->param.rc.i_qp_max )
         {
             if( h->mb.i_last_qp == h->mb.i_qp )
                 last_qp_tried = 1;
-            h->mb.i_chroma_qp = h->chroma_qp_table[h->mb.i_qp];
-            cost = x264_rd_cost_mb( h, a->i_lambda2 );
-            COPY2_IF_LT( bcost, cost, bqp, h->mb.i_qp );
+            if( h->mb.i_qp == already_checked_qp )
+                cost = already_checked_cost;
+            else
+            {
+                h->mb.i_chroma_qp = h->chroma_qp_table[h->mb.i_qp];
+                cost = x264_rd_cost_mb( h, a->i_lambda2 );
+                COPY2_IF_LT( bcost, cost, bqp, h->mb.i_qp );
+            }
 
             /* We can't assume that the costs are monotonic over QPs.
              * Tie case-as-failure seems to give better results. */



More information about the x264-devel mailing list