package org.mp4parser.muxer;
import org.mp4parser.Box;
import org.mp4parser.Container;
import org.mp4parser.boxes.iso14496.part12.*;
import org.mp4parser.boxes.iso23001.part7.AbstractSampleEncryptionBox;
import org.mp4parser.boxes.iso23001.part7.AbstractTrackEncryptionBox;
import org.mp4parser.boxes.iso23001.part7.CencSampleAuxiliaryDataFormat;
import org.mp4parser.muxer.tracks.CencEncryptedTrack;
import org.mp4parser.tools.Path;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
/**
* This track implementation is to be used when MP4 track is CENC encrypted.
*/
public class PiffMp4TrackImpl extends Mp4TrackImpl implements CencEncryptedTrack {
private List<CencSampleAuxiliaryDataFormat> sampleEncryptionEntries;
private UUID defaultKeyId;
/**
* Creates a track from a TrackBox and potentially fragments. Use <b>fragements parameter
* only</b> to supply additional fragments that are not located in the main file.
*
* @param trackId ID of the track to extract
* @param isofile the parsed MP4 file
* @param randomAccess the RandomAccessSource to read the samples from
* @param name an arbitrary naem to identify track later - e.g. filename
* @throws IOException if reading from underlying <code>DataSource</code> fails
*/
public PiffMp4TrackImpl(final long trackId, Container isofile, RandomAccessSource randomAccess, String name) throws IOException {
super(trackId, isofile, randomAccess, name);
TrackBox trackBox = null;
for (TrackBox box : Path.<TrackBox>getPaths(isofile, "moov/trak")) {
if (box.getTrackHeaderBox().getTrackId() == trackId) {
trackBox = box;
break;
}
}
SchemeTypeBox schm = Path.getPath(trackBox, "mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schm[0]");
assert schm != null && (schm.getSchemeType().equals("piff")) : "Track must be PIFF encrypted";
sampleEncryptionEntries = new ArrayList<CencSampleAuxiliaryDataFormat>();
final List<MovieExtendsBox> movieExtendsBoxes = Path.getPaths(isofile, "moov/mvex");
if (!movieExtendsBoxes.isEmpty()) {
for (MovieFragmentBox movieFragmentBox : isofile.getBoxes(MovieFragmentBox.class)) {
List<TrackFragmentBox> trafs = movieFragmentBox.getBoxes(TrackFragmentBox.class);
for (TrackFragmentBox traf : trafs) {
if (traf.getTrackFragmentHeaderBox().getTrackId() == trackId) {
AbstractTrackEncryptionBox tenc = Path.getPath(trackBox, "mdia[0]/minf[0]/stbl[0]/stsd[0]/enc.[0]/sinf[0]/schi[0]/uuid[0]");
assert tenc != null;
defaultKeyId = tenc.getDefault_KID();
long baseOffset;
if (traf.getTrackFragmentHeaderBox().hasBaseDataOffset()) {
baseOffset = traf.getTrackFragmentHeaderBox().getBaseDataOffset();
} else {
Iterator<Box> it = isofile.getBoxes().iterator();
baseOffset = 0;
for (Box b = it.next(); b != movieFragmentBox; b = it.next()) {
baseOffset += b.getSize();
}
}
List<TrackRunBox> truns = traf.getBoxes(TrackRunBox.class);
int sampleNo = 0;
AbstractSampleEncryptionBox senc = traf.getBoxes(AbstractSampleEncryptionBox.class).get(0);
for (CencSampleAuxiliaryDataFormat cencSampleAuxiliaryDataFormat : senc.getEntries()) {
sampleEncryptionEntries.add(cencSampleAuxiliaryDataFormat);
}
}
}
}
}
}
public UUID getDefaultKeyId() {
return defaultKeyId;
}
public boolean hasSubSampleEncryption() {
return false;
}
public List<CencSampleAuxiliaryDataFormat> getSampleEncryptionEntries() {
return sampleEncryptionEntries;
}
@Override
public String toString() {
return "PiffMp4TrackImpl{" +
"handler='" + getHandler() + '\'' +
'}';
}
@Override
public String getName() {
return "enc(" + super.getName() + ")";
}
}