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)); }