[x265] [PATCH 1 of 2] encoder: if zero-latency, encode each picture in single call

Steve Borho steve at borho.org
Wed Jan 21 18:21:34 CET 2015


# HG changeset patch
# User Steve Borho <steve at borho.org>
# Date 1421860810 21600
#      Wed Jan 21 11:20:10 2015 -0600
# Node ID 7aec6406358de473ffe6ec97fa3916cc95a2307c
# Parent  3f7902a3e5e418a192f3d933ead1fa0b0e15349e
encoder: if zero-latency, encode each picture in single call

This patch deliberately doesn't change indentation so the logic changes are
clear. It's fairly ugly but I can't think of a cleaner method to handle the
problem.

diff -r 3f7902a3e5e4 -r 7aec6406358d source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Wed Jan 21 10:17:14 2015 -0600
+++ b/source/encoder/encoder.cpp	Wed Jan 21 11:20:10 2015 -0600
@@ -257,6 +257,8 @@
         }
     }
 
+    m_bZeroLatency = !m_param->bframes && !m_param->lookaheadDepth && m_param->frameNumThreads == 1;
+
     m_aborted |= parseLambdaFile(m_param);
 
     m_encodeStartTime = x265_mdate();
@@ -488,10 +490,21 @@
     m_curEncoder = (m_curEncoder + 1) % m_param->frameNumThreads;
     int ret = 0;
 
+    /* Normal operation is to wait for the current frame encoder to complete its current frame
+     * and then to give it a new frame to work on.  In zero-latency mode, we must encode this
+     * input picture before returning so the order must be reversed. This do/while() loop allows
+     * us to alternate the order of the calls without ugly code replication */
+    Frame* outFrame = NULL;
+    Frame* frameEnc = NULL;
+    int pass = 0;
+    do
+    {
+
     /* getEncodedPicture() should block until the FrameEncoder has completed
      * encoding the frame.  This is how back-pressure through the API is
      * accomplished when the encoder is full */
-    Frame *outFrame = curEncoder->getEncodedPicture(m_nalList);
+    if (!m_bZeroLatency || pass)
+        outFrame = curEncoder->getEncodedPicture(m_nalList);
     if (outFrame)
     {
         Slice *slice = outFrame->m_encData->m_slice;
@@ -591,8 +604,9 @@
 
     /* pop a single frame from decided list, then provide to frame encoder
      * curEncoder is guaranteed to be idle at this point */
-    Frame* frameEnc = m_lookahead->getDecidedPicture();
-    if (frameEnc)
+    if (!pass)
+        frameEnc = m_lookahead->getDecidedPicture();
+    if (frameEnc && !pass)
     {
         /* give this frame a FrameData instance before encoding */
         if (m_dpb->m_picSymFreeList)
@@ -655,6 +669,9 @@
     else if (m_encodedFrameNum)
         m_rateControl->setFinalFrameCount(m_encodedFrameNum);
 
+    }
+    while (m_bZeroLatency && ++pass < 2);
+
     return ret;
 }
 
diff -r 3f7902a3e5e4 -r 7aec6406358d source/encoder/encoder.h
--- a/source/encoder/encoder.h	Wed Jan 21 10:17:14 2015 -0600
+++ b/source/encoder/encoder.h	Wed Jan 21 11:20:10 2015 -0600
@@ -131,6 +131,7 @@
     Lookahead*         m_lookahead;
     Window             m_conformanceWindow;
 
+    bool               m_bZeroLatency;     // x265_encoder_encode() returns NALs for the input picture, zero lag
     bool               m_aborted;          // fatal error detected
 
     Encoder();


More information about the x265-devel mailing list