rename isom to aacparser

This commit is contained in:
nareix 2016-04-19 21:33:07 +08:00
parent a5ec0acea0
commit dfd71d04bf
12 changed files with 230 additions and 255 deletions

View File

@ -1,13 +1,12 @@
package ts package ts
import ( import (
"io"
"fmt"
"encoding/hex" "encoding/hex"
"fmt"
"io"
) )
var ieeeCrc32Tbl = []uint32 { var ieeeCrc32Tbl = []uint32{
0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517, 0x00000000, 0xB71DC104, 0x6E3B8209, 0xD926430D, 0xDC760413, 0x6B6BC517,
0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B, 0xB24D861A, 0x0550471E, 0xB8ED0826, 0x0FF0C922, 0xD6D68A2F, 0x61CB4B2B,
0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048, 0x649B0C35, 0xD386CD31, 0x0AA08E3C, 0xBDBD4F38, 0x70DB114C, 0xC7C6D048,
@ -55,13 +54,13 @@ var ieeeCrc32Tbl = []uint32 {
func updateIeeeCrc32(crc uint32, data []byte) uint32 { func updateIeeeCrc32(crc uint32, data []byte) uint32 {
for _, b := range data { for _, b := range data {
crc = ieeeCrc32Tbl[b^byte(crc)]^(crc>>8) crc = ieeeCrc32Tbl[b^byte(crc)] ^ (crc >> 8)
} }
return crc return crc
} }
type Crc32Reader struct { type Crc32Reader struct {
R io.Reader R io.Reader
Crc32 uint32 Crc32 uint32
} }
@ -90,7 +89,7 @@ func (self *Crc32Reader) ReadCrc32UIntAndCheck() (err error) {
} }
type Crc32Writer struct { type Crc32Writer struct {
W io.Writer W io.Writer
Crc32 uint32 Crc32 uint32
} }
@ -101,4 +100,3 @@ func (self *Crc32Writer) Write(b []byte) (n int, err error) {
self.Crc32 = updateIeeeCrc32(self.Crc32, b) self.Crc32 = updateIeeeCrc32(self.Crc32, b)
return return
} }

View File

@ -1,4 +1,3 @@
package ts package ts
import ( import (
@ -7,8 +6,7 @@ import (
func TestChecksum(t *testing.T) { func TestChecksum(t *testing.T) {
b := []byte("hello world") b := []byte("hello world")
b = append(b, []byte{0xbb,0x08,0xec,0x87}...) b = append(b, []byte{0xbb, 0x08, 0xec, 0x87}...)
crc := updateIeeeCrc32(0xffffffff, b) crc := updateIeeeCrc32(0xffffffff, b)
t.Logf("%x", crc) t.Logf("%x", crc)
} }

View File

@ -1,21 +1,20 @@
package ts package ts
import ( import (
"io"
"bytes" "bytes"
"fmt" "fmt"
"github.com/nareix/mp4/isom" "github.com/nareix/codec/aacparser"
"io"
) )
type Demuxer struct { type Demuxer struct {
R io.Reader R io.Reader
pat PAT pat PAT
pmt *PMT pmt *PMT
Tracks []*Track Tracks []*Track
TrackH264 *Track TrackH264 *Track
TrackAAC *Track TrackAAC *Track
} }
// ParsePacket() (pid uint, counter int, isStart bool, pts, dst int64, isKeyFrame bool) // ParsePacket() (pid uint, counter int, isStart bool, pts, dst int64, isKeyFrame bool)
@ -33,7 +32,7 @@ func (self *Demuxer) ReadHeader() (err error) {
for { for {
if self.pmt != nil { if self.pmt != nil {
n := 0 n := 0
for _, track := range(self.Tracks) { for _, track := range self.Tracks {
if track.payloadReady { if track.payloadReady {
n++ n++
} }
@ -58,7 +57,7 @@ func (self *Demuxer) ReadSample() (track *Track, err error) {
} }
for { for {
for _, _track := range(self.Tracks) { for _, _track := range self.Tracks {
if _track.payloadReady { if _track.payloadReady {
track = _track track = _track
return return
@ -87,13 +86,13 @@ func (self *Demuxer) readPacket() (err error) {
} }
} else { } else {
if self.pmt == nil { if self.pmt == nil {
for _, entry := range(self.pat.Entries) { for _, entry := range self.pat.Entries {
if entry.ProgramMapPID == header.PID { if entry.ProgramMapPID == header.PID {
self.pmt = new(PMT) self.pmt = new(PMT)
if *self.pmt, err = ReadPMT(bytes.NewReader(payload)); err != nil { if *self.pmt, err = ReadPMT(bytes.NewReader(payload)); err != nil {
return return
} }
for _, info := range(self.pmt.ElementaryStreamInfos) { for _, info := range self.pmt.ElementaryStreamInfos {
track := &Track{} track := &Track{}
track.demuxer = self track.demuxer = self
@ -113,7 +112,7 @@ func (self *Demuxer) readPacket() (err error) {
} }
} else { } else {
for _, track := range(self.Tracks) { for _, track := range self.Tracks {
if header.PID == track.pid { if header.PID == track.pid {
if err = track.appendPacket(header, payload); err != nil { if err = track.appendPacket(header, payload); err != nil {
return return
@ -126,7 +125,7 @@ func (self *Demuxer) readPacket() (err error) {
return return
} }
func (self *Track) GetMPEG4AudioConfig() isom.MPEG4AudioConfig { func (self *Track) GetMPEG4AudioConfig() aacparser.MPEG4AudioConfig {
return self.mpeg4AudioConfig return self.mpeg4AudioConfig
} }
@ -154,7 +153,7 @@ func (self *Track) appendPayload() (err error) {
if self.Type == AAC { if self.Type == AAC {
if !self.mpeg4AudioConfig.IsValid() { if !self.mpeg4AudioConfig.IsValid() {
if self.mpeg4AudioConfig, _, _, _, err = isom.ReadADTSFrame(self.payload); err != nil { if self.mpeg4AudioConfig, _, _, _, err = aacparser.ReadADTSFrame(self.payload); err != nil {
return return
} }
self.mpeg4AudioConfig = self.mpeg4AudioConfig.Complete() self.mpeg4AudioConfig = self.mpeg4AudioConfig.Complete()
@ -200,4 +199,3 @@ func (self *Track) appendPacket(header TSHeader, payload []byte) (err error) {
return return
} }

View File

@ -1,52 +1,51 @@
package main package main
import ( import (
"bytes"
"os"
"io"
ts "../" ts "../"
"fmt" "bytes"
"encoding/hex"
"encoding/gob" "encoding/gob"
"runtime/pprof" "encoding/hex"
"flag" "flag"
"fmt"
"io"
"os"
"runtime/pprof"
) )
type GobAllSamples struct { type GobAllSamples struct {
TimeScale int TimeScale int
SPS []byte SPS []byte
PPS []byte PPS []byte
Samples []GobSample Samples []GobSample
} }
type GobSample struct { type GobSample struct {
Duration int Duration int
Data []byte Data []byte
Sync bool Sync bool
} }
type Stream struct { type Stream struct {
PID uint PID uint
PESHeader *ts.PESHeader PESHeader *ts.PESHeader
FirstTSHeader ts.TSHeader FirstTSHeader ts.TSHeader
Title string Title string
Data bytes.Buffer Data bytes.Buffer
Type uint Type uint
PCR uint64 PCR uint64
} }
type Sample struct { type Sample struct {
Type uint Type uint
PCR uint64 PCR uint64
PTS uint64 PTS uint64
DTS uint64 DTS uint64
Data []byte Data []byte
RandomAccessIndicator bool RandomAccessIndicator bool
} }
var ( var (
debugData = true debugData = true
debugStream = true debugStream = true
) )
@ -75,7 +74,7 @@ func readSamples(filename string, ch chan Sample) {
stream, _ = streams[pid] stream, _ = streams[pid]
if stream == nil { if stream == nil {
stream = &Stream{ stream = &Stream{
PID: pid, PID: pid,
Type: info.StreamType, Type: info.StreamType,
} }
if stream.Type == ts.ElementaryStreamTypeH264 { if stream.Type == ts.ElementaryStreamTypeH264 {
@ -99,9 +98,9 @@ func readSamples(filename string, ch chan Sample) {
ch <- Sample{ ch <- Sample{
Type: stream.Type, Type: stream.Type,
Data: stream.Data.Bytes(), Data: stream.Data.Bytes(),
PTS: stream.PESHeader.PTS, PTS: stream.PESHeader.PTS,
DTS: stream.PESHeader.DTS, DTS: stream.PESHeader.DTS,
PCR: stream.FirstTSHeader.PCR, PCR: stream.FirstTSHeader.PCR,
RandomAccessIndicator: stream.FirstTSHeader.RandomAccessIndicator, RandomAccessIndicator: stream.FirstTSHeader.RandomAccessIndicator,
} }
} }
@ -157,7 +156,7 @@ func readSamples(filename string, ch chan Sample) {
} }
} }
for _, entry := range(pat.Entries) { for _, entry := range pat.Entries {
if entry.ProgramMapPID == header.PID { if entry.ProgramMapPID == header.PID {
//fmt.Println("matchs", entry) //fmt.Println("matchs", entry)
if pmt, err = ts.ReadPMT(pr); err != nil { if pmt, err = ts.ReadPMT(pr); err != nil {
@ -167,7 +166,7 @@ func readSamples(filename string, ch chan Sample) {
} }
} }
for _, info = range(pmt.ElementaryStreamInfos) { for _, info = range pmt.ElementaryStreamInfos {
if info.ElementaryPID == header.PID { if info.ElementaryPID == header.PID {
onStreamPayload() onStreamPayload()
} }
@ -231,7 +230,7 @@ func testInputGob(pathGob string, pathOut string, testSeg bool, writeM3u8 bool)
if sample.Sync { if sample.Sync {
syncCount++ syncCount++
if testSeg { if testSeg {
if syncCount % 3 == 0 { if syncCount%3 == 0 {
filename := fmt.Sprintf("%s.seg%d.ts", pathOut, segCount) filename := fmt.Sprintf("%s.seg%d.ts", pathOut, segCount)
if debugStream { if debugStream {
@ -241,7 +240,7 @@ func testInputGob(pathGob string, pathOut string, testSeg bool, writeM3u8 bool)
if m3u8file != nil { if m3u8file != nil {
info, _ := outfile.Stat() info, _ := outfile.Stat()
size := info.Size() size := info.Size()
dur := float64(trackH264.PTS - lastPTS) / float64(allSamples.TimeScale) dur := float64(trackH264.PTS-lastPTS) / float64(allSamples.TimeScale)
writeM3U8Item(m3u8file, lastFilename, size, dur) writeM3U8Item(m3u8file, lastFilename, size, dur)
} }
@ -353,8 +352,8 @@ func main() {
pes := ts.PESHeader{ pes := ts.PESHeader{
StreamId: streamId, StreamId: streamId,
PTS: sample.PTS, PTS: sample.PTS,
DTS: sample.DTS, DTS: sample.DTS,
} }
w.PID = pid w.PID = pid
w.PCR = sample.PCR w.PCR = sample.PCR
@ -369,7 +368,7 @@ func main() {
writePAT() writePAT()
writePMT() writePMT()
w = &ts.TSWriter{ w = &ts.TSWriter{
W: file, W: file,
PID: 0x100, PID: 0x100,
} }
w.EnableVecWriter() w.EnableVecWriter()
@ -395,4 +394,3 @@ func main() {
} }
} }

View File

@ -1,21 +1,20 @@
package ts package ts
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"github.com/nareix/mp4/isom"
"github.com/nareix/codec/h264parser" "github.com/nareix/codec/h264parser"
"github.com/nareix/codec/aacparser"
"io"
) )
type Muxer struct { type Muxer struct {
W io.Writer W io.Writer
tswPAT *TSWriter tswPAT *TSWriter
tswPMT *TSWriter tswPMT *TSWriter
elemStreams []ElementaryStreamInfo elemStreams []ElementaryStreamInfo
TrackH264 *Track TrackH264 *Track
Tracks []*Track Tracks []*Track
} }
func (self *Muxer) newTrack(pid uint, streamId uint) (track *Track) { func (self *Muxer) newTrack(pid uint, streamId uint) (track *Track) {
@ -66,7 +65,7 @@ func (self *Muxer) WriteHeader() (err error) {
} }
WritePAT(bufPAT, pat) WritePAT(bufPAT, pat)
pmt := PMT{ pmt := PMT{
PCRPID: 0x100, PCRPID: 0x100,
ElementaryStreamInfos: self.elemStreams, ElementaryStreamInfos: self.elemStreams,
} }
WritePMT(bufPMT, pmt) WritePMT(bufPMT, pmt)
@ -87,7 +86,7 @@ func (self *Muxer) WriteHeader() (err error) {
} }
// about to remove // about to remove
for _, track := range(self.Tracks) { for _, track := range self.Tracks {
track.spsHasWritten = false track.spsHasWritten = false
} }
@ -106,20 +105,20 @@ func (self *Track) TimeScale() int64 {
return self.timeScale return self.timeScale
} }
func (self *Track) SetMPEG4AudioConfig(config isom.MPEG4AudioConfig) { func (self *Track) SetMPEG4AudioConfig(config aacparser.MPEG4AudioConfig) {
self.mpeg4AudioConfig = config self.mpeg4AudioConfig = config
} }
func (self *Track) tsToPesTs(ts int64) uint64 { func (self *Track) tsToPesTs(ts int64) uint64 {
return uint64(ts)*PTS_HZ/uint64(self.timeScale)+PTS_HZ return uint64(ts)*PTS_HZ/uint64(self.timeScale) + PTS_HZ
} }
func (self *Track) tsToPCR(ts int64) uint64 { func (self *Track) tsToPCR(ts int64) uint64 {
return uint64(ts)*PCR_HZ/uint64(self.timeScale)+PCR_HZ return uint64(ts)*PCR_HZ/uint64(self.timeScale) + PCR_HZ
} }
func (self *Track) tsToTime(ts int64) float64 { func (self *Track) tsToTime(ts int64) float64 {
return float64(ts)/float64(self.timeScale) return float64(ts) / float64(self.timeScale)
} }
func (self *Track) WriteSample(pts int64, dts int64, isKeyFrame bool, data []byte) (err error) { func (self *Track) WriteSample(pts int64, dts int64, isKeyFrame bool, data []byte) (err error) {
@ -129,8 +128,8 @@ func (self *Track) WriteSample(pts int64, dts int64, isKeyFrame bool, data []byt
if self.Type == AAC { if self.Type == AAC {
if !isom.IsADTSFrame(data) { if !aacparser.IsADTSFrame(data) {
data = append(isom.MakeADTSHeader(self.mpeg4AudioConfig, 1024, len(data)), data...) data = append(aacparser.MakeADTSHeader(self.mpeg4AudioConfig, 1024, len(data)), data...)
} }
if false { if false {
fmt.Printf("WriteSample=%x\n", data[:5]) fmt.Printf("WriteSample=%x\n", data[:5])
@ -139,7 +138,7 @@ func (self *Track) WriteSample(pts int64, dts int64, isKeyFrame bool, data []byt
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
pes := PESHeader{ pes := PESHeader{
StreamId: self.streamId, StreamId: self.streamId,
PTS: self.tsToPesTs(pts), PTS: self.tsToPesTs(pts),
} }
WritePESHeader(buf, pes, len(data)) WritePESHeader(buf, pes, len(data))
buf.Write(data) buf.Write(data)
@ -154,7 +153,7 @@ func (self *Track) WriteSample(pts int64, dts int64, isKeyFrame bool, data []byt
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
pes := PESHeader{ pes := PESHeader{
StreamId: self.streamId, StreamId: self.streamId,
PTS: self.tsToPesTs(pts), PTS: self.tsToPesTs(pts),
} }
if dts != pts { if dts != pts {
pes.DTS = self.tsToPesTs(dts) pes.DTS = self.tsToPesTs(dts)
@ -182,17 +181,17 @@ func (self *Track) WriteSample(pts int64, dts int64, isKeyFrame bool, data []byt
/* about to remove */ /* about to remove */
func (self *Track) setPCR() { func (self *Track) setPCR() {
self.tsw.PCR = uint64(self.PTS)*PCR_HZ/uint64(self.timeScale) self.tsw.PCR = uint64(self.PTS) * PCR_HZ / uint64(self.timeScale)
} }
func (self *Track) getPesHeader(dataLength int) (data []byte){ func (self *Track) getPesHeader(dataLength int) (data []byte) {
if self.PTS == 0 { if self.PTS == 0 {
self.PTS = self.timeScale self.PTS = self.timeScale
} }
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
pes := PESHeader{ pes := PESHeader{
StreamId: self.streamId, StreamId: self.streamId,
PTS: uint64(self.PTS)*PTS_HZ/uint64(self.timeScale), PTS: uint64(self.PTS) * PTS_HZ / uint64(self.timeScale),
} }
WritePESHeader(buf, pes, dataLength) WritePESHeader(buf, pes, dataLength)
return buf.Bytes() return buf.Bytes()
@ -216,9 +215,9 @@ func (self *Track) WriteH264NALU(sync bool, duration int, nalu []byte) (err erro
for i, nalu := range nalus { for i, nalu := range nalus {
var startCode []byte var startCode []byte
if i == 0 { if i == 0 {
startCode = []byte{0,0,0,1,0x9,0xf0,0,0,0,1} // AUD startCode = []byte{0, 0, 0, 1, 0x9, 0xf0, 0, 0, 0, 1} // AUD
} else { } else {
startCode = []byte{0,0,1} startCode = []byte{0, 0, 1}
} }
data.Append(startCode) data.Append(startCode)
data.Append(nalu) data.Append(nalu)
@ -252,4 +251,3 @@ func (self *Track) WriteADTSAACFrame(duration int, frame []byte) (err error) {
self.incPTS(duration) self.incPTS(duration)
return return
} }

View File

@ -1,4 +1,3 @@
package ts package ts
import ( import (
@ -32,7 +31,7 @@ func ReadUInt64(r io.Reader, n int) (res uint64, err error) {
if res32, err = ReadUInt(r, n-4); err != nil { if res32, err = ReadUInt(r, n-4); err != nil {
return return
} }
res |= uint64(res32)<<32 res |= uint64(res32) << 32
n = 4 n = 4
} }
if res32, err = ReadUInt(r, n); err != nil { if res32, err = ReadUInt(r, n); err != nil {
@ -59,9 +58,9 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
if DebugReader { if DebugReader {
fmt.Printf("ts: flags %s\n", FieldsDumper{ fmt.Printf("ts: flags %s\n", FieldsDumper{
Fields: []struct{ Fields: []struct {
Length int Length int
Desc string Desc string
}{ }{
{8, "sync"}, {8, "sync"},
{1, "transport_error_indicator"}, {1, "transport_error_indicator"},
@ -73,17 +72,17 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
{1, "payload_flag"}, {1, "payload_flag"},
{4, "continuity_counter"}, {4, "continuity_counter"},
}, },
Val: flags, Val: flags,
Length: 32, Length: 32,
}) })
} }
if flags & 0x400000 != 0 { if flags&0x400000 != 0 {
// When set to '1' it indicates that this TS packet contains the first PES packet. // When set to '1' it indicates that this TS packet contains the first PES packet.
self.PayloadUnitStart = true self.PayloadUnitStart = true
} }
if (flags & 0xff000000) >> 24 != 0x47 { if (flags&0xff000000)>>24 != 0x47 {
err = fmt.Errorf("invalid sync") err = fmt.Errorf("invalid sync")
return return
} }
@ -91,7 +90,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
self.PID = (flags & 0x1fff00) >> 8 self.PID = (flags & 0x1fff00) >> 8
self.ContinuityCounter = flags & 0xf self.ContinuityCounter = flags & 0xf
if flags & 0x20 != 0 { if flags&0x20 != 0 {
var flags, length uint var flags, length uint
if length, err = ReadUInt(r, 1); err != nil { if length, err = ReadUInt(r, 1); err != nil {
return return
@ -104,9 +103,9 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
if DebugReader { 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
Desc string Desc string
}{ }{
{1, "discontinuity_indicator"}, {1, "discontinuity_indicator"},
{1, "random_access_indicator"}, {1, "random_access_indicator"},
@ -117,18 +116,18 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
{1, "transport_private_data_flag"}, {1, "transport_private_data_flag"},
{1, "adaptation_field_extension_flag"}, {1, "adaptation_field_extension_flag"},
}, },
Val: flags, Val: flags,
Length: 8, Length: 8,
}) })
} }
// random_access_indicator // random_access_indicator
if flags & 0x40 != 0 { if flags&0x40 != 0 {
self.RandomAccessIndicator = true self.RandomAccessIndicator = true
} }
// PCR // PCR
if flags & 0x10 != 0 { if flags&0x10 != 0 {
var v uint64 var v uint64
if v, err = ReadUInt64(lr, 6); err != nil { if v, err = ReadUInt64(lr, 6); err != nil {
return return
@ -141,7 +140,7 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
} }
// OPCR // OPCR
if flags & 0x08 != 0 { if flags&0x08 != 0 {
var v uint64 var v uint64
if v, err = ReadUInt64(lr, 6); err != nil { if v, err = ReadUInt64(lr, 6); err != nil {
return return
@ -150,14 +149,14 @@ func ReadTSHeader(r io.Reader) (self TSHeader, err error) {
} }
// Splice countdown // Splice countdown
if flags & 0x04 != 0 { if flags&0x04 != 0 {
if _, err = ReadUInt(lr, 1); err != nil { if _, err = ReadUInt(lr, 1); err != nil {
return return
} }
} }
// Transport private data // Transport private data
if flags & 0x02 != 0 { if flags&0x02 != 0 {
var length uint var length uint
if length, err = ReadUInt(lr, 1); err != nil { if length, err = ReadUInt(lr, 1); err != nil {
return return
@ -212,7 +211,6 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
fmt.Printf("psi: pointer=%d\n", pointer) fmt.Printf("psi: pointer=%d\n", pointer)
} }
if pointer != 0 { if pointer != 0 {
if err = ReadDummy(r, int(pointer)); err != nil { if err = ReadDummy(r, int(pointer)); err != nil {
return return
@ -253,15 +251,15 @@ func ReadPSI(r io.Reader) (self PSI, lr *io.LimitedReader, cr *Crc32Reader, err
if DebugReader { if DebugReader {
fmt.Printf("psi: %s\n", FieldsDumper{ fmt.Printf("psi: %s\n", FieldsDumper{
Fields: []struct{ Fields: []struct {
Length int Length int
Desc string Desc string
}{ }{
{2, "resverd"}, {2, "resverd"},
{5, "version"}, {5, "version"},
{1, "current_next_indicator"}, {1, "current_next_indicator"},
}, },
Val: flags, Val: flags,
Length: 8, Length: 8,
}) })
} }
@ -328,14 +326,14 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
if DebugReader { if DebugReader {
fmt.Printf("pmt: %s\n", FieldsDumper{ fmt.Printf("pmt: %s\n", FieldsDumper{
Fields: []struct{ Fields: []struct {
Length int Length int
Desc string Desc string
}{ }{
{3, "reserved"}, {3, "reserved"},
{13, "pcrpid"}, {13, "pcrpid"},
}, },
Val: flags, Val: flags,
Length: 16, Length: 16,
}) })
} }
@ -374,14 +372,14 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
if DebugReader { if DebugReader {
fmt.Printf("pmt: info1 %s\n", FieldsDumper{ fmt.Printf("pmt: info1 %s\n", FieldsDumper{
Fields: []struct{ Fields: []struct {
Length int Length int
Desc string Desc string
}{ }{
{3, "reserved"}, {3, "reserved"},
{13, "elementary_pid"}, {13, "elementary_pid"},
}, },
Val: flags, Val: flags,
Length: 16, Length: 16,
}) })
} }
@ -395,14 +393,14 @@ func ReadPMT(r io.Reader) (self PMT, err error) {
if DebugReader { if DebugReader {
fmt.Printf("pmt: info2 %s\n", FieldsDumper{ fmt.Printf("pmt: info2 %s\n", FieldsDumper{
Fields: []struct{ Fields: []struct {
Length int Length int
Desc string Desc string
}{ }{
{6, "reserved"}, {6, "reserved"},
{10, "es_info_length"}, {10, "es_info_length"},
}, },
Val: flags, Val: flags,
Length: 16, Length: 16,
}) })
} }
@ -500,7 +498,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
} }
if length == 0 { if length == 0 {
length = 1<<31 length = 1 << 31
} }
lrAll := &io.LimitedReader{R: r, N: int64(length)} lrAll := &io.LimitedReader{R: r, N: int64(length)}
lr := lrAll lr := lrAll
@ -517,9 +515,9 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
if DebugReader { if DebugReader {
fmt.Printf("pes: %s\n", FieldsDumper{ fmt.Printf("pes: %s\n", FieldsDumper{
Fields: []struct{ Fields: []struct {
Length int Length int
Desc string Desc string
}{ }{
{2, "scrambling_control"}, {2, "scrambling_control"},
{1, "priority"}, {1, "priority"},
@ -527,7 +525,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
{1, "copyright"}, {1, "copyright"},
{1, "original_or_copy"}, {1, "original_or_copy"},
}, },
Val: flags, Val: flags,
Length: 6, Length: 6,
}) })
} }
@ -545,9 +543,9 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
if DebugReader { if DebugReader {
fmt.Printf("pes: %s\n", FieldsDumper{ fmt.Printf("pes: %s\n", FieldsDumper{
Fields: []struct{ Fields: []struct {
Length int Length int
Desc string Desc string
}{ }{
{2, "pts_dts_flags"}, {2, "pts_dts_flags"},
{1, "escr_flag"}, {1, "escr_flag"},
@ -557,7 +555,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
{1, "pes_crc_flag"}, {1, "pes_crc_flag"},
{1, "pes_extension_flag"}, {1, "pes_extension_flag"},
}, },
Val: flags, Val: flags,
Length: 8, Length: 8,
}) })
} }
@ -568,7 +566,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
} }
lr = &io.LimitedReader{R: lr, N: int64(length)} lr = &io.LimitedReader{R: lr, N: int64(length)}
if flags & 0x80 != 0 { if flags&0x80 != 0 {
var v uint64 var v uint64
if v, err = ReadUInt64(lr, 5); err != nil { if v, err = ReadUInt64(lr, 5); err != nil {
return return
@ -580,7 +578,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
} }
} }
if flags & 0x40 != 0 && flags & 0x80 != 0 { if flags&0x40 != 0 && flags&0x80 != 0 {
var v uint64 var v uint64
if v, err = ReadUInt64(lr, 5); err != nil { if v, err = ReadUInt64(lr, 5); err != nil {
return return
@ -592,35 +590,35 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
} }
// ESCR flag // ESCR flag
if flags & 0x20 != 0 { if flags&0x20 != 0 {
if _, err = ReadUInt64(lr, 6); err != nil { if _, err = ReadUInt64(lr, 6); err != nil {
return return
} }
} }
// ES rate flag // ES rate flag
if flags & 0x10 != 0 { if flags&0x10 != 0 {
if _, err = ReadUInt64(lr, 3); err != nil { if _, err = ReadUInt64(lr, 3); err != nil {
return return
} }
} }
// additional copy info flag // additional copy info flag
if flags & 0x04 != 0 { if flags&0x04 != 0 {
if _, err = ReadUInt(lr, 1); err != nil { if _, err = ReadUInt(lr, 1); err != nil {
return return
} }
} }
// PES CRC flag // PES CRC flag
if flags & 0x02 != 0 { if flags&0x02 != 0 {
if _, err = ReadUInt(lr, 2); err != nil { if _, err = ReadUInt(lr, 2); err != nil {
return return
} }
} }
// PES extension flag // PES extension flag
if flags & 0x01 != 0 { if flags&0x01 != 0 {
var flags uint var flags uint
// PES private data flag(1) // PES private data flag(1)
@ -634,7 +632,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
} }
// PES private data flag(1) // PES private data flag(1)
if flags & 0x80 != 0 { if flags&0x80 != 0 {
// if set to 1 16 bytes of user defined data is appended to the header data field // if set to 1 16 bytes of user defined data is appended to the header data field
if err = ReadDummy(lr, 16); err != nil { if err = ReadDummy(lr, 16); err != nil {
return return
@ -642,7 +640,7 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
} }
// pack header field flag(1) // pack header field flag(1)
if flags & 0x40 != 0 { if flags&0x40 != 0 {
// if set to 1 the 8-bit pack field length value is appended to the header data field // if set to 1 the 8-bit pack field length value is appended to the header data field
if err = ReadDummy(lr, 1); err != nil { if err = ReadDummy(lr, 1); err != nil {
return return
@ -650,21 +648,21 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
} }
// program packet sequence counter flag(1) // program packet sequence counter flag(1)
if flags & 0x20 != 0 { if flags&0x20 != 0 {
if err = ReadDummy(lr, 2); err != nil { if err = ReadDummy(lr, 2); err != nil {
return return
} }
} }
// P-STD buffer flag(1) // P-STD buffer flag(1)
if flags & 0x10 != 0 { if flags&0x10 != 0 {
if err = ReadDummy(lr, 2); err != nil { if err = ReadDummy(lr, 2); err != nil {
return return
} }
} }
// PES extension flag 2(1) // PES extension flag 2(1)
if flags & 0x01 != 0 { if flags&0x01 != 0 {
if err = ReadDummy(lr, 2); err != nil { if err = ReadDummy(lr, 2); err != nil {
return return
} }
@ -684,4 +682,3 @@ func ReadPESHeader(r io.Reader) (res *PESHeader, err error) {
res = self res = self
return return
} }

View File

@ -1,9 +1,8 @@
package ts package ts
import ( import (
"bytes" "bytes"
"github.com/nareix/mp4/isom" "github.com/nareix/codec/aacparser"
) )
type Track struct { type Track struct {
@ -12,28 +11,27 @@ type Track struct {
Type int Type int
pid uint pid uint
PTS int64 PTS int64
timeScale int64 timeScale int64
mpeg4AudioConfig isom.MPEG4AudioConfig mpeg4AudioConfig aacparser.MPEG4AudioConfig
buf bytes.Buffer buf bytes.Buffer
payload []byte payload []byte
peshdr *PESHeader peshdr *PESHeader
tshdr TSHeader tshdr TSHeader
spsHasWritten bool spsHasWritten bool
payloadReady bool payloadReady bool
demuxer *Demuxer demuxer *Demuxer
mux *Muxer mux *Muxer
streamId uint streamId uint
tsw *TSWriter tsw *TSWriter
dataBuf *iovec dataBuf *iovec
cacheSize int cacheSize int
} }
const ( const (
H264 = 1 H264 = 1
AAC = 2 AAC = 2
) )

66
ts.go
View File

@ -1,4 +1,3 @@
package ts package ts
import ( import (
@ -6,24 +5,24 @@ import (
) )
const ( const (
ElementaryStreamTypeH264 = 0x1B ElementaryStreamTypeH264 = 0x1B
ElementaryStreamTypeAdtsAAC = 0x0F ElementaryStreamTypeAdtsAAC = 0x0F
) )
type TSHeader struct { type TSHeader struct {
PID uint PID uint
PCR uint64 PCR uint64
OPCR uint64 OPCR uint64
ContinuityCounter uint ContinuityCounter uint
PayloadUnitStart bool PayloadUnitStart bool
DiscontinuityIndicator bool DiscontinuityIndicator bool
RandomAccessIndicator bool RandomAccessIndicator bool
HeaderLength uint HeaderLength uint
} }
type PATEntry struct { type PATEntry struct {
ProgramNumber uint ProgramNumber uint
NetworkPID uint NetworkPID uint
ProgramMapPID uint ProgramMapPID uint
} }
@ -32,45 +31,45 @@ type PAT struct {
} }
type PMT struct { type PMT struct {
PCRPID uint PCRPID uint
ProgramDescriptors []Descriptor ProgramDescriptors []Descriptor
ElementaryStreamInfos []ElementaryStreamInfo ElementaryStreamInfos []ElementaryStreamInfo
} }
type Descriptor struct { type Descriptor struct {
Tag uint Tag uint
Data []byte Data []byte
} }
type ElementaryStreamInfo struct { type ElementaryStreamInfo struct {
StreamType uint StreamType uint
ElementaryPID uint ElementaryPID uint
Descriptors []Descriptor Descriptors []Descriptor
} }
type PSI struct { type PSI struct {
TableIdExtension uint TableIdExtension uint
TableId uint TableId uint
SecNum uint SecNum uint
LastSecNum uint LastSecNum uint
} }
const ( const (
StreamIdH264 = 0xe0 StreamIdH264 = 0xe0
StreamIdAAC = 0xc0 StreamIdAAC = 0xc0
) )
type PESHeader struct { type PESHeader struct {
StreamId uint // H264=0xe0 AAC=0xc0 StreamId uint // H264=0xe0 AAC=0xc0
DataLength uint DataLength uint
PTS uint64 PTS uint64
DTS uint64 DTS uint64
ESCR uint64 ESCR uint64
} }
func PESUIntToTs(v uint64) (ts uint64) { func PESUIntToTs(v uint64) (ts uint64) {
// 0010 PTS 32..30 1 PTS 29..15 1 PTS 14..00 1 // 0010 PTS 32..30 1 PTS 29..15 1 PTS 14..00 1
return (((v>>33)&0x7)<<30) | (((v>>17)&0x7fff)<<15) | ((v>>1)&0x7fff) return (((v >> 33) & 0x7) << 30) | (((v >> 17) & 0x7fff) << 15) | ((v >> 1) & 0x7fff)
} }
func PESTsToUInt(ts uint64) (v uint64) { func PESTsToUInt(ts uint64) (v uint64) {
@ -85,23 +84,23 @@ const (
func UIntToPCR(v uint64) uint64 { func UIntToPCR(v uint64) uint64 {
// base(33)+resverd(6)+ext(9) // base(33)+resverd(6)+ext(9)
base := v>>15 base := v >> 15
ext := v&0x1ff ext := v & 0x1ff
return base*300+ext return base*300 + ext
} }
func PCRToUInt(pcr uint64) uint64 { func PCRToUInt(pcr uint64) uint64 {
base := pcr/300 base := pcr / 300
ext := pcr%300 ext := pcr % 300
return base<<15|0x3f<<9|ext return base<<15 | 0x3f<<9 | ext
} }
type FieldsDumper struct { type FieldsDumper struct {
Fields []struct { Fields []struct {
Length int Length int
Desc string Desc string
} }
Val uint Val uint
Length uint Length uint
} }
@ -109,11 +108,10 @@ func (self FieldsDumper) String() (res string) {
pos := uint(self.Length) pos := uint(self.Length)
for _, field := range self.Fields { for _, field := range self.Fields {
pos -= uint(field.Length) pos -= uint(field.Length)
val := (self.Val>>pos)&(1<<uint(field.Length)-1) val := (self.Val >> pos) & (1<<uint(field.Length) - 1)
if val != 0 { if val != 0 {
res += fmt.Sprintf("%s=%x ", field.Desc, val) res += fmt.Sprintf("%s=%x ", field.Desc, val)
} }
} }
return return
} }

View File

@ -1,4 +1,3 @@
package ts package ts
import ( import (
@ -8,4 +7,3 @@ import (
func TestPESTsConv(t *testing.T) { func TestPESTsConv(t *testing.T) {
t.Logf("%x", PESTsToUInt(0x123)) t.Logf("%x", PESTsToUInt(0x123))
} }

View File

@ -1,20 +1,19 @@
package ts package ts
import ( import (
"io"
"os"
"net"
"fmt" "fmt"
"unsafe" "io"
"net"
"os"
"syscall" "syscall"
"unsafe"
) )
type iovec struct { type iovec struct {
data [][]byte data [][]byte
Len int Len int
pos int pos int
idx int idx int
} }
func (self *iovec) Prepend(b []byte) { func (self *iovec) Prepend(b []byte) {
@ -57,13 +56,13 @@ func (self *iovec) WriteTo(w io.Writer, n int) (written int, err error) {
type sysiovec struct { type sysiovec struct {
Base uintptr Base uintptr
Len uint64 Len uint64
} }
type vecWriter struct { type vecWriter struct {
fd uintptr fd uintptr
smallBytesBuf []byte smallBytesBuf []byte
iov []sysiovec iov []sysiovec
} }
func (self *vecWriter) Write(p []byte) (written int, err error) { func (self *vecWriter) Write(p []byte) (written int, err error) {
@ -134,4 +133,3 @@ func newVecWriter(w io.Writer) (vecw *vecWriter) {
} }
return return
} }

View File

@ -1,17 +1,16 @@
package ts package ts
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"bytes"
) )
var DebugWriter = false var DebugWriter = false
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
for i := n-1; i >= 0; i-- { for i := n - 1; i >= 0; i-- {
b[i] = byte(val) b[i] = byte(val)
val >>= 8 val >>= 8
} }
@ -51,13 +50,13 @@ func WriteTSHeader(w io.Writer, self TSHeader, dataLength int) (written int, err
// Payload flag(1) 0x10 // Payload flag(1) 0x10
// Continuity counter(4) // Continuity counter(4)
flags = 0x47<<24 flags = 0x47 << 24
flags |= 0x10 flags |= 0x10
if self.PayloadUnitStart { if self.PayloadUnitStart {
flags |= 0x400000 flags |= 0x400000
} }
flags |= (self.PID&0x1fff)<<8 flags |= (self.PID & 0x1fff) << 8
flags |= self.ContinuityCounter&0xf flags |= self.ContinuityCounter & 0xf
if DebugWriter { if DebugWriter {
fmt.Printf("tsw: pid=%x\n", self.PID) fmt.Printf("tsw: pid=%x\n", self.PID)
@ -94,26 +93,26 @@ func WriteTSHeader(w io.Writer, self TSHeader, dataLength int) (written int, err
} }
written += 4 written += 4
if flags & EXT != 0 { if flags&EXT != 0 {
var length uint var length uint
// Discontinuity indicator 1 0x80 // Discontinuity indicator 1 0x80
// Random Access indicator 1 0x40 // Random Access indicator 1 0x40
// Elementary stream priority indicator 1 0x20 // Elementary stream priority indicator 1 0x20
// PCR flag 1 0x10 // PCR flag 1 0x10
// OPCR flag 1 0x08 // OPCR flag 1 0x08
length = 1 // extFlags length = 1 // extFlags
if extFlags & PCR != 0 { if extFlags&PCR != 0 {
length += 6 length += 6
} }
if extFlags & OPCR != 0 { if extFlags&OPCR != 0 {
length += 6 length += 6
} }
paddingLength := 0 paddingLength := 0
// need padding // need padding
if int(length) + 5 + dataLength < 188 { if int(length)+5+dataLength < 188 {
paddingLength = 188 - dataLength - 5 - int(length) paddingLength = 188 - dataLength - 5 - int(length)
length = 188 - uint(dataLength) - 5 length = 188 - uint(dataLength) - 5
} }
@ -129,13 +128,13 @@ func WriteTSHeader(w io.Writer, self TSHeader, dataLength int) (written int, err
return return
} }
if extFlags & PCR != 0 { if extFlags&PCR != 0 {
if err = WriteUInt64(w, PCRToUInt(self.PCR), 6); err != nil { if err = WriteUInt64(w, PCRToUInt(self.PCR), 6); err != nil {
return return
} }
} }
if extFlags & OPCR != 0 { if extFlags&OPCR != 0 {
if err = WriteUInt64(w, PCRToUInt(self.OPCR), 6); err != nil { if err = WriteUInt64(w, PCRToUInt(self.OPCR), 6); err != nil {
return return
} }
@ -147,17 +146,17 @@ func WriteTSHeader(w io.Writer, self TSHeader, dataLength int) (written int, err
} }
} }
written += int(length)+1 written += int(length) + 1
} }
return return
} }
type TSWriter struct { type TSWriter struct {
W io.Writer W io.Writer
PID uint PID uint
TSHeader TSHeader
DisableHeaderPadding bool DisableHeaderPadding bool
DiscontinuityIndicator bool DiscontinuityIndicator bool
vecw *vecWriter vecw *vecWriter
@ -192,8 +191,8 @@ func (self *TSWriter) WriteIovec(data *iovec) (err error) {
func (self *TSWriter) WriteIovecTo(w io.Writer, data *iovec) (err error) { func (self *TSWriter) WriteIovecTo(w io.Writer, data *iovec) (err error) {
for i := 0; data.Len > 0; i++ { for i := 0; data.Len > 0; i++ {
header := TSHeader{ header := TSHeader{
PID: self.PID, PID: self.PID,
ContinuityCounter: self.ContinuityCounter, ContinuityCounter: self.ContinuityCounter,
DiscontinuityIndicator: self.DiscontinuityIndicator, DiscontinuityIndicator: self.DiscontinuityIndicator,
} }
@ -214,7 +213,7 @@ func (self *TSWriter) WriteIovecTo(w io.Writer, data *iovec) (err error) {
} }
payloadLength := 188 - headerLength payloadLength := 188 - headerLength
if self.DisableHeaderPadding && data.Len < payloadLength { if self.DisableHeaderPadding && data.Len < payloadLength {
data.Append(makeRepeatValBytes(0xff, payloadLength - data.Len)) data.Append(makeRepeatValBytes(0xff, payloadLength-data.Len))
} }
if DebugWriter { if DebugWriter {
@ -267,8 +266,8 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
// section_syntax_indicator(1)=1,private_bit(1)=0,reserved(2)=3,unused(2)=0,section_length(10) // section_syntax_indicator(1)=1,private_bit(1)=0,reserved(2)=3,unused(2)=0,section_length(10)
var flags, length uint var flags, length uint
length = 2+3+4+uint(len(data)) length = 2 + 3 + 4 + uint(len(data))
flags = 0xa<<12|length flags = 0xa<<12 | length
if err = WriteUInt(cw, flags, 2); err != nil { if err = WriteUInt(cw, flags, 2); err != nil {
return return
} }
@ -283,7 +282,7 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
} }
// resverd(2)=3,version(5)=0,Current_next_indicator(1)=1 // resverd(2)=3,version(5)=0,Current_next_indicator(1)=1
flags = 0x3<<6|1 flags = 0x3<<6 | 1
if err = WriteUInt(cw, flags, 1); err != nil { if err = WriteUInt(cw, flags, 1); err != nil {
return return
} }
@ -312,7 +311,7 @@ func WritePSI(w io.Writer, self PSI, data []byte) (err error) {
} }
func bswap32(v uint) uint { func bswap32(v uint) uint {
return (v>>24)|((v>>16)&0xff)<<8|((v>>8)&0xff)<<16|(v&0xff)<<24 return (v >> 24) | ((v>>16)&0xff)<<8 | ((v>>8)&0xff)<<16 | (v&0xff)<<24
} }
func WritePESHeader(w io.Writer, self PESHeader, dataLength int) (err error) { func WritePESHeader(w io.Writer, self PESHeader, dataLength int) (err error) {
@ -340,8 +339,8 @@ func WritePESHeader(w io.Writer, self PESHeader, dataLength int) (err error) {
return return
} }
const PTS = 1<<7 const PTS = 1 << 7
const DTS = 1<<6 const DTS = 1 << 6
if self.PTS != 0 { if self.PTS != 0 {
pts_dts_flags |= PTS pts_dts_flags |= PTS
@ -350,10 +349,10 @@ func WritePESHeader(w io.Writer, self PESHeader, dataLength int) (err error) {
} }
} }
if pts_dts_flags & PTS != 0 { if pts_dts_flags&PTS != 0 {
header_length += 5 header_length += 5
} }
if pts_dts_flags & DTS != 0 { if pts_dts_flags&DTS != 0 {
header_length += 5 header_length += 5
} }
@ -361,8 +360,8 @@ func WritePESHeader(w io.Writer, self PESHeader, dataLength int) (err error) {
packet_length = uint(dataLength) + header_length + 3 packet_length = uint(dataLength) + header_length + 3
} }
// packet_length(16) if zero then variable length // packet_length(16) if zero then variable length
// Specifies the number of bytes remaining in the packet after this field. Can be zero. // Specifies the number of bytes remaining in the packet after this field. Can be zero.
// If the PES packet length is set to zero, the PES packet can be of any length. // If the PES packet length is set to zero, the PES packet can be of any length.
// A value of zero for the PES packet length can be used only when the PES packet payload is a video elementary stream. // A value of zero for the PES packet length can be used only when the PES packet payload is a video elementary stream.
if err = WriteUInt(w, packet_length, 2); err != nil { if err = WriteUInt(w, packet_length, 2); err != nil {
return return
@ -385,8 +384,8 @@ func WritePESHeader(w io.Writer, self PESHeader, dataLength int) (err error) {
// pts(40)? // pts(40)?
// dts(40)? // dts(40)?
if pts_dts_flags & PTS != 0 { if pts_dts_flags&PTS != 0 {
if pts_dts_flags & DTS != 0 { if pts_dts_flags&DTS != 0 {
if err = WriteUInt64(w, PESTsToUInt(self.PTS)|3<<36, 5); err != nil { if err = WriteUInt64(w, PESTsToUInt(self.PTS)|3<<36, 5); err != nil {
return return
} }
@ -447,8 +446,8 @@ func WritePAT(w io.Writer, self PAT) (err error) {
func WritePATPacket(w io.Writer, pat PAT) (err error) { func WritePATPacket(w io.Writer, pat PAT) (err error) {
tsw := &TSWriter{ tsw := &TSWriter{
W: w, W: w,
PID: 0, PID: 0,
DisableHeaderPadding: true, DisableHeaderPadding: true,
} }
bw := &bytes.Buffer{} bw := &bytes.Buffer{}
@ -529,8 +528,8 @@ func WritePMT(w io.Writer, self PMT) (err error) {
return return
} }
psi := PSI { psi := PSI{
TableId: 2, TableId: 2,
TableIdExtension: 1, TableIdExtension: 1,
} }
if err = WritePSI(w, psi, bw.Bytes()); err != nil { if err = WritePSI(w, psi, bw.Bytes()); err != nil {
@ -542,8 +541,8 @@ func WritePMT(w io.Writer, self PMT) (err error) {
func WritePMTPacket(w io.Writer, pmt PMT, pid uint) (err error) { func WritePMTPacket(w io.Writer, pmt PMT, pid uint) (err error) {
tsw := &TSWriter{ tsw := &TSWriter{
W: w, W: w,
PID: pid, PID: pid,
DisableHeaderPadding: true, DisableHeaderPadding: true,
} }
bw := &bytes.Buffer{} bw := &bytes.Buffer{}
@ -557,14 +556,14 @@ func WritePMTPacket(w io.Writer, pmt PMT, pid uint) (err error) {
} }
type SimpleH264Writer struct { type SimpleH264Writer struct {
W io.Writer W io.Writer
TimeScale int TimeScale int
SPS []byte SPS []byte
PPS []byte PPS []byte
tswPAT *TSWriter tswPAT *TSWriter
tswPMT *TSWriter tswPMT *TSWriter
tswH264 *TSWriter tswH264 *TSWriter
PTS int64 PTS int64
@ -668,7 +667,7 @@ func (self *SimpleH264Writer) WriteNALU(sync bool, duration int, nalu []byte) (e
pes := PESHeader{ pes := PESHeader{
StreamId: StreamIdH264, StreamId: StreamIdH264,
PTS: uint64(self.PTS)*PTS_HZ/uint64(self.TimeScale), PTS: uint64(self.PTS) * PTS_HZ / uint64(self.TimeScale),
} }
if err = WritePESHeader(self.pesBuf, pes, 0); err != nil { if err = WritePESHeader(self.pesBuf, pes, 0); err != nil {
return return
@ -679,16 +678,16 @@ func (self *SimpleH264Writer) WriteNALU(sync bool, duration int, nalu []byte) (e
for i, nalu := range nalus { for i, nalu := range nalus {
var startCode []byte var startCode []byte
if i == 0 { if i == 0 {
startCode = []byte{0,0,0,1,0x9,0xf0,0,0,0,1} // AUD startCode = []byte{0, 0, 0, 1, 0x9, 0xf0, 0, 0, 0, 1} // AUD
} else { } else {
startCode = []byte{0,0,1} startCode = []byte{0, 0, 1}
} }
data.Append(startCode) data.Append(startCode)
data.Append(nalu) data.Append(nalu)
} }
self.tswH264.RandomAccessIndicator = sync self.tswH264.RandomAccessIndicator = sync
self.tswH264.PCR = uint64(self.PCR)*PCR_HZ/uint64(self.TimeScale) self.tswH264.PCR = uint64(self.PCR) * PCR_HZ / uint64(self.TimeScale)
self.tswH264.W = self.W self.tswH264.W = self.W
if err = self.tswH264.WriteIovec(data); err != nil { if err = self.tswH264.WriteIovec(data); err != nil {
@ -701,4 +700,3 @@ func (self *SimpleH264Writer) WriteNALU(sync bool, duration int, nalu []byte) (e
return return
} }

View File

@ -1,19 +1,17 @@
package ts package ts
import ( import (
"testing"
"encoding/hex"
"bytes" "bytes"
"encoding/hex"
"testing"
) )
func TestWriteTSHeader(t *testing.T) { func TestWriteTSHeader(t *testing.T) {
bw := &bytes.Buffer{} bw := &bytes.Buffer{}
w := &TSWriter{ w := &TSWriter{
W: bw, W: bw,
PCR: 0x12345678, PCR: 0x12345678,
} }
w.Write([]byte{'h','e','l','o'}[:], false) w.Write([]byte{'h', 'e', 'l', 'o'}[:], false)
t.Logf("\n%s", hex.Dump(bw.Bytes())) t.Logf("\n%s", hex.Dump(bw.Bytes()))
} }