Understanding VC-1
There is a WMV9/VC-1 reference decoder available on the internet which answers to the filename vc1_reference_decoder_release6.zip. This section of the MultimediaWiki is an effort to create an open VC-1 specification based on that reference implementation.
Supplemental Pages:
Acronyms/Abbreviations
This section defines various terms that are useful to know when plodding through a discussion of the VC-1 reference implementation.
- AC/DC/DCAC = transform coefficients
- CBP/CBPCY = coded block pattern
- IC = intensity compensation
- IDU = independently decodable unit
- MB = macroblock
- MV = motion vector
- MVBP = motion vector block pattern
- NZC = non-zero coefficients
- PQuant/AltPQuant = probably means picture-level quantizer/alternate picture-level quantizer
- RLL = run/level/last values
- SBP = sub block pattern
- SRD = SMPTE reference decoder (used in this description, not in the actual SRD)
- TTBLK = block transform type
- TTMB = macroblock transform type
- VOP = video object plane (?)
Frame Types
- I-frame: intraframe
- P-frame: predicted frame
- B-frame: bi-directionally predicted frame
- BI-frame: B-frames where all macroblocks are intra coded, but the frame cannot be used as a reference.
Hierarchy of VC-1 Decoding Functions
These functions are necessary for processing VC-1 data using the reference decoder:
// set up pointers to bitstream (extradata) in internal state structure vc1DECBIT_InitialiseBitstream // analyze how much memory the client app needs to allocate vc1DEC_DecoderRequirements // init decoder vc1DEC_DecoderInitialise // process the extradata setup bitstream vc1DEC_DecodeSequence // decode a frame vc1DEC_DecodeFrame
These are the call trees for the above functions
vc1DECBIT_InitialiseBitstream +- vc1DECBIT_ReadBytes
vc1DEC_DecoderRequirements +- vc1DECBIT_GetBits +- vc1TOOLS_InitReferencePicture +- vc1TOOLS_InitImagePosition
vc1DEC_DecoderInitialise +- vc1DEC_SetMaxSize +- vc1TOOLS_InitReferencePicture
vc1DEC_DecodeSequence +- vc1DECSEQ_UnpackSequenceLayer +- vc1DECBIT_GetBits
vc1DEC_DecodeFrame +- vc1DECPIC_UnpackPictureLayer +- vc1DECPIC_ReadPictureLayer +- vc1DECBIT_GetBits +- vc1DECPIC_SetDimensionsInMB +- vc1DECPIC_UnpackPictureLayerAdvanced +- vc1DECBIT_GetBits +- vc1DECBIT_GetVLC +- vc1DECPIC_UnpackPanScanParams +- vc1DECBIT_GetBits +- vc1DECPIC_UnpackPictureLayerSimpleMain +- vc1DECBIT_BitCountGet +- vc1DECBIT_GetBits +- vc1DECBIT_GetVLC +- vc1DECPIC_UnpackQuantizationParams +- vc1DECBIT_GetBits +- vc1IQUANT_GetQuantizer +- vc1DECPIC_SetDimensionsInMB +- vc1DECBITPL_ReadBitplane +- vc1DECBIT_GetBits +- vc1DECBIT_GetVLC +- vc1DECBITPL_DecodeNorm2Bits +- vc1DECBIT_GetBits +- vc1DECBIT_GetVLC +- vc1DECBITPL_DecodeNorm6Bits +- vc1DECBIT_GetBits +- vc1DECBIT_GetVLC +- vc1DECBITPL_DecodeRowskipBits +- vc1DECBIT_GetBits +- vc1DECBITPL_DecodeColskipBits +- vc1DECBIT_GetBits +- vc1DECBITPL_DecodeDiff2Bits +- vc1DECBITPL_DecodeNorm2Bits +- vc1DECBITPL_BitplaneDiff +- vc1DECBITPL_DecodeDiff6Bits +- vc1DECBITPL_DecodeNorm6Bits +- vc1DECBITPL_BitplaneDiff +- vc1DECBITPL_DecodeRawBits +- vc1DECPIC_UnpackVOPDQUANTParams +- vc1DECBIT_GetBits +- vc1DECPIC_UnpackFieldPictureLayer +- vc1DECPIC_ReadAdvancedPictureLayer +- vc1DECPIC_UnpackFieldPictureLayerIAdvanced +- vc1DECPIC_UnpackQuantizationParams +- vc1DECBIT_GetBits +- vc1DECBITPL_ReadBitplane +- vc1DECBIT_GetVLC +- vc1DECPIC_UnpackVOPDQUANTParams +- vc1DECPIC_UnpackFieldPictureLayerPBAdvanced +- vc1DECPIC_UnpackQuantizationParams +- vc1DECBIT_GetBits +- vc1DECBIT_GetVLC +- vc1DECPIC_UnpackInterlaceMVModeParams +- vc1DECBITPL_ReadBitplane +- vc1DECPIC_DisplayPicture +- vc1DECPIC_DisplayField +- vc1DECPIC_InitialiseAppPicture +- vc1TOOLS_ResolutionUpsample +- vc1TOOLS_InitReferencePicture +- vc1TOOLS_NewReference +- vc1TOOLS_CopyReference +- vc1TOOLS_ICPadReferencePicture +- vc1TOOLS_RangeReduceReference +- vc1TOOLS_RangeReduce16 +- vc1TOOLS_RangeExpand +- vc1TOOLS_IntensityCompensate +- vc1TOOLS_ICComponent +- vc1TOOLS_PadReferencePicture +- vc1TOOLS_PadComponent +- vc1SCALEMV_InitScaleMV +- vc1DECSLICE_DecodeSlice +- vc1DECBIT_GetBits +- vc1DECPIC_UnpackSyncmarker +- vc1DECBIT_AlignBit +- vc1DECBIT_ReadBytes +- vc1DECBIT_GetBits +- vc1DECMB_UnpackMacroblockLayer +- vc1IQUANT_ChooseQuantizer +- vc1DECMB_UnpackMacroblockI +- vc1DECBITPL_ReadBitplaneBit +- vc1DECBIT_GetBits +- vc1DECBIT_GetVLC +- vc1PREDCBP_ApplyCBPCYPred +- vc1DECBIT_GetBits +- vc1DECMB_UnpackMBQuantParams +- vc1DECBIT_GetBits +- vc1DECMB_UnpackMacroblockProgP +- vc1DECBITPL_ReadBitplaneBit +- vc1DECMB_UnpackMacroblockProgPSkipped +- vc1DECBIT_LookBits +- vc1DECBIT_ReadBits +- vc1PREDMV_PredictProgressiveMV +- vc1PRED_pTopBlk +- vc1PRED_pLeftBlk +- vc1PRED_pB1MVBlk +- vc1PRED_pB4MVBlk +- vc1TOOLS_Median3 +- vc1CROPMV_BPredPullBack +- vc1DECBIT_GetBits +- vc1DECMV_ApplyMVPrediction +- vc1DERIVEMV_DecideChromaBlockType +- vc1DECMB_UnpackMacroblockProgP1MV +- vc1DECMV_UnpackMVData +- vc1DECBIT_LookBits +- vc1PREDMV_PredictProgressiveMV +- vc1DECBIT_GetBits +- vc1DECMV_ApplyMVPrediction +- vc1DERIVEMV_DecideChromaBlockType +- vc1DECMB_UnpackMBQuantParams +- vc1DECBIT_GetVLC +- vc1DECMB_DecodeTransformInfo +- vc1DECMB_UnpackTTMB +- vc1DECBIT_GetVLC +- vc1DECMB_UnpackMacroblockProgP4MV +- vc1DECBIT_GetVLC +- vc1DECMV_UnpackMVData +- vc1DECBIT_LookBits +- vc1PREDMV_PredictProgressiveMV +- vc1DECBIT_GetBits +- vc1DECMV_ApplyMVPrediction +- vc1DERIVEMV_DecideChromaBlockType +- vc1DECMB_UnpackMBQuantParams +- vc1PREDDCAC_ACPREDPresent +- vc1DECMB_DecodeTransformInfo +- vc1DECMB_UnpackMacroblockFieldP +- vc1DECBIT_GetVLC +- vc1DECMV_UnpackMVDataInterlace +- vc1DECBIT_GetVLC +- vc1DECBIT_GetBits +- vc1DECBIT_LookBits +- vc1PREDMV_PredictInterlacedFieldMV +- vc1SCALEMV_ScaleMV +- vc1TOOLS_Median3 +- vc1DECBIT_GetBits +- vc1DECMV_ApplyMVPrediction +- vc1DERIVEMV_DecideChromaBlockType +- vc1DECMB_UnpackMBQuantParams +- vc1DECMB_DecodeTransformInfo +- vc1DECMB_UnpackMacroblockFrameP +- vc1DECBITPL_ReadBitplaneBit +- vc1PREDMV_PredictInterlacedFrameMV +- vc1PREDMV_FrameMBPred +- vc1TOOLS_Median3 +- vc1DECMV_ApplyMVPrediction +- vc1DECBIT_GetVLC +- vc1DECBIT_GetBits +- vc1DERIVEMV_DecideChromaBlockType +- vc1DECMB_UnpackMBQuantParams +- vc1DECMV_UnpackMVDataInterlace +- vc1DECMB_UnpackMacroblockProgB +- vc1DECBITPL_ReadBitplaneBit +- vc1DECMV_UnpackMVData +- vc1DECBIT_GetVLC +- vc1DECMB_UnpackMBQuantParams +- vc1DECBIT_GetBits +- vc1PREDMV_PredictProgressiveMV +- vc1DECMV_ApplyMVPrediction +- vc1DERIVEMV_DecideChromaBlockType +- vc1DECMB_DecodeTransformInfo +- vc1DECMB_UnpackMacroblockFieldB +- vc1DECBIT_GetVLC +- vc1DECBITPL_ReadBitplaneBit +- vc1DECBITPL_SkipBitplaneBit +- vc1DECBIT_GetBits +- vc1DECMV_UnpackMVDataInterlace +- vc1PREDMV_PredictInterlacedFieldMV +- vc1DECMV_ApplyMVPrediction +- vc1DECMB_UnpackMBQuantParams +- vc1DERIVEMV_DecideChromaBlockType +- vc1DECMB_DecodeTransformInfo +- vc1DECMB_UnpackMacroblockFrameB +- vc1DECBITPL_ReadBitplaneBit +- vc1DECBIT_GetVLC +- vc1DECBITPL_SkipBitplaneBit +- vc1DECBIT_GetBits +- vc1DECMB_UnpackMBQuantParams +- vc1DERIVEMV_DecideChromaBlockType +- vc1DECMV_UnpackMVDataInterlace +- vc1PREDMV_PredictInterlacedFrameMV +- vc1DECMV_ApplyMVPrediction +- vc1DECMB_AssignCodedBlockPattern +- vc1DECBLK_DecodeBlockLayer +- vc1DECBLK_UnpackIntraBlock +- vc1PREDDCAC_DCDefault +- vc1PREDDCAC_DCStepSize +- vc1PREDDCAC_PredictDCAC +- vc1PREDDCAC_GetQuant +- vc1PREDDCAC_ScaleDC +- vc1PREDDCAC_DCStepSize +- vc1DECBLK_UnpackDCDifferential +- vc1DECBIT_GetVLC +- vc1DECBIT_GetBits +- vc1DEC3DH_DecodeACRunLevel +- vc1DEC3DH_ChooseACCodingSet +- vc1DEC3DH_ChooseEscapeMode3Table +- vc1DEC3DH_UnpackTransformACCoef +- vc1DECBIT_GetVLC +- vc1DECBIT_GetBits +- vc1DECZZ_DeZigZagBlock +- vc1DECZZ_DeZigZag +- vc1DECBLK_ApplyACPrediction +- vc1PREDDCAC_CopyDCAC +- vc1DECBLK_UnpackInterBlock +- vc1DECBLK_UnpackSubBlockPattern +- vc1DECBIT_GetVLC +- vc1DECBLK_UnpackTTBLK +- vc1DECBIT_GetVLC +- vc1DEC3DH_DecodeACRunLevel +- vc1DECZZ_DeZigZagBlock +- vc1INTERP_PredictMB +- vc1DERIVEMV_StoreMotionVectors +- vc1DERIVEMV_DeriveMV +- vc1DERIVEMV_DirectMV +- vc1DERIVEMV_DeriveProgMV +- vc1TOOLS_Median3 +- vc1TOOLS_Median4 +- vc1CROPMV_ChromaPullBack +- vc1DERIVEMV_DeriveIntFieldMV +- vc1TOOLS_Median4 +- vc1TOOLS_Median3 +- vc1DERIVEMV_DeriveIntFrameDirectMV +- vc1CROPMV_PPredPullBack +- vc1DERIVEMV_FillInInterlaceFieldMV +- vc1PREDMV_PredictInterlacedFieldMV +- vc1SCALEMV_ScaleMV +- vc1TOOLS_Median3 +- vc1INTERP_InterpolateBlock +- vc1CROPMV_LumaPullBack +- vc1DERIVEMV_DeriveChromaMV +- vc1DERIVEMV_DeriveProgMV +- vc1CROPMV_LumaPullBack +- vc1DERIVEMV_DeriveSecondStageChromaMV +- vc1CROPMV_ChromaPullBack +- vc1DERIVEMV_DeriveIntFieldMV +- vc1TOOLS_Median4 +- vc1CROPMV_ChromaPullBack +- vc1INTERP_InterpPatchQuarterPelBilinear +- vc1INTERP_InterpPatchHalfPelBilinear +- vc1INTERP_InterpPatchQuarterPelBilinear +- vc1INTERP_InterpPatchQuarterPelBicubic +- vc1INTERP_CopyPatch +- vc1INTERP_InterpPatchQuarterPelBicubicVert +- vc1INTERP_InterpPatchQuarterPelBicubicHoriz +- vc1INTERP_InterpPatchQuarterPelBicubicDiag +- vc1INTERP_InterpPatchHalfPelBicubic +- vc1INTERP_InterpPatchQuarterPelBicubic +- vc1INTERP_AverageBlocks +- vc1RECON_ReconstructMB +- vc1IQUANT_InverseACQuantize +- vc1IQUANT_InverseDCQuantize +- vc1PREDDCAC_DCStepSize +- vc1ITRANS_InverseTransformBlock +- vc1ITRANS_InverseTransform_AnnexA1 +- vc1RECON_ApplyPredictionAndCopyMB +- vc1INTERP_InterlaceDiffMB +- vc1INTERP_InterlacePredMB +- vc1SMOOTH_OverlapSmoothMB +- vc1PRED_pLeftMB +- vc1TOOLS_GetPictureDestination +- vc1SMOOTH_OverlapSmoothVertBlk +- vc1SMOOTH_OverlapSmoothHorizMB +- vc1TOOLS_GetPictureDestination +- vc1SMOOTH_OverlapSmoothHorizBlk +- vc1TOOLS_GetPictureDestination +- vc1SMOOTH_OverlapSmoothHorizMB +- vc1DEBLOCK_DeblockSlice +- vc1DEBLOCK_HorizDeblockMB +- vc1TOOLS_GetPictureDestination +- vc1DEBLOCK_HorizDeblockBlk +- vc1DEBLOCK_VertDeblockMB +- vc1TOOLS_GetPictureDestination +- vc1DEBLOCK_VertDeblockBlk +- vc1TOOLS_CopyReference +- vc1DECPIC_DisplayPicture
vc1CROPMV_BPredPullBack
vc1CROPMV_ChromaPullBack
vc1CROPMV_LumaPullBack
vc1CROPMV_PPredPullBack
vc1DEBLOCK_DeblockSlice
vc1DEBLOCK_HorizDeblockBlk
vc1DEBLOCK_HorizDeblockMB
vc1DEBLOCK_VertDeblockBlk
vc1DEBLOCK_VertDeblockMB
vc1DEC3DH_ChooseACCodingSet
This function selects an AC coding set to be used to decode a particular block.
- initialize chosen coding set to 0
- if picture type is P or B
- AC index = frame transform AC coding set index from picture parameters
- if this block is intra-coded
- if the block is a Y block
- coding set = 2
- if the block is a Y block
- else if the picture type is I or BI
- if the block is a Y block
- coding set = 2
- AC index = frame transform AC coding set index 2 from picture parameters
- else
- AC index = frame transform AC coding set index from picture parameters
- if the block is a Y block
- else
- fatal error: invalid picture type
- if picture quantizer index in picture parameters > 8
- coding set ++
note that the SRD contains 2 cases with the previous conditional, one for intra-coded blocks and one for inter-coded blocks; the code in both is the same but it apparently covers 2 different spots in the spec
- the AC coding set used is found in vc1DEC3DH_pACCodingSets[coding set][AC index] which is specified in VC-1 Tables#3D Huffman Tables
vc1DEC3DH_ChooseEscapeMode3Table
This function selects a block escape mode VLC table based on certain members in the picture parameters data structure.
- if (quantizer mode is not default) or (picture quantizer <= 7)
- choose table 1 (1 <= PQuant <= 7)
- else
- choose table 2 (8 <= PQuant <= 31)
vc1DEC3DH_DecodeACRunLevel
This function decodes a block's quantized AC coefficients from the bitstream. This includes runs of zero coefficients between non-zero AC coefficients.
- if the block is intra-coded
- make one pass for 63 AC coefficients (skip the DC coefficient)
- else if the block is inter-coded in 8x8
- make one pass for all 64 coefficients
- else if the block is inter-coded in 4x8 or 8x4
- make two passes, decoding 32 coefficients on each pass
- else if the block is inter-coded in 4x4
- make four decoding passes, decoding 16 coefficients on each pass
- else
- fatal error: unexpected block type
- foreach loop in number of passes
- if (block is intra-coded) or (this sub-block is coded)
- do
- call vc1DEC3DH_UnpackTransformACCoef to obtain a run, level, and last flag value
- skip (run) places in the output (all zeros)
- output the level as the next coefficient
- while (last flag is not set)
- do
- advance to the next block in the coefficient buffer
- if (block is intra-coded) or (this sub-block is coded)
Note that there is no check if run is larger than the maximum number of coefficients per subblock. It is unclear what the specification states in such case.
vc1DEC3DH_UnpackTransformACCoef
This function decodes a run value, a level value, and a last flag based on a selected AC coding set and selected escape mode 3 table.
- decode a VLC from the bitstream based on the VLC table specified in the AC coding set
- if the decoded VLC is an escape code
- decode the escape mode as a VLC from the bitstream based on the VLC table vc1DEC3DH_Escape_Decoding_Mode
- if the escape mode is 1
- decode a VLC from the bitstream based on the VLC table specified in the AC coding set
- the decoded value acts as an index into the RLL table specified in the AC coding set to obtain the run, level and last values
- if the last flag is set
- increase level by a value from the DeltaLevel table specified in the AC coding set and indexed by run
- else
- increase level by a value from the DeltaLevelLast table specified in the AC coding set and indexed by run
- 1 bit: level sign
- if the sign bit is set
- negate the level value
- if the escape mode is 2
- decode a VLC from the bitstream based on the VLC table specified in the AC coding set
- the decoded value acts as an index into the RLL table specified in the AC coding set to obtain the run, level and last values
- if the last flag is set
- increase run by a value from the DeltaRun table specified in the AC coding set and indexed by level
- increase run by 1
- else
- increase run by a value from the DeltaRunLast table specified in the AC coding set and indexed by level
- increase run by 1
- 1 bit: level sign
- if the sign bit is set
- negate the level value
- if the escape mode is 3
- 1 bit: last flag
- if this is the first time that this escape mode 3 occurs in this frame
- decode a VLC from the bitstream based on the VLC table selected as the escape mode 3 table
- this value is the LevelCodeSize of this frame
- 2 bis: value
- this value + 3 is the RunCodeSize of this frame
- decode run from the bitstream with a bit length of RunCodeSize bits
- 1 bit: level sign
- decode level from the bitstream with a bit length of LevelCodeSize bits
- if the sign bit is set
- negate the level value
- else
- the decoded value acts as an index into the RLL table specified in the AC coding set to obtain the run, level and last values
- 1 bit: level sign
- if the sign bit is set
- negate the level value
vc1DEC_DecodeFrame
call vc1DECPIC_UnpackPictureLayer
vc1DEC_DecoderInitialise
This sets up the positions and structures contained within the memory pool allocated for the SRD.
vc1DEC_DecoderRequirements
This function is an API glue function to the VC-1 reference decoder. The function takes the first part of the encoded bitstream (which may be the extradata setup information passed from an encapsulating ASF file), and DecoderCofiguration data structure, and returns the total number of bytes that the client application must allocate for the decoder to establish all of its internal data structures.
- 2 bits: VC-1 profile
- if (profile == advanced (3))
- 3 bits: which level in the advanced profile (invalid if greater than 4)
- 2 bits: chroma format (note that only format 1, YUV 4:2:0 is defined)
- 3 bits: QFrameRateForPostProc ("see standard", SRD does not use)
- 5 bits: QBitRateForPostProc ("see standard", SRD does not use)
- 1 bit: post processing flag (SRD does not use)
- 12 bits: max coded width (actual width = (width + 1) * 2)
- 12 bits: max coded height (actual height = (h + 1) * 2)
- else
- if level in decoder configuration data structure is set to unknown (VC-1 Enumerations#Profile Level Enumeration)
- max coded width and height were already set in the decoder configuration data structure
- width in macroblocks = (max coded width + 15) / 16
- height in macroblocks = (max coded height + 15) / 16
- number of macroblocks = MB width * MB height
- iterate through the level limits for the profile, starting at level 0, and find the first level that can handle the number of macroblocks in a frame; fatal error if none of the levels can handle the number
- if level in decoder configuration data structure is set to unknown (VC-1 Enumerations#Profile Level Enumeration)
- SRD requires space for an internal state data structure
- SRD requires space for a number of macroblock data structures; the number is equal to the maximum number allow by the profile/level limit, rather than the actual number in the frame
- call vc1TOOLS_InitReferencePicture to obtain size of an individual reference picture; invoke with parameters to indicate max coded dimensions, interlacing, and advanced profile, likely as a worst case scenario, space-wise
- SRD requires space for 4 frames, whose size is calculated in previous step; 4 frames are:
- old reference
- new reference
- B reference
- reference with no intensity compensation applied
- SRD requires space for 7 bitplanes; the space allocated is essentially 1 byte per macroblock, as defined by the maximum number of macroblocks allowed byte the profile/level limit; the 7 bitplanes are known as:
- ACPRED
- SKIPMB
- MVTYPEMB
- DIRECTMB
- OVERFLAGS
- FORWARDMB
- FIELDTX
- SRD requires a motion vector history data structure for each macroblock as defined by the actual number of macroblocks in the coded frame, + 1 row of macroblocks (SRD explains it's needed to handle interlaced field case)
- return a byte count indicating how much contiguous memory the client application needs to provide to the SRD
vc1DEC_DecodeSequence
call vc1DECSEQ_UnpackSequenceLayer
vc1DEC_SetMaxSize
This function takes the width and height dimension pair for an image. The function validates that the number of macroblocks is allowed under to current profile. Then it assigns the dimension pair (not rounded) to 5 other dimension pairs:
- vc1DEC_sState.vc1_sSequenceLayer.MaxCoded[Width|Height]
- vc1DEC_sState.vc1_sSequenceLayer.Coded[Width|Height]
- vc1DEC_sState.vc1_sSequenceLayer.Display[Width|Height]
- vc1DEC_sState.vc1_sPosition.Coded[Width|Height]
- vc1DEC_sState.vc1_sPosition.MaxCoded[Width|Height]
vc1DECBIT_AlignBit
This function aligns the input bitstream on a byte boundary.
vc1DECBIT_BitCountGet
This function returns the total number of unconsumed bits remaining in the input bitstream.
vc1DECBIT_GetBits
GetBits returns and consumes the next n bits from the bitstream, as opposed to LookBits, which does not consume the bits after reading them.
vc1DECBIT_GetVLC
The GetVLC function returns the value represented by the next variable length code (i.e., Huffman) code in the bitstream. The reference decoder performes this operation in an exceptionally slow manner but it is also not held to any specific performance standards. Thus, a new VC-1 implementation should maintain VLC tables and decode values from then however it sees fit to do so.
vc1DECBIT_InitialiseBitstream
This function takes a pointer to bitstream accounting structure, a pointer to a buffer containing an encoded bitstream, and the length of that buffer. It initializes the internal bitstream accounting data structure. It also calls vc1DECBIT_ReadBytes to fill up the internal bit buffer in preparation for bit extraction. This function can also accept a flag that specifies the IDUs are encapsulated.
vc1DECBIT_LookBits
LookBits asks the bitstream reader to return the next n bits from the stream but to not actually consume them, as GetBits() would do.
vc1DECBIT_ReadBits
ReadBits is essentially equivalent to GetBits.
vc1DECBIT_ReadBytes
ReadBytes() is a bitstream accounting function that ensures the 32-bit bit buffer is completely filled.
vc1DECBITPL_BitplaneDiff
This function takes a bitplane data structure, an invert bit, and the width and height of the frame in macroblocks. It decodes 1 bit per MB. The bitplane data structure is assumed to be arranged as a macroblock frame with (width x height) macroblocks.
Each MB bit in the bitplane (which was decoded by another function) is XOR'd against a predictor bit. The predictor bit depends on the MB's placement in the bitplane. The precise algorithm follows:
- foreach j in 0..MBheight - 1
- foreach i in 0..MBwidth - 1
- if i and j are both 0 (upper left MB)
- predictor = invert flag
- else if i is 0 (left column MB)
- predictor = the MB bit above the current MB (MB[MBwidth * (j - 1)])
- else if (the current MB is not on the top row) and (the MB bit above the current MB != the MB bit to the left of the current MB)
- predictor = invert flag
- else
- predictor = MB bit to the left of the current MB
- current MB bit = current MB bit XOR predictor
- if i and j are both 0 (upper left MB)
- foreach i in 0..MBwidth - 1
vc1DECBITPL_DecodeColskipBits
This function takes a bitplane data structure, an invert bit, and the width and height of the frame in macroblocks. It decodes 1 bit per MB. The bitplane data structure is assumed to be arranged as a macroblock frame with (width x height) macroblocks.
- foreach i in 0..MBwidth - 1
- 1 bit: column skip value (colskip)
- foreach j in 0..MBheight - 1
- value = 0
- if colskip is 1
- 1 bit: value
- bitplane_macroblock[j * MBwidth + i] = value
- apply invert bit as necessary
vc1DECBITPL_DecodeDiff2Bits
This function takes a bitplane data structure, an invert bit, and the width and height of the frame in macroblocks. It decodes 1 bit per MB.
- call vc1DECBITPL_DecodeNorm2Bits with the invert parameter set to false
- call vc1DECBITPL_BitplaneDiff
vc1DECBITPL_DecodeDiff6Bits
This function takes a bitplane data structure, an invert bit, and the width and height of the frame in macroblocks. It decodes 1 bit per MB.
- call vc1DECBITPL_DecodeNorm6Bits with the invert parameter set to false
- call vc1DECBITPL_BitplaneDiff
vc1DECBITPL_DecodeNorm2Bits
This function takes a bitplane data structure, an invert bit, and the width (MBwidth) and height (MBheight) of the frame in macroblocks. It decodes 1 bit per MB.
- MBcount = count of MBs in frame (MBwidth * MBheight)
- if MBcount is odd
- 1 bit: value defines the first MB
- if the invert flag is set
- invert the value
- decrement MBcount
- foreach i in MBcount/2
- decode a VLC from the bitstream using the Norm-2 VLC table
- if the invert flag is set
- invert the decoded value
- the 2-bit value is laid out as a 'ab' bit sequence (msb first) and applied to the next 2 MBs
note that the bits are applied differently to Norm-6. Norm-2 uses msb first but Norm-6 uses lsb first.
vc1DECBITPL_DecodeNorm6Bits
This function takes a bitplane data structure, an invert bit, and the width (MBwidth) and height (MBheight) of the frame in macroblocks. It decodes 1 bit per MB.
- if the MBheight is divisible by 3 but the MBwidth is not
- decode using 2x3 tiles as follows...
- a b
- c d
- e f
- foreach 2x3 tile in bitplane data structure progressing from left → right and top → bottom
- decode a VLC from the bitstream using the Norm-6 VLC table
- if the invert flag is set
- invert the decoded value
- the 6-bit value is laid out as a 'fedcba' bit sequence (lsb first) and applied in the arrangement given above
- ResidualX = MBwidth modulo 2
- ResidualY = MBheight modulo 3 which is always 0
- decode using 2x3 tiles as follows...
- else
- decode using 3x2 tiles as follows...
- a b c
- d e f
- foreach 3x2 tile in bitplane data structure progressing from left → right and top → bottom
- decode a VLC from the bitstream using the Norm-6 VLC table
- if the invert flag is set
- invert the decoded value
- the 6-bit value is laid out as a 'fedcba' bit sequence (lsb first) and applied in the arrangement given above
- ResidualX = MBwidth modulo 3
- ResidualY = MBheight modulo 2
- decode using 3x2 tiles as follows...
- foreach i in ResidualX
- read the column as defined in colskip
- foreach i in ResidualY
- read the row as defined in rowskip
vc1DECBITPL_DecodeRawBits
This function is conceptually a no-op. In raw mode, the bitplane is not encoded at all. 8 bitplane bits are packed into each byte and are read from right -> left.
vc1DECBITPL_DecodeRowskipBits
This function takes a bitplane data structure, an invert bit, and the width and height of the frame in macroblocks. It decodes 1 bit per MB. The bitplane data structure is assumed to be arranged as a macroblock frame with (width x height) macroblocks.
- foreach j in 0..MBheight - 1
- 1 bit: row skip value (rowskip)
- foreach i in 0..MBwidth - 1
- value rowskip is 1
- 1 bit: value
- bitplane_macroblock[j * MBwidth + i] = value
- apply invert bit as necessary
- value rowskip is 1
vc1DECBITPL_ReadBitplane
This function decodes a bitplane from an encoded VC-1 bitstream using 1 of a number of different methods.
- 1 bit: bitplane invert
- VLC: I-mode table VLC
- initialize bitplane data structure BP:
- BP.position = 0
- BP.RawMode = false
- select bitplane decoding method using I-mode VLC:
- 0: normal-2 bitplane coding, call vc1DECBITPL_DecodeNorm2Bits
- 1: normal-6 bitplane coding, call vc1DECBITPL_DecodeNorm6Bits
- 2: rowskip bitplane coding, call vc1DECBITPL_DecodeRowskipBits
- 3: colskip bitplane coding, call vc1DECBITPL_DecodeColskipBits
- 4: diff-2 bitplane coding, call vc1DECBITPL_DecodeDiff2Bits
- 5: diff-6 bitplane coding, call vc1DECBITPL_DecodeDiff6Bits
- 6: raw bitplane coding, vc1DECBITPL_DecodeRawBits
- if the coding mode was not 6 (raw)
- indicate in the master state structure that bitplane coding is used
Each of the 7 bitplane decoding methods take a bitplane structure and the frame width and height expressed in macroblocks, as well as the invert bit decoded in this function. The bitplane decoders use their respective algorithms to decode a map of flags, one per macroblock. If the invert bit is set, each flag is inverted during the bitplane decode operation.
vc1DECBITPL_ReadBitplaneBit
This function returns the next bit in a decoded bitplane data structure.
vc1DECBITPL_SkipBitplaneBit
This function skips the next bit in the decoded bitplane data structure.
vc1DECBLK_ApplyACPrediction
This function takes an 8x8 block of transform coefficients, an array of 7 AC coefficient predictors and a flag indicating the block type.
- if the block type is INTRA_TOP
- add 7 AC coefficients to the 7 top row coefficients of the 8x8 block without the first (left-top corner)
- if the block type is INTRA_LEFT
- add 7 AC coefficients to the 7 left column coefficients of the 8x8 block without the first (left-top corner)
vc1DECBLK_DecodeBlockLayer
This function unpacks and reconstructs a macroblock. The macroblock is read from the current position in the bitstream. VC-1 only allows YUV 4:2:0 so there are always 6 blocks in a macroblock.
- foreach block (Y0, Y1, Y2, Y3, U(Cr), V(Cb)) in a macroblock
- if the macroblock is not skipped
- if the block is intra-coded
- else
- if the macroblock is not skipped
- vc1INTERP_PredictMB
- vc1RECON_ReconstructMB
vc1DECBLK_UnpackDCDifferential
This function unpacks from the encoded bitstream the DC transform coefficient differential value for an intra-coded block.
- select one of 4 VLC tables (see VC-1 Tables) based on
- block is a Y or C block
- picture parameters specify intra transform DC (high/low motion)
- decode DC differential as a VLC from the bitstream using that table
- if the DC differential is not 0
- if the DC differential value is the escape code
- if the current macroblock quantizer is
- 1: DC differential = next 10 bits in bitstream
- 2: DC differential = next 9 bits in bitstream
- else DC differential = next 8 bits in bitstream
- if the current macroblock quantizer is
- else
- if the current macroblock quantizer is
- 1: value = next 2 bits in bitstream; DC differential = DC differential * 4 + value - 3
- 2: value = next bit in bitstream; DC differential = DC differential * 2 + value - 1
- if the current macroblock quantizer is
- 1 bit: sign
- if the sign bit is set
- negate the DC differential
- if the DC differential value is the escape code
vc1DECBLK_UnpackInterBlock
This function unpacks the coefficients of an inter-coded 8x8 block using the following algorithm:
- set all 64 elements in a coefficient array to 0
- if the block is marked as coded, per its data structure
- declare a temporary 64-element array and set to 0
- if the block is marked as inter-coded 8x8
- mark the entire 8x8 block as being coded
- else if the block is inter-coded 4x8 or 8x4
- if (the block number in the macroblock is greater than the number of the first coded block in the MB) or (the frame transform type in the picture parameters data structure is the same as the block coding type -- either 4x8 or 8x4 in this conditional)
- else if the block is inter-coded 4x4
- else if the block is marked as "any" (as yet undetermined)
- vc1DECBLK_UnpackTTBLK
- if block is marked as inter-coded 4x4
- vc1DEC3DH_DecodeACRunLevel
- vc1DECZZ_DeZigZagBlock
vc1DECBLK_UnpackIntraBlock
This function decodes an intra-coded block in a macroblock.
- zero out the 64-element coefficient array
- if (macroblock enables overlap filter) or (frame is not intra-coded) or (profile is advanced)
- vc1PREDDCAC_DCDefault with a bias of 128
- else
- vc1PREDDCAC_DCDefault with a bias of 0
- block_type = vc1PREDDCAC_PredictDCAC in pred[] array
- set block's block_type = block_type
- vc1DECBLK_UnpackDCDifferential in dc_differential
- if block is marked as coded
- set block's NZC = 1
- vc1DEC3DH_DecodeACRunLevel
- vc1DECZZ_DeZigZagBlock
- else
- set block's NZC = 0
- if macroblock's ACPRED is enabled
- set DC coefficient coeff[0] = pred[0] + dc_differential
- vc1PREDDCAC_CopyDCAC
vc1DECBLK_UnpackSubBlockPattern
This function applies to inter-coded blocks that are coded as 2 8x4 sub-blocks, 2 4x8 sub-blocks, or 4 4x4 sub-blocks. This function unpacks the sub-block coding pattern for a particular 8x8 block. This entails reading a VLC out of the bitstream. The VLC table used depends on whether the picture parameters list the PQuant value as being between 1..4, 5..12, or 13..31. See VC-1 Tables. The meaning of the decoded VLC values varies depending the block type. In the case of an 8x4 or 4x8 inter-coded block, the VLC block with be 0, 1, or 2:
- 0: both sub-blocks are coded
- 1: bottom 8x4 or right 4x8 sub-block is coded
- 2: top 8x4 or left 4x8 sub-block is coded
If the block type is inter-coded 4x4 sub-blocks then the VLC is a 4-bit value indicating which of the 4 sub-blocks is coded. The bits (3..0) correspond to the following sub-blocks:
3 | 2 |
1 | 0 |
A bit value of 1 indicates that the sub-block is coded.
vc1DECBLK_UnpackTTBLK
This function unpacks the block transform type for a particular 8x8 block. This entails reading a VLC out of the bitstream. The VLC table used depends on whether the picture parameters list the PQuant value as being between 1..4, 5..12, or 13..31. See VC-1 Tables. The possible VLC values are in the range 0..7 and correspond to the first 8 entries of the Sub-block Patterns enumeration.
vc1DECMB_AssignCodedBlockPattern
In the SRD, this function assigns the individual bits of the coded block pattern to 6 constituent blocks of a macroblock.
vc1DECMB_DecodeTransformInfo
- if variable size transforms are in use, per the decoding state's sequence parameters data structure
- if (the picture parameters data structure's macroblock transform type flag is false) and (the macroblock is not intra-coded)
- else
- foreach of the 6 constituent blocks in the macroblock
- if entire macroblock is intra-coded
- set the block's coding type to intra-coded, no AC prediction
- else
- if the block is not already set to intra-coded
- set the block coding type to be the same as the picture parameter's frame transform type
- if the block is not already set to intra-coded
- if entire macroblock is intra-coded
- foreach of the 6 constituent blocks in the macroblock
- else
- the macroblock's block type inherits the picture parameter's frame transform type, which had better be 8x8 inter-coded (0 according to the block types enumeration)
vc1DECMB_UnpackMacroblockFieldB
vc1DECMB_UnpackMacroblockFieldP
vc1DECMB_UnpackMacroblockFrameB
vc1DECMB_UnpackMacroblockFrameP
vc1DECMB_UnpackMacroblockI
- if the picture format is interlaced
- read the next bit from the field TX bitplane
- if the bit is 1
- set the macroblock properties to include the field transform property
- decode a CBP VLC from the I-frame CBP VLC table (see VC-1 Tables)
- call vc1PREDCBP_ApplyCBPCYPred to compute the actual CBP
- if profile is advanced
- read the next bit from the AC prediction bitplane
- else
- 1 bit: AC prediction
- the read bit indicates whether AC prediction is enabled for the macroblock
- read the next bit from the overlap flags bitplane
- the read bit indicates whether the overlap filter is enabled for this macroblock
- if (the profile is advanced) and (DQuantFrame is true, according to the picture parameters)
- set all 6 of the macroblock's constituent blocks as intra-coded
vc1DECMB_UnpackMacroblockLayer
- initialize the following variables in the macroblock's state structure:
- set that quantizer the same as the picture-level quantizer
- set the quantizer half-step the same as the picture-level quantizer half-step
- set the overlap filter the same as the picture-level overlap filter
- set the macroblock skip flag to false
- set the block type the same as the picture-level transform type
- set the CBP vector to 0
- set the AC prediction mode to off
- call vc1IQUANT_ChooseQuantizer
- foreach of the 6 constituent blocks of the macroblock
- initialize block's coded status to 0
- initialize all motion vector components to 0
- initialize the macroblock's uniform vs. non-uniform quantizer to the same as the picture-level state
- if picture type is I or BI
- if picture type is P
- if picture format is progessive
- else if picture format is interlaced
- else
- if picture type is B
- if picture format is progessive
- else if picture format is interlaced
- else
- call vc1DECMB_AssignCodedBlockPattern
- if picture type is B
- force overlap filter to false as there is no overlap filter in B pictures
- call vc1DECBLK_DecodeBlockLayer
(SRD contains a bunch of debug statements here for when the MB is to be skipped)
vc1DECMB_UnpackMacroblockProgB
This function unpacks a progressive B-frame macroblock.
- set the macroblock's properties to include 1 motion vector and forward prediction, respectively
- read the next bit from the B-frame direct mode bitplane
- if the bit is true then set the macroblock's properties to include 1 motion vector and direct prediction
- read the next bit from the macroblock skip bitplane and set the skipped flag in the macroblock data structure accordingly
- if the macroblock does not use direct prediction
- if the macroblock is not to be skipped
- else
- foreach of the 4 Y blocks in the macroblock
- set the block's type to inter-coded 8x8
- foreach of the 4 Y blocks in the macroblock
- if the block 0 (first Y block) is intra-coded
- assume the entire MB is intra-coded and set he MB's type as such
- if (the macroblock is skipped) or (block 0 is inter-coded)
B-fraction processing (UNFINISHED)
- else
- foreach of the 4 Y blocks in the macroblock
- set the block type to be the same as the picture-level frame transform type
- foreach of the 4 Y blocks in the macroblock
(UNFINISHED)
vc1DECMB_UnpackMacroblockProgP
This function unpacks a progressive P-frame macroblock.
- set the macroblock's type to the default properties of 1 motion vector, forward prediction
- if the current position's motion vector mode is mixed
- read the next bit from the motion vector bitplane
- if the motion vector bit is 1
- set the macroblock's properties to 4 motion vectors, forward prediction
- read the next bit from the macroblock skip bitplane
- if the bit is 1
- vc1DECMB_UnpackMacroblockProgPSkipped
- make a note in the position data structure that the current macroblock was skipped
- else
- if the macroblock properties include 1 motion vector coding
- else if the macroblock properties include 4 motion vector coding
- else
- progressive P-frame macroblock had neither 1- nor 4-motion vector coding mode; fatal error
vc1DECMB_UnpackMacroblockProgP1MV
This function unpacks the macroblock data for a progressive P-frame macroblock with 1 motion vector.
- call vc1DECMV_UnpackMVData to unpack the motion vector data into the macroblock data structure
- if block 0 (first Y block) is intra-coded
- in the macroblock's data structure, set the macroblock type and the block coding type both as intra-coded
- if the macroblock is inter-coded
- peek the next bit (might be the hybrid prediction bit)
- call vc1PREDMV_PredictProgressiveMV with that bit
- if the previous function call returns true, the prediction used the hybrid bit, so discard 1 bit from the bitstream
- vc1DECMV_ApplyMVPrediction
- vc1DERIVEMV_DecideChromaBlockType
- if (macroblock is intra-coded) and (block 0 is not coded at all)
- if the picture parameter's DQuantFrame flag is true
- 1 bit: macroblock AC prediction flag
- macroblock CBP = 0
- else if block 0 is coded
- if macroblock is intra-coded
- 1 bit: macroblock AC prediction flag
- read macroblock CBP from appropriate VLC table (selected earlier and stored in the picture parameters); see VC-1 Tables
- if the picture parameter's DQuantFrame flag is true
- SRD has some accounting at this point with this upshot: if this first block is marked as coded and the MB has CBP, even if CBP is 0, macroblock transform type still needs to be decoded
- vc1DECMB_DecodeTransformInfo
- else
- macroblock's CBP = 0
vc1DECMB_UnpackMacroblockProgP4MV
This function unpacks the macroblock data for a progressive P-frame macroblock with 4 motion vectors.
- read macroblock CBP from appropriate VLC table (selected earlier and stored in the picture parameters); see VC-1 Tables
- foreach of the 4 Y blocks in the macroblock
- if the block is coded according the macroblock CBP
- else
- block's transform type is set to be the same as the picture parameter's frame transform type
- block's coded status is set to false
- block's index 0 motion vector is set to 0
- if the macroblock is inter-coded
- peek the next bit (might be the hybrid prediction bit)
- call vc1PREDMV_PredictProgressiveMV with that bit
- if the previous function call returns true, the prediction used the hybrid bit, so discard 1 bit from the bitstream
- vc1DECMV_ApplyMVPrediction
- else
- AnyIntra = 1
- vc1DERIVEMV_DecideChromaBlockType
- if picture parameter's DQuantFrame
- if (AnyIntra) or (Macroblock's CBP is not 0)
- if AnyIntra
- vc1PREDDCAC_ACPREDPresent
- if previous call returns true
- 1 bit: macroblock AC prediction on/off (1 = on
- else
- macroblock's AC prediction is turned off
- vc1DECMB_DecodeTransformInfo
vc1DECMB_UnpackMacroblockProgPSkipped
This function unpacks a skipped macroblock in a progressive P-frame, which sounds like an odd thing to do. Primarily, this function updates block and macroblock accounting information which needs to be maintained even for skipped macroblocks.
- macroblock CBP = 0
- foreach of the 4 Y blocks in the macroblock
- set the index 0 differential motion vectors to 0
- if macroblock type is 4 motion vectors
- foreach of the 4 Y blocks in the macroblock
- peek the next bit (might be the hybrid prediction bit)
- call vc1PREDMV_PredictProgressiveMV with that bit
- if the previous function call returns true, the prediction used the hybrid bit, so discard 1 bit from the bitstream
- vc1DECMV_ApplyMVPrediction
- block type is set to inter-coded 8x8
- foreach of the 4 Y blocks in the macroblock
- else
- peek the next bit (might be the hybrid prediction bit)
- call vc1PREDMV_PredictProgressiveMV with that bit
- if the previous function call returns true, the prediction used the hybrid bit, so discard 1 bit from the bitstream
- vc1DECMV_ApplyMVPrediction
- foreach of the 4 Y blocks in the macroblock
- block type is set to inter-coded 8x8
- vc1DERIVEMV_DecideChromaBlockType
vc1DECMB_UnpackMBQuantParams
This function unpacks from the bitstream the quantization parameters pertaining to a specific macroblock.
- if the picture parameters data structure contains a quantization mode indicating that PQuant & AltPQuant are selected on a per-MB basis
- quantizer selector: 1 bit
- if selector is 1
- macroblock-level quantizer is the alternate picture-level quantizer
- macroblock-level quantizer half-step is 0
- else
- macroblock-level quantizer is the picture-level quantizer
- (SRD does not do anything about the MB-level quantizer half-step here)
- else if picture parameters data structure contains a quantization mode indicating that the quantizer is decoded per macroblock
- macroblock quantizer half-step = 0
- macroblock quantizer delta: 3 bits
- if delta is 7
- macroblock quantizer: 5 bits
- else
- macroblock quantizer = picture-level quantizer + delta
vc1DECMB_UnpackTTMB
This function determines how the macroblock will be transformed. This applies to macroblocks that have at least 1 inter-coded block.
- find the first of the 6 blocks in the MB that is inter-coded (order: Y0, Y1, Y2, Y3, U, V)
- if all 6 of the MB's constituent blocks are intra-coded
- return
- select a macroblock transform type VLC table depending on whether the picture-level quantizer is in the range 1..4, 5..12, or 13..31. See VC-1 Tables
- read the sub-block pattern (SBP) VLC from the bitstream (decoded value corresponds to Sub-block Patterns enumeration)
- if the SBP pertains to only 1 block (vs. all inter-coded blocks in macroblock)
- mark the block type within the macroblock data structure as an inter-coded, transform type not yet determined (block type 4 in Block Types enumeration)
- signal to the master decoding state data structure which block is the first coded
- for the first inter-coded block, set the sub-block coding information depending on the SBP
- if the SBP indicated that the SBP applies to all inter-coded blocks in this macroblock
- replicate the sub-block coding information from the first inter-coded block to the other inter-coded blocks in the macroblock
- else
- foreach of the remaining inter-coded SBPs in the macroblock
- set the block type to indicate inter-coded, transform type not yet determined (4 in the enumeration) and the information will be decoded later
- foreach of the remaining inter-coded SBPs in the macroblock
vc1DECMV_ApplyMVPrediction
vc1DECMV_UnpackMVData
vc1DECMV_UnpackMVDataInterlace
vc1DECPIC_DisplayField
vc1DECPIC_DisplayPicture
vc1DECPIC_InitialiseAppPicture
vc1DECPIC_ReadAdvancedPictureLayer
vc1DECPIC_ReadPictureLayer
- if profile is advanced
- if picture is interlaced (pState->sSeqParams.Interlace = true)
- 1 bit: FCM_1
- if (FCM_1 != 0)
- 1 bit: FCM_2
- if (FCM_2 is 1)
- field count = 2
- picture format is interlaced (pPosition->ePictureFormat = true)
- call vc1DECPIC_SetDimensionsInMB
- if picture format is interlaced
- validate that the number of macroblocks is allowed under the current profile
- call vc1DECPIC_UnpackPictureLayerAdvanced
- if picture is interlaced (pState->sSeqParams.Interlace = true)
- else
vc1DECPIC_SetDimensionsInMB
This function performs frame size accounting.
- if the profile is either simple or main
- if the picture resolution is configured to be doubled horizontally
- divide the coded width by 2
- if the picture resolution is configured to be doubled vertically
- divide the coded height by 2
- if the picture resolution is configured to be doubled horizontally
- if the picture format specifies interlaced fields
- divide coded height by 2
- width in MB = coded width / 16, rounded up to the nearest MB boundary (MBwidth = (codedwidth + 15) / 16)
- height in MB = coded height / 16, rounded up to the nearest MB boundary (MBheight = (codedheight + 15) / 16)
- frame size in MB = MBwidth * MBheight
vc1DECPIC_UnpackFieldPictureLayer
- if picture format is not progressive
- Position.bottomfieldflag = Position.Position.secondfieldflag
- if PictureParams.TopFieldFirst is false
- Position.bottomfieldflag = 1 - Position.secondfieldflag
- Position.picturetype = PictureParams.PictureType[Position.secondfieldflag]
- if profile is advanced
- BitPlaneCodingUsed = false
- vc1DECPIC_ReadAdvancedPictureLayer
- ZigZagTableIndex = vc1GENTAB_ChooseZigZagTableSet
- PictureParams.Interpolate.Size[X|Y] = 8
- if (picture type is I- or P-frame) or (picture type is "skipped")
- ...
- else
- ...
(UNFINISHED)
vc1DECPIC_UnpackFieldPictureLayerIAdvanced
vc1DECPIC_UnpackFieldPictureLayerPBAdvanced
vc1DECPIC_UnpackInterlaceMVModeParams
vc1DECPIC_UnpackPanScanParams
vc1DECPIC_UnpackPictureLayer
- call vc1DECPIC_ReadPictureLayer
- foreach field in the picture
vc1DECPIC_UnpackPictureLayerAdvanced
vc1DECPIC_UnpackPictureLayerSimpleMain
- if there are 8 or fewer bits remaining in the encoded bitstream, skip this picture (unchanged from the previous frame); disregard the remaining bits in the bitstream
- initialize "bitplane coding used" to false
- if frame interpolation flag is true
- 1 bit: frame smoothness interpolation hint
- else
- frame smoothness interpolation hint is set to false
- if profile is simple or main
- 2 bits: frame count (SRD indicates that this is not used by decoder)
- if range reduction flag is set
- 1 bit: range reduction (0 indicates scale value of 8, 1 indicates 16)
- RangeYScale = RangeUVScale = scale value
- else
- RangeYScale = RangeUVScale = 8
- 1 bit: frame type bit 1
- if frame type bit 1 is 1
- frame type is P-frame
- else
- if "max B-frames" is 0
- frame type is I-frame
- else
- 1 bit: frame type bit 2
- if frame type bit 2 is 0
- frame type is B-frame
- else
- frame type is I-frame
- if "max B-frames" is 0
- if frame type is B-frame
- "B fraction processing":
- VLC: B fraction VLC
- The decoded B fraction value indexes into a table that yields a numerator and denominator
- if the denominator is 0
- if the numerator is 1
- invalid B fraction
- if the numerator is 2
- frame type is BI-frame
- (note: SRD makes no provisions for other special cases when denominator is 0)
- if the numerator is 1
- if frame type is I- or BI-frame
- 7 bits: buffer fullness field
- vc1DECPIC_UnpackQuantizationParams
- if (extended motion vectors)
- VLC: motion vector range VLC
- else
- motion vector range is range #0 (see VC-1 Tables)
- if frame type is I- or O-frame
- if MultiResCoding is true
- 2 bits: progressive resolution picture index (see VC-1 Tables: Scaling Modes)
- if frame type is P-frame
- the decoded index needs to match that of the corresponding I-frame
- else progressive resolution picture mode = 1x1 (no scaling)
- if MultiResCoding is true
- at this point, enough information is known to determine image size in MBs; call vc1DECPIC_SetDimensionsInMB
- if frame type is P-frame
- if PictureLayerParams.PQuant > 12
- VLC: P-frame low rate motion vector mode
- else
- VLC: P-frame high rate motion vector mode
- if decoded VLC indicates indicated IC mode
- if profile is simple
- fatal error: IC not allowed in simple profile
- PictureLayerParams.IC[0].icflag = true
- if PictureLayerParams.PQuant > 12
- VLC: P-frame low rate motion vector mode
- else
- VLC: P-frame high rate motion vector mode
- 6 bits: luminance scale value (assign to PictureLayerParams.IC[0].LuminanceScale)
- 6 bits: luminance shift value (assign to PictureLayerParams.IC[0].LuminanceShift)
- if profile is simple
- else
- PictureLayerParams.IC[0].icflag = false
- if PictureLayerParams.PQuant > 12
- else if frame type is B-frame
- determine motion vector type for B-frame:
- if next bit is 0
- frame uses 1 MV/MB, half-pel grid, bilinear filtered
- else
- frame uses 1 MV/MB, full-pel grid
- PictureLayerParams.IC[0].icflag = false
- if frame type is P- or B-frame
- if motion vector mode is mixed mode (3)
- decode motion vector type bitplane by calling vc1DECBITPL_ReadBitplane
- if motion vector mode is mixed mode (3)
- if frame type is B-frame
- decode B-frame direct macroblock bitplane by calling vc1DECBITPL_ReadBitplane
- if (frame type is P- or B-frame
- decode macroblock skip bitplane by calling vc1DECBITPL_ReadBitplane
- 2 bits: which motion vector diff VLC table to use
- 2 bits: which CBP table to use
- vc1DECPIC_UnpackVOPDQUANTParams
- if SequenceParameters.VSTransform
- if next bit is 1
- 2 bits: frame-level block transform type (see VC-1 Tables, block transform types)
- else
- no frame-level block transform type
- if next bit is 1
- else
- block transform type for entire frame = 8x8
- decode frame level transform AC coding set index based on next 1-2 bits:
- 0 = 0
- 10 = 1
- 11 = 2
- if frame type is I- or BI-frame, decode frame level transform AC coding set index #2 based on next 1-2 bits:
- 0 = 0
- 10 = 1
- 11 = 2
- 1 bit: which intra transform DC table to use
- PictureParams.ConditionalOverlap = 1 (indicate that all MBs overlap smooth)
- if (frame type is B-frame) or (PictureParams.PQuant < 9) or (overlapped transform flag is false)
- PictureParams.ConditionalOverlap = 0 (indicate that no MBs overlap smooth)
vc1DECPIC_UnpackQuantizationParams
- 5 bits: picture quantizer (PQ) index
- if SequenceParameters.eQuantizer != 1 (1 indicates quantizer is explicity signaled)
- if PQ index is 0
- invalid PQ index (0 is reserved or forbidden)
- vc1IQUANT_GetQuantizer
- store the quantizer returned from the previous step's call in the Params data structure
- save the information of whether the decoded quantizer is uniform or non-uniform
- if PQ index is 0
- else
- The quantizer is explicit, and signaled on a per frame basis (vs. a per layer basis?)
- initialize half QP step = 0
- if PQ index >= 8
- 1 bit: half QP step (needs to be copied into each MB struct later)
- if quantizer is explicit
- 1 bit: picture quantizer type
- if picture quantizer type is 0
- set Params.Quantizer as non-uniform
- vc1IQUANT_GetQuantizer, save quantizer
- else
- set Params.Quantizer as uniform
- vc1IQUANT_GetQuantizer, save quantizer
vc1DECPIC_UnpackSyncmarker
This function unpacks a sync marker but discards the payload data.
- 24 bits: first part of sync marker
- if sync marker is 0x0000AA
- 5-byte sync marker; read and discard next 5 bytes
- else if sync marker is 0x0000AB
- 11-byte sync marker, read and discard next 11 bytes
- else
- unknown sync marker; fatal error
vc1DECPIC_UnpackVOPDQUANTParams
- if SequenceLayerParams.DQuant is either 1 or 3
- 1 bit: MB quantization frame value
- if value is 1
- 2 bits: MB quantization profile
- if profile is 0
- quantization mode is: MB quantisation selection on all four edges; Edge macroblocks use ALTPQUANT
- else if profile is 1
- MB quantisation selection on pair of edges
- 2 bits: which pair of edges:
- 0: Left/Top macroblocks use ALTPQUANT
- 1: Top/Right macroblocks use ALTPQUANT
- 2: Right/Bottom macroblocks use ALTPQUANT
- 3: Bottom/Left macroblocks use ALTPQUANT
- else if profile is 2
- MB quantisation selection on single edges
- 2 bits: which edge:
- 0: Left macroblocks use ALTPQUANT
- 1: Top macroblocks use ALTPQUANT
- 2: Right macroblocks use ALTPQUANT
- 3: Bottom macroblocks use ALTPQUANT
- else if profile is 3
- Macroblock quantization bi-level
- 1 bit: value
- if value is 0
- quantization mode is: Any QUANT selected on a macroblock basis
- else
- PQUANT/ALTPQUANT selected on macroblock basis
- else
- quantization mode is: default (all MBs use PQUANT)
- else if SequenceLayerParams.DQuant is 2
- quantization mode is: Edge macroblocks use ALTPQUANT
- if SequenceLayerParams.DQuant is 1, 2, or 3
- decode pquant value
- if quantizer mode is "Any QUANT selected on a macroblock basis" or "All macroblocks use PQUANT"
- 3 bits: value (PQuant differential or escape code)
- if value != 7
- altpquant = pquant + value + 1
- else
- 5 bits: altpquant
- else
- altpquant = 0
- quantizer mode is: All macroblocks use PQUANT
vc1DECSEQ_UnpackSequenceLayer
This function unpacks the sequence layer:
- 2 bits: profile
- if (profile is simple or main (0 or 1))
- 2 bits: reserved, should be 0
- if (profile is advanced (3))
- 3 bits: level of advanced profile (values 5-7 are invalid)
- 2 bits: chroma format (note that only format 1, YUV 4:2:0 is defined)
- 3 bits: QFrameRateForPostProc ("see standard", SRD does not use)
- 5 bits: QBitRateForPostProc ("see standard", SRD does not use)
- if (profile is simple or main)
- 1 bit: loop filter flag
- 1 bit: reserved, should be 0
- 1 bit: multiresolution coding flag
- 1 bit: reserved, should be 1, SRD calls it "RES_FASTTX"
- 1 bit: fast U/V motion compensation (note: must be 1 in simple profile)
- 1 bit: extended motion vectors (note: must be 0 in simple profile)
- 2 bits: macroblock dequantization
- 1 bit: variable sized transform
- 1 bit: reserved, should be 0, SRD calls it "RES_TRANSTAB"
- 1 bit: overlapped transform flag
- 1 bit: sync marker flag
- 1 bit: range reduction flag
- 3 bits: maximum number of consecutive B frames
- 2 bits: quantizer
- if (profile is advanced)
- 1 bit: post processing flag
- 12 bits: max coded width (actual width = (width + 1) * 2)
- 12 bits: max coded height (actual height = (height + 1) * 2)
- 1 bit: pulldown flag
- 1 bit: interlaced
- 1 bit: frame counter flag
- 1 bit: frame interpolation flag
- if (profile is advanced)
- (UNFINISHED: lots more stuff to be filled in when advanced profile is needed)
- if (profile is simple or main)
- 1 bit: reserved, should be 1, SRD calls it "RES_RTM_FLAG"
vc1DECSLICE_DecodeSlice
vc1DECZZ_DeZigZag
This function takes pointers to before and after buffers for the de-zigzag operation, the width and height of the block to be operated on, and a pointer to a scan table. There is a total of 31 separate scan tables. See VC-1 Zigzag Tables for the specific tables.
vc1DECZZ_DeZigZagBlock
This function de-zigzags an entire 8x8 block by calling vc1DECZZ_DeZigZag on either the whole 8x8 block, 2 8x4 sub-blocks, 2 4x8 sub-blocks, or 4 4x4 sub-blocks, depending on how the block is coded.
vc1DERIVEMV_DecideChromaBlockType
vc1DERIVEMV_DeriveChromaMV
vc1DERIVEMV_DeriveIntFieldMV
vc1DERIVEMV_DeriveIntFrameDirectMV
vc1DERIVEMV_DeriveMV
vc1DERIVEMV_DeriveProgMV
vc1DERIVEMV_DeriveSecondStageChromaMV
vc1DERIVEMV_DirectMV
vc1DERIVEMV_FillInInterlaceFieldMV
vc1DERIVEMV_StoreMotionVectors
vc1GENTAB_ChooseZigZagTableSet
Choose from among 5 different zigzag table sets depending on profile and interlacing:
- if (picture format is interlaced frame)
- choose set 4
- if (picture is intra)
- choose set 0
- else
- if (profile is simple or main)
- choose set 1
- else
- if (picture format is progressive)
- choose set 2
- else
- choose set 3
- if (picture format is progressive)
- if (profile is simple or main)
vc1INTERP_AverageBlocks
This function takes pointers to 2 64-element byte arrays and averages them into a third 64-element byte array. The averaging weights up:
average = (a + b + 1) / 2
vc1INTERP_CopyPatch
This function is called when there is no need to do any inter-pixel interpolation because the X and Y coordinates line up on the fractional pel grid.
vc1INTERP_InterlaceDiffMB
vc1INTERP_InterlacePredMB
vc1INTERP_InterpolateBlock
vc1INTERP_InterpPatchHalfPelBicubic
This function takes X and Y coordinates in half-pel coordinate. It calls vc1INTERP_InterpPatchQuarterPelBicubic after multiplying each coordinate by 2.
vc1INTERP_InterpPatchHalfPelBilinear
This function takes X and Y coordinates in half-pel coordinate. It calls vc1INTERP_InterpPatchQuarterPelBilinear after multiplying each coordinate by 2.
vc1INTERP_InterpPatchQuarterPelBicubic
This function takes X and Y coordinates in quarter pel coordinates.
- if X and Y are both divisible by 4
- else if X is divisible by 4
- else if Y is divisible by 4
- else
vc1INTERP_InterpPatchQuarterPelBicubicDiag
vc1INTERP_InterpPatchQuarterPelBicubicHoriz
This function takes a pointer to a plane of byte samples and the quarter-pel coordinates of a rectangle to interpolate and returns a rectangle of interpolated samples. This function is used for the case when the X quarter-pel coordinate is not divisible by 4 but the Y quarter-pel coordinate is. Further, this function also accepts a flag governing whether the interpolated values should be rounded to the nearest number or always rounded down.
This is the precise interpolation algorithm:
- derive the full-pel X and Y coordinates of the rectangle by dividing the quarter-pel coordinates by 4 (shift right by 2 for proper accuracy)
- foreach rectangle row (Y) as specified by the rectangle height
- foreach pixel in the row (X) as specified by the rectangle width:
- compute the interpolated pixel @ (X, Y) as:
- foreach pixel in the row (X) as specified by the rectangle width:
ROUND(a0p0 + a1p1 + a2p2 + a3p3) / divisor
where:
- p0 = sample @ (X - 1, Y)
- p1 = sample @ (X, Y)
- p2 = sample @ (X + 1, Y)
- p3 = sample @ (X + 2, Y)
- coefficients [a0...a3] depend on whether the quarter-pel X coordinate falls at the 1/4, 1/2, or 3/4 point between 2 pixels; see VC-1 Tables for the coefficients
- if the samples are to be rounded up ROUND() adds the quantity (divisor / 2 - 1) to the sum before division
- divisor is always a power of 2 so the sum can be shifted right by (log2divisor) for speed; the rounding portion of the previous step counts on this; see VC-1 Tables for the possible divisors
- the final sample is saturated to an unsigned byte range of 0..255
vc1INTERP_InterpPatchQuarterPelBicubicVert
This function takes a pointer to a plane of byte samples and the quarter-pel coordinates of a rectangle to interpolate and returns a rectangle of interpolated samples. This function is used for the case when the Y quarter-pel coordinate is not divisible by 4 but the X quarter-pel coordinate is. Further, this function also accepts a flag governing whether the interpolated values should be rounded to the nearest number or always rounded down.
This is the precise interpolation algorithm:
- derive the full-pel X and Y coordinates of the rectangle by dividing the quarter-pel coordinates by 4 (shift right by 2 for proper accuracy)
- foreach rectangle row (Y) as specified by the rectangle height
- foreach pixel in the row (X) as specified by the rectangle width:
- compute the interpolated pixel @ (X, Y) as:
- foreach pixel in the row (X) as specified by the rectangle width:
ROUND(a0p0 + a1p1 + a2p2 + a3p3) / divisor
where:
- p0 = sample @ (X, Y - 1)
- p1 = sample @ (X, Y)
- p2 = sample @ (X, Y + 1)
- p3 = sample @ (X, Y + 2)
- coefficients [a0...a3] depend on whether the quarter-pel Y coordinate falls at the 1/4, 1/2, or 3/4 point between 2 pixels; see VC-1 Tables for the coefficients
- if the samples are to be rounded up ROUND() adds the quantity (divisor / 2 - 1) to the sum before division
- divisor is always a power of 2 so the sum can be shifted right by (log2divisor) for speed; the rounding portion of the previous step counts on this; see VC-1 Tables for the possible divisors
- the final sample is saturated to an unsigned byte range of 0..255
vc1INTERP_InterpPatchQuarterPelBilinear
This function takes a pointer to a plane of byte samples and the quarter-pel coordinates of a rectangle to interpolate and returns a rectangle of interpolated samples. Further, this function accepts a flag governing whether the interpolated values should be rounded to the nearest number or always rounded down.
This is the precise interpolation algorithm:
- derive the full-pel X and Y coordinates of the rectangle by dividing the quarter-pel coordinates by 4 (shift right by 2 for proper accuracy)
- foreach rectangle row (Y) as specified by the rectangle height
- foreach pixel in the row (X) as specified by the rectangle width:
- compute the interpolated pixel @ (X, Y) as:
- foreach pixel in the row (X) as specified by the rectangle width:
ROUND(axayp0 + axbyp1 + bxayp2 + bxbyp3) / 16
where:
- p0 = sample @ (X, Y)
- p1 = sample @ (X + 1, Y)
- p2 = sample @ (X, Y + 1)
- p3 = sample @ (X + 1, Y + 2)
- the a and b coefficients are defined in VC-1 Tables; the x and y indices are the quarter-pel fractional coordinates of the rectangle, i.e.:
x = (x quarter-pel coordinate & 3) y = (y quarter-pel coordinate & 3)
- the ROUND() function adds 8 to the sum before division if rounding control flag indicates that the interpolation should round towards to the nearest number vs. always rounding down
- the division by 16 should be carried out as a bit shift right by 4 bits to maintain accuracy
vc1INTERP_PredictMB
- vc1DERIVEMV_StoreMotionVectors
- if macroblock is not intra-coded
- vc1DERIVEMV_DeriveMV
- foreach block in MB (Y0, Y1, Y2, Y3, U, V)
- if block is intra-coded
- iterate to next block
- switch = 0
- if this MB type is a switch MV
- if the block is either the U or V component
- switch = 1
- if the block is either the U or V component
- if the MB uses forward prediction
- call vc1INTERP_InterpolateBlock using the (switch) parameter
- else if the MV uses backward prediction
- call vc1INTERP_InterpolateBlock using the (switch) parameter inverted
- else
- block uses both forward and backward prediction
- call vc1INTERP_InterpolateBlock with a (switch) parameter of 0
- call vc1INTERP_InterpolateBlock with a (switch) parameter of 1
- call vc1INTERP_AverageBlocks to average the 2 interpolated blocks
- if block is intra-coded
vc1IQUANT_ChooseQuantizer
This function evaluates the position of the macroblock and the quantization mode and assigns the "alternate" quantizer as the macroblock quantizer if the macroblock meets the right boundary conditions. The quantization modes are enumerated in Macroblock Quantizer Step Sizes.
switch(quantizer mode):
- case 1: edge MBs use ALTPQUANT
- if macroblock touches any border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches any border
- case 2: left/top MBs use ALTPQUANT
- if macroblock touches the left or top border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches the left or top border
- case 3: top/right MBs use ALTPQUANT
- if macroblock touches the top or right border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches the top or right border
- case 4: right/bottom MBs use ALTPQUANT
- if macroblock touches the right or bottom border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches the right or bottom border
- case 5: bottom/left MBs use ALTPQUANT
- if macroblock touches the bottom or left border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches the bottom or left border
- case 6: left MBs use ALTPQUANT
- if macroblock touches the left border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches the left border
- case 7: top MBs use ALTPQUANT
- if macroblock touches the top border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches the top border
- case 8: right MBs use ALTPQUANT
- if macroblock touches the right border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches the right border
- case 9: bottom MBs use ALTPQUANT
- if macroblock touches the bottom border
- use alternate picture quantizer for this macroblock
- quantizer half step = 0
- if macroblock touches the bottom border
vc1IQUANT_GetQuantizer
This function takes a picture quantizer index and determines the picture quantizer and the non-uniformity based on the quantizer mode (as enumerated in Quantizer Modes).
- picture quantizer = picture quantizer index
- if quantizer mode is implicit
- if the picture quantizer index >= 9
- picture quantizer = NonUniformImplicit[index] (see VC-1 Tables)
- if the picture quantizer index >= 9
- if quantizer mode is non-uniform
- set quantizer data structure's non-uniform flag
vc1IQUANT_InverseACQuantize
This function takes a quantizer data structure and dequantizes a group of 63 or 64 coefficients. If the block is intra-coded the function will not operate on the DC coefficient; it will operate on the DC coefficient of an inter-coded block.
- mquant is the quantizer value in the quantizer data structure
- half step is the half step value in the quantizer data structure
- if the quantizer data structure indicates uniform quantization
- foreach AC coefficient to be dequantized
- if quantized AC coefficient is not 0
- dequantized AC coefficient = (quantized AC coefficient * (2 * mquant + half step))
- else
- dequantized AC coefficient is set to 0
- if quantized AC coefficient is not 0
- foreach AC coefficient to be dequantized
- else
- foreach AC coefficient to be dequantized
- if quantized AC coefficient is not 0
- dequantized AC coefficient = (quantized AC coefficient * (2 * mquant + half step))
- if (quantized AC coefficient * mquant) < 0
- decrement dequantized AC coefficient
- else
- increment dequantized AC coefficient
- else
- dequantized AC coefficient is set to 0
- if quantized AC coefficient is not 0
- foreach AC coefficient to be dequantized
vc1IQUANT_InverseDCQuantize
This function takes a quantized DC Coefficient and a quantizer data structure. It returns the dequantized DC coefficient.
- the quantizer is the quantizer specified in the quantizer data structure
- if the (1 > quantizer > 31)
- fatal error: invalid quantizer
- compute DC step size by calling vc1PREDDCAC_DCStepSize with quantizer
- return quantized DC coefficient * DC step size
vc1ITRANS_InverseTransform_AnnexA1
This function transforms a MxN block of samples. Learning from problems encountered in earlier coding methods, VC-1 specifies a bit-exact transform that will be outlined here. (This section could use a formal mathematical definition and some research regarding optimizations.)
VC-1 block sizes are 4x4, 4x8, 8x4, and 8x8. The transform takes 4 parameters: input[64], output[64], width, and height. For the transform matrices and constants, see VC-1 Tables-- Transform Tables
note: The SRD comments Equation: E = (M * T + 4) >> 3 in this function. This is incorrect. The correct equation is E = (D * T + 4) >> 3 as so it is defined and implemented.
- declare temp_matrix[64]
- if width is 8
- transform_matrix = transform_matrix_8x8
- else
- transform_matrix = transform_matrix_4x4
- row transform:
- foreach j in 0..height - 1
- foreach i in 0..width - 1
- accumulator = 0
- foreach k in 0..width - 1
- accumulator += input[j * 8 + k] * transform_matrix[k * width + i]
- temp_matrix[j * 8 + i] = (accumulator + 4) / 8
- foreach i in 0..width - 1
- if height is 8
- transform_matrix = transform_matrix_8x8
- else
- transform_matrix = transform_matrix_4x4
- if height is 8
- constants = constants_8
- else
- constants = constants_4
- column transform:
- foreach i in 0..width - 1
- foreach j in 0..height - 1
- accumulator = 0
- foreach k in 0..height - 1
- accumulator += temp_matrix[i + k * 8] * transform_matrix[k * height + j]
- output[i + j * 8] = (accumulator + constants[j] + 64) / 128
- foreach j in 0..height - 1
vc1ITRANS_InverseTransformBlock
This function takes a buffer of 64 transformed samples laid out as an 8x8 matrix.
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
If the block type is 8x8, the array is passed to vc1ITRANS_InverseTransform_AnnexA1 to be transformed. If the block type is 8x4 this function partitions the array into 2 halves and calls vc1ITRANS_InverseTransform_AnnexA1 twice.
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
The same goes for a 4x8 block size, except that the block to be transformed is split in half vertically:
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
Finally, the block type might be 4x4 which partitions the block and calls vc1ITRANS_InverseTransform_AnnexA1 4 times:
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X
vc1PRED_pB1MVBlk
vc1PRED_pB4MVBlk
vc1PRED_pLeftBlk
This is an SRD support function that returns a pointer to the data structure representing the block to the left of a specified block.
vc1PRED_pLeftMB
This is an SRD support function that returns a pointer to the data structure representing the macroblock to the left of a specified macroblock.
vc1PRED_pTopBlk
This is an SRD support function that returns a pointer to the data structure representing the block above a specified block.
vc1PREDCBP_ApplyCBPCYPred
This function takes the position of a macroblock in a frame as well as a vector of differential bits for the MB's coded block pattern (CBP). This differential vector shall be expressed as having components (DY0, DY1, DY2, DY3, DCb, DCr). This function evaluates which of the surrounding blocks are coded and predicts the current MB's CBP based on those blocks. The prediction only applies to the Y blocks. This is the arrangement of the relevant MBs with respect to the current MB:
top-left | top |
left | current |
The Y blocks of each MB can be expanded thusly:
LT0 | LT1 | T0 | T1 |
LT2 | LT3 | T2 | T3 |
L0 | L1 | Y0 | Y1 |
L2 | L3 | Y2 | Y3 |
Each of those 12 Y blocks in the top, left, and top-left MBs contains a bit specifying whether it is coded in this frame. Depending on where the current MB is in the frame, any of the 3 predicting MBs may not exist which makes all of their constituent coded bits 0. This is the algorithm for applying the predictors to find the actual CBP:
- if LT3 == T2
- Y0 = L1 XOR DY0
- else
- Y0 = T2 XOR DY0
- if T2 == T3
- Y1 = Y0 XOR DY1
- else
- Y1 = T3 XOR DY1
- if L1 == Y0
- Y2 = L3 XOR DY2
- else
- Y2 = Y0 XOR DY2
- if Y0 == Y1
- Y3 = Y2 XOR DY3
- else
- Y3 = Y1 XOR DY3
vc1PREDDCAC_ACPREDPresent
This function decides if AC prediction is enabled for a particular macroblock. It returns TRUE if prediction is to be used and FALSE if not.
- if macroblock is intracoded
- return TRUE
- if macroblock is not coded with 4MV
- return FALSE
- foreach of the 6 constituent blocks in the macroblock
- if the block type is intra-coded
- if the block above exists and is intra-coded
- return TRUE
- if the block to the left exists and is intra-coded
- return TRUE
- if the block above exists and is intra-coded
- if the block type is intra-coded
- return FALSE
vc1PREDDCAC_CopyDCAC
This function copies the DC coefficient, along with the top 7 and left 7 AC coefficients of an 8x8 intra-coded transformed block into data structures established by the SRD. These will be used for prediction at a later step.
vc1PREDDCAC_DCDefault
Compute a block's default DC predictor. The function takes a quantizer for the entire MB and a bias (either 0 or 128). The default is expected to be round(8*(128-Bias)/DCStepSize).
- if bias is 128
- return 0
- dc_step_size = vc1PREDDCAC_DCStepSize(quantizer)
- return ((1024 + (dc_step_size >> 1)) / dc_step_size)
vc1PREDDCAC_DCStepSize
This function takes a quantization step size and returns a calculated DC step size. This function only applies towards 8x8 intra-coded blocks.
- if (quantizer < 4)
- return (1 << quantizer)
- else
- return (quantizer / 2) + 6
vc1PREDDCAC_GetQuant
Based on a the quantizer and half step values found in a macroblock's data structure, this function expressions the quantizer in the form:
2 * quantizer + half step
vc1PREDDCAC_PredictDCAC
This function predicts the DC and AC coefficients for a block based on the surrounding blocks that have already been decoded.
This function takes a block number within a particular macroblock, and a DC_default value which is defined as:
- rule A: 0
- rule B: ((1024 + (DCStepSize>>1)) / DCStepSize)
It also takes an array of 8 prediction values. The first value is for the predicted DC coefficient and the remaining 7 values are for AC coefficients.
This is the arrangement of the relevant MBs with respect to the current MB:
top-left | top |
left | current |
The Y blocks of each MB can be expanded thusly:
LT0 | LT1 | T0 | T1 |
LT2 | LT3 | T2 | T3 |
L0 | L1 | Y0 | Y1 |
L2 | L3 | Y2 | Y3 |
Y0 predicts from blocks LT3, T2 and L1, if they exist (i.e., if the current macroblock is not on a frame boundary). Y1 predicts from blocks Y0 (always) and T2 and T3 if they exist. Y2 predicts from Y0 (always) and L1 and L3 if they exist. Y3 always predicts from Y0, Y1 and Y2.
For the 2 chrominance blocks (U and V): Each is predicted from the same component blocks from the top, left, and top-left macroblocks if those MBs exist.
- quantizer_current = quantizer_top = quantizer_left_top = quantizer_left = vc1PREDDCAC_GetQuant
- for this particular block, determine which of the surrounding blocks exist; if a surrounding block, call vc1PREDDCAC_GetQuant for its encapsulating macroblock and assign to the appropriate quantizer variable
- example: for a Y0 block, check if the block above exists; if it does, call vc1PREDDCAC_GetQuant for the macroblock above and assign the returned quantizer to quantizer_top
The next step is to decide prediction direction, either left, top, or none.
- if (top block exists) and (top block is intra-coded)
- DC_top = vc1PREDDCAC_ScaleDC(top.DC, quantizer_top, quantizer_current)
- if (left block exists) and (left block is intra-coded)
- DC_left_top = DC_default
- DC_left = vc1PREDDCAC_ScaleDC(left.DC, quantizer_left, quantizer_current)
- if top-left block is intra-coded
- DC_top_left = vc1PREDDCAC_ScaleDC(top_left.DC, quantizer_top_left, quantizer_current)
- D1 = abs(DC_top_left - DC_top)
- D2 = abs(DC_top_left - DC_left)
- if (D1 <= D2)
- prediction direction = left
- DC_predicted = DC_left
- else
- prediction direction = top
- DC_predicted = DC_top
- else
- prediction direction = top
- DC_predicted = DC_top
- if (profile is not advanced) && (picture type is intra-coded)
- if (DC_top == DC_default)
- prediction direction = none (comment: "I/BI pictures predict DC left if Top==Default. Therefore there is no AC prediction from as the left block is off the image. However, we use the left zig-zag table.)
- if (DC_top == DC_default)
- else
- if (left block exists) and (left block is intra-coded)
- prediction direction = left
- DC_predicted = vc1PREDDCAC_ScaleDC(left.DC, quantizer_left, quantizer_current)
- if (left block exists) and (left block is intra-coded)
- place DC_predicted in the first index in the 64-element predicted output (pred[0])
- if prediction direction is left
- if AC prediction is enabled for this macroblock
- scale = round(0x20000 / (quantizer_current - 1)) * (quantizer_left - 1)
- apply the scale to each of the left block's left AC coefficients and store them in the predicted array, indices 1..7:
- for i = 1..7
- pred[i] = ((left AC predictor #(i - 1)) * scale + 0x20000) >> 18
- for i = 1..7
- else
- prediction direction = none
- if AC prediction is enabled for this macroblock
- else if prediction direction is top
- if AC prediction is enabled for this macroblock
- scale = round(0x20000 / (quantizer_current - 1)) * (quantizer_top - 1)
- apply the scale to each of the top block's top AC coefficients and store them in the predicted array, indices 1..7:
- for i = 1..7
- pred[i] = ((top AC predictor #(i - 1)) * scale + 0x20000) >> 18
- for i = 1..7
- else
- prediction direction = none
- if AC prediction is enabled for this macroblock
- else if prediction direction is none
- if AC prediction is enabled for this macroblock
- for i = 1..7
- pred[i] = 0
- prediction direction = left (comment: "If AC prediction is zero but AC prediction is on, then prediction direction is left (affects the zig-zag table used)")
- for i = 1..7
- if picture format is interlaced
- prediction direction = none
- if AC prediction is enabled for this macroblock
- return prediction direction
(SIMD): 7 parallel multiplications and bit shifts
vc1PREDDCAC_ScaleDC
This function takes a DC coefficient, an old quantizer value and a new quantizer value. It scales the DC coefficient per the new quantizer value vs. the old value. Both quantizers are represented as (2 * quantizer + half-step).
- remove the half-step by shifting the old and new quantizer values right 1 bit
- if the new quantizer is not the same as the old quantizer
- new quantizer = vc1PREDDCAC_DCStepSize(new quantizer)
- old quantizer = vc1PREDDCAC_DCStepSize(old quantizer)
- DC value = (DC value * round(0x20000 / new quantizer) * old quantizer + 0x20000) >> 18
vc1PREDMV_FrameMBPred
vc1PREDMV_PredictInterlacedFieldMV
vc1PREDMV_PredictInterlacedFrameMV
vc1PREDMV_PredictProgressiveMV
vc1RECON_ApplyPredictionAndCopyMB
vc1RECON_ReconstructMB
vc1SCALEMV_InitScaleMV
vc1SCALEMV_ScaleMV
vc1SMOOTH_OverlapSmoothHorizBlk
vc1SMOOTH_OverlapSmoothHorizMB
vc1SMOOTH_OverlapSmoothMB
vc1SMOOTH_OverlapSmoothVertBlk
vc1TOOLS_CopyReference
This function copies an entire reference picture and all associated data structures to another. The reference source notes that it is to be used in the case of a skipped frame.
vc1TOOLS_GetPictureDestination
Provided a block number, this function returns a data structure with the information about that block.
vc1TOOLS_ICComponent
vc1TOOLS_ICPadReferencePicture
vc1TOOLS_InitImagePosition
vc1TOOLS_InitReferencePicture
vc1TOOLS_IntensityCompensate
vc1TOOLS_Median3
The Median3 function takes 3 numbers as input and returns the middle value of the 3.
vc1TOOLS_Median4
The Median4 function takes 4 numbers as input and returns the average between the middle 2 values of the set, weighted down. For 4 inputs, (a, b, c, d), find the minimum and maximum values of the set (min, max) and the median4 value is computed as:
(a + b + c + d - min - max) / 2
vc1TOOLS_NewReference
vc1TOOLS_PadComponent
vc1TOOLS_PadReferencePicture
vc1TOOLS_RangeExpand
This function takes a scale value and a pointer to a rectangle of byte values and performs the following operation on each byte in the rectangle:
byte = (((byte - 128) * scale + 4) / 8) + 128
The final arithmetic is saturated to an unsigned byte range (0..255).
vc1TOOLS_RangeReduce16
This function takes a pointer to a rectangle of byte values and performs the following operation on each byte:
byte = ((byte - 128) / 2) + 128
vc1TOOLS_RangeReduceReference
This function performs intensity compensation on a reference picture. It takes a reference picture data structure and a new range reduction value.
- for each of the planes, Y, U, and V:
- if range reduction value is 16 then
- call RangeReduce16 with the entire plane as the rectangle
- else
- call RangeReduce with the entire plane as the rectange and 16 as the scale value
- if range reduction value is 16 then
note: if 16 is always the scale value, then there is an optimization opportunity in RangeExpand()
vc1TOOLS_ResolutionUpsample
The reference decoder includes the upsampling filter but the exact implementation is not defined in the official spec.
(TODO: Fill in the reference decoder's algorithm anyway)
Miscellaneous Notes
Uncategorized notes from the original VC-1 page
This description assumes that the data to be decoded in WMV3 data coming in from a Microsoft ASF file. The video data should be packaged with "extradata" which is attached to the end of a BITMAPINFOHEADER structure and transported in the ASF file. The format of the extradata is as follows:
2 bits VC-1 Profile if (profile == 3) 3 bits Profile level 2 bits Chroma format (SRD does not care) 3 bits VC1_BITS_FRMRTQ_POSTPROC (? SRD does not care) 5 bits VC1_BITS_BITRTQ_POSTPROC (? SRD does not care) 1 bit VC1_BITS_POSTPROCFLAG (? SRD does not care) 12 bits Encoded width (actual width = (w + 1) * 2) 12 bits Encoded height (actual height = (h + 1) * 2)
There are 4 VC-1 profiles:
- 0 simple profile
- 1 main profile
- 2 reserved
- 3 advanced profile
If profile is advanced, the extradata carries a lot of setup information. For simple and main profiles, the relevant setup data is established outside of the decoder, e.g., the BITMAPINFOHEADER of a Microsoft ASF file. This information provides the width and height that the decoder uses to set up its state.
The decoder computes the macroblock width and height as the ceiling of each dimension divided by 16:
macroblock_width = (frame_width + 15) / 16 macroblock_height = (frame_height + 15) / 16
The total number of macroblocks in a frame is defined as:
total_macroblocks = macroblock_width * macroblock_height
If the level is marked as unknown during the initialization process, figure out what level the video belongs at. This is determined by the number of macroblocks in combination with the profile. The relevant table is vc1gentab.c:vc1GENTAB_LevelLimits[][]. The profile/level combination defines the following limits:
max macroblocks/second max macroblocks/frame max peak transmission rate in kbps max buffer size in multiples of 16 kbits motion vector range
The initializer then needs to compute how much space to allocate for each reference frame. The size of a frame determined by frame width and height, encoding profile, and interlacing. This size is used to allocate space for 4 different frames:
reference new (new/current I/P frame) reference old (old I/P reference frame) reference B (reconstructed B frame) reference NoIC (B reference before intensity compensation was applied)
Further, the initializer allocates space for 7 different bitplanes. Each bitplanes has 1 flag per each macroblock as enumerated by the max macroblocks per frame for the profile/level. The bitplanes are:
ACPRED SKIPMB MVTYPEMB DIRECTMB OVERFLAGS FORWARDMB FIELDTX
Allocate space for motion vector history. The number of entries in this array is macroblock_width * (macroblock_height + 1) (extra height is for interlaced field). Each entry is a motion vector history structure which contains the 4 Y block motion vectors for a particular macroblock. The individual motion vector structures are the same as in the intra structure which provides hybrid prediction, motion vectors, and diff MVs (again, 4 for each block?).
And that's it for the SRD "requirements gathering" process (vc1dec.c:vc1DEC_DecoderRequirements()). The function returns the number of bytes needed for the decoder's internal state. The client app is expected to allocate enough space for this state.
Finally, it is time to decode an actual frame (referred to as "unpacking the picture layer"). The decode process iterates through however many fields comprise the frame (1 or 2).
(unfinished) ... there is a lot more logic dealing with frame accounting; let's skip to the real meat: macroblock decoding! ...
Decode a macroblock:
set the macroblock overlap filter flag, coding type, quantizer and halfstep parameters to the same as the picture clear the skipped flag set the CBP to 0 (no coded blocks) choose the quantizer (long list of logic, see vc1iquant.c:vc1IQUANT_ChooseQuantizer()) for each of the 6 sub-blocks, set coded field to 0, clear down all MV data decide on non-uniform quantizer unpack an I or BI macroblock:
(unfinished)