fix codec and track
This commit is contained in:
parent
292592fcb5
commit
fccce247d0
86
av/av.go
86
av/av.go
@ -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)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -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,7 +195,7 @@ 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.
|
||||||
@ -204,8 +203,8 @@ type PacketReader interface {
|
|||||||
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user