You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lal/pkg/avc/beta.go

416 lines
11 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// Copyright 2021, Chef. All rights reserved.
// https://github.com/q191201771/lal
//
// Use of this source code is governed by a MIT-style license
// that can be found in the License file.
//
// Author: Chef (191201771@qq.com)
package avc
import (
"encoding/hex"
"github.com/q191201771/naza/pkg/nazaerrors"
"github.com/q191201771/naza/pkg/bele"
"github.com/q191201771/naza/pkg/nazabits"
"github.com/q191201771/naza/pkg/nazalog"
"github.com/q191201771/naza/pkg/nazastring"
)
func ParseSps(payload []byte, ctx *Context) error {
br := nazabits.NewBitReader(payload)
var sps Sps
if err := parseSpsBasic(&br, &sps); err != nil {
nazalog.Errorf("parseSpsBasic failed. err=%+v, payload=%s", err, hex.Dump(nazastring.SubSliceSafety(payload, 128)))
return err
}
ctx.Profile = sps.ProfileIdc
ctx.Level = sps.LevelIdc
if err := parseSpsBeta(&br, &sps); err != nil {
// 注意这里不将错误返回给上层因为可能是Beta自身解析的问题
nazalog.Errorf("parseSpsBeta failed. err=%+v, payload=%s", err, hex.Dump(nazastring.SubSliceSafety(payload, 128)))
}
ctx.Width = (sps.PicWidthInMbsMinusOne+1)*16 - (sps.FrameCropLeftOffset+sps.FrameCropRightOffset)*2
ctx.Height = (2-uint32(sps.FrameMbsOnlyFlag))*(sps.PicHeightInMapUnitsMinusOne+1)*16 - (sps.FrameCropTopOffset+sps.FrameCropBottomOffset)*2
return nil
}
// 尝试解析PPS所有字段实验中请勿直接使用该函数
func TryParsePps(payload []byte) error {
// ISO-14496-10.pdf
// 7.3.2.2 Picture parameter set RBSP syntax
// TODO impl me
return nil
}
// 尝试解析SeqHeader所有字段实验中请勿直接使用该函数
//
// @param <payload> rtmp message的payload部分或者flv tag的payload部分
// 注意包含了头部2字节类型以及3字节的cts
//
func TryParseSeqHeader(payload []byte) error {
if len(payload) < 5 {
return ErrAvc
}
if payload[0] != 0x17 || payload[1] != 0x00 || payload[2] != 0 || payload[3] != 0 || payload[4] != 0 {
return ErrAvc
}
// H.264-AVC-ISO_IEC_14496-15.pdf
// 5.2.4 Decoder configuration information
var dcr DecoderConfigurationRecord
var err error
br := nazabits.NewBitReader(payload[5:])
// TODO check error
dcr.ConfigurationVersion, err = br.ReadBits8(8)
dcr.AvcProfileIndication, err = br.ReadBits8(8)
dcr.ProfileCompatibility, err = br.ReadBits8(8)
dcr.AvcLevelIndication, err = br.ReadBits8(8)
_, err = br.ReadBits8(6) // reserved = '111111'b
dcr.LengthSizeMinusOne, err = br.ReadBits8(2)
_, err = br.ReadBits8(3) // reserved = '111'b
dcr.NumOfSps, err = br.ReadBits8(5)
b, err := br.ReadBytes(2)
dcr.SpsLength = bele.BeUint16(b)
_, _ = br.ReadBytes(uint(dcr.SpsLength))
_, err = br.ReadBits8(3) // reserved = '111'b
dcr.NumOfPps, err = br.ReadBits8(5)
b, err = br.ReadBytes(2)
dcr.PpsLength = bele.BeUint16(b)
nazalog.Debugf("%+v", dcr)
// 5 + 5 + 1 + 2
var ctx Context
_ = ParseSps(payload[13:13+dcr.SpsLength], &ctx)
// 13 + 1 + 2
_ = TryParsePps(payload[16 : 16+dcr.PpsLength])
return err
}
func parseSpsBasic(br *nazabits.BitReader, sps *Sps) error {
t, err := br.ReadBits8(8) //nalType SPS should be 0x67
if err != nil {
return nazaerrors.Wrap(err)
}
_ = t
//if t != 0x67 {
// return Context{}, ErrAvc
//}
sps.ProfileIdc, err = br.ReadBits8(8)
if err != nil {
return nazaerrors.Wrap(err)
}
sps.ConstraintSet0Flag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
sps.ConstraintSet1Flag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
sps.ConstraintSet2Flag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
_, err = br.ReadBits8(5)
if err != nil {
return nazaerrors.Wrap(err)
}
sps.LevelIdc, err = br.ReadBits8(8)
if err != nil {
return nazaerrors.Wrap(err)
}
sps.SpsId, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
if sps.SpsId >= 32 {
return nazaerrors.Wrap(ErrAvc)
}
return nil
}
func parseSpsBeta(br *nazabits.BitReader, sps *Sps) error {
var err error
// 100 High profile
if sps.ProfileIdc == 100 {
sps.ChromaFormatIdc, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
if sps.ChromaFormatIdc > 3 {
return nazaerrors.Wrap(ErrAvc)
}
if sps.ChromaFormatIdc == 3 {
sps.ResidualColorTransformFlag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
}
sps.BitDepthLuma, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
sps.BitDepthLuma += 8
sps.BitDepthChroma, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
sps.BitDepthChroma += 8
if sps.BitDepthChroma != sps.BitDepthLuma || sps.BitDepthChroma < 8 || sps.BitDepthChroma > 14 {
return nazaerrors.Wrap(ErrAvc)
}
sps.TransFormBypass, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
// seq scaling matrix present
flag, err := br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
if flag == 1 {
nazalog.Debugf("scaling matrix present.")
// TODO chef: 还没有正确实现只是针对特定case做了处理
_, err = br.ReadBits32(128)
if err != nil {
return nazaerrors.Wrap(err)
}
}
} else {
sps.ChromaFormatIdc = 1
sps.BitDepthLuma = 8
sps.BitDepthChroma = 8
}
sps.Log2MaxFrameNumMinus4, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
if sps.Log2MaxFrameNumMinus4 > 12 {
return nazaerrors.Wrap(ErrAvc)
}
sps.PicOrderCntType, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
if sps.PicOrderCntType == 0 {
sps.Log2MaxPicOrderCntLsb, err = br.ReadGolomb()
sps.Log2MaxPicOrderCntLsb += 4
} else if sps.PicOrderCntType == 2 {
// noop
} else {
nazalog.Debugf("not impl yet. sps.PicOrderCntType=%d", sps.PicOrderCntType)
return nazaerrors.Wrap(ErrAvc)
}
sps.NumRefFrames, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
sps.GapsInFrameNumValueAllowedFlag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
sps.PicWidthInMbsMinusOne, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
sps.PicHeightInMapUnitsMinusOne, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
sps.FrameMbsOnlyFlag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
if sps.FrameMbsOnlyFlag == 0 {
sps.MbAdaptiveFrameFieldFlag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
}
sps.Direct8X8InferenceFlag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
sps.FrameCroppingFlag, err = br.ReadBits8(1)
if err != nil {
return nazaerrors.Wrap(err)
}
if sps.FrameCroppingFlag == 1 {
sps.FrameCropLeftOffset, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
sps.FrameCropRightOffset, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
sps.FrameCropTopOffset, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
sps.FrameCropBottomOffset, err = br.ReadGolomb()
if err != nil {
return nazaerrors.Wrap(err)
}
}
// TODO parse sps vui parameters
return nil
}
//var defaultScaling4 = [][]uint8{
// {
// 6, 13, 20, 28, 13, 20, 28, 32,
// 20, 28, 32, 37, 28, 32, 37, 42,
// },
// {
// 10, 14, 20, 24, 14, 20, 24, 27,
// 20, 24, 27, 30, 24, 27, 30, 34,
// },
//}
//
//var defaultScaling8 = [][]uint8{
// {
// 6, 10, 13, 16, 18, 23, 25, 27,
// 10, 11, 16, 18, 23, 25, 27, 29,
// 13, 16, 18, 23, 25, 27, 29, 31,
// 16, 18, 23, 25, 27, 29, 31, 33,
// 18, 23, 25, 27, 29, 31, 33, 36,
// 23, 25, 27, 29, 31, 33, 36, 38,
// 25, 27, 29, 31, 33, 36, 38, 40,
// 27, 29, 31, 33, 36, 38, 40, 42,
// },
// {
// 9, 13, 15, 17, 19, 21, 22, 24,
// 13, 13, 17, 19, 21, 22, 24, 25,
// 15, 17, 19, 21, 22, 24, 25, 27,
// 17, 19, 21, 22, 24, 25, 27, 28,
// 19, 21, 22, 24, 25, 27, 28, 30,
// 21, 22, 24, 25, 27, 28, 30, 32,
// 22, 24, 25, 27, 28, 30, 32, 33,
// 24, 25, 27, 28, 30, 32, 33, 35,
// },
//}
//
//var ffZigzagDirect = []uint8{
// 0, 1, 8, 16, 9, 2, 3, 10,
// 17, 24, 32, 25, 18, 11, 4, 5,
// 12, 19, 26, 33, 40, 48, 41, 34,
// 27, 20, 13, 6, 7, 14, 21, 28,
// 35, 42, 49, 56, 57, 50, 43, 36,
// 29, 22, 15, 23, 30, 37, 44, 51,
// 58, 59, 52, 45, 38, 31, 39, 46,
// 53, 60, 61, 54, 47, 55, 62, 63,
//}
//
//var ffZigzagScan = []uint8{
// 0 + 0*4, 1 + 0*4, 0 + 1*4, 0 + 2*4,
// 1 + 1*4, 2 + 0*4, 3 + 0*4, 2 + 1*4,
// 1 + 2*4, 0 + 3*4, 1 + 3*4, 2 + 2*4,
// 3 + 1*4, 3 + 2*4, 2 + 3*4, 3 + 3*4,
//}
//
//func decodeScalingMatrices(reader *nazabits.BitReader) error {
// // 6 * 16
// var spsScalingMatrix4 = [][]uint8{
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// }
// // 6 * 64
// var spsScalingMatrix8 = [][]uint8{
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
// }
//
// fallback := [][]uint8{defaultScaling4[0], defaultScaling4[1], defaultScaling8[0], defaultScaling8[1]}
// decodeScalingList(reader, spsScalingMatrix4[0], 16, defaultScaling4[0], fallback[0])
// decodeScalingList(reader, spsScalingMatrix4[1], 16, defaultScaling4[0], spsScalingMatrix4[0])
// decodeScalingList(reader, spsScalingMatrix4[2], 16, defaultScaling4[0], spsScalingMatrix4[1])
// decodeScalingList(reader, spsScalingMatrix4[3], 16, defaultScaling4[1], fallback[1])
// decodeScalingList(reader, spsScalingMatrix4[4], 16, defaultScaling4[1], spsScalingMatrix4[3])
// decodeScalingList(reader, spsScalingMatrix4[4], 16, defaultScaling4[1], spsScalingMatrix4[3])
//
// decodeScalingList(reader, spsScalingMatrix8[0], 64, defaultScaling8[0], fallback[2])
// decodeScalingList(reader, spsScalingMatrix8[3], 64, defaultScaling8[1], fallback[3])
//
// return nil
//}
//
//func decodeScalingList(reader *nazabits.BitReader, factors []uint8, size int, jvtList []uint8, fallbackList []uint8) error {
// var (
// i = 0
// last = 8
// next = 8
// scan []uint8
// )
// if size == 16 {
// scan = ffZigzagScan
// } else {
// scan = ffZigzagDirect
// }
// flag, err := reader.ReadBit()
// if err != nil {
// return err
// }
// return nil
// if flag == 0 {
// for n := 0; n < size; n++ {
// factors[n] = fallbackList[n]
// }
// } else {
// for i = 0; i < size; i++ {
// if next != 0 {
// v, err := reader.ReadGolomb()
// if err != nil {
// return err
// }
// next = (last + int(v)) & 0xff
// }
// if i == 0 && next == 0 {
// for n := 0; n < size; n++ {
// factors[n] = jvtList[n]
// }
// break
// }
// if next != 0 {
// factors[scan[i]] = uint8(next)
// last = next
// } else {
// factors[scan[i]] = uint8(last)
// }
// }
// }
// return nil
//}