-
-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from mafintosh/es-class
Drop inherits, buffer-alloc dependencies
- Loading branch information
Showing
4 changed files
with
248 additions
and
259 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,191 +1,183 @@ | ||
var stream = require('readable-stream') | ||
var inherits = require('inherits') | ||
var nextEvent = require('next-event') | ||
var Box = require('mp4-box-encoding') | ||
var bufferAlloc = require('buffer-alloc') | ||
|
||
var EMPTY = bufferAlloc(0) | ||
var EMPTY = Buffer.alloc(0) | ||
|
||
module.exports = Decoder | ||
class Decoder extends stream.Writable { | ||
constructor (opts) { | ||
super(opts) | ||
|
||
function Decoder () { | ||
if (!(this instanceof Decoder)) return new Decoder() | ||
stream.Writable.call(this) | ||
this.destroyed = false | ||
|
||
this.destroyed = false | ||
this._pending = 0 | ||
this._missing = 0 | ||
this._ignoreEmpty = false | ||
this._buf = null | ||
this._str = null | ||
this._cb = null | ||
this._ondrain = null | ||
this._writeBuffer = null | ||
this._writeCb = null | ||
|
||
this._pending = 0 | ||
this._missing = 0 | ||
this._ignoreEmpty = false | ||
this._buf = null | ||
this._str = null | ||
this._cb = null | ||
this._ondrain = null | ||
this._writeBuffer = null | ||
this._writeCb = null | ||
this._ondrain = null | ||
this._kick() | ||
} | ||
|
||
this._ondrain = null | ||
this._kick() | ||
} | ||
destroy (err) { | ||
if (this.destroyed) return | ||
this.destroyed = true | ||
if (err) this.emit('error', err) | ||
this.emit('close') | ||
} | ||
|
||
inherits(Decoder, stream.Writable) | ||
_write (data, enc, next) { | ||
if (this.destroyed) return | ||
var drained = !this._str || !this._str._writableState.needDrain | ||
|
||
Decoder.prototype.destroy = function (err) { | ||
if (this.destroyed) return | ||
this.destroyed = true | ||
if (err) this.emit('error', err) | ||
this.emit('close') | ||
} | ||
while (data.length && !this.destroyed) { | ||
if (!this._missing && !this._ignoreEmpty) { | ||
this._writeBuffer = data | ||
this._writeCb = next | ||
return | ||
} | ||
|
||
Decoder.prototype._write = function (data, enc, next) { | ||
if (this.destroyed) return | ||
var drained = !this._str || !this._str._writableState.needDrain | ||
var consumed = data.length < this._missing ? data.length : this._missing | ||
if (this._buf) data.copy(this._buf, this._buf.length - this._missing) | ||
else if (this._str) drained = this._str.write(consumed === data.length ? data : data.slice(0, consumed)) | ||
|
||
while (data.length && !this.destroyed) { | ||
if (!this._missing && !this._ignoreEmpty) { | ||
this._writeBuffer = data | ||
this._writeCb = next | ||
return | ||
} | ||
this._missing -= consumed | ||
|
||
var consumed = data.length < this._missing ? data.length : this._missing | ||
if (this._buf) data.copy(this._buf, this._buf.length - this._missing) | ||
else if (this._str) drained = this._str.write(consumed === data.length ? data : data.slice(0, consumed)) | ||
if (!this._missing) { | ||
var buf = this._buf | ||
var cb = this._cb | ||
var stream = this._str | ||
|
||
this._missing -= consumed | ||
this._buf = this._cb = this._str = this._ondrain = null | ||
drained = true | ||
|
||
if (!this._missing) { | ||
var buf = this._buf | ||
var cb = this._cb | ||
var stream = this._str | ||
this._ignoreEmpty = false | ||
if (stream) stream.end() | ||
if (cb) cb(buf) | ||
} | ||
|
||
this._buf = this._cb = this._str = this._ondrain = null | ||
drained = true | ||
data = consumed === data.length ? EMPTY : data.slice(consumed) | ||
} | ||
|
||
this._ignoreEmpty = false | ||
if (stream) stream.end() | ||
if (cb) cb(buf) | ||
if (this._pending && !this._missing) { | ||
this._writeBuffer = data | ||
this._writeCb = next | ||
return | ||
} | ||
|
||
data = consumed === data.length ? EMPTY : data.slice(consumed) | ||
if (drained) next() | ||
else this._ondrain(next) | ||
} | ||
|
||
if (this._pending && !this._missing) { | ||
this._writeBuffer = data | ||
this._writeCb = next | ||
return | ||
_buffer (size, cb) { | ||
this._missing = size | ||
this._buf = Buffer.alloc(size) | ||
this._cb = cb | ||
} | ||
|
||
if (drained) next() | ||
else this._ondrain(next) | ||
} | ||
_stream (size, cb) { | ||
this._missing = size | ||
this._str = new MediaData(this) | ||
this._ondrain = nextEvent(this._str, 'drain') | ||
this._pending++ | ||
this._str.on('end', () => { | ||
this._pending-- | ||
this._kick() | ||
}) | ||
this._cb = cb | ||
return this._str | ||
} | ||
|
||
Decoder.prototype._buffer = function (size, cb) { | ||
this._missing = size | ||
this._buf = bufferAlloc(size) | ||
this._cb = cb | ||
} | ||
_readBox () { | ||
const bufferHeaders = (len, buf) => { | ||
this._buffer(len, additionalBuf => { | ||
if (buf) { | ||
buf = Buffer.concat([buf, additionalBuf]) | ||
} else { | ||
buf = additionalBuf | ||
} | ||
var headers = Box.readHeaders(buf) | ||
if (typeof headers === 'number') { | ||
bufferHeaders(headers - buf.length, buf) | ||
} else { | ||
this._pending++ | ||
this._headers = headers | ||
this.emit('box', headers) | ||
} | ||
}) | ||
} | ||
|
||
Decoder.prototype._stream = function (size, cb) { | ||
var self = this | ||
this._missing = size | ||
this._str = new MediaData(this) | ||
this._ondrain = nextEvent(this._str, 'drain') | ||
this._pending++ | ||
this._str.on('end', function () { | ||
self._pending-- | ||
self._kick() | ||
}) | ||
this._cb = cb | ||
return this._str | ||
} | ||
bufferHeaders(8) | ||
} | ||
|
||
Decoder.prototype._readBox = function () { | ||
var self = this | ||
bufferHeaders(8) | ||
stream () { | ||
if (!this._headers) throw new Error('this function can only be called once after \'box\' is emitted') | ||
var headers = this._headers | ||
this._headers = null | ||
|
||
function bufferHeaders (len, buf) { | ||
self._buffer(len, function (additionalBuf) { | ||
if (buf) { | ||
buf = Buffer.concat([buf, additionalBuf]) | ||
} else { | ||
buf = additionalBuf | ||
} | ||
var headers = Box.readHeaders(buf) | ||
if (typeof headers === 'number') { | ||
bufferHeaders(headers - buf.length, buf) | ||
} else { | ||
self._pending++ | ||
self._headers = headers | ||
self.emit('box', headers) | ||
} | ||
}) | ||
return this._stream(headers.contentLen, null) | ||
} | ||
} | ||
|
||
Decoder.prototype.stream = function () { | ||
var self = this | ||
if (!self._headers) throw new Error('this function can only be called once after \'box\' is emitted') | ||
var headers = self._headers | ||
self._headers = null | ||
decode (cb) { | ||
if (!this._headers) throw new Error('this function can only be called once after \'box\' is emitted') | ||
var headers = this._headers | ||
this._headers = null | ||
|
||
return self._stream(headers.contentLen, null) | ||
} | ||
|
||
Decoder.prototype.decode = function (cb) { | ||
var self = this | ||
if (!self._headers) throw new Error('this function can only be called once after \'box\' is emitted') | ||
var headers = self._headers | ||
self._headers = null | ||
|
||
self._buffer(headers.contentLen, function (buf) { | ||
var box = Box.decodeWithoutHeaders(headers, buf) | ||
cb(box) | ||
self._pending-- | ||
self._kick() | ||
}) | ||
} | ||
this._buffer(headers.contentLen, buf => { | ||
var box = Box.decodeWithoutHeaders(headers, buf) | ||
cb(box) | ||
this._pending-- | ||
this._kick() | ||
}) | ||
} | ||
|
||
Decoder.prototype.ignore = function () { | ||
var self = this | ||
if (!self._headers) throw new Error('this function can only be called once after \'box\' is emitted') | ||
var headers = self._headers | ||
self._headers = null | ||
ignore () { | ||
if (!this._headers) throw new Error('this function can only be called once after \'box\' is emitted') | ||
var headers = this._headers | ||
this._headers = null | ||
|
||
this._missing = headers.contentLen | ||
if (this._missing === 0) { | ||
this._ignoreEmpty = true | ||
this._missing = headers.contentLen | ||
if (this._missing === 0) { | ||
this._ignoreEmpty = true | ||
} | ||
this._cb = () => { | ||
this._pending-- | ||
this._kick() | ||
} | ||
} | ||
this._cb = function () { | ||
self._pending-- | ||
self._kick() | ||
|
||
_kick () { | ||
if (this._pending) return | ||
if (!this._buf && !this._str) this._readBox() | ||
if (this._writeBuffer) { | ||
var next = this._writeCb | ||
var buffer = this._writeBuffer | ||
this._writeBuffer = null | ||
this._writeCb = null | ||
this._write(buffer, null, next) | ||
} | ||
} | ||
} | ||
|
||
Decoder.prototype._kick = function () { | ||
if (this._pending) return | ||
if (!this._buf && !this._str) this._readBox() | ||
if (this._writeBuffer) { | ||
var next = this._writeCb | ||
var buffer = this._writeBuffer | ||
this._writeBuffer = null | ||
this._writeCb = null | ||
this._write(buffer, null, next) | ||
class MediaData extends stream.PassThrough { | ||
constructor (parent) { | ||
super() | ||
this._parent = parent | ||
this.destroyed = false | ||
} | ||
} | ||
|
||
function MediaData (parent) { | ||
this._parent = parent | ||
this.destroyed = false | ||
stream.PassThrough.call(this) | ||
destroy (err) { | ||
if (this.destroyed) return | ||
this.destroyed = true | ||
this._parent.destroy(err) | ||
if (err) this.emit('error', err) | ||
this.emit('close') | ||
} | ||
} | ||
|
||
inherits(MediaData, stream.PassThrough) | ||
|
||
MediaData.prototype.destroy = function (err) { | ||
if (this.destroyed) return | ||
this.destroyed = true | ||
this._parent.destroy(err) | ||
if (err) this.emit('error', err) | ||
this.emit('close') | ||
} | ||
module.exports = Decoder |
Oops, something went wrong.