123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- package mpeg2
- import (
- "github.com/yapingcat/gomedia/codec"
- )
- type psstream struct {
- sid uint8
- cid PS_STREAM_TYPE
- pts uint64
- dts uint64
- streamBuf []byte
- }
- func newpsstream(sid uint8, cid PS_STREAM_TYPE) *psstream {
- return &psstream{
- sid: sid,
- cid: cid,
- streamBuf: make([]byte, 0, 4096),
- }
- }
- type PSDemuxer struct {
- streamMap map[uint8]*psstream
- pkg *PSPacket
- mpeg1 bool
- cache []byte
- OnFrame func(frame []byte, cid PS_STREAM_TYPE, pts uint64, dts uint64)
- //解ps包过程中,解码回调psm,system header,pes包等
- //decodeResult 解码ps包时的产生的错误
- //这个回调主要用于debug,查看是否ps包存在问题
- OnPacket func(pkg Display, decodeResult error)
- }
- func NewPSDemuxer() *PSDemuxer {
- return &PSDemuxer{
- streamMap: make(map[uint8]*psstream),
- pkg: new(PSPacket),
- cache: make([]byte, 0, 256),
- OnFrame: nil,
- OnPacket: nil,
- }
- }
- func (psdemuxer *PSDemuxer) Input(data []byte) error {
- var bs *codec.BitStream
- if len(psdemuxer.cache) > 0 {
- psdemuxer.cache = append(psdemuxer.cache, data...)
- bs = codec.NewBitStream(psdemuxer.cache)
- } else {
- bs = codec.NewBitStream(data)
- }
- saveReseved := func() {
- tmpcache := make([]byte, bs.RemainBytes())
- copy(tmpcache, bs.RemainData())
- psdemuxer.cache = tmpcache
- }
- var ret error = nil
- for !bs.EOS() {
- if mpegerr, ok := ret.(Error); ok {
- if mpegerr.NeedMore() {
- saveReseved()
- }
- break
- }
- if bs.RemainBits() < 32 {
- ret = errNeedMore
- saveReseved()
- break
- }
- prefix_code := bs.NextBits(32)
- switch prefix_code {
- case 0x000001BA: //pack header
- if psdemuxer.pkg.Header == nil {
- psdemuxer.pkg.Header = new(PSPackHeader)
- }
- ret = psdemuxer.pkg.Header.Decode(bs)
- psdemuxer.mpeg1 = psdemuxer.pkg.Header.IsMpeg1
- if psdemuxer.OnPacket != nil {
- psdemuxer.OnPacket(psdemuxer.pkg.Header, ret)
- }
- case 0x000001BB: //system header
- if psdemuxer.pkg.Header == nil {
- panic("psdemuxer.pkg.Header must not be nil")
- }
- if psdemuxer.pkg.System == nil {
- psdemuxer.pkg.System = new(System_header)
- }
- ret = psdemuxer.pkg.System.Decode(bs)
- if psdemuxer.OnPacket != nil {
- psdemuxer.OnPacket(psdemuxer.pkg.System, ret)
- }
- case 0x000001BC: //program stream map
- if psdemuxer.pkg.Psm == nil {
- psdemuxer.pkg.Psm = new(Program_stream_map)
- }
- if ret = psdemuxer.pkg.Psm.Decode(bs); ret == nil {
- for _, streaminfo := range psdemuxer.pkg.Psm.Stream_map {
- if _, found := psdemuxer.streamMap[streaminfo.Elementary_stream_id]; !found {
- stream := newpsstream(streaminfo.Elementary_stream_id, PS_STREAM_TYPE(streaminfo.Stream_type))
- psdemuxer.streamMap[stream.sid] = stream
- }
- }
- }
- if psdemuxer.OnPacket != nil {
- psdemuxer.OnPacket(psdemuxer.pkg.Psm, ret)
- }
- case 0x000001BD, 0x000001BE, 0x000001BF, 0x000001F0, 0x000001F1,
- 0x000001F2, 0x000001F3, 0x000001F4, 0x000001F5, 0x000001F6,
- 0x000001F7, 0x000001F8, 0x000001F9, 0x000001FA, 0x000001FB:
- if psdemuxer.pkg.CommPes == nil {
- psdemuxer.pkg.CommPes = new(CommonPesPacket)
- }
- ret = psdemuxer.pkg.CommPes.Decode(bs)
- case 0x000001FF: //program stream directory
- if psdemuxer.pkg.Psd == nil {
- psdemuxer.pkg.Psd = new(Program_stream_directory)
- }
- ret = psdemuxer.pkg.Psd.Decode(bs)
- case 0x000001B9: //MPEG_program_end_code
- continue
- default:
- if prefix_code&0xFFFFFFE0 == 0x000001C0 || prefix_code&0xFFFFFFE0 == 0x000001E0 {
- if psdemuxer.pkg.Pes == nil {
- psdemuxer.pkg.Pes = NewPesPacket()
- }
- if psdemuxer.mpeg1 {
- ret = psdemuxer.pkg.Pes.DecodeMpeg1(bs)
- } else {
- ret = psdemuxer.pkg.Pes.Decode(bs)
- }
- if psdemuxer.OnPacket != nil {
- psdemuxer.OnPacket(psdemuxer.pkg.Pes, ret)
- }
- if ret == nil {
- if stream, found := psdemuxer.streamMap[psdemuxer.pkg.Pes.Stream_id]; found {
- if psdemuxer.mpeg1 && stream.cid == PS_STREAM_UNKNOW {
- psdemuxer.guessCodecid(stream)
- }
- psdemuxer.demuxPespacket(stream, psdemuxer.pkg.Pes)
- } else {
- if psdemuxer.mpeg1 {
- stream := newpsstream(psdemuxer.pkg.Pes.Stream_id, PS_STREAM_UNKNOW)
- psdemuxer.streamMap[stream.sid] = stream
- stream.streamBuf = append(stream.streamBuf, psdemuxer.pkg.Pes.Pes_payload...)
- stream.pts = psdemuxer.pkg.Pes.Pts
- stream.dts = psdemuxer.pkg.Pes.Dts
- }
- }
- }
- } else {
- bs.SkipBits(8)
- }
- }
- }
- if ret == nil && len(psdemuxer.cache) > 0 {
- psdemuxer.cache = nil
- }
- return ret
- }
- func (psdemuxer *PSDemuxer) Flush() {
- for _, stream := range psdemuxer.streamMap {
- if len(stream.streamBuf) == 0 {
- continue
- }
- if psdemuxer.OnFrame != nil {
- psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90)
- }
- }
- }
- func (psdemuxer *PSDemuxer) guessCodecid(stream *psstream) {
- if stream.sid&0xE0 == uint8(PES_STREAM_AUDIO) {
- stream.cid = PS_STREAM_AAC
- } else if stream.sid&0xE0 == uint8(PES_STREAM_VIDEO) {
- h264score := 0
- h265score := 0
- codec.SplitFrame(stream.streamBuf, func(nalu []byte) bool {
- h264nalutype := codec.H264NaluTypeWithoutStartCode(nalu)
- h265nalutype := codec.H265NaluTypeWithoutStartCode(nalu)
- if h264nalutype == codec.H264_NAL_PPS ||
- h264nalutype == codec.H264_NAL_SPS ||
- h264nalutype == codec.H264_NAL_I_SLICE {
- h264score += 2
- } else if h264nalutype < 5 {
- h264score += 1
- } else if h264nalutype > 20 {
- h264score -= 1
- }
- if h265nalutype == codec.H265_NAL_PPS ||
- h265nalutype == codec.H265_NAL_SPS ||
- h265nalutype == codec.H265_NAL_VPS ||
- (h265nalutype >= codec.H265_NAL_SLICE_BLA_W_LP && h265nalutype <= codec.H265_NAL_SLICE_CRA) {
- h265score += 2
- } else if h265nalutype >= codec.H265_NAL_Slice_TRAIL_N && h265nalutype <= codec.H265_NAL_SLICE_RASL_R {
- h265score += 1
- } else if h265nalutype > 40 {
- h265score -= 1
- }
- if h264score > h265score && h264score >= 4 {
- stream.cid = PS_STREAM_H264
- } else if h264score < h265score && h265score >= 4 {
- stream.cid = PS_STREAM_H265
- }
- return true
- })
- }
- }
- func (psdemuxer *PSDemuxer) demuxPespacket(stream *psstream, pes *PesPacket) error {
- switch stream.cid {
- case PS_STREAM_AAC, PS_STREAM_G711A, PS_STREAM_G711U:
- return psdemuxer.demuxAudio(stream, pes)
- case PS_STREAM_H264, PS_STREAM_H265:
- return psdemuxer.demuxH26x(stream, pes)
- case PS_STREAM_UNKNOW:
- if stream.pts != pes.Pts {
- stream.streamBuf = nil
- }
- stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
- stream.pts = pes.Pts
- stream.dts = pes.Dts
- }
- return nil
- }
- func (psdemuxer *PSDemuxer) demuxAudio(stream *psstream, pes *PesPacket) error {
- if stream.pts != pes.Pts && len(stream.streamBuf) > 0 {
- if psdemuxer.OnFrame != nil {
- psdemuxer.OnFrame(stream.streamBuf, stream.cid, stream.pts/90, stream.dts/90)
- }
- stream.streamBuf = stream.streamBuf[:0]
- }
- stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
- stream.pts = pes.Pts
- stream.dts = pes.Dts
- return nil
- }
- func (psdemuxer *PSDemuxer) demuxH26x(stream *psstream, pes *PesPacket) error {
- if len(stream.streamBuf) == 0 {
- stream.pts = pes.Pts
- stream.dts = pes.Dts
- }
- stream.streamBuf = append(stream.streamBuf, pes.Pes_payload...)
- start, sc := codec.FindStartCode(stream.streamBuf, 0)
- for start >= 0 {
- end, sc2 := codec.FindStartCode(stream.streamBuf, start+int(sc))
- if end < 0 {
- break
- }
- if stream.cid == PS_STREAM_H264 {
- naluType := codec.H264NaluType(stream.streamBuf[start:])
- if naluType != codec.H264_NAL_AUD {
- if psdemuxer.OnFrame != nil {
- psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90)
- }
- }
- } else if stream.cid == PS_STREAM_H265 {
- naluType := codec.H265NaluType(stream.streamBuf[start:])
- if naluType != codec.H265_NAL_AUD {
- if psdemuxer.OnFrame != nil {
- psdemuxer.OnFrame(stream.streamBuf[start:end], stream.cid, stream.pts/90, stream.dts/90)
- }
- }
- }
- start = end
- sc = sc2
- }
- stream.streamBuf = stream.streamBuf[start:]
- stream.pts = pes.Pts
- stream.dts = pes.Dts
- return nil
- }
|