Skip to content

Commit

Permalink
Merge pull request #349 from ZSC714725/opus
Browse files Browse the repository at this point in the history
feat: support opus
  • Loading branch information
q191201771 authored Apr 7, 2024
2 parents 08487f9 + 3361edd commit 0cd88bd
Show file tree
Hide file tree
Showing 17 changed files with 313 additions and 68 deletions.
11 changes: 6 additions & 5 deletions pkg/base/avpacket.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ type AvPacketPt int

const (
AvPacketPtUnknown AvPacketPt = -1
AvPacketPtG711U AvPacketPt = 0 // g711u
AvPacketPtG711A AvPacketPt = 8 // g711a
AvPacketPtAvc AvPacketPt = 96 // h264
AvPacketPtHevc AvPacketPt = 98 // h265
AvPacketPtAac AvPacketPt = 97 // aac
AvPacketPtG711U AvPacketPt = 0 // g711u
AvPacketPtG711A AvPacketPt = 8 // g711a
AvPacketPtAvc AvPacketPt = 96 // h264
AvPacketPtHevc AvPacketPt = 98 // h265
AvPacketPtAac AvPacketPt = 97 // aac
AvPacketPtOpus AvPacketPt = 101 // opus
)

func (a AvPacketPt) ReadableString() string {
Expand Down
1 change: 1 addition & 0 deletions pkg/base/t_http_an__.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
AudioCodecAac = "AAC"
AudioCodecG711U = "PCMU"
AudioCodecG711A = "PCMA"
AudioCodecOpus = "OPUS"

// VideoCodecAvc StatGroup.VideoCodec
VideoCodecAvc = "H264"
Expand Down
2 changes: 2 additions & 0 deletions pkg/base/t_rtmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package base
import (
"encoding/hex"
"fmt"

"github.com/q191201771/naza/pkg/bele"
"github.com/q191201771/naza/pkg/nazabytes"
)
Expand Down Expand Up @@ -117,6 +118,7 @@ const (
RtmpSoundFormatG711A uint8 = 7
RtmpSoundFormatG711U uint8 = 8
RtmpSoundFormatAac uint8 = 10
RtmpSoundFormatOpus uint8 = 13

RtmpAacPacketTypeSeqHeader = 0
RtmpAacPacketTypeRaw = 1
Expand Down
5 changes: 4 additions & 1 deletion pkg/logic/group__core_streaming.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
package logic

import (
"github.com/q191201771/lal/pkg/rtsp"
"net"

"github.com/q191201771/lal/pkg/rtsp"

"github.com/q191201771/lal/pkg/rtmp"
"github.com/q191201771/naza/pkg/nazalog"

Expand Down Expand Up @@ -409,6 +410,8 @@ func (group *Group) broadcastByRtmpMsg(msg base.RtmpMsg) {
group.stat.AudioCodec = base.AudioCodecG711U
case base.RtmpSoundFormatG711A:
group.stat.AudioCodec = base.AudioCodecG711A
case base.RtmpSoundFormatOpus:
group.stat.AudioCodec = base.AudioCodecOpus
}
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/mpegts/mpegts.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ const (
// 0x24 HEVC (HEVC video stream as defined in Rec. ITU-T H.265 | ISO/IEC 23008-2 MPEG-H Part 2)
// -----------------------------------------------------------------------------
StreamTypeUnknown uint8 = 0x00
StreamTypePrivate uint8 = 0x06
StreamTypeAac uint8 = 0x0F
StreamTypeAvc uint8 = 0x1B
StreamTypeHevc uint8 = 0x24
Expand Down
52 changes: 46 additions & 6 deletions pkg/mpegts/pmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package mpegts

import (
"github.com/q191201771/lal/pkg/base"
"github.com/q191201771/naza/pkg/nazabits"
)

Expand Down Expand Up @@ -57,9 +58,10 @@ type Pmt struct {
}

type PmtProgramElement struct {
StreamType uint8
Pid uint16
Length uint16
StreamType uint8
Pid uint16
Length uint16
Descriptors []Descriptor
}

func ParsePmt(b []byte) (pmt Pmt) {
Expand Down Expand Up @@ -110,7 +112,7 @@ func (pmt *Pmt) SearchPid(pid uint16) *PmtProgramElement {
return nil
}

func PackPmt(videoStreamType, audioStreamType uint8) []byte {
func PackPmt(videoCodecId, audioCodecId int) []byte {
ts := make([]byte, 188)
tsheader := []byte{0x47, 0x50, 0x01, 0x10}
copy(ts, tsheader)
Expand All @@ -122,18 +124,56 @@ func PackPmt(videoStreamType, audioStreamType uint8) []byte {
psi.sectionData.section.currentNextIndicator = 1
psi.sectionData.pmtData.pcrPid = 0x100

videoStreamType := StreamTypeUnknown
if videoCodecId == int(base.RtmpCodecIdAvc) {
videoStreamType = StreamTypeAvc
} else if videoCodecId == int(base.RtmpCodecIdHevc) {
videoStreamType = StreamTypeHevc
}

if videoStreamType != StreamTypeUnknown {
psi.sectionData.pmtData.pes = append(psi.sectionData.pmtData.pes, PmtProgramElement{
StreamType: videoStreamType,
Pid: PidVideo,
})
}

audioStreamType := StreamTypeUnknown
if audioCodecId == int(base.RtmpSoundFormatAac) {
audioStreamType = StreamTypeAac
} else if audioCodecId == int(base.RtmpSoundFormatOpus) {
audioStreamType = StreamTypePrivate
}

if audioStreamType != StreamTypeUnknown {
psi.sectionData.pmtData.pes = append(psi.sectionData.pmtData.pes, PmtProgramElement{
pmtEle := PmtProgramElement{
StreamType: audioStreamType,
Pid: PidAudio,
})
}

if audioCodecId == int(base.RtmpSoundFormatOpus) {
descriptor := []Descriptor{
{
Length: 4,
Tag: DescriptorTagRegistration,
Registration: DescriptorRegistration{
FormatIdentifier: opusIdentifier,
},
},
{
Length: 2,
Tag: DescriptorTagExtension,
Extension: DescriptorExtension{
Tag: 0x80,
Unknown: []uint8{0x02},
},
},
}

pmtEle.Descriptors = append(pmtEle.Descriptors, descriptor...)
}

psi.sectionData.pmtData.pes = append(psi.sectionData.pmtData.pes, pmtEle)
}

psilen, psiData := psi.Pack()
Expand Down
154 changes: 150 additions & 4 deletions pkg/mpegts/psi.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,36 @@ const (
TsPsiIdForbidden = 0xFF // forbidden
)

const (
DescriptorTagAC3 = 0x6a
DescriptorTagAVCVideo = 0x28
DescriptorTagComponent = 0x50
DescriptorTagContent = 0x54
DescriptorTagDataStreamAlignment = 0x6
DescriptorTagEnhancedAC3 = 0x7a
DescriptorTagExtendedEvent = 0x4e
DescriptorTagExtension = 0x7f
DescriptorTagISO639LanguageAndAudioType = 0xa
DescriptorTagLocalTimeOffset = 0x58
DescriptorTagMaximumBitrate = 0xe
DescriptorTagNetworkName = 0x40
DescriptorTagParentalRating = 0x55
DescriptorTagPrivateDataIndicator = 0xf
DescriptorTagPrivateDataSpecifier = 0x5f
DescriptorTagRegistration = 0x5
DescriptorTagService = 0x48
DescriptorTagShortEvent = 0x4d
DescriptorTagStreamIdentifier = 0x52
DescriptorTagSubtitling = 0x59
DescriptorTagTeletext = 0x56
DescriptorTagVBIData = 0x45
DescriptorTagVBITeletext = 0x46
)

const (
opusIdentifier = 0x4f707573 // Opus
)

type PsiSection struct {
pointerFileld uint8
sectionData PsiSectionData
Expand Down Expand Up @@ -152,13 +182,58 @@ func (psi *PsiSection) calaPatSectionLength() (length uint16) {
}

func (psi *PsiSection) calaPmtSectionLength() (length uint16) {
// 暂不考虑Program descriptors
// Reserved bits(3 bits)+PCR PID(13 bits)+Reserved bits(4 bits)+Program info length(12 bits)
length = 4
length += uint16(5 * len(psi.sectionData.pmtData.pes))

for _, pe := range psi.sectionData.pmtData.pes {
length += 5

if len(pe.Descriptors) > 0 {
length += psi.calcDescriptorsLength(pe.Descriptors)
}
}

return
}

func (psi *PsiSection) calcDescriptorsLength(ds []Descriptor) uint16 {
length := uint16(0)
for _, d := range ds {
length += 2 // tag and length
length += uint16(psi.calcDescriptorLength(d))
}
return length
}

func (psi *PsiSection) calcDescriptorLength(d Descriptor) uint8 {
if d.Length == 0 {
return 0
}

switch d.Tag {
case DescriptorTagRegistration:
return psi.calcDescriptorRegistrationLength(d.Registration)
case DescriptorTagExtension:
return psi.calcDescriptorExtensionLength(d.Extension)
}

return 0
}

func (psi *PsiSection) calcDescriptorRegistrationLength(d DescriptorRegistration) uint8 {
return uint8(4 + len(d.AdditionalIdentificationInfo))
}

func (psi *PsiSection) calcDescriptorExtensionLength(d DescriptorExtension) uint8 {
// tag
ret := 1
if d.Unknown != nil {
ret += len(d.Unknown)
}

return uint8(ret)
}

func (psi *PsiSection) writePatSection(bw *nazabits.BitWriter) {
for _, pe := range psi.sectionData.patData.pes {
bw.WriteBits16(16, pe.pn)
Expand All @@ -179,8 +254,79 @@ func (psi *PsiSection) writePmtSection(bw *nazabits.BitWriter) {
bw.WriteBits8(8, pe.StreamType)
bw.WriteBits8(3, 0xff)
bw.WriteBits16(13, pe.Pid)
bw.WriteBits8(4, 0xff)
bw.WriteBits16(12, 0)
psi.writeDescriptorsWithLength(bw, pe.Descriptors)
}
return
}

func (psi *PsiSection) writeDescriptorsWithLength(bw *nazabits.BitWriter, dps []Descriptor) {
bw.WriteBits8(4, 0xff)

infolen := psi.calcDescriptorsLength(dps)
bw.WriteBits16(12, infolen)

for _, dp := range dps {
psi.writeDescriptor(bw, dp)
}
}

func (psi *PsiSection) writeDescriptor(bw *nazabits.BitWriter, d Descriptor) {
length := psi.calcDescriptorLength(d)

bw.WriteBits8(8, d.Tag)
bw.WriteBits8(8, length)

switch d.Tag {
case DescriptorTagRegistration:
psi.writeDescriptorRegistration(bw, d.Registration)
case DescriptorTagExtension:
psi.writeDescriptorExtension(bw, d.Extension)
}
}

func (psi *PsiSection) writeDescriptorRegistration(bw *nazabits.BitWriter, d DescriptorRegistration) {
bw.WriteBits16(16, uint16((d.FormatIdentifier>>16)&0xFFFF))
bw.WriteBits16(16, uint16(d.FormatIdentifier&0xFFFF))

if len(d.AdditionalIdentificationInfo) > 0 {
for _, b := range d.AdditionalIdentificationInfo {
bw.WriteBits8(8, b)
}
}
}

func (psi *PsiSection) writeDescriptorExtension(bw *nazabits.BitWriter, d DescriptorExtension) {
bw.WriteBits8(8, d.Tag)

if len(d.Unknown) > 0 {
for _, b := range d.Unknown {
bw.WriteBits8(8, b)
}
}
}

type Descriptor struct {
Length uint8
Tag uint8
Registration DescriptorRegistration
Extension DescriptorExtension
}

type DescriptorRegistration struct {
AdditionalIdentificationInfo []byte
FormatIdentifier uint32
}

type DescriptorExtension struct {
SupplementaryAudio DescriptorExtensionSupplementaryAudio
Tag uint8
Unknown []byte
}

type DescriptorExtensionSupplementaryAudio struct {
EditorialClassification uint8
HasLanguageCode bool
LanguageCode []byte
MixType bool
PrivateData []byte
}
8 changes: 8 additions & 0 deletions pkg/remux/avpacket2rtmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,14 @@ func (r *AvPacket2RtmpRemuxer) FeedAvPacket(pkt base.AvPacket) {
copy(payload[1:], pkt.Payload)
r.emitRtmpAvMsg(true, payload, pkt.Timestamp)

case base.AvPacketPtOpus:
length := len(pkt.Payload) + 1
payload := make([]byte, length)
// codecid=13, 44kHz、16bits、Stereo
payload[0] = 0xdf
copy(payload[1:], pkt.Payload)
r.emitRtmpAvMsg(true, payload, pkt.Timestamp)

default:
Log.Warnf("unsupported packet. type=%d", pkt.PayloadType)
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/remux/remux.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ package remux

var _ iRtmp2MpegtsFilterObserver = &Rtmp2MpegtsRemuxer{}

const pcmDefaultSampleRate = 8000
const (
pcmDefaultSampleRate = 8000
opusDefaultSampleRate = 48000
)
Loading

0 comments on commit 0cd88bd

Please sign in to comment.