fix WriteUInt
This commit is contained in:
parent
5d520f0d72
commit
57a7d68cf3
@ -65,13 +65,13 @@ type Crc32Reader struct {
|
|||||||
Crc32 uint32
|
Crc32 uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
var debugCrc32 = false
|
var DebugCrc32 = false
|
||||||
|
|
||||||
func (self *Crc32Reader) Read(b []byte) (n int, err error) {
|
func (self *Crc32Reader) Read(b []byte) (n int, err error) {
|
||||||
if n, err = self.R.Read(b); err != nil {
|
if n, err = self.R.Read(b); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if debugCrc32 {
|
if DebugCrc32 {
|
||||||
fmt.Println("crc32: update", hex.EncodeToString(b))
|
fmt.Println("crc32: update", hex.EncodeToString(b))
|
||||||
}
|
}
|
||||||
self.Crc32 = updateIeeeCrc32(self.Crc32, b)
|
self.Crc32 = updateIeeeCrc32(self.Crc32, b)
|
||||||
@ -83,7 +83,7 @@ func (self *Crc32Reader) ReadCrc32UIntAndCheck() (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.Crc32 != 0 {
|
if self.Crc32 != 0 {
|
||||||
err = fmt.Errorf("crc32 != 0")
|
err = fmt.Errorf("crc32(%x) != 0", self.Crc32)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
ts "../"
|
ts "../"
|
||||||
"fmt"
|
"fmt"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"flag"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Stream struct {
|
type Stream struct {
|
||||||
@ -27,7 +28,7 @@ type Sample struct {
|
|||||||
Data []byte
|
Data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func readSamples(ch chan Sample) {
|
func readSamples(filename string, ch chan Sample) {
|
||||||
defer func() {
|
defer func() {
|
||||||
close(ch)
|
close(ch)
|
||||||
}()
|
}()
|
||||||
@ -36,7 +37,7 @@ func readSamples(ch chan Sample) {
|
|||||||
|
|
||||||
var file *os.File
|
var file *os.File
|
||||||
var err error
|
var err error
|
||||||
if file, err = os.Open("/tmp/out.ts"); err != nil {
|
if file, err = os.Open(filename); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +138,46 @@ func readSamples(ch chan Sample) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
input := flag.String("i", "", "input file")
|
||||||
|
output := flag.String("o", "", "output file")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var file *os.File
|
||||||
|
var err error
|
||||||
|
|
||||||
ch := make(chan Sample, 0)
|
ch := make(chan Sample, 0)
|
||||||
go readSamples(ch)
|
go readSamples(*input, ch)
|
||||||
|
|
||||||
|
if *output != "" {
|
||||||
|
if file, err = os.Create(*output); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writePAT := func() (err error) {
|
||||||
|
w := &ts.TSWriter{
|
||||||
|
W: file,
|
||||||
|
PID: 0,
|
||||||
|
}
|
||||||
|
pat := ts.PAT {
|
||||||
|
Entries: []ts.PATEntry{
|
||||||
|
{ProgramNumber: 1, ProgramMapPID: 4096},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
bw := &bytes.Buffer{}
|
||||||
|
if err = ts.WritePAT(bw, pat); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = w.Write(bw.Bytes(), false); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if file != nil {
|
||||||
|
writePAT()
|
||||||
|
file.Close()
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
var sample Sample
|
var sample Sample
|
||||||
@ -147,8 +186,10 @@ func main() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if sample.Type == ts.ElementaryStreamTypeH264 {
|
if sample.Type == ts.ElementaryStreamTypeH264 {
|
||||||
fmt.Println("sample", len(sample.Data), "PCR", sample.PCR)
|
if false {
|
||||||
fmt.Print(hex.Dump(sample.Data))
|
fmt.Println("sample: ", len(sample.Data), "PCR", sample.PCR)
|
||||||
|
//fmt.Print(hex.Dump(sample.Data))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
47
reader.go
47
reader.go
@ -7,6 +7,8 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var DebugReader = true
|
||||||
|
|
||||||
func ReadUInt(r io.Reader, n int) (res uint, err error) {
|
func ReadUInt(r io.Reader, n int) (res uint, err error) {
|
||||||
var b [4]byte
|
var b [4]byte
|
||||||
if _, err = r.Read(b[0:n]); err != nil {
|
if _, err = r.Read(b[0:n]); err != nil {
|
||||||
@ -55,7 +57,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("ts: flags %s\n", FieldsDumper{
|
fmt.Printf("ts: flags %s\n", FieldsDumper{
|
||||||
Fields: []struct{
|
Fields: []struct{
|
||||||
Length int
|
Length int
|
||||||
@ -99,7 +101,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("ts: ext_flags %s\n", FieldsDumper{
|
fmt.Printf("ts: ext_flags %s\n", FieldsDumper{
|
||||||
Fields: []struct{
|
Fields: []struct{
|
||||||
Length int
|
Length int
|
||||||
@ -127,7 +129,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
|
|||||||
}
|
}
|
||||||
// clock is 27MHz
|
// clock is 27MHz
|
||||||
self.PCR = UIntToPCR(v)
|
self.PCR = UIntToPCR(v)
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("ts: PCR %d %f\n", self.PCR, float64(self.PCR)/27000000)
|
fmt.Printf("ts: PCR %d %f\n", self.PCR, float64(self.PCR)/27000000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -168,7 +170,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
// rubish
|
// rubish
|
||||||
//fmt.Println("ts: ", data)
|
//fmt.Println("ts: ", data)
|
||||||
}
|
}
|
||||||
@ -216,17 +218,8 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
|||||||
}
|
}
|
||||||
length = flags & 0x3FF
|
length = flags & 0x3FF
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("psi: %s\n", FieldsDumper{
|
fmt.Printf("psi: tableid=%d len=%d\n", self.TableId, length)
|
||||||
Fields: []struct{
|
|
||||||
Length int
|
|
||||||
Desc string
|
|
||||||
}{
|
|
||||||
{4, "reserved"},
|
|
||||||
},
|
|
||||||
Val: flags,
|
|
||||||
Length: 16,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lr = &io.LimitedReader{R: cr, N: int64(length)}
|
lr = &io.LimitedReader{R: cr, N: int64(length)}
|
||||||
@ -243,7 +236,7 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("psi: %s\n", FieldsDumper{
|
fmt.Printf("psi: %s\n", FieldsDumper{
|
||||||
Fields: []struct{
|
Fields: []struct{
|
||||||
Length int
|
Length int
|
||||||
@ -268,7 +261,7 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("psi: table_id=%x table_extension=%x secnum=%x lastsecnum=%x\n",
|
fmt.Printf("psi: table_id=%x table_extension=%x secnum=%x lastsecnum=%x\n",
|
||||||
self.TableId,
|
self.TableId,
|
||||||
self.TableIdExtension,
|
self.TableIdExtension,
|
||||||
@ -299,7 +292,7 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
|||||||
}
|
}
|
||||||
self.PCRPID = flags & 0x1fff
|
self.PCRPID = flags & 0x1fff
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("pmt: %s\n", FieldsDumper{
|
fmt.Printf("pmt: %s\n", FieldsDumper{
|
||||||
Fields: []struct{
|
Fields: []struct{
|
||||||
Length int
|
Length int
|
||||||
@ -375,12 +368,15 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
|
|||||||
self.ElementaryStreamInfos = append(self.ElementaryStreamInfos, info)
|
self.ElementaryStreamInfos = append(self.ElementaryStreamInfos, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("pmt: ProgramDescriptors %v\n", self.ProgramDescriptors)
|
fmt.Printf("pmt: ProgramDescriptors %v\n", self.ProgramDescriptors)
|
||||||
fmt.Printf("pmt: ElementaryStreamInfos %v\n", self.ElementaryStreamInfos)
|
fmt.Printf("pmt: ElementaryStreamInfos %v\n", self.ElementaryStreamInfos)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
||||||
|
if DebugReader {
|
||||||
|
fmt.Printf("pmt: %s\n", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,10 +412,13 @@ func ReadPAT(r io.Reader) (self PAT, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
|
||||||
|
if DebugReader {
|
||||||
|
fmt.Printf("pat: %s\n", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("pat: %v\n", self)
|
fmt.Printf("pat: %v\n", self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +460,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("pes: %s\n", FieldsDumper{
|
fmt.Printf("pes: %s\n", FieldsDumper{
|
||||||
Fields: []struct{
|
Fields: []struct{
|
||||||
Length int
|
Length int
|
||||||
@ -489,7 +488,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("pes: %s\n", FieldsDumper{
|
fmt.Printf("pes: %s\n", FieldsDumper{
|
||||||
Fields: []struct{
|
Fields: []struct{
|
||||||
Length int
|
Length int
|
||||||
@ -521,7 +520,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
}
|
}
|
||||||
self.PTS = PESUIntToTs(v)
|
self.PTS = PESUIntToTs(v)
|
||||||
|
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("pes: pts %x=>%x %f\n",
|
fmt.Printf("pes: pts %x=>%x %f\n",
|
||||||
v, self.PTS, float64(self.PTS)/90000)
|
v, self.PTS, float64(self.PTS)/90000)
|
||||||
}
|
}
|
||||||
@ -533,7 +532,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.DTS = PESUIntToTs(v)
|
self.DTS = PESUIntToTs(v)
|
||||||
if debug {
|
if DebugReader {
|
||||||
fmt.Printf("pes: dts %d\n", self.PTS)
|
fmt.Printf("pes: dts %d\n", self.PTS)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
ts.go
2
ts.go
@ -5,8 +5,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
const debug = true
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ElementaryStreamTypeH264 = 0x1B
|
ElementaryStreamTypeH264 = 0x1B
|
||||||
ElementaryStreamTypeAdtsAAC = 0x0F
|
ElementaryStreamTypeAdtsAAC = 0x0F
|
||||||
|
79
writer.go
79
writer.go
@ -2,16 +2,12 @@
|
|||||||
package ts
|
package ts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
_ "fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"bytes"
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TSWriter struct {
|
const DebugWriter = true
|
||||||
W io.Writer
|
|
||||||
ContinuityCounter uint
|
|
||||||
PayloadUnitStart bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func WriteUInt64(w io.Writer, val uint64, n int) (err error) {
|
func WriteUInt64(w io.Writer, val uint64, n int) (err error) {
|
||||||
var b [8]byte
|
var b [8]byte
|
||||||
@ -19,7 +15,7 @@ func WriteUInt64(w io.Writer, val uint64, n int) (err error) {
|
|||||||
b[i] = byte(val)
|
b[i] = byte(val)
|
||||||
val >>= 8
|
val >>= 8
|
||||||
}
|
}
|
||||||
if _, err = w.Write(b[:]); err != nil {
|
if _, err = w.Write(b[:n]); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -108,6 +104,63 @@ func WriteTSHeader(w io.Writer, self TSHeader) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TSWriter struct {
|
||||||
|
W io.Writer
|
||||||
|
PID uint
|
||||||
|
PCR uint64
|
||||||
|
OPCR uint64
|
||||||
|
ContinuityCounter uint
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TSWriter) Write(b []byte, RandomAccessIndicator bool) (err error) {
|
||||||
|
for i := 0; len(b) > 0; i++ {
|
||||||
|
header := TSHeader{
|
||||||
|
PID: self.PID,
|
||||||
|
PCR: self.PCR,
|
||||||
|
OPCR: self.OPCR,
|
||||||
|
ContinuityCounter: self.ContinuityCounter,
|
||||||
|
RandomAccessIndicator: RandomAccessIndicator,
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
header.PayloadUnitStart = true
|
||||||
|
}
|
||||||
|
bw := &bytes.Buffer{}
|
||||||
|
if err = WriteTSHeader(bw, header); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var data []byte
|
||||||
|
dataLen := 188-bw.Len()
|
||||||
|
|
||||||
|
if DebugWriter {
|
||||||
|
fmt.Printf("tsw: datalen=%d blen=%d\n", dataLen, len(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(b) > dataLen {
|
||||||
|
data = b[:dataLen]
|
||||||
|
b = b[dataLen:]
|
||||||
|
} else {
|
||||||
|
data = make([]byte, dataLen)
|
||||||
|
copy(data, b)
|
||||||
|
for i := len(b); i < dataLen; i++ {
|
||||||
|
data[i] = 0xff
|
||||||
|
}
|
||||||
|
b = b[len(b):]
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = self.W.Write(bw.Bytes()); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, err = self.W.Write(data); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ContinuityCounter++
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
|
func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
|
||||||
// pointer(8)
|
// pointer(8)
|
||||||
// table_id(8)
|
// table_id(8)
|
||||||
@ -135,10 +188,14 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
|
|||||||
var flags, length uint
|
var flags, length uint
|
||||||
length = 2+3+4+uint(len(data))
|
length = 2+3+4+uint(len(data))
|
||||||
flags = 0xb<<10|length
|
flags = 0xb<<10|length
|
||||||
if err = WriteUInt(cw, flags, 1); err != nil {
|
if err = WriteUInt(cw, flags, 2); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if DebugWriter {
|
||||||
|
fmt.Printf("wpsi: flags=%x\n", flags)
|
||||||
|
}
|
||||||
|
|
||||||
// Table ID extension(16)
|
// Table ID extension(16)
|
||||||
if err = WriteUInt(cw, self.TableIdExtension, 2); err != nil {
|
if err = WriteUInt(cw, self.TableIdExtension, 2); err != nil {
|
||||||
return
|
return
|
||||||
@ -166,13 +223,17 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// crc(32)
|
// crc(32)
|
||||||
if err = WriteUInt(w, uint(cw.Crc32), 4); err != nil {
|
if err = WriteUInt(w, bswap32(uint(cw.Crc32)), 4); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func bswap32(v uint) uint {
|
||||||
|
return (v>>24)|((v>>16)&0xff)<<8|((v>>8)&0xff)<<16|(v&0xff)<<24
|
||||||
|
}
|
||||||
|
|
||||||
func WritePES(w io.Writer, self PESHeader, data []byte) (err error) {
|
func WritePES(w io.Writer, self PESHeader, data []byte) (err error) {
|
||||||
// http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
|
// http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user