| 1 | /***************************************************************************** |
| 2 | * Copyright (C) 2013 x265 project |
| 3 | * |
| 4 | * Authors: Steve Borho <steve@borho.org> |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA. |
| 19 | * |
| 20 | * This program is also available under a commercial proprietary license. |
| 21 | * For more information, contact us at license @ x265.com. |
| 22 | *****************************************************************************/ |
| 23 | |
| 24 | #include "common.h" |
| 25 | #include "frame.h" |
| 26 | #include "framedata.h" |
| 27 | #include "picyuv.h" |
| 28 | #include "slice.h" |
| 29 | |
| 30 | #include "dpb.h" |
| 31 | |
| 32 | using namespace x265; |
| 33 | |
| 34 | DPB::~DPB() |
| 35 | { |
| 36 | while (!m_freeList.empty()) |
| 37 | { |
| 38 | Frame* curFrame = m_freeList.popFront(); |
| 39 | curFrame->destroy(); |
| 40 | delete curFrame; |
| 41 | } |
| 42 | |
| 43 | while (!m_picList.empty()) |
| 44 | { |
| 45 | Frame* curFrame = m_picList.popFront(); |
| 46 | curFrame->destroy(); |
| 47 | delete curFrame; |
| 48 | } |
| 49 | |
| 50 | while (m_picSymFreeList) |
| 51 | { |
| 52 | FrameData* next = m_picSymFreeList->m_freeListNext; |
| 53 | m_picSymFreeList->destroy(); |
| 54 | |
| 55 | m_picSymFreeList->m_reconPic->destroy(); |
| 56 | delete m_picSymFreeList->m_reconPic; |
| 57 | |
| 58 | delete m_picSymFreeList; |
| 59 | m_picSymFreeList = next; |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | // move unreferenced pictures from picList to freeList for recycle |
| 64 | void DPB::recycleUnreferenced() |
| 65 | { |
| 66 | Frame *iterFrame = m_picList.first(); |
| 67 | |
| 68 | while (iterFrame) |
| 69 | { |
| 70 | Frame *curFrame = iterFrame; |
| 71 | iterFrame = iterFrame->m_next; |
| 72 | if (!curFrame->m_encData->m_bHasReferences && !curFrame->m_countRefEncoders) |
| 73 | { |
| 74 | curFrame->m_reconRowCount.set(0); |
| 75 | curFrame->m_bChromaExtended = false; |
| 76 | |
| 77 | // iterator is invalidated by remove, restart scan |
| 78 | m_picList.remove(*curFrame); |
| 79 | iterFrame = m_picList.first(); |
| 80 | |
| 81 | m_freeList.pushBack(*curFrame); |
| 82 | curFrame->m_encData->m_freeListNext = m_picSymFreeList; |
| 83 | m_picSymFreeList = curFrame->m_encData; |
| 84 | curFrame->m_encData = NULL; |
| 85 | curFrame->m_reconPic = NULL; |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | void DPB::prepareEncode(Frame *newFrame) |
| 91 | { |
| 92 | Slice* slice = newFrame->m_encData->m_slice; |
| 93 | slice->m_poc = newFrame->m_poc; |
| 94 | |
| 95 | int pocCurr = slice->m_poc; |
| 96 | int type = newFrame->m_lowres.sliceType; |
| 97 | bool bIsKeyFrame = newFrame->m_lowres.bKeyframe; |
| 98 | |
| 99 | slice->m_nalUnitType = getNalUnitType(pocCurr, bIsKeyFrame); |
| 100 | if (slice->m_nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) |
| 101 | m_lastIDR = pocCurr; |
| 102 | slice->m_lastIDR = m_lastIDR; |
| 103 | slice->m_sliceType = IS_X265_TYPE_B(type) ? B_SLICE : (type == X265_TYPE_P) ? P_SLICE : I_SLICE; |
| 104 | |
| 105 | if (type == X265_TYPE_B) |
| 106 | { |
| 107 | // change from _R "referenced" to _N "non-referenced" NAL unit type |
| 108 | switch (slice->m_nalUnitType) |
| 109 | { |
| 110 | case NAL_UNIT_CODED_SLICE_TRAIL_R: |
| 111 | slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_TRAIL_N; |
| 112 | break; |
| 113 | case NAL_UNIT_CODED_SLICE_RADL_R: |
| 114 | slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RADL_N; |
| 115 | break; |
| 116 | case NAL_UNIT_CODED_SLICE_RASL_R: |
| 117 | slice->m_nalUnitType = NAL_UNIT_CODED_SLICE_RASL_N; |
| 118 | break; |
| 119 | default: |
| 120 | break; |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | /* m_bHasReferences starts out as true for non-B pictures, and is set to false |
| 125 | * once no more pictures reference it */ |
| 126 | newFrame->m_encData->m_bHasReferences = IS_REFERENCED(newFrame); |
| 127 | |
| 128 | m_picList.pushFront(*newFrame); |
| 129 | |
| 130 | // Do decoding refresh marking if any |
| 131 | decodingRefreshMarking(pocCurr, slice->m_nalUnitType); |
| 132 | |
| 133 | computeRPS(pocCurr, slice->isIRAP(), &slice->m_rps, slice->m_sps->maxDecPicBuffering); |
| 134 | |
| 135 | // Mark pictures in m_piclist as unreferenced if they are not included in RPS |
| 136 | applyReferencePictureSet(&slice->m_rps, pocCurr); |
| 137 | |
| 138 | slice->m_numRefIdx[0] = X265_MIN(m_maxRefL0, slice->m_rps.numberOfNegativePictures); // Ensuring L0 contains just the -ve POC |
| 139 | slice->m_numRefIdx[1] = X265_MIN(m_maxRefL1, slice->m_rps.numberOfPositivePictures); |
| 140 | slice->setRefPicList(m_picList); |
| 141 | |
| 142 | X265_CHECK(slice->m_sliceType != B_SLICE || slice->m_numRefIdx[1], "B slice without L1 references (non-fatal)\n"); |
| 143 | |
| 144 | if (slice->m_sliceType == B_SLICE) |
| 145 | { |
| 146 | /* TODO: the lookahead should be able to tell which reference picture |
| 147 | * had the least motion residual. We should be able to use that here to |
| 148 | * select a colocation reference list and index */ |
| 149 | slice->m_colFromL0Flag = false; |
| 150 | slice->m_colRefIdx = 0; |
| 151 | slice->m_bCheckLDC = false; |
| 152 | } |
| 153 | else |
| 154 | { |
| 155 | slice->m_bCheckLDC = true; |
| 156 | slice->m_colFromL0Flag = true; |
| 157 | slice->m_colRefIdx = 0; |
| 158 | } |
| 159 | slice->m_sLFaseFlag = (SLFASE_CONSTANT & (1 << (pocCurr % 31))) > 0; |
| 160 | |
| 161 | /* Increment reference count of all motion-referenced frames to prevent them |
| 162 | * from being recycled. These counts are decremented at the end of |
| 163 | * compressFrame() */ |
| 164 | int numPredDir = slice->isInterP() ? 1 : slice->isInterB() ? 2 : 0; |
| 165 | for (int l = 0; l < numPredDir; l++) |
| 166 | { |
| 167 | for (int ref = 0; ref < slice->m_numRefIdx[l]; ref++) |
| 168 | { |
| 169 | Frame *refpic = slice->m_refPicList[l][ref]; |
| 170 | ATOMIC_INC(&refpic->m_countRefEncoders); |
| 171 | } |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | void DPB::computeRPS(int curPoc, bool isRAP, RPS * rps, unsigned int maxDecPicBuffer) |
| 176 | { |
| 177 | unsigned int poci = 0, numNeg = 0, numPos = 0; |
| 178 | |
| 179 | Frame* iterPic = m_picList.first(); |
| 180 | |
| 181 | while (iterPic && (poci < maxDecPicBuffer - 1)) |
| 182 | { |
| 183 | if ((iterPic->m_poc != curPoc) && iterPic->m_encData->m_bHasReferences) |
| 184 | { |
| 185 | rps->poc[poci] = iterPic->m_poc; |
| 186 | rps->deltaPOC[poci] = rps->poc[poci] - curPoc; |
| 187 | (rps->deltaPOC[poci] < 0) ? numNeg++ : numPos++; |
| 188 | rps->bUsed[poci] = !isRAP; |
| 189 | poci++; |
| 190 | } |
| 191 | iterPic = iterPic->m_next; |
| 192 | } |
| 193 | |
| 194 | rps->numberOfPictures = poci; |
| 195 | rps->numberOfPositivePictures = numPos; |
| 196 | rps->numberOfNegativePictures = numNeg; |
| 197 | |
| 198 | rps->sortDeltaPOC(); |
| 199 | } |
| 200 | |
| 201 | /* Marking reference pictures when an IDR/CRA is encountered. */ |
| 202 | void DPB::decodingRefreshMarking(int pocCurr, NalUnitType nalUnitType) |
| 203 | { |
| 204 | if (nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) |
| 205 | { |
| 206 | /* If the nal_unit_type is IDR, all pictures in the reference picture |
| 207 | * list are marked as "unused for reference" */ |
| 208 | Frame* iterFrame = m_picList.first(); |
| 209 | while (iterFrame) |
| 210 | { |
| 211 | if (iterFrame->m_poc != pocCurr) |
| 212 | iterFrame->m_encData->m_bHasReferences = false; |
| 213 | iterFrame = iterFrame->m_next; |
| 214 | } |
| 215 | } |
| 216 | else // CRA or No DR |
| 217 | { |
| 218 | if (m_bRefreshPending && pocCurr > m_pocCRA) |
| 219 | { |
| 220 | /* If the bRefreshPending flag is true (a deferred decoding refresh |
| 221 | * is pending) and the current temporal reference is greater than |
| 222 | * the temporal reference of the latest CRA picture (pocCRA), mark |
| 223 | * all reference pictures except the latest CRA picture as "unused |
| 224 | * for reference" and set the bRefreshPending flag to false */ |
| 225 | Frame* iterFrame = m_picList.first(); |
| 226 | while (iterFrame) |
| 227 | { |
| 228 | if (iterFrame->m_poc != pocCurr && iterFrame->m_poc != m_pocCRA) |
| 229 | iterFrame->m_encData->m_bHasReferences = false; |
| 230 | iterFrame = iterFrame->m_next; |
| 231 | } |
| 232 | |
| 233 | m_bRefreshPending = false; |
| 234 | } |
| 235 | if (nalUnitType == NAL_UNIT_CODED_SLICE_CRA) |
| 236 | { |
| 237 | /* If the nal_unit_type is CRA, set the bRefreshPending flag to true |
| 238 | * and pocCRA to the temporal reference of the current picture */ |
| 239 | m_bRefreshPending = true; |
| 240 | m_pocCRA = pocCurr; |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | /* Note that the current picture is already placed in the reference list and |
| 245 | * its marking is not changed. If the current picture has a nal_ref_idc |
| 246 | * that is not 0, it will remain marked as "used for reference" */ |
| 247 | } |
| 248 | |
| 249 | /** Function for applying picture marking based on the Reference Picture Set */ |
| 250 | void DPB::applyReferencePictureSet(RPS *rps, int curPoc) |
| 251 | { |
| 252 | // loop through all pictures in the reference picture buffer |
| 253 | Frame* iterFrame = m_picList.first(); |
| 254 | while (iterFrame) |
| 255 | { |
| 256 | if (iterFrame->m_poc != curPoc && iterFrame->m_encData->m_bHasReferences) |
| 257 | { |
| 258 | // loop through all pictures in the Reference Picture Set |
| 259 | // to see if the picture should be kept as reference picture |
| 260 | bool referenced = false; |
| 261 | for (int i = 0; i < rps->numberOfPositivePictures + rps->numberOfNegativePictures; i++) |
| 262 | { |
| 263 | if (iterFrame->m_poc == curPoc + rps->deltaPOC[i]) |
| 264 | { |
| 265 | referenced = true; |
| 266 | break; |
| 267 | } |
| 268 | } |
| 269 | if (!referenced) |
| 270 | iterFrame->m_encData->m_bHasReferences = false; |
| 271 | } |
| 272 | iterFrame = iterFrame->m_next; |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | /* deciding the nal_unit_type */ |
| 277 | NalUnitType DPB::getNalUnitType(int curPOC, bool bIsKeyFrame) |
| 278 | { |
| 279 | if (!curPOC) |
| 280 | return NAL_UNIT_CODED_SLICE_IDR_W_RADL; |
| 281 | |
| 282 | if (bIsKeyFrame) |
| 283 | return m_bOpenGOP ? NAL_UNIT_CODED_SLICE_CRA : NAL_UNIT_CODED_SLICE_IDR_W_RADL; |
| 284 | |
| 285 | if (m_pocCRA && curPOC < m_pocCRA) |
| 286 | // All leading pictures are being marked as TFD pictures here since |
| 287 | // current encoder uses all reference pictures while encoding leading |
| 288 | // pictures. An encoder can ensure that a leading picture can be still |
| 289 | // decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by |
| 290 | // controlling the reference pictures used for encoding that leading |
| 291 | // picture. Such a leading picture need not be marked as a TFD picture. |
| 292 | return NAL_UNIT_CODED_SLICE_RASL_R; |
| 293 | |
| 294 | if (m_lastIDR && curPOC < m_lastIDR) |
| 295 | return NAL_UNIT_CODED_SLICE_RADL_R; |
| 296 | |
| 297 | return NAL_UNIT_CODED_SLICE_TRAIL_R; |
| 298 | } |