func (this *TDecGop) DecompressSlice(pcBitstream *TLibCommon.TComInputBitstream, rpcPic *TLibCommon.TComPic, pTraceFile io.Writer) { pcSlice := rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()) // Table of extracted substreams. // These must be deallocated AND their internal fifos, too. //TComInputBitstream **ppcSubstreams = NULL; //-- For time output for each slice iBeforeTime := time.Now() uiStartCUAddr := pcSlice.GetSliceSegmentCurStartCUAddr() uiSliceStartCuAddr := pcSlice.GetSliceCurStartCUAddr() if uiSliceStartCuAddr == uiStartCUAddr { l := len(this.m_sliceStartCUAddress) this.m_sliceStartCUAddress[l] = int(uiSliceStartCuAddr) //this.m_sliceStartCUAddress.PushBack(uiSliceStartCuAddr); } this.m_pcSbacDecoder.Init(this.m_pcBinCABAC) //(TDecBinIf*) this.m_pcEntropyDecoder.SetEntropyDecoder(this.m_pcSbacDecoder) this.m_pcEntropyDecoder.SetTraceFile(pTraceFile) var uiNumSubstreams uint if pcSlice.GetPPS().GetEntropyCodingSyncEnabledFlag() { uiNumSubstreams = uint(pcSlice.GetNumEntryPointOffsets() + 1) } else { uiNumSubstreams = uint(pcSlice.GetPPS().GetNumSubstreams()) } // init each couple {EntropyDecoder, Substream} puiSubstreamSizes := pcSlice.GetSubstreamSizes() ppcSubstreams := make([]*TLibCommon.TComInputBitstream, uiNumSubstreams) this.m_pcSbacDecoders = make([]*TDecSbac, uiNumSubstreams) this.m_pcBinCABACs = make([]*TDecBinCabac, uiNumSubstreams) for ui := uint(0); ui < uiNumSubstreams; ui++ { this.m_pcSbacDecoders[ui] = NewTDecSbac() this.m_pcBinCABACs[ui] = NewTDecBinCabac() this.m_pcSbacDecoders[ui].Init(this.m_pcBinCABACs[ui]) if ui+1 < uiNumSubstreams { ppcSubstreams[ui] = pcBitstream.ExtractSubstream(puiSubstreamSizes[ui]) } else { ppcSubstreams[ui] = pcBitstream.ExtractSubstream(pcBitstream.GetNumBitsLeft()) } } for ui := uint(0); ui+1 < uiNumSubstreams; ui++ { this.m_pcEntropyDecoder.SetEntropyDecoder(this.m_pcSbacDecoders[uiNumSubstreams-1-ui]) this.m_pcEntropyDecoder.SetTraceFile(pTraceFile) this.m_pcEntropyDecoder.SetBitstream(ppcSubstreams[uiNumSubstreams-1-ui]) this.m_pcEntropyDecoder.ResetEntropy(pcSlice) } this.m_pcEntropyDecoder.SetEntropyDecoder(this.m_pcSbacDecoder) this.m_pcEntropyDecoder.SetTraceFile(pTraceFile) this.m_pcEntropyDecoder.SetBitstream(ppcSubstreams[0]) this.m_pcEntropyDecoder.ResetEntropy(pcSlice) if uiSliceStartCuAddr == uiStartCUAddr { l := len(this.m_LFCrossSliceBoundaryFlag) this.m_LFCrossSliceBoundaryFlag[l] = pcSlice.GetLFCrossSliceBoundaryFlag() //this.m_LFCrossSliceBoundaryFlag.PushBack( pcSlice.GetLFCrossSliceBoundaryFlag()); } this.m_pcSbacDecoders[0].Load(this.m_pcSbacDecoder) this.m_pcSliceDecoder.DecompressSlice(ppcSubstreams, rpcPic, this.m_pcSbacDecoder, this.m_pcSbacDecoders) this.m_pcEntropyDecoder.SetBitstream(ppcSubstreams[uiNumSubstreams-1]) // deallocate all created substreams, including internal buffers. /*for ui := uint(0); ui < uiNumSubstreams; ui++ { ppcSubstreams[ui]->deleteFifo(); delete ppcSubstreams[ui]; } delete[] ppcSubstreams; delete[] m_pcSbacDecoders; delete[] m_pcBinCABACs; */ this.m_pcSbacDecoders = nil this.m_pcBinCABACs = nil lAfterTime := time.Now() this.m_dDecTime += lAfterTime.Sub(iBeforeTime) }
func (this *TDecSlice) DecompressSlice(ppcSubstreams []*TLibCommon.TComInputBitstream, rpcPic *TLibCommon.TComPic, pcSbacDecoder *TDecSbac, pcSbacDecoders []*TDecSbac) { //var pcCU *TLibCommon.TComDataCU; uiIsLast := uint(0) var iStartCUEncOrder uint if rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()).GetSliceCurStartCUAddr()/rpcPic.GetNumPartInCU() > rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()).GetSliceSegmentCurStartCUAddr()/rpcPic.GetNumPartInCU() { iStartCUEncOrder = rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()).GetSliceCurStartCUAddr() / rpcPic.GetNumPartInCU() } else { iStartCUEncOrder = rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()).GetSliceSegmentCurStartCUAddr() / rpcPic.GetNumPartInCU() } iStartCUAddr := int(rpcPic.GetPicSym().GetCUOrderMap(int(iStartCUEncOrder))) // decoder don't need prediction & residual frame buffer rpcPic.SetPicYuvPred(nil) rpcPic.SetPicYuvResi(nil) //#if ENC_DEC_TRACE // g_bJustDoIt = g_bEncDecTraceEnable; //#endif // DTRACE_CABAC_VL( g_nSymbolCounter++ ); // DTRACE_CABAC_T( "\tPOC: " ); // DTRACE_CABAC_V( rpcPic.GetPOC() ); // DTRACE_CABAC_T( "\n" ); //#if ENC_DEC_TRACE // g_bJustDoIt = g_bEncDecTraceDisable; //#endif uiTilesAcross := rpcPic.GetPicSym().GetNumColumnsMinus1() + 1 pcSlice := rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()) iNumSubstreams := pcSlice.GetPPS().GetNumSubstreams() // delete decoders if already allocated in previous slice /*if (m_pcBufferSbacDecoders) { delete [] m_pcBufferSbacDecoders; } if (m_pcBufferBinCABACs) { delete [] m_pcBufferBinCABACs; }*/ // allocate new decoders based on tile numbaer this.m_pcBufferSbacDecoders = make([]*TDecSbac, uiTilesAcross) this.m_pcBufferBinCABACs = make([]*TDecBinCabac, uiTilesAcross) for ui := 0; ui < uiTilesAcross; ui++ { this.m_pcBufferBinCABACs[ui] = NewTDecBinCabac() this.m_pcBufferSbacDecoders[ui] = NewTDecSbac() this.m_pcBufferSbacDecoders[ui].Init(this.m_pcBufferBinCABACs[ui]) } //save init. state for ui := 0; ui < uiTilesAcross; ui++ { this.m_pcBufferSbacDecoders[ui].Load(pcSbacDecoder) } // free memory if already allocated in previous call /*if (this.m_pcBufferLowLatSbacDecoders) { delete [] this.m_pcBufferLowLatSbacDecoders; } if (this.m_pcBufferLowLatBinCABACs) { delete [] this.m_pcBufferLowLatBinCABACs; }*/ this.m_pcBufferLowLatSbacDecoders = make([]*TDecSbac, uiTilesAcross) this.m_pcBufferLowLatBinCABACs = make([]*TDecBinCabac, uiTilesAcross) for ui := 0; ui < uiTilesAcross; ui++ { this.m_pcBufferLowLatBinCABACs[ui] = NewTDecBinCabac() this.m_pcBufferLowLatSbacDecoders[ui] = NewTDecSbac() this.m_pcBufferLowLatSbacDecoders[ui].Init(this.m_pcBufferLowLatBinCABACs[ui]) } //save init. state for ui := 0; ui < uiTilesAcross; ui++ { this.m_pcBufferLowLatSbacDecoders[ui].Load(pcSbacDecoder) } uiWidthInLCUs := rpcPic.GetPicSym().GetFrameWidthInCU() //UInt uiHeightInLCUs = rpcPic.GetPicSym().GetFrameHeightInCU(); uiCol := uint(0) uiLin := uint(0) uiSubStrm := uint(0) var uiTileCol, uiTileStartLCU, uiTileLCUX uint iNumSubstreamsPerTile := 1 // if independent. depSliceSegmentsEnabled := rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()).GetPPS().GetDependentSliceSegmentsEnabledFlag() uiTileStartLCU = rpcPic.GetPicSym().GetTComTile(rpcPic.GetPicSym().GetTileIdxMap(iStartCUAddr)).GetFirstCUAddr() if depSliceSegmentsEnabled { if (!rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()).IsNextSlice()) && iStartCUAddr != int(rpcPic.GetPicSym().GetTComTile(rpcPic.GetPicSym().GetTileIdxMap(iStartCUAddr)).GetFirstCUAddr()) { if pcSlice.GetPPS().GetEntropyCodingSyncEnabledFlag() { uiTileCol = rpcPic.GetPicSym().GetTileIdxMap(iStartCUAddr) % uint(rpcPic.GetPicSym().GetNumColumnsMinus1()+1) this.m_pcBufferSbacDecoders[uiTileCol].LoadContexts(this.CTXMem[1]) //2.LCU if (uint(iStartCUAddr)%uiWidthInLCUs + 1) >= uiWidthInLCUs { uiTileLCUX = uiTileStartLCU % uiWidthInLCUs uiCol = uint(iStartCUAddr) % uiWidthInLCUs if uiCol == uiTileLCUX { this.CTXMem[0].LoadContexts(pcSbacDecoder) } } } pcSbacDecoder.LoadContexts(this.CTXMem[0]) //end of depSlice-1 pcSbacDecoders[uiSubStrm].LoadContexts(pcSbacDecoder) } else { if pcSlice.GetPPS().GetEntropyCodingSyncEnabledFlag() { this.CTXMem[1].LoadContexts(pcSbacDecoder) } this.CTXMem[0].LoadContexts(pcSbacDecoder) } } for iCUAddr := iStartCUAddr; uiIsLast == 0 && iCUAddr < int(rpcPic.GetNumCUsInFrame()); iCUAddr = int(rpcPic.GetPicSym().XCalculateNxtCUAddr(uint(iCUAddr))) { pcCU := rpcPic.GetCU(uint(iCUAddr)) pcCU.InitCU(rpcPic, uint(iCUAddr)) fmt.Printf("%d ", iCUAddr) //#ifdef ENC_DEC_TRACE pcSbacDecoder.XTraceLCUHeader(TLibCommon.TRACE_LCU) pcSbacDecoder.XReadAeTr(iCUAddr, "lcu_address", TLibCommon.TRACE_LCU) pcSbacDecoder.XReadAeTr(int(rpcPic.GetPicSym().GetTileIdxMap(iCUAddr)), "tile_id", TLibCommon.TRACE_LCU) //#endif uiTileCol = rpcPic.GetPicSym().GetTileIdxMap(int(iCUAddr)) % uint(rpcPic.GetPicSym().GetNumColumnsMinus1()+1) // what column of tiles are we in? uiTileStartLCU = rpcPic.GetPicSym().GetTComTile(rpcPic.GetPicSym().GetTileIdxMap(int(iCUAddr))).GetFirstCUAddr() uiTileLCUX = uiTileStartLCU % uiWidthInLCUs uiCol = uint(iCUAddr) % uiWidthInLCUs // The 'line' is now relative to the 1st line in the slice, not the 1st line in the picture. uiLin = (uint(iCUAddr) / uiWidthInLCUs) - (uint(iStartCUAddr) / uiWidthInLCUs) // inherit from TR if necessary, select substream to use. if (pcSlice.GetPPS().GetNumSubstreams() > 1) || (depSliceSegmentsEnabled && (uiCol == uiTileLCUX) && (pcSlice.GetPPS().GetEntropyCodingSyncEnabledFlag())) { // independent tiles => substreams are "per tile". iNumSubstreams has already been multiplied. iNumSubstreamsPerTile = iNumSubstreams / rpcPic.GetPicSym().GetNumTiles() uiSubStrm = rpcPic.GetPicSym().GetTileIdxMap(iCUAddr)*uint(iNumSubstreamsPerTile) + uiLin%uint(iNumSubstreamsPerTile) this.m_pcEntropyDecoder.SetBitstream(ppcSubstreams[uiSubStrm]) // Synchronize cabac probabilities with upper-right LCU if it's available and we're at the start of a line. if ((pcSlice.GetPPS().GetNumSubstreams() > 1) || depSliceSegmentsEnabled) && (uiCol == uiTileLCUX) && (pcSlice.GetPPS().GetEntropyCodingSyncEnabledFlag()) { // We'll sync if the TR is available. pcCUUp := pcCU.GetCUAbove() uiWidthInCU := rpcPic.GetFrameWidthInCU() var pcCUTR *TLibCommon.TComDataCU if pcCUUp != nil && ((uint(iCUAddr)%uiWidthInCU + 1) < uiWidthInCU) { pcCUTR = rpcPic.GetCU(uint(iCUAddr) - uiWidthInCU + 1) } uiMaxParts := uint(1 << (pcSlice.GetSPS().GetMaxCUDepth() << 1)) if true && //bEnforceSliceRestriction ((pcCUTR == nil) || (pcCUTR.GetSlice() == nil) || ((pcCUTR.GetSCUAddr() + uiMaxParts - 1) < pcSlice.GetSliceCurStartCUAddr()) || (rpcPic.GetPicSym().GetTileIdxMap(int(pcCUTR.GetAddr())) != rpcPic.GetPicSym().GetTileIdxMap(iCUAddr))) { // TR not available. } else { // TR is available, we use it. pcSbacDecoders[uiSubStrm].LoadContexts(this.m_pcBufferSbacDecoders[uiTileCol]) } } pcSbacDecoder.Load(pcSbacDecoders[uiSubStrm]) //this load is used to simplify the code (avoid to change all the call to pcSbacDecoders) } else if pcSlice.GetPPS().GetNumSubstreams() <= 1 { // Set variables to appropriate values to avoid later code change. iNumSubstreamsPerTile = 1 } if (uint(iCUAddr) == rpcPic.GetPicSym().GetTComTile(rpcPic.GetPicSym().GetTileIdxMap(iCUAddr)).GetFirstCUAddr()) && // 1st in tile. (iCUAddr != 0) && (uint(iCUAddr) != rpcPic.GetPicSym().GetPicSCUAddr(rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()).GetSliceCurStartCUAddr())/rpcPic.GetNumPartInCU()) && (uint(iCUAddr) != rpcPic.GetPicSym().GetPicSCUAddr(rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()).GetSliceSegmentCurStartCUAddr())/rpcPic.GetNumPartInCU()) { // !1st in frame && !1st in slice if pcSlice.GetPPS().GetNumSubstreams() > 1 { // We're crossing into another tile, tiles are independent. // When tiles are independent, we have "substreams per tile". Each substream has already been terminated, and we no longer // have to perform it here. // For TILES_DECODER, there can be a header at the start of the 1st substream in a tile. These are read when the substreams // are extracted, not here. } else { sliceType := pcSlice.GetSliceType() if pcSlice.GetCabacInitFlag() { switch sliceType { case TLibCommon.P_SLICE: // change initialization table to B_SLICE intialization sliceType = TLibCommon.B_SLICE //break; case TLibCommon.B_SLICE: // change initialization table to P_SLICE intialization sliceType = TLibCommon.P_SLICE //break; //default : // should not occur //assert(0); } } this.m_pcEntropyDecoder.UpdateContextTables(sliceType, pcSlice.GetSliceQp()) } } //#if ENC_DEC_TRACE // g_bJustDoIt = g_bEncDecTraceEnable; //#endif if pcSlice.GetSPS().GetUseSAO() && (pcSlice.GetSaoEnabledFlag() || pcSlice.GetSaoEnabledFlagChroma()) { saoParam := rpcPic.GetPicSym().GetSaoParam() saoParam.SaoFlag[0] = pcSlice.GetSaoEnabledFlag() if iCUAddr == iStartCUAddr { saoParam.SaoFlag[1] = pcSlice.GetSaoEnabledFlagChroma() } numCuInWidth := saoParam.NumCuInWidth cuAddrInSlice := iCUAddr - int(rpcPic.GetPicSym().GetCUOrderMap(int(pcSlice.GetSliceCurStartCUAddr()/rpcPic.GetNumPartInCU()))) cuAddrUpInSlice := cuAddrInSlice - numCuInWidth rx := iCUAddr % numCuInWidth ry := iCUAddr / numCuInWidth allowMergeLeft := true allowMergeUp := true if rx != 0 { if rpcPic.GetPicSym().GetTileIdxMap(iCUAddr-1) != rpcPic.GetPicSym().GetTileIdxMap(iCUAddr) { allowMergeLeft = false } } if ry != 0 { if rpcPic.GetPicSym().GetTileIdxMap(iCUAddr-numCuInWidth) != rpcPic.GetPicSym().GetTileIdxMap(iCUAddr) { allowMergeUp = false } } pcSbacDecoder.ParseSaoOneLcuInterleaving(rx, ry, saoParam, pcCU, cuAddrInSlice, cuAddrUpInSlice, allowMergeLeft, allowMergeUp) } else if pcSlice.GetSPS().GetUseSAO() { addr := pcCU.GetAddr() saoParam := rpcPic.GetPicSym().GetSaoParam() for cIdx := 0; cIdx < 3; cIdx++ { saoLcuParam := &(saoParam.SaoLcuParam[cIdx][addr]) if ((cIdx == 0) && !pcSlice.GetSaoEnabledFlag()) || ((cIdx == 1 || cIdx == 2) && !pcSlice.GetSaoEnabledFlagChroma()) { saoLcuParam.MergeUpFlag = false saoLcuParam.MergeLeftFlag = false saoLcuParam.SubTypeIdx = 0 saoLcuParam.TypeIdx = -1 saoLcuParam.Offset[0] = 0 saoLcuParam.Offset[1] = 0 saoLcuParam.Offset[2] = 0 saoLcuParam.Offset[3] = 0 } } } this.m_pcCuDecoder.DecodeCU(pcCU, &uiIsLast) this.m_pcCuDecoder.DecompressCU(pcCU) //#if ENC_DEC_TRACE // g_bJustDoIt = g_bEncDecTraceDisable; //#endif pcSbacDecoders[uiSubStrm].Load(pcSbacDecoder) //Store probabilities of second LCU in line into buffer if (uiCol == uiTileLCUX+1) && (depSliceSegmentsEnabled || (pcSlice.GetPPS().GetNumSubstreams() > 1)) && (pcSlice.GetPPS().GetEntropyCodingSyncEnabledFlag()) { this.m_pcBufferSbacDecoders[uiTileCol].LoadContexts(pcSbacDecoders[uiSubStrm]) } if uiIsLast != 0 && depSliceSegmentsEnabled { if pcSlice.GetPPS().GetEntropyCodingSyncEnabledFlag() { this.CTXMem[1].LoadContexts(this.m_pcBufferSbacDecoders[uiTileCol]) //ctx 2.LCU } this.CTXMem[0].LoadContexts(pcSbacDecoder) //ctx end of dep.slice return } } return }
func (this *TDecGop) FilterPicture(rpcPic *TLibCommon.TComPic) { pcSlice := rpcPic.GetSlice(rpcPic.GetCurrSliceIdx()) //-- For time output for each slice iBeforeTime := time.Now() // deblocking filter bLFCrossTileBoundary := pcSlice.GetPPS().GetLoopFilterAcrossTilesEnabledFlag() this.m_pcLoopFilter.SetCfg(bLFCrossTileBoundary) this.m_pcLoopFilter.LoopFilterPic(rpcPic) if pcSlice.GetSPS().GetUseSAO() { l := len(this.m_sliceStartCUAddress) this.m_sliceStartCUAddress[l] = int(rpcPic.GetNumCUsInFrame() * rpcPic.GetNumPartInCU()) ///this.m_sliceStartCUAddress.PushBack(rpcPic.GetNumCUsInFrame()* rpcPic.GetNumPartInCU()); rpcPic.CreateNonDBFilterInfo(this.m_sliceStartCUAddress, 0, this.m_LFCrossSliceBoundaryFlag, rpcPic.GetPicSym().GetNumTiles(), bLFCrossTileBoundary) } if pcSlice.GetSPS().GetUseSAO() { saoParam := rpcPic.GetPicSym().GetSaoParam() saoParam.SaoFlag[0] = pcSlice.GetSaoEnabledFlag() saoParam.SaoFlag[1] = pcSlice.GetSaoEnabledFlagChroma() this.m_pcSAO.SetSaoLcuBasedOptimization(true) this.m_pcSAO.CreatePicSaoInfo(rpcPic) //, len(this.m_sliceStartCUAddress)-1) this.m_pcSAO.SAOProcess(saoParam) this.m_pcSAO.PCMLFDisableProcess(rpcPic) this.m_pcSAO.DestroyPicSaoInfo() } if pcSlice.GetSPS().GetUseSAO() { rpcPic.DestroyNonDBFilterInfo() } rpcPic.CompressMotion() //this.DumpMotionField(rpcPic); var c string if pcSlice.IsIntra() { c = "I" } else if pcSlice.IsInterP() { if pcSlice.IsReferenced() { c = "P" } else { c = "p" } } else { if pcSlice.IsReferenced() { c = "B" } else { c = "b" } } //-- For time output for each slice fmt.Printf("\nPOC %4d TId: %1d ( %s-SLICE, QP%3d ) ", pcSlice.GetPOC(), pcSlice.GetTLayer(), c, pcSlice.GetSliceQp()) this.m_dDecTime += time.Now().Sub(iBeforeTime) fmt.Printf("[DT %10v] ", this.m_dDecTime) this.m_dDecTime = 0 for iRefList := 0; iRefList < 2; iRefList++ { fmt.Printf("[L%d ", iRefList) for iRefIndex := 0; iRefIndex < pcSlice.GetNumRefIdx(TLibCommon.RefPicList(iRefList)); iRefIndex++ { fmt.Printf("%d ", pcSlice.GetRefPOC(TLibCommon.RefPicList(iRefList), iRefIndex)) } fmt.Printf("] ") } if this.m_decodedPictureHashSEIEnabled > 0 { this.CalcAndPrintHashStatus(rpcPic.GetPicYuvRec(), rpcPic.GetSEIs()) } rpcPic.SetOutputMark(true) rpcPic.SetReconMark(true) //this.m_sliceStartCUAddress.Init(); //this.m_LFCrossSliceBoundaryFlag.Init(); slicesize := len(this.m_sliceStartCUAddress) for i := 0; i < slicesize; i++ { delete(this.m_sliceStartCUAddress, i) } if len(this.m_sliceStartCUAddress) != 0 { fmt.Printf("clear this.m_sliceStartCUAddress error\n") } lfsize := len(this.m_LFCrossSliceBoundaryFlag) for i := 0; i < lfsize; i++ { delete(this.m_LFCrossSliceBoundaryFlag, i) } if len(this.m_LFCrossSliceBoundaryFlag) != 0 { fmt.Printf("clear this.m_LFCrossSliceBoundaryFlag error\n") } }