fix WriteUInt

This commit is contained in:
nareix 2015-12-06 16:55:18 +08:00
parent 5d520f0d72
commit 57a7d68cf3
5 changed files with 142 additions and 43 deletions

View File

@ -65,13 +65,13 @@ type Crc32Reader struct {
Crc32 uint32
}
var debugCrc32 = false
var DebugCrc32 = false
func (self *Crc32Reader) Read(b []byte) (n int, err error) {
if n, err = self.R.Read(b); err != nil {
return
}
if debugCrc32 {
if DebugCrc32 {
fmt.Println("crc32: update", hex.EncodeToString(b))
}
self.Crc32 = updateIeeeCrc32(self.Crc32, b)
@ -83,7 +83,7 @@ func (self *Crc32Reader) ReadCrc32UIntAndCheck() (err error) {
return
}
if self.Crc32 != 0 {
err = fmt.Errorf("crc32 != 0")
err = fmt.Errorf("crc32(%x) != 0", self.Crc32)
return
}
return

View File

@ -8,6 +8,7 @@ import (
ts "../"
"fmt"
"encoding/hex"
"flag"
)
type Stream struct {
@ -27,7 +28,7 @@ type Sample struct {
Data []byte
}
func readSamples(ch chan Sample) {
func readSamples(filename string, ch chan Sample) {
defer func() {
close(ch)
}()
@ -36,7 +37,7 @@ func readSamples(ch chan Sample) {
var file *os.File
var err error
if file, err = os.Open("/tmp/out.ts"); err != nil {
if file, err = os.Open(filename); err != nil {
return
}
@ -137,8 +138,46 @@ func readSamples(ch chan Sample) {
}
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)
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 {
var sample Sample
@ -147,8 +186,10 @@ func main() {
break
}
if sample.Type == ts.ElementaryStreamTypeH264 {
fmt.Println("sample", len(sample.Data), "PCR", sample.PCR)
fmt.Print(hex.Dump(sample.Data))
if false {
fmt.Println("sample: ", len(sample.Data), "PCR", sample.PCR)
//fmt.Print(hex.Dump(sample.Data))
}
}
}
}

View File

@ -7,6 +7,8 @@ import (
"io/ioutil"
)
var DebugReader = true
func ReadUInt(r io.Reader, n int) (res uint, err error) {
var b [4]byte
if _, err = r.Read(b[0:n]); err != nil {
@ -55,7 +57,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
return
}
if debug {
if DebugReader {
fmt.Printf("ts: flags %s\n", FieldsDumper{
Fields: []struct{
Length int
@ -99,7 +101,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
return
}
if debug {
if DebugReader {
fmt.Printf("ts: ext_flags %s\n", FieldsDumper{
Fields: []struct{
Length int
@ -127,7 +129,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
}
// clock is 27MHz
self.PCR = UIntToPCR(v)
if debug {
if DebugReader {
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
}
if debug {
if DebugReader {
// rubish
//fmt.Println("ts: ", data)
}
@ -216,17 +218,8 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
}
length = flags & 0x3FF
if debug {
fmt.Printf("psi: %s\n", FieldsDumper{
Fields: []struct{
Length int
Desc string
}{
{4, "reserved"},
},
Val: flags,
Length: 16,
})
if DebugReader {
fmt.Printf("psi: tableid=%d len=%d\n", self.TableId, 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
}
if debug {
if DebugReader {
fmt.Printf("psi: %s\n", FieldsDumper{
Fields: []struct{
Length int
@ -268,7 +261,7 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
return
}
if debug {
if DebugReader {
fmt.Printf("psi: table_id=%x table_extension=%x secnum=%x lastsecnum=%x\n",
self.TableId,
self.TableIdExtension,
@ -299,7 +292,7 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
}
self.PCRPID = flags & 0x1fff
if debug {
if DebugReader {
fmt.Printf("pmt: %s\n", FieldsDumper{
Fields: []struct{
Length int
@ -375,12 +368,15 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
self.ElementaryStreamInfos = append(self.ElementaryStreamInfos, info)
}
if debug {
if DebugReader {
fmt.Printf("pmt: ProgramDescriptors %v\n", self.ProgramDescriptors)
fmt.Printf("pmt: ElementaryStreamInfos %v\n", self.ElementaryStreamInfos)
}
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
if DebugReader {
fmt.Printf("pmt: %s\n", err)
}
return
}
@ -416,10 +412,13 @@ func ReadPAT(r io.Reader) (self PAT, err error) {
}
if err = cr.ReadCrc32UIntAndCheck(); err != nil {
if DebugReader {
fmt.Printf("pat: %s\n", err)
}
return
}
if debug {
if DebugReader {
fmt.Printf("pat: %v\n", self)
}
@ -461,7 +460,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
return
}
if debug {
if DebugReader {
fmt.Printf("pes: %s\n", FieldsDumper{
Fields: []struct{
Length int
@ -489,7 +488,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
return
}
if debug {
if DebugReader {
fmt.Printf("pes: %s\n", FieldsDumper{
Fields: []struct{
Length int
@ -521,7 +520,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
}
self.PTS = PESUIntToTs(v)
if debug {
if DebugReader {
fmt.Printf("pes: pts %x=>%x %f\n",
v, self.PTS, float64(self.PTS)/90000)
}
@ -533,7 +532,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
return
}
self.DTS = PESUIntToTs(v)
if debug {
if DebugReader {
fmt.Printf("pes: dts %d\n", self.PTS)
}
}

2
ts.go
View File

@ -5,8 +5,6 @@ import (
"fmt"
)
const debug = true
const (
ElementaryStreamTypeH264 = 0x1B
ElementaryStreamTypeAdtsAAC = 0x0F

View File

@ -2,16 +2,12 @@
package ts
import (
_ "fmt"
"fmt"
"io"
"bytes"
)
type TSWriter struct {
W io.Writer
ContinuityCounter uint
PayloadUnitStart bool
}
const DebugWriter = true
func WriteUInt64(w io.Writer, val uint64, n int) (err error) {
var b [8]byte
@ -19,7 +15,7 @@ func WriteUInt64(w io.Writer, val uint64, n int) (err error) {
b[i] = byte(val)
val >>= 8
}
if _, err = w.Write(b[:]); err != nil {
if _, err = w.Write(b[:n]); err != nil {
return
}
return
@ -108,6 +104,63 @@ func WriteTSHeader(w io.Writer, self TSHeader) (err error) {
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) {
// pointer(8)
// table_id(8)
@ -135,10 +188,14 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
var flags, length uint
length = 2+3+4+uint(len(data))
flags = 0xb<<10|length
if err = WriteUInt(cw, flags, 1); err != nil {
if err = WriteUInt(cw, flags, 2); err != nil {
return
}
if DebugWriter {
fmt.Printf("wpsi: flags=%x\n", flags)
}
// Table ID extension(16)
if err = WriteUInt(cw, self.TableIdExtension, 2); err != nil {
return
@ -166,13 +223,17 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
}
// 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
}
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) {
// http://dvd.sourceforge.net/dvdinfo/pes-hdr.html