mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
DVR: Support blackbox test based on hooks. v5.0.132 (#3365)
This commit is contained in:
parent
a27ce1d50f
commit
e655948e96
31 changed files with 4704 additions and 3925 deletions
596
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/pes-proto.go
generated
vendored
596
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/pes-proto.go
generated
vendored
|
@ -1,10 +1,10 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
var H264_AUD_NALU []byte = []byte{0x00, 0x00, 0x00, 0x01, 0x09, 0xF0} //ffmpeg mpegtsenc.c mpegts_write_packet_internal
|
||||
|
@ -13,337 +13,337 @@ var H265_AUD_NALU []byte = []byte{0x00, 0x00, 0x00, 0x01, 0x46, 0x01, 0x50}
|
|||
type PES_STREMA_ID int
|
||||
|
||||
const (
|
||||
PES_STREAM_END PES_STREMA_ID = 0xB9
|
||||
PES_STREAM_START PES_STREMA_ID = 0xBA
|
||||
PES_STREAM_SYSTEM_HEAD PES_STREMA_ID = 0xBB
|
||||
PES_STREAM_MAP PES_STREMA_ID = 0xBC
|
||||
PES_STREAM_PRIVATE PES_STREMA_ID = 0xBD
|
||||
PES_STREAM_AUDIO PES_STREMA_ID = 0xC0
|
||||
PES_STREAM_VIDEO PES_STREMA_ID = 0xE0
|
||||
PES_STREAM_END PES_STREMA_ID = 0xB9
|
||||
PES_STREAM_START PES_STREMA_ID = 0xBA
|
||||
PES_STREAM_SYSTEM_HEAD PES_STREMA_ID = 0xBB
|
||||
PES_STREAM_MAP PES_STREMA_ID = 0xBC
|
||||
PES_STREAM_PRIVATE PES_STREMA_ID = 0xBD
|
||||
PES_STREAM_AUDIO PES_STREMA_ID = 0xC0
|
||||
PES_STREAM_VIDEO PES_STREMA_ID = 0xE0
|
||||
)
|
||||
|
||||
func findPESIDByStreamType(cid TS_STREAM_TYPE) PES_STREMA_ID {
|
||||
if cid == TS_STREAM_AAC {
|
||||
return PES_STREAM_AUDIO
|
||||
} else if cid == TS_STREAM_H264 || cid == TS_STREAM_H265 {
|
||||
return PES_STREAM_VIDEO
|
||||
} else {
|
||||
return PES_STREAM_PRIVATE
|
||||
}
|
||||
if cid == TS_STREAM_AAC {
|
||||
return PES_STREAM_AUDIO
|
||||
} else if cid == TS_STREAM_H264 || cid == TS_STREAM_H265 {
|
||||
return PES_STREAM_VIDEO
|
||||
} else {
|
||||
return PES_STREAM_PRIVATE
|
||||
}
|
||||
}
|
||||
|
||||
type PesPacket struct {
|
||||
Stream_id uint8
|
||||
PES_packet_length uint16
|
||||
PES_scrambling_control uint8
|
||||
PES_priority uint8
|
||||
Data_alignment_indicator uint8
|
||||
Copyright uint8
|
||||
Original_or_copy uint8
|
||||
PTS_DTS_flags uint8
|
||||
ESCR_flag uint8
|
||||
ES_rate_flag uint8
|
||||
DSM_trick_mode_flag uint8
|
||||
Additional_copy_info_flag uint8
|
||||
PES_CRC_flag uint8
|
||||
PES_extension_flag uint8
|
||||
PES_header_data_length uint8
|
||||
Pts uint64
|
||||
Dts uint64
|
||||
ESCR_base uint64
|
||||
ESCR_extension uint16
|
||||
ES_rate uint32
|
||||
Trick_mode_control uint8
|
||||
Trick_value uint8
|
||||
Additional_copy_info uint8
|
||||
Previous_PES_packet_CRC uint16
|
||||
Pes_payload []byte
|
||||
//TODO
|
||||
//if ( PES_extension_flag == '1')
|
||||
// PES_private_data_flag uint8
|
||||
// pack_header_field_flag uint8
|
||||
// program_packet_sequence_counter_flag uint8
|
||||
// P_STD_buffer_flag uint8
|
||||
// PES_extension_flag_2 uint8
|
||||
// PES_private_data [16]byte
|
||||
Stream_id uint8
|
||||
PES_packet_length uint16
|
||||
PES_scrambling_control uint8
|
||||
PES_priority uint8
|
||||
Data_alignment_indicator uint8
|
||||
Copyright uint8
|
||||
Original_or_copy uint8
|
||||
PTS_DTS_flags uint8
|
||||
ESCR_flag uint8
|
||||
ES_rate_flag uint8
|
||||
DSM_trick_mode_flag uint8
|
||||
Additional_copy_info_flag uint8
|
||||
PES_CRC_flag uint8
|
||||
PES_extension_flag uint8
|
||||
PES_header_data_length uint8
|
||||
Pts uint64
|
||||
Dts uint64
|
||||
ESCR_base uint64
|
||||
ESCR_extension uint16
|
||||
ES_rate uint32
|
||||
Trick_mode_control uint8
|
||||
Trick_value uint8
|
||||
Additional_copy_info uint8
|
||||
Previous_PES_packet_CRC uint16
|
||||
Pes_payload []byte
|
||||
//TODO
|
||||
//if ( PES_extension_flag == '1')
|
||||
// PES_private_data_flag uint8
|
||||
// pack_header_field_flag uint8
|
||||
// program_packet_sequence_counter_flag uint8
|
||||
// P_STD_buffer_flag uint8
|
||||
// PES_extension_flag_2 uint8
|
||||
// PES_private_data [16]byte
|
||||
}
|
||||
|
||||
func NewPesPacket() *PesPacket {
|
||||
return new(PesPacket)
|
||||
return new(PesPacket)
|
||||
}
|
||||
|
||||
func (pkg *PesPacket) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("stream_id:%d\n", pkg.Stream_id))
|
||||
file.WriteString(fmt.Sprintf("PES_packet_length:%d\n", pkg.PES_packet_length))
|
||||
file.WriteString(fmt.Sprintf("PES_scrambling_control:%d\n", pkg.PES_scrambling_control))
|
||||
file.WriteString(fmt.Sprintf("PES_priority:%d\n", pkg.PES_priority))
|
||||
file.WriteString(fmt.Sprintf("data_alignment_indicator:%d\n", pkg.Data_alignment_indicator))
|
||||
file.WriteString(fmt.Sprintf("copyright:%d\n", pkg.Copyright))
|
||||
file.WriteString(fmt.Sprintf("original_or_copy:%d\n", pkg.Original_or_copy))
|
||||
file.WriteString(fmt.Sprintf("PTS_DTS_flags:%d\n", pkg.PTS_DTS_flags))
|
||||
file.WriteString(fmt.Sprintf("ESCR_flag:%d\n", pkg.ESCR_flag))
|
||||
file.WriteString(fmt.Sprintf("ES_rate_flag:%d\n", pkg.ES_rate_flag))
|
||||
file.WriteString(fmt.Sprintf("DSM_trick_mode_flag:%d\n", pkg.DSM_trick_mode_flag))
|
||||
file.WriteString(fmt.Sprintf("additional_copy_info_flag:%d\n", pkg.Additional_copy_info_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_CRC_flag:%d\n", pkg.PES_CRC_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_extension_flag:%d\n", pkg.PES_extension_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_header_data_length:%d\n", pkg.PES_header_data_length))
|
||||
if pkg.PTS_DTS_flags&0x02 == 0x02 {
|
||||
file.WriteString(fmt.Sprintf("PTS:%d\n", pkg.Pts))
|
||||
}
|
||||
if pkg.PTS_DTS_flags&0x03 == 0x03 {
|
||||
file.WriteString(fmt.Sprintf("DTS:%d\n", pkg.Dts))
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("stream_id:%d\n", pkg.Stream_id))
|
||||
file.WriteString(fmt.Sprintf("PES_packet_length:%d\n", pkg.PES_packet_length))
|
||||
file.WriteString(fmt.Sprintf("PES_scrambling_control:%d\n", pkg.PES_scrambling_control))
|
||||
file.WriteString(fmt.Sprintf("PES_priority:%d\n", pkg.PES_priority))
|
||||
file.WriteString(fmt.Sprintf("data_alignment_indicator:%d\n", pkg.Data_alignment_indicator))
|
||||
file.WriteString(fmt.Sprintf("copyright:%d\n", pkg.Copyright))
|
||||
file.WriteString(fmt.Sprintf("original_or_copy:%d\n", pkg.Original_or_copy))
|
||||
file.WriteString(fmt.Sprintf("PTS_DTS_flags:%d\n", pkg.PTS_DTS_flags))
|
||||
file.WriteString(fmt.Sprintf("ESCR_flag:%d\n", pkg.ESCR_flag))
|
||||
file.WriteString(fmt.Sprintf("ES_rate_flag:%d\n", pkg.ES_rate_flag))
|
||||
file.WriteString(fmt.Sprintf("DSM_trick_mode_flag:%d\n", pkg.DSM_trick_mode_flag))
|
||||
file.WriteString(fmt.Sprintf("additional_copy_info_flag:%d\n", pkg.Additional_copy_info_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_CRC_flag:%d\n", pkg.PES_CRC_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_extension_flag:%d\n", pkg.PES_extension_flag))
|
||||
file.WriteString(fmt.Sprintf("PES_header_data_length:%d\n", pkg.PES_header_data_length))
|
||||
if pkg.PTS_DTS_flags&0x02 == 0x02 {
|
||||
file.WriteString(fmt.Sprintf("PTS:%d\n", pkg.Pts))
|
||||
}
|
||||
if pkg.PTS_DTS_flags&0x03 == 0x03 {
|
||||
file.WriteString(fmt.Sprintf("DTS:%d\n", pkg.Dts))
|
||||
}
|
||||
|
||||
if pkg.ESCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("ESCR_base:%d\n", pkg.ESCR_base))
|
||||
file.WriteString(fmt.Sprintf("ESCR_extension:%d\n", pkg.ESCR_extension))
|
||||
}
|
||||
if pkg.ESCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("ESCR_base:%d\n", pkg.ESCR_base))
|
||||
file.WriteString(fmt.Sprintf("ESCR_extension:%d\n", pkg.ESCR_extension))
|
||||
}
|
||||
|
||||
if pkg.ES_rate_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("ES_rate:%d\n", pkg.ES_rate))
|
||||
}
|
||||
if pkg.ES_rate_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("ES_rate:%d\n", pkg.ES_rate))
|
||||
}
|
||||
|
||||
if pkg.DSM_trick_mode_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("trick_mode_control:%d\n", pkg.Trick_mode_control))
|
||||
}
|
||||
if pkg.DSM_trick_mode_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("trick_mode_control:%d\n", pkg.Trick_mode_control))
|
||||
}
|
||||
|
||||
if pkg.Additional_copy_info_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("additional_copy_info:%d\n", pkg.Additional_copy_info))
|
||||
}
|
||||
if pkg.Additional_copy_info_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("additional_copy_info:%d\n", pkg.Additional_copy_info))
|
||||
}
|
||||
|
||||
if pkg.PES_CRC_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("previous_PES_packet_CRC:%d\n", pkg.Previous_PES_packet_CRC))
|
||||
}
|
||||
file.WriteString("PES_packet_data_byte:\n")
|
||||
file.WriteString(fmt.Sprintf(" Size: %d\n", len(pkg.Pes_payload)))
|
||||
file.WriteString(" data:")
|
||||
for i := 0; i < 12 && i < len(pkg.Pes_payload); i++ {
|
||||
if i%4 == 0 {
|
||||
file.WriteString("\n")
|
||||
file.WriteString(" ")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("0x%02x ", pkg.Pes_payload[i]))
|
||||
}
|
||||
file.WriteString("\n")
|
||||
if pkg.PES_CRC_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("previous_PES_packet_CRC:%d\n", pkg.Previous_PES_packet_CRC))
|
||||
}
|
||||
file.WriteString("PES_packet_data_byte:\n")
|
||||
file.WriteString(fmt.Sprintf(" Size: %d\n", len(pkg.Pes_payload)))
|
||||
file.WriteString(" data:")
|
||||
for i := 0; i < 12 && i < len(pkg.Pes_payload); i++ {
|
||||
if i%4 == 0 {
|
||||
file.WriteString("\n")
|
||||
file.WriteString(" ")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("0x%02x ", pkg.Pes_payload[i]))
|
||||
}
|
||||
file.WriteString("\n")
|
||||
}
|
||||
|
||||
func (pkg *PesPacket) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 9 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24) //packet_start_code_prefix
|
||||
pkg.Stream_id = bs.Uint8(8) //stream_id
|
||||
pkg.PES_packet_length = bs.Uint16(16)
|
||||
bs.SkipBits(2) //'10'
|
||||
pkg.PES_scrambling_control = bs.Uint8(2)
|
||||
pkg.PES_priority = bs.Uint8(1)
|
||||
pkg.Data_alignment_indicator = bs.Uint8(1)
|
||||
pkg.Copyright = bs.Uint8(1)
|
||||
pkg.Original_or_copy = bs.Uint8(1)
|
||||
pkg.PTS_DTS_flags = bs.Uint8(2)
|
||||
pkg.ESCR_flag = bs.Uint8(1)
|
||||
pkg.ES_rate_flag = bs.Uint8(1)
|
||||
pkg.DSM_trick_mode_flag = bs.Uint8(1)
|
||||
pkg.Additional_copy_info_flag = bs.Uint8(1)
|
||||
pkg.PES_CRC_flag = bs.Uint8(1)
|
||||
pkg.PES_extension_flag = bs.Uint8(1)
|
||||
pkg.PES_header_data_length = bs.Uint8(8)
|
||||
if bs.RemainBytes() < int(pkg.PES_header_data_length) {
|
||||
bs.UnRead(9 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.Markdot()
|
||||
if pkg.PTS_DTS_flags&0x02 == 0x02 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
if pkg.PTS_DTS_flags&0x03 == 0x03 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Dts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else {
|
||||
pkg.Dts = pkg.Pts
|
||||
}
|
||||
if bs.RemainBytes() < 9 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24) //packet_start_code_prefix
|
||||
pkg.Stream_id = bs.Uint8(8) //stream_id
|
||||
pkg.PES_packet_length = bs.Uint16(16)
|
||||
bs.SkipBits(2) //'10'
|
||||
pkg.PES_scrambling_control = bs.Uint8(2)
|
||||
pkg.PES_priority = bs.Uint8(1)
|
||||
pkg.Data_alignment_indicator = bs.Uint8(1)
|
||||
pkg.Copyright = bs.Uint8(1)
|
||||
pkg.Original_or_copy = bs.Uint8(1)
|
||||
pkg.PTS_DTS_flags = bs.Uint8(2)
|
||||
pkg.ESCR_flag = bs.Uint8(1)
|
||||
pkg.ES_rate_flag = bs.Uint8(1)
|
||||
pkg.DSM_trick_mode_flag = bs.Uint8(1)
|
||||
pkg.Additional_copy_info_flag = bs.Uint8(1)
|
||||
pkg.PES_CRC_flag = bs.Uint8(1)
|
||||
pkg.PES_extension_flag = bs.Uint8(1)
|
||||
pkg.PES_header_data_length = bs.Uint8(8)
|
||||
if bs.RemainBytes() < int(pkg.PES_header_data_length) {
|
||||
bs.UnRead(9 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.Markdot()
|
||||
if pkg.PTS_DTS_flags&0x02 == 0x02 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
if pkg.PTS_DTS_flags&0x03 == 0x03 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Dts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = (pkg.Dts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else {
|
||||
pkg.Dts = pkg.Pts
|
||||
}
|
||||
|
||||
if pkg.ESCR_flag == 1 {
|
||||
bs.SkipBits(2)
|
||||
pkg.ESCR_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_extension = bs.Uint16(9)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
if pkg.ESCR_flag == 1 {
|
||||
bs.SkipBits(2)
|
||||
pkg.ESCR_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_base = (pkg.Pts << 15) | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.ESCR_extension = bs.Uint16(9)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
|
||||
if pkg.ES_rate_flag == 1 {
|
||||
bs.SkipBits(1)
|
||||
pkg.ES_rate = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
if pkg.ES_rate_flag == 1 {
|
||||
bs.SkipBits(1)
|
||||
pkg.ES_rate = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
|
||||
if pkg.DSM_trick_mode_flag == 1 {
|
||||
pkg.Trick_mode_control = bs.Uint8(3)
|
||||
pkg.Trick_value = bs.Uint8(5)
|
||||
}
|
||||
if pkg.DSM_trick_mode_flag == 1 {
|
||||
pkg.Trick_mode_control = bs.Uint8(3)
|
||||
pkg.Trick_value = bs.Uint8(5)
|
||||
}
|
||||
|
||||
if pkg.Additional_copy_info_flag == 1 {
|
||||
pkg.Additional_copy_info = bs.Uint8(7)
|
||||
}
|
||||
if pkg.Additional_copy_info_flag == 1 {
|
||||
pkg.Additional_copy_info = bs.Uint8(7)
|
||||
}
|
||||
|
||||
if pkg.PES_CRC_flag == 1 {
|
||||
pkg.Previous_PES_packet_CRC = bs.Uint16(16)
|
||||
}
|
||||
if pkg.PES_CRC_flag == 1 {
|
||||
pkg.Previous_PES_packet_CRC = bs.Uint16(16)
|
||||
}
|
||||
|
||||
loc := bs.DistanceFromMarkDot()
|
||||
bs.SkipBits(int(pkg.PES_header_data_length)*8 - loc) // skip remaining header
|
||||
loc := bs.DistanceFromMarkDot()
|
||||
bs.SkipBits(int(pkg.PES_header_data_length)*8 - loc) // skip remaining header
|
||||
|
||||
// the -3 bytes are the combined lengths
|
||||
// of all fields between PES_packet_length and PES_header_data_length (2 bytes)
|
||||
// and the PES_header_data_length itself (1 byte)
|
||||
dataLen := int(pkg.PES_packet_length - 3 - uint16(pkg.PES_header_data_length))
|
||||
// the -3 bytes are the combined lengths
|
||||
// of all fields between PES_packet_length and PES_header_data_length (2 bytes)
|
||||
// and the PES_header_data_length itself (1 byte)
|
||||
dataLen := int(pkg.PES_packet_length - 3 - uint16(pkg.PES_header_data_length))
|
||||
|
||||
if bs.RemainBytes() < dataLen {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.UnRead((9 + int(pkg.PES_header_data_length)) * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.RemainBytes() < dataLen {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.UnRead((9 + int(pkg.PES_header_data_length)) * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
|
||||
if pkg.PES_packet_length == 0 || bs.RemainBytes() <= dataLen {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.SkipBits(bs.RemainBits())
|
||||
} else {
|
||||
pkg.Pes_payload = bs.RemainData()[:dataLen]
|
||||
bs.SkipBits(dataLen * 8)
|
||||
}
|
||||
if pkg.PES_packet_length == 0 || bs.RemainBytes() <= dataLen {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.SkipBits(bs.RemainBits())
|
||||
} else {
|
||||
pkg.Pes_payload = bs.RemainData()[:dataLen]
|
||||
bs.SkipBits(dataLen * 8)
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pkg *PesPacket) DecodeMpeg1(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24) //packet_start_code_prefix
|
||||
pkg.Stream_id = bs.Uint8(8) //stream_id
|
||||
pkg.PES_packet_length = bs.Uint16(16)
|
||||
if pkg.PES_packet_length != 0 && bs.RemainBytes() < int(pkg.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.Markdot()
|
||||
for bs.NextBits(8) == 0xFF {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
if bs.NextBits(2) == 0x01 {
|
||||
bs.SkipBits(16)
|
||||
}
|
||||
if bs.NextBits(4) == 0x02 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else if bs.NextBits(4) == 0x03 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else if bs.NextBits(8) == 0x0F {
|
||||
bs.SkipBits(8)
|
||||
} else {
|
||||
return errParser
|
||||
}
|
||||
loc := bs.DistanceFromMarkDot() / 8
|
||||
if pkg.PES_packet_length < uint16(loc) {
|
||||
return errParser
|
||||
}
|
||||
if pkg.PES_packet_length == 0 ||
|
||||
bs.RemainBits() <= int(pkg.PES_packet_length-uint16(loc))*8 {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.SkipBits(bs.RemainBits())
|
||||
} else {
|
||||
pkg.Pes_payload = bs.RemainData()[:pkg.PES_packet_length-uint16(loc)]
|
||||
bs.SkipBits(int(pkg.PES_packet_length-uint16(loc)) * 8)
|
||||
}
|
||||
return nil
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24) //packet_start_code_prefix
|
||||
pkg.Stream_id = bs.Uint8(8) //stream_id
|
||||
pkg.PES_packet_length = bs.Uint16(16)
|
||||
if pkg.PES_packet_length != 0 && bs.RemainBytes() < int(pkg.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.Markdot()
|
||||
for bs.NextBits(8) == 0xFF {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
if bs.NextBits(2) == 0x01 {
|
||||
bs.SkipBits(16)
|
||||
}
|
||||
if bs.NextBits(4) == 0x02 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else if bs.NextBits(4) == 0x03 {
|
||||
bs.SkipBits(4)
|
||||
pkg.Pts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Pts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
pkg.Dts = pkg.Pts<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
} else if bs.NextBits(8) == 0x0F {
|
||||
bs.SkipBits(8)
|
||||
} else {
|
||||
return errParser
|
||||
}
|
||||
loc := bs.DistanceFromMarkDot() / 8
|
||||
if pkg.PES_packet_length < uint16(loc) {
|
||||
return errParser
|
||||
}
|
||||
if pkg.PES_packet_length == 0 ||
|
||||
bs.RemainBits() <= int(pkg.PES_packet_length-uint16(loc))*8 {
|
||||
pkg.Pes_payload = bs.RemainData()
|
||||
bs.SkipBits(bs.RemainBits())
|
||||
} else {
|
||||
pkg.Pes_payload = bs.RemainData()[:pkg.PES_packet_length-uint16(loc)]
|
||||
bs.SkipBits(int(pkg.PES_packet_length-uint16(loc)) * 8)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pkg *PesPacket) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01})
|
||||
bsw.PutByte(pkg.Stream_id)
|
||||
bsw.PutUint16(pkg.PES_packet_length, 16)
|
||||
bsw.PutUint8(0x02, 2)
|
||||
bsw.PutUint8(pkg.PES_scrambling_control, 2)
|
||||
bsw.PutUint8(pkg.PES_priority, 1)
|
||||
bsw.PutUint8(pkg.Data_alignment_indicator, 1)
|
||||
bsw.PutUint8(pkg.Copyright, 1)
|
||||
bsw.PutUint8(pkg.Original_or_copy, 1)
|
||||
bsw.PutUint8(pkg.PTS_DTS_flags, 2)
|
||||
bsw.PutUint8(pkg.ESCR_flag, 1)
|
||||
bsw.PutUint8(pkg.ES_rate_flag, 1)
|
||||
bsw.PutUint8(pkg.DSM_trick_mode_flag, 1)
|
||||
bsw.PutUint8(pkg.Additional_copy_info_flag, 1)
|
||||
bsw.PutUint8(pkg.PES_CRC_flag, 1)
|
||||
bsw.PutUint8(pkg.PES_extension_flag, 1)
|
||||
bsw.PutByte(pkg.PES_header_data_length)
|
||||
if pkg.PTS_DTS_flags == 0x02 {
|
||||
bsw.PutUint8(0x02, 4)
|
||||
bsw.PutUint64(pkg.Pts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01})
|
||||
bsw.PutByte(pkg.Stream_id)
|
||||
bsw.PutUint16(pkg.PES_packet_length, 16)
|
||||
bsw.PutUint8(0x02, 2)
|
||||
bsw.PutUint8(pkg.PES_scrambling_control, 2)
|
||||
bsw.PutUint8(pkg.PES_priority, 1)
|
||||
bsw.PutUint8(pkg.Data_alignment_indicator, 1)
|
||||
bsw.PutUint8(pkg.Copyright, 1)
|
||||
bsw.PutUint8(pkg.Original_or_copy, 1)
|
||||
bsw.PutUint8(pkg.PTS_DTS_flags, 2)
|
||||
bsw.PutUint8(pkg.ESCR_flag, 1)
|
||||
bsw.PutUint8(pkg.ES_rate_flag, 1)
|
||||
bsw.PutUint8(pkg.DSM_trick_mode_flag, 1)
|
||||
bsw.PutUint8(pkg.Additional_copy_info_flag, 1)
|
||||
bsw.PutUint8(pkg.PES_CRC_flag, 1)
|
||||
bsw.PutUint8(pkg.PES_extension_flag, 1)
|
||||
bsw.PutByte(pkg.PES_header_data_length)
|
||||
if pkg.PTS_DTS_flags == 0x02 {
|
||||
bsw.PutUint8(0x02, 4)
|
||||
bsw.PutUint64(pkg.Pts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
|
||||
if pkg.PTS_DTS_flags == 0x03 {
|
||||
bsw.PutUint8(0x03, 4)
|
||||
bsw.PutUint64(pkg.Pts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint8(0x01, 4)
|
||||
bsw.PutUint64(pkg.Dts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Dts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Dts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
if pkg.PTS_DTS_flags == 0x03 {
|
||||
bsw.PutUint8(0x03, 4)
|
||||
bsw.PutUint64(pkg.Pts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Pts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint8(0x01, 4)
|
||||
bsw.PutUint64(pkg.Dts>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Dts>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.Dts, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
|
||||
if pkg.ESCR_flag == 1 {
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint64(pkg.ESCR_base>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.ESCR_base>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.ESCR_base, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
bsw.PutBytes(pkg.Pes_payload)
|
||||
if pkg.ESCR_flag == 1 {
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint64(pkg.ESCR_base>>30, 3)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.ESCR_base>>15, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
bsw.PutUint64(pkg.ESCR_base, 15)
|
||||
bsw.PutUint8(0x01, 1)
|
||||
}
|
||||
bsw.PutBytes(pkg.Pes_payload)
|
||||
}
|
||||
|
|
482
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-demuxer.go
generated
vendored
482
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-demuxer.go
generated
vendored
|
@ -1,280 +1,280 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
type psstream struct {
|
||||
sid uint8
|
||||
cid PS_STREAM_TYPE
|
||||
pts uint64
|
||||
dts uint64
|
||||
streamBuf []byte
|
||||
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),
|
||||
}
|
||||
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)
|
||||
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,
|
||||
}
|
||||
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)
|
||||
}
|
||||
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
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
if ret == nil && len(psdemuxer.cache) > 0 {
|
||||
psdemuxer.cache = nil
|
||||
}
|
||||
|
||||
return ret
|
||||
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)
|
||||
}
|
||||
}
|
||||
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 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
|
||||
})
|
||||
}
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
}
|
||||
|
|
264
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-muxer.go
generated
vendored
264
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-muxer.go
generated
vendored
|
@ -3,146 +3,146 @@ package mpeg2
|
|||
import "github.com/yapingcat/gomedia/codec"
|
||||
|
||||
type PSMuxer struct {
|
||||
system *System_header
|
||||
psm *Program_stream_map
|
||||
OnPacket func(pkg []byte)
|
||||
firstframe bool
|
||||
system *System_header
|
||||
psm *Program_stream_map
|
||||
OnPacket func(pkg []byte)
|
||||
firstframe bool
|
||||
}
|
||||
|
||||
func NewPsMuxer() *PSMuxer {
|
||||
muxer := new(PSMuxer)
|
||||
muxer.firstframe = true
|
||||
muxer.system = new(System_header)
|
||||
muxer.system.Rate_bound = 26234
|
||||
muxer.psm = new(Program_stream_map)
|
||||
muxer.psm.Current_next_indicator = 1
|
||||
muxer.psm.Program_stream_map_version = 1
|
||||
muxer.OnPacket = nil
|
||||
return muxer
|
||||
muxer := new(PSMuxer)
|
||||
muxer.firstframe = true
|
||||
muxer.system = new(System_header)
|
||||
muxer.system.Rate_bound = 26234
|
||||
muxer.psm = new(Program_stream_map)
|
||||
muxer.psm.Current_next_indicator = 1
|
||||
muxer.psm.Program_stream_map_version = 1
|
||||
muxer.OnPacket = nil
|
||||
return muxer
|
||||
}
|
||||
|
||||
func (muxer *PSMuxer) AddStream(cid PS_STREAM_TYPE) uint8 {
|
||||
if cid == PS_STREAM_H265 || cid == PS_STREAM_H264 {
|
||||
es := NewElementary_Stream(uint8(PES_STREAM_VIDEO) + muxer.system.Video_bound)
|
||||
es.P_STD_buffer_bound_scale = 1
|
||||
es.P_STD_buffer_size_bound = 400
|
||||
muxer.system.Streams = append(muxer.system.Streams, es)
|
||||
muxer.system.Video_bound++
|
||||
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
|
||||
muxer.psm.Program_stream_map_version++
|
||||
return es.Stream_id
|
||||
} else {
|
||||
es := NewElementary_Stream(uint8(PES_STREAM_AUDIO) + muxer.system.Audio_bound)
|
||||
es.P_STD_buffer_bound_scale = 0
|
||||
es.P_STD_buffer_size_bound = 32
|
||||
muxer.system.Streams = append(muxer.system.Streams, es)
|
||||
muxer.system.Audio_bound++
|
||||
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
|
||||
muxer.psm.Program_stream_map_version++
|
||||
return es.Stream_id
|
||||
}
|
||||
if cid == PS_STREAM_H265 || cid == PS_STREAM_H264 {
|
||||
es := NewElementary_Stream(uint8(PES_STREAM_VIDEO) + muxer.system.Video_bound)
|
||||
es.P_STD_buffer_bound_scale = 1
|
||||
es.P_STD_buffer_size_bound = 400
|
||||
muxer.system.Streams = append(muxer.system.Streams, es)
|
||||
muxer.system.Video_bound++
|
||||
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
|
||||
muxer.psm.Program_stream_map_version++
|
||||
return es.Stream_id
|
||||
} else {
|
||||
es := NewElementary_Stream(uint8(PES_STREAM_AUDIO) + muxer.system.Audio_bound)
|
||||
es.P_STD_buffer_bound_scale = 0
|
||||
es.P_STD_buffer_size_bound = 32
|
||||
muxer.system.Streams = append(muxer.system.Streams, es)
|
||||
muxer.system.Audio_bound++
|
||||
muxer.psm.Stream_map = append(muxer.psm.Stream_map, NewElementary_stream_elem(uint8(cid), es.Stream_id))
|
||||
muxer.psm.Program_stream_map_version++
|
||||
return es.Stream_id
|
||||
}
|
||||
}
|
||||
|
||||
func (muxer *PSMuxer) Write(sid uint8, frame []byte, pts uint64, dts uint64) error {
|
||||
var stream *Elementary_stream_elem = nil
|
||||
for _, es := range muxer.psm.Stream_map {
|
||||
if es.Elementary_stream_id == sid {
|
||||
stream = es
|
||||
break
|
||||
}
|
||||
}
|
||||
if stream == nil {
|
||||
return errNotFound
|
||||
}
|
||||
var withaud bool = false
|
||||
var idr_flag bool = false
|
||||
var first bool = true
|
||||
var vcl bool = false
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) || stream.Stream_type == uint8(PS_STREAM_H265) {
|
||||
codec.SplitFrame(frame, func(nalu []byte) bool {
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) {
|
||||
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H264_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH264VCLNaluType(nalu_type) {
|
||||
if nalu_type == codec.H264_NAL_I_SLICE {
|
||||
idr_flag = true
|
||||
}
|
||||
vcl = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H265_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH265VCLNaluType(nalu_type) {
|
||||
if nalu_type >= codec.H265_NAL_SLICE_BLA_W_LP && nalu_type <= codec.H265_NAL_SLICE_CRA {
|
||||
idr_flag = true
|
||||
}
|
||||
vcl = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
var stream *Elementary_stream_elem = nil
|
||||
for _, es := range muxer.psm.Stream_map {
|
||||
if es.Elementary_stream_id == sid {
|
||||
stream = es
|
||||
break
|
||||
}
|
||||
}
|
||||
if stream == nil {
|
||||
return errNotFound
|
||||
}
|
||||
var withaud bool = false
|
||||
var idr_flag bool = false
|
||||
var first bool = true
|
||||
var vcl bool = false
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) || stream.Stream_type == uint8(PS_STREAM_H265) {
|
||||
codec.SplitFrame(frame, func(nalu []byte) bool {
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) {
|
||||
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H264_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH264VCLNaluType(nalu_type) {
|
||||
if nalu_type == codec.H264_NAL_I_SLICE {
|
||||
idr_flag = true
|
||||
}
|
||||
vcl = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H265_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH265VCLNaluType(nalu_type) {
|
||||
if nalu_type >= codec.H265_NAL_SLICE_BLA_W_LP && nalu_type <= codec.H265_NAL_SLICE_CRA {
|
||||
idr_flag = true
|
||||
}
|
||||
vcl = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
dts = dts * 90
|
||||
pts = pts * 90
|
||||
bsw := codec.NewBitStreamWriter(1024)
|
||||
var pack PSPackHeader
|
||||
pack.System_clock_reference_base = dts - 3600
|
||||
pack.System_clock_reference_extension = 0
|
||||
pack.Program_mux_rate = 6106
|
||||
pack.Encode(bsw)
|
||||
if muxer.firstframe || idr_flag {
|
||||
muxer.system.Encode(bsw)
|
||||
muxer.psm.Encode(bsw)
|
||||
muxer.firstframe = false
|
||||
}
|
||||
if muxer.OnPacket != nil {
|
||||
muxer.OnPacket(bsw.Bits())
|
||||
}
|
||||
bsw.Reset()
|
||||
pespkg := NewPesPacket()
|
||||
for len(frame) > 0 {
|
||||
peshdrlen := 13
|
||||
pespkg.Stream_id = sid
|
||||
pespkg.PTS_DTS_flags = 0x03
|
||||
pespkg.PES_header_data_length = 10
|
||||
pespkg.Pts = pts
|
||||
pespkg.Dts = dts
|
||||
if idr_flag {
|
||||
pespkg.Data_alignment_indicator = 1
|
||||
}
|
||||
if first && !withaud && vcl {
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) {
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, H264_AUD_NALU...)
|
||||
peshdrlen += 6
|
||||
} else if stream.Stream_type == uint8(PS_STREAM_H265) {
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, H265_AUD_NALU...)
|
||||
peshdrlen += 7
|
||||
}
|
||||
}
|
||||
if peshdrlen+len(frame) >= 0xFFFF {
|
||||
pespkg.PES_packet_length = 0xFFFF
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:0xFFFF-peshdrlen]...)
|
||||
frame = frame[0xFFFF-peshdrlen:]
|
||||
} else {
|
||||
pespkg.PES_packet_length = uint16(peshdrlen + len(frame))
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:]...)
|
||||
frame = frame[:0]
|
||||
}
|
||||
pespkg.Encode(bsw)
|
||||
pespkg.Pes_payload = pespkg.Pes_payload[:0]
|
||||
if muxer.OnPacket != nil {
|
||||
muxer.OnPacket(bsw.Bits())
|
||||
}
|
||||
bsw.Reset()
|
||||
first = false
|
||||
}
|
||||
return nil
|
||||
dts = dts * 90
|
||||
pts = pts * 90
|
||||
bsw := codec.NewBitStreamWriter(1024)
|
||||
var pack PSPackHeader
|
||||
pack.System_clock_reference_base = dts - 3600
|
||||
pack.System_clock_reference_extension = 0
|
||||
pack.Program_mux_rate = 6106
|
||||
pack.Encode(bsw)
|
||||
if muxer.firstframe || idr_flag {
|
||||
muxer.system.Encode(bsw)
|
||||
muxer.psm.Encode(bsw)
|
||||
muxer.firstframe = false
|
||||
}
|
||||
if muxer.OnPacket != nil {
|
||||
muxer.OnPacket(bsw.Bits())
|
||||
}
|
||||
bsw.Reset()
|
||||
pespkg := NewPesPacket()
|
||||
for len(frame) > 0 {
|
||||
peshdrlen := 13
|
||||
pespkg.Stream_id = sid
|
||||
pespkg.PTS_DTS_flags = 0x03
|
||||
pespkg.PES_header_data_length = 10
|
||||
pespkg.Pts = pts
|
||||
pespkg.Dts = dts
|
||||
if idr_flag {
|
||||
pespkg.Data_alignment_indicator = 1
|
||||
}
|
||||
if first && !withaud && vcl {
|
||||
if stream.Stream_type == uint8(PS_STREAM_H264) {
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, H264_AUD_NALU...)
|
||||
peshdrlen += 6
|
||||
} else if stream.Stream_type == uint8(PS_STREAM_H265) {
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, H265_AUD_NALU...)
|
||||
peshdrlen += 7
|
||||
}
|
||||
}
|
||||
if peshdrlen+len(frame) >= 0xFFFF {
|
||||
pespkg.PES_packet_length = 0xFFFF
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:0xFFFF-peshdrlen]...)
|
||||
frame = frame[0xFFFF-peshdrlen:]
|
||||
} else {
|
||||
pespkg.PES_packet_length = uint16(peshdrlen + len(frame))
|
||||
pespkg.Pes_payload = append(pespkg.Pes_payload, frame[0:]...)
|
||||
frame = frame[:0]
|
||||
}
|
||||
pespkg.Encode(bsw)
|
||||
pespkg.Pes_payload = pespkg.Pes_payload[:0]
|
||||
if muxer.OnPacket != nil {
|
||||
muxer.OnPacket(bsw.Bits())
|
||||
}
|
||||
bsw.Reset()
|
||||
first = false
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
670
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-proto.go
generated
vendored
670
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ps-proto.go
generated
vendored
|
@ -1,17 +1,17 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
type Error interface {
|
||||
NeedMore() bool
|
||||
ParserError() bool
|
||||
StreamIdNotFound() bool
|
||||
NeedMore() bool
|
||||
ParserError() bool
|
||||
StreamIdNotFound() bool
|
||||
}
|
||||
|
||||
var errNeedMore error = &needmoreError{}
|
||||
|
@ -44,12 +44,12 @@ func (e *sidNotFoundError) StreamIdNotFound() bool { return true }
|
|||
type PS_STREAM_TYPE int
|
||||
|
||||
const (
|
||||
PS_STREAM_UNKNOW PS_STREAM_TYPE = 0xFF
|
||||
PS_STREAM_AAC PS_STREAM_TYPE = 0x0F
|
||||
PS_STREAM_H264 PS_STREAM_TYPE = 0x1B
|
||||
PS_STREAM_H265 PS_STREAM_TYPE = 0x24
|
||||
PS_STREAM_G711A PS_STREAM_TYPE = 0x90
|
||||
PS_STREAM_G711U PS_STREAM_TYPE = 0x91
|
||||
PS_STREAM_UNKNOW PS_STREAM_TYPE = 0xFF
|
||||
PS_STREAM_AAC PS_STREAM_TYPE = 0x0F
|
||||
PS_STREAM_H264 PS_STREAM_TYPE = 0x1B
|
||||
PS_STREAM_H265 PS_STREAM_TYPE = 0x24
|
||||
PS_STREAM_G711A PS_STREAM_TYPE = 0x90
|
||||
PS_STREAM_G711U PS_STREAM_TYPE = 0x91
|
||||
)
|
||||
|
||||
// Table 2-33 – Program Stream pack header
|
||||
|
@ -78,113 +78,113 @@ const (
|
|||
// }
|
||||
|
||||
type PSPackHeader struct {
|
||||
IsMpeg1 bool
|
||||
System_clock_reference_base uint64 //33 bits
|
||||
System_clock_reference_extension uint16 //9 bits
|
||||
Program_mux_rate uint32 //22 bits
|
||||
Pack_stuffing_length uint8 //3 bitss
|
||||
IsMpeg1 bool
|
||||
System_clock_reference_base uint64 //33 bits
|
||||
System_clock_reference_extension uint16 //9 bits
|
||||
Program_mux_rate uint32 //22 bits
|
||||
Pack_stuffing_length uint8 //3 bitss
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("IsMpeg1:%t\n", ps_pkg_hdr.IsMpeg1))
|
||||
file.WriteString(fmt.Sprintf("System_clock_reference_base:%d\n", ps_pkg_hdr.System_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("System_clock_reference_extension:%d\n", ps_pkg_hdr.System_clock_reference_extension))
|
||||
file.WriteString(fmt.Sprintf("Program_mux_rate:%d\n", ps_pkg_hdr.Program_mux_rate))
|
||||
file.WriteString(fmt.Sprintf("Pack_stuffing_length:%d\n", ps_pkg_hdr.Pack_stuffing_length))
|
||||
file.WriteString(fmt.Sprintf("IsMpeg1:%t\n", ps_pkg_hdr.IsMpeg1))
|
||||
file.WriteString(fmt.Sprintf("System_clock_reference_base:%d\n", ps_pkg_hdr.System_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("System_clock_reference_extension:%d\n", ps_pkg_hdr.System_clock_reference_extension))
|
||||
file.WriteString(fmt.Sprintf("Program_mux_rate:%d\n", ps_pkg_hdr.Program_mux_rate))
|
||||
file.WriteString(fmt.Sprintf("Pack_stuffing_length:%d\n", ps_pkg_hdr.Pack_stuffing_length))
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 5 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001BA {
|
||||
panic("ps header must start with 000001BA")
|
||||
}
|
||||
if bs.RemainBytes() < 5 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001BA {
|
||||
panic("ps header must start with 000001BA")
|
||||
}
|
||||
|
||||
if bs.NextBits(2) == 0x01 { //mpeg2
|
||||
if bs.RemainBytes() < 10 {
|
||||
return errNeedMore
|
||||
}
|
||||
return ps_pkg_hdr.decodeMpeg2(bs)
|
||||
} else if bs.NextBits(4) == 0x02 { //mpeg1
|
||||
if bs.RemainBytes() < 8 {
|
||||
return errNeedMore
|
||||
}
|
||||
ps_pkg_hdr.IsMpeg1 = true
|
||||
return ps_pkg_hdr.decodeMpeg1(bs)
|
||||
} else {
|
||||
return errParser
|
||||
}
|
||||
if bs.NextBits(2) == 0x01 { //mpeg2
|
||||
if bs.RemainBytes() < 10 {
|
||||
return errNeedMore
|
||||
}
|
||||
return ps_pkg_hdr.decodeMpeg2(bs)
|
||||
} else if bs.NextBits(4) == 0x02 { //mpeg1
|
||||
if bs.RemainBytes() < 8 {
|
||||
return errNeedMore
|
||||
}
|
||||
ps_pkg_hdr.IsMpeg1 = true
|
||||
return ps_pkg_hdr.decodeMpeg1(bs)
|
||||
} else {
|
||||
return errParser
|
||||
}
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) decodeMpeg2(bs *codec.BitStream) error {
|
||||
bs.SkipBits(2)
|
||||
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_extension = bs.Uint16(9)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.Program_mux_rate = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
bs.SkipBits(1)
|
||||
bs.SkipBits(5)
|
||||
ps_pkg_hdr.Pack_stuffing_length = bs.Uint8(3)
|
||||
if bs.RemainBytes() < int(ps_pkg_hdr.Pack_stuffing_length) {
|
||||
bs.UnRead(10 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(ps_pkg_hdr.Pack_stuffing_length) * 8)
|
||||
return nil
|
||||
bs.SkipBits(2)
|
||||
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_extension = bs.Uint16(9)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.Program_mux_rate = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
bs.SkipBits(1)
|
||||
bs.SkipBits(5)
|
||||
ps_pkg_hdr.Pack_stuffing_length = bs.Uint8(3)
|
||||
if bs.RemainBytes() < int(ps_pkg_hdr.Pack_stuffing_length) {
|
||||
bs.UnRead(10 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(ps_pkg_hdr.Pack_stuffing_length) * 8)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) decodeMpeg1(bs *codec.BitStream) error {
|
||||
bs.SkipBits(4)
|
||||
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_extension = 1
|
||||
ps_pkg_hdr.Program_mux_rate = bs.Uint32(7)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.Program_mux_rate = ps_pkg_hdr.Program_mux_rate<<15 | bs.Uint32(15)
|
||||
bs.SkipBits(1)
|
||||
return nil
|
||||
bs.SkipBits(4)
|
||||
ps_pkg_hdr.System_clock_reference_base = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_base = ps_pkg_hdr.System_clock_reference_base<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.System_clock_reference_extension = 1
|
||||
ps_pkg_hdr.Program_mux_rate = bs.Uint32(7)
|
||||
bs.SkipBits(1)
|
||||
ps_pkg_hdr.Program_mux_rate = ps_pkg_hdr.Program_mux_rate<<15 | bs.Uint32(15)
|
||||
bs.SkipBits(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ps_pkg_hdr *PSPackHeader) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBA})
|
||||
bsw.PutUint8(1, 2)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>30, 3)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>15, 15)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base, 15)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint16(ps_pkg_hdr.System_clock_reference_extension, 9)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint32(ps_pkg_hdr.Program_mux_rate, 22)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(0x1F, 5)
|
||||
bsw.PutUint8(ps_pkg_hdr.Pack_stuffing_length, 3)
|
||||
bsw.PutRepetValue(0xFF, int(ps_pkg_hdr.Pack_stuffing_length))
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBA})
|
||||
bsw.PutUint8(1, 2)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>30, 3)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base>>15, 15)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint64(ps_pkg_hdr.System_clock_reference_base, 15)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint16(ps_pkg_hdr.System_clock_reference_extension, 9)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint32(ps_pkg_hdr.Program_mux_rate, 22)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(0x1F, 5)
|
||||
bsw.PutUint8(ps_pkg_hdr.Pack_stuffing_length, 3)
|
||||
bsw.PutRepetValue(0xFF, int(ps_pkg_hdr.Pack_stuffing_length))
|
||||
}
|
||||
|
||||
type Elementary_Stream struct {
|
||||
Stream_id uint8
|
||||
P_STD_buffer_bound_scale uint8
|
||||
P_STD_buffer_size_bound uint16
|
||||
Stream_id uint8
|
||||
P_STD_buffer_bound_scale uint8
|
||||
P_STD_buffer_size_bound uint16
|
||||
}
|
||||
|
||||
func NewElementary_Stream(sid uint8) *Elementary_Stream {
|
||||
return &Elementary_Stream{
|
||||
Stream_id: sid,
|
||||
}
|
||||
return &Elementary_Stream{
|
||||
Stream_id: sid,
|
||||
}
|
||||
}
|
||||
|
||||
// system_header () {
|
||||
|
@ -211,118 +211,118 @@ func NewElementary_Stream(sid uint8) *Elementary_Stream {
|
|||
// }
|
||||
|
||||
type System_header struct {
|
||||
Header_length uint16
|
||||
Rate_bound uint32
|
||||
Audio_bound uint8
|
||||
Fixed_flag uint8
|
||||
CSPS_flag uint8
|
||||
System_audio_lock_flag uint8
|
||||
System_video_lock_flag uint8
|
||||
Video_bound uint8
|
||||
Packet_rate_restriction_flag uint8
|
||||
Streams []*Elementary_Stream
|
||||
Header_length uint16
|
||||
Rate_bound uint32
|
||||
Audio_bound uint8
|
||||
Fixed_flag uint8
|
||||
CSPS_flag uint8
|
||||
System_audio_lock_flag uint8
|
||||
System_video_lock_flag uint8
|
||||
Video_bound uint8
|
||||
Packet_rate_restriction_flag uint8
|
||||
Streams []*Elementary_Stream
|
||||
}
|
||||
|
||||
func (sh *System_header) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Header_length:%d\n", sh.Header_length))
|
||||
file.WriteString(fmt.Sprintf("Rate_bound:%d\n", sh.Rate_bound))
|
||||
file.WriteString(fmt.Sprintf("Audio_bound:%d\n", sh.Audio_bound))
|
||||
file.WriteString(fmt.Sprintf("Fixed_flag:%d\n", sh.Fixed_flag))
|
||||
file.WriteString(fmt.Sprintf("CSPS_flag:%d\n", sh.CSPS_flag))
|
||||
file.WriteString(fmt.Sprintf("System_audio_lock_flag:%d\n", sh.System_audio_lock_flag))
|
||||
file.WriteString(fmt.Sprintf("System_video_lock_flag:%d\n", sh.System_video_lock_flag))
|
||||
file.WriteString(fmt.Sprintf("Video_bound:%d\n", sh.Video_bound))
|
||||
file.WriteString(fmt.Sprintf("Packet_rate_restriction_flag:%d\n", sh.Packet_rate_restriction_flag))
|
||||
for i, es := range sh.Streams {
|
||||
file.WriteString(fmt.Sprintf("----streams %d\n", i))
|
||||
file.WriteString(fmt.Sprintf(" Stream_id:%d\n", es.Stream_id))
|
||||
file.WriteString(fmt.Sprintf(" P_STD_buffer_bound_scale:%d\n", es.P_STD_buffer_bound_scale))
|
||||
file.WriteString(fmt.Sprintf(" P_STD_buffer_size_bound:%d\n", es.P_STD_buffer_size_bound))
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("Header_length:%d\n", sh.Header_length))
|
||||
file.WriteString(fmt.Sprintf("Rate_bound:%d\n", sh.Rate_bound))
|
||||
file.WriteString(fmt.Sprintf("Audio_bound:%d\n", sh.Audio_bound))
|
||||
file.WriteString(fmt.Sprintf("Fixed_flag:%d\n", sh.Fixed_flag))
|
||||
file.WriteString(fmt.Sprintf("CSPS_flag:%d\n", sh.CSPS_flag))
|
||||
file.WriteString(fmt.Sprintf("System_audio_lock_flag:%d\n", sh.System_audio_lock_flag))
|
||||
file.WriteString(fmt.Sprintf("System_video_lock_flag:%d\n", sh.System_video_lock_flag))
|
||||
file.WriteString(fmt.Sprintf("Video_bound:%d\n", sh.Video_bound))
|
||||
file.WriteString(fmt.Sprintf("Packet_rate_restriction_flag:%d\n", sh.Packet_rate_restriction_flag))
|
||||
for i, es := range sh.Streams {
|
||||
file.WriteString(fmt.Sprintf("----streams %d\n", i))
|
||||
file.WriteString(fmt.Sprintf(" Stream_id:%d\n", es.Stream_id))
|
||||
file.WriteString(fmt.Sprintf(" P_STD_buffer_bound_scale:%d\n", es.P_STD_buffer_bound_scale))
|
||||
file.WriteString(fmt.Sprintf(" P_STD_buffer_size_bound:%d\n", es.P_STD_buffer_size_bound))
|
||||
}
|
||||
}
|
||||
|
||||
func (sh *System_header) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBB})
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint16(0, 16)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint32(sh.Rate_bound, 22)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(sh.Audio_bound, 6)
|
||||
bsw.PutUint8(sh.Fixed_flag, 1)
|
||||
bsw.PutUint8(sh.CSPS_flag, 1)
|
||||
bsw.PutUint8(sh.System_audio_lock_flag, 1)
|
||||
bsw.PutUint8(sh.System_video_lock_flag, 1)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(sh.Video_bound, 5)
|
||||
bsw.PutUint8(sh.Packet_rate_restriction_flag, 1)
|
||||
bsw.PutUint8(0x7F, 7)
|
||||
for _, stream := range sh.Streams {
|
||||
bsw.PutUint8(stream.Stream_id, 8)
|
||||
bsw.PutUint8(3, 2)
|
||||
bsw.PutUint8(stream.P_STD_buffer_bound_scale, 1)
|
||||
bsw.PutUint16(stream.P_STD_buffer_size_bound, 13)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot() / 8
|
||||
bsw.SetUint16(uint16(length), loc)
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBB})
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint16(0, 16)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint32(sh.Rate_bound, 22)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(sh.Audio_bound, 6)
|
||||
bsw.PutUint8(sh.Fixed_flag, 1)
|
||||
bsw.PutUint8(sh.CSPS_flag, 1)
|
||||
bsw.PutUint8(sh.System_audio_lock_flag, 1)
|
||||
bsw.PutUint8(sh.System_video_lock_flag, 1)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint8(sh.Video_bound, 5)
|
||||
bsw.PutUint8(sh.Packet_rate_restriction_flag, 1)
|
||||
bsw.PutUint8(0x7F, 7)
|
||||
for _, stream := range sh.Streams {
|
||||
bsw.PutUint8(stream.Stream_id, 8)
|
||||
bsw.PutUint8(3, 2)
|
||||
bsw.PutUint8(stream.P_STD_buffer_bound_scale, 1)
|
||||
bsw.PutUint16(stream.P_STD_buffer_size_bound, 13)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot() / 8
|
||||
bsw.SetUint16(uint16(length), loc)
|
||||
}
|
||||
|
||||
func (sh *System_header) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 12 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001BB {
|
||||
panic("system header must start with 000001BB")
|
||||
}
|
||||
sh.Header_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(sh.Header_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
if sh.Header_length < 6 || (sh.Header_length-6)%3 != 0 {
|
||||
return errParser
|
||||
}
|
||||
bs.SkipBits(1)
|
||||
sh.Rate_bound = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
sh.Audio_bound = bs.Uint8(6)
|
||||
sh.Fixed_flag = bs.Uint8(1)
|
||||
sh.CSPS_flag = bs.Uint8(1)
|
||||
sh.System_audio_lock_flag = bs.Uint8(1)
|
||||
sh.System_video_lock_flag = bs.Uint8(1)
|
||||
bs.SkipBits(1)
|
||||
sh.Video_bound = bs.Uint8(5)
|
||||
sh.Packet_rate_restriction_flag = bs.Uint8(1)
|
||||
bs.SkipBits(7)
|
||||
sh.Streams = sh.Streams[:0]
|
||||
least := sh.Header_length - 6
|
||||
for least > 0 && bs.NextBits(1) == 0x01 {
|
||||
es := new(Elementary_Stream)
|
||||
es.Stream_id = bs.Uint8(8)
|
||||
bs.SkipBits(2)
|
||||
es.P_STD_buffer_bound_scale = bs.GetBit()
|
||||
es.P_STD_buffer_size_bound = bs.Uint16(13)
|
||||
sh.Streams = append(sh.Streams, es)
|
||||
least -= 3
|
||||
}
|
||||
if least > 0 {
|
||||
return errParser
|
||||
}
|
||||
return nil
|
||||
if bs.RemainBytes() < 12 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001BB {
|
||||
panic("system header must start with 000001BB")
|
||||
}
|
||||
sh.Header_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(sh.Header_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
if sh.Header_length < 6 || (sh.Header_length-6)%3 != 0 {
|
||||
return errParser
|
||||
}
|
||||
bs.SkipBits(1)
|
||||
sh.Rate_bound = bs.Uint32(22)
|
||||
bs.SkipBits(1)
|
||||
sh.Audio_bound = bs.Uint8(6)
|
||||
sh.Fixed_flag = bs.Uint8(1)
|
||||
sh.CSPS_flag = bs.Uint8(1)
|
||||
sh.System_audio_lock_flag = bs.Uint8(1)
|
||||
sh.System_video_lock_flag = bs.Uint8(1)
|
||||
bs.SkipBits(1)
|
||||
sh.Video_bound = bs.Uint8(5)
|
||||
sh.Packet_rate_restriction_flag = bs.Uint8(1)
|
||||
bs.SkipBits(7)
|
||||
sh.Streams = sh.Streams[:0]
|
||||
least := sh.Header_length - 6
|
||||
for least > 0 && bs.NextBits(1) == 0x01 {
|
||||
es := new(Elementary_Stream)
|
||||
es.Stream_id = bs.Uint8(8)
|
||||
bs.SkipBits(2)
|
||||
es.P_STD_buffer_bound_scale = bs.GetBit()
|
||||
es.P_STD_buffer_size_bound = bs.Uint16(13)
|
||||
sh.Streams = append(sh.Streams, es)
|
||||
least -= 3
|
||||
}
|
||||
if least > 0 {
|
||||
return errParser
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Elementary_stream_elem struct {
|
||||
Stream_type uint8
|
||||
Elementary_stream_id uint8
|
||||
Elementary_stream_info_length uint16
|
||||
Stream_type uint8
|
||||
Elementary_stream_id uint8
|
||||
Elementary_stream_info_length uint16
|
||||
}
|
||||
|
||||
func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem {
|
||||
return &Elementary_stream_elem{
|
||||
Stream_type: stype,
|
||||
Elementary_stream_id: esid,
|
||||
}
|
||||
return &Elementary_stream_elem{
|
||||
Stream_type: stype,
|
||||
Elementary_stream_id: esid,
|
||||
}
|
||||
}
|
||||
|
||||
// program_stream_map() {
|
||||
|
@ -351,171 +351,171 @@ func NewElementary_stream_elem(stype uint8, esid uint8) *Elementary_stream_elem
|
|||
// }
|
||||
|
||||
type Program_stream_map struct {
|
||||
Map_stream_id uint8
|
||||
Program_stream_map_length uint16
|
||||
Current_next_indicator uint8
|
||||
Program_stream_map_version uint8
|
||||
Program_stream_info_length uint16
|
||||
Elementary_stream_map_length uint16
|
||||
Stream_map []*Elementary_stream_elem
|
||||
Map_stream_id uint8
|
||||
Program_stream_map_length uint16
|
||||
Current_next_indicator uint8
|
||||
Program_stream_map_version uint8
|
||||
Program_stream_info_length uint16
|
||||
Elementary_stream_map_length uint16
|
||||
Stream_map []*Elementary_stream_elem
|
||||
}
|
||||
|
||||
func (psm *Program_stream_map) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("map_stream_id:%d\n", psm.Map_stream_id))
|
||||
file.WriteString(fmt.Sprintf("program_stream_map_length:%d\n", psm.Program_stream_map_length))
|
||||
file.WriteString(fmt.Sprintf("current_next_indicator:%d\n", psm.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("program_stream_map_version:%d\n", psm.Program_stream_map_version))
|
||||
file.WriteString(fmt.Sprintf("program_stream_info_length:%d\n", psm.Program_stream_info_length))
|
||||
file.WriteString(fmt.Sprintf("elementary_stream_map_length:%d\n", psm.Elementary_stream_map_length))
|
||||
for i, es := range psm.Stream_map {
|
||||
file.WriteString(fmt.Sprintf("----ES stream %d\n", i))
|
||||
if es.Stream_type == uint8(PS_STREAM_AAC) {
|
||||
file.WriteString(" stream_type:AAC\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_G711A) {
|
||||
file.WriteString(" stream_type:G711A\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_G711U) {
|
||||
file.WriteString(" stream_type:G711U\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_H264) {
|
||||
file.WriteString(" stream_type:H264\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_H265) {
|
||||
file.WriteString(" stream_type:H265\n")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf(" elementary_stream_id:%d\n", es.Elementary_stream_id))
|
||||
file.WriteString(fmt.Sprintf(" elementary_stream_info_length:%d\n", es.Elementary_stream_info_length))
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("map_stream_id:%d\n", psm.Map_stream_id))
|
||||
file.WriteString(fmt.Sprintf("program_stream_map_length:%d\n", psm.Program_stream_map_length))
|
||||
file.WriteString(fmt.Sprintf("current_next_indicator:%d\n", psm.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("program_stream_map_version:%d\n", psm.Program_stream_map_version))
|
||||
file.WriteString(fmt.Sprintf("program_stream_info_length:%d\n", psm.Program_stream_info_length))
|
||||
file.WriteString(fmt.Sprintf("elementary_stream_map_length:%d\n", psm.Elementary_stream_map_length))
|
||||
for i, es := range psm.Stream_map {
|
||||
file.WriteString(fmt.Sprintf("----ES stream %d\n", i))
|
||||
if es.Stream_type == uint8(PS_STREAM_AAC) {
|
||||
file.WriteString(" stream_type:AAC\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_G711A) {
|
||||
file.WriteString(" stream_type:G711A\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_G711U) {
|
||||
file.WriteString(" stream_type:G711U\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_H264) {
|
||||
file.WriteString(" stream_type:H264\n")
|
||||
} else if es.Stream_type == uint8(PS_STREAM_H265) {
|
||||
file.WriteString(" stream_type:H265\n")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf(" elementary_stream_id:%d\n", es.Elementary_stream_id))
|
||||
file.WriteString(fmt.Sprintf(" elementary_stream_info_length:%d\n", es.Elementary_stream_info_length))
|
||||
}
|
||||
}
|
||||
|
||||
func (psm *Program_stream_map) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBC})
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint16(psm.Program_stream_map_length, 16)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(psm.Current_next_indicator, 1)
|
||||
bsw.PutUint8(3, 2)
|
||||
bsw.PutUint8(psm.Program_stream_map_version, 5)
|
||||
bsw.PutUint8(0x7F, 7)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint16(0, 16)
|
||||
psm.Elementary_stream_map_length = uint16(len(psm.Stream_map) * 4)
|
||||
bsw.PutUint16(psm.Elementary_stream_map_length, 16)
|
||||
for _, streaminfo := range psm.Stream_map {
|
||||
bsw.PutUint8(streaminfo.Stream_type, 8)
|
||||
bsw.PutUint8(streaminfo.Elementary_stream_id, 8)
|
||||
bsw.PutUint16(0, 16)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()/8 + 4
|
||||
bsw.SetUint16(uint16(length), loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(length-4)-4:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
bsw.PutBytes([]byte{0x00, 0x00, 0x01, 0xBC})
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint16(psm.Program_stream_map_length, 16)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(psm.Current_next_indicator, 1)
|
||||
bsw.PutUint8(3, 2)
|
||||
bsw.PutUint8(psm.Program_stream_map_version, 5)
|
||||
bsw.PutUint8(0x7F, 7)
|
||||
bsw.PutUint8(1, 1)
|
||||
bsw.PutUint16(0, 16)
|
||||
psm.Elementary_stream_map_length = uint16(len(psm.Stream_map) * 4)
|
||||
bsw.PutUint16(psm.Elementary_stream_map_length, 16)
|
||||
for _, streaminfo := range psm.Stream_map {
|
||||
bsw.PutUint8(streaminfo.Stream_type, 8)
|
||||
bsw.PutUint8(streaminfo.Elementary_stream_id, 8)
|
||||
bsw.PutUint16(0, 16)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()/8 + 4
|
||||
bsw.SetUint16(uint16(length), loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(length-4)-4:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
}
|
||||
|
||||
func (psm *Program_stream_map) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 16 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(24) != 0x000001 {
|
||||
panic("program stream map must startwith 0x000001")
|
||||
}
|
||||
psm.Map_stream_id = bs.Uint8(8)
|
||||
if psm.Map_stream_id != 0xBC {
|
||||
panic("map stream id must be 0xBC")
|
||||
}
|
||||
psm.Program_stream_map_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psm.Program_stream_map_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
psm.Current_next_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(2)
|
||||
psm.Program_stream_map_version = bs.Uint8(5)
|
||||
bs.SkipBits(8)
|
||||
psm.Program_stream_info_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psm.Program_stream_info_length)+2 {
|
||||
bs.UnRead(10 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(psm.Program_stream_info_length) * 8)
|
||||
psm.Elementary_stream_map_length = bs.Uint16(16)
|
||||
if psm.Program_stream_map_length != 6+psm.Program_stream_info_length+psm.Elementary_stream_map_length+4 {
|
||||
return errParser
|
||||
}
|
||||
if bs.RemainBytes() < int(psm.Elementary_stream_map_length)+4 {
|
||||
bs.UnRead(12*8 + int(psm.Program_stream_info_length)*8)
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.RemainBytes() < 16 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(24) != 0x000001 {
|
||||
panic("program stream map must startwith 0x000001")
|
||||
}
|
||||
psm.Map_stream_id = bs.Uint8(8)
|
||||
if psm.Map_stream_id != 0xBC {
|
||||
panic("map stream id must be 0xBC")
|
||||
}
|
||||
psm.Program_stream_map_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psm.Program_stream_map_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
psm.Current_next_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(2)
|
||||
psm.Program_stream_map_version = bs.Uint8(5)
|
||||
bs.SkipBits(8)
|
||||
psm.Program_stream_info_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psm.Program_stream_info_length)+2 {
|
||||
bs.UnRead(10 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(psm.Program_stream_info_length) * 8)
|
||||
psm.Elementary_stream_map_length = bs.Uint16(16)
|
||||
if psm.Program_stream_map_length != 6+psm.Program_stream_info_length+psm.Elementary_stream_map_length+4 {
|
||||
return errParser
|
||||
}
|
||||
if bs.RemainBytes() < int(psm.Elementary_stream_map_length)+4 {
|
||||
bs.UnRead(12*8 + int(psm.Program_stream_info_length)*8)
|
||||
return errNeedMore
|
||||
}
|
||||
|
||||
i := 0
|
||||
psm.Stream_map = psm.Stream_map[:0]
|
||||
for i < int(psm.Elementary_stream_map_length) {
|
||||
elem := new(Elementary_stream_elem)
|
||||
elem.Stream_type = bs.Uint8(8)
|
||||
elem.Elementary_stream_id = bs.Uint8(8)
|
||||
elem.Elementary_stream_info_length = bs.Uint16(16)
|
||||
//TODO Parser descriptor
|
||||
if bs.RemainBytes() < int(elem.Elementary_stream_info_length) {
|
||||
return errParser
|
||||
}
|
||||
bs.SkipBits(int(elem.Elementary_stream_info_length) * 8)
|
||||
i += int(4 + elem.Elementary_stream_info_length)
|
||||
psm.Stream_map = append(psm.Stream_map, elem)
|
||||
}
|
||||
i := 0
|
||||
psm.Stream_map = psm.Stream_map[:0]
|
||||
for i < int(psm.Elementary_stream_map_length) {
|
||||
elem := new(Elementary_stream_elem)
|
||||
elem.Stream_type = bs.Uint8(8)
|
||||
elem.Elementary_stream_id = bs.Uint8(8)
|
||||
elem.Elementary_stream_info_length = bs.Uint16(16)
|
||||
//TODO Parser descriptor
|
||||
if bs.RemainBytes() < int(elem.Elementary_stream_info_length) {
|
||||
return errParser
|
||||
}
|
||||
bs.SkipBits(int(elem.Elementary_stream_info_length) * 8)
|
||||
i += int(4 + elem.Elementary_stream_info_length)
|
||||
psm.Stream_map = append(psm.Stream_map, elem)
|
||||
}
|
||||
|
||||
if i != int(psm.Elementary_stream_map_length) {
|
||||
return errParser
|
||||
}
|
||||
if i != int(psm.Elementary_stream_map_length) {
|
||||
return errParser
|
||||
}
|
||||
|
||||
bs.SkipBits(32)
|
||||
return nil
|
||||
bs.SkipBits(32)
|
||||
return nil
|
||||
}
|
||||
|
||||
type Program_stream_directory struct {
|
||||
PES_packet_length uint16
|
||||
PES_packet_length uint16
|
||||
}
|
||||
|
||||
func (psd *Program_stream_directory) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001FF {
|
||||
panic("program stream directory 000001FF")
|
||||
}
|
||||
psd.PES_packet_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psd.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
//TODO Program Stream directory
|
||||
bs.SkipBits(int(psd.PES_packet_length) * 8)
|
||||
return nil
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
if bs.Uint32(32) != 0x000001FF {
|
||||
panic("program stream directory 000001FF")
|
||||
}
|
||||
psd.PES_packet_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(psd.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
//TODO Program Stream directory
|
||||
bs.SkipBits(int(psd.PES_packet_length) * 8)
|
||||
return nil
|
||||
}
|
||||
|
||||
type CommonPesPacket struct {
|
||||
Stream_id uint8
|
||||
PES_packet_length uint16
|
||||
Stream_id uint8
|
||||
PES_packet_length uint16
|
||||
}
|
||||
|
||||
func (compes *CommonPesPacket) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24)
|
||||
compes.Stream_id = bs.Uint8(8)
|
||||
compes.PES_packet_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(compes.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(compes.PES_packet_length) * 8)
|
||||
return nil
|
||||
if bs.RemainBytes() < 6 {
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(24)
|
||||
compes.Stream_id = bs.Uint8(8)
|
||||
compes.PES_packet_length = bs.Uint16(16)
|
||||
if bs.RemainBytes() < int(compes.PES_packet_length) {
|
||||
bs.UnRead(6 * 8)
|
||||
return errNeedMore
|
||||
}
|
||||
bs.SkipBits(int(compes.PES_packet_length) * 8)
|
||||
return nil
|
||||
}
|
||||
|
||||
type PSPacket struct {
|
||||
Header *PSPackHeader
|
||||
System *System_header
|
||||
Psm *Program_stream_map
|
||||
Psd *Program_stream_directory
|
||||
CommPes *CommonPesPacket
|
||||
Pes *PesPacket
|
||||
Header *PSPackHeader
|
||||
System *System_header
|
||||
Psm *Program_stream_map
|
||||
Psd *Program_stream_directory
|
||||
CommPes *CommonPesPacket
|
||||
Pes *PesPacket
|
||||
}
|
||||
|
|
356
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-demuxer.go
generated
vendored
356
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-demuxer.go
generated
vendored
|
@ -1,218 +1,218 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
type pakcet_t struct {
|
||||
payload []byte
|
||||
pts uint64
|
||||
dts uint64
|
||||
payload []byte
|
||||
pts uint64
|
||||
dts uint64
|
||||
}
|
||||
|
||||
func newPacket_t(size uint32) *pakcet_t {
|
||||
return &pakcet_t{
|
||||
payload: make([]byte, 0, size),
|
||||
pts: 0,
|
||||
dts: 0,
|
||||
}
|
||||
return &pakcet_t{
|
||||
payload: make([]byte, 0, size),
|
||||
pts: 0,
|
||||
dts: 0,
|
||||
}
|
||||
}
|
||||
|
||||
type tsstream struct {
|
||||
cid TS_STREAM_TYPE
|
||||
pes_sid PES_STREMA_ID
|
||||
pes_pkg *PesPacket
|
||||
pkg *pakcet_t
|
||||
cid TS_STREAM_TYPE
|
||||
pes_sid PES_STREMA_ID
|
||||
pes_pkg *PesPacket
|
||||
pkg *pakcet_t
|
||||
}
|
||||
|
||||
type tsprogram struct {
|
||||
pn uint16
|
||||
streams map[uint16]*tsstream
|
||||
pn uint16
|
||||
streams map[uint16]*tsstream
|
||||
}
|
||||
|
||||
type TSDemuxer struct {
|
||||
programs map[uint16]*tsprogram
|
||||
OnFrame func(cid TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64)
|
||||
OnTSPacket func(pkg *TSPacket)
|
||||
programs map[uint16]*tsprogram
|
||||
OnFrame func(cid TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64)
|
||||
OnTSPacket func(pkg *TSPacket)
|
||||
}
|
||||
|
||||
func NewTSDemuxer() *TSDemuxer {
|
||||
return &TSDemuxer{
|
||||
programs: make(map[uint16]*tsprogram),
|
||||
OnFrame: nil,
|
||||
OnTSPacket: nil,
|
||||
}
|
||||
return &TSDemuxer{
|
||||
programs: make(map[uint16]*tsprogram),
|
||||
OnFrame: nil,
|
||||
OnTSPacket: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) Input(r io.Reader) error {
|
||||
buf := make([]byte, TS_PAKCET_SIZE)
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
return errNeedMore
|
||||
}
|
||||
for {
|
||||
bs := codec.NewBitStream(buf)
|
||||
var pkg TSPacket
|
||||
if err := pkg.DecodeHeader(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
if pkg.PID == uint16(TS_PID_PAT) {
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
pat := NewPat()
|
||||
if err := pat.Decode(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = pat
|
||||
if pat.Table_id != uint8(TS_TID_PAS) {
|
||||
return errors.New("pat table id is wrong")
|
||||
}
|
||||
for _, pmt := range pat.Pmts {
|
||||
if pmt.Program_number != 0x0000 {
|
||||
if _, found := demuxer.programs[pmt.PID]; !found {
|
||||
demuxer.programs[pmt.PID] = &tsprogram{pn: 0, streams: make(map[uint16]*tsstream)}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for p, s := range demuxer.programs {
|
||||
if p == pkg.PID { // pmt table
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
bs.SkipBits(8) //pointer filed
|
||||
}
|
||||
pmt := NewPmt()
|
||||
if err := pmt.Decode(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = pmt
|
||||
s.pn = pmt.Program_number
|
||||
for _, ps := range pmt.Streams {
|
||||
if _, found := s.streams[ps.Elementary_PID]; !found {
|
||||
s.streams[ps.Elementary_PID] = &tsstream{
|
||||
cid: TS_STREAM_TYPE(ps.StreamType),
|
||||
pes_sid: findPESIDByStreamType(TS_STREAM_TYPE(ps.StreamType)),
|
||||
pes_pkg: NewPesPacket(),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for sid, stream := range s.streams {
|
||||
if sid != pkg.PID {
|
||||
continue
|
||||
}
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
err := stream.pes_pkg.Decode(bs)
|
||||
// ignore error if it was a short payload read, next ts packet should append missing data
|
||||
if err != nil && !(errors.Is(err, errNeedMore) && stream.pes_pkg.Pes_payload != nil) {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = stream.pes_pkg
|
||||
} else {
|
||||
stream.pes_pkg.Pes_payload = bs.RemainData()
|
||||
pkg.Payload = bs.RemainData()
|
||||
}
|
||||
stype := findPESIDByStreamType(stream.cid)
|
||||
if stype == PES_STREAM_AUDIO {
|
||||
demuxer.doAudioPesPacket(stream, pkg.Payload_unit_start_indicator)
|
||||
} else if stype == PES_STREAM_VIDEO {
|
||||
demuxer.doVideoPesPacket(stream, pkg.Payload_unit_start_indicator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if demuxer.OnTSPacket != nil {
|
||||
demuxer.OnTSPacket(&pkg)
|
||||
}
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
} else {
|
||||
return errNeedMore
|
||||
}
|
||||
}
|
||||
}
|
||||
demuxer.flush()
|
||||
return nil
|
||||
buf := make([]byte, TS_PAKCET_SIZE)
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
return errNeedMore
|
||||
}
|
||||
for {
|
||||
bs := codec.NewBitStream(buf)
|
||||
var pkg TSPacket
|
||||
if err := pkg.DecodeHeader(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
if pkg.PID == uint16(TS_PID_PAT) {
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
bs.SkipBits(8)
|
||||
}
|
||||
pat := NewPat()
|
||||
if err := pat.Decode(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = pat
|
||||
if pat.Table_id != uint8(TS_TID_PAS) {
|
||||
return errors.New("pat table id is wrong")
|
||||
}
|
||||
for _, pmt := range pat.Pmts {
|
||||
if pmt.Program_number != 0x0000 {
|
||||
if _, found := demuxer.programs[pmt.PID]; !found {
|
||||
demuxer.programs[pmt.PID] = &tsprogram{pn: 0, streams: make(map[uint16]*tsstream)}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for p, s := range demuxer.programs {
|
||||
if p == pkg.PID { // pmt table
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
bs.SkipBits(8) //pointer filed
|
||||
}
|
||||
pmt := NewPmt()
|
||||
if err := pmt.Decode(bs); err != nil {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = pmt
|
||||
s.pn = pmt.Program_number
|
||||
for _, ps := range pmt.Streams {
|
||||
if _, found := s.streams[ps.Elementary_PID]; !found {
|
||||
s.streams[ps.Elementary_PID] = &tsstream{
|
||||
cid: TS_STREAM_TYPE(ps.StreamType),
|
||||
pes_sid: findPESIDByStreamType(TS_STREAM_TYPE(ps.StreamType)),
|
||||
pes_pkg: NewPesPacket(),
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for sid, stream := range s.streams {
|
||||
if sid != pkg.PID {
|
||||
continue
|
||||
}
|
||||
if pkg.Payload_unit_start_indicator == 1 {
|
||||
err := stream.pes_pkg.Decode(bs)
|
||||
// ignore error if it was a short payload read, next ts packet should append missing data
|
||||
if err != nil && !(errors.Is(err, errNeedMore) && stream.pes_pkg.Pes_payload != nil) {
|
||||
return err
|
||||
}
|
||||
pkg.Payload = stream.pes_pkg
|
||||
} else {
|
||||
stream.pes_pkg.Pes_payload = bs.RemainData()
|
||||
pkg.Payload = bs.RemainData()
|
||||
}
|
||||
stype := findPESIDByStreamType(stream.cid)
|
||||
if stype == PES_STREAM_AUDIO {
|
||||
demuxer.doAudioPesPacket(stream, pkg.Payload_unit_start_indicator)
|
||||
} else if stype == PES_STREAM_VIDEO {
|
||||
demuxer.doVideoPesPacket(stream, pkg.Payload_unit_start_indicator)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if demuxer.OnTSPacket != nil {
|
||||
demuxer.OnTSPacket(&pkg)
|
||||
}
|
||||
_, err := io.ReadFull(r, buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
} else {
|
||||
return errNeedMore
|
||||
}
|
||||
}
|
||||
}
|
||||
demuxer.flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) flush() {
|
||||
for _, pm := range demuxer.programs {
|
||||
for _, stream := range pm.streams {
|
||||
if stream.pkg == nil || len(stream.pkg.payload) == 0 {
|
||||
continue
|
||||
}
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, pm := range demuxer.programs {
|
||||
for _, stream := range pm.streams {
|
||||
if stream.pkg == nil || len(stream.pkg.payload) == 0 {
|
||||
continue
|
||||
}
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) doVideoPesPacket(stream *tsstream, start uint8) {
|
||||
if stream.cid != TS_STREAM_H264 && stream.cid != TS_STREAM_H265 {
|
||||
return
|
||||
}
|
||||
if stream.pkg == nil {
|
||||
stream.pkg = newPacket_t(1024)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
|
||||
demuxer.splitH26XFrame(stream)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
if stream.cid != TS_STREAM_H264 && stream.cid != TS_STREAM_H265 {
|
||||
return
|
||||
}
|
||||
if stream.pkg == nil {
|
||||
stream.pkg = newPacket_t(1024)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
|
||||
demuxer.splitH26XFrame(stream)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) doAudioPesPacket(stream *tsstream, start uint8) {
|
||||
if stream.cid != TS_STREAM_AAC {
|
||||
return
|
||||
}
|
||||
if stream.cid != TS_STREAM_AAC {
|
||||
return
|
||||
}
|
||||
|
||||
if stream.pkg == nil {
|
||||
stream.pkg = newPacket_t(1024)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
if stream.pkg == nil {
|
||||
stream.pkg = newPacket_t(1024)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
|
||||
if len(stream.pkg.payload) > 0 && (start == 1 || stream.pes_pkg.Pts != stream.pkg.pts) {
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
stream.pkg.payload = stream.pkg.payload[:0]
|
||||
}
|
||||
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
if len(stream.pkg.payload) > 0 && (start == 1 || stream.pes_pkg.Pts != stream.pkg.pts) {
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, stream.pkg.payload, stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
stream.pkg.payload = stream.pkg.payload[:0]
|
||||
}
|
||||
stream.pkg.payload = append(stream.pkg.payload, stream.pes_pkg.Pes_payload...)
|
||||
stream.pkg.pts = stream.pes_pkg.Pts
|
||||
stream.pkg.dts = stream.pes_pkg.Dts
|
||||
}
|
||||
|
||||
func (demuxer *TSDemuxer) splitH26XFrame(stream *tsstream) {
|
||||
data := stream.pkg.payload
|
||||
start, _ := codec.FindStartCode(data, 0)
|
||||
datalen := len(data)
|
||||
for start < datalen {
|
||||
end, _ := codec.FindStartCode(data, start+3)
|
||||
if end < 0 {
|
||||
break
|
||||
}
|
||||
if (stream.cid == TS_STREAM_H264 && codec.H264NaluTypeWithoutStartCode(data[start:end]) == codec.H264_NAL_AUD) ||
|
||||
(stream.cid == TS_STREAM_H265 && codec.H265NaluTypeWithoutStartCode(data[start:end]) == codec.H265_NAL_AUD) {
|
||||
start = end
|
||||
continue
|
||||
}
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, data[start:end], stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
start = end
|
||||
}
|
||||
if start == 0 {
|
||||
return
|
||||
}
|
||||
copy(stream.pkg.payload, data[start:datalen])
|
||||
stream.pkg.payload = stream.pkg.payload[0 : datalen-start]
|
||||
data := stream.pkg.payload
|
||||
start, _ := codec.FindStartCode(data, 0)
|
||||
datalen := len(data)
|
||||
for start < datalen {
|
||||
end, _ := codec.FindStartCode(data, start+3)
|
||||
if end < 0 {
|
||||
break
|
||||
}
|
||||
if (stream.cid == TS_STREAM_H264 && codec.H264NaluTypeWithoutStartCode(data[start:end]) == codec.H264_NAL_AUD) ||
|
||||
(stream.cid == TS_STREAM_H265 && codec.H265NaluTypeWithoutStartCode(data[start:end]) == codec.H265_NAL_AUD) {
|
||||
start = end
|
||||
continue
|
||||
}
|
||||
if demuxer.OnFrame != nil {
|
||||
demuxer.OnFrame(stream.cid, data[start:end], stream.pkg.pts/90, stream.pkg.dts/90)
|
||||
}
|
||||
start = end
|
||||
}
|
||||
if start == 0 {
|
||||
return
|
||||
}
|
||||
copy(stream.pkg.payload, data[start:datalen])
|
||||
stream.pkg.payload = stream.pkg.payload[0 : datalen-start]
|
||||
}
|
||||
|
|
548
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-muxer.go
generated
vendored
548
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-muxer.go
generated
vendored
|
@ -1,93 +1,93 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"errors"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
type pes_stream struct {
|
||||
pid uint16
|
||||
cc uint8
|
||||
streamtype TS_STREAM_TYPE
|
||||
pid uint16
|
||||
cc uint8
|
||||
streamtype TS_STREAM_TYPE
|
||||
}
|
||||
|
||||
func NewPESStream(pid uint16, cid TS_STREAM_TYPE) *pes_stream {
|
||||
return &pes_stream{
|
||||
pid: pid,
|
||||
cc: 0,
|
||||
streamtype: cid,
|
||||
}
|
||||
return &pes_stream{
|
||||
pid: pid,
|
||||
cc: 0,
|
||||
streamtype: cid,
|
||||
}
|
||||
}
|
||||
|
||||
type table_pmt struct {
|
||||
pid uint16
|
||||
cc uint8
|
||||
pcr_pid uint16
|
||||
version_number uint8
|
||||
pm uint16
|
||||
streams []*pes_stream
|
||||
pid uint16
|
||||
cc uint8
|
||||
pcr_pid uint16
|
||||
version_number uint8
|
||||
pm uint16
|
||||
streams []*pes_stream
|
||||
}
|
||||
|
||||
func NewTablePmt() *table_pmt {
|
||||
return &table_pmt{
|
||||
pid: 0,
|
||||
cc: 0,
|
||||
pcr_pid: 0,
|
||||
version_number: 0,
|
||||
pm: 0,
|
||||
streams: make([]*pes_stream, 0, 2),
|
||||
}
|
||||
return &table_pmt{
|
||||
pid: 0,
|
||||
cc: 0,
|
||||
pcr_pid: 0,
|
||||
version_number: 0,
|
||||
pm: 0,
|
||||
streams: make([]*pes_stream, 0, 2),
|
||||
}
|
||||
}
|
||||
|
||||
type table_pat struct {
|
||||
cc uint8
|
||||
version_number uint8
|
||||
pmts []*table_pmt
|
||||
cc uint8
|
||||
version_number uint8
|
||||
pmts []*table_pmt
|
||||
}
|
||||
|
||||
func NewTablePat() *table_pat {
|
||||
return &table_pat{
|
||||
cc: 0,
|
||||
version_number: 0,
|
||||
pmts: make([]*table_pmt, 0, 8),
|
||||
}
|
||||
return &table_pat{
|
||||
cc: 0,
|
||||
version_number: 0,
|
||||
pmts: make([]*table_pmt, 0, 8),
|
||||
}
|
||||
}
|
||||
|
||||
type TSMuxer struct {
|
||||
pat *table_pat
|
||||
stream_pid uint16
|
||||
pmt_pid uint16
|
||||
pat_period uint64
|
||||
OnPacket func(pkg []byte)
|
||||
pat *table_pat
|
||||
stream_pid uint16
|
||||
pmt_pid uint16
|
||||
pat_period uint64
|
||||
OnPacket func(pkg []byte)
|
||||
}
|
||||
|
||||
func NewTSMuxer() *TSMuxer {
|
||||
return &TSMuxer{
|
||||
pat: NewTablePat(),
|
||||
stream_pid: 0x100,
|
||||
pmt_pid: 0x200,
|
||||
pat_period: 0,
|
||||
OnPacket: nil,
|
||||
}
|
||||
return &TSMuxer{
|
||||
pat: NewTablePat(),
|
||||
stream_pid: 0x100,
|
||||
pmt_pid: 0x200,
|
||||
pat_period: 0,
|
||||
OnPacket: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (mux *TSMuxer) AddStream(cid TS_STREAM_TYPE) uint16 {
|
||||
if mux.pat == nil {
|
||||
mux.pat = NewTablePat()
|
||||
}
|
||||
if len(mux.pat.pmts) == 0 {
|
||||
tmppmt := NewTablePmt()
|
||||
tmppmt.pid = mux.pmt_pid
|
||||
tmppmt.pm = 1
|
||||
mux.pmt_pid++
|
||||
mux.pat.pmts = append(mux.pat.pmts, tmppmt)
|
||||
}
|
||||
sid := mux.stream_pid
|
||||
tmpstream := NewPESStream(sid, cid)
|
||||
mux.stream_pid++
|
||||
mux.pat.pmts[0].streams = append(mux.pat.pmts[0].streams, tmpstream)
|
||||
return sid
|
||||
if mux.pat == nil {
|
||||
mux.pat = NewTablePat()
|
||||
}
|
||||
if len(mux.pat.pmts) == 0 {
|
||||
tmppmt := NewTablePmt()
|
||||
tmppmt.pid = mux.pmt_pid
|
||||
tmppmt.pm = 1
|
||||
mux.pmt_pid++
|
||||
mux.pat.pmts = append(mux.pat.pmts, tmppmt)
|
||||
}
|
||||
sid := mux.stream_pid
|
||||
tmpstream := NewPESStream(sid, cid)
|
||||
mux.stream_pid++
|
||||
mux.pat.pmts[0].streams = append(mux.pat.pmts[0].streams, tmpstream)
|
||||
return sid
|
||||
}
|
||||
|
||||
/// Muxer audio/video stream data
|
||||
|
@ -95,239 +95,239 @@ func (mux *TSMuxer) AddStream(cid TS_STREAM_TYPE) uint16 {
|
|||
/// pts: audio/video stream timestamp in ms
|
||||
/// dts: audio/video stream timestamp in ms
|
||||
func (mux *TSMuxer) Write(pid uint16, data []byte, pts uint64, dts uint64) error {
|
||||
var whichpmt *table_pmt = nil
|
||||
var whichstream *pes_stream = nil
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
for _, stream := range pmt.streams {
|
||||
if stream.pid == pid {
|
||||
whichpmt = pmt
|
||||
whichstream = stream
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if whichpmt == nil || whichstream == nil {
|
||||
return errors.New("not Found pid stream")
|
||||
}
|
||||
if whichpmt.pcr_pid == 0 || (findPESIDByStreamType(whichstream.streamtype) == PES_STREAM_VIDEO && whichpmt.pcr_pid != pid) {
|
||||
whichpmt.pcr_pid = pid
|
||||
}
|
||||
var whichpmt *table_pmt = nil
|
||||
var whichstream *pes_stream = nil
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
for _, stream := range pmt.streams {
|
||||
if stream.pid == pid {
|
||||
whichpmt = pmt
|
||||
whichstream = stream
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if whichpmt == nil || whichstream == nil {
|
||||
return errors.New("not Found pid stream")
|
||||
}
|
||||
if whichpmt.pcr_pid == 0 || (findPESIDByStreamType(whichstream.streamtype) == PES_STREAM_VIDEO && whichpmt.pcr_pid != pid) {
|
||||
whichpmt.pcr_pid = pid
|
||||
}
|
||||
|
||||
var withaud bool = false
|
||||
var withaud bool = false
|
||||
|
||||
if whichstream.streamtype == TS_STREAM_H264 || whichstream.streamtype == TS_STREAM_H265 {
|
||||
codec.SplitFrame(data, func(nalu []byte) bool {
|
||||
if whichstream.streamtype == TS_STREAM_H264 {
|
||||
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H264_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH264VCLNaluType(nalu_type) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H265_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH265VCLNaluType(nalu_type) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
if whichstream.streamtype == TS_STREAM_H264 || whichstream.streamtype == TS_STREAM_H265 {
|
||||
codec.SplitFrame(data, func(nalu []byte) bool {
|
||||
if whichstream.streamtype == TS_STREAM_H264 {
|
||||
nalu_type := codec.H264NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H264_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH264VCLNaluType(nalu_type) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
nalu_type := codec.H265NaluTypeWithoutStartCode(nalu)
|
||||
if nalu_type == codec.H265_NAL_AUD {
|
||||
withaud = true
|
||||
return false
|
||||
} else if codec.IsH265VCLNaluType(nalu_type) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if mux.pat_period == 0 || mux.pat_period+400 < dts {
|
||||
mux.pat_period = dts
|
||||
if mux.pat_period == 0 {
|
||||
mux.pat_period = 1 //avoid write pat twice
|
||||
}
|
||||
tmppat := NewPat()
|
||||
tmppat.Version_number = mux.pat.version_number
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
tmppm := PmtPair{
|
||||
Program_number: pmt.pm,
|
||||
PID: pmt.pid,
|
||||
}
|
||||
tmppat.Pmts = append(tmppat.Pmts, tmppm)
|
||||
}
|
||||
mux.writePat(tmppat)
|
||||
if mux.pat_period == 0 || mux.pat_period+400 < dts {
|
||||
mux.pat_period = dts
|
||||
if mux.pat_period == 0 {
|
||||
mux.pat_period = 1 //avoid write pat twice
|
||||
}
|
||||
tmppat := NewPat()
|
||||
tmppat.Version_number = mux.pat.version_number
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
tmppm := PmtPair{
|
||||
Program_number: pmt.pm,
|
||||
PID: pmt.pid,
|
||||
}
|
||||
tmppat.Pmts = append(tmppat.Pmts, tmppm)
|
||||
}
|
||||
mux.writePat(tmppat)
|
||||
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
tmppmt := NewPmt()
|
||||
tmppmt.Program_number = pmt.pm
|
||||
tmppmt.Version_number = pmt.version_number
|
||||
tmppmt.PCR_PID = pmt.pcr_pid
|
||||
for _, stream := range pmt.streams {
|
||||
var sp StreamPair
|
||||
sp.StreamType = uint8(stream.streamtype)
|
||||
sp.Elementary_PID = stream.pid
|
||||
sp.ES_Info_Length = 0
|
||||
tmppmt.Streams = append(tmppmt.Streams, sp)
|
||||
}
|
||||
mux.writePmt(tmppmt, pmt)
|
||||
}
|
||||
}
|
||||
for _, pmt := range mux.pat.pmts {
|
||||
tmppmt := NewPmt()
|
||||
tmppmt.Program_number = pmt.pm
|
||||
tmppmt.Version_number = pmt.version_number
|
||||
tmppmt.PCR_PID = pmt.pcr_pid
|
||||
for _, stream := range pmt.streams {
|
||||
var sp StreamPair
|
||||
sp.StreamType = uint8(stream.streamtype)
|
||||
sp.Elementary_PID = stream.pid
|
||||
sp.ES_Info_Length = 0
|
||||
tmppmt.Streams = append(tmppmt.Streams, sp)
|
||||
}
|
||||
mux.writePmt(tmppmt, pmt)
|
||||
}
|
||||
}
|
||||
|
||||
flag := false
|
||||
switch whichstream.streamtype {
|
||||
case TS_STREAM_H264:
|
||||
flag = codec.IsH264IDRFrame(data)
|
||||
case TS_STREAM_H265:
|
||||
flag = codec.IsH265IDRFrame(data)
|
||||
}
|
||||
flag := false
|
||||
switch whichstream.streamtype {
|
||||
case TS_STREAM_H264:
|
||||
flag = codec.IsH264IDRFrame(data)
|
||||
case TS_STREAM_H265:
|
||||
flag = codec.IsH265IDRFrame(data)
|
||||
}
|
||||
|
||||
mux.writePES(whichstream, whichpmt, data, pts*90, dts*90, flag, withaud)
|
||||
return nil
|
||||
mux.writePES(whichstream, whichpmt, data, pts*90, dts*90, flag, withaud)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mux *TSMuxer) writePat(pat *Pat) {
|
||||
var tshdr TSPacket
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
tshdr.PID = 0
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = mux.pat.cc
|
||||
mux.pat.cc++
|
||||
mux.pat.cc = (mux.pat.cc + 1) % 16
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
tshdr.EncodeHeader(bsw)
|
||||
bsw.PutByte(0x00) //pointer
|
||||
pat.Encode(bsw)
|
||||
bsw.FillRemainData(0xff)
|
||||
if mux.OnPacket != nil {
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
var tshdr TSPacket
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
tshdr.PID = 0
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = mux.pat.cc
|
||||
mux.pat.cc++
|
||||
mux.pat.cc = (mux.pat.cc + 1) % 16
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
tshdr.EncodeHeader(bsw)
|
||||
bsw.PutByte(0x00) //pointer
|
||||
pat.Encode(bsw)
|
||||
bsw.FillRemainData(0xff)
|
||||
if mux.OnPacket != nil {
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
}
|
||||
|
||||
func (mux *TSMuxer) writePmt(pmt *Pmt, t_pmt *table_pmt) {
|
||||
var tshdr TSPacket
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
tshdr.PID = t_pmt.pid
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = t_pmt.cc
|
||||
t_pmt.cc = (t_pmt.cc + 1) % 16
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
tshdr.EncodeHeader(bsw)
|
||||
bsw.PutByte(0x00) //pointer
|
||||
pmt.Encode(bsw)
|
||||
bsw.FillRemainData(0xff)
|
||||
if mux.OnPacket != nil {
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
var tshdr TSPacket
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
tshdr.PID = t_pmt.pid
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = t_pmt.cc
|
||||
t_pmt.cc = (t_pmt.cc + 1) % 16
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
tshdr.EncodeHeader(bsw)
|
||||
bsw.PutByte(0x00) //pointer
|
||||
pmt.Encode(bsw)
|
||||
bsw.FillRemainData(0xff)
|
||||
if mux.OnPacket != nil {
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
}
|
||||
|
||||
func (mux *TSMuxer) writePES(pes *pes_stream, pmt *table_pmt, data []byte, pts uint64, dts uint64, idr_flag bool, withaud bool) {
|
||||
var firstPesPacket bool = true
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
for {
|
||||
bsw.Reset()
|
||||
var tshdr TSPacket
|
||||
if firstPesPacket {
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
}
|
||||
tshdr.PID = pes.pid
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = pes.cc
|
||||
headlen := 4
|
||||
pes.cc = (pes.cc + 1) % 16
|
||||
var adaptation *Adaptation_field = nil
|
||||
if firstPesPacket && idr_flag {
|
||||
adaptation = new(Adaptation_field)
|
||||
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
|
||||
adaptation.Random_access_indicator = 1
|
||||
headlen += 2
|
||||
}
|
||||
var firstPesPacket bool = true
|
||||
bsw := codec.NewBitStreamWriter(TS_PAKCET_SIZE)
|
||||
for {
|
||||
bsw.Reset()
|
||||
var tshdr TSPacket
|
||||
if firstPesPacket {
|
||||
tshdr.Payload_unit_start_indicator = 1
|
||||
}
|
||||
tshdr.PID = pes.pid
|
||||
tshdr.Adaptation_field_control = 0x01
|
||||
tshdr.Continuity_counter = pes.cc
|
||||
headlen := 4
|
||||
pes.cc = (pes.cc + 1) % 16
|
||||
var adaptation *Adaptation_field = nil
|
||||
if firstPesPacket && idr_flag {
|
||||
adaptation = new(Adaptation_field)
|
||||
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
|
||||
adaptation.Random_access_indicator = 1
|
||||
headlen += 2
|
||||
}
|
||||
|
||||
if firstPesPacket && pes.pid == pmt.pcr_pid {
|
||||
if adaptation == nil {
|
||||
adaptation = new(Adaptation_field)
|
||||
headlen += 2
|
||||
}
|
||||
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
|
||||
adaptation.PCR_flag = 1
|
||||
var pcr_base uint64 = 0
|
||||
var pcr_ext uint16 = 0
|
||||
if dts == 0 {
|
||||
pcr_base = pts * 300 / 300
|
||||
pcr_ext = uint16(pts * 300 % 300)
|
||||
} else {
|
||||
pcr_base = dts * 300 / 300
|
||||
pcr_ext = uint16(dts * 300 % 300)
|
||||
}
|
||||
adaptation.Program_clock_reference_base = pcr_base
|
||||
adaptation.Program_clock_reference_extension = pcr_ext
|
||||
headlen += 6
|
||||
}
|
||||
if firstPesPacket && pes.pid == pmt.pcr_pid {
|
||||
if adaptation == nil {
|
||||
adaptation = new(Adaptation_field)
|
||||
headlen += 2
|
||||
}
|
||||
tshdr.Adaptation_field_control = tshdr.Adaptation_field_control | 0x20
|
||||
adaptation.PCR_flag = 1
|
||||
var pcr_base uint64 = 0
|
||||
var pcr_ext uint16 = 0
|
||||
if dts == 0 {
|
||||
pcr_base = pts * 300 / 300
|
||||
pcr_ext = uint16(pts * 300 % 300)
|
||||
} else {
|
||||
pcr_base = dts * 300 / 300
|
||||
pcr_ext = uint16(dts * 300 % 300)
|
||||
}
|
||||
adaptation.Program_clock_reference_base = pcr_base
|
||||
adaptation.Program_clock_reference_extension = pcr_ext
|
||||
headlen += 6
|
||||
}
|
||||
|
||||
var payload []byte
|
||||
var pespkg *PesPacket = nil
|
||||
if firstPesPacket {
|
||||
oldheadlen := headlen
|
||||
headlen += 19
|
||||
if !withaud && pes.streamtype == TS_STREAM_H264 {
|
||||
headlen += 6
|
||||
payload = append(payload, H264_AUD_NALU...)
|
||||
} else if !withaud && pes.streamtype == TS_STREAM_H265 {
|
||||
payload = append(payload, H265_AUD_NALU...)
|
||||
headlen += 7
|
||||
}
|
||||
pespkg = NewPesPacket()
|
||||
pespkg.PTS_DTS_flags = 0x03
|
||||
pespkg.PES_header_data_length = 10
|
||||
pespkg.Pts = pts
|
||||
pespkg.Dts = dts
|
||||
pespkg.Stream_id = uint8(findPESIDByStreamType(pes.streamtype))
|
||||
if idr_flag {
|
||||
pespkg.Data_alignment_indicator = 1
|
||||
}
|
||||
if headlen-oldheadlen-6+len(data) > 0xFFFF {
|
||||
pespkg.PES_packet_length = 0
|
||||
} else {
|
||||
pespkg.PES_packet_length = uint16(len(data) + headlen - oldheadlen - 6)
|
||||
}
|
||||
var payload []byte
|
||||
var pespkg *PesPacket = nil
|
||||
if firstPesPacket {
|
||||
oldheadlen := headlen
|
||||
headlen += 19
|
||||
if !withaud && pes.streamtype == TS_STREAM_H264 {
|
||||
headlen += 6
|
||||
payload = append(payload, H264_AUD_NALU...)
|
||||
} else if !withaud && pes.streamtype == TS_STREAM_H265 {
|
||||
payload = append(payload, H265_AUD_NALU...)
|
||||
headlen += 7
|
||||
}
|
||||
pespkg = NewPesPacket()
|
||||
pespkg.PTS_DTS_flags = 0x03
|
||||
pespkg.PES_header_data_length = 10
|
||||
pespkg.Pts = pts
|
||||
pespkg.Dts = dts
|
||||
pespkg.Stream_id = uint8(findPESIDByStreamType(pes.streamtype))
|
||||
if idr_flag {
|
||||
pespkg.Data_alignment_indicator = 1
|
||||
}
|
||||
if headlen-oldheadlen-6+len(data) > 0xFFFF {
|
||||
pespkg.PES_packet_length = 0
|
||||
} else {
|
||||
pespkg.PES_packet_length = uint16(len(data) + headlen - oldheadlen - 6)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if len(data)+headlen < TS_PAKCET_SIZE {
|
||||
if adaptation == nil {
|
||||
adaptation = new(Adaptation_field)
|
||||
headlen += 1
|
||||
if TS_PAKCET_SIZE-len(data)-headlen >= 1 {
|
||||
headlen += 1
|
||||
} else {
|
||||
adaptation.SingleStuffingByte = true
|
||||
}
|
||||
}
|
||||
adaptation.Stuffing_byte = uint8(TS_PAKCET_SIZE - len(data) - headlen)
|
||||
payload = append(payload, data...)
|
||||
data = data[:0]
|
||||
} else {
|
||||
payload = append(payload, data[0:TS_PAKCET_SIZE-headlen]...)
|
||||
data = data[TS_PAKCET_SIZE-headlen:]
|
||||
}
|
||||
if len(data)+headlen < TS_PAKCET_SIZE {
|
||||
if adaptation == nil {
|
||||
adaptation = new(Adaptation_field)
|
||||
headlen += 1
|
||||
if TS_PAKCET_SIZE-len(data)-headlen >= 1 {
|
||||
headlen += 1
|
||||
} else {
|
||||
adaptation.SingleStuffingByte = true
|
||||
}
|
||||
}
|
||||
adaptation.Stuffing_byte = uint8(TS_PAKCET_SIZE - len(data) - headlen)
|
||||
payload = append(payload, data...)
|
||||
data = data[:0]
|
||||
} else {
|
||||
payload = append(payload, data[0:TS_PAKCET_SIZE-headlen]...)
|
||||
data = data[TS_PAKCET_SIZE-headlen:]
|
||||
}
|
||||
|
||||
if adaptation != nil {
|
||||
tshdr.Field = adaptation
|
||||
tshdr.Adaptation_field_control |= 0x02
|
||||
}
|
||||
tshdr.EncodeHeader(bsw)
|
||||
if pespkg != nil {
|
||||
pespkg.Pes_payload = payload
|
||||
pespkg.Encode(bsw)
|
||||
} else {
|
||||
bsw.PutBytes(payload)
|
||||
}
|
||||
firstPesPacket = false
|
||||
if mux.OnPacket != nil {
|
||||
if len(bsw.Bits()) != TS_PAKCET_SIZE {
|
||||
panic("packet ts packet failed")
|
||||
}
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
if len(data) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if adaptation != nil {
|
||||
tshdr.Field = adaptation
|
||||
tshdr.Adaptation_field_control |= 0x02
|
||||
}
|
||||
tshdr.EncodeHeader(bsw)
|
||||
if pespkg != nil {
|
||||
pespkg.Pes_payload = payload
|
||||
pespkg.Encode(bsw)
|
||||
} else {
|
||||
bsw.PutBytes(payload)
|
||||
}
|
||||
firstPesPacket = false
|
||||
if mux.OnPacket != nil {
|
||||
if len(bsw.Bits()) != TS_PAKCET_SIZE {
|
||||
panic("packet ts packet failed")
|
||||
}
|
||||
mux.OnPacket(bsw.Bits())
|
||||
}
|
||||
if len(data) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
864
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-proto.go
generated
vendored
864
trunk/3rdparty/srs-bench/vendor/github.com/yapingcat/gomedia/mpeg2/ts-proto.go
generated
vendored
|
@ -1,50 +1,50 @@
|
|||
package mpeg2
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
)
|
||||
|
||||
//PID
|
||||
type TS_PID int
|
||||
|
||||
const (
|
||||
TS_PID_PAT TS_PID = 0x0000
|
||||
TS_PID_CAT
|
||||
TS_PID_TSDT
|
||||
TS_PID_IPMP
|
||||
TS_PID_Nil = 0x1FFFF
|
||||
TS_PID_PAT TS_PID = 0x0000
|
||||
TS_PID_CAT
|
||||
TS_PID_TSDT
|
||||
TS_PID_IPMP
|
||||
TS_PID_Nil = 0x1FFFF
|
||||
)
|
||||
|
||||
//Table id
|
||||
type PAT_TID int
|
||||
|
||||
const (
|
||||
TS_TID_PAS PAT_TID = 0x00 // program_association_section
|
||||
TS_TID_CAS = 0x01 // conditional_access_section(CA_section)
|
||||
TS_TID_PMS = 0x02 // TS_program_map_section
|
||||
TS_TID_SDS = 0x03 //TS_description_section
|
||||
TS_TID_FORBIDDEN PAT_TID = 0xFF
|
||||
TS_TID_PAS PAT_TID = 0x00 // program_association_section
|
||||
TS_TID_CAS = 0x01 // conditional_access_section(CA_section)
|
||||
TS_TID_PMS = 0x02 // TS_program_map_section
|
||||
TS_TID_SDS = 0x03 //TS_description_section
|
||||
TS_TID_FORBIDDEN PAT_TID = 0xFF
|
||||
)
|
||||
|
||||
type TS_STREAM_TYPE int
|
||||
|
||||
const (
|
||||
TS_STREAM_AAC TS_STREAM_TYPE = 0x0F
|
||||
TS_STREAM_H264 TS_STREAM_TYPE = 0x1B
|
||||
TS_STREAM_H265 TS_STREAM_TYPE = 0x24
|
||||
TS_STREAM_AAC TS_STREAM_TYPE = 0x0F
|
||||
TS_STREAM_H264 TS_STREAM_TYPE = 0x1B
|
||||
TS_STREAM_H265 TS_STREAM_TYPE = 0x24
|
||||
)
|
||||
|
||||
const (
|
||||
TS_PAKCET_SIZE = 188
|
||||
TS_PAKCET_SIZE = 188
|
||||
)
|
||||
|
||||
type Display interface {
|
||||
PrettyPrint(file *os.File)
|
||||
PrettyPrint(file *os.File)
|
||||
}
|
||||
|
||||
// transport_packet(){
|
||||
|
@ -67,63 +67,63 @@ type Display interface {
|
|||
// }
|
||||
|
||||
type TSPacket struct {
|
||||
Transport_error_indicator uint8
|
||||
Payload_unit_start_indicator uint8
|
||||
Transport_priority uint8
|
||||
PID uint16
|
||||
Transport_scrambling_control uint8
|
||||
Adaptation_field_control uint8
|
||||
Continuity_counter uint8
|
||||
Field *Adaptation_field
|
||||
Payload interface{}
|
||||
Transport_error_indicator uint8
|
||||
Payload_unit_start_indicator uint8
|
||||
Transport_priority uint8
|
||||
PID uint16
|
||||
Transport_scrambling_control uint8
|
||||
Adaptation_field_control uint8
|
||||
Continuity_counter uint8
|
||||
Field *Adaptation_field
|
||||
Payload interface{}
|
||||
}
|
||||
|
||||
func (pkg *TSPacket) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Transport_error_indicator:%d\n", pkg.Transport_error_indicator))
|
||||
file.WriteString(fmt.Sprintf("Payload_unit_start_indicator:%d\n", pkg.Payload_unit_start_indicator))
|
||||
file.WriteString(fmt.Sprintf("Transport_priority:%d\n", pkg.Transport_priority))
|
||||
file.WriteString(fmt.Sprintf("PID:%d\n", pkg.PID))
|
||||
file.WriteString(fmt.Sprintf("Transport_scrambling_control:%d\n", pkg.Transport_scrambling_control))
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_control:%d\n", pkg.Adaptation_field_control))
|
||||
file.WriteString(fmt.Sprintf("Continuity_counter:%d\n", pkg.Continuity_counter))
|
||||
file.WriteString(fmt.Sprintf("Transport_error_indicator:%d\n", pkg.Transport_error_indicator))
|
||||
file.WriteString(fmt.Sprintf("Payload_unit_start_indicator:%d\n", pkg.Payload_unit_start_indicator))
|
||||
file.WriteString(fmt.Sprintf("Transport_priority:%d\n", pkg.Transport_priority))
|
||||
file.WriteString(fmt.Sprintf("PID:%d\n", pkg.PID))
|
||||
file.WriteString(fmt.Sprintf("Transport_scrambling_control:%d\n", pkg.Transport_scrambling_control))
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_control:%d\n", pkg.Adaptation_field_control))
|
||||
file.WriteString(fmt.Sprintf("Continuity_counter:%d\n", pkg.Continuity_counter))
|
||||
}
|
||||
|
||||
func (pkg *TSPacket) EncodeHeader(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutByte(0x47)
|
||||
bsw.PutUint8(pkg.Transport_error_indicator, 1)
|
||||
bsw.PutUint8(pkg.Payload_unit_start_indicator, 1)
|
||||
bsw.PutUint8(pkg.Transport_priority, 1)
|
||||
bsw.PutUint16(pkg.PID, 13)
|
||||
bsw.PutUint8(pkg.Transport_scrambling_control, 2)
|
||||
bsw.PutUint8(pkg.Adaptation_field_control, 2)
|
||||
bsw.PutUint8(pkg.Continuity_counter, 4)
|
||||
if pkg.Field != nil && (pkg.Adaptation_field_control&0x02) != 0 {
|
||||
pkg.Field.Encode(bsw)
|
||||
}
|
||||
bsw.PutByte(0x47)
|
||||
bsw.PutUint8(pkg.Transport_error_indicator, 1)
|
||||
bsw.PutUint8(pkg.Payload_unit_start_indicator, 1)
|
||||
bsw.PutUint8(pkg.Transport_priority, 1)
|
||||
bsw.PutUint16(pkg.PID, 13)
|
||||
bsw.PutUint8(pkg.Transport_scrambling_control, 2)
|
||||
bsw.PutUint8(pkg.Adaptation_field_control, 2)
|
||||
bsw.PutUint8(pkg.Continuity_counter, 4)
|
||||
if pkg.Field != nil && (pkg.Adaptation_field_control&0x02) != 0 {
|
||||
pkg.Field.Encode(bsw)
|
||||
}
|
||||
}
|
||||
|
||||
func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error {
|
||||
sync_byte := bs.Uint8(8)
|
||||
if sync_byte != 0x47 {
|
||||
return errors.New("ts packet must start with 0x47")
|
||||
}
|
||||
pkg.Transport_error_indicator = bs.GetBit()
|
||||
pkg.Payload_unit_start_indicator = bs.GetBit()
|
||||
pkg.Transport_priority = bs.GetBit()
|
||||
pkg.PID = bs.Uint16(13)
|
||||
pkg.Transport_scrambling_control = bs.Uint8(2)
|
||||
pkg.Adaptation_field_control = bs.Uint8(2)
|
||||
pkg.Continuity_counter = bs.Uint8(4)
|
||||
if pkg.Adaptation_field_control == 0x02 || pkg.Adaptation_field_control == 0x03 {
|
||||
if pkg.Field == nil {
|
||||
pkg.Field = new(Adaptation_field)
|
||||
}
|
||||
err := pkg.Field.Decode(bs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
sync_byte := bs.Uint8(8)
|
||||
if sync_byte != 0x47 {
|
||||
return errors.New("ts packet must start with 0x47")
|
||||
}
|
||||
pkg.Transport_error_indicator = bs.GetBit()
|
||||
pkg.Payload_unit_start_indicator = bs.GetBit()
|
||||
pkg.Transport_priority = bs.GetBit()
|
||||
pkg.PID = bs.Uint16(13)
|
||||
pkg.Transport_scrambling_control = bs.Uint8(2)
|
||||
pkg.Adaptation_field_control = bs.Uint8(2)
|
||||
pkg.Continuity_counter = bs.Uint8(4)
|
||||
if pkg.Adaptation_field_control == 0x02 || pkg.Adaptation_field_control == 0x03 {
|
||||
if pkg.Field == nil {
|
||||
pkg.Field = new(Adaptation_field)
|
||||
}
|
||||
err := pkg.Field.Decode(bs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -189,414 +189,414 @@ func (pkg *TSPacket) DecodeHeader(bs *codec.BitStream) error {
|
|||
// }
|
||||
|
||||
type Adaptation_field struct {
|
||||
SingleStuffingByte bool // The value 0 is for inserting a single stuffing byte in a Transport Stream packet
|
||||
Adaptation_field_length uint8 //8 uimsbf
|
||||
Discontinuity_indicator uint8 //1 bslbf
|
||||
Random_access_indicator uint8 //1 bslbf
|
||||
Elementary_stream_priority_indicator uint8 //1 bslbf
|
||||
PCR_flag uint8 //1 bslbf
|
||||
OPCR_flag uint8 //1 bslbf
|
||||
Splicing_point_flag uint8 //1 bslbf
|
||||
Transport_private_data_flag uint8 //1 bslbf
|
||||
Adaptation_field_extension_flag uint8 //1 bslbf
|
||||
Program_clock_reference_base uint64 //33 uimsbf
|
||||
Program_clock_reference_extension uint16 //9 uimsbf
|
||||
Original_program_clock_reference_base uint64 //33 uimsbf
|
||||
Original_program_clock_reference_extension uint16 //9 uimsbf
|
||||
Splice_countdown uint8 //8 uimsbf
|
||||
Transport_private_data_length uint8 //8 uimsbf
|
||||
Adaptation_field_extension_length uint8 //8 uimsbf
|
||||
Ltw_flag uint8 //1 bslbf
|
||||
Piecewise_rate_flag uint8 //1 bslbf
|
||||
Seamless_splice_flag uint8 //1 bslbf
|
||||
Ltw_valid_flag uint8 //1 bslbf
|
||||
Ltw_offset uint16 //15 uimsbf
|
||||
Piecewise_rate uint32 //22 uimsbf
|
||||
Splice_type uint8 //4 uimsbf
|
||||
DTS_next_AU uint64
|
||||
Stuffing_byte uint8
|
||||
SingleStuffingByte bool // The value 0 is for inserting a single stuffing byte in a Transport Stream packet
|
||||
Adaptation_field_length uint8 //8 uimsbf
|
||||
Discontinuity_indicator uint8 //1 bslbf
|
||||
Random_access_indicator uint8 //1 bslbf
|
||||
Elementary_stream_priority_indicator uint8 //1 bslbf
|
||||
PCR_flag uint8 //1 bslbf
|
||||
OPCR_flag uint8 //1 bslbf
|
||||
Splicing_point_flag uint8 //1 bslbf
|
||||
Transport_private_data_flag uint8 //1 bslbf
|
||||
Adaptation_field_extension_flag uint8 //1 bslbf
|
||||
Program_clock_reference_base uint64 //33 uimsbf
|
||||
Program_clock_reference_extension uint16 //9 uimsbf
|
||||
Original_program_clock_reference_base uint64 //33 uimsbf
|
||||
Original_program_clock_reference_extension uint16 //9 uimsbf
|
||||
Splice_countdown uint8 //8 uimsbf
|
||||
Transport_private_data_length uint8 //8 uimsbf
|
||||
Adaptation_field_extension_length uint8 //8 uimsbf
|
||||
Ltw_flag uint8 //1 bslbf
|
||||
Piecewise_rate_flag uint8 //1 bslbf
|
||||
Seamless_splice_flag uint8 //1 bslbf
|
||||
Ltw_valid_flag uint8 //1 bslbf
|
||||
Ltw_offset uint16 //15 uimsbf
|
||||
Piecewise_rate uint32 //22 uimsbf
|
||||
Splice_type uint8 //4 uimsbf
|
||||
DTS_next_AU uint64
|
||||
Stuffing_byte uint8
|
||||
}
|
||||
|
||||
func (adaptation *Adaptation_field) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_length:%d\n", adaptation.Adaptation_field_length))
|
||||
file.WriteString(fmt.Sprintf("Discontinuity_indicator:%d\n", adaptation.Discontinuity_indicator))
|
||||
file.WriteString(fmt.Sprintf("Random_access_indicator:%d\n", adaptation.Random_access_indicator))
|
||||
file.WriteString(fmt.Sprintf("Elementary_stream_priority_indicator:%d\n", adaptation.Elementary_stream_priority_indicator))
|
||||
file.WriteString(fmt.Sprintf("PCR_flag:%d\n", adaptation.PCR_flag))
|
||||
file.WriteString(fmt.Sprintf("OPCR_flag:%d\n", adaptation.OPCR_flag))
|
||||
file.WriteString(fmt.Sprintf("Splicing_point_flag:%d\n", adaptation.Splicing_point_flag))
|
||||
file.WriteString(fmt.Sprintf("Transport_private_data_flag:%d\n", adaptation.Transport_private_data_flag))
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_extension_flag:%d\n", adaptation.Adaptation_field_extension_flag))
|
||||
if adaptation.PCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Program_clock_reference_base:%d\n", adaptation.Program_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("Program_clock_reference_extension:%d\n", adaptation.Program_clock_reference_extension))
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Original_program_clock_reference_base:%d\n", adaptation.Original_program_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("Original_program_clock_reference_extension:%d\n", adaptation.Original_program_clock_reference_extension))
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Splice_countdown:%d\n", adaptation.Splice_countdown))
|
||||
}
|
||||
if adaptation.Transport_private_data_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Transport_private_data_length:%d\n", adaptation.Transport_private_data_length))
|
||||
}
|
||||
if adaptation.Adaptation_field_extension_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_extension_length:%d\n", adaptation.Adaptation_field_extension_length))
|
||||
file.WriteString(fmt.Sprintf("Ltw_flag:%d\n", adaptation.Ltw_flag))
|
||||
file.WriteString(fmt.Sprintf("Piecewise_rate_flag:%d\n", adaptation.Piecewise_rate_flag))
|
||||
file.WriteString(fmt.Sprintf("Seamless_splice_flag:%d\n", adaptation.Seamless_splice_flag))
|
||||
if adaptation.Ltw_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Ltw_valid_flag:%d\n", adaptation.Ltw_valid_flag))
|
||||
file.WriteString(fmt.Sprintf("Ltw_offset:%d\n", adaptation.Ltw_offset))
|
||||
}
|
||||
if adaptation.Piecewise_rate_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Piecewise_rate:%d\n", adaptation.Piecewise_rate))
|
||||
}
|
||||
if adaptation.Seamless_splice_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Splice_type:%d\n", adaptation.Splice_type))
|
||||
file.WriteString(fmt.Sprintf("DTS_next_AU:%d\n", adaptation.DTS_next_AU))
|
||||
}
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_length:%d\n", adaptation.Adaptation_field_length))
|
||||
file.WriteString(fmt.Sprintf("Discontinuity_indicator:%d\n", adaptation.Discontinuity_indicator))
|
||||
file.WriteString(fmt.Sprintf("Random_access_indicator:%d\n", adaptation.Random_access_indicator))
|
||||
file.WriteString(fmt.Sprintf("Elementary_stream_priority_indicator:%d\n", adaptation.Elementary_stream_priority_indicator))
|
||||
file.WriteString(fmt.Sprintf("PCR_flag:%d\n", adaptation.PCR_flag))
|
||||
file.WriteString(fmt.Sprintf("OPCR_flag:%d\n", adaptation.OPCR_flag))
|
||||
file.WriteString(fmt.Sprintf("Splicing_point_flag:%d\n", adaptation.Splicing_point_flag))
|
||||
file.WriteString(fmt.Sprintf("Transport_private_data_flag:%d\n", adaptation.Transport_private_data_flag))
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_extension_flag:%d\n", adaptation.Adaptation_field_extension_flag))
|
||||
if adaptation.PCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Program_clock_reference_base:%d\n", adaptation.Program_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("Program_clock_reference_extension:%d\n", adaptation.Program_clock_reference_extension))
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Original_program_clock_reference_base:%d\n", adaptation.Original_program_clock_reference_base))
|
||||
file.WriteString(fmt.Sprintf("Original_program_clock_reference_extension:%d\n", adaptation.Original_program_clock_reference_extension))
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Splice_countdown:%d\n", adaptation.Splice_countdown))
|
||||
}
|
||||
if adaptation.Transport_private_data_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Transport_private_data_length:%d\n", adaptation.Transport_private_data_length))
|
||||
}
|
||||
if adaptation.Adaptation_field_extension_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Adaptation_field_extension_length:%d\n", adaptation.Adaptation_field_extension_length))
|
||||
file.WriteString(fmt.Sprintf("Ltw_flag:%d\n", adaptation.Ltw_flag))
|
||||
file.WriteString(fmt.Sprintf("Piecewise_rate_flag:%d\n", adaptation.Piecewise_rate_flag))
|
||||
file.WriteString(fmt.Sprintf("Seamless_splice_flag:%d\n", adaptation.Seamless_splice_flag))
|
||||
if adaptation.Ltw_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Ltw_valid_flag:%d\n", adaptation.Ltw_valid_flag))
|
||||
file.WriteString(fmt.Sprintf("Ltw_offset:%d\n", adaptation.Ltw_offset))
|
||||
}
|
||||
if adaptation.Piecewise_rate_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Piecewise_rate:%d\n", adaptation.Piecewise_rate))
|
||||
}
|
||||
if adaptation.Seamless_splice_flag == 1 {
|
||||
file.WriteString(fmt.Sprintf("Splice_type:%d\n", adaptation.Splice_type))
|
||||
file.WriteString(fmt.Sprintf("DTS_next_AU:%d\n", adaptation.DTS_next_AU))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (adaptation *Adaptation_field) Encode(bsw *codec.BitStreamWriter) {
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(adaptation.Adaptation_field_length, 8)
|
||||
if adaptation.SingleStuffingByte {
|
||||
return
|
||||
}
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(adaptation.Discontinuity_indicator, 1)
|
||||
bsw.PutUint8(adaptation.Random_access_indicator, 1)
|
||||
bsw.PutUint8(adaptation.Elementary_stream_priority_indicator, 1)
|
||||
bsw.PutUint8(adaptation.PCR_flag, 1)
|
||||
bsw.PutUint8(adaptation.OPCR_flag, 1)
|
||||
bsw.PutUint8(adaptation.Splicing_point_flag, 1)
|
||||
bsw.PutUint8(0 /*adaptation.Transport_private_data_flag*/, 1)
|
||||
bsw.PutUint8(0 /*adaptation.Adaptation_field_extension_flag*/, 1)
|
||||
if adaptation.PCR_flag == 1 {
|
||||
bsw.PutUint64(adaptation.Program_clock_reference_base, 33)
|
||||
bsw.PutUint8(0, 6)
|
||||
bsw.PutUint16(adaptation.Program_clock_reference_extension, 9)
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
bsw.PutUint64(adaptation.Original_program_clock_reference_base, 33)
|
||||
bsw.PutUint8(0, 6)
|
||||
bsw.PutUint16(adaptation.Original_program_clock_reference_extension, 9)
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
bsw.PutUint8(adaptation.Splice_countdown, 8)
|
||||
}
|
||||
//TODO
|
||||
// if adaptation.Transport_private_data_flag == 0 {
|
||||
// }
|
||||
// if adaptation.Adaptation_field_extension_flag == 0 {
|
||||
// }
|
||||
adaptation.Adaptation_field_length = uint8(bsw.DistanceFromMarkDot() / 8)
|
||||
bsw.PutRepetValue(0xff, int(adaptation.Stuffing_byte))
|
||||
adaptation.Adaptation_field_length += adaptation.Stuffing_byte
|
||||
bsw.SetByte(adaptation.Adaptation_field_length, loc)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(adaptation.Adaptation_field_length, 8)
|
||||
if adaptation.SingleStuffingByte {
|
||||
return
|
||||
}
|
||||
bsw.Markdot()
|
||||
bsw.PutUint8(adaptation.Discontinuity_indicator, 1)
|
||||
bsw.PutUint8(adaptation.Random_access_indicator, 1)
|
||||
bsw.PutUint8(adaptation.Elementary_stream_priority_indicator, 1)
|
||||
bsw.PutUint8(adaptation.PCR_flag, 1)
|
||||
bsw.PutUint8(adaptation.OPCR_flag, 1)
|
||||
bsw.PutUint8(adaptation.Splicing_point_flag, 1)
|
||||
bsw.PutUint8(0 /*adaptation.Transport_private_data_flag*/, 1)
|
||||
bsw.PutUint8(0 /*adaptation.Adaptation_field_extension_flag*/, 1)
|
||||
if adaptation.PCR_flag == 1 {
|
||||
bsw.PutUint64(adaptation.Program_clock_reference_base, 33)
|
||||
bsw.PutUint8(0, 6)
|
||||
bsw.PutUint16(adaptation.Program_clock_reference_extension, 9)
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
bsw.PutUint64(adaptation.Original_program_clock_reference_base, 33)
|
||||
bsw.PutUint8(0, 6)
|
||||
bsw.PutUint16(adaptation.Original_program_clock_reference_extension, 9)
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
bsw.PutUint8(adaptation.Splice_countdown, 8)
|
||||
}
|
||||
//TODO
|
||||
// if adaptation.Transport_private_data_flag == 0 {
|
||||
// }
|
||||
// if adaptation.Adaptation_field_extension_flag == 0 {
|
||||
// }
|
||||
adaptation.Adaptation_field_length = uint8(bsw.DistanceFromMarkDot() / 8)
|
||||
bsw.PutRepetValue(0xff, int(adaptation.Stuffing_byte))
|
||||
adaptation.Adaptation_field_length += adaptation.Stuffing_byte
|
||||
bsw.SetByte(adaptation.Adaptation_field_length, loc)
|
||||
}
|
||||
|
||||
func (adaptation *Adaptation_field) Decode(bs *codec.BitStream) error {
|
||||
if bs.RemainBytes() < 1 {
|
||||
return errors.New("len of data < 1 byte")
|
||||
}
|
||||
adaptation.Adaptation_field_length = bs.Uint8(8)
|
||||
startoffset := bs.ByteOffset()
|
||||
//fmt.Printf("Adaptation_field_length=%d\n", adaptation.Adaptation_field_length)
|
||||
if bs.RemainBytes() < int(adaptation.Adaptation_field_length) {
|
||||
return errors.New("len of data < Adaptation_field_length")
|
||||
}
|
||||
if adaptation.Adaptation_field_length == 0 {
|
||||
return nil
|
||||
}
|
||||
adaptation.Discontinuity_indicator = bs.GetBit()
|
||||
adaptation.Random_access_indicator = bs.GetBit()
|
||||
adaptation.Elementary_stream_priority_indicator = bs.GetBit()
|
||||
adaptation.PCR_flag = bs.GetBit()
|
||||
adaptation.OPCR_flag = bs.GetBit()
|
||||
adaptation.Splicing_point_flag = bs.GetBit()
|
||||
adaptation.Transport_private_data_flag = bs.GetBit()
|
||||
adaptation.Adaptation_field_extension_flag = bs.GetBit()
|
||||
if adaptation.PCR_flag == 1 {
|
||||
adaptation.Program_clock_reference_base = bs.GetBits(33)
|
||||
bs.SkipBits(6)
|
||||
adaptation.Program_clock_reference_extension = uint16(bs.GetBits(9))
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
adaptation.Original_program_clock_reference_base = bs.GetBits(33)
|
||||
bs.SkipBits(6)
|
||||
adaptation.Original_program_clock_reference_extension = uint16(bs.GetBits(9))
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
adaptation.Splice_countdown = bs.Uint8(8)
|
||||
}
|
||||
if adaptation.Transport_private_data_flag == 1 {
|
||||
adaptation.Transport_private_data_length = bs.Uint8(8)
|
||||
bs.SkipBits(8 * int(adaptation.Transport_private_data_length))
|
||||
}
|
||||
if adaptation.Adaptation_field_extension_flag == 1 {
|
||||
adaptation.Adaptation_field_extension_length = bs.Uint8(8)
|
||||
bs.Markdot()
|
||||
adaptation.Ltw_flag = bs.GetBit()
|
||||
adaptation.Piecewise_rate_flag = bs.GetBit()
|
||||
adaptation.Seamless_splice_flag = bs.GetBit()
|
||||
bs.SkipBits(5)
|
||||
if adaptation.Ltw_flag == 1 {
|
||||
adaptation.Ltw_valid_flag = bs.GetBit()
|
||||
adaptation.Ltw_offset = uint16(bs.GetBits(15))
|
||||
}
|
||||
if adaptation.Piecewise_rate_flag == 1 {
|
||||
bs.SkipBits(2)
|
||||
adaptation.Piecewise_rate = uint32(bs.GetBits(22))
|
||||
}
|
||||
if adaptation.Seamless_splice_flag == 1 {
|
||||
adaptation.Splice_type = uint8(bs.GetBits(4))
|
||||
adaptation.DTS_next_AU = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
bitscount := bs.DistanceFromMarkDot()
|
||||
if bitscount%8 > 0 {
|
||||
panic("maybe parser ts file failed")
|
||||
}
|
||||
bs.SkipBits(int(adaptation.Adaptation_field_extension_length*8 - uint8(bitscount)))
|
||||
}
|
||||
endoffset := bs.ByteOffset()
|
||||
bs.SkipBits((int(adaptation.Adaptation_field_length) - (endoffset - startoffset)) * 8)
|
||||
return nil
|
||||
if bs.RemainBytes() < 1 {
|
||||
return errors.New("len of data < 1 byte")
|
||||
}
|
||||
adaptation.Adaptation_field_length = bs.Uint8(8)
|
||||
startoffset := bs.ByteOffset()
|
||||
//fmt.Printf("Adaptation_field_length=%d\n", adaptation.Adaptation_field_length)
|
||||
if bs.RemainBytes() < int(adaptation.Adaptation_field_length) {
|
||||
return errors.New("len of data < Adaptation_field_length")
|
||||
}
|
||||
if adaptation.Adaptation_field_length == 0 {
|
||||
return nil
|
||||
}
|
||||
adaptation.Discontinuity_indicator = bs.GetBit()
|
||||
adaptation.Random_access_indicator = bs.GetBit()
|
||||
adaptation.Elementary_stream_priority_indicator = bs.GetBit()
|
||||
adaptation.PCR_flag = bs.GetBit()
|
||||
adaptation.OPCR_flag = bs.GetBit()
|
||||
adaptation.Splicing_point_flag = bs.GetBit()
|
||||
adaptation.Transport_private_data_flag = bs.GetBit()
|
||||
adaptation.Adaptation_field_extension_flag = bs.GetBit()
|
||||
if adaptation.PCR_flag == 1 {
|
||||
adaptation.Program_clock_reference_base = bs.GetBits(33)
|
||||
bs.SkipBits(6)
|
||||
adaptation.Program_clock_reference_extension = uint16(bs.GetBits(9))
|
||||
}
|
||||
if adaptation.OPCR_flag == 1 {
|
||||
adaptation.Original_program_clock_reference_base = bs.GetBits(33)
|
||||
bs.SkipBits(6)
|
||||
adaptation.Original_program_clock_reference_extension = uint16(bs.GetBits(9))
|
||||
}
|
||||
if adaptation.Splicing_point_flag == 1 {
|
||||
adaptation.Splice_countdown = bs.Uint8(8)
|
||||
}
|
||||
if adaptation.Transport_private_data_flag == 1 {
|
||||
adaptation.Transport_private_data_length = bs.Uint8(8)
|
||||
bs.SkipBits(8 * int(adaptation.Transport_private_data_length))
|
||||
}
|
||||
if adaptation.Adaptation_field_extension_flag == 1 {
|
||||
adaptation.Adaptation_field_extension_length = bs.Uint8(8)
|
||||
bs.Markdot()
|
||||
adaptation.Ltw_flag = bs.GetBit()
|
||||
adaptation.Piecewise_rate_flag = bs.GetBit()
|
||||
adaptation.Seamless_splice_flag = bs.GetBit()
|
||||
bs.SkipBits(5)
|
||||
if adaptation.Ltw_flag == 1 {
|
||||
adaptation.Ltw_valid_flag = bs.GetBit()
|
||||
adaptation.Ltw_offset = uint16(bs.GetBits(15))
|
||||
}
|
||||
if adaptation.Piecewise_rate_flag == 1 {
|
||||
bs.SkipBits(2)
|
||||
adaptation.Piecewise_rate = uint32(bs.GetBits(22))
|
||||
}
|
||||
if adaptation.Seamless_splice_flag == 1 {
|
||||
adaptation.Splice_type = uint8(bs.GetBits(4))
|
||||
adaptation.DTS_next_AU = bs.GetBits(3)
|
||||
bs.SkipBits(1)
|
||||
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
adaptation.DTS_next_AU = adaptation.DTS_next_AU<<15 | bs.GetBits(15)
|
||||
bs.SkipBits(1)
|
||||
}
|
||||
bitscount := bs.DistanceFromMarkDot()
|
||||
if bitscount%8 > 0 {
|
||||
panic("maybe parser ts file failed")
|
||||
}
|
||||
bs.SkipBits(int(adaptation.Adaptation_field_extension_length*8 - uint8(bitscount)))
|
||||
}
|
||||
endoffset := bs.ByteOffset()
|
||||
bs.SkipBits((int(adaptation.Adaptation_field_length) - (endoffset - startoffset)) * 8)
|
||||
return nil
|
||||
}
|
||||
|
||||
type PmtPair struct {
|
||||
Program_number uint16
|
||||
PID uint16
|
||||
Program_number uint16
|
||||
PID uint16
|
||||
}
|
||||
|
||||
type Pat struct {
|
||||
Table_id uint8 //8 uimsbf
|
||||
Section_syntax_indicator uint8 //1 bslbf
|
||||
Section_length uint16 //12 uimsbf
|
||||
Transport_stream_id uint16 //16 uimsbf
|
||||
Version_number uint8 //5 uimsbf
|
||||
Current_next_indicator uint8 //1 bslbf
|
||||
Section_number uint8 //8 uimsbf
|
||||
Last_section_number uint8 //8 uimsbf
|
||||
Pmts []PmtPair
|
||||
Table_id uint8 //8 uimsbf
|
||||
Section_syntax_indicator uint8 //1 bslbf
|
||||
Section_length uint16 //12 uimsbf
|
||||
Transport_stream_id uint16 //16 uimsbf
|
||||
Version_number uint8 //5 uimsbf
|
||||
Current_next_indicator uint8 //1 bslbf
|
||||
Section_number uint8 //8 uimsbf
|
||||
Last_section_number uint8 //8 uimsbf
|
||||
Pmts []PmtPair
|
||||
}
|
||||
|
||||
func NewPat() *Pat {
|
||||
return &Pat{
|
||||
Table_id: uint8(TS_TID_PAS),
|
||||
Pmts: make([]PmtPair, 0, 8),
|
||||
}
|
||||
return &Pat{
|
||||
Table_id: uint8(TS_TID_PAS),
|
||||
Pmts: make([]PmtPair, 0, 8),
|
||||
}
|
||||
}
|
||||
|
||||
func (pat *Pat) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Table id:%d\n", pat.Table_id))
|
||||
file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pat.Section_syntax_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_length:%d\n", pat.Section_length))
|
||||
file.WriteString(fmt.Sprintf("Transport_stream_id:%d\n", pat.Transport_stream_id))
|
||||
file.WriteString(fmt.Sprintf("Version_number:%d\n", pat.Version_number))
|
||||
file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pat.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_number:%d\n", pat.Section_number))
|
||||
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pat.Last_section_number))
|
||||
for i, pmt := range pat.Pmts {
|
||||
file.WriteString(fmt.Sprintf("----pmt %d\n", i))
|
||||
file.WriteString(fmt.Sprintf(" program_number:%d\n", pmt.Program_number))
|
||||
if pmt.Program_number == 0x0000 {
|
||||
file.WriteString(fmt.Sprintf(" network_PID:%d\n", pmt.PID))
|
||||
} else {
|
||||
file.WriteString(fmt.Sprintf(" program_map_PID:%d\n", pmt.PID))
|
||||
}
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("Table id:%d\n", pat.Table_id))
|
||||
file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pat.Section_syntax_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_length:%d\n", pat.Section_length))
|
||||
file.WriteString(fmt.Sprintf("Transport_stream_id:%d\n", pat.Transport_stream_id))
|
||||
file.WriteString(fmt.Sprintf("Version_number:%d\n", pat.Version_number))
|
||||
file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pat.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_number:%d\n", pat.Section_number))
|
||||
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pat.Last_section_number))
|
||||
for i, pmt := range pat.Pmts {
|
||||
file.WriteString(fmt.Sprintf("----pmt %d\n", i))
|
||||
file.WriteString(fmt.Sprintf(" program_number:%d\n", pmt.Program_number))
|
||||
if pmt.Program_number == 0x0000 {
|
||||
file.WriteString(fmt.Sprintf(" network_PID:%d\n", pmt.PID))
|
||||
} else {
|
||||
file.WriteString(fmt.Sprintf(" program_map_PID:%d\n", pmt.PID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (pat *Pat) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutUint8(0x00, 8)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(pat.Section_syntax_indicator, 1)
|
||||
bsw.PutUint8(0x00, 1)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint16(0, 12)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint16(pat.Transport_stream_id, 16)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint8(pat.Version_number, 5)
|
||||
bsw.PutUint8(pat.Current_next_indicator, 1)
|
||||
bsw.PutUint8(pat.Section_number, 8)
|
||||
bsw.PutUint8(pat.Last_section_number, 8)
|
||||
for _, pms := range pat.Pmts {
|
||||
bsw.PutUint16(pms.Program_number, 16)
|
||||
bsw.PutUint8(0x07, 3)
|
||||
bsw.PutUint16(pms.PID, 13)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()
|
||||
//|Section_syntax_indicator|'0'|reserved|Section_length|
|
||||
pat.Section_length = uint16(length)/8 + 4
|
||||
bsw.SetUint16(pat.Section_length&0x0FFF|(uint16(pat.Section_syntax_indicator)<<15)|0x3000, loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pat.Section_length-4)-3:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
bsw.PutUint8(0x00, 8)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(pat.Section_syntax_indicator, 1)
|
||||
bsw.PutUint8(0x00, 1)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint16(0, 12)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint16(pat.Transport_stream_id, 16)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint8(pat.Version_number, 5)
|
||||
bsw.PutUint8(pat.Current_next_indicator, 1)
|
||||
bsw.PutUint8(pat.Section_number, 8)
|
||||
bsw.PutUint8(pat.Last_section_number, 8)
|
||||
for _, pms := range pat.Pmts {
|
||||
bsw.PutUint16(pms.Program_number, 16)
|
||||
bsw.PutUint8(0x07, 3)
|
||||
bsw.PutUint16(pms.PID, 13)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()
|
||||
//|Section_syntax_indicator|'0'|reserved|Section_length|
|
||||
pat.Section_length = uint16(length)/8 + 4
|
||||
bsw.SetUint16(pat.Section_length&0x0FFF|(uint16(pat.Section_syntax_indicator)<<15)|0x3000, loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pat.Section_length-4)-3:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
}
|
||||
|
||||
func (pat *Pat) Decode(bs *codec.BitStream) error {
|
||||
pat.Table_id = bs.Uint8(8)
|
||||
pat.Table_id = bs.Uint8(8)
|
||||
|
||||
if pat.Table_id != uint8(TS_TID_PAS) {
|
||||
return errors.New("table id is Not TS_TID_PAS")
|
||||
}
|
||||
pat.Section_syntax_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(3)
|
||||
pat.Section_length = bs.Uint16(12)
|
||||
pat.Transport_stream_id = bs.Uint16(16)
|
||||
bs.SkipBits(2)
|
||||
pat.Version_number = bs.Uint8(5)
|
||||
pat.Current_next_indicator = bs.Uint8(1)
|
||||
pat.Section_number = bs.Uint8(8)
|
||||
pat.Last_section_number = bs.Uint8(8)
|
||||
for i := 0; i+4 <= int(pat.Section_length)-5-4; i = i + 4 {
|
||||
tmp := PmtPair{
|
||||
Program_number: 0,
|
||||
PID: 0,
|
||||
}
|
||||
tmp.Program_number = bs.Uint16(16)
|
||||
bs.SkipBits(3)
|
||||
tmp.PID = bs.Uint16(13)
|
||||
pat.Pmts = append(pat.Pmts, tmp)
|
||||
}
|
||||
return nil
|
||||
if pat.Table_id != uint8(TS_TID_PAS) {
|
||||
return errors.New("table id is Not TS_TID_PAS")
|
||||
}
|
||||
pat.Section_syntax_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(3)
|
||||
pat.Section_length = bs.Uint16(12)
|
||||
pat.Transport_stream_id = bs.Uint16(16)
|
||||
bs.SkipBits(2)
|
||||
pat.Version_number = bs.Uint8(5)
|
||||
pat.Current_next_indicator = bs.Uint8(1)
|
||||
pat.Section_number = bs.Uint8(8)
|
||||
pat.Last_section_number = bs.Uint8(8)
|
||||
for i := 0; i+4 <= int(pat.Section_length)-5-4; i = i + 4 {
|
||||
tmp := PmtPair{
|
||||
Program_number: 0,
|
||||
PID: 0,
|
||||
}
|
||||
tmp.Program_number = bs.Uint16(16)
|
||||
bs.SkipBits(3)
|
||||
tmp.PID = bs.Uint16(13)
|
||||
pat.Pmts = append(pat.Pmts, tmp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type StreamPair struct {
|
||||
StreamType uint8 //8 uimsbf
|
||||
Elementary_PID uint16 //13 uimsbf
|
||||
ES_Info_Length uint16 //12 uimsbf
|
||||
StreamType uint8 //8 uimsbf
|
||||
Elementary_PID uint16 //13 uimsbf
|
||||
ES_Info_Length uint16 //12 uimsbf
|
||||
}
|
||||
|
||||
type Pmt struct {
|
||||
Table_id uint8 //8 uimsbf
|
||||
Section_syntax_indicator uint8 //1 bslbf
|
||||
Section_length uint16 //12 uimsbf
|
||||
Program_number uint16 //16 uimsbf
|
||||
Version_number uint8 //5 uimsbf
|
||||
Current_next_indicator uint8 //1 bslbf
|
||||
Section_number uint8 //8 uimsbf
|
||||
Last_section_number uint8 //8 uimsbf
|
||||
PCR_PID uint16 //13 uimsbf
|
||||
Program_info_length uint16 //12 uimsbf
|
||||
Streams []StreamPair
|
||||
Table_id uint8 //8 uimsbf
|
||||
Section_syntax_indicator uint8 //1 bslbf
|
||||
Section_length uint16 //12 uimsbf
|
||||
Program_number uint16 //16 uimsbf
|
||||
Version_number uint8 //5 uimsbf
|
||||
Current_next_indicator uint8 //1 bslbf
|
||||
Section_number uint8 //8 uimsbf
|
||||
Last_section_number uint8 //8 uimsbf
|
||||
PCR_PID uint16 //13 uimsbf
|
||||
Program_info_length uint16 //12 uimsbf
|
||||
Streams []StreamPair
|
||||
}
|
||||
|
||||
func NewPmt() *Pmt {
|
||||
return &Pmt{
|
||||
Table_id: uint8(TS_TID_PMS),
|
||||
Streams: make([]StreamPair, 0, 8),
|
||||
}
|
||||
return &Pmt{
|
||||
Table_id: uint8(TS_TID_PMS),
|
||||
Streams: make([]StreamPair, 0, 8),
|
||||
}
|
||||
}
|
||||
|
||||
func (pmt *Pmt) PrettyPrint(file *os.File) {
|
||||
file.WriteString(fmt.Sprintf("Table id:%d\n", pmt.Table_id))
|
||||
file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pmt.Section_syntax_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_length:%d\n", pmt.Section_length))
|
||||
file.WriteString(fmt.Sprintf("Program_number:%d\n", pmt.Program_number))
|
||||
file.WriteString(fmt.Sprintf("Version_number:%d\n", pmt.Version_number))
|
||||
file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pmt.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_number:%d\n", pmt.Section_number))
|
||||
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pmt.Last_section_number))
|
||||
file.WriteString(fmt.Sprintf("PCR_PID:%d\n", pmt.PCR_PID))
|
||||
file.WriteString(fmt.Sprintf("program_info_length:%d\n", pmt.Program_info_length))
|
||||
for i, stream := range pmt.Streams {
|
||||
file.WriteString(fmt.Sprintf("----stream %d\n", i))
|
||||
if stream.StreamType == uint8(TS_STREAM_AAC) {
|
||||
file.WriteString(" stream_type:AAC\n")
|
||||
} else if stream.StreamType == uint8(TS_STREAM_H264) {
|
||||
file.WriteString(" stream_type:H264\n")
|
||||
} else if stream.StreamType == uint8(TS_STREAM_H265) {
|
||||
file.WriteString(" stream_type:H265\n")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf(" elementary_PID:%d\n", stream.Elementary_PID))
|
||||
file.WriteString(fmt.Sprintf(" ES_info_length:%d\n", stream.ES_Info_Length))
|
||||
}
|
||||
file.WriteString(fmt.Sprintf("Table id:%d\n", pmt.Table_id))
|
||||
file.WriteString(fmt.Sprintf("Section_syntax_indicator:%d\n", pmt.Section_syntax_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_length:%d\n", pmt.Section_length))
|
||||
file.WriteString(fmt.Sprintf("Program_number:%d\n", pmt.Program_number))
|
||||
file.WriteString(fmt.Sprintf("Version_number:%d\n", pmt.Version_number))
|
||||
file.WriteString(fmt.Sprintf("Current_next_indicator:%d\n", pmt.Current_next_indicator))
|
||||
file.WriteString(fmt.Sprintf("Section_number:%d\n", pmt.Section_number))
|
||||
file.WriteString(fmt.Sprintf("Last_section_number:%d\n", pmt.Last_section_number))
|
||||
file.WriteString(fmt.Sprintf("PCR_PID:%d\n", pmt.PCR_PID))
|
||||
file.WriteString(fmt.Sprintf("program_info_length:%d\n", pmt.Program_info_length))
|
||||
for i, stream := range pmt.Streams {
|
||||
file.WriteString(fmt.Sprintf("----stream %d\n", i))
|
||||
if stream.StreamType == uint8(TS_STREAM_AAC) {
|
||||
file.WriteString(" stream_type:AAC\n")
|
||||
} else if stream.StreamType == uint8(TS_STREAM_H264) {
|
||||
file.WriteString(" stream_type:H264\n")
|
||||
} else if stream.StreamType == uint8(TS_STREAM_H265) {
|
||||
file.WriteString(" stream_type:H265\n")
|
||||
}
|
||||
file.WriteString(fmt.Sprintf(" elementary_PID:%d\n", stream.Elementary_PID))
|
||||
file.WriteString(fmt.Sprintf(" ES_info_length:%d\n", stream.ES_Info_Length))
|
||||
}
|
||||
}
|
||||
|
||||
func (pmt *Pmt) Encode(bsw *codec.BitStreamWriter) {
|
||||
bsw.PutUint8(pmt.Table_id, 8)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(pmt.Section_syntax_indicator, 1)
|
||||
bsw.PutUint8(0x00, 1)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint16(pmt.Section_length, 12)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint16(pmt.Program_number, 16)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint8(pmt.Version_number, 5)
|
||||
bsw.PutUint8(pmt.Current_next_indicator, 1)
|
||||
bsw.PutUint8(pmt.Section_number, 8)
|
||||
bsw.PutUint8(pmt.Last_section_number, 8)
|
||||
bsw.PutUint8(0x07, 3)
|
||||
bsw.PutUint16(pmt.PCR_PID, 13)
|
||||
bsw.PutUint8(0x0f, 4)
|
||||
//TODO Program info length
|
||||
bsw.PutUint16(0x0000 /*pmt.Program_info_length*/, 12)
|
||||
for _, stream := range pmt.Streams {
|
||||
bsw.PutUint8(stream.StreamType, 8)
|
||||
bsw.PutUint8(0x00, 3)
|
||||
bsw.PutUint16(stream.Elementary_PID, 13)
|
||||
bsw.PutUint8(0x00, 4)
|
||||
//TODO ES_info
|
||||
bsw.PutUint8(0 /*ES_info_length*/, 12)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()
|
||||
pmt.Section_length = uint16(length)/8 + 4
|
||||
bsw.SetUint16(pmt.Section_length&0x0FFF|(uint16(pmt.Section_syntax_indicator)<<15)|0x3000, loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pmt.Section_length-4)-3:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
bsw.PutUint8(pmt.Table_id, 8)
|
||||
loc := bsw.ByteOffset()
|
||||
bsw.PutUint8(pmt.Section_syntax_indicator, 1)
|
||||
bsw.PutUint8(0x00, 1)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint16(pmt.Section_length, 12)
|
||||
bsw.Markdot()
|
||||
bsw.PutUint16(pmt.Program_number, 16)
|
||||
bsw.PutUint8(0x03, 2)
|
||||
bsw.PutUint8(pmt.Version_number, 5)
|
||||
bsw.PutUint8(pmt.Current_next_indicator, 1)
|
||||
bsw.PutUint8(pmt.Section_number, 8)
|
||||
bsw.PutUint8(pmt.Last_section_number, 8)
|
||||
bsw.PutUint8(0x07, 3)
|
||||
bsw.PutUint16(pmt.PCR_PID, 13)
|
||||
bsw.PutUint8(0x0f, 4)
|
||||
//TODO Program info length
|
||||
bsw.PutUint16(0x0000 /*pmt.Program_info_length*/, 12)
|
||||
for _, stream := range pmt.Streams {
|
||||
bsw.PutUint8(stream.StreamType, 8)
|
||||
bsw.PutUint8(0x00, 3)
|
||||
bsw.PutUint16(stream.Elementary_PID, 13)
|
||||
bsw.PutUint8(0x00, 4)
|
||||
//TODO ES_info
|
||||
bsw.PutUint8(0 /*ES_info_length*/, 12)
|
||||
}
|
||||
length := bsw.DistanceFromMarkDot()
|
||||
pmt.Section_length = uint16(length)/8 + 4
|
||||
bsw.SetUint16(pmt.Section_length&0x0FFF|(uint16(pmt.Section_syntax_indicator)<<15)|0x3000, loc)
|
||||
crc := codec.CalcCrc32(0xffffffff, bsw.Bits()[bsw.ByteOffset()-int(pmt.Section_length-4)-3:bsw.ByteOffset()])
|
||||
tmpcrc := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(tmpcrc, crc)
|
||||
bsw.PutBytes(tmpcrc)
|
||||
}
|
||||
|
||||
func (pmt *Pmt) Decode(bs *codec.BitStream) error {
|
||||
pmt.Table_id = bs.Uint8(8)
|
||||
if pmt.Table_id != uint8(TS_TID_PMS) {
|
||||
return errors.New("table id is Not TS_TID_PAS")
|
||||
}
|
||||
pmt.Section_syntax_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(3)
|
||||
pmt.Section_length = bs.Uint16(12)
|
||||
pmt.Program_number = bs.Uint16(16)
|
||||
bs.SkipBits(2)
|
||||
pmt.Version_number = bs.Uint8(5)
|
||||
pmt.Current_next_indicator = bs.Uint8(1)
|
||||
pmt.Section_number = bs.Uint8(8)
|
||||
pmt.Last_section_number = bs.Uint8(8)
|
||||
bs.SkipBits(3)
|
||||
pmt.PCR_PID = bs.Uint16(13)
|
||||
bs.SkipBits(4)
|
||||
pmt.Program_info_length = bs.Uint16(12)
|
||||
//TODO N loop descriptors
|
||||
bs.SkipBits(int(pmt.Program_info_length) * 8)
|
||||
//fmt.Printf("section length %d pmt.Pogram_info_length=%d\n", pmt.Section_length, pmt.Pogram_info_length)
|
||||
for i := 0; i < int(pmt.Section_length)-9-int(pmt.Program_info_length)-4; {
|
||||
tmp := StreamPair{
|
||||
StreamType: 0,
|
||||
Elementary_PID: 0,
|
||||
ES_Info_Length: 0,
|
||||
}
|
||||
tmp.StreamType = bs.Uint8(8)
|
||||
bs.SkipBits(3)
|
||||
tmp.Elementary_PID = bs.Uint16(13)
|
||||
bs.SkipBits(4)
|
||||
tmp.ES_Info_Length = bs.Uint16(12)
|
||||
//TODO N loop descriptors
|
||||
bs.SkipBits(int(tmp.ES_Info_Length) * 8)
|
||||
pmt.Streams = append(pmt.Streams, tmp)
|
||||
i += 5 + int(tmp.ES_Info_Length)
|
||||
}
|
||||
return nil
|
||||
pmt.Table_id = bs.Uint8(8)
|
||||
if pmt.Table_id != uint8(TS_TID_PMS) {
|
||||
return errors.New("table id is Not TS_TID_PAS")
|
||||
}
|
||||
pmt.Section_syntax_indicator = bs.Uint8(1)
|
||||
bs.SkipBits(3)
|
||||
pmt.Section_length = bs.Uint16(12)
|
||||
pmt.Program_number = bs.Uint16(16)
|
||||
bs.SkipBits(2)
|
||||
pmt.Version_number = bs.Uint8(5)
|
||||
pmt.Current_next_indicator = bs.Uint8(1)
|
||||
pmt.Section_number = bs.Uint8(8)
|
||||
pmt.Last_section_number = bs.Uint8(8)
|
||||
bs.SkipBits(3)
|
||||
pmt.PCR_PID = bs.Uint16(13)
|
||||
bs.SkipBits(4)
|
||||
pmt.Program_info_length = bs.Uint16(12)
|
||||
//TODO N loop descriptors
|
||||
bs.SkipBits(int(pmt.Program_info_length) * 8)
|
||||
//fmt.Printf("section length %d pmt.Pogram_info_length=%d\n", pmt.Section_length, pmt.Pogram_info_length)
|
||||
for i := 0; i < int(pmt.Section_length)-9-int(pmt.Program_info_length)-4; {
|
||||
tmp := StreamPair{
|
||||
StreamType: 0,
|
||||
Elementary_PID: 0,
|
||||
ES_Info_Length: 0,
|
||||
}
|
||||
tmp.StreamType = bs.Uint8(8)
|
||||
bs.SkipBits(3)
|
||||
tmp.Elementary_PID = bs.Uint16(13)
|
||||
bs.SkipBits(4)
|
||||
tmp.ES_Info_Length = bs.Uint16(12)
|
||||
//TODO N loop descriptors
|
||||
bs.SkipBits(int(tmp.ES_Info_Length) * 8)
|
||||
pmt.Streams = append(pmt.Streams, tmp)
|
||||
i += 5 + int(tmp.ES_Info_Length)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue