From 031feda56586fb968d261c7d9726442c65f69955 Mon Sep 17 00:00:00 2001 From: Saxon Date: Sat, 28 Mar 2020 00:43:35 +1030 Subject: [PATCH] codec/h265: Lexer -> Extractor --- codec/h265/{lex.go => extract.go} | 85 +++++++++++---------- codec/h265/{lex_test.go => extract_test.go} | 15 ++-- 2 files changed, 51 insertions(+), 49 deletions(-) rename codec/h265/{lex.go => extract.go} (66%) rename codec/h265/{lex_test.go => extract_test.go} (95%) diff --git a/codec/h265/lex.go b/codec/h265/extract.go similarity index 66% rename from codec/h265/lex.go rename to codec/h265/extract.go index 2fb41a9d..fca50ebc 100644 --- a/codec/h265/lex.go +++ b/codec/h265/extract.go @@ -1,9 +1,10 @@ /* NAME - lex.go + extract.go DESCRIPTION - lex.go provides a lexer for taking RTP HEVC (H265) and lexing into access units. + extract.go provides a extractor for taking RTP HEVC (H265) and extracting + access units. AUTHORS Saxon A. Nelson-Milton @@ -25,7 +26,7 @@ LICENSE in gpl.txt. If not, see http://www.gnu.org/licenses. */ -// Package h265 provides an RTP h265 lexer that can extract h265 access units +// Package h265 provides an RTP h265 extractor that can extract h265 access units // from an RTP stream. package h265 @@ -52,25 +53,25 @@ const ( maxRTPSize = 4096 ) -// Lexer is an H265 lexer. -type Lexer struct { +// Extractor is an RTP HEVC access unit extractor. +type Extractor struct { donl bool // Indicates whether DONL and DOND will be used for the RTP stream. buf *bytes.Buffer // Holds the current access unit. frag bool // Indicates if we're currently dealing with a fragmentation packet. } -// NewLexer returns a new Lexer. -func NewLexer(donl bool) *Lexer { - return &Lexer{ +// NewExtractor returns a new Extractor. +func NewExtractor(donl bool) *Extractor { + return &Extractor{ donl: donl, buf: bytes.NewBuffer(make([]byte, 0, maxAUSize)), } } -// Lex continually reads RTP packets from the io.Reader src and lexes into -// access units which are written to the io.Writer dst. Lex expects that for -// each read from src, a single RTP packet is received. -func (l *Lexer) Lex(dst io.Writer, src io.Reader, delay time.Duration) error { +// Extract continually reads RTP packets from the io.Reader src and extracts +// H.265 access units which are written to the io.Writer dst. Extract expects +// that for each read from src, a single RTP packet is received. +func (e *Extractor) Extract(dst io.Writer, src io.Reader, delay time.Duration) error { buf := make([]byte, maxRTPSize) for { n, err := src.Read(buf) @@ -78,7 +79,7 @@ func (l *Lexer) Lex(dst io.Writer, src io.Reader, delay time.Duration) error { case nil: // Do nothing. default: if err == io.EOF { - if l.buf.Len() == 0 { + if e.buf.Len() == 0 { return io.EOF } return io.ErrUnexpectedEOF @@ -94,21 +95,21 @@ func (l *Lexer) Lex(dst io.Writer, src io.Reader, delay time.Duration) error { nalType := (payload[0] >> 1) & 0x3f // If not currently fragmented then we ignore current write. - if l.frag && nalType != typeFragmentation { - l.buf.Reset() - l.frag = false + if e.frag && nalType != typeFragmentation { + e.buf.Reset() + e.frag = false continue } switch nalType { case typeAggregation: - l.handleAggregation(payload) + e.handleAggregation(payload) case typeFragmentation: - l.handleFragmentation(payload) + e.handleFragmentation(payload) case typePACI: - l.handlePACI(payload) + e.handlePACI(payload) default: - l.writeWithPrefix(payload) + e.writeWithPrefix(payload) } markerIsSet, err := rtp.Marker(buf[:n]) @@ -117,22 +118,22 @@ func (l *Lexer) Lex(dst io.Writer, src io.Reader, delay time.Duration) error { } if markerIsSet { - _, err := l.buf.WriteTo(dst) + _, err := e.buf.WriteTo(dst) if err != nil { // TODO: work out what to do here. } - l.buf.Reset() + e.buf.Reset() } } return nil } // handleAggregation parses NAL units from an aggregation packet and writes -// them to the Lexers buffer buf. -func (l *Lexer) handleAggregation(d []byte) { +// them to the Extractor's buffer buf. +func (e *Extractor) handleAggregation(d []byte) { idx := 2 for idx < len(d) { - if l.donl { + if e.donl { switch idx { case 2: idx += 2 @@ -144,13 +145,13 @@ func (l *Lexer) handleAggregation(d []byte) { idx += 2 nalu := d[idx : idx+size] idx += size - l.writeWithPrefix(nalu) + e.writeWithPrefix(nalu) } } // handleFragmentation parses NAL units from fragmentation packets and writes -// them to the Lexer's buf. -func (l *Lexer) handleFragmentation(d []byte) { +// them to the Extractor's buf. +func (e *Extractor) handleFragmentation(d []byte) { // Get start and end indiciators from FU header. start := d[2]&0x80 != 0 end := d[2]&0x40 != 0 @@ -159,27 +160,27 @@ func (l *Lexer) handleFragmentation(d []byte) { b2 := d[1] if start { d = d[1:] - if l.donl { + if e.donl { d = d[2:] } d[0] = b1 d[1] = b2 } else { d = d[3:] - if l.donl { + if e.donl { d = d[2:] } } switch { case start && !end: - l.frag = true - l.writeWithPrefix(d) + e.frag = true + e.writeWithPrefix(d) case !start && end: - l.frag = false + e.frag = false fallthrough case !start && !end: - l.writeNoPrefix(d) + e.writeNoPrefix(d) default: panic("bad fragmentation packet") } @@ -188,20 +189,20 @@ func (l *Lexer) handleFragmentation(d []byte) { // handlePACI will handle PACI packets // // TODO: complete this -func (l *Lexer) handlePACI(d []byte) { +func (e *Extractor) handlePACI(d []byte) { panic("unsupported nal type") } -// write writes a NAL unit to the Lexer's buf in byte stream format using the +// write writes a NAL unit to the Extractor's buf in byte stream format using the // start code. -func (l *Lexer) writeWithPrefix(d []byte) { +func (e *Extractor) writeWithPrefix(d []byte) { const prefix = "\x00\x00\x00\x01" - l.buf.Write([]byte(prefix)) - l.buf.Write(d) + e.buf.Write([]byte(prefix)) + e.buf.Write(d) } -// writeNoPrefix writes data to the Lexer's buf. This is used for non start +// writeNoPrefix writes data to the Extractor's buf. This is used for non start // fragmentations of a NALU. -func (l *Lexer) writeNoPrefix(d []byte) { - l.buf.Write(d) +func (e *Extractor) writeNoPrefix(d []byte) { + e.buf.Write(d) } diff --git a/codec/h265/lex_test.go b/codec/h265/extract_test.go similarity index 95% rename from codec/h265/lex_test.go rename to codec/h265/extract_test.go index 9f725bb9..68f91a3d 100644 --- a/codec/h265/lex_test.go +++ b/codec/h265/extract_test.go @@ -1,9 +1,10 @@ /* NAME - lex_test.go + extract_test.go DESCRIPTION - lex_test.go provides tests to check validity of the Lexer found in lex.go. + extract_test.go provides tests to check validity of the Extractor found in + extract.go. AUTHORS Saxon A. Nelson-Milton @@ -19,7 +20,7 @@ LICENSE It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. + for more details. You should have received a copy of the GNU General Public License in gpl.txt. If not, see http://www.gnu.org/licenses. @@ -53,7 +54,7 @@ func (r *rtpReader) Read(p []byte) (int, error) { return n, nil } -// destination holds the access units extracted during the lexing process. +// destination holds the access units extracted during the extraction process. type destination [][]byte // Write implements io.Writer. @@ -64,7 +65,7 @@ func (d *destination) Write(p []byte) (int, error) { return len(p), nil } -// TestLex checks that the Lexer can correctly extract H265 access units from +// TestLex checks that the Extractor can correctly extract H265 access units from // HEVC RTP stream in RTP payload format. func TestLex(t *testing.T) { const rtpVer = 2 @@ -246,11 +247,11 @@ func TestLex(t *testing.T) { for testNum, test := range tests { r := &rtpReader{packets: test.packets} d := &destination{} - err := NewLexer(test.donl).Lex(d, r, 0) + err := NewExtractor(test.donl).Extract(d, r, 0) switch err { case nil, io.EOF: // Do nothing default: - t.Fatalf("error lexing: %v\n", err) + t.Fatalf("error extracting: %v\n", err) } for i, accessUnit := range test.expect {