Ejemplo n.º 1
0
  /**
   * Buffers the given packet up ready for writing to the stream, but doesn't write it to disk yet.
   * The granule position is updated on the page. If writing the packet requires a new page, then
   * the updated granule position only applies to the new page
   */
  public void bufferPacket(OggPacket packet, long granulePosition) {
    if (closed) {
      throw new IllegalStateException("Can't buffer packets on a closed stream!");
    }
    if (!doneFirstPacket) {
      packet.setIsBOS();
      doneFirstPacket = true;
    }

    int size = packet.getData().length;
    boolean emptyPacket = (size == 0);

    // Add to pages in turn
    OggPage page = getCurrentPage(false);
    int pos = 0;
    while (pos < size || emptyPacket) {
      pos = page.addPacket(packet, pos);
      if (pos < size) {
        page = getCurrentPage(true);
        page.setIsContinuation();
      }
      page.setGranulePosition(granulePosition);
      emptyPacket = false;
    }
    currentGranulePosition = granulePosition;
    packet.setParent(page);
  }
Ejemplo n.º 2
0
 /**
  * Returns the number of bytes (excluding headers) currently waiting to be written to disk. RFC
  * 3533 suggests that pages should normally be in the 4-8kb range. If this size exceeds just shy
  * of 64kb, then multiple pages will be needed in the underlying stream.
  */
 public int getSizePendingFlush() {
   int size = 0;
   for (OggPage p : buffer) {
     size += p.getDataSize();
   }
   return size;
 }
Ejemplo n.º 3
0
 private OggPage getCurrentPage(boolean forceNew) {
   if (buffer.size() == 0 || forceNew) {
     OggPage page = new OggPage(sid, sequenceNumber++);
     if (currentGranulePosition > 0) {
       page.setGranulePosition(currentGranulePosition);
     }
     buffer.add(page);
     return page;
   }
   return buffer.get(buffer.size() - 1);
 }
Ejemplo n.º 4
0
  /**
   * Returns the next packet in the file, or null if no more packets remain. Call {@link
   * OggPacket#isBeginningOfStream()} to detect if it is the first packet in the stream or not, and
   * use {@link OggPacket#getSid()} to track which stream it belongs to.
   */
  public OggPacket getNextPacket() throws IOException {
    // If we skipped to a point in the stream, and
    //  have a packet waiting, return that
    if (nextPacket != null) {
      OggPacket p = nextPacket;
      nextPacket = null;
      return p;
    }

    // If we're already part way through a page,
    //  then fetch the next packet. If it's a
    //  full one, then we're done.
    OggPacketData leftOver = null;
    if (it != null && it.hasNext()) {
      OggPacketData packet = it.next();
      if (packet instanceof OggPacket) {
        return (OggPacket) packet;
      }
      leftOver = packet;
    }

    // Find the next page, from which
    //  to get our next packet from
    int searched = 0;
    int pos = -1;
    boolean found = false;
    int r;
    while (searched < 65536 && !found) {
      r = inp.read();
      if (r == -1) {
        // No more data
        return null;
      }

      switch (pos) {
        case -1:
          if (r == (int) 'O') {
            pos = 0;
          }
          break;
        case 0:
          if (r == (int) 'g') {
            pos = 1;
          } else {
            pos = -1;
          }
          break;
        case 1:
          if (r == (int) 'g') {
            pos = 2;
          } else {
            pos = -1;
          }
          break;
        case 2:
          if (r == (int) 'S') {
            found = true;
          } else {
            pos = -1;
          }
          break;
      }

      if (!found) {
        searched++;
      }
    }

    if (!found) {
      throw new IOException(
          "Next ogg packet header not found after searching " + searched + " bytes");
    }

    searched -= 3; // OggS
    if (searched > 0) {
      System.err.println(
          "Warning - had to skip "
              + searched
              + " bytes of junk data before finding the next packet header");
    }

    // Create the page, and prime the iterator on it
    try {
      OggPage page = new OggPage(inp);
      if (!page.isChecksumValid()) {
        System.err.println(
            "Warning - invalid checksum on page "
                + page.getSequenceNumber()
                + " of stream "
                + Integer.toHexString(page.getSid())
                + " ("
                + page.getSid()
                + ")");
      }
      it = page.getPacketIterator(leftOver);
      return getNextPacket();
    } catch (EOFException eof) {
      System.err.println("Warning - data ended mid-page: " + eof.getMessage());
      return null;
    }
  }
Ejemplo n.º 5
0
 /**
  * Sets the current granule position. The granule position will be applied to all un-flushed
  * packets, and all future packets. As such, you should normally either call a flush just before
  * or just after this call.
  */
 public void setGranulePosition(long position) {
   currentGranulePosition = position;
   for (OggPage p : buffer) {
     p.setGranulePosition(position);
   }
 }
Ejemplo n.º 6
0
  /**
   * Returns the size of the page currently being written to, including its headers. For a new
   * stream, or a stream that has just been flushed, will return zero.
   *
   * @return Current page size, or 0 if no current page
   */
  public int getCurrentPageSize() {
    if (buffer.isEmpty()) return 0;

    OggPage p = buffer.get(buffer.size() - 1);
    return p.getPageSize();
  }