Understanding VC-1

From MultimediaWiki
Jump to navigation Jump to search

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
  • 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
  • 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

vc1DEC3DH_ChooseEscapeMode3Table

This function selects a block escape mode VLC table based on certain members in the picture parameters data structure.

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)
    • advance to the next block in the coefficient buffer

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
  • 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

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.

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.

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
  • 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
  • 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

vc1DECBITPL_ReadBitplane

This function decodes a bitplane from an encoded VC-1 bitstream using 1 of a number of different methods.

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.

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
    • 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
    • 1 bit: sign
    • if the sign bit is set
      • negate the DC differential

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

vc1DECBLK_UnpackIntraBlock

This function decodes an intra-coded block in a macroblock.

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
  • 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

(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
    • 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

(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
  • else

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
  • vc1DERIVEMV_DecideChromaBlockType
  • if (macroblock is intra-coded) and (block 0 is not coded at all)
  • 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
    • else
      • AnyIntra = 1
  • vc1DERIVEMV_DecideChromaBlockType
  • if picture parameter's DQuantFrame
  • if AnyIntra
  • 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
  • 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

vc1DECMV_ApplyMVPrediction

vc1DECMV_UnpackMVData

vc1DECMV_UnpackMVDataInterlace

vc1DECPIC_DisplayField

vc1DECPIC_DisplayPicture

vc1DECPIC_InitialiseAppPicture

vc1DECPIC_ReadAdvancedPictureLayer

vc1DECPIC_ReadPictureLayer

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 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
  • 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

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 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 frame type is I- or BI-frame
    • 7 bits: buffer fullness field
  • vc1DECPIC_UnpackQuantizationParams
  • if (extended motion vectors)
    • VLC: motion vector range VLC
  • else
  • 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)
  • 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)
    • else
      • PictureLayerParams.IC[0].icflag = false
  • 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 frame type is B-frame
  • 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
    • 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
  • 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

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

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.

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:
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:
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:
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

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
  • 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
  • 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
  • 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
  • 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
  • case 6: left MBs use ALTPQUANT
    • if macroblock touches the left border
      • use alternate picture quantizer for this macroblock
      • quantizer half step = 0
  • case 7: top MBs use ALTPQUANT
    • if macroblock touches the top border
      • use alternate picture quantizer for this macroblock
      • quantizer half step = 0
  • case 8: right MBs use ALTPQUANT
    • if macroblock touches the right border
      • use alternate picture quantizer for this macroblock
      • quantizer half step = 0
  • case 9: bottom MBs use ALTPQUANT
    • if macroblock touches the bottom border
      • use alternate picture quantizer for this macroblock
      • quantizer half step = 0

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 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
  • 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

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
  • 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

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
  • 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
      • 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.)
  • else
    • if (left block exists) and (left block is intra-coded)
      • prediction direction = left
      • DC_predicted = vc1PREDDCAC_ScaleDC(left.DC, quantizer_left, quantizer_current)
  • 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
    • else
      • prediction direction = none
  • 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
    • else
      • prediction direction = none
  • 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)")
    • if picture format is interlaced
      • prediction direction = none
  • 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

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
    • else
      • call RangeReduce with the entire plane as the rectange and 16 as the scale value

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)