Exemplo n.º 1
0
  /*
   * Parse stream headers until a compressed block or end of stream is reached. Possible return codes: OK - a
   * compressed block was found FINISH - end of stream was reached MORE - more input is need, parsing was suspended
   * ERR_HEADER - invalid stream header ERR_STRMCRC - stream CRC does not match ERR_EOF - unterminated stream (EOF
   * reached before end of stream) garbage is set only when returning FINISH. It is number of garbage bits consumed
   * after end of stream was reached.
   */
  Status parse(Header hd, BitStream bs, int[] garbage) throws StreamFormatException {
    assert (state != ACCEPT);

    while (OK == bs.need(16)) {
      int word = bs.peek(16);

      bs.dump(16);

      switch (state) {
        case STREAM_MAGIC_1:
          if (0x425A != word) {
            hd.bs100k = -1;
            hd.crc = 0;
            state = ACCEPT;
            garbage[0] = 16;
            return FINISH;
          }
          state = STREAM_MAGIC_2;
          continue;

        case STREAM_MAGIC_2:
          if (0x6839 < word || 0x6831 > word) {
            hd.bs100k = -1;
            hd.crc = 0;
            state = ACCEPT;
            garbage[0] = 32;
            return FINISH;
          }
          bs100k = word & 0xF;
          state = BLOCK_MAGIC_1;
          continue;

        case BLOCK_MAGIC_1:
          if (0x1772 == word) {
            state = EOS_2;
            continue;
          }
          if (0x3141 != word) throw new StreamFormatException("ERR_HEADER");
          state = BLOCK_MAGIC_2;
          continue;

        case BLOCK_MAGIC_2:
          if (0x5926 != word) throw new StreamFormatException("ERR_HEADER");
          state = BLOCK_MAGIC_3;
          continue;

        case BLOCK_MAGIC_3:
          if (0x5359 != word) throw new StreamFormatException("ERR_HEADER");
          state = BLOCK_CRC_1;
          continue;

        case BLOCK_CRC_1:
          stored_crc = word;
          state = BLOCK_CRC_2;
          continue;

        case BLOCK_CRC_2:
          hd.crc = (stored_crc << 16) | word;
          hd.bs100k = bs100k;
          computed_crc = (computed_crc << 1) ^ (computed_crc >>> 31) ^ hd.crc;
          state = BLOCK_MAGIC_1;
          return OK;

        case EOS_2:
          if (0x4538 != word) throw new StreamFormatException("ERR_HEADER");
          state = EOS_3;
          continue;

        case EOS_3:
          if (0x5090 != word) throw new StreamFormatException("ERR_HEADER");
          state = EOS_CRC_1;
          continue;

        case EOS_CRC_1:
          stored_crc = word;
          state = EOS_CRC_2;
          continue;

        case EOS_CRC_2:
          stored_crc = (stored_crc << 16) | word;
          if (stored_crc != computed_crc) throw new StreamFormatException("ERR_STRMCRC");
          computed_crc = 0;
          bs.align();
          state = STREAM_MAGIC_1;
          continue;

        default:
          break;
      }

      throw new IllegalStateException();
    }

    if (FINISH != bs.need(16)) return MORE;

    if (state == STREAM_MAGIC_1) {
      state = ACCEPT;
      garbage[0] = 0;
      return FINISH;
    }
    if (state == STREAM_MAGIC_2) {
      state = ACCEPT;
      garbage[0] = 16;
      return FINISH;
    }

    throw new StreamFormatException("ERR_EOF");
  }