1
1
mirror of https://github.com/wader/fq.git synced 2024-11-25 23:13:19 +03:00
fq/format/mpeg/mpeg_pes_packet.go
2021-09-12 13:08:51 +02:00

194 lines
5.5 KiB
Go

package mpeg
// http://dvdnav.mplayerhq.hu/dvdinfo/mpeghdrs.html
// http://stnsoft.com/DVD/sys_hdr.html))
import (
"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/pkg/bitio"
"github.com/wader/fq/pkg/decode"
)
func init() {
registry.MustRegister(&decode.Format{
Name: format.MPEG_PES_PACKET,
Description: "MPEG Packetized elementary stream packet",
DecodeFn: pesPacketDecode,
})
}
const (
sequenceHeader = 0xb3
packHeader = 0xba
systemHeader = 0xbb
privateStream1 = 0xbd
)
type subStreamPacket struct {
number int
bb *bitio.Buffer
}
var startAndStreamNames = map[[2]uint64]string{
{0x00, 0x00}: "Picture",
{0x01, 0xaf}: "Slice",
{0xb0, 0xb1}: "Reserved",
{0xb2, 0xb2}: "User data",
{0xb3, 0xb3}: "SequenceHeader",
{0xb4, 0xb4}: "SequenceError",
{0xb5, 0xb5}: "Extension",
{0xb6, 0xb6}: "Reserved",
{0xb7, 0xb7}: "SequenceEnd",
{0xb8, 0xb8}: "GroupOfPictures",
{0xb9, 0xb9}: "ProgramEnd",
{0xba, 0xba}: "PackHeader",
{0xbb, 0xbb}: "SystemHeader",
{0xbc, 0xbc}: "ProgramStreamMap",
{0xbd, 0xbd}: "PrivateStream1",
{0xbe, 0xbe}: "PaddingStream",
{0xbf, 0xbf}: "PrivateStream2",
{0xc0, 0xdf}: "MPEG1OrMPEG2AudioStream",
{0xe0, 0xef}: "MPEG1OrMPEG2VideoStream",
{0xf0, 0xf0}: "ECMStream",
{0xf1, 0xf1}: "EMMStream",
{0xf2, 0xf2}: "ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A or ISO/IEC 13818-6_DSMCC_stream",
{0xf3, 0xf3}: "ISO/IEC_13522_stream",
{0xf4, 0xf4}: "ITU-T Rec. H.222.1 type A",
{0xf5, 0xf5}: "ITU-T Rec. H.222.1 type B",
{0xf6, 0xf6}: "ITU-T Rec. H.222.1 type C",
{0xf7, 0xf7}: "ITU-T Rec. H.222.1 type D",
{0xf8, 0xf8}: "ITU-T Rec. H.222.1 type E",
{0xf9, 0xf9}: "Ancillary_stream",
{0xfa, 0xfe}: "Reserved",
{0xff, 0xff}: "Program Stream Directory",
}
func pesPacketDecode(d *decode.D, in interface{}) interface{} {
var v interface{}
d.FieldValidateUFn("prefix", 0b0000_0000_0000_0000_0000_0001, d.U24)
startCode, _ := d.FieldStringRangeMapFn("start_code", startAndStreamNames, "Unknown", d.U8, decode.NumberHex)
switch {
case startCode == sequenceHeader:
d.FieldU12("horizontal_size")
d.FieldU12("vertical_size")
d.FieldU4("aspect_ratio")
d.FieldU4("frame_rate_code")
// TODO: bit rate * 400, rounded upwards. Use 0x3FFFF for variable bit rate
d.FieldU18("bit_rate")
d.FieldU1("marker_bit")
d.FieldU10("vbv_buf_size")
d.FieldU1("constrained_parameters_flag")
loadIntraQuantizerMatrix := d.FieldBool("load_intra_quantizer_matrix")
if loadIntraQuantizerMatrix {
d.FieldBitBufLen("intra_quantizer_matrix", 8*64)
}
loadNonIntraQuantizerMatrix := d.FieldBool("load_non_intra_quantizer_matrix")
if loadNonIntraQuantizerMatrix {
d.FieldBitBufLen("non_intra_quantizer_matrix", 8*64)
}
case startCode == packHeader:
d.FieldStructFn("scr", func(d *decode.D) {
d.FieldU2("skip0")
scr0 := d.FieldU3("scr0")
d.FieldU1("skip1")
scr1 := d.FieldU15("scr1")
d.FieldU1("skip2")
scr2 := d.FieldU15("scr2")
d.FieldU1("skip3")
d.FieldU9("scr_ext")
d.FieldU1("skip4")
scr := scr0<<30 | scr1<<15 | scr2
d.FieldValueU("scr", scr, "")
})
d.FieldU22("mux_rate")
d.FieldU2("skip0")
d.FieldU5("reserved")
packStuffingLength := d.FieldU3("pack_stuffing_length")
if packStuffingLength > 0 {
d.FieldBitBufLen("stuffing", int64(packStuffingLength*8))
}
case startCode == systemHeader:
d.FieldU16("length")
d.FieldU1("skip0")
d.FieldU22("rate_bound")
d.FieldU1("skip1")
d.FieldU6("audio_bound")
d.FieldU1("fixed_flag")
d.FieldU1("csps_flag")
d.FieldU1("system_audio_lock_flag")
d.FieldU1("system_video_lock_flag")
d.FieldU1("skip2")
d.FieldU5("video_bound")
d.FieldU1("packet_rate_restriction_flag")
d.FieldU7("reserved")
d.FieldArrayFn("stream_bound_entries", func(d *decode.D) {
for d.PeekBits(1) == 1 {
d.FieldStructFn("stream_bound_entry", func(d *decode.D) {
d.FieldU8("stream_id")
d.FieldU2("skip0")
d.FieldU1("pstd_buffer_bound_scale")
d.FieldU13("pstd_buffer_size_bound")
})
}
})
case startCode >= 0xbd:
//log.Printf("startCode: %#+v\n", startCode)
length := d.FieldU16("length")
// 0xbd-0xbd // Privatestream1
// 0xc0-0xdf // MPEG1OrMPEG2AudioStream
// 0xe0-0xef // MPEG1OrMPEG2VideoStream
hasExtension := startCode == 0xbd || (startCode >= 0xc0 && startCode <= 0xef)
var headerDataLength uint64
var extensionLength uint64
if hasExtension {
extensionLength = 3
d.FieldStructFn("extension", func(d *decode.D) {
d.FieldU2("skip0")
d.FieldU2("scramble_control")
d.FieldU1("priority")
d.FieldU1("data_alignment_indicator")
d.FieldU1("copyright")
d.FieldU1("original")
d.FieldU2("pts_dts_flags")
d.FieldU1("escr_flag")
d.FieldU1("es_rate_flag")
d.FieldU1("dsm_trick_mode_flag")
d.FieldU1("additional_copy_info_flag")
d.FieldU1("pes_crc_flag")
d.FieldU1("pes_ext_flag")
headerDataLength = d.FieldU8("header_data_length")
})
// TODO:
d.FieldBitBufLen("header_data", int64(headerDataLength)*8)
}
dataLen := int64(length-headerDataLength-extensionLength) * 8
switch startCode {
case privateStream1:
d.FieldStructFn("data", func(d *decode.D) {
d.DecodeLenFn(dataLen, func(d *decode.D) {
substreamNumber := d.FieldU8("substream")
substreamBB := d.FieldBitBufLen("data", dataLen-8)
v = subStreamPacket{
number: int(substreamNumber),
bb: substreamBB,
}
})
})
default:
d.FieldBitBufLen("data", dataLen)
}
default:
d.FieldBitBufLen("data", d.BitsLeft())
}
return v
}