Fix AAC inside MP4
This commit is contained in:
+21
-5
@@ -9,6 +9,8 @@ import (
|
|||||||
const RTPPacketVersionAAC = 0
|
const RTPPacketVersionAAC = 0
|
||||||
|
|
||||||
func RTPDepay(handler core.HandlerFunc) core.HandlerFunc {
|
func RTPDepay(handler core.HandlerFunc) core.HandlerFunc {
|
||||||
|
var timestamp uint32
|
||||||
|
|
||||||
return func(packet *rtp.Packet) {
|
return func(packet *rtp.Packet) {
|
||||||
// support ONLY 2 bytes header size!
|
// support ONLY 2 bytes header size!
|
||||||
// streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1408
|
// streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config=1408
|
||||||
@@ -16,16 +18,30 @@ func RTPDepay(handler core.HandlerFunc) core.HandlerFunc {
|
|||||||
|
|
||||||
//log.Printf("[RTP/AAC] units: %d, size: %4d, ts: %10d, %t", headersSize/2, len(packet.Payload), packet.Timestamp, packet.Marker)
|
//log.Printf("[RTP/AAC] units: %d, size: %4d, ts: %10d, %t", headersSize/2, len(packet.Payload), packet.Timestamp, packet.Marker)
|
||||||
|
|
||||||
data := packet.Payload[2+headersSize:]
|
headers := packet.Payload[2 : 2+headersSize]
|
||||||
if IsADTS(data) {
|
units := packet.Payload[2+headersSize:]
|
||||||
data = data[7:]
|
|
||||||
}
|
for len(headers) > 0 {
|
||||||
|
unitSize := binary.BigEndian.Uint16(headers) >> 3
|
||||||
|
|
||||||
|
unit := units[:unitSize]
|
||||||
|
|
||||||
|
headers = headers[2:]
|
||||||
|
units = units[unitSize:]
|
||||||
|
|
||||||
|
timestamp += 1024
|
||||||
|
|
||||||
clone := *packet
|
clone := *packet
|
||||||
clone.Version = RTPPacketVersionAAC
|
clone.Version = RTPPacketVersionAAC
|
||||||
clone.Payload = data
|
clone.Timestamp = timestamp
|
||||||
|
if IsADTS(unit) {
|
||||||
|
clone.Payload = unit[7:]
|
||||||
|
} else {
|
||||||
|
clone.Payload = unit
|
||||||
|
}
|
||||||
handler(&clone)
|
handler(&clone)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func RTPPay(handler core.HandlerFunc) core.HandlerFunc {
|
func RTPPay(handler core.HandlerFunc) core.HandlerFunc {
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ const (
|
|||||||
SampleVideoIFrame = sampleDependsOn2
|
SampleVideoIFrame = sampleDependsOn2
|
||||||
SampleVideoNonIFrame = sampleDependsOn1 | sampleIsNonSync
|
SampleVideoNonIFrame = sampleDependsOn1 | sampleIsNonSync
|
||||||
SampleAudio = sampleIsNonSync
|
SampleAudio = sampleIsNonSync
|
||||||
|
SampleAudioAAC = sampleDependsOn2
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Movie) WriteFileType() {
|
func (m *Movie) WriteFileType() {
|
||||||
|
|||||||
+13
-9
@@ -151,19 +151,14 @@ func (m *Muxer) Reset() {
|
|||||||
func (m *Muxer) Marshal(trackID byte, packet *rtp.Packet) []byte {
|
func (m *Muxer) Marshal(trackID byte, packet *rtp.Packet) []byte {
|
||||||
codec := m.codecs[trackID]
|
codec := m.codecs[trackID]
|
||||||
|
|
||||||
|
m.fragIndex++
|
||||||
|
|
||||||
duration := packet.Timestamp - m.pts[trackID]
|
duration := packet.Timestamp - m.pts[trackID]
|
||||||
m.pts[trackID] = packet.Timestamp
|
m.pts[trackID] = packet.Timestamp
|
||||||
|
|
||||||
// minumum duration important for MSE in Apple Safari
|
|
||||||
if duration == 0 || duration > codec.ClockRate {
|
|
||||||
duration = codec.ClockRate/1000 + 1
|
|
||||||
m.pts[trackID] += duration
|
|
||||||
}
|
|
||||||
|
|
||||||
size := len(packet.Payload)
|
|
||||||
|
|
||||||
// flags important for Apple Finder video preview
|
// flags important for Apple Finder video preview
|
||||||
var flags uint32
|
var flags uint32
|
||||||
|
|
||||||
switch codec.Name {
|
switch codec.Name {
|
||||||
case core.CodecH264:
|
case core.CodecH264:
|
||||||
if h264.IsKeyframe(packet.Payload) {
|
if h264.IsKeyframe(packet.Payload) {
|
||||||
@@ -177,11 +172,20 @@ func (m *Muxer) Marshal(trackID byte, packet *rtp.Packet) []byte {
|
|||||||
} else {
|
} else {
|
||||||
flags = iso.SampleVideoNonIFrame
|
flags = iso.SampleVideoNonIFrame
|
||||||
}
|
}
|
||||||
|
case core.CodecAAC:
|
||||||
|
duration = 1024 // important for Apple Finder and QuickTime
|
||||||
|
flags = iso.SampleAudioAAC // not important
|
||||||
default:
|
default:
|
||||||
flags = iso.SampleAudio // not important
|
flags = iso.SampleAudio // not important
|
||||||
}
|
}
|
||||||
|
|
||||||
m.fragIndex++
|
// minumum duration important for MSE in Apple Safari
|
||||||
|
if duration == 0 || duration > codec.ClockRate {
|
||||||
|
duration = codec.ClockRate/1000 + 1
|
||||||
|
m.pts[trackID] += duration
|
||||||
|
}
|
||||||
|
|
||||||
|
size := len(packet.Payload)
|
||||||
|
|
||||||
mv := iso.NewMovie(1024 + size)
|
mv := iso.NewMovie(1024 + size)
|
||||||
mv.WriteMovieFragment(
|
mv.WriteMovieFragment(
|
||||||
|
|||||||
Reference in New Issue
Block a user