Skip to content

Commit

Permalink
Add ResetReader func to IVFReader
Browse files Browse the repository at this point in the history
Add ResetReader function for resetting the underlying file
in IVFReader. This is for keeping the stream alive if the file
is being encoded at the same time as it's being streamed.
It takes in a function that returns an io.Reader. A sample
function might look like:
func(bytesRead int64) io.Reader {
	underlyingFile.Seek(bytesRead, io.SeekStart)
	return underlyingFile
}
and you would call it when ivf.ParseNextFrame(...) returns
an error indicating incomplete data.
  • Loading branch information
Clayton McCray authored and Sean-Der committed Feb 17, 2020
1 parent e7e1cf5 commit 09a6722
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ Check out the **[contributing wiki](https://github.com/pion/webrtc/wiki/Contribu
* [Bao Nguyen](https://github.com/sysbot)
* [Luke S](https://github.com/encounter)
* [Hendrik Hofstadt](https://github.com/hendrikhofstadt)
* [Clayton McCray](https://github.com/ClaytonMcCray)

### License
MIT License - see [LICENSE](LICENSE) for full text
14 changes: 13 additions & 1 deletion pkg/media/ivfreader/ivfreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ type IVFFrameHeader struct {

// IVFReader is used to read IVF files and return frame payloads
type IVFReader struct {
stream io.Reader
stream io.Reader
bytesReadSuccesfully int64
}

// NewWith returns a new IVF reader and IVF file header
Expand All @@ -59,6 +60,13 @@ func NewWith(in io.Reader) (*IVFReader, *IVFFileHeader, error) {
return reader, header, nil
}

// ResetReader resets the internal stream of IVFReader. This is useful
// for live streams, where the end of the file might be read without the
// data being finished.
func (i *IVFReader) ResetReader(reset func(bytesRead int64) io.Reader) {
i.stream = reset(i.bytesReadSuccesfully)
}

// ParseNextFrame reads from stream and returns IVF frame payload, header,
// and an error if there is incomplete frame data.
// Returns all nil values when no more frames are available.
Expand All @@ -67,6 +75,7 @@ func (i *IVFReader) ParseNextFrame() ([]byte, *IVFFrameHeader, error) {
var header *IVFFrameHeader

bytesRead, err := i.stream.Read(buffer)
headerBytesRead := bytesRead
if err != nil {
return nil, nil, err
} else if bytesRead != ivfFrameHeaderSize {
Expand All @@ -87,6 +96,8 @@ func (i *IVFReader) ParseNextFrame() ([]byte, *IVFFrameHeader, error) {
} else if bytesRead != int(header.FrameSize) {
return nil, nil, fmt.Errorf("incomplete frame data")
}

i.bytesReadSuccesfully += int64(headerBytesRead) + int64(bytesRead)
return payload, header, nil
}

Expand Down Expand Up @@ -123,5 +134,6 @@ func (i *IVFReader) parseFileHeader() (*IVFFileHeader, error) {
return nil, fmt.Errorf(errStr)
}

i.bytesReadSuccesfully += int64(bytesRead)
return header, nil
}
3 changes: 3 additions & 0 deletions pkg/media/ivfreader/ivfreader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ func TestIVFReader_ParseValidFrames(t *testing.T) {
0xDE, 0xAD, 0xBE, 0xEF,
},
"Payload value should be 0xDEADBEEF")
assert.Equal(int64(ivfFrameHeaderSize+ivfFileHeaderSize+header.FrameSize), reader.bytesReadSuccesfully)
previousBytesRead := reader.bytesReadSuccesfully

// Parse Frame #2
payload, header, err = reader.ParseNextFrame()
Expand All @@ -103,6 +105,7 @@ func TestIVFReader_ParseValidFrames(t *testing.T) {
0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,
},
"Payload value should be 0xDEADBEEFDEADBEEF")
assert.Equal(int64(ivfFrameHeaderSize+header.FrameSize)+previousBytesRead, reader.bytesReadSuccesfully)
}

func TestIVFReader_ParseIncompleteFrameHeader(t *testing.T) {
Expand Down

0 comments on commit 09a6722

Please sign in to comment.