add mpes frame extractor

This commit is contained in:
notch
2020-12-14 08:52:44 +08:00
parent 5e0398ae94
commit 4508302351

View File

@@ -0,0 +1,126 @@
// Copyright (c) 2019,CAOHONGJU All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package rtp
import (
"fmt"
"github.com/cnotch/tomatox/av/aac"
)
type mpesFrameExtractor struct {
w FrameWriter
sizeLength int
indexLength int
extractFunc func(packet *Packet) error
}
// NewMPESFrameExtractor 实例化 MPES 帧提取器
func NewMPESFrameExtractor(w FrameWriter, sizeLength, indexLength int) FrameExtractor {
fe := &mpesFrameExtractor{
w: w,
sizeLength: sizeLength,
indexLength: indexLength,
}
switch sizeLength + indexLength {
case 8:
fe.extractFunc = fe.extractFor1ByteAUHeader
case 16:
fe.extractFunc = fe.extractFor2ByteAUHeader
default:
panic(fmt.Sprintf("not supported au_header size(%d,%d)", sizeLength, indexLength))
}
return fe
}
// 以下是当 sizelength=13;indexlength=3;indexdeltalength=3 时
// Au-header = 13+3 bits(2byte) 的示意图
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
// | AU-headers-length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
// | AU-header(1) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
// | AU-header(2) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
// | ... |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
// | AU-header(n) |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
// | pading bits |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
// 当 sizelength=6;indexlength=2;indexdeltalength=2 时
// 单帧封装时rtp payload的长度 = AU-header-lengths(两个字节) + AU-header(6+2) + AU的长度
func (fe *mpesFrameExtractor) Extract(packet *Packet) (err error) {
return fe.extractFunc(packet)
}
func (fe *mpesFrameExtractor) extractFor2ByteAUHeader(packet *Packet) (err error) {
payload := packet.Payload()
// AU-headers-length 2bytes
auHeadersLength := uint16(0) | (uint16(payload[0]) << 8) | uint16(payload[1])
// AU-headers-length / 16
auHeadersCount := auHeadersLength >> 4
// AU 帧数据偏移位置
framesPayloadOffset := 2 + int(auHeadersCount)<<1
auHeaders := payload[2:framesPayloadOffset]
framesPayload := payload[framesPayloadOffset:]
frameTimeStamp := packet.Timestamp
for i := 0; i < int(auHeadersCount); i++ {
auHeader := uint16(0) | (uint16(payload[0]) << 8) | uint16(payload[1])
frameSize := auHeader >> fe.indexLength
frame := &Frame{
FrameAudio,
frameTimeStamp,
framesPayload[:frameSize],
}
if err = fe.w.Write(frame); err != nil {
return
}
// 下一帧
auHeaders = auHeaders[2:]
framesPayload = framesPayload[frameSize:]
frameTimeStamp += aac.SamplesPerFrame // 每帧采样数
}
return
}
func (fe *mpesFrameExtractor) extractFor1ByteAUHeader(packet *Packet) (err error) {
payload := packet.Payload()
// AU-headers-length 2bytes
auHeadersLength := uint16(0) | (uint16(payload[0]) << 8) | uint16(payload[1])
// AU-headers-length / 16
auHeadersCount := auHeadersLength >> 4
// AU 帧数据偏移位置
framesPayloadOffset := 2 + int(auHeadersCount)
auHeaders := payload[2:framesPayloadOffset]
framesPayload := payload[framesPayloadOffset:]
frameTimeStamp := packet.Timestamp
for i := 0; i < int(auHeadersCount); i++ {
auHeader := payload[0]
frameSize := auHeader >> fe.indexLength
frame := &Frame{
FrameAudio,
frameTimeStamp,
framesPayload[:frameSize],
}
if err = fe.w.Write(frame); err != nil {
return
}
// 下一帧
auHeaders = auHeaders[1:]
framesPayload = framesPayload[frameSize:]
frameTimeStamp += aac.SamplesPerFrame // 每帧采样数
}
return
}