UNPKG

@sqhead/mux.js

Version:

A collection of lightweight utilities for inspecting and manipulating video container formats.

95 lines (75 loc) 2.76 kB
var Stream = require('../utils/stream.js'); var H264Stream = require('../codecs/h264').H264Stream; var VideoSegmentStream = require('../mp4/transmuxer').VideoSegmentStream; var CoalesceStream = require('./coalesce-stream.js'); // object types var Transmuxer; var TIMESCALE = 90000; // Hz var ACCESS_UNIT_DELIMITER = new Uint8Array([0, 0, 0, 1, 9]); /** * A Stream that takes raw H264 frames as binary data as input and produces * corresponding media segments, suitable for use with Media Source * Extension (MSE) implementations that support the ISO BMFF byte * stream format, like Chrome. */ Transmuxer = function(options) { Transmuxer.prototype.init.call(this); options = options || {}; this.baseMediaDecodeTime = options.baseMediaDecodeTime || 0; this.transmuxPipeline_; this.setupPipeline = function() { var pipeline = {}; this.transmuxPipeline_ = pipeline; pipeline.type = 'rawh264'; var videoTrack = { timelineStartInfo: { baseMediaDecodeTime: 0 }, id: 0, codec: 'avc', type: 'video' }; // Setup pipelines pipeline.h264Stream = new H264Stream(); pipeline.videoSegmentStream = new VideoSegmentStream(videoTrack, options); pipeline.coalesceStream = new CoalesceStream(options); pipeline.coalesceStream.numberOfTracks++; pipeline.h264Stream .pipe(pipeline.videoSegmentStream) .pipe(pipeline.coalesceStream); // Re-emit any data coming from the coalesce stream to the outside world pipeline.coalesceStream.on('data', this.trigger.bind(this, 'data')); // Let the consumer know we have finished flushing the entire pipeline pipeline.coalesceStream.on('done', this.trigger.bind(this, 'done')); // Set head of pipeline pipeline.headOfPipeline = pipeline.h264Stream; }; this.setupPipeline(); // feed incoming data to the front of the parsing pipeline // data must be object with `data` and `timestamp` fields this.push = function(data) { // Set correct pts/dts values pts = dts = data.timestamp * TIMESCALE; // Prepend Access Unit Delimiter packetData = new Uint8Array(data.data.byteLength + ACCESS_UNIT_DELIMITER.byteLength); packetData.set(ACCESS_UNIT_DELIMITER); packetData.set(data.data, ACCESS_UNIT_DELIMITER.byteLength); var packet = { type: 'video', trackId: 0, pts: pts, dts: dts, data: packetData }; this.transmuxPipeline_.headOfPipeline.push(packet); }; // flush any buffered data this.flush = function() { // Start at the top of the pipeline and flush all pending work this.transmuxPipeline_.headOfPipeline.flush(); }; }; Transmuxer.prototype = new Stream(); module.exports = { Transmuxer: Transmuxer };