extract(userDataSeiMessage, pts) {
    if (this.waitingForFirstPacket_) {
      shaka.log.debug('Setting first pts value to', pts);
      for (const stream of this.cea608ModeToStream_.values()) {
        stream.firstPts(pts);
      }
      this.waitingForFirstPacket_ = false;
    }

    const reader = new shaka.util.DataViewReader(
        userDataSeiMessage, shaka.util.DataViewReader.Endianness.BIG_ENDIAN);

    if (reader.getLength() < shaka.cea.CeaDecoder.MIN_LENGTH) {
      return;
    }
    if (reader.readUint8() !== shaka.cea.CeaDecoder.USA_COUNTRY_CODE) {
      return;
    }
    if (reader.readUint16() !== shaka.cea.CeaDecoder.ATSC_PROVIDER_CODE) {
      return;
    }
    if (reader.readUint32() !== shaka.cea.CeaDecoder.ATSC1_USER_IDENTIFIER) {
      return;
    }

    // user_data_type_code: 0x03 - cc_data()
    if (reader.readUint8() !== 0x03) {
      return;
    }

    // 1 bit reserved
    // 1 bit process_cc_data_flag
    // 1 bit zero_bit
    // 5 bits cc_count
    const captionData = reader.readUint8();
    // If process_cc_data_flag is not set, do not process this data.
    if ((captionData & 0x40) === 0) {
      return;
    }

    const count = captionData & 0x1f;

    // 8 bits reserved
    reader.skip(1);

    for (let i = 0; i < count; i++) {
      const cc = reader.readUint8();
      // When ccValid is 0, the next two bytes should be discarded.
      const ccValid = (cc & 0x04) >> 2;
      const ccData1 = reader.readUint8();
      const ccData2 = reader.readUint8();

      if (ccValid) {
        const ccType = cc & 0x03;
        // Send the packet to the appropriate data array (CEA-608 or CEA-708).
        if (ccType === shaka.cea.CeaDecoder.NTSC_CC_FIELD_1 ||
            ccType === shaka.cea.CeaDecoder.NTSC_CC_FIELD_2) {
          // CEA-608 NTSC (Line 21) Data.
          this.cea608DataArray_.push({
            pts,
            type: ccType,
            ccData1,
            ccData2,
            order: this.cea608DataArray_.length,
          });
        } else {
          // CEA-708 DTVCC Data.
          this.cea708DataArray_.push({
            pts,
            type: ccType,
            value: ccData1,
            order: this.cea708DataArray_.length,
          });

          // The second byte should always be labelled as DTVCC packet data.
          // Even if this pair was a DTVCC packet start, only the first byte
          // contains header info, and the second byte is just packet data.
          this.cea708DataArray_.push({
            pts,
            type: shaka.cea.DtvccPacketBuilder.DTVCC_PACKET_DATA,
            value: ccData2,
            order: this.cea708DataArray_.length,
          });
        }
      }
    }
  }
Extracts closed caption bytes from CEA-X08 packets from the stream based on
ANSI/SCTE 128 and A/53, Part 4.
@override