UNPKG

mpegts.js

Version:

HTML5 MPEG2-TS Stream Player

116 lines (95 loc) 3.75 kB
/* * Copyright (C) 2016 Bilibili. All Rights Reserved. * * @author zheng qian <xqq@xqq.im> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {IllegalStateException, InvalidArgumentException} from '../utils/exception.js'; // Exponential-Golomb buffer decoder class ExpGolomb { constructor(uint8array) { this.TAG = 'ExpGolomb'; this._buffer = uint8array; this._buffer_index = 0; this._total_bytes = uint8array.byteLength; this._total_bits = uint8array.byteLength * 8; this._current_word = 0; this._current_word_bits_left = 0; } destroy() { this._buffer = null; } _fillCurrentWord() { let buffer_bytes_left = this._total_bytes - this._buffer_index; if (buffer_bytes_left <= 0) throw new IllegalStateException('ExpGolomb: _fillCurrentWord() but no bytes available'); let bytes_read = Math.min(4, buffer_bytes_left); let word = new Uint8Array(4); word.set(this._buffer.subarray(this._buffer_index, this._buffer_index + bytes_read)); this._current_word = new DataView(word.buffer).getUint32(0, false); this._buffer_index += bytes_read; this._current_word_bits_left = bytes_read * 8; } readBits(bits) { if (bits > 32) throw new InvalidArgumentException('ExpGolomb: readBits() bits exceeded max 32bits!'); if (bits <= this._current_word_bits_left) { let result = this._current_word >>> (32 - bits); this._current_word <<= bits; this._current_word_bits_left -= bits; return result; } let result = this._current_word_bits_left ? this._current_word : 0; result = result >>> (32 - this._current_word_bits_left); let bits_need_left = bits - this._current_word_bits_left; this._fillCurrentWord(); let bits_read_next = Math.min(bits_need_left, this._current_word_bits_left); let result2 = this._current_word >>> (32 - bits_read_next); this._current_word <<= bits_read_next; this._current_word_bits_left -= bits_read_next; result = (result << bits_read_next) | result2; return result; } readBool() { return this.readBits(1) === 1; } readByte() { return this.readBits(8); } _skipLeadingZero() { let zero_count; for (zero_count = 0; zero_count < this._current_word_bits_left; zero_count++) { if (0 !== (this._current_word & (0x80000000 >>> zero_count))) { this._current_word <<= zero_count; this._current_word_bits_left -= zero_count; return zero_count; } } this._fillCurrentWord(); return zero_count + this._skipLeadingZero(); } readUEG() { // unsigned exponential golomb let leading_zeros = this._skipLeadingZero(); return this.readBits(leading_zeros + 1) - 1; } readSEG() { // signed exponential golomb let value = this.readUEG(); if (value & 0x01) { return (value + 1) >>> 1; } else { return -1 * (value >>> 1); } } } export default ExpGolomb;