func (this *TAppDecTop) IsNaluWithinTargetDecLayerIdSet(nalu *TLibDecoder.InputNALUnit) bool { if this.m_targetDecLayerIdSet.Len() == 0 { // By default, the set is empty, meaning all LayerIds are allowed return true } for e := this.m_targetDecLayerIdSet.Front(); e != nil; e = e.Next() { it := e.Value.(int) if int(nalu.GetReservedZero6Bits()) == it { return true } } return false }
func (this *TAppDecTop) Decode() (err error) { bSkipPictureForBLA := false var poc int var pcListPic *list.List // = NULL; var nalUnit, oldNalUnit *list.List //vector<uint8_t> var nalu TLibDecoder.InputNALUnit bitstreamFile, err := os.Open(this.m_pchBitstreamFile) if err != nil { fmt.Printf("\nfailed to open bitstream file `%s' for reading\n", this.m_pchBitstreamFile) return err } defer bitstreamFile.Close() bytestream := TLibDecoder.NewInputByteStream(bitstreamFile) // create & initialize internal classes this.xCreateDecLib() this.xInitDecLib() this.m_iPOCLastDisplay += this.m_iSkipFrame // set the last displayed POC correctly for skip forward. // main decoder loop recon_opened := false // reconstruction file not yet opened. (must be performed after SPS is seen) eof := false bNewPicture := false iDecodedFrameNum := 0 for !eof || bNewPicture { // (!!bitstreamFile) /* location serves to work around a design fault in the decoder, whereby * the process of reading a new slice that is the first slice of a new frame * requires the TDecTop::decode() method to be called again with the same * nal unit. */ //streampos location = bitstreamFile.tellg(); var stats TLibDecoder.AnnexBStats // stats = AnnexBStats(); bPreviousPictureDecoded := false if !bNewPicture { nalUnit = list.New() //vector<uint8_t> eof, _ = bytestream.ByteStreamNALUnit(nalUnit, &stats) } else { nalUnit = oldNalUnit } // call actual decoding function if nalUnit.Len() == 0 { /* this can happen if the following occur: * - empty input file * - two back-to-back start_code_prefixes * - start_code_prefix immediately followed by EOF */ fmt.Printf("Warning: Attempt to decode an empty NAL unit\n") break } else { //fmt.Printf("NalUnit Len=%d\n", nalUnit.Len()) oldNalUnit = nalu.Read(nalUnit) //fmt.Printf("Type=%d\n", nalu.GetNalUnitType()) if (this.m_iMaxTemporalLayer >= 0 && int(nalu.GetTemporalId()) > this.m_iMaxTemporalLayer) || !this.IsNaluWithinTargetDecLayerIdSet(&nalu) { if bPreviousPictureDecoded { bNewPicture = true bPreviousPictureDecoded = false } else { bNewPicture = false } } else { bNewPicture = this.m_cTDecTop.Decode(&nalu, &this.m_iSkipFrame, &this.m_iPOCLastDisplay, &bSkipPictureForBLA, !bNewPicture) bPreviousPictureDecoded = true } } if bNewPicture || eof { pcListPic = this.m_cTDecTop.ExecuteLoopFilters(&poc, bSkipPictureForBLA) } if pcListPic != nil { if this.m_pchReconFile != "" && !recon_opened { if this.m_outputBitDepthY == 0 { this.m_outputBitDepthY = TLibCommon.G_bitDepthY } if this.m_outputBitDepthC == 0 { this.m_outputBitDepthC = TLibCommon.G_bitDepthC } this.m_cTVideoIOYuvReconFile.Open(this.m_pchReconFile, true, this.m_outputBitDepthY, this.m_outputBitDepthC, TLibCommon.G_bitDepthY, TLibCommon.G_bitDepthC) // write mode recon_opened = true } //fmt.Printf("bNewPicture=%d m_nalUnitType=%d ", TLibCommon.B2U(bNewPicture), nalu.GetNalUnitType()); if bNewPicture && (nalu.GetNalUnitType() == TLibCommon.NAL_UNIT_CODED_SLICE_IDR || nalu.GetNalUnitType() == TLibCommon.NAL_UNIT_CODED_SLICE_IDR_N_LP || nalu.GetNalUnitType() == TLibCommon.NAL_UNIT_CODED_SLICE_BLA_N_LP || nalu.GetNalUnitType() == TLibCommon.NAL_UNIT_CODED_SLICE_BLANT || nalu.GetNalUnitType() == TLibCommon.NAL_UNIT_CODED_SLICE_BLA) { this.xFlushOutput(pcListPic) } // write reconstruction to file if bNewPicture { this.xWriteOutput(pcListPic, nalu.GetTemporalId()) iDecodedFrameNum++ if iDecodedFrameNum >= this.m_iFrameNum && this.m_iFrameNum > 0 { break } } } } this.xFlushOutput(pcListPic) // delete buffers this.m_cTDecTop.DeletePicBuffer() // destroy internal classes this.xDestroyDecLib() return nil }