예제 #1
0
파일: Cut.java 프로젝트: 2php/jcodec
 private static void saveSlices(List<MovieBox> slices, List<String> names, File parentFile)
     throws IOException {
   for (int i = 0; i < slices.size(); i++) {
     if (names.get(i) == null) continue;
     SeekableByteChannel out = null;
     try {
       out = writableChannel(new File(parentFile, names.get(i)));
       MP4Util.writeMovie(out, slices.get(i));
     } finally {
       NIOUtils.closeQuietly(out);
     }
   }
 }
예제 #2
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));
  }
예제 #3
0
파일: Cut.java 프로젝트: 2php/jcodec
  public static void main1(String[] args) throws Exception {
    if (args.length < 1) {
      System.out.println(
          "Syntax: cut [-command arg]...[-command arg] [-self] <movie file>\n"
              + "\tCreates a reference movie out of the file and applies a set of changes specified by the commands to it.");
      System.exit(-1);
    }

    List<Slice> slices = new ArrayList<Slice>();
    List<String> sliceNames = new ArrayList<String>();

    boolean selfContained = false;
    int shift = 0;
    while (true) {
      if ("-cut".equals(args[shift])) {
        String[] pt = StringUtils.splitS(args[shift + 1], ":");
        slices.add(new Slice(parseInt(pt[0]), parseInt(pt[1])));
        if (pt.length > 2) sliceNames.add(pt[2]);
        else sliceNames.add(null);
        shift += 2;
      } else if ("-self".equals(args[shift])) {
        ++shift;
        selfContained = true;
      } else break;
    }
    File source = new File(args[shift]);

    SeekableByteChannel input = null;
    SeekableByteChannel out = null;
    List<SeekableByteChannel> outs = new ArrayList<SeekableByteChannel>();
    try {
      input = readableChannel(source);
      MovieBox movie = createRefMovie(input, "file://" + source.getCanonicalPath());
      List<MovieBox> slicesMovs;
      if (!selfContained) {
        out =
            writableChannel(
                new File(
                    source.getParentFile(),
                    JCodecUtil2.removeExtension(source.getName()) + ".ref.mov"));
        slicesMovs = new Cut().cut(movie, slices);
        MP4Util.writeMovie(out, movie);
      } else {
        out =
            writableChannel(
                new File(
                    source.getParentFile(),
                    JCodecUtil2.removeExtension(source.getName()) + ".self.mov"));
        slicesMovs = new Cut().cut(movie, slices);
        new Strip().strip(movie);
        new Flattern().flatternChannel(movie, out);
      }
      saveSlices(slicesMovs, sliceNames, source.getParentFile());
    } finally {
      if (input != null) input.close();
      if (out != null) out.close();
      for (SeekableByteChannel o : outs) {
        o.close();
      }
    }
  }