1
0
Fork 0
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:
Winlin 2023-01-07 20:36:59 +08:00 committed by winlin
parent a27ce1d50f
commit e655948e96
31 changed files with 4704 additions and 3925 deletions

View file

@ -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)
}

View file

@ -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包过程中解码回调psmsystem headerpes包等
//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包过程中解码回调psmsystem headerpes包等
//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
}

View file

@ -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
}

View file

@ -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
}

View file

@ -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]
}

View file

@ -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
}
}
}

View file

@ -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
}