mirror of
https://github.com/cnotch/ipchub.git
synced 2025-09-26 19:41:18 +08:00
add mpes frame extractor
This commit is contained in:
126
protos/rtp/mpes_frame_extractor.go
Normal file
126
protos/rtp/mpes_frame_extractor.go
Normal 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
|
||||
}
|
Reference in New Issue
Block a user