コード例 #1
0
ファイル: Mp4BoxHeader.java プロジェクト: kiniry-teaching/UCD
  /**
   * Seek for box with the specified id starting from the current location of filepointer,
   *
   * <p>Note it wont find the box if it is contained with a level below the current level, nor if we
   * are at a parent atom that also contains data and we havent yet processed the data. It will work
   * if we are at the start of a child box even if it not the required box as long as the box we are
   * looking for is the same level (or the level above in some cases).
   *
   * @param raf
   * @param id
   * @throws java.io.IOException
   */
  public static Mp4BoxHeader seekWithinLevel(RandomAccessFile raf, String id) throws IOException {
    logger.finer("Started searching for:" + id + " in file at:" + raf.getChannel().position());

    Mp4BoxHeader boxHeader = new Mp4BoxHeader();
    ByteBuffer headerBuffer = ByteBuffer.allocate(HEADER_LENGTH);
    int bytesRead = raf.getChannel().read(headerBuffer);
    if (bytesRead != HEADER_LENGTH) {
      return null;
    }
    headerBuffer.rewind();
    boxHeader.update(headerBuffer);
    while (!boxHeader.getId().equals(id)) {
      logger.finer("Still searching for:" + id + " in file at:" + raf.getChannel().position());

      // Something gone wrong probably not at the start of an atom so return null;
      if (boxHeader.getLength() < Mp4BoxHeader.HEADER_LENGTH) {
        return null;
      }
      int noOfBytesSkipped = raf.skipBytes(boxHeader.getDataLength());
      logger.finer("Skipped:" + noOfBytesSkipped);
      if (noOfBytesSkipped < boxHeader.getDataLength()) {
        return null;
      }
      headerBuffer.rewind();
      bytesRead = raf.getChannel().read(headerBuffer);
      logger.finer("Header Bytes Read:" + bytesRead);
      headerBuffer.rewind();
      if (bytesRead == Mp4BoxHeader.HEADER_LENGTH) {
        boxHeader.update(headerBuffer);
      } else {
        return null;
      }
    }
    return boxHeader;
  }
コード例 #2
0
  protected void build(ByteBuffer data) throws UnsupportedEncodingException {
    // Data actually contains a 'Data' Box so process data using this
    Mp4BoxHeader header = new Mp4BoxHeader(data);
    Mp4DataBox databox = new Mp4DataBox(header, data);
    dataSize = header.getDataLength();
    numbers = databox.getNumbers();

    // Disc number always hold four values, we can discard the first one and last one, the second
    // one is the disc no
    // and the third is the total no of discs so only use if not zero
    StringBuffer sb = new StringBuffer();
    sb.append(numbers.get(DISC_NO_INDEX));
    if (numbers.get(DISC_TOTAL_INDEX) > 0) {
      sb.append("/" + numbers.get(DISC_TOTAL_INDEX));
    }
    content = sb.toString();
  }
コード例 #3
0
  /**
   * @param header parentHeader info
   * @param dataBuffer data of box (doesnt include parentHeader data)
   */
  public Mp4NameBox(Mp4BoxHeader header, ByteBuffer dataBuffer) {
    this.header = header;

    // Double check
    if (!header.getId().equals(IDENTIFIER)) {
      throw new RuntimeException(
          "Unable to process name box because identifier is:" + header.getId());
    }

    // Make slice so operations here don't effect position of main buffer
    this.dataBuffer = dataBuffer.slice();

    // issuer
    this.name =
        Utils.getString(
            this.dataBuffer,
            PRE_DATA_LENGTH,
            header.getDataLength() - PRE_DATA_LENGTH,
            header.getEncoding());
  }
コード例 #4
0
  /**
   * @param header parentHeader info
   * @param dataBuffer data of box (doesnt include parentHeader data)
   */
  public Mp4DataBox(Mp4BoxHeader header, ByteBuffer dataBuffer) {
    this.header = header;
    // Double check
    if (!header.getId().equals(IDENTIFIER)) {
      throw new RuntimeException(
          "Unable to process data box because identifier is:" + header.getId());
    }

    // Make slice so operations here don't effect position of main buffer
    this.dataBuffer = dataBuffer.slice();

    // Type
    type =
        Utils.getIntBE(
            this.dataBuffer, Mp4DataBox.TYPE_POS, Mp4DataBox.TYPE_POS + Mp4DataBox.TYPE_LENGTH - 1);

    if (type == Mp4FieldType.TEXT.getFileClassId()) {
      content =
          Utils.getString(
              this.dataBuffer,
              PRE_DATA_LENGTH,
              header.getDataLength() - PRE_DATA_LENGTH,
              header.getEncoding());
    } else if (type == Mp4FieldType.NUMERIC.getFileClassId()) {
      numbers = new ArrayList<Short>();

      for (int i = 0; i < ((header.getDataLength() - PRE_DATA_LENGTH) / NUMBER_LENGTH); i++) {
        short number =
            Utils.getShortBE(
                this.dataBuffer,
                PRE_DATA_LENGTH + (i * NUMBER_LENGTH),
                PRE_DATA_LENGTH + (i * NUMBER_LENGTH) + (NUMBER_LENGTH - 1));
        numbers.add(number);
      }

      // Make String representation  (separate values with slash)
      StringBuffer sb = new StringBuffer();
      ListIterator<Short> iterator = numbers.listIterator();
      while (iterator.hasNext()) {
        sb.append(iterator.next());
        if (iterator.hasNext()) {
          sb.append("/");
        }
      }
      content = sb.toString();
    } else if (type == Mp4FieldType.BYTE.getFileClassId()) {
      // TODO byte data length seems to be 1 for pgap and cpil but 2 for tmpo ?
      // Create String representation for display
      content = Utils.getIntBE(this.dataBuffer, PRE_DATA_LENGTH, header.getDataLength() - 1) + "";

      // But store data for safer writng back to file
      bytedata = new byte[header.getDataLength() - PRE_DATA_LENGTH];
      int pos = dataBuffer.position();
      dataBuffer.position(pos + PRE_DATA_LENGTH);
      dataBuffer.get(bytedata);
      dataBuffer.position(pos);
    } else if (type == Mp4FieldType.COVERART_JPEG.getFileClassId()) {
      content =
          Utils.getString(
              this.dataBuffer,
              PRE_DATA_LENGTH,
              header.getDataLength() - PRE_DATA_LENGTH,
              header.getEncoding());
    }
  }