add pcm and fix audio rtsp v2
This commit is contained in:
		
							
								
								
									
										4
									
								
								av/av.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								av/av.go
									
									
									
									
									
								
							| @@ -116,11 +116,13 @@ type CodecType uint32 | |||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	H264       = MakeVideoCodecType(avCodecTypeMagic + 1) | 	H264       = MakeVideoCodecType(avCodecTypeMagic + 1) | ||||||
|  | 	H265       = MakeVideoCodecType(avCodecTypeMagic + 2) | ||||||
| 	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) | ||||||
|  | 	PCM        = MakeAudioCodecType(avCodecTypeMagic + 6) | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const codecTypeAudioBit = 0x1 | const codecTypeAudioBit = 0x1 | ||||||
| @@ -140,6 +142,8 @@ func (self CodecType) String() string { | |||||||
| 		return "SPEEX" | 		return "SPEEX" | ||||||
| 	case NELLYMOSER: | 	case NELLYMOSER: | ||||||
| 		return "NELLYMOSER" | 		return "NELLYMOSER" | ||||||
|  | 	case PCM: | ||||||
|  | 		return "PCM" | ||||||
| 	} | 	} | ||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -37,6 +37,12 @@ func NewPCMMulawCodecData() av.AudioCodecData { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func NewPCMCodecData() av.AudioCodecData { | ||||||
|  | 	return PCMUCodecData{ | ||||||
|  | 		typ: av.PCM, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func NewPCMAlawCodecData() av.AudioCodecData { | func NewPCMAlawCodecData() av.AudioCodecData { | ||||||
| 	return PCMUCodecData{ | 	return PCMUCodecData{ | ||||||
| 		typ: av.PCM_ALAW, | 		typ: av.PCM_ALAW, | ||||||
|   | |||||||
| @@ -47,6 +47,12 @@ func Parse(content string) (sess Session, medias []Media) { | |||||||
| 						if len(mfields) >= 3 { | 						if len(mfields) >= 3 { | ||||||
| 							media.PayloadType, _ = strconv.Atoi(mfields[2]) | 							media.PayloadType, _ = strconv.Atoi(mfields[2]) | ||||||
| 						} | 						} | ||||||
|  | 						switch media.PayloadType { | ||||||
|  | 						case 0: | ||||||
|  | 							media.Type = av.PCM_MULAW | ||||||
|  | 						case 8: | ||||||
|  | 							media.Type = av.PCM_ALAW | ||||||
|  | 						} | ||||||
| 					default: | 					default: | ||||||
| 						media = nil | 						media = nil | ||||||
| 					} | 					} | ||||||
| @@ -75,6 +81,8 @@ func Parse(content string) (sess Session, medias []Media) { | |||||||
| 							switch strings.ToUpper(key) { | 							switch strings.ToUpper(key) { | ||||||
| 							case "MPEG4-GENERIC": | 							case "MPEG4-GENERIC": | ||||||
| 								media.Type = av.AAC | 								media.Type = av.AAC | ||||||
|  | 							case "L16": | ||||||
|  | 								media.Type = av.PCM | ||||||
| 							case "H264": | 							case "H264": | ||||||
| 								media.Type = av.H264 | 								media.Type = av.H264 | ||||||
| 							} | 							} | ||||||
|   | |||||||
| @@ -18,6 +18,8 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
| 	"github.com/deepch/vdk/av" | 	"github.com/deepch/vdk/av" | ||||||
|  | 	"github.com/deepch/vdk/codec" | ||||||
|  | 	"github.com/deepch/vdk/codec/aacparser" | ||||||
| 	"github.com/deepch/vdk/codec/h264parser" | 	"github.com/deepch/vdk/codec/h264parser" | ||||||
| 	"github.com/deepch/vdk/format/rtsp/sdp" | 	"github.com/deepch/vdk/format/rtsp/sdp" | ||||||
| ) | ) | ||||||
| @@ -54,6 +56,8 @@ type RTSPClient struct { | |||||||
| 	startAudioTS        int64 | 	startAudioTS        int64 | ||||||
| 	videoID             int | 	videoID             int | ||||||
| 	audioID             int | 	audioID             int | ||||||
|  | 	videoIDX            int8 | ||||||
|  | 	audioIDX            int8 | ||||||
| 	mediaSDP            []sdp.Media | 	mediaSDP            []sdp.Media | ||||||
| 	SDPRaw              []byte | 	SDPRaw              []byte | ||||||
| 	conn                net.Conn | 	conn                net.Conn | ||||||
| @@ -71,6 +75,7 @@ type RTSPClient struct { | |||||||
| 	sps                 []byte | 	sps                 []byte | ||||||
| 	pps                 []byte | 	pps                 []byte | ||||||
| 	CodecData           []av.CodecData | 	CodecData           []av.CodecData | ||||||
|  | 	PCMTime             int64 | ||||||
| } | } | ||||||
|  |  | ||||||
| type RTSPClientOptions struct { | type RTSPClientOptions struct { | ||||||
| @@ -91,6 +96,8 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) { | |||||||
| 		BufferRtpPacket:     bytes.NewBuffer([]byte{}), | 		BufferRtpPacket:     bytes.NewBuffer([]byte{}), | ||||||
| 		videoID:             0, | 		videoID:             0, | ||||||
| 		audioID:             2, | 		audioID:             2, | ||||||
|  | 		videoIDX:            0, | ||||||
|  | 		audioIDX:            1, | ||||||
| 		options:             options, | 		options:             options, | ||||||
| 	} | 	} | ||||||
| 	client.headers["User-Agent"] = "Lavf58.20.100" | 	client.headers["User-Agent"] = "Lavf58.20.100" | ||||||
| @@ -131,6 +138,7 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) { | |||||||
| 					client.sps = i2.SpropParameterSets[0] | 					client.sps = i2.SpropParameterSets[0] | ||||||
| 					client.pps = i2.SpropParameterSets[1] | 					client.pps = i2.SpropParameterSets[1] | ||||||
| 					client.CodecData = append(client.CodecData, codecData) | 					client.CodecData = append(client.CodecData, codecData) | ||||||
|  | 					client.videoIDX = int8(len(client.CodecData) - 1) | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				client.Println("SDP Video Codec Type Not Supported", i2.Type) | 				client.Println("SDP Video Codec Type Not Supported", i2.Type) | ||||||
| @@ -139,6 +147,26 @@ func Dial(options RTSPClientOptions) (*RTSPClient, error) { | |||||||
| 		} | 		} | ||||||
| 		if i2.AVType == AUDIO { | 		if i2.AVType == AUDIO { | ||||||
| 			client.audioID = ch | 			client.audioID = ch | ||||||
|  | 			var CodecData av.AudioCodecData | ||||||
|  | 			switch i2.Type { | ||||||
|  | 			case av.AAC: | ||||||
|  | 				CodecData, err = aacparser.NewCodecDataFromMPEG4AudioConfigBytes(i2.Config) | ||||||
|  | 				if err == nil { | ||||||
|  | 					client.Println("Audio AAC bad config") | ||||||
|  | 				} | ||||||
|  | 			case av.PCM_MULAW: | ||||||
|  | 				CodecData = codec.NewPCMMulawCodecData() | ||||||
|  | 			case av.PCM_ALAW: | ||||||
|  | 				CodecData = codec.NewPCMMulawCodecData() | ||||||
|  | 			case av.PCM: | ||||||
|  | 				CodecData = codec.NewPCMCodecData() | ||||||
|  | 			default: | ||||||
|  | 				client.Println("Audio Codec", i2.Type, "not supported") | ||||||
|  | 			} | ||||||
|  | 			if CodecData != nil { | ||||||
|  | 				client.CodecData = append(client.CodecData, CodecData) | ||||||
|  | 				client.audioIDX = int8(len(client.CodecData) - 1) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		ch += 2 | 		ch += 2 | ||||||
| 	} | 	} | ||||||
| @@ -481,7 +509,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { | |||||||
| 				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, | ||||||
| 					Idx:             0, | 					Idx:             client.videoIDX, | ||||||
| 					IsKeyFrame:      naluType == 5, | 					IsKeyFrame:      naluType == 5, | ||||||
| 					Time:            time.Duration(timestamp/90) * time.Millisecond, | 					Time:            time.Duration(timestamp/90) * time.Millisecond, | ||||||
| 				}) | 				}) | ||||||
| @@ -510,7 +538,7 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { | |||||||
| 						retmap = append(retmap, &av.Packet{ | 						retmap = append(retmap, &av.Packet{ | ||||||
| 							Data:            append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), | 							Data:            append(binSize(client.BufferRtpPacket.Len()), client.BufferRtpPacket.Bytes()...), | ||||||
| 							CompositionTime: time.Duration(1) * time.Millisecond, | 							CompositionTime: time.Duration(1) * time.Millisecond, | ||||||
| 							Idx:             0, | 							Idx:             client.videoIDX, | ||||||
| 							IsKeyFrame:      naluTypef == 5, | 							IsKeyFrame:      naluTypef == 5, | ||||||
| 							Time:            time.Duration(timestamp/90) * time.Millisecond, | 							Time:            time.Duration(timestamp/90) * time.Millisecond, | ||||||
| 						}) | 						}) | ||||||
| @@ -525,7 +553,21 @@ func (client *RTSPClient) RTPDemuxer(payloadRAW *[]byte) ([]*av.Packet, bool) { | |||||||
| 			return retmap, true | 			return retmap, true | ||||||
| 		} | 		} | ||||||
| 	case client.audioID: | 	case client.audioID: | ||||||
| 		client.Println("Audio Unsupported try report to https://github.com/deepch/vdk", padding, extension, timestamp) | 		nalRaw, _ := h264parser.SplitNALUs(content[offset:end]) | ||||||
|  | 		var retmap []*av.Packet | ||||||
|  | 		for _, nal := range nalRaw { | ||||||
|  | 			//client.PCMTime += int64(float32(1000) / (float32(8000) / float32(len(nal)))) | ||||||
|  | 			retmap = append(retmap, &av.Packet{ | ||||||
|  | 				Data:            append(binSize(len(nal)), nal...), | ||||||
|  | 				CompositionTime: time.Duration(1) * time.Millisecond, | ||||||
|  | 				Idx:             client.audioIDX, | ||||||
|  | 				IsKeyFrame:      false, | ||||||
|  | 				Time:            time.Duration(timestamp/8) * time.Millisecond, | ||||||
|  | 			}) | ||||||
|  | 		} | ||||||
|  | 		if len(retmap) > 0 { | ||||||
|  | 			return retmap, true | ||||||
|  | 		} | ||||||
| 	default: | 	default: | ||||||
| 		client.Println("Unsuported Intervaled data packet", int(content[1]), content[offset:end]) | 		client.Println("Unsuported Intervaled data packet", int(content[1]), content[offset:end]) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ var ( | |||||||
| 	ErrorCodecNotSupported = errors.New("WebRTC Codec Not Supported") | 	ErrorCodecNotSupported = errors.New("WebRTC Codec Not Supported") | ||||||
| 	ErrorClientOffline     = errors.New("WebRTC Client Offline") | 	ErrorClientOffline     = errors.New("WebRTC Client Offline") | ||||||
| 	ErrorNotTrackAvailable = errors.New("WebRTC Not Track Available") | 	ErrorNotTrackAvailable = errors.New("WebRTC Not Track Available") | ||||||
| 	ErrorIgnoreAudioTrack  = errors.New("WebRTC Ignore Audio Track codec not supported WebRTC") | 	ErrorIgnoreAudioTrack  = errors.New("WebRTC Ignore Audio Track codec not supported WebRTC support only PCM_ALAW or PCM_MULAW") | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type Muxer struct { | type Muxer struct { | ||||||
| @@ -192,7 +192,7 @@ func (element *Muxer) WritePacket(pkt av.Packet) (err error) { | |||||||
| 		default: | 		default: | ||||||
| 			return ErrorCodecNotSupported | 			return ErrorCodecNotSupported | ||||||
| 		} | 		} | ||||||
| 		err = tmp.track.WriteSample(media.Sample{Data: pkt.Data, Duration: pkt.Time - tmp.ts}) | 		err = tmp.track.WriteSample(media.Sample{Data: pkt.Data, Duration: pkt.Time - element.streams[pkt.Idx].ts}) | ||||||
| 		if err == nil { | 		if err == nil { | ||||||
| 			element.streams[pkt.Idx].ts = pkt.Time | 			element.streams[pkt.Idx].ts = pkt.Time | ||||||
| 			WritePacketSuccess = true | 			WritePacketSuccess = true | ||||||
| @@ -213,8 +213,10 @@ func (element *Muxer) WaitCloser() { | |||||||
| 			} | 			} | ||||||
| 			waitT.Reset(time.Second * 10) | 			waitT.Reset(time.Second * 10) | ||||||
| 		case <-element.StreamACK.C: | 		case <-element.StreamACK.C: | ||||||
|  | 			log.Println("Stream Not Send Video Close") | ||||||
| 			element.Close() | 			element.Close() | ||||||
| 		case <-element.ClientACK.C: | 		case <-element.ClientACK.C: | ||||||
|  | 			log.Println("Client Not Send ACK (probably the browser is minimized) or tab not active Close client") | ||||||
| 			element.Close() | 			element.Close() | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Andrey Semochkin
					Andrey Semochkin