コード例 #1
0
ファイル: Flattern.java プロジェクト: 2php/jcodec
 private int calcSpaceReq(MovieBox movie) {
   int sum = 0;
   TrakBox[] tracks = movie.getTracks();
   for (int i = 0; i < tracks.length; i++) {
     TrakBox trakBox = tracks[i];
     ChunkOffsetsBox stco = trakBox.getStco();
     if (stco != null) sum += stco.getChunkOffsets().length * 4;
   }
   return sum;
 }
コード例 #2
0
ファイル: Cut.java プロジェクト: 2php/jcodec
  public List<MovieBox> cut(MovieBox movie, List<Slice> commands) {

    TrakBox videoTrack = movie.getVideoTrack();
    if (videoTrack != null && videoTrack.getTimescale() != movie.getTimescale())
      movie.fixTimescale(videoTrack.getTimescale());

    TrakBox[] tracks = movie.getTracks();
    for (int i = 0; i < tracks.length; i++) {
      TrakBox trakBox = tracks[i];
      forceEditList(movie, trakBox);
      List<Edit> edits = trakBox.getEdits();
      for (Slice cut : commands) {
        split(edits, cut.inSec, movie, trakBox);
        split(edits, cut.outSec, movie, trakBox);
      }
    }
    ArrayList<MovieBox> result = new ArrayList<MovieBox>();
    for (Slice cut : commands) {
      MovieBox clone =
          (MovieBox) NodeBox.cloneBox(movie, 16 * 1024 * 1024, BoxFactory.getDefault());
      for (TrakBox trakBox : clone.getTracks()) {
        selectInner(trakBox.getEdits(), cut, movie, trakBox);
      }
      result.add(clone);
    }

    long movDuration = 0;
    for (TrakBox trakBox : movie.getTracks()) {
      selectOuter(trakBox.getEdits(), commands, movie, trakBox);
      trakBox.setEdits(trakBox.getEdits());
      movDuration = max(movDuration, trakBox.getDuration());
    }
    movie.setDuration(movDuration);

    return result;
  }
コード例 #3
0
ファイル: Flattern.java プロジェクト: 2php/jcodec
 protected SeekableByteChannel[][] getInputs(MovieBox movie) throws IOException {
   TrakBox[] tracks = movie.getTracks();
   SeekableByteChannel[][] result = new SeekableByteChannel[tracks.length][];
   for (int i = 0; i < tracks.length; i++) {
     DataRefBox drefs =
         NodeBox.findFirstPath(tracks[i], DataRefBox.class, Box.path("mdia.minf.dinf.dref"));
     if (drefs == null) {
       throw new RuntimeException("No data references");
     }
     List<Box> entries = drefs.getBoxes();
     SeekableByteChannel[] e = new SeekableByteChannel[entries.size()];
     SeekableByteChannel[] inputs = new SeekableByteChannel[entries.size()];
     for (int j = 0; j < e.length; j++) {
       inputs[j] = resolveDataRef(entries.get(j));
     }
     result[i] = inputs;
   }
   return result;
 }
コード例 #4
0
ファイル: Flattern.java プロジェクト: 2php/jcodec
  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));
  }