mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-12-24 13:48:04 +08:00
126 lines
3.4 KiB
Go
126 lines
3.4 KiB
Go
package box
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"io"
|
|
|
|
"github.com/yapingcat/gomedia/go-codec"
|
|
)
|
|
|
|
// class ChannelMappingTable (unsigned int(8) OutputChannelCount){
|
|
// unsigned int(8) StreamCount;
|
|
// unsigned int(8) CoupledCount;
|
|
// unsigned int(8 * OutputChannelCount) ChannelMapping;
|
|
// }
|
|
// aligned(8) class OpusSpecificBox extends Box('dOps'){
|
|
// unsigned int(8) Version;
|
|
// unsigned int(8) OutputChannelCount;
|
|
// unsigned int(16) PreSkip;
|
|
// unsigned int(32) InputSampleRate;
|
|
// signed int(16) OutputGain;
|
|
// unsigned int(8) ChannelMappingFamily;
|
|
// if (ChannelMappingFamily != 0) {
|
|
// ChannelMappingTable(OutputChannelCount);
|
|
// }
|
|
// }
|
|
|
|
type ChannelMappingTable struct {
|
|
StreamCount uint8
|
|
CoupledCount uint8
|
|
ChannelMapping []byte
|
|
}
|
|
|
|
type OpusSpecificBox struct {
|
|
Box *BasicBox
|
|
Version uint8
|
|
OutputChannelCount uint8
|
|
PreSkip uint16
|
|
InputSampleRate uint32
|
|
OutputGain int16
|
|
ChanMapTable *ChannelMappingTable
|
|
}
|
|
|
|
func NewdOpsBox() *OpusSpecificBox {
|
|
return &OpusSpecificBox{
|
|
Box: NewBasicBox([4]byte{'d', 'O', 'p', 's'}),
|
|
}
|
|
}
|
|
|
|
func (dops *OpusSpecificBox) Size() uint64 {
|
|
return uint64(8 + 10 + 2 + dops.OutputChannelCount)
|
|
}
|
|
|
|
func (dops *OpusSpecificBox) Encode() (int, []byte) {
|
|
dops.Box.Size = dops.Size()
|
|
offset, buf := dops.Box.Encode()
|
|
buf[offset] = dops.Version
|
|
offset++
|
|
buf[offset] = dops.OutputChannelCount
|
|
offset++
|
|
binary.LittleEndian.PutUint16(buf[offset:], dops.PreSkip)
|
|
offset += 2
|
|
binary.BigEndian.PutUint32(buf[offset:], dops.InputSampleRate)
|
|
offset += 4
|
|
binary.LittleEndian.PutUint16(buf[offset:], uint16(dops.OutputGain))
|
|
offset += 2
|
|
if dops.ChanMapTable != nil {
|
|
buf[offset] = dops.ChanMapTable.StreamCount
|
|
offset++
|
|
buf[offset] = dops.ChanMapTable.CoupledCount
|
|
offset++
|
|
copy(buf[offset:], dops.ChanMapTable.ChannelMapping)
|
|
offset += len(dops.ChanMapTable.ChannelMapping)
|
|
}
|
|
return offset, buf
|
|
}
|
|
|
|
func (dops *OpusSpecificBox) Decode(r io.Reader, size uint32) (offset int, err error) {
|
|
|
|
dopsBuf := make([]byte, size-BasicBoxLen)
|
|
ChannelMappingFamily := 0
|
|
if size-BasicBoxLen-10 > 0 {
|
|
ChannelMappingFamily = int(size - BasicBoxLen - 10)
|
|
}
|
|
|
|
if _, err = io.ReadFull(r, dopsBuf); err != nil {
|
|
return
|
|
}
|
|
|
|
dops.Version = dopsBuf[0]
|
|
dops.OutputChannelCount = dopsBuf[1]
|
|
dops.PreSkip = binary.BigEndian.Uint16(dopsBuf[2:])
|
|
dops.InputSampleRate = binary.BigEndian.Uint32(dopsBuf[4:])
|
|
dops.OutputGain = int16(binary.BigEndian.Uint16(dopsBuf[8:]))
|
|
dops.ChanMapTable = nil
|
|
if ChannelMappingFamily > 0 {
|
|
dops.ChanMapTable = &ChannelMappingTable{}
|
|
dops.ChanMapTable.StreamCount = dopsBuf[10]
|
|
dops.ChanMapTable.CoupledCount = dopsBuf[11]
|
|
dops.ChanMapTable.ChannelMapping = make([]byte, ChannelMappingFamily-2)
|
|
copy(dops.ChanMapTable.ChannelMapping, dopsBuf[12:])
|
|
}
|
|
|
|
return int(size - BasicBoxLen), nil
|
|
}
|
|
|
|
func MakeOpusSpecificBox(extraData []byte) []byte {
|
|
ctx := &codec.OpusContext{}
|
|
ctx.ParseExtranData(extraData)
|
|
dops := NewdOpsBox()
|
|
dops.Version = 0
|
|
dops.OutputChannelCount = uint8(ctx.ChannelCount)
|
|
dops.PreSkip = uint16(ctx.Preskip)
|
|
dops.InputSampleRate = uint32(ctx.SampleRate)
|
|
dops.OutputGain = int16(ctx.OutputGain)
|
|
if ctx.MapType > 0 {
|
|
dops.ChanMapTable = &ChannelMappingTable{
|
|
StreamCount: uint8(ctx.StreamCount),
|
|
CoupledCount: uint8(ctx.StereoStreamCount),
|
|
ChannelMapping: make([]byte, len(ctx.Channel)),
|
|
}
|
|
copy(dops.ChanMapTable.ChannelMapping, ctx.Channel)
|
|
}
|
|
_, dopsbox := dops.Encode()
|
|
return dopsbox
|
|
}
|