1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /*------------------------------------------------------------------------------ 18 19 Table of contents 20 21 1. Include headers 22 2. External compiler flags 23 3. Module defines 24 4. Local function prototypes 25 5. Functions 26 h264bsdDecodeSliceData 27 SetMbParams 28 h264bsdMarkSliceCorrupted 29 30 ------------------------------------------------------------------------------*/ 31 32 /*------------------------------------------------------------------------------ 33 1. Include headers 34 ------------------------------------------------------------------------------*/ 35 36 #include "h264bsd_slice_data.h" 37 #include "h264bsd_util.h" 38 #include "h264bsd_vlc.h" 39 40 /*------------------------------------------------------------------------------ 41 2. External compiler flags 42 -------------------------------------------------------------------------------- 43 44 -------------------------------------------------------------------------------- 45 3. Module defines 46 ------------------------------------------------------------------------------*/ 47 48 /*------------------------------------------------------------------------------ 49 4. Local function prototypes 50 ------------------------------------------------------------------------------*/ 51 52 static void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId, 53 i32 chromaQpIndexOffset); 54 55 /*------------------------------------------------------------------------------ 56 57 5.1 Function name: h264bsdDecodeSliceData 58 59 Functional description: 60 Decode one slice. Function decodes stream data, i.e. macroblocks 61 and possible skip_run fields. h264bsdDecodeMacroblock function is 62 called to handle all other macroblock related processing. 63 Macroblock to slice group mapping is considered when next 64 macroblock to process is determined (h264bsdNextMbAddress function) 65 map 66 67 Inputs: 68 pStrmData pointer to stream data structure 69 pStorage pointer to storage structure 70 currImage pointer to current processed picture, needed for 71 intra prediction of the macroblocks 72 pSliceHeader pointer to slice header of the current slice 73 74 Outputs: 75 currImage processed macroblocks are written to current image 76 pStorage mbStorage structure of each processed macroblock 77 is updated here 78 79 Returns: 80 HANTRO_OK success 81 HANTRO_NOK invalid stream data 82 83 ------------------------------------------------------------------------------*/ 84 85 u32 h264bsdDecodeSliceData(strmData_t *pStrmData, storage_t *pStorage, 86 image_t *currImage, sliceHeader_t *pSliceHeader) 87 { 88 89 /* Variables */ 90 91 u8 mbData[384 + 15 + 32]; 92 u8 *data; 93 u32 tmp; 94 u32 skipRun; 95 u32 prevSkipped; 96 u32 currMbAddr; 97 u32 moreMbs; 98 u32 mbCount; 99 i32 qpY; 100 macroblockLayer_t *mbLayer; 101 102 /* Code */ 103 104 ASSERT(pStrmData); 105 ASSERT(pSliceHeader); 106 ASSERT(pStorage); 107 ASSERT(pSliceHeader->firstMbInSlice < pStorage->picSizeInMbs); 108 109 /* ensure 16-byte alignment */ 110 data = (u8*)ALIGN(mbData, 16); 111 112 mbLayer = pStorage->mbLayer; 113 114 currMbAddr = pSliceHeader->firstMbInSlice; 115 skipRun = 0; 116 prevSkipped = HANTRO_FALSE; 117 118 /* increment slice index, will be one for decoding of the first slice of 119 * the picture */ 120 pStorage->slice->sliceId++; 121 122 /* lastMbAddr stores address of the macroblock that was last successfully 123 * decoded, needed for error handling */ 124 pStorage->slice->lastMbAddr = 0; 125 126 mbCount = 0; 127 /* initial quantization parameter for the slice is obtained as the sum of 128 * initial QP for the picture and sliceQpDelta for the current slice */ 129 qpY = (i32)pStorage->activePps->picInitQp + pSliceHeader->sliceQpDelta; 130 do 131 { 132 /* primary picture and already decoded macroblock -> error */ 133 if (!pSliceHeader->redundantPicCnt && pStorage->mb[currMbAddr].decoded) 134 { 135 EPRINT("Primary and already decoded"); 136 return(HANTRO_NOK); 137 } 138 139 SetMbParams(pStorage->mb + currMbAddr, pSliceHeader, 140 pStorage->slice->sliceId, pStorage->activePps->chromaQpIndexOffset); 141 142 if (!IS_I_SLICE(pSliceHeader->sliceType)) 143 { 144 if (!prevSkipped) 145 { 146 tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &skipRun); 147 if (tmp != HANTRO_OK) 148 return(tmp); 149 /* skip_run shall be less than or equal to number of 150 * macroblocks left */ 151 if (skipRun > (pStorage->picSizeInMbs - currMbAddr)) 152 { 153 EPRINT("skip_run"); 154 return(HANTRO_NOK); 155 } 156 if (skipRun) 157 { 158 prevSkipped = HANTRO_TRUE; 159 H264SwDecMemset(&mbLayer->mbPred, 0, sizeof(mbPred_t)); 160 /* mark current macroblock skipped */ 161 mbLayer->mbType = P_Skip; 162 } 163 } 164 } 165 166 if (skipRun) 167 { 168 DEBUG(("Skipping macroblock %d\n", currMbAddr)); 169 skipRun--; 170 } 171 else 172 { 173 prevSkipped = HANTRO_FALSE; 174 tmp = h264bsdDecodeMacroblockLayer(pStrmData, mbLayer, 175 pStorage->mb + currMbAddr, pSliceHeader->sliceType, 176 pSliceHeader->numRefIdxL0Active); 177 if (tmp != HANTRO_OK) 178 { 179 EPRINT("macroblock_layer"); 180 return(tmp); 181 } 182 } 183 184 tmp = h264bsdDecodeMacroblock(pStorage->mb + currMbAddr, mbLayer, 185 currImage, pStorage->dpb, &qpY, currMbAddr, 186 pStorage->activePps->constrainedIntraPredFlag, data); 187 if (tmp != HANTRO_OK) 188 { 189 EPRINT("MACRO_BLOCK"); 190 return(tmp); 191 } 192 193 /* increment macroblock count only for macroblocks that were decoded 194 * for the first time (redundant slices) */ 195 if (pStorage->mb[currMbAddr].decoded == 1) 196 mbCount++; 197 198 /* keep on processing as long as there is stream data left or 199 * processing of macroblocks to be skipped based on the last skipRun is 200 * not finished */ 201 moreMbs = (h264bsdMoreRbspData(pStrmData) || skipRun) ? 202 HANTRO_TRUE : HANTRO_FALSE; 203 204 /* lastMbAddr is only updated for intra slices (all macroblocks of 205 * inter slices will be lost in case of an error) */ 206 if (IS_I_SLICE(pSliceHeader->sliceType)) 207 pStorage->slice->lastMbAddr = currMbAddr; 208 209 currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap, 210 pStorage->picSizeInMbs, currMbAddr); 211 /* data left in the buffer but no more macroblocks for current slice 212 * group -> error */ 213 if (moreMbs && !currMbAddr) 214 { 215 EPRINT("Next mb address"); 216 return(HANTRO_NOK); 217 } 218 219 } while (moreMbs); 220 221 if ((pStorage->slice->numDecodedMbs + mbCount) > pStorage->picSizeInMbs) 222 { 223 EPRINT("Num decoded mbs"); 224 return(HANTRO_NOK); 225 } 226 227 pStorage->slice->numDecodedMbs += mbCount; 228 229 return(HANTRO_OK); 230 231 } 232 233 /*------------------------------------------------------------------------------ 234 235 5.2 Function: SetMbParams 236 237 Functional description: 238 Set macroblock parameters that remain constant for this slice 239 240 Inputs: 241 pSlice pointer to current slice header 242 sliceId id of the current slice 243 chromaQpIndexOffset 244 245 Outputs: 246 pMb pointer to macroblock structure which is updated 247 248 Returns: 249 none 250 251 ------------------------------------------------------------------------------*/ 252 253 void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId, 254 i32 chromaQpIndexOffset) 255 { 256 257 /* Variables */ 258 u32 tmp1; 259 i32 tmp2, tmp3; 260 261 /* Code */ 262 263 tmp1 = pSlice->disableDeblockingFilterIdc; 264 tmp2 = pSlice->sliceAlphaC0Offset; 265 tmp3 = pSlice->sliceBetaOffset; 266 pMb->sliceId = sliceId; 267 pMb->disableDeblockingFilterIdc = tmp1; 268 pMb->filterOffsetA = tmp2; 269 pMb->filterOffsetB = tmp3; 270 pMb->chromaQpIndexOffset = chromaQpIndexOffset; 271 272 } 273 274 /*------------------------------------------------------------------------------ 275 276 5.3 Function name: h264bsdMarkSliceCorrupted 277 278 Functional description: 279 Mark macroblocks of the slice corrupted. If lastMbAddr in the slice 280 storage is set -> picWidhtInMbs (or at least 10) macroblocks back 281 from the lastMbAddr are marked corrupted. However, if lastMbAddr 282 is not set -> all macroblocks of the slice are marked. 283 284 Inputs: 285 pStorage pointer to storage structure 286 firstMbInSlice address of the first macroblock in the slice, this 287 identifies the slice to be marked corrupted 288 289 Outputs: 290 pStorage mbStorage for the corrupted macroblocks updated 291 292 Returns: 293 none 294 295 ------------------------------------------------------------------------------*/ 296 297 void h264bsdMarkSliceCorrupted(storage_t *pStorage, u32 firstMbInSlice) 298 { 299 300 /* Variables */ 301 302 u32 tmp, i; 303 u32 sliceId; 304 u32 currMbAddr; 305 306 /* Code */ 307 308 ASSERT(pStorage); 309 ASSERT(firstMbInSlice < pStorage->picSizeInMbs); 310 311 currMbAddr = firstMbInSlice; 312 313 sliceId = pStorage->slice->sliceId; 314 315 /* DecodeSliceData sets lastMbAddr for I slices -> if it was set, go back 316 * MAX(picWidthInMbs, 10) macroblocks and start marking from there */ 317 if (pStorage->slice->lastMbAddr) 318 { 319 ASSERT(pStorage->mb[pStorage->slice->lastMbAddr].sliceId == sliceId); 320 i = pStorage->slice->lastMbAddr - 1; 321 tmp = 0; 322 while (i > currMbAddr) 323 { 324 if (pStorage->mb[i].sliceId == sliceId) 325 { 326 tmp++; 327 if (tmp >= MAX(pStorage->activeSps->picWidthInMbs, 10)) 328 break; 329 } 330 i--; 331 } 332 currMbAddr = i; 333 } 334 335 do 336 { 337 338 if ( (pStorage->mb[currMbAddr].sliceId == sliceId) && 339 (pStorage->mb[currMbAddr].decoded) ) 340 { 341 pStorage->mb[currMbAddr].decoded--; 342 } 343 else 344 { 345 break; 346 } 347 348 currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap, 349 pStorage->picSizeInMbs, currMbAddr); 350 351 } while (currMbAddr); 352 353 } 354 355