mirror of
https://github.com/lkmio/lkm.git
synced 2025-09-27 03:26:01 +08:00
220 lines
5.7 KiB
Go
220 lines
5.7 KiB
Go
package stream
|
||
|
||
import (
|
||
"github.com/yangjiechina/avformat"
|
||
"github.com/yangjiechina/avformat/utils"
|
||
"github.com/yangjiechina/live-server/transcode"
|
||
"time"
|
||
)
|
||
|
||
// SourceType Source 推流类型
|
||
type SourceType byte
|
||
|
||
// Protocol 输出协议
|
||
type Protocol uint32
|
||
|
||
const (
|
||
SourceTypeRtmp = SourceType(1)
|
||
SourceType28181 = SourceType(2)
|
||
SourceType1078 = SourceType(3)
|
||
|
||
ProtocolRtmp = Protocol(1)
|
||
ProtocolFlv = Protocol(2)
|
||
ProtocolRtsp = Protocol(3)
|
||
ProtocolHls = Protocol(4)
|
||
ProtocolRtc = Protocol(5)
|
||
)
|
||
|
||
// SessionState 推拉流Session状态
|
||
// 包含, 握手阶段、Hook授权.
|
||
type SessionState uint32
|
||
|
||
const (
|
||
SessionStateCreate = SessionState(1)
|
||
SessionStateHandshaking = SessionState(2)
|
||
SessionStateHandshakeFailure = SessionState(3)
|
||
SessionStateHandshakeDone = SessionState(4)
|
||
SessionStateTransferring = SessionState(5)
|
||
)
|
||
|
||
type ISource interface {
|
||
// Id Source的唯一ID/**
|
||
Id() string
|
||
|
||
// Input 输入推流数据
|
||
Input(data []byte)
|
||
|
||
// CreateTransDeMuxer 创建推流的解服用器
|
||
CreateTransDeMuxer() ITransDeMuxer
|
||
|
||
// CreateTranscoder 创建转码器
|
||
CreateTranscoder(src utils.AVStream, dst utils.AVStream) transcode.ITranscoder
|
||
|
||
// OriginStreams 返回推流的原始Streams
|
||
OriginStreams() []utils.AVStream
|
||
|
||
// TranscodeStreams 返回转码的Streams
|
||
TranscodeStreams() []utils.AVStream
|
||
|
||
// AddSink 添加Sink, 在此之前请确保Sink已经握手、授权通过. 如果Source还未WriteHeader,将Sink添加到等待队列.
|
||
// 匹配拉流的编码器, 创建TransMuxer或向存在TransMuxer添加Sink
|
||
AddSink(sink ISink) bool
|
||
|
||
// RemoveSink 删除Sink/**
|
||
RemoveSink(tid TransStreamId, sinkId string) bool
|
||
|
||
// Close 关闭Source
|
||
// 停止一切封装和转发流以及转码工作
|
||
// 将Sink添加到等待队列
|
||
Close()
|
||
}
|
||
|
||
type onSourceHandler interface {
|
||
onDeMuxStream(stream utils.AVStream)
|
||
}
|
||
|
||
type SourceImpl struct {
|
||
Id_ string
|
||
type_ SourceType
|
||
state SessionState
|
||
|
||
deMuxer ITransDeMuxer //负责从推流协议中解析出AVStream和AVPacket
|
||
recordSink ISink //每个Source唯一的一个录制流
|
||
audioTranscoders []transcode.ITranscoder //音频解码器
|
||
videoTranscoders []transcode.ITranscoder //视频解码器
|
||
originStreams StreamManager //推流的音视频Streams
|
||
allStreams StreamManager //推流Streams+转码器获得的Streams
|
||
|
||
completed bool
|
||
probeTimer *time.Timer
|
||
|
||
//所有的输出协议, 持有Sink
|
||
transStreams map[TransStreamId]ITransStream
|
||
}
|
||
|
||
func (s *SourceImpl) Id() string {
|
||
return s.Id_
|
||
}
|
||
|
||
func (s *SourceImpl) Input(data []byte) {
|
||
s.deMuxer.Input(data)
|
||
}
|
||
|
||
func (s *SourceImpl) CreateTransDeMuxer() ITransDeMuxer {
|
||
//TODO implement me
|
||
panic("implement me")
|
||
}
|
||
|
||
func (s *SourceImpl) CreateTranscoder(src utils.AVStream, dst utils.AVStream) transcode.ITranscoder {
|
||
//TODO implement me
|
||
panic("implement me")
|
||
}
|
||
|
||
func (s *SourceImpl) OriginStreams() []utils.AVStream {
|
||
return s.originStreams.All()
|
||
}
|
||
|
||
func (s *SourceImpl) TranscodeStreams() []utils.AVStream {
|
||
return s.allStreams.All()
|
||
}
|
||
|
||
func IsSupportMux(protocol Protocol, audioCodecId, videoCodecId utils.AVCodecID) bool {
|
||
if ProtocolRtmp == protocol || ProtocolFlv == protocol {
|
||
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
func (s *SourceImpl) AddSink(sink ISink) bool {
|
||
// 暂时不考虑多路视频流,意味着只能1路视频流和多路音频流,同理originStreams和allStreams里面的Stream互斥. 同时多路音频流的Codec必须一致
|
||
audioCodecId, videoCodecId := sink.DesiredAudioCodecId(), sink.DesiredVideoCodecId()
|
||
audioStream := s.originStreams.FindStreamWithType(utils.AVMediaTypeAudio)
|
||
videoStream := s.originStreams.FindStreamWithType(utils.AVMediaTypeVideo)
|
||
|
||
disableAudio := audioStream == nil
|
||
disableVideo := videoStream == nil || !sink.EnableVideo()
|
||
if disableAudio && disableVideo {
|
||
return false
|
||
}
|
||
|
||
//不支持对期望编码的流封装. 降级
|
||
if (utils.AVCodecIdNONE != audioCodecId || utils.AVCodecIdNONE != videoCodecId) && !IsSupportMux(sink.Protocol(), audioCodecId, videoCodecId) {
|
||
audioCodecId = utils.AVCodecIdNONE
|
||
videoCodecId = utils.AVCodecIdNONE
|
||
}
|
||
|
||
if !disableAudio && utils.AVCodecIdNONE == audioCodecId {
|
||
audioCodecId = audioStream.CodecId()
|
||
}
|
||
if !disableVideo && utils.AVCodecIdNONE == videoCodecId {
|
||
videoCodecId = videoStream.CodecId()
|
||
}
|
||
|
||
//创建音频转码器
|
||
if !disableAudio && audioCodecId != audioStream.CodecId() {
|
||
avformat.Assert(false)
|
||
}
|
||
|
||
//创建视频转码器
|
||
if !disableVideo && videoCodecId != videoStream.CodecId() {
|
||
avformat.Assert(false)
|
||
}
|
||
|
||
var streams [5]utils.AVStream
|
||
var index int
|
||
for _, stream := range s.originStreams.All() {
|
||
if disableVideo && stream.Type() == utils.AVMediaTypeVideo {
|
||
continue
|
||
}
|
||
|
||
streams[index] = stream
|
||
index++
|
||
}
|
||
|
||
//transStreamId := GenerateTransStreamId(sink.Protocol(), streams[:]...)
|
||
TransStreamFactory(sink.Protocol(), streams[:])
|
||
return false
|
||
}
|
||
|
||
func (s *SourceImpl) RemoveSink(tid TransStreamId, sinkId string) bool {
|
||
//TODO implement me
|
||
panic("implement me")
|
||
}
|
||
|
||
func (s *SourceImpl) Close() {
|
||
//TODO implement me
|
||
panic("implement me")
|
||
}
|
||
|
||
func (s *SourceImpl) OnDeMuxStream(stream utils.AVStream) {
|
||
s.originStreams.Add(stream)
|
||
s.allStreams.Add(stream)
|
||
if len(s.originStreams.All()) == 1 {
|
||
s.probeTimer = time.AfterFunc(time.Duration(AppConfig.ProbeTimeout)*time.Millisecond, s.writeHeader)
|
||
}
|
||
}
|
||
|
||
// 从DeMuxer解析完Stream后, 处理等待Sinks
|
||
func (s *SourceImpl) writeHeader() {
|
||
avformat.Assert(!s.completed)
|
||
s.probeTimer.Stop()
|
||
s.completed = true
|
||
|
||
sinks := PopWaitingSinks(s.Id_)
|
||
for _, sink := range sinks {
|
||
s.AddSink(sink)
|
||
}
|
||
}
|
||
|
||
func (s *SourceImpl) OnDeMuxStreamDone() {
|
||
s.writeHeader()
|
||
}
|
||
|
||
func (s *SourceImpl) OnDeMuxPacket(index int, packet utils.AVPacket) {
|
||
|
||
}
|
||
|
||
func (s *SourceImpl) OnDeMuxDone() {
|
||
}
|