@Override
 public final void writeMessage(InputStream message) {
   if (outboundPhase() != Phase.MESSAGE) {
     throw new IllegalStateException("Messages are only permitted after headers and before close");
   }
   super.writeMessage(message);
 }
  /** @see stream.io.AbstractStream#close() */
  @Override
  public void close() throws Exception {
    log.info("Closing TransportStream...");
    super.close();
    closed.set(true);

    while (prefetcher.isAlive()) {
      log.info("Waiting for pre-fetcher thread to finish...");
      try {
        prefetcher.interrupt();
        prefetcher.join();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  /** @see stream.io.AbstractStream#init() */
  @Override
  public void init() throws Exception {
    super.init();

    stream = this.getInputStream();

    prefetcher =
        new Thread() {
          public void run() {
            while (!closed.get()) {

              try {
                byte[] packet = new byte[188];

                int read = 0;
                while (!closed.get() && read < 188) {
                  int bytes = stream.read(packet, read, packet.length - read);
                  log.debug("Read {} bytes from stream...", bytes);
                  if (bytes > 0) {
                    read += bytes;
                    offset += bytes;
                  }
                }

                byte mask = 0xff >> 3;
                int pid = ((mask & packet[1]) << 8) + packet[2];

                // log.info("PID is: 0x{}", Integer.toHexString(pid));
                if (pid == 0) {
                  log.debug("packet {} has PID 0, offset is {}", sequenceId, offset);
                  log.debug("   total of {}k read", offset / 1024);
                }

                byte flags = packet[3];
                // log.info("Flags:              'SCAP____'");
                // log.info(
                // "Flags:              '{}'",
                // String.format("%8s",
                // Integer.toBinaryString(flags)));

                // log.info(
                // "scramble vector is  '{}'",
                // String.format("%8s",
                // Integer.toBinaryString(SCRAMBLE_BIT)));

                if ((flags & SCRAMBLE_BIT) > 0) {
                  log.debug("scrambling found!");
                }

                // log.info(
                // "adaption vector is  '{}'",
                // String.format("%8s",
                // Integer.toBinaryString(ADAPTION_BIT)));
                if ((flags & ADAPTION_BIT) > 0) {
                  // log.info("Adaption bit set!");

                  int adaptionSize = Byte.valueOf(packet[4]).intValue();
                  // short adaptionSize = (short) packet[4];
                  // log.info("Adaption header has {} bytes",
                  // adaptionSize);
                  if (adaptionSize > 0) {
                    // byte flag = packet[5];
                    //
                    // if ((flag & ADAPTION_PCR) > 0) {
                    // log.info("Found PCR !");
                    // long pcr_base = ((((int) packet[6]) << 24)
                    // + (packet[7] << 16)
                    // + (packet[8] << 8) + packet[9]) << 1;
                    //
                    // long rest = (packet[10] << 8) + packet[11];
                    // if ((rest & 0x8000) > 0) {
                    // pcr_base++;
                    // }
                    // log.info("pcr_base = {}", pcr_base);
                    // long pcr_ref_ext = (rest & 0x1FF);
                    // log.info("pcr_ref_ext = {}", pcr_ref_ext);
                    // }
                    //
                    // if ((flag & ADAPTION_OPCR) > 0) {
                    // log.info("Found OPCR !");
                    // }
                  }
                }

                // if ((flags & PAYLOAD_BIT) > 0) {
                // log.debug("payload bit set!");
                // }

                // int count = (int) (flags & 15);
                // log.info("Counter is: {}", count);

                // if (pid == 0) {
                // log.info("Found Program Association Table (PAT)!");
                //
                // int table_id = packet[5];
                // log.info("table id is: {}",
                // Integer.toHexString(table_id));
                // }

                // log.info("count   vector is   '{}'", String.format(
                // "%8s", Integer.toBinaryString(15)));

                Data item = DataFactory.create();
                item.put("packet:data", packet);
                item.put("packet:pid", pid);
                item.put("packet:offset", offset - 188);
                item.put("packet:sequence", sequenceId++);
                item.put("packet:source:url", getUrl() + "");
                while (queue.remainingCapacity() < 1) {
                  log.debug("Waiting for queue to drain a bit...");
                  Thread.sleep(100);
                }
                queue.add(item);
              } catch (Exception e) {
                e.printStackTrace();
              }
            }
            log.debug("Prefetcher thread finished.");
          }
        };
    prefetcher.setDaemon(true);
    prefetcher.start();
  }