1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

GB28181: Enable regression test for gb28181. v5.0.122

1. Build regression test tool for gb28181.
2. Run regression test for gb28181.
3. Format go code and eliminate logs.
4. Change base docker to ubuntu20.
This commit is contained in:
winlin 2022-12-31 17:15:07 +08:00
parent 4b09a7d686
commit 7750bdae10
32 changed files with 3882 additions and 9727 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
}