Example #1
0
  public void flatternChannel(MovieBox movie, SeekableByteChannel out) throws IOException {
    if (!movie.isPureRefMovie(movie))
      throw new IllegalArgumentException("movie should be reference");
    ByteBuffer buf = ByteBuffer.allocate(16 * 1024 * 1024);
    FileTypeBox ftyp =
        FileTypeBox.createFileTypeBox("qt  ", 0x20050300, Arrays.asList(new String[] {"qt  "}));
    ftyp.write(buf);
    long movieOff = buf.position();
    movie.write(buf);

    int extraSpace = calcSpaceReq(movie);
    Header.createHeader("free", 8 + extraSpace).write(buf);
    NIOUtils.skip(buf, extraSpace);

    long mdatOff = buf.position();
    Header.createHeader("mdat", 0x100000001L).write(buf);
    buf.flip();
    out.write(buf);

    SeekableByteChannel[][] inputs = getInputs(movie);

    TrakBox[] tracks = movie.getTracks();
    ChunkReader[] readers = new ChunkReader[tracks.length];
    ChunkWriter[] writers = new ChunkWriter[tracks.length];
    Chunk[] head = new Chunk[tracks.length];
    int totalChunks = 0, writtenChunks = 0, lastProgress = 0;
    long[] off = new long[tracks.length];
    for (int i = 0; i < tracks.length; i++) {
      readers[i] = new ChunkReader(tracks[i]);
      totalChunks += readers[i].size();

      writers[i] = new ChunkWriter(tracks[i], inputs[i], out);
      head[i] = readers[i].next();
      if (tracks[i].isVideo()) off[i] = 2 * movie.getTimescale();
    }

    while (true) {
      int min = -1;
      for (int i = 0; i < readers.length; i++) {
        if (head[i] == null) continue;

        if (min == -1) min = i;
        else {
          long iTv = movie.rescale(head[i].getStartTv(), tracks[i].getTimescale()) + off[i];
          long minTv = movie.rescale(head[min].getStartTv(), tracks[min].getTimescale()) + off[min];
          if (iTv < minTv) min = i;
        }
      }
      if (min == -1) break;
      writers[min].write(head[min]);
      head[min] = readers[min].next();
      writtenChunks++;

      lastProgress = calcProgress(totalChunks, writtenChunks, lastProgress);
    }
    long mdatSize = out.position() - mdatOff;

    for (int i = 0; i < tracks.length; i++) {
      writers[i].apply();
    }
    out.setPosition(movieOff);
    MP4Util.writeMovie(out, movie);

    long extra = mdatOff - out.position();
    if (extra < 0) throw new RuntimeException("Not enough space to write the header");
    out.write(
        (ByteBuffer)
            ByteBuffer.allocate(8).putInt((int) extra).put(new byte[] {'f', 'r', 'e', 'e'}).flip());

    out.setPosition(mdatOff + 8);
    out.write(ByteBuffer.allocate(8).putLong(mdatSize));
  }