diff --git a/demuxer.go b/demuxer.go index 3304bd2..8909547 100644 --- a/demuxer.go +++ b/demuxer.go @@ -6,9 +6,20 @@ import ( "github.com/nareix/av" "github.com/nareix/mp4/atom" "github.com/nareix/mp4/isom" + "github.com/nareix/codec/aacparser" + "github.com/nareix/codec/h264parser" "io" ) +func Open(R io.ReadSeeker) (demuxer *Demuxer, err error) { + _demuxer := &Demuxer{R: R} + if err = _demuxer.ReadHeader(); err != nil { + return + } + demuxer = _demuxer + return +} + type Demuxer struct { R io.ReadSeeker @@ -16,7 +27,7 @@ type Demuxer struct { movieAtom *atom.Movie } -func (self *Demuxer) Streams() (streams []av.Stream) { +func (self *Demuxer) Streams() (streams []av.CodecData) { for _, stream := range self.streams { streams = append(streams, stream) } @@ -76,19 +87,17 @@ func (self *Demuxer) ReadHeader() (err error) { } if avc1 := atom.GetAvc1ConfByTrack(atrack); avc1 != nil { - stream.SetType(av.H264) - if err = stream.SetCodecData(avc1.Data); err != nil { + if stream.CodecData, err = h264parser.NewCodecDataFromAVCDecoderConfRecord(avc1.Data); err != nil { return } self.streams = append(self.streams, stream) } else if mp4a := atom.GetMp4aDescByTrack(atrack); mp4a != nil && mp4a.Conf != nil { - stream.SetType(av.AAC) var config []byte if config, err = isom.ReadElemStreamDesc(bytes.NewReader(mp4a.Conf.Data)); err != nil { return } - if err = stream.SetCodecData(config); err != nil { + if stream.CodecData, err = aacparser.NewCodecDataFromMPEG4AudioConfigBytes(config); err != nil { return } self.streams = append(self.streams, stream) @@ -295,17 +304,17 @@ func (self *Stream) sampleCount() int { } func (self *Demuxer) ReadPacket() (streamIndex int, pkt av.Packet, err error) { - var choose *Stream + var chosen *Stream for i, stream := range self.streams { - if choose == nil || stream.tsToTime(stream.dts) < choose.tsToTime(choose.dts) { - choose = stream + if chosen == nil || stream.tsToTime(stream.dts) < chosen.tsToTime(chosen.dts) { + chosen = stream streamIndex = i } } if false { - fmt.Printf("ReadPacket: choose index=%v time=%v\n", choose.idx, choose.tsToTime(choose.dts)) + fmt.Printf("ReadPacket: chosen index=%v time=%v\n", chosen.idx, chosen.tsToTime(chosen.dts)) } - pkt, err = choose.readPacket() + pkt, err = chosen.readPacket() return } diff --git a/muxer.go b/muxer.go index 82a55a9..058f422 100644 --- a/muxer.go +++ b/muxer.go @@ -11,14 +11,23 @@ import ( "io" ) +func Create(W io.WriteSeeker, streams []av.CodecData) (muxer *Muxer, err error) { + _muxer := &Muxer{W: W} + if err = _muxer.WriteHeader(streams); err != nil { + return + } + muxer = _muxer + return +} + type Muxer struct { W io.WriteSeeker streams []*Stream mdatWriter *atom.Writer } -func (self *Muxer) NewStream() av.Stream { - stream := &Stream{} +func (self *Muxer) NewStream(codec av.CodecData) (err error) { + stream := &Stream{CodecData: codec} stream.sample = &atom.SampleTable{ SampleDesc: &atom.SampleDesc{}, @@ -66,7 +75,7 @@ func (self *Muxer) NewStream() av.Stream { stream.muxer = self self.streams = append(self.streams, stream) - return stream + return } func (self *Stream) fillTrackAtom() (err error) { @@ -74,7 +83,8 @@ func (self *Stream) fillTrackAtom() (err error) { self.trackAtom.Media.Header.Duration = int(self.duration) if self.Type() == av.H264 { - width, height := self.Width(), self.Height() + codec := self.CodecData.(av.H264CodecData) + width, height := codec.Width(), codec.Height() self.sample.SampleDesc.Avc1Desc = &atom.Avc1Desc{ DataRefIdx: 1, HorizontalResolution: 72, @@ -84,7 +94,7 @@ func (self *Stream) fillTrackAtom() (err error) { FrameCount: 1, Depth: 24, ColorTableId: -1, - Conf: &atom.Avc1Conf{Data: self.CodecData()}, + Conf: &atom.Avc1Conf{Data: codec.AVCDecoderConfRecordBytes()}, } self.sample.SyncSample = &atom.SyncSample{} self.trackAtom.Media.Handler = &atom.HandlerRefer{ @@ -98,15 +108,16 @@ func (self *Stream) fillTrackAtom() (err error) { self.trackAtom.Header.TrackHeight = atom.IntToFixed(int(height)) } else if self.Type() == av.AAC { + codec := self.CodecData.(av.AACCodecData) buf := &bytes.Buffer{} - if err = isom.WriteElemStreamDesc(buf, self.CodecData(), uint(self.trackAtom.Header.TrackId)); err != nil { + if err = isom.WriteElemStreamDesc(buf, codec.MPEG4AudioConfigBytes(), uint(self.trackAtom.Header.TrackId)); err != nil { return } self.sample.SampleDesc.Mp4aDesc = &atom.Mp4aDesc{ DataRefIdx: 1, - NumberOfChannels: self.ChannelCount(), - SampleSize: self.ChannelCount() * 8, - SampleRate: atom.IntToFixed(self.SampleRate()), + NumberOfChannels: codec.ChannelCount(), + SampleSize: codec.ChannelCount() * 8, + SampleRate: atom.IntToFixed(codec.SampleRate()), Conf: &atom.ElemStreamDesc{ Data: buf.Bytes(), }, @@ -126,12 +137,18 @@ func (self *Stream) fillTrackAtom() (err error) { return } -func (self *Muxer) WriteHeader() (err error) { +func (self *Muxer) WriteHeader(streams []av.CodecData) (err error) { + for _, stream := range streams { + if err = self.NewStream(stream); err != nil { + return + } + } + if self.mdatWriter, err = atom.WriteAtomHeader(self.W, "mdat"); err != nil { return } for _, stream := range self.streams { - if stream.Type().IsVideo() { + if stream.IsVideo() { stream.sample.CompositionOffset = &atom.CompositionOffset{} } } @@ -143,7 +160,7 @@ func (self *Muxer) WritePacket(streamIndex int, pkt av.Packet) (err error) { frame := pkt.Data if stream.Type() == av.AAC && aacparser.IsADTSFrame(frame) { - sampleRate := stream.SampleRate() + sampleRate := stream.CodecData.(av.AudioCodecData).SampleRate() for len(frame) > 0 { var payload []byte var samples int diff --git a/stream.go b/stream.go index 550b398..2e6cdf2 100644 --- a/stream.go +++ b/stream.go @@ -7,7 +7,7 @@ import ( ) type Stream struct { - av.StreamCommon + av.CodecData trackAtom *atom.Track r io.ReadSeeker