UNPKG

shaka-player

Version:
190 lines (165 loc) 5.21 kB
/*! @license * Shaka Player * Copyright 2016 Google LLC * SPDX-License-Identifier: Apache-2.0 */ goog.provide('shaka.cea.DtvccPacketBuilder'); goog.provide('shaka.cea.DtvccPacket'); goog.require('shaka.util.Error'); goog.requireType('shaka.cea.Cea708Service'); /** * CEA-708 DTVCC Packet Builder. * Builds packets based on Figure 5 CCP State Table in 5.2 of CEA-708-E. * Initially, there is no packet. When a DTVCC_PACKET_START payload is received, * a packet begins construction. The packet is considered "built" once all bytes * indicated in the header are read, and ignored if a new packet starts building * before the current packet is finished being built. */ shaka.cea.DtvccPacketBuilder = class { /** */ constructor() { /** * An array containing built DTVCC packets that are ready to be processed. * @private {!Array<!shaka.cea.DtvccPacket>} */ this.builtPackets_ = []; /** * Stores the packet data for the current packet being processed, if any. * @private {?Array<!shaka.cea.Cea708Service.Cea708Byte>} */ this.currentPacketBeingBuilt_ = null; /** * Keeps track of the number of bytes left to add in the current packet. * @private {number} */ this.bytesLeftToAddInCurrentPacket_ = 0; } /** * @param {!shaka.cea.Cea708Service.Cea708Byte} cea708Byte */ addByte(cea708Byte) { if (cea708Byte.type === shaka.cea.DtvccPacketBuilder.DTVCC_PACKET_START) { // If there was a packet being built that finished, it would have // already been added to the built packets when it finished. So if // there's an open packet at this point, it must be unfinished. As // per the spec, we don't deal with unfinished packets. So we ignore them. // A new packet should be opened. const packetSize = cea708Byte.value & 0x3f; // As per spec, number of packet data bytes to follow is packetSize*2-1. this.bytesLeftToAddInCurrentPacket_ = packetSize * 2 - 1; this.currentPacketBeingBuilt_ = []; return; } if (!this.currentPacketBeingBuilt_) { // There is no packet open. Then an incoming byte should not // have come in at all. Ignore it. return; } if (this.bytesLeftToAddInCurrentPacket_ > 0) { this.currentPacketBeingBuilt_.push(cea708Byte); this.bytesLeftToAddInCurrentPacket_--; } if (this.bytesLeftToAddInCurrentPacket_ === 0) { // Current packet is complete and ready for processing. const packet = new shaka.cea.DtvccPacket(this.currentPacketBeingBuilt_); this.builtPackets_.push(packet); this.currentPacketBeingBuilt_ = null; this.bytesLeftToAddInCurrentPacket_ = 0; } } /** * @return {!Array<!shaka.cea.DtvccPacket>} */ getBuiltPackets() { return this.builtPackets_; } /** Clear built packets. */ clearBuiltPackets() { this.builtPackets_ = []; } /** Clear built packets and packets in progress. */ clear() { this.builtPackets_ = []; this.currentPacketBeingBuilt_ = []; this.bytesLeftToAddInCurrentPacket_ = 0; } }; shaka.cea.DtvccPacket = class { /** * @param {!Array<!shaka.cea.Cea708Service.Cea708Byte>} packetData */ constructor(packetData) { /** * Keeps track of the position to read the next byte from in the packet. * @private {number} */ this.pos_ = 0; /** * Bytes that represent the data in the DTVCC packet. * @private {!Array<!shaka.cea.Cea708Service.Cea708Byte>} */ this.packetData_ = packetData; } /** * @return {boolean} */ hasMoreData() { return this.pos_ < this.packetData_.length; } /** * @return {number} */ getPosition() { return this.pos_; } /** * Reads a byte from the packet. TODO CONSIDER RENAMING THIS TO BLOCK * @return {!shaka.cea.Cea708Service.Cea708Byte} * @throws {!shaka.util.Error} */ readByte() { if (!this.hasMoreData()) { throw new shaka.util.Error( shaka.util.Error.Severity.CRITICAL, shaka.util.Error.Category.TEXT, shaka.util.Error.Code.BUFFER_READ_OUT_OF_BOUNDS); } return this.packetData_[this.pos_++]; } /** * Skips the provided number of blocks in the buffer. * @param {number} numBlocks * @throws {!shaka.util.Error} */ skip(numBlocks) { if (this.pos_ + numBlocks > this.packetData_.length) { throw new shaka.util.Error( shaka.util.Error.Severity.CRITICAL, shaka.util.Error.Category.TEXT, shaka.util.Error.Code.BUFFER_READ_OUT_OF_BOUNDS); } this.pos_ += numBlocks; } /** * Rewinds the provided number of blocks in the buffer. * @param {number} numBlocks * @throws {!shaka.util.Error} */ rewind(numBlocks) { if (this.pos_ - numBlocks < 0) { throw new shaka.util.Error( shaka.util.Error.Severity.CRITICAL, shaka.util.Error.Category.TEXT, shaka.util.Error.Code.BUFFER_READ_OUT_OF_BOUNDS); } this.pos_ -= numBlocks; } }; /** * @const {number} */ shaka.cea.DtvccPacketBuilder.DTVCC_PACKET_DATA = 2; /** * @const {number} */ shaka.cea.DtvccPacketBuilder.DTVCC_PACKET_START = 3;