[x265-commits] [x265] slicetype: fill in missing detail from slicetypeDecide()
Steve Borho
steve at borho.org
Mon Oct 14 05:36:51 CEST 2013
details: http://hg.videolan.org/x265/rev/9bdff3310321
branches:
changeset: 4441:9bdff3310321
user: Steve Borho <steve at borho.org>
date: Tue Sep 10 22:26:32 2013 -0500
description:
slicetype: fill in missing detail from slicetypeDecide()
This moves slicetypeDecide() to make the file more readable. It also adds stubs
for features that we do not support yet including weightp, B-pyramid, intra
refresh, user-supplied slice types, etc
Subject: [x265] common: sanity check some lookahead settings
details: http://hg.videolan.org/x265/rev/eb0aa9c42bba
branches:
changeset: 4442:eb0aa9c42bba
user: Steve Borho <steve at borho.org>
date: Sun Oct 13 22:25:24 2013 -0500
description:
common: sanity check some lookahead settings
diffstat:
source/common/common.cpp | 4 +
source/common/common.h | 12 +
source/common/lowres.cpp | 2 +
source/common/lowres.h | 13 +-
source/encoder/slicetype.cpp | 365 ++++++++++++++++++++++++++----------------
source/encoder/slicetype.h | 6 +-
6 files changed, 251 insertions(+), 151 deletions(-)
diffs (truncated from 546 to 300 lines):
diff -r 8011064113f7 -r eb0aa9c42bba source/common/common.cpp
--- a/source/common/common.cpp Sun Oct 13 11:53:20 2013 -0500
+++ b/source/common/common.cpp Sun Oct 13 22:25:24 2013 -0500
@@ -289,6 +289,10 @@ int x265_check_params(x265_param_t *para
"RD Level is out of range");
CHECK(param->bframes > param->lookaheadDepth,
"Lookahead depth must be greater than the max consecutive bframe count");
+ CHECK(param->bframes > X265_BFRAME_MAX,
+ "max consecutive bframe count must be 16 or smaller");
+ CHECK(param->lookaheadDepth > X265_LOOKAHEAD_MAX,
+ "Lookahead depth must be less than 256");
// max CU size should be power of 2
uint32_t i = param->maxCUSize;
diff -r 8011064113f7 -r eb0aa9c42bba source/common/common.h
--- a/source/common/common.h Sun Oct 13 11:53:20 2013 -0500
+++ b/source/common/common.h Sun Oct 13 22:25:24 2013 -0500
@@ -58,6 +58,18 @@
#define X265_MIN4(a, b, c, d) X265_MIN((a), X265_MIN3((b), (c), (d)))
#define X265_MAX4(a, b, c, d) X265_MAX((a), X265_MAX3((b), (c), (d)))
#define QP_BD_OFFSET (6*(X265_DEPTH-8))
+
+// arbitrary, but low because SATD scores are 1/4 normal
+#define X265_LOOKAHEAD_QP (12 + QP_BD_OFFSET)
+#define X265_LOOKAHEAD_MAX 250
+
+// Use the same size blocks as x264. Using larger blocks seems to give artificially
+// high cost estimates (intra and inter both suffer)
+#define X265_LOWRES_CU_SIZE 8
+#define X265_LOWRES_CU_BITS 3
+
+#define X265_BFRAME_MAX 16
+
#define MAX_NAL_UNITS 5
#define MIN_FIFO_SIZE 1000
#define EMULATION_SIZE 1000
diff -r 8011064113f7 -r eb0aa9c42bba source/common/lowres.cpp
--- a/source/common/lowres.cpp Sun Oct 13 11:53:20 2013 -0500
+++ b/source/common/lowres.cpp Sun Oct 13 22:25:24 2013 -0500
@@ -110,9 +110,11 @@ void Lowres::init(TComPicYuv *orig, int
{
bScenecut = true;
bIntraCalculated = false;
+ bLastMiniGopBFrame = false;
bKeyframe = false; // Not a keyframe unless identified by lookahead
sliceType = type;
frameNum = poc;
+ leadingBframes = 0;
memset(costEst, -1, sizeof(costEst));
for (int y = 0; y < bframes + 2; y++)
{
diff -r 8011064113f7 -r eb0aa9c42bba source/common/lowres.h
--- a/source/common/lowres.h Sun Oct 13 11:53:20 2013 -0500
+++ b/source/common/lowres.h Sun Oct 13 22:25:24 2013 -0500
@@ -33,25 +33,20 @@ namespace x265 {
class TComPic;
-// Use the same size blocks as x264. Using larger blocks seems to give artificially
-// high cost estimates (intra and inter both suffer)
-#define X265_LOWRES_CU_SIZE 8
-#define X265_LOWRES_CU_BITS 3
-
-#define X265_BFRAME_MAX 16
-
struct Lowres : public ReferencePlanes
{
/* lowres buffers, sizes and strides */
pixel *buffer[4];
- int width; // width of lowres frame in pixels
- int lines; // height of lowres frame in pixel lines
+ int width; // width of lowres frame in pixels
+ int lines; // height of lowres frame in pixel lines
int frameNum; // Presentation frame number
int sliceType; // Slice type decided by lookahead
+ int leadingBframes; // number of leading B frames for P or I
bool bIntraCalculated;
bool bScenecut; // Set to false if the frame cannot possibly be part of a real scenecut.
bool bKeyframe;
+ bool bLastMiniGopBFrame;
/* lookahead output data */
int costEst[X265_BFRAME_MAX + 2][X265_BFRAME_MAX + 2];
diff -r 8011064113f7 -r eb0aa9c42bba source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp Sun Oct 13 11:53:20 2013 -0500
+++ b/source/encoder/slicetype.cpp Sun Oct 13 22:25:24 2013 -0500
@@ -66,6 +66,8 @@ Lookahead::Lookahead(TEncCfg *_cfg)
{
this->cfg = _cfg;
numDecided = 0;
+ lastKeyframe = -cfg->param.keyframeMax;
+ lastNonB = NULL;
predictions = (pixel*)X265_MALLOC(pixel, 35 * 8 * 8);
me.setQP(X265_LOOKAHEAD_QP);
me.setSearchMethod(X265_HEX_SEARCH);
@@ -114,127 +116,6 @@ void Lookahead::flush()
slicetypeDecide();
}
-void Lookahead::slicetypeDecide()
-{
- if (numDecided == 0)
- {
- // Special case for POC 0, send directly to output queue as I slice
- TComPic *pic = inputQueue.popFront();
- pic->m_lowres.sliceType = X265_TYPE_I;
- pic->m_lowres.bKeyframe = true;
- lastKeyframe = 0;
- outputQueue.pushBack(*pic);
- numDecided++;
- frames[0] = &(pic->m_lowres);
- return;
- }
- else if (cfg->param.bFrameAdaptive && cfg->param.lookaheadDepth && cfg->param.bframes)
- {
- slicetypeAnalyse(false);
-
- int dframes;
- TComPic* picsAnalysed[X265_LOOKAHEAD_MAX]; //Used for sorting the pics into encode order
- int idx = 1;
-
- for (dframes = 0; (frames[dframes + 1] != NULL) && (frames[dframes + 1]->sliceType != X265_TYPE_AUTO); dframes++)
- {
- if (frames[dframes + 1]->sliceType == X265_TYPE_I)
- {
- frames[dframes + 1]->bKeyframe = true;
- lastKeyframe = frames[dframes]->frameNum;
- if (cfg->param.decodingRefreshType == 2 && dframes > 0) //If an IDR frame following a B
- {
- frames[dframes]->sliceType = X265_TYPE_P;
- dframes--;
- }
- }
- if (!IS_X265_TYPE_B(frames[dframes + 1]->sliceType))
- {
- dframes++;
- break;
- }
- }
-
- TComPic *pic = NULL;
- for (int i = 1; i <= dframes && !inputQueue.empty(); i++)
- {
- pic = inputQueue.popFront();
- picsAnalysed[idx++] = pic;
- }
-
- picsAnalysed[0] = pic; //Move the P-frame following B-frames to the beginning
-
- //Push pictures in encode order
- for (int i = 0; i < dframes; i++)
- {
- outputQueue.pushBack(*picsAnalysed[i]);
- }
-
- if (pic)
- frames[0] = &(pic->m_lowres); // last nonb
- return;
- }
-
- // Fixed GOP structures for when B-Adapt and/or lookahead are disabled
- if (cfg->param.keyframeMax == 1)
- {
- TComPic *pic = inputQueue.popFront();
-
- pic->m_lowres.sliceType = X265_TYPE_I;
- pic->m_lowres.bKeyframe = true;
- lastKeyframe = pic->m_lowres.frameNum;
- outputQueue.pushBack(*pic);
- numDecided++;
- }
- else if (cfg->param.bframes == 0 || inputQueue.size() == 1)
- {
- TComPic *pic = inputQueue.popFront();
- if (pic->getPOC() % cfg->param.keyframeMax)
- pic->m_lowres.sliceType = X265_TYPE_P;
- else
- {
- pic->m_lowres.sliceType = X265_TYPE_I;
- pic->m_lowres.bKeyframe = true;
- lastKeyframe = pic->m_lowres.frameNum;
- }
- outputQueue.pushBack(*pic);
- numDecided++;
- }
- else
- {
- TComPic *list[X265_BFRAME_MAX+1];
- int j;
- for (j = 0; j <= cfg->param.bframes && !inputQueue.empty(); j++)
- {
- TComPic *pic = inputQueue.popFront();
- list[j] = pic;
- if (pic->m_lowres.frameNum >= lastKeyframe + cfg->param.keyframeMax)
- {
- pic->m_lowres.sliceType = X265_TYPE_I;
- pic->m_lowres.bKeyframe = true;
- lastKeyframe = pic->m_lowres.frameNum;
- if (j) list[j - 1]->m_lowres.sliceType = X265_TYPE_P;
- j++;
- break;
- }
- }
-
- TComPic *pic = list[j - 1];
- if (pic->m_lowres.sliceType == X265_TYPE_AUTO)
- pic->m_lowres.sliceType = X265_TYPE_P;
- outputQueue.pushBack(*pic);
- numDecided++;
- for (int i = 0; i < j - 1; i++)
- {
- pic = list[i];
- if (pic->m_lowres.sliceType == X265_TYPE_AUTO)
- pic->m_lowres.sliceType = X265_TYPE_B;
- outputQueue.pushBack(*pic);
- numDecided++;
- }
- }
-}
-
// Called by RateControl to get the estimated SATD cost for a given picture.
// It assumes dpb->prepareEncode() has already been called for the picture and
// all the references are established
@@ -253,7 +134,7 @@ int Lookahead::getEstimatedPictureCost(T
return estimateFrameCost(0, 0, 0, false);
case P_SLICE:
d0 = poc - l0poc;
- frames[0] = &pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0)->m_lowres;
+ frames[0] = lastNonB;
frames[d0] = &pic->m_lowres;
return estimateFrameCost(0, d0, d0, false);
case B_SLICE:
@@ -262,14 +143,14 @@ int Lookahead::getEstimatedPictureCost(T
{
// L1 reference is truly in the future
d1 = l1poc - poc;
- frames[0] = &pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0)->m_lowres;
+ frames[0] = lastNonB;
frames[d0] = &pic->m_lowres;
frames[d0 + d1] = &pic->getSlice()->getRefPic(REF_PIC_LIST_1, 0)->m_lowres;
return estimateFrameCost(0, d0 + d1, d0, false);
}
else
{
- frames[0] = &pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0)->m_lowres;
+ frames[0] = lastNonB;
frames[d0] = &pic->m_lowres;
return estimateFrameCost(0, d0, d0, false);
}
@@ -552,6 +433,220 @@ void Lookahead::estimateCUCost(int cux,
fenc->lowresCosts[b - p0][p1 - b][cuXY] = (uint16_t)(X265_MIN(bcost, LOWRES_COST_MASK) | (listused << LOWRES_COST_SHIFT));
}
+void Lookahead::slicetypeDecide()
+{
+ if (cfg->param.bFrameAdaptive && cfg->param.lookaheadDepth && cfg->param.bframes)
+ {
+ slicetypeAnalyse(false);
+
+ TComPic *list[X265_LOOKAHEAD_MAX];
+ TComPic *ipic = inputQueue.first();
+ int j;
+ for (j = 0; ipic && j < cfg->param.bframes + 2; ipic = ipic->m_next)
+ list[j++] = ipic;
+ list[j] = NULL;
+
+ int bframes, brefs;
+ for (bframes = 0, brefs = 0 ;; bframes++)
+ {
+ Lowres& frm = list[bframes]->m_lowres;
+
+ if (frm.sliceType == X265_TYPE_BREF
+ /* && h->param.i_bframe_pyramid < X264_B_PYRAMID_NORMAL && brefs == h->param.i_bframe_pyramid*/)
+ {
+ frm.sliceType = X265_TYPE_B;
+ x265_log(&cfg->param, X265_LOG_WARNING, "B-ref is not yet supported\n");
+ }
+ /* pyramid with multiple B-refs needs a big enough dpb that the preceding P-frame stays available.
+ smaller dpb could be supported by smart enough use of mmco, but it's easier just to forbid it.
+ else if (frm.sliceType == X265_TYPE_BREF && cfg->param.i_bframe_pyramid == X265_B_PYRAMID_NORMAL &&
+ brefs && cfg->param.i_frame_reference <= (brefs+3))
+ {
+ frm.sliceType = X265_TYPE_B;
+ x265_log(&cfg->param, X265_LOG_WARNING, "B-ref at frame %d incompatible with B-pyramid %s and %d reference frames\n",
+ frm.sliceType, x264_b_pyramid_names[h->param.i_bframe_pyramid], h->param.i_frame_reference);
+ } */
+
+ if (frm.sliceType == X265_TYPE_KEYFRAME)
+ frm.sliceType = cfg->param.bOpenGOP ? X265_TYPE_I : X265_TYPE_IDR;
+ if ((/* !cfg->param.intraRefresh || */ frm.frameNum == 0) && frm.frameNum - lastKeyframe >= cfg->param.keyframeMax)
+ {
+ if (frm.sliceType == X265_TYPE_AUTO || frm.sliceType == X265_TYPE_I)
+ frm.sliceType = cfg->param.bOpenGOP && lastKeyframe >= 0 ? X265_TYPE_I : X265_TYPE_IDR;
+ bool warn = frm.sliceType != X265_TYPE_IDR;
+ if (warn && cfg->param.bOpenGOP)
+ warn &= frm.sliceType != X265_TYPE_I;
+ if (warn)
+ {
+ x265_log(&cfg->param, X265_LOG_WARNING, "specified frame type (%d) at %d is not compatible with keyframe interval\n", frm.sliceType, frm.frameNum);
More information about the x265-commits
mailing list