![JAR search and dependency download from the Maven repository](/logo.png)
org.jcodec.containers.mp4.boxes.MovieBox Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jcodec Show documentation
Show all versions of jcodec Show documentation
Pure Java implementation of video/audio codecs and formats
package org.jcodec.containers.mp4.boxes;
import org.jcodec.common.model.Rational;
import org.jcodec.common.model.Size;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Creates MP4 file out of a set of samples
*
* @author The JCodec project
*
*/
public class MovieBox extends NodeBox {
public MovieBox(Header atom) {
super(atom);
}
public static String fourcc() {
return "moov";
}
public static MovieBox createMovieBox() {
return new MovieBox(new Header(fourcc()));
}
public TrakBox[] getTracks() {
return NodeBox.findAll(this, TrakBox.class, "trak");
}
public TrakBox getVideoTrack() {
TrakBox[] tracks = getTracks();
for (int i = 0; i < tracks.length; i++) {
TrakBox trakBox = tracks[i];
if (trakBox.isVideo())
return trakBox;
}
return null;
}
public TrakBox getTimecodeTrack() {
TrakBox[] tracks = getTracks();
for (int i = 0; i < tracks.length; i++) {
TrakBox trakBox = tracks[i];
if (trakBox.isTimecode())
return trakBox;
}
return null;
}
public int getTimescale() {
return getMovieHeader().getTimescale();
}
public long rescale(long tv, long ts) {
return (tv * getTimescale()) / ts;
}
public void fixTimescale(int newTs) {
int oldTs = getTimescale();
setTimescale(newTs);
TrakBox[] tracks = getTracks();
for (int i = 0; i < tracks.length; i++) {
TrakBox trakBox = tracks[i];
trakBox.setDuration(rescale(trakBox.getDuration(), oldTs));
List edits = trakBox.getEdits();
if (edits == null)
continue;
ListIterator 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));
}
private void setTimescale(int newTs) {
NodeBox.findFirst(this, MovieHeaderBox.class, "mvhd").setTimescale(newTs);
}
public void setDuration(long movDuration) {
getMovieHeader().setDuration(movDuration);
}
private MovieHeaderBox getMovieHeader() {
return NodeBox.findFirst(this, MovieHeaderBox.class, "mvhd");
}
public List getAudioTracks() {
ArrayList result = new ArrayList();
TrakBox[] tracks = getTracks();
for (int i = 0; i < tracks.length; i++) {
TrakBox trakBox = tracks[i];
if (trakBox.isAudio())
result.add(trakBox);
}
return result;
}
public long getDuration() {
return getMovieHeader().getDuration();
}
public TrakBox importTrack(MovieBox movie, TrakBox track) {
TrakBox newTrack = (TrakBox) NodeBox.cloneBox(track, 1024 * 1024, factory);
List edits = newTrack.getEdits();
ArrayList result = new ArrayList();
if (edits != null) {
for (Edit edit : edits) {
result.add(new Edit(rescale(edit.getDuration(), movie.getTimescale()), edit.getMediaTime(), edit
.getRate()));
}
}
newTrack.setEdits(result);
return newTrack;
}
public void appendTrack(TrakBox newTrack) {
newTrack.getTrackHeader().setNo(getMovieHeader().getNextTrackId());
getMovieHeader().setNextTrackId(getMovieHeader().getNextTrackId() + 1);
boxes.add(newTrack);
}
public boolean isPureRefMovie(MovieBox movie) {
boolean pureRef = true;
TrakBox[] tracks = movie.getTracks();
for (int i = 0; i < tracks.length; i++) {
TrakBox trakBox = tracks[i];
pureRef &= trakBox.isPureRef();
}
return pureRef;
}
public void updateDuration() {
TrakBox[] tracks = getTracks();
long min = Integer.MAX_VALUE;
for (int i = 0; i < tracks.length; i++) {
TrakBox trakBox = tracks[i];
if (trakBox.getDuration() < min)
min = trakBox.getDuration();
}
getMovieHeader().setDuration(min);
}
public Size getDisplaySize() {
TrakBox videoTrack = getVideoTrack();
if (videoTrack == null)
return null;
ClearApertureBox clef = NodeBox.findFirstPath(videoTrack, ClearApertureBox.class, Box.path("tapt.clef"));
if (clef != null) {
return applyMatrix(videoTrack, new Size((int) clef.getWidth(), (int) clef.getHeight()));
}
Box box = NodeBox.findFirstPath(videoTrack, SampleDescriptionBox.class, Box.path("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()));
}
private Size applyMatrix(TrakBox videoTrack, Size size) {
int[] matrix = videoTrack.getTrackHeader().getMatrix();
return new Size((int) ((double) size.getWidth() * matrix[0] / 65536), (int) ((double) size.getHeight()
* matrix[4] / 65536));
}
public Size getStoredSize() {
TrakBox videoTrack = getVideoTrack();
if (videoTrack == null)
return null;
EncodedPixelBox enof = NodeBox.findFirstPath(videoTrack, EncodedPixelBox.class, Box.path("tapt.enof"));
if (enof != null) {
return new Size((int) enof.getWidth(), (int) enof.getHeight());
}
Box box = NodeBox.findFirstPath(videoTrack, SampleDescriptionBox.class, Box.path("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());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy