public void paste(MovieBox to, MovieBox from, double sec) { TrakBox videoTrack = to.getVideoTrack(); if (videoTrack != null && videoTrack.getTimescale() != to.getTimescale()) to.fixTimescale(videoTrack.getTimescale()); long displayTv = (long) (to.getTimescale() * sec); forceEditListMov(to); forceEditListMov(from); TrakBox[] fromTracks = from.getTracks(); TrakBox[] toTracks = to.getTracks(); int[][] matches = findMatches(fromTracks, toTracks); for (int i = 0; i < matches[0].length; i++) { TrakBox localTrack = to.importTrack(from, fromTracks[i]); if (matches[0][i] != -1) { insertTo(to, toTracks[matches[0][i]], localTrack, displayTv); } else { to.appendTrack(localTrack); shift(to, localTrack, displayTv); } } for (int i = 0; i < matches[1].length; i++) { if (matches[1][i] == -1) { spread(to, toTracks[i], displayTv, to.rescale(from.getDuration(), from.getTimescale())); } } to.updateDuration(); }
public MovieBox finalizeHeader() throws IOException { MovieBox movie = MovieBox.createMovieBox(); MovieHeaderBox mvhd = movieHeader(); movie.addFirst(mvhd); for (AbstractMP4MuxerTrack track : tracks) { Box trak = track.finish(mvhd); if (trak != null) movie.add(trak); } return movie; }
MovieBox movie = MP4Util.parseMovie(new File("path to file")); Assert.assertEquals(movie.getVideoTrack().getSampleEntries()[0].getFourcc(), "avc1"); for (TrakBox trakBox : movie.getAudioTracks()) { Assert.assertEquals(trakBox.getSampleEntries()[0].getFourcc(), "mp4a"); }
public void fixTimescale(int newTs) { int oldTs = getTimescale(); setTimescale(newTs); for (TrakBox trakBox : getTracks()) { trakBox.setDuration(rescale(trakBox.getDuration(), oldTs)); List<Edit> edits = trakBox.getEdits(); if (edits == null) continue; ListIterator<Edit> lit = edits.listIterator(); while (lit.hasNext()) { Edit edit = lit.next(); lit.set(new Edit(rescale(edit.getDuration(), oldTs), edit.getMediaTime(), edit.getRate())); } } setDuration(rescale(getDuration(), oldTs)); }
/** * Calculates and formats standard time as in Quicktime player * * @param movie * @param mediaFrameNo * @return */ public static String qtPlayerTime(MovieBox movie, int mediaFrameNo) { TrakBox videoTrack = movie.getVideoTrack(); long editedTv = mediaToEdited(videoTrack, frameToTimevalue(videoTrack, mediaFrameNo), movie.getTimescale()); int sec = (int) (editedTv / videoTrack.getTimescale()); return String.format("%02d", sec / 3600) + "_" + String.format("%02d", (sec % 3600) / 60) + "_" + String.format("%02d", sec % 60); }
public static int tv2QTFrameNo(MovieBox movie, long tv) { TrakBox videoTrack = movie.getVideoTrack(); TrakBox timecodeTrack = movie.getTimecodeTrack(); if (timecodeTrack != null && Box.findFirst(videoTrack, "tref", "tmcd") != null) { return timevalueToTimecodeFrame(timecodeTrack, new RationalLarge(tv, videoTrack.getTimescale()), movie.getTimescale()); } else { return timevalueToFrame(videoTrack, tv); } }
public List<Movie> cut(Movie movie, List<Slice> commands) { MovieBox moov = movie.getMoov(); TrakBox videoTrack = moov.getVideoTrack(); if (videoTrack != null && videoTrack.getTimescale() != moov.getTimescale()) moov.fixTimescale(videoTrack.getTimescale()); TrakBox[] tracks = moov.getTracks(); for (int i = 0; i < tracks.length; i++) { TrakBox trakBox = tracks[i]; for (Slice cut : commands) { MovieBox clone = (MovieBox) NodeBox.cloneBox(moov, 16 * 1024 * 1024, BoxFactory.getDefault()); for (TrakBox trakBox : clone.getTracks()) { selectInner(trakBox.getEdits(), cut, moov, trakBox); for (TrakBox trakBox : moov.getTracks()) { selectOuter(trakBox.getEdits(), commands, moov, trakBox); trakBox.setEdits(trakBox.getEdits()); movDuration = max(movDuration, trakBox.getDuration()); moov.setDuration(movDuration);
public Size getDisplaySize() { TrakBox videoTrack = getVideoTrack(); if (videoTrack == null) return null; ClearApertureBox clef = NodeBox.findFirst(videoTrack, ClearApertureBox.class, "tapt", "clef"); if (clef != null) { return applyMatrix(videoTrack, new Size((int) clef.getWidth(), (int) clef.getHeight())); } Box box = NodeBox.findFirst(videoTrack, SampleDescriptionBox.class, "mdia", "minf", "stbl", "stsd").getBoxes() .get(0); if (box == null || !(box instanceof VideoSampleEntry)) return null; VideoSampleEntry vs = (VideoSampleEntry) box; Rational par = videoTrack.getPAR(); return applyMatrix(videoTrack, new Size((int) ((vs.getWidth() * par.getNum()) / par.getDen()), (int) vs.getHeight())); }
public static WebOptimizedMP4Muxer withOldHeader(SeekableByteChannel output, Brand brand, MovieBox oldHeader) throws IOException { int size = (int) oldHeader.getHeader().getSize(); TrakBox vt = oldHeader.getVideoTrack(); SampleToChunkBox stsc = Box.findFirst(vt, SampleToChunkBox.class, "mdia", "minf", "stbl", "stsc"); size -= stsc.getSampleToChunk().length * 12; size += 12; ChunkOffsetsBox stco = Box.findFirst(vt, ChunkOffsetsBox.class, "mdia", "minf", "stbl", "stco"); if (stco != null) { size -= stco.getChunkOffsets().length << 2; size += vt.getFrameCount() << 3; } else { ChunkOffsets64Box co64 = Box.findFirst(vt, ChunkOffsets64Box.class, "mdia", "minf", "stbl", "co64"); size -= co64.getChunkOffsets().length << 3; size += vt.getFrameCount() << 3; } return new WebOptimizedMP4Muxer(output, brand, size + (size >> 1)); }
@Override public void apply(MovieBox mov) { TrakBox vt = mov.getVideoTrack(); TimeToSampleBox stts = vt.getStts(); TimeToSampleEntry[] entries = stts.getEntries(); long newDuration = totalDuration * mov.getTimescale() / vt.getTimescale(); mov.setDuration(newDuration); vt.setDuration(newDuration); } else {
public void updateDuration() { TrakBox[] tracks = getTracks(); long min = Integer.MAX_VALUE; for (TrakBox trakBox : tracks) { if (trakBox.getDuration() < min) min = trakBox.getDuration(); } getMovieHeader().setDuration(min); }
public long getDuration() { return getMovieHeader().getDuration(); }
public Size getStoredSize() { TrakBox videoTrack = getVideoTrack(); if (videoTrack == null) return null; EncodedPixelBox enof = NodeBox.findFirst(videoTrack, EncodedPixelBox.class, "tapt", "enof"); if (enof != null) { return new Size((int) enof.getWidth(), (int) enof.getHeight()); } Box box = NodeBox.findFirst(videoTrack, SampleDescriptionBox.class, "mdia", "minf", "stbl", "stsd").getBoxes() .get(0); if (box == null || !(box instanceof VideoSampleEntry)) return null; VideoSampleEntry vs = (VideoSampleEntry) box; return new Size((int) vs.getWidth(), (int) vs.getHeight()); }
public MovieBox() { super(new Header(fourcc())); }
public void apply(MovieBox mov) { TrakBox vt = mov.getVideoTrack(); MediaHeaderBox mdhd = NodeBox.findFirstPath(vt, MediaHeaderBox.class, Box.path("mdia.mdhd")); int oldTs = mdhd.getTimescale(); if (oldTs > ts) { throw new RuntimeException("Old timescale (" + oldTs + ") is greater then new timescale (" + ts + "), not touching."); } vt.fixMediaTimescale(ts); mov.fixTimescale(ts); }
@Override public void apply(MovieBox movie) { MetaBox meta1 = NodeBox.findFirst(movie, MetaBox.class, MetaBox.fourcc()); MetaBox meta2 = NodeBox.findFirstPath(movie, MetaBox.class, new String[] { "udta", MetaBox.fourcc() }); if (keyedMeta != null && keyedMeta.size() > 0) { if (meta1 == null) { meta1 = new MetaBox(); movie.add(meta1); } meta1.setKeyedMeta(keyedMeta); } if (itunesMeta != null && itunesMeta.size() > 0) { if (meta2 == null) { meta2 = new UdtaMetaBox(); NodeBox udta = NodeBox.findFirst(movie, NodeBox.class, "udta"); if (udta == null) { udta = new NodeBox(Header.createHeader("udta", 0)); movie.add(udta); } udta.add(meta2); } meta2.setItunesMeta(itunesMeta); } } };
public void fixTimescale(int newTs) { int oldTs = getTimescale(); setTimescale(newTs); for (TrakBox trakBox : getTracks()) { trakBox.setDuration(rescale(trakBox.getDuration(), oldTs)); List<Edit> edits = trakBox.getEdits(); if (edits == null) continue; ListIterator<Edit> lit = edits.listIterator(); while (lit.hasNext()) { Edit edit = lit.next(); lit.set(new Edit(rescale(edit.getDuration(), oldTs), edit.getMediaTime(), edit.getRate())); } } setDuration(rescale(getDuration(), oldTs)); }
/** * Calculates frame number as it shows in quicktime player * * @param movie * @param mediaFrameNo * @return */ public static int qtPlayerFrameNo(MovieBox movie, int mediaFrameNo) { TrakBox videoTrack = movie.getVideoTrack(); long editedTv = mediaToEdited(videoTrack, frameToTimevalue(videoTrack, mediaFrameNo), movie.getTimescale()); return tv2QTFrameNo(movie, editedTv); }