Пример #1
0
  private void selectInner(List<Edit> edits, Slice cut, MovieBox movie, TrakBox trakBox) {
    long inMv = (long) (movie.getTimescale() * cut.inSec);
    long outMv = (long) (movie.getTimescale() * cut.outSec);

    long editStart = 0;
    ListIterator<Edit> lit = edits.listIterator();
    while (lit.hasNext()) {
      Edit edit = lit.next();
      if (editStart + edit.getDuration() <= inMv || editStart >= outMv) lit.remove();
      editStart += edit.getDuration();
    }
  }
Пример #2
0
 private void selectOuter(
     List<Edit> edits, List<Slice> commands, MovieBox movie, TrakBox trakBox) {
   long[] inMv = new long[commands.size()];
   long[] outMv = new long[commands.size()];
   for (int i = 0; i < commands.size(); i++) {
     inMv[i] = (long) (commands.get(i).inSec * movie.getTimescale());
     outMv[i] = (long) (commands.get(i).outSec * movie.getTimescale());
   }
   long editStartMv = 0;
   ListIterator<Edit> lit = edits.listIterator();
   while (lit.hasNext()) {
     Edit edit = lit.next();
     for (int i = 0; i < inMv.length; i++) {
       if (editStartMv + edit.getDuration() > inMv[i] && editStartMv < outMv[i]) lit.remove();
     }
     editStartMv += edit.getDuration();
   }
 }
Пример #3
0
  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;
  }
Пример #4
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));
  }
Пример #5
0
 private void split(List<Edit> edits, double sec, MovieBox movie, TrakBox trakBox) {
   Util.split(movie, trakBox, (long) (sec * movie.getTimescale()));
 }