mfxStatus AVC_Spl::AddSliceNalUnit(mfxBitstream * nalUnit, AVCSlice * slice) { static mfxU8 start_code_prefix[] = {0, 0, 1}; mfxU32 sliceLength = (mfxU32)(nalUnit->DataLength + sizeof(start_code_prefix)); if (m_frame.DataLength + sliceLength >= BUFFER_SIZE) return MFX_ERR_NOT_ENOUGH_BUFFER; MSDK_MEMCPY_BUF(m_frame.Data, m_frame.DataLength, BUFFER_SIZE, start_code_prefix, sizeof(start_code_prefix)); MSDK_MEMCPY_BUF(m_frame.Data, m_frame.DataLength + sizeof(start_code_prefix), BUFFER_SIZE, nalUnit->Data + nalUnit->DataOffset, nalUnit->DataLength); if (!m_frame.SliceNum) { m_frame.TimeStamp = nalUnit->TimeStamp; } m_frame.SliceNum++; if (m_slices.size() <= m_frame.SliceNum) { m_slices.resize(m_frame.SliceNum + 10); m_frame.Slice = &m_slices[0]; } SliceSplitterInfo & newSlice = m_slices[m_frame.SliceNum - 1]; AVCHeadersBitstream * bs = slice->GetBitStream(); newSlice.HeaderLength = (mfxU32)bs->BytesDecoded(); // add number of 003 sequence to HeaderLength for(mfxU8 *ptr = nalUnit->Data + sizeof(start_code_prefix); ptr < nalUnit->Data + sizeof(start_code_prefix) + newSlice.HeaderLength; ptr++) { if (ptr[0]==0 && ptr[1]==0 && ptr[2]==3) { newSlice.HeaderLength++; } } newSlice.HeaderLength += sizeof(start_code_prefix) + 1; newSlice.DataLength = sliceLength; newSlice.DataOffset = m_frame.DataLength; if(IS_I_SLICE(slice->GetSliceHeader()->slice_type)) newSlice.SliceType = TYPE_I; else if(IS_P_SLICE(slice->GetSliceHeader()->slice_type)) newSlice.SliceType = TYPE_P; else if(IS_B_SLICE(slice->GetSliceHeader()->slice_type)) newSlice.SliceType = TYPE_B; m_frame.DataLength += sliceLength; if (!m_currentInfo->m_index) m_frame.FirstFieldSliceNum++; return MFX_ERR_NONE; }
u32 h264bsdConceal(storage_t *pStorage, image_t *currImage, u32 sliceType) { /* Variables */ u32 i, j; u32 row, col; u32 width, height; u8 *refData; mbStorage_t *mb; /* Code */ ASSERT(pStorage); ASSERT(currImage); DEBUG(("Concealing %s slice\n", IS_I_SLICE(sliceType) ? "intra" : "inter")); width = currImage->width; height = currImage->height; refData = NULL; /* use reference picture with smallest available index */ if (IS_P_SLICE(sliceType) || (pStorage->intraConcealmentFlag != 0)) { i = 0; do { refData = h264bsdGetRefPicData(pStorage->dpb, i); i++; if (i >= 16) break; } while (refData == NULL); } i = row = col = 0; /* find first properly decoded macroblock -> start point for concealment */ while (i < pStorage->picSizeInMbs && !pStorage->mb[i].decoded) { i++; col++; if (col == width) { row++; col = 0; } } /* whole picture lost -> copy previous or set grey */ if (i == pStorage->picSizeInMbs) { if ( (IS_I_SLICE(sliceType) && (pStorage->intraConcealmentFlag == 0)) || refData == NULL) { memset(currImage->data, 128, width*height*384); } else { #ifndef FLASCC memcpy(currImage->data, refData, width*height*384); #else int ii = 0; int size = width*height*384; u8* curr_data = currImage->data; for (ii = 0; ii < size;ii++) curr_data[i] = refData[i]; #endif } pStorage->numConcealedMbs = pStorage->picSizeInMbs; /* no filtering if whole picture concealed */ for (i = 0; i < pStorage->picSizeInMbs; i++) pStorage->mb[i].disableDeblockingFilterIdc = 1; return(HANTRO_OK); } /* start from the row containing the first correct macroblock, conceal the * row in question, all rows above that row and then continue downwards */ mb = pStorage->mb + row * width; for (j = col; j--;) { ConcealMb(mb+j, currImage, row, j, sliceType, refData); mb[j].decoded = 1; pStorage->numConcealedMbs++; } for (j = col + 1; j < width; j++) { if (!mb[j].decoded) { ConcealMb(mb+j, currImage, row, j, sliceType, refData); mb[j].decoded = 1; pStorage->numConcealedMbs++; } } /* if previous row(s) could not be concealed -> conceal them now */ if (row) { for (j = 0; j < width; j++) { i = row - 1; mb = pStorage->mb + i*width + j; do { ConcealMb(mb, currImage, i, j, sliceType, refData); mb->decoded = 1; pStorage->numConcealedMbs++; mb -= width; } while(i--); } } /* process rows below the one containing the first correct macroblock */ for (i = row + 1; i < height; i++) { mb = pStorage->mb + i * width; for (j = 0; j < width; j++) { if (!mb[j].decoded) { ConcealMb(mb+j, currImage, i, j, sliceType, refData); mb[j].decoded = 1; pStorage->numConcealedMbs++; } } } return(HANTRO_OK); }
u32 h264bsdDecodeSliceHeader(strmData_t *pStrmData, sliceHeader_t *pSliceHeader, seqParamSet_t *pSeqParamSet, picParamSet_t *pPicParamSet, nalUnit_t *pNalUnit) { /* Variables */ u32 tmp, i, value; i32 itmp; u32 picSizeInMbs; /* Code */ ASSERT(pStrmData); ASSERT(pSliceHeader); ASSERT(pSeqParamSet); ASSERT(pPicParamSet); ASSERT( pNalUnit->nalUnitType == NAL_CODED_SLICE || pNalUnit->nalUnitType == NAL_CODED_SLICE_IDR ); H264SwDecMemset(pSliceHeader, 0, sizeof(sliceHeader_t)); picSizeInMbs = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->firstMbInSlice = value; if (value >= picSizeInMbs) { EPRINT("first_mb_in_slice"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->sliceType = value; /* slice type has to be either I or P slice. P slice is not allowed when * current NAL unit is an IDR NAL unit or num_ref_frames is 0 */ if ( !IS_I_SLICE(pSliceHeader->sliceType) && ( !IS_P_SLICE(pSliceHeader->sliceType) || IS_IDR_NAL_UNIT(pNalUnit) || !pSeqParamSet->numRefFrames ) ) { EPRINT("slice_type"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->picParameterSetId = value; if (pSliceHeader->picParameterSetId != pPicParamSet->picParameterSetId) { EPRINT("pic_parameter_set_id"); return(HANTRO_NOK); } /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (pSeqParamSet->maxFrameNum >> i) i++; i--; tmp = h264bsdGetBits(pStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); if (IS_IDR_NAL_UNIT(pNalUnit) && tmp != 0) { EPRINT("frame_num"); return(HANTRO_NOK); } pSliceHeader->frameNum = tmp; if (IS_IDR_NAL_UNIT(pNalUnit)) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->idrPicId = value; if (value > 65535) { EPRINT("idr_pic_id"); return(HANTRO_NOK); } } if (pSeqParamSet->picOrderCntType == 0) { /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ i = 0; while (pSeqParamSet->maxPicOrderCntLsb >> i) i++; i--; tmp = h264bsdGetBits(pStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSliceHeader->picOrderCntLsb = tmp; if (pPicParamSet->picOrderPresentFlag) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->deltaPicOrderCntBottom = itmp; } /* check that picOrderCnt for IDR picture will be zero. See * DecodePicOrderCnt function to understand the logic here */ if ( IS_IDR_NAL_UNIT(pNalUnit) && ( (pSliceHeader->picOrderCntLsb > pSeqParamSet->maxPicOrderCntLsb/2) || MIN((i32)pSliceHeader->picOrderCntLsb, (i32)pSliceHeader->picOrderCntLsb + pSliceHeader->deltaPicOrderCntBottom) != 0 ) ) { return(HANTRO_NOK); } }