[x265] [PATCH] slicetype: fill in missing detail from slicetypeDecide()
Deepthi Nandakumar
deepthi at multicorewareinc.com
Thu Sep 19 11:33:03 CEST 2013
On Thu, Sep 19, 2013 at 3:35 AM, Steve Borho <steve at borho.org> wrote:
> # HG changeset patch
> # User Steve Borho <steve at borho.org>
> # Date 1378869992 18000
> # Tue Sep 10 22:26:32 2013 -0500
> # Node ID a5810b7397ddec0bbec0e885bc5e7fd9bd5a7040
> # Parent 5bab261d0dd7ac68c4af3837853d48d56017d4d6
> 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
>
> diff -r 5bab261d0dd7 -r a5810b7397dd source/common/lowres.cpp
> --- a/source/common/lowres.cpp Wed Sep 18 16:13:33 2013 -0500
> +++ b/source/common/lowres.cpp Tue Sep 10 22:26:32 2013 -0500
> @@ -108,11 +108,13 @@
> // (re) initialize lowres state
> void Lowres::init(TComPicYuv *orig, int bframes)
> {
> - scenecut = 1;
> + scenecut = true;
> bIntraCalculated = false;
> + bLastMiniGopBFrame = false;
> + keyframe = false; // Not a keyframe unless identified by lookahead
> + sliceType = X265_TYPE_AUTO;
> + leadingBframes = 0;
> memset(costEst, -1, sizeof(costEst));
> - sliceType = X265_TYPE_AUTO;
> - keyframe = 0; //Not a keyframe unless identified by lookahead
> for (int y = 0; y < bframes + 2; y++)
> {
> for (int x = 0; x < bframes + 2; x++)
> diff -r 5bab261d0dd7 -r a5810b7397dd source/common/lowres.h
> --- a/source/common/lowres.h Wed Sep 18 16:13:33 2013 -0500
> +++ b/source/common/lowres.h Tue Sep 10 22:26:32 2013 -0500
> @@ -44,14 +44,17 @@
> {
> /* 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;
> - int frameNum; // Presentation frame number
> - int scenecut; // Set to zero if the frame cannot possibly be part
> of a real scenecut.
> -
> - int sliceType; // Slice type decided by lookahead
> - int keyframe;
> + bool scenecut; // Set to zero if the frame cannot possibly be part
> of a real scenecut.
> + bool keyframe;
> + bool bLastMiniGopBFrame;
>
> /* lookahead output data */
> int costEst[X265_BFRAME_MAX + 2][X265_BFRAME_MAX + 2];
> diff -r 5bab261d0dd7 -r a5810b7397dd source/encoder/slicetype.cpp
> --- a/source/encoder/slicetype.cpp Wed Sep 18 16:13:33 2013 -0500
> +++ b/source/encoder/slicetype.cpp Tue Sep 10 22:26:32 2013 -0500
> @@ -66,6 +66,8 @@
> {
> this->cfg = _cfg;
> numDecided = 0;
> + lastKeyframe = -cfg->param.keyframeMax;
>
_cfg typo here.
> + lastNonB = NULL;
> predictions = (pixel*)X265_MALLOC(pixel, 35 * 8 * 8);
> me.setQP(X265_LOOKAHEAD_QP);
> me.setSearchMethod(X265_HEX_SEARCH);
> @@ -115,118 +117,6 @@
> 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;
> - outputQueue.pushBack(pic);
> - numDecided++;
> - lastKeyframe = 0;
> - pic->m_lowres.keyframe = 1;
> - 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]->keyframe = 1;
> - 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.keyframe = 1;
> - outputQueue.pushBack(pic);
> - numDecided++;
> - }
> - else if (cfg->param.bframes == 0 || inputQueue.size() == 1)
> - {
> - TComPic *pic = inputQueue.popFront();
> -
> - bool forceIntra = (pic->getPOC() % cfg->param.keyframeMax) == 0;
> - pic->m_lowres.sliceType = forceIntra ? X265_TYPE_I : X265_TYPE_P;
> - pic->m_lowres.keyframe = forceIntra ? 1 : 0;
> - outputQueue.pushBack(pic);
> - numDecided++;
> - }
> - else
> - {
> - TComPic *picB = inputQueue.popFront();
> - TComPic *picP = inputQueue.popFront();
> -
> - bool forceIntra = (picP->getPOC() % cfg->param.keyframeMax) == 0
> || (picB->getPOC() % cfg->param.keyframeMax) == 0;
> - if (forceIntra)
> - {
> - picB->m_lowres.sliceType = (picB->getPOC() %
> cfg->param.keyframeMax) ? X265_TYPE_P : X265_TYPE_I;
> - picB->m_lowres.keyframe = (picB->getPOC() %
> cfg->param.keyframeMax) ? 0 : 1;
> - outputQueue.pushBack(picB);
> - numDecided++;
> -
> - picP->m_lowres.sliceType = (picP->getPOC() %
> cfg->param.keyframeMax) ? X265_TYPE_P : X265_TYPE_I;
> - picP->m_lowres.keyframe = (picP->getPOC() %
> cfg->param.keyframeMax) ? 0 : 1;
> - outputQueue.pushBack(picP);
> - numDecided++;
> - }
> - else
> - {
> - picP->m_lowres.sliceType = X265_TYPE_P;
> - outputQueue.pushBack(picP);
> - numDecided++;
> -
> - picB->m_lowres.sliceType = X265_TYPE_B;
> - outputQueue.pushBack(picB);
> - 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
> @@ -482,6 +372,219 @@
> 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];
> + TComList<TComPic*>::iterator iterPic = inputQueue.begin();
> + int j;
> + for (j = 0; j < cfg->param.bframes + 2 && iterPic !=
> inputQueue.end(); iterPic++)
> + list[j++] = (*iterPic);
> + 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);
> + frm.sliceType = cfg->param.bOpenGOP && lastKeyframe
> >= 0 ? X265_TYPE_I : X265_TYPE_IDR;
> + }
> + }
> + if (frm.sliceType == X265_TYPE_I && frm.sliceType -
> lastKeyframe >= cfg->param.keyframeMin)
> + {
> + if (cfg->param.bOpenGOP)
> + {
> + lastKeyframe = frm.frameNum; // Use display order
> + frm.keyframe = true;
> + }
> + else
> + frm.sliceType = X265_TYPE_IDR;
> + }
> + if (frm.sliceType == X265_TYPE_IDR)
> + {
> + /* Close GOP */
> + lastKeyframe = frm.frameNum;
> + frm.keyframe = true;
> + if (bframes > 0)
> + {
> + frames[bframes]->sliceType = X265_TYPE_P;
> + bframes--;
> + }
> + }
> +
> + if (bframes == cfg->param.bframes || !list[bframes+1])
> + {
> + if (IS_X265_TYPE_B(frm.sliceType))
> + x265_log(&cfg->param, X265_LOG_WARNING, "specified
> frame type is not compatible with max B-frames\n");
> + if (frm.sliceType == X265_TYPE_AUTO ||
> IS_X265_TYPE_B(frm.sliceType))
> + frm.sliceType = X265_TYPE_P;
> + }
> + if (frm.sliceType == X265_TYPE_BREF)
> + brefs++;
> + if (frm.sliceType == X265_TYPE_AUTO)
> + frm.sliceType = X265_TYPE_B;
> + else if (!IS_X265_TYPE_B(frm.sliceType))
> + break;
> + }
> + if (bframes)
> + list[bframes-1]->m_lowres.bLastMiniGopBFrame = true;
> + list[bframes]->m_lowres.leadingBframes = bframes;
> + lastNonB = &list[bframes]->m_lowres;
> +
> + /* insert a bref into the sequence
> + if (h->param.i_bframe_pyramid && bframes > 1 && !brefs)
> + {
> + h->lookahead->next.list[bframes/2]->i_type = X264_TYPE_BREF;
> + brefs++;
> + } */
> +
> + /* calculate the frame costs ahead of time for
> x264_rc_analyse_slice while we still have lowres */
> + if (cfg->param.rc.rateControlMode != X265_RC_CQP)
> + {
> + int p0, p1, b;
> + p1 = b = bframes + 1;
> +
> + frames[0] = lastNonB;
> + if (IS_X265_TYPE_I(frames[bframes+1]->sliceType))
> + p0 = bframes + 1;
> + else // P
> + p0 = 0;
> +
> + estimateFrameCost(p0, p1, b, 0);
> +
> + /*
> + if ((p0 != p1 || bframes) && cfg->param.rc.i_vbv_buffer_size)
> + {
> + // We need the intra costs for row SATDs
> + estimateFrameCost(b, b, b, 0);
> +
> + // We need B-frame costs for row SATDs
> + p0 = 0;
> + for (b = 1; b <= bframes; b++)
> + {
> + if (frames[b]->i_type == X265_TYPE_B)
> + for (p1 = b; frames[p1]->sliceType ==
> X265_TYPE_B;)
> + p1++;
> + else
> + p1 = bframes + 1;
> + estimateFrameCost( p0, p1, b, 0 );
> + if (frames[b]->sliceType == X265_TYPE_BREF)
> + p0 = b;
> + }
> + } */
> + }
> + /* Analyse for weighted P frames
> + if (!h->param.rc.b_stat_read &&
> h->lookahead->next.list[bframes]->i_type == X264_TYPE_P
> + && h->param.analyse.i_weighted_pred >= X264_WEIGHTP_SIMPLE)
> + {
> + x265_emms();
> + x264_weights_analyse(h, h->lookahead->next.list[bframes],
> h->lookahead->last_nonb, 0);
> + }*/
> +
> + /* add to output queue in encode order */
> + outputQueue.pushBack(list[bframes]);
> + inputQueue.popFront();
> + for (int i = 0; i < bframes; i++)
> + {
> + outputQueue.pushBack(list[i]);
> + inputQueue.popFront();
> + }
> + return;
> + }
> +
> + // Fixed GOP structures for when B-Adapt and/or lookahead are disabled
> + 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;
> + outputQueue.pushBack(pic);
> + numDecided++;
> + lastKeyframe = 0;
> + pic->m_lowres.keyframe = 1;
> + return;
> + }
> + else if (cfg->param.keyframeMax == 1)
> + {
> + TComPic *pic = inputQueue.popFront();
> +
> + pic->m_lowres.sliceType = X265_TYPE_I;
> + pic->m_lowres.keyframe = 1;
> + outputQueue.pushBack(pic);
> + numDecided++;
> + }
> + else if (cfg->param.bframes == 0 || inputQueue.size() == 1)
> + {
> + TComPic *pic = inputQueue.popFront();
> +
> + bool forceIntra = (pic->getPOC() % cfg->param.keyframeMax) == 0;
> + pic->m_lowres.sliceType = forceIntra ? X265_TYPE_I : X265_TYPE_P;
> + pic->m_lowres.keyframe = forceIntra ? 1 : 0;
> + outputQueue.pushBack(pic);
> + numDecided++;
> + }
> + else
> + {
> + TComPic *picB = inputQueue.popFront();
> + TComPic *picP = inputQueue.popFront();
> +
> + bool forceIntra = (picP->getPOC() % cfg->param.keyframeMax) == 0
> || (picB->getPOC() % cfg->param.keyframeMax) == 0;
> + if (forceIntra)
> + {
> + picB->m_lowres.sliceType = (picB->getPOC() %
> cfg->param.keyframeMax) ? X265_TYPE_P : X265_TYPE_I;
> + picB->m_lowres.keyframe = (picB->getPOC() %
> cfg->param.keyframeMax) ? 0 : 1;
> + outputQueue.pushBack(picB);
> + numDecided++;
> +
> + picP->m_lowres.sliceType = (picP->getPOC() %
> cfg->param.keyframeMax) ? X265_TYPE_P : X265_TYPE_I;
> + picP->m_lowres.keyframe = (picP->getPOC() %
> cfg->param.keyframeMax) ? 0 : 1;
> + outputQueue.pushBack(picP);
> + numDecided++;
> + }
> + else
> + {
> + picP->m_lowres.sliceType = X265_TYPE_P;
> + outputQueue.pushBack(picP);
> + numDecided++;
> +
> + picB->m_lowres.sliceType = X265_TYPE_B;
> + outputQueue.pushBack(picB);
> + numDecided++;
> + }
> + }
> +}
> +
> void Lookahead::slicetypeAnalyse(bool bKeyframe)
> {
> int num_frames, origNumFrames, keyint_limit, framecnt;
> @@ -489,8 +592,10 @@
> int cuCount = NUM_CUS;
> int cost1p0, cost2p0, cost1b1, cost2p1;
> int reset_start;
> - int vbv_lookahead = 0;
>
> + if (!lastNonB)
> + return;
> + frames[0] = lastNonB;
> TComList<TComPic*>::iterator iterPic = inputQueue.begin();
> for (framecnt = 0; (framecnt < maxSearch) && (framecnt <
> (int)inputQueue.size()) && (*iterPic)->m_lowres.sliceType ==
> X265_TYPE_AUTO; framecnt++)
> {
> @@ -499,8 +604,7 @@
>
> if (!framecnt)
> {
> - frames[1] = &((*iterPic)->m_lowres);
> - frames[2] = NULL;
> + // TODO: mb-tree
> return;
> }
>
> @@ -509,14 +613,7 @@
> keyint_limit = cfg->param.keyframeMax - frames[1]->frameNum +
> lastKeyframe;
> origNumFrames = num_frames = X265_MIN(framecnt, keyint_limit);
>
> - /* This is important psy-wise: if we have a non-scenecut keyframe,
> - * there will be significant visual artifacts if the frames just
> before
> - * go down in quality due to being referenced less, despite it being
> - * more RD-optimal. */
> -
> - if (vbv_lookahead)
> - num_frames = framecnt;
> - else if (num_frames < framecnt)
> + if (cfg->param.bOpenGOP && num_frames < framecnt)
> num_frames++;
> else if (num_frames == 0)
> {
> @@ -641,7 +738,7 @@
> }
>
> // TODO if rc.b_mb_tree Enabled the need to call
> x264_macroblock_tree currently Ignored the call
> -
> + // if (!cfg->param.bIntraRefresh)
> for (int j = keyint_limit + 1; j <= num_frames; j +=
> cfg->param.keyframeMax)
> {
> frames[j]->sliceType = X265_TYPE_I;
> diff -r 5bab261d0dd7 -r a5810b7397dd source/encoder/slicetype.h
> --- a/source/encoder/slicetype.h Wed Sep 18 16:13:33 2013 -0500
> +++ b/source/encoder/slicetype.h Tue Sep 10 22:26:32 2013 -0500
> @@ -44,6 +44,7 @@
> TEncCfg *cfg;
> pixel *predictions; // buffer for 35 intra predictions
> Lowres *frames[X265_LOOKAHEAD_MAX];
> + Lowres *lastNonB;
> int merange;
> int numDecided;
> int lastKeyframe;
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20130919/21866830/attachment-0001.html>
More information about the x265-devel
mailing list