decodeCea608_(ccPacket) {
    const fieldNum = ccPacket.type;

    // If this packet is a control code, then it also sets the channel.
    // For control codes, cc_data_1 has the form |P|0|0|1|C|X|X|X|.
    // "C" is the channel bit. It indicates whether to set C2 active.
    if (shaka.cea.Cea608DataChannel.isControlCode(ccPacket.ccData1)) {
      const channelNum = (ccPacket.ccData1 >> 3) & 0x01; // Get channel bit.

      // Change the stream based on the field, and the new channel
      if (fieldNum === 0) {
        this.currentField1Channel_ = channelNum;
      } else {
        this.currentField2Channel_ = channelNum;
      }
    }

    // Get the correct stream for this caption packet (CC1, ..., CC4)
    const selectedChannel = fieldNum ?
        this.currentField2Channel_ : this.currentField1Channel_;
    const selectedMode = `CC${((fieldNum << 1) | selectedChannel) + 1}`;
    const selectedStream = this.cea608ModeToStream_.get(selectedMode);

    // Check for bad frames (bad pairs). This can be two 0xff, two 0x00, or any
    // byte of even parity. ccData1 and ccData2 should be uint8 of odd parity.
    if ((ccPacket.ccData1 === 0xff && ccPacket.ccData2 === 0xff) ||
        (!ccPacket.ccData1 && !ccPacket.ccData2) ||
        !this.isOddParity_(ccPacket.ccData1) ||
        !this.isOddParity_(ccPacket.ccData2)) {
      // Per CEA-608-B C.21, reset the memory after 45 consecutive bad frames.
      if (++this.badFrames_ >= 45) {
        this.reset();
      }
      return null;
    }
    this.badFrames_ = 0;

    // Remove the MSB (parity bit).
    ccPacket.ccData1 &= 0x7f;
    ccPacket.ccData2 &= 0x7f;

    // Ignore XDS
    if (shaka.cea.Cea608DataChannel.isXdsControlCode(ccPacket.ccData1)) {
      return null;
    }

    // Check for empty captions and skip them.
    if (!ccPacket.ccData1 && !ccPacket.ccData2) {
      return null;
    }

    // Process the clean CC data pair.
    let parsedClosedCaption = null;
    if (shaka.cea.Cea608DataChannel.isControlCode(ccPacket.ccData1)) {
      this.streams_.add(selectedMode);
      parsedClosedCaption = selectedStream.handleControlCode(ccPacket);
    } else {
      // Handle as a Basic North American Character.
      selectedStream.handleBasicNorthAmericanChar(
          ccPacket.ccData1, ccPacket.ccData2);
    }

    return parsedClosedCaption;
  }
Decodes a CEA-608 closed caption packet based on ANSI/CEA-608.
@param {shaka.cea.Cea608DataChannel.Cea608Packet} ccPacket
@return {?shaka.extern.ICaptionDecoder.ClosedCaption}
@private