fix codec and track

This commit is contained in:
Andrey Semochkin 2020-09-04 04:09:55 +03:00
parent 292592fcb5
commit fccce247d0
2 changed files with 54 additions and 50 deletions

View File

@ -1,4 +1,3 @@
// Package av defines basic interfaces and data structures of container demux/mux and audio encode/decode. // Package av defines basic interfaces and data structures of container demux/mux and audio encode/decode.
package av package av
@ -11,17 +10,17 @@ import (
type SampleFormat uint8 type SampleFormat uint8
const ( const (
U8 = SampleFormat(iota + 1) // 8-bit unsigned integer U8 = SampleFormat(iota + 1) // 8-bit unsigned integer
S16 // signed 16-bit integer S16 // signed 16-bit integer
S32 // signed 32-bit integer S32 // signed 32-bit integer
FLT // 32-bit float FLT // 32-bit float
DBL // 64-bit float DBL // 64-bit float
U8P // 8-bit unsigned integer in planar U8P // 8-bit unsigned integer in planar
S16P // signed 16-bit integer in planar S16P // signed 16-bit integer in planar
S32P // signed 32-bit integer in planar S32P // signed 32-bit integer in planar
FLTP // 32-bit float in planar FLTP // 32-bit float in planar
DBLP // 64-bit float in planar DBLP // 64-bit float in planar
U32 // unsigned 32-bit integer U32 // unsigned 32-bit integer
) )
func (self SampleFormat) BytesPerSample() int { func (self SampleFormat) BytesPerSample() int {
@ -116,11 +115,11 @@ func (self ChannelLayout) Count() (n int) {
type CodecType uint32 type CodecType uint32
var ( var (
H264 = MakeVideoCodecType(avCodecTypeMagic + 1) H264 = MakeVideoCodecType(avCodecTypeMagic + 1)
AAC = MakeAudioCodecType(avCodecTypeMagic + 1) AAC = MakeAudioCodecType(avCodecTypeMagic + 1)
PCM_MULAW = MakeAudioCodecType(avCodecTypeMagic + 2) PCM_MULAW = MakeAudioCodecType(avCodecTypeMagic + 2)
PCM_ALAW = MakeAudioCodecType(avCodecTypeMagic + 3) PCM_ALAW = MakeAudioCodecType(avCodecTypeMagic + 3)
SPEEX = MakeAudioCodecType(avCodecTypeMagic + 4) SPEEX = MakeAudioCodecType(avCodecTypeMagic + 4)
NELLYMOSER = MakeAudioCodecType(avCodecTypeMagic + 5) NELLYMOSER = MakeAudioCodecType(avCodecTypeMagic + 5)
) )
@ -171,7 +170,7 @@ const avCodecTypeMagic = 233333
// can be converted to VideoCodecData or AudioCodecData using: // can be converted to VideoCodecData or AudioCodecData using:
// //
// codecdata.(AudioCodecData) or codecdata.(VideoCodecData) // codecdata.(AudioCodecData) or codecdata.(VideoCodecData)
// //
// for H264, CodecData is AVCDecoderConfigure bytes, includes SPS/PPS. // for H264, CodecData is AVCDecoderConfigure bytes, includes SPS/PPS.
type CodecData interface { type CodecData interface {
Type() CodecType // Video/Audio codec type Type() CodecType // Video/Audio codec type
@ -179,15 +178,15 @@ type CodecData interface {
type VideoCodecData interface { type VideoCodecData interface {
CodecData CodecData
Width() int // Video width Width() int // Video width
Height() int // Video height Height() int // Video height
} }
type AudioCodecData interface { type AudioCodecData interface {
CodecData CodecData
SampleFormat() SampleFormat // audio sample format SampleFormat() SampleFormat // audio sample format
SampleRate() int // audio sample rate SampleRate() int // audio sample rate
ChannelLayout() ChannelLayout // audio channel layout ChannelLayout() ChannelLayout // audio channel layout
PacketDuration([]byte) (time.Duration, error) // get audio compressed packet duration PacketDuration([]byte) (time.Duration, error) // get audio compressed packet duration
} }
@ -196,16 +195,16 @@ type PacketWriter interface {
} }
type PacketReader interface { type PacketReader interface {
ReadPacket() (Packet,error) ReadPacket() (Packet, error)
} }
// Muxer describes the steps of writing compressed audio/video packets into container formats like MP4/FLV/MPEG-TS. // Muxer describes the steps of writing compressed audio/video packets into container formats like MP4/FLV/MPEG-TS.
// //
// Container formats, rtmp.Conn, and transcode.Muxer implements Muxer interface. // Container formats, rtmp.Conn, and transcode.Muxer implements Muxer interface.
type Muxer interface { type Muxer interface {
WriteHeader([]CodecData) error // write the file header WriteHeader([]CodecData) error // write the file header
PacketWriter // write compressed audio/video packets PacketWriter // write compressed audio/video packets
WriteTrailer() error // finish writing file, this func can be called only once WriteTrailer() error // finish writing file, this func can be called only once
} }
// Muxer with Close() method // Muxer with Close() method
@ -216,7 +215,7 @@ type MuxCloser interface {
// Demuxer can read compressed audio/video packets from container formats like MP4/FLV/MPEG-TS. // Demuxer can read compressed audio/video packets from container formats like MP4/FLV/MPEG-TS.
type Demuxer interface { type Demuxer interface {
PacketReader // read compressed audio/video packets PacketReader // read compressed audio/video packets
Streams() ([]CodecData, error) // reads the file header, contains video/audio meta infomations Streams() ([]CodecData, error) // reads the file header, contains video/audio meta infomations
} }
@ -228,20 +227,20 @@ type DemuxCloser interface {
// Packet stores compressed audio/video data. // Packet stores compressed audio/video data.
type Packet struct { type Packet struct {
IsKeyFrame bool // video packet is key frame IsKeyFrame bool // video packet is key frame
Idx int8 // stream index in container format Idx int8 // stream index in container format
CompositionTime time.Duration // packet presentation time minus decode time for H264 B-Frame CompositionTime time.Duration // packet presentation time minus decode time for H264 B-Frame
Time time.Duration // packet decode time Time time.Duration // packet decode time
Data []byte // packet data Data []byte // packet data
} }
// Raw audio frame. // Raw audio frame.
type AudioFrame struct { type AudioFrame struct {
SampleFormat SampleFormat // audio sample format, e.g: S16,FLTP,... SampleFormat SampleFormat // audio sample format, e.g: S16,FLTP,...
ChannelLayout ChannelLayout // audio channel layout, e.g: CH_MONO,CH_STEREO,... ChannelLayout ChannelLayout // audio channel layout, e.g: CH_MONO,CH_STEREO,...
SampleCount int // sample count in this frame SampleCount int // sample count in this frame
SampleRate int // sample rate SampleRate int // sample rate
Data [][]byte // data array for planar format len(Data) > 1 Data [][]byte // data array for planar format len(Data) > 1
} }
func (self AudioFrame) Duration() time.Duration { func (self AudioFrame) Duration() time.Duration {
@ -291,26 +290,25 @@ func (self AudioFrame) Concat(in AudioFrame) (out AudioFrame) {
// AudioEncoder can encode raw audio frame into compressed audio packets. // AudioEncoder can encode raw audio frame into compressed audio packets.
// cgo/ffmpeg inplements AudioEncoder, using ffmpeg.NewAudioEncoder to create it. // cgo/ffmpeg inplements AudioEncoder, using ffmpeg.NewAudioEncoder to create it.
type AudioEncoder interface { type AudioEncoder interface {
CodecData() (AudioCodecData, error) // encoder's codec data can put into container CodecData() (AudioCodecData, error) // encoder's codec data can put into container
Encode(AudioFrame) ([][]byte, error) // encode raw audio frame into compressed pakcet(s) Encode(AudioFrame) ([][]byte, error) // encode raw audio frame into compressed pakcet(s)
Close() // close encoder, free cgo contexts Close() // close encoder, free cgo contexts
SetSampleRate(int) (error) // set encoder sample rate SetSampleRate(int) error // set encoder sample rate
SetChannelLayout(ChannelLayout) (error) // set encoder channel layout SetChannelLayout(ChannelLayout) error // set encoder channel layout
SetSampleFormat(SampleFormat) (error) // set encoder sample format SetSampleFormat(SampleFormat) error // set encoder sample format
SetBitrate(int) (error) // set encoder bitrate SetBitrate(int) error // set encoder bitrate
SetOption(string,interface{}) (error) // encoder setopt, in ffmpeg is av_opt_set_dict() SetOption(string, interface{}) error // encoder setopt, in ffmpeg is av_opt_set_dict()
GetOption(string,interface{}) (error) // encoder getopt GetOption(string, interface{}) error // encoder getopt
} }
// AudioDecoder can decode compressed audio packets into raw audio frame. // AudioDecoder can decode compressed audio packets into raw audio frame.
// use ffmpeg.NewAudioDecoder to create it. // use ffmpeg.NewAudioDecoder to create it.
type AudioDecoder interface { type AudioDecoder interface {
Decode([]byte) (bool, AudioFrame, error) // decode one compressed audio packet Decode([]byte) (bool, AudioFrame, error) // decode one compressed audio packet
Close() // close decode, free cgo contexts Close() // close decode, free cgo contexts
} }
// AudioResampler can convert raw audio frames in different sample rate/format/channel layout. // AudioResampler can convert raw audio frames in different sample rate/format/channel layout.
type AudioResampler interface { type AudioResampler interface {
Resample(AudioFrame) (AudioFrame, error) // convert raw audio frames Resample(AudioFrame) (AudioFrame, error) // convert raw audio frames
} }

View File

@ -120,7 +120,7 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) {
if (i2.AVType != VIDEO && i2.AVType != AUDIO) || (client.options.DisableAudio && i2.AVType == AUDIO) { if (i2.AVType != VIDEO && i2.AVType != AUDIO) || (client.options.DisableAudio && i2.AVType == AUDIO) {
continue continue
} }
err = client.request(SETUP, map[string]string{"Transport": "RTP/AVP/TCP;unicast;interleaved=" + strconv.Itoa(ch) + "-" + strconv.Itoa(ch+1)}, client.control+i2.Control, false, false) err = client.request(SETUP, map[string]string{"Transport": "RTP/AVP/TCP;unicast;interleaved=" + strconv.Itoa(ch) + "-" + strconv.Itoa(ch+1)}, client.ControlTrack(i2.Control), false, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -150,6 +150,13 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) {
return client, nil return client, nil
} }
func (client *RTSPClient) ControlTrack(track string) string {
if strings.Contains(track, "rtsp://") {
return track
}
return client.control + track
}
func (client *RTSPClient) startStream() { func (client *RTSPClient) startStream() {
defer func() { defer func() {
client.Signals <- SignalStreamRTPStop client.Signals <- SignalStreamRTPStop
@ -469,7 +476,6 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
switch { switch {
case naluType >= 1 && naluType <= 5: case naluType >= 1 && naluType <= 5:
client.Println("Fix Stream IDX") client.Println("Fix Stream IDX")
retmap = append(retmap, &av.Packet{ retmap = append(retmap, &av.Packet{
Data: append(binSize(len(nal)), nal...), Data: append(binSize(len(nal)), nal...),
CompositionTime: time.Duration(1) * time.Millisecond, CompositionTime: time.Duration(1) * time.Millisecond,
@ -527,7 +533,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) {
func (client *RTSPClient) CodecUpdateSPS(val []byte) { func (client *RTSPClient) CodecUpdateSPS(val []byte) {
if bytes.Compare(val, client.sps) != 0 { if bytes.Compare(val, client.sps) != 0 {
if len(client.sps) > 0 && len(client.pps) > 0 { if len(client.sps) > 0 && len(client.pps) > 0 {
codecData, err := h264parser.NewCodecDataFromSPSAndPPS(client.sps, client.pps) codecData, err := h264parser.NewCodecDataFromSPSAndPPS(val, client.pps)
if err != nil { if err != nil {
client.Println("Parse Codec Data Error", err) client.Println("Parse Codec Data Error", err)
return return
@ -550,7 +556,7 @@ func (client *RTSPClient) CodecUpdateSPS(val []byte) {
func (client *RTSPClient) CodecUpdatePPS(val []byte) { func (client *RTSPClient) CodecUpdatePPS(val []byte) {
if bytes.Compare(val, client.pps) != 0 { if bytes.Compare(val, client.pps) != 0 {
if len(client.sps) > 0 && len(client.pps) > 0 { if len(client.sps) > 0 && len(client.pps) > 0 {
codecData, err := h264parser.NewCodecDataFromSPSAndPPS(client.sps, client.pps) codecData, err := h264parser.NewCodecDataFromSPSAndPPS(client.sps, val)
if err != nil { if err != nil {
client.Println("Parse Codec Data Error", err) client.Println("Parse Codec Data Error", err)
return return