www in docker support
This commit is contained in:
parent
539a848e95
commit
c227fce036
2145 changed files with 399596 additions and 58 deletions
|
|
@ -0,0 +1,88 @@
|
|||
package org.jcodec.containers.mxf;
|
||||
|
||||
import org.jcodec.common.Codec;
|
||||
import org.jcodec.containers.mxf.model.UL;
|
||||
|
||||
public class MXFCodec {
|
||||
private final UL ul;
|
||||
|
||||
private final Codec codec;
|
||||
|
||||
static MXFCodec mxfCodec(String ul, Codec codec) {
|
||||
return new MXFCodec(UL.newUL(ul), codec);
|
||||
}
|
||||
|
||||
MXFCodec(UL ul, Codec codec) {
|
||||
this.ul = ul;
|
||||
this.codec = codec;
|
||||
}
|
||||
|
||||
public UL getUl() {
|
||||
return this.ul;
|
||||
}
|
||||
|
||||
public Codec getCodec() {
|
||||
return this.codec;
|
||||
}
|
||||
|
||||
public static final MXFCodec MPEG2_XDCAM = mxfCodec("06.0E.2B.34.04.01.01.03.04.01.02.02.01.04.03", Codec.MPEG2);
|
||||
|
||||
public static final MXFCodec MPEG2_ML = mxfCodec("06.0E.2B.34.04.01.01.03.04.01.02.02.01.01.11", Codec.MPEG2);
|
||||
|
||||
public static final MXFCodec MPEG2_D10_PAL = mxfCodec("06.0E.2B.34.04.01.01.01.04.01.02.02.01.02.01.01", Codec.MPEG2);
|
||||
|
||||
public static final MXFCodec MPEG2_HL = mxfCodec("06.0E.2B.34.04.01.01.03.04.01.02.02.01.03.03", Codec.MPEG2);
|
||||
|
||||
public static final MXFCodec MPEG2_HL_422_I = mxfCodec("06.0E.2B.34.04.01.01.03.04.01.02.02.01.04.02", Codec.MPEG2);
|
||||
|
||||
public static final MXFCodec MPEG4_XDCAM_PROXY = mxfCodec("06.0E.2B.34.04.01.01.03.04.01.02.02.01.20.02.03", Codec.MPEG4);
|
||||
|
||||
public static final MXFCodec DV_25_PAL = mxfCodec("06.0E.2B.34.04.01.01.01.04.01.02.02.02.01.02", Codec.DV);
|
||||
|
||||
public static final MXFCodec JPEG2000 = mxfCodec("06.0E.2B.34.04.01.01.07.04.01.02.02.03.01.01", Codec.J2K);
|
||||
|
||||
public static final MXFCodec VC1 = mxfCodec("06.0e.2b.34.04.01.01.0A.04.01.02.02.04", Codec.VC1);
|
||||
|
||||
public static final MXFCodec RAW = mxfCodec("06.0E.2B.34.04.01.01.01.04.01.02.01.7F", null);
|
||||
|
||||
public static final MXFCodec RAW_422 = mxfCodec("06.0E.2B.34.04.01.01.0A.04.01.02.01.01.02.01", null);
|
||||
|
||||
public static final MXFCodec VC3_DNXHD = mxfCodec("06.0E.2B.34.04.01.01.01.04.01.02.02.03.02", Codec.VC3);
|
||||
|
||||
public static final MXFCodec VC3_DNXHD_2 = mxfCodec("06.0E.2B.34.04.01.01.01.04.01.02.02.71", Codec.VC3);
|
||||
|
||||
public static final MXFCodec VC3_DNXHD_AVID = mxfCodec("06.0E.2B.34.04.01.01.01.0E.04.02.01.02.04.01", Codec.VC3);
|
||||
|
||||
public static final MXFCodec AVC_INTRA = mxfCodec("06.0E.2B.34.04.01.01.0A.04.01.02.02.01.32", Codec.H264);
|
||||
|
||||
public static final MXFCodec AVC_SPSPPS = mxfCodec("06.0E.2B.34.04.01.01.0A.04.01.02.02.01.31.11.01", Codec.H264);
|
||||
|
||||
public static final MXFCodec V210 = mxfCodec("06.0E.2B.34.04.01.01.0A.04.01.02.01.01.02.02", Codec.V210);
|
||||
|
||||
public static final MXFCodec PRORES_AVID = mxfCodec("06.0E.2B.34.04.01.01.01.0E.04.02.01.02.11", Codec.PRORES);
|
||||
|
||||
public static final MXFCodec PRORES = mxfCodec("06.0E.2B.34.04.01.01.0D.04.01.02.02.03.06", Codec.PRORES);
|
||||
|
||||
public static final MXFCodec PCM_S16LE_1 = mxfCodec("06.0E.2B.34.04.01.01.01.04.02.02.01", null);
|
||||
|
||||
public static final MXFCodec PCM_S16LE_3 = mxfCodec("06.0E.2B.34.04.01.01.01.04.02.02.01.01", null);
|
||||
|
||||
public static final MXFCodec PCM_S16LE_2 = mxfCodec("06.0E.2B.34.04.01.01.01.04.02.02.01.7F", null);
|
||||
|
||||
public static final MXFCodec PCM_S16BE = mxfCodec("06.0E.2B.34.04.01.01.07.04.02.02.01.7E", null);
|
||||
|
||||
public static final MXFCodec PCM_ALAW = mxfCodec("06.0E.2B.34.04.01.01.04.04.02.02.02.03.01.01", Codec.ALAW);
|
||||
|
||||
public static final MXFCodec AC3 = mxfCodec("06.0E.2B.34.04.01.01.01.04.02.02.02.03.02.01", Codec.AC3);
|
||||
|
||||
public static final MXFCodec MP2 = mxfCodec("06.0E.2B.34.04.01.01.01.04.02.02.02.03.02.05", Codec.MP3);
|
||||
|
||||
public static final MXFCodec UNKNOWN = new MXFCodec(new UL(new byte[0]), null);
|
||||
|
||||
public static MXFCodec[] values() {
|
||||
return new MXFCodec[] {
|
||||
MPEG2_XDCAM, MPEG2_ML, MPEG2_D10_PAL, MPEG2_HL, MPEG2_HL_422_I, MPEG4_XDCAM_PROXY, DV_25_PAL, JPEG2000, VC1, RAW,
|
||||
RAW_422, VC3_DNXHD, VC3_DNXHD_2, VC3_DNXHD_AVID, AVC_INTRA, AVC_SPSPPS, V210, PRORES_AVID, PRORES, PCM_S16LE_1,
|
||||
PCM_S16LE_3, PCM_S16LE_2, PCM_S16BE, PCM_ALAW, AC3, MP2 };
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package org.jcodec.containers.mxf;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.jcodec.containers.mxf.model.AES3PCMDescriptor;
|
||||
import org.jcodec.containers.mxf.model.CDCIEssenceDescriptor;
|
||||
import org.jcodec.containers.mxf.model.ContentStorage;
|
||||
import org.jcodec.containers.mxf.model.EssenceContainerData;
|
||||
import org.jcodec.containers.mxf.model.FileDescriptor;
|
||||
import org.jcodec.containers.mxf.model.GenericDataEssenceDescriptor;
|
||||
import org.jcodec.containers.mxf.model.GenericDescriptor;
|
||||
import org.jcodec.containers.mxf.model.GenericPictureEssenceDescriptor;
|
||||
import org.jcodec.containers.mxf.model.GenericSoundEssenceDescriptor;
|
||||
import org.jcodec.containers.mxf.model.Identification;
|
||||
import org.jcodec.containers.mxf.model.IndexSegment;
|
||||
import org.jcodec.containers.mxf.model.J2KPictureDescriptor;
|
||||
import org.jcodec.containers.mxf.model.MPEG2VideoDescriptor;
|
||||
import org.jcodec.containers.mxf.model.MXFMetadata;
|
||||
import org.jcodec.containers.mxf.model.MXFPartitionPack;
|
||||
import org.jcodec.containers.mxf.model.MaterialPackage;
|
||||
import org.jcodec.containers.mxf.model.Preface;
|
||||
import org.jcodec.containers.mxf.model.RGBAEssenceDescriptor;
|
||||
import org.jcodec.containers.mxf.model.Sequence;
|
||||
import org.jcodec.containers.mxf.model.SourceClip;
|
||||
import org.jcodec.containers.mxf.model.SourcePackage;
|
||||
import org.jcodec.containers.mxf.model.TimecodeComponent;
|
||||
import org.jcodec.containers.mxf.model.TimelineTrack;
|
||||
import org.jcodec.containers.mxf.model.UL;
|
||||
import org.jcodec.containers.mxf.model.WaveAudioDescriptor;
|
||||
|
||||
public class MXFConst {
|
||||
public static final UL HEADER_PARTITION_KLV = UL.newUL("06.0e.2b.34.02.05.01.01.0d.01.02.01.01.02");
|
||||
|
||||
public static final UL INDEX_KLV = UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.02.01.01.10.01.00");
|
||||
|
||||
public static final UL GENERIC_DESCRIPTOR_KLV = UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01");
|
||||
|
||||
public static Map<UL, Class<? extends MXFMetadata>> klMetadata = new HashMap<>();
|
||||
|
||||
static {
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.18.00"), ContentStorage.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.37.00"), SourcePackage.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.0F.00"), Sequence.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0D.01.01.01.01.01.2F.00"), Preface.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.30.00"), Identification.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.11.00"), SourceClip.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.23.00"), EssenceContainerData.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.3A.00"), TimelineTrack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.3B.00"), TimelineTrack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.36.00"), MaterialPackage.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.02.01.01.10.01.00"), IndexSegment.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.44.00"), GenericDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.5b.00"), GenericDataEssenceDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.5b.00"), GenericDataEssenceDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.5c.00"), GenericDataEssenceDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.43.00"), GenericDataEssenceDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.42.00"), GenericSoundEssenceDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.28.00"), CDCIEssenceDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.29.00"), RGBAEssenceDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.51.00"), MPEG2VideoDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.48.00"), WaveAudioDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.25.00"), FileDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.27.00"), GenericPictureEssenceDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0d.01.01.01.01.01.47.00"), AES3PCMDescriptor.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.05.01.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.02.01.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.02.02.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.02.03.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.02.04.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.03.01.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.03.02.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.03.03.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.03.04.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.04.02.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.05.01.01.0d.01.02.01.01.04.04.00"), MXFPartitionPack.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.02.53.01.01.0D.01.01.01.01.01.14.00"), TimecodeComponent.class);
|
||||
klMetadata.put(UL.newUL("06.0E.2B.34.01.01.01.02.03.01.02.10.01.00.00.00"), KLVFill.class);
|
||||
klMetadata.put(UL.newUL("06.0e.2b.34.02.53.01.01.0d.01.01.01.01.01.5a.00"), J2KPictureDescriptor.class);
|
||||
}
|
||||
|
||||
public static class KLVFill extends MXFMetadata {
|
||||
public KLVFill(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
public void readBuf(ByteBuffer bb) {}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,585 @@
|
|||
package org.jcodec.containers.mxf;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.jcodec.api.NotSupportedException;
|
||||
import org.jcodec.common.DemuxerTrackMeta;
|
||||
import org.jcodec.common.SeekableDemuxerTrack;
|
||||
import org.jcodec.common.TrackType;
|
||||
import org.jcodec.common.VideoCodecMeta;
|
||||
import org.jcodec.common.io.FileChannelWrapper;
|
||||
import org.jcodec.common.io.NIOUtils;
|
||||
import org.jcodec.common.io.SeekableByteChannel;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
import org.jcodec.common.model.ColorSpace;
|
||||
import org.jcodec.common.model.Packet;
|
||||
import org.jcodec.common.model.Rational;
|
||||
import org.jcodec.common.model.Size;
|
||||
import org.jcodec.common.model.TapeTimecode;
|
||||
import org.jcodec.containers.mxf.model.FileDescriptor;
|
||||
import org.jcodec.containers.mxf.model.GenericDescriptor;
|
||||
import org.jcodec.containers.mxf.model.GenericPictureEssenceDescriptor;
|
||||
import org.jcodec.containers.mxf.model.GenericSoundEssenceDescriptor;
|
||||
import org.jcodec.containers.mxf.model.IndexSegment;
|
||||
import org.jcodec.containers.mxf.model.KLV;
|
||||
import org.jcodec.containers.mxf.model.MXFMetadata;
|
||||
import org.jcodec.containers.mxf.model.MXFPartition;
|
||||
import org.jcodec.containers.mxf.model.MXFUtil;
|
||||
import org.jcodec.containers.mxf.model.SourceClip;
|
||||
import org.jcodec.containers.mxf.model.TimecodeComponent;
|
||||
import org.jcodec.containers.mxf.model.TimelineTrack;
|
||||
import org.jcodec.containers.mxf.model.UL;
|
||||
import org.jcodec.containers.mxf.model.WaveAudioDescriptor;
|
||||
import org.jcodec.platform.Platform;
|
||||
|
||||
public class MXFDemuxer {
|
||||
protected List<MXFMetadata> metadata;
|
||||
|
||||
protected MXFPartition header;
|
||||
|
||||
protected List<MXFPartition> partitions;
|
||||
|
||||
protected List<IndexSegment> indexSegments;
|
||||
|
||||
protected SeekableByteChannel ch;
|
||||
|
||||
protected MXFDemuxerTrack[] tracks;
|
||||
|
||||
protected int totalFrames;
|
||||
|
||||
protected double duration;
|
||||
|
||||
protected TimecodeComponent timecode;
|
||||
|
||||
public MXFDemuxer(SeekableByteChannel ch) throws IOException {
|
||||
this.ch = ch;
|
||||
ch.setPosition(0L);
|
||||
parseHeader(ch);
|
||||
findIndex();
|
||||
this.tracks = findTracks();
|
||||
this.timecode = MXFUtil.<TimecodeComponent>findMeta(this.metadata, TimecodeComponent.class);
|
||||
}
|
||||
|
||||
public static final class OP {
|
||||
public static final OP OP1a = new OP(1, 1);
|
||||
|
||||
public static final OP OP1b = new OP(1, 2);
|
||||
|
||||
public static final OP OP1c = new OP(1, 3);
|
||||
|
||||
public static final OP OP2a = new OP(2, 1);
|
||||
|
||||
public static final OP OP2b = new OP(2, 2);
|
||||
|
||||
public static final OP OP2c = new OP(2, 3);
|
||||
|
||||
public static final OP OP3a = new OP(3, 1);
|
||||
|
||||
public static final OP OP3b = new OP(3, 2);
|
||||
|
||||
public static final OP OP3c = new OP(3, 3);
|
||||
|
||||
public static final OP OPAtom = new OP(16, 0);
|
||||
|
||||
private static final OP[] _values = new OP[] { OP1a, OP1b, OP1c, OP2a, OP2b, OP2c, OP3a, OP3b, OP3c, OPAtom };
|
||||
|
||||
public int major;
|
||||
|
||||
public int minor;
|
||||
|
||||
private OP(int major, int minor) {
|
||||
this.major = major;
|
||||
this.minor = minor;
|
||||
}
|
||||
|
||||
public static OP[] values() {
|
||||
return _values;
|
||||
}
|
||||
}
|
||||
|
||||
public OP getOp() {
|
||||
UL op = this.header.getPack().getOp();
|
||||
OP[] values = OP.values();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
OP op2 = values[i];
|
||||
if (op.get(12) == op2.major && op.get(13) == op2.minor)
|
||||
return op2;
|
||||
}
|
||||
return OP.OPAtom;
|
||||
}
|
||||
|
||||
public MXFDemuxerTrack[] findTracks() throws IOException {
|
||||
List<TimelineTrack> _tracks = MXFUtil.findAllMeta(this.metadata, TimelineTrack.class);
|
||||
List<FileDescriptor> descriptors = MXFUtil.findAllMeta(this.metadata, FileDescriptor.class);
|
||||
Map<Integer, MXFDemuxerTrack> tracks = new LinkedHashMap<>();
|
||||
for (TimelineTrack track : _tracks) {
|
||||
if (track.getTrackId() == 0 || track.getTrackNumber() == 0) {
|
||||
Logger.warn("trackId == 0 || trackNumber == 0");
|
||||
continue;
|
||||
}
|
||||
int trackId = track.getTrackId();
|
||||
if (tracks.containsKey(Integer.valueOf(trackId))) {
|
||||
Logger.warn("duplicate trackId " + trackId);
|
||||
continue;
|
||||
}
|
||||
FileDescriptor descriptor = findDescriptor(descriptors, track.getTrackId());
|
||||
if (descriptor == null) {
|
||||
Logger.warn("No generic descriptor for track: " + track.getTrackId());
|
||||
if (descriptors.size() == 1 && descriptors.get(0).getLinkedTrackId() == 0)
|
||||
descriptor = descriptors.get(0);
|
||||
}
|
||||
if (descriptor == null) {
|
||||
Logger.warn("Track without descriptor: " + track.getTrackId());
|
||||
continue;
|
||||
}
|
||||
int trackNumber = track.getTrackNumber();
|
||||
UL ul = UL.newULFromInts(new int[] {
|
||||
6, 14, 43, 52, 1, 2, 1, 1, 13, 1,
|
||||
3, 1, trackNumber >>> 24 & 0xFF, trackNumber >>> 16 & 0xFF, trackNumber >>> 8 & 0xFF, trackNumber & 0xFF });
|
||||
MXFDemuxerTrack dt = createTrack(ul, track, descriptor);
|
||||
if (dt.getCodec() != null || descriptor instanceof WaveAudioDescriptor)
|
||||
tracks.put(Integer.valueOf(trackId), dt);
|
||||
}
|
||||
return (MXFDemuxerTrack[])tracks.values().toArray(new MXFDemuxerTrack[tracks.size()]);
|
||||
}
|
||||
|
||||
public static FileDescriptor findDescriptor(List<FileDescriptor> descriptors, int trackId) {
|
||||
for (FileDescriptor descriptor : descriptors) {
|
||||
if (descriptor.getLinkedTrackId() == trackId)
|
||||
return descriptor;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected MXFDemuxerTrack createTrack(UL ul, TimelineTrack track, GenericDescriptor descriptor) throws IOException {
|
||||
return new MXFDemuxerTrack(this, ul, track, descriptor);
|
||||
}
|
||||
|
||||
public List<IndexSegment> getIndexes() {
|
||||
return this.indexSegments;
|
||||
}
|
||||
|
||||
public List<MXFPartition> getEssencePartitions() {
|
||||
return this.partitions;
|
||||
}
|
||||
|
||||
public TimecodeComponent getTimecode() {
|
||||
return this.timecode;
|
||||
}
|
||||
|
||||
public void parseHeader(SeekableByteChannel ff) throws IOException {
|
||||
this.header = readHeaderPartition(ff);
|
||||
this.metadata = new ArrayList<>();
|
||||
this.partitions = new ArrayList<>();
|
||||
long nextPartition = ff.size();
|
||||
ff.setPosition(this.header.getPack().getFooterPartition());
|
||||
do {
|
||||
long thisPartition = ff.position();
|
||||
KLV kl = KLV.readKL(ff);
|
||||
ByteBuffer fetchFrom = NIOUtils.fetchFromChannel(ff, (int)kl.len);
|
||||
this.header = MXFPartition.read(kl.key, fetchFrom, ff.position() - kl.offset, nextPartition);
|
||||
if (this.header.getPack().getNbEssenceContainers() > 0)
|
||||
this.partitions.add(0, this.header);
|
||||
this.metadata.addAll(0, readPartitionMeta(ff, this.header));
|
||||
ff.setPosition(this.header.getPack().getPrevPartition());
|
||||
nextPartition = thisPartition;
|
||||
} while (this.header.getPack().getThisPartition() != 0L);
|
||||
}
|
||||
|
||||
public static List<MXFMetadata> readPartitionMeta(SeekableByteChannel ff, MXFPartition header) throws IOException {
|
||||
long basePos = ff.position();
|
||||
List<MXFMetadata> local = new ArrayList<>();
|
||||
ByteBuffer metaBuffer = NIOUtils.fetchFromChannel(ff, (int)Math.max(0L, header.getEssenceFilePos() - basePos));
|
||||
KLV kl;
|
||||
while (metaBuffer.hasRemaining() && (kl = KLV.readKLFromBuffer(metaBuffer, basePos)) != null &&
|
||||
(long)metaBuffer.remaining() >= kl.len) {
|
||||
MXFMetadata meta = parseMeta(kl.key, NIOUtils.read(metaBuffer, (int)kl.len));
|
||||
if (meta != null)
|
||||
local.add(meta);
|
||||
}
|
||||
return local;
|
||||
}
|
||||
|
||||
public static MXFPartition readHeaderPartition(SeekableByteChannel ff) throws IOException {
|
||||
MXFPartition header = null;
|
||||
KLV kl;
|
||||
while ((kl = KLV.readKL(ff)) != null) {
|
||||
if (MXFConst.HEADER_PARTITION_KLV.equals(kl.key)) {
|
||||
ByteBuffer data = NIOUtils.fetchFromChannel(ff, (int)kl.len);
|
||||
header = MXFPartition.read(kl.key, data, ff.position() - kl.offset, 0L);
|
||||
break;
|
||||
}
|
||||
ff.setPosition(ff.position() + kl.len);
|
||||
}
|
||||
return header;
|
||||
}
|
||||
|
||||
private static MXFMetadata parseMeta(UL ul, ByteBuffer _bb) {
|
||||
Class<? extends MXFMetadata> class1 = MXFConst.klMetadata.get(ul);
|
||||
if (class1 == null) {
|
||||
Logger.warn("Unknown metadata piece: " + String.valueOf(ul));
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
MXFMetadata meta = Platform.newInstance(class1, new Object[] { ul });
|
||||
meta.readBuf(_bb);
|
||||
return meta;
|
||||
} catch (Exception e) {
|
||||
Logger.warn("Unknown metadata piece: " + String.valueOf(ul));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void findIndex() {
|
||||
this.indexSegments = new ArrayList<>();
|
||||
for (MXFMetadata meta : this.metadata) {
|
||||
if (meta instanceof IndexSegment) {
|
||||
IndexSegment is = (IndexSegment)meta;
|
||||
this.indexSegments.add(is);
|
||||
this.totalFrames = (int)((long)this.totalFrames + is.getIndexDuration());
|
||||
this.duration += (double)is.getIndexEditRateDen() * (double)is.getIndexDuration() / (double)is.getIndexEditRateNum();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MXFDemuxerTrack[] getTracks() {
|
||||
return this.tracks;
|
||||
}
|
||||
|
||||
public MXFDemuxerTrack getVideoTrack() {
|
||||
for (MXFDemuxerTrack track : this.tracks) {
|
||||
if (track.isVideo())
|
||||
return track;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public MXFDemuxerTrack[] getAudioTracks() {
|
||||
List<MXFDemuxerTrack> audio = new ArrayList<>();
|
||||
for (MXFDemuxerTrack track : this.tracks) {
|
||||
if (track.isAudio())
|
||||
audio.add(track);
|
||||
}
|
||||
return audio.<MXFDemuxerTrack>toArray(new MXFDemuxerTrack[0]);
|
||||
}
|
||||
|
||||
public static class MXFDemuxerTrack implements SeekableDemuxerTrack {
|
||||
private UL essenceUL;
|
||||
|
||||
private int dataLen;
|
||||
|
||||
private int indexSegmentIdx;
|
||||
|
||||
private int indexSegmentSubIdx;
|
||||
|
||||
private int frameNo;
|
||||
|
||||
private long pts;
|
||||
|
||||
private int partIdx;
|
||||
|
||||
private long partEssenceOffset;
|
||||
|
||||
private GenericDescriptor descriptor;
|
||||
|
||||
private TimelineTrack track;
|
||||
|
||||
private boolean video;
|
||||
|
||||
private boolean audio;
|
||||
|
||||
private MXFCodec codec;
|
||||
|
||||
private int audioFrameDuration;
|
||||
|
||||
private int audioTimescale;
|
||||
|
||||
private MXFDemuxer demuxer;
|
||||
|
||||
public MXFDemuxerTrack(MXFDemuxer demuxer, UL essenceUL, TimelineTrack track, GenericDescriptor descriptor) throws IOException {
|
||||
this.demuxer = demuxer;
|
||||
this.essenceUL = essenceUL;
|
||||
this.track = track;
|
||||
this.descriptor = descriptor;
|
||||
if (descriptor instanceof GenericPictureEssenceDescriptor) {
|
||||
this.video = true;
|
||||
} else if (descriptor instanceof GenericSoundEssenceDescriptor) {
|
||||
this.audio = true;
|
||||
}
|
||||
this.codec = resolveCodec();
|
||||
if (this.codec != null || descriptor instanceof WaveAudioDescriptor) {
|
||||
Logger.warn("Track type: " + this.video + ", " + this.audio);
|
||||
if (this.audio && descriptor instanceof WaveAudioDescriptor) {
|
||||
WaveAudioDescriptor wave = (WaveAudioDescriptor)descriptor;
|
||||
cacheAudioFrameSizes(demuxer.ch);
|
||||
this.audioFrameDuration = this.dataLen / ((wave.getQuantizationBits() >> 3) * wave.getChannelCount());
|
||||
this.audioTimescale = (int)wave.getAudioSamplingRate().scalar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAudio() {
|
||||
return this.audio;
|
||||
}
|
||||
|
||||
public boolean isVideo() {
|
||||
return this.video;
|
||||
}
|
||||
|
||||
public double getDuration() {
|
||||
return this.demuxer.duration;
|
||||
}
|
||||
|
||||
public int getNumFrames() {
|
||||
return this.demuxer.totalFrames;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.track.getName();
|
||||
}
|
||||
|
||||
private void cacheAudioFrameSizes(SeekableByteChannel ch) throws IOException {
|
||||
for (MXFPartition mxfPartition : this.demuxer.partitions) {
|
||||
if (mxfPartition.getEssenceLength() > 0L) {
|
||||
KLV kl;
|
||||
ch.setPosition(mxfPartition.getEssenceFilePos());
|
||||
do {
|
||||
kl = KLV.readKL(ch);
|
||||
if (kl == null)
|
||||
break;
|
||||
ch.setPosition(ch.position() + kl.len);
|
||||
} while (!this.essenceUL.equals(kl.key));
|
||||
if (kl != null && this.essenceUL.equals(kl.key)) {
|
||||
this.dataLen = (int)kl.len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Packet nextFrame() throws IOException {
|
||||
Packet result;
|
||||
if (this.indexSegmentIdx >= this.demuxer.indexSegments.size())
|
||||
return null;
|
||||
IndexSegment seg = this.demuxer.indexSegments.get(this.indexSegmentIdx);
|
||||
long[] off = seg.getIe().getFileOff();
|
||||
int erDen = seg.getIndexEditRateNum();
|
||||
int erNum = seg.getIndexEditRateDen();
|
||||
long frameEssenceOffset = off[this.indexSegmentSubIdx];
|
||||
byte toff = seg.getIe().getDisplayOff()[this.indexSegmentSubIdx];
|
||||
boolean kf = (seg.getIe().getKeyFrameOff()[this.indexSegmentSubIdx] == 0);
|
||||
while (frameEssenceOffset >= this.partEssenceOffset + this.demuxer.partitions.get(this.partIdx).getEssenceLength() && this.partIdx <
|
||||
this.demuxer.partitions.size() - 1) {
|
||||
this.partEssenceOffset += this.demuxer.partitions.get(this.partIdx).getEssenceLength();
|
||||
this.partIdx++;
|
||||
}
|
||||
long frameFileOffset = frameEssenceOffset - this.partEssenceOffset +
|
||||
this.demuxer.partitions.get(this.partIdx).getEssenceFilePos();
|
||||
if (!this.audio) {
|
||||
result = readPacket(frameFileOffset, this.dataLen, this.pts + (long)(erNum * toff), erDen, erNum, this.frameNo++, kf);
|
||||
this.pts += (long)erNum;
|
||||
} else {
|
||||
result = readPacket(frameFileOffset, this.dataLen, this.pts, this.audioTimescale, this.audioFrameDuration, this.frameNo++, kf);
|
||||
this.pts += (long)this.audioFrameDuration;
|
||||
}
|
||||
this.indexSegmentSubIdx++;
|
||||
if (this.indexSegmentSubIdx >= off.length) {
|
||||
this.indexSegmentIdx++;
|
||||
this.indexSegmentSubIdx = 0;
|
||||
if (this.dataLen == 0 && this.indexSegmentIdx < this.demuxer.indexSegments.size()) {
|
||||
IndexSegment nseg = this.demuxer.indexSegments.get(this.indexSegmentIdx);
|
||||
this.pts = this.pts * (long)nseg.getIndexEditRateNum() / (long)erDen;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public MXFDemuxer.MXFPacket readPacket(long off, int len, long pts, int timescale, int duration, int frameNo, boolean kf) throws IOException {
|
||||
assert false : "Decompilation failed at line #420 -> offsets [0]";
|
||||
assert false : "Decompilation failed at line #421 -> offsets [9]";
|
||||
assert false : "Decompilation failed at line #422 -> offsets [15]";
|
||||
assert false : "Decompilation failed at line #424 -> offsets [24]";
|
||||
assert false : "Decompilation failed at line #425 -> offsets [31]";
|
||||
assert false : "Decompilation failed at line #426 -> offsets [51]";
|
||||
assert false : "Decompilation failed at line #427 -> offsets [72]";
|
||||
assert false : "Decompilation failed at line #430 -> offsets [82, 154]";
|
||||
assert false : "Decompilation failed at line #431 -> offsets [102]";
|
||||
assert false : "Decompilation failed at line #432 -> offsets [127]";
|
||||
assert false : "Decompilation failed at line #433 -> offsets [150]";
|
||||
assert false : "Decompilation failed at line #434 -> offsets [155]";
|
||||
}
|
||||
|
||||
public boolean gotoFrame(long frameNo) {
|
||||
if (frameNo == (long)this.frameNo)
|
||||
return true;
|
||||
this.indexSegmentSubIdx = (int)frameNo;
|
||||
this.indexSegmentIdx = 0;
|
||||
for (; this.indexSegmentIdx < this.demuxer.indexSegments.size() && (long)this.indexSegmentSubIdx >= this.demuxer.indexSegments.get(this.indexSegmentIdx)
|
||||
.getIndexDuration(); this.indexSegmentIdx++)
|
||||
this.indexSegmentSubIdx = (int)((long)this.indexSegmentSubIdx - this.demuxer.indexSegments.get(this.indexSegmentIdx).getIndexDuration());
|
||||
this.indexSegmentSubIdx = Math.min(this.indexSegmentSubIdx,
|
||||
(int)this.demuxer.indexSegments.get(this.indexSegmentIdx).getIndexDuration());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean gotoSyncFrame(long frameNo) {
|
||||
if (!gotoFrame(frameNo))
|
||||
return false;
|
||||
IndexSegment seg = this.demuxer.indexSegments.get(this.indexSegmentIdx);
|
||||
byte kfOff = seg.getIe().getKeyFrameOff()[this.indexSegmentSubIdx];
|
||||
return gotoFrame(frameNo + (long)kfOff);
|
||||
}
|
||||
|
||||
public long getCurFrame() {
|
||||
return (long)this.frameNo;
|
||||
}
|
||||
|
||||
public void seek(double second) {
|
||||
throw new NotSupportedException("");
|
||||
}
|
||||
|
||||
public UL getEssenceUL() {
|
||||
return this.essenceUL;
|
||||
}
|
||||
|
||||
public GenericDescriptor getDescriptor() {
|
||||
return this.descriptor;
|
||||
}
|
||||
|
||||
public MXFCodec getCodec() {
|
||||
return this.codec;
|
||||
}
|
||||
|
||||
private MXFCodec resolveCodec() {
|
||||
UL codecUL;
|
||||
if (this.video) {
|
||||
codecUL = ((GenericPictureEssenceDescriptor)this.descriptor).getPictureEssenceCoding();
|
||||
} else if (this.audio) {
|
||||
codecUL = ((GenericSoundEssenceDescriptor)this.descriptor).getSoundEssenceCompression();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
MXFCodec[] values = MXFCodec.values();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
MXFCodec codec = values[i];
|
||||
if (codec.getUl().equals(codecUL))
|
||||
return codec;
|
||||
}
|
||||
Logger.warn("Unknown codec: " + String.valueOf(codecUL));
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getTrackId() {
|
||||
return this.track.getTrackId();
|
||||
}
|
||||
|
||||
public DemuxerTrackMeta getMeta() {
|
||||
Size size = null;
|
||||
if (this.video) {
|
||||
GenericPictureEssenceDescriptor pd = (GenericPictureEssenceDescriptor)this.descriptor;
|
||||
size = new Size(pd.getStoredWidth(), pd.getStoredHeight());
|
||||
}
|
||||
TrackType t = this.video ? TrackType.VIDEO : (this.audio ? TrackType.AUDIO : TrackType.OTHER);
|
||||
return new DemuxerTrackMeta(t, getCodec().getCodec(), this.demuxer.duration, null, this.demuxer.totalFrames, null,
|
||||
VideoCodecMeta.createSimpleVideoCodecMeta(size, ColorSpace.YUV420), null);
|
||||
}
|
||||
|
||||
public Rational getEditRate() {
|
||||
return this.track.getEditRate();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MXFPacket extends Packet {
|
||||
private long offset;
|
||||
|
||||
private int len;
|
||||
|
||||
public MXFPacket(ByteBuffer data, long pts, int timescale, long duration, long frameNo, Packet.FrameType frameType, TapeTimecode tapeTimecode, long offset, int len) {
|
||||
super(data, pts, timescale, duration, frameNo, frameType, tapeTimecode, 0);
|
||||
this.offset = offset;
|
||||
this.len = len;
|
||||
}
|
||||
|
||||
public long getOffset() {
|
||||
return this.offset;
|
||||
}
|
||||
|
||||
public int getLen() {
|
||||
return this.len;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Fast extends MXFDemuxer {
|
||||
public Fast(SeekableByteChannel ch) throws IOException {
|
||||
super(ch);
|
||||
}
|
||||
|
||||
public void parseHeader(SeekableByteChannel ff) throws IOException {
|
||||
this.partitions = new ArrayList<>();
|
||||
this.metadata = new ArrayList<>();
|
||||
this.header = readHeaderPartition(ff);
|
||||
this.metadata.addAll(readPartitionMeta(ff, this.header));
|
||||
this.partitions.add(this.header);
|
||||
ff.setPosition(this.header.getPack().getFooterPartition());
|
||||
KLV kl = KLV.readKL(ff);
|
||||
if (kl != null) {
|
||||
ByteBuffer fetchFrom = NIOUtils.fetchFromChannel(ff, (int)kl.len);
|
||||
MXFPartition footer = MXFPartition.read(kl.key, fetchFrom, ff.position() - kl.offset, ff.size());
|
||||
this.metadata.addAll(readPartitionMeta(ff, footer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<SourceClip> getSourceClips(int trackId) {
|
||||
boolean trackFound = true;
|
||||
List<SourceClip> clips = new ArrayList<>();
|
||||
for (MXFMetadata m : this.metadata) {
|
||||
if (m instanceof TimelineTrack) {
|
||||
TimelineTrack tt = (TimelineTrack)m;
|
||||
int trackId2 = tt.getTrackId();
|
||||
trackFound = (trackId2 == trackId);
|
||||
}
|
||||
if (trackFound && m instanceof SourceClip) {
|
||||
SourceClip clip = (SourceClip)m;
|
||||
if (clip.getSourceTrackId() == trackId)
|
||||
clips.add(clip);
|
||||
}
|
||||
}
|
||||
return clips;
|
||||
}
|
||||
|
||||
public static TapeTimecode readTapeTimecode(File mxf) throws IOException {
|
||||
FileChannelWrapper read = NIOUtils.readableChannel(mxf);
|
||||
try {
|
||||
Fast fast = new Fast(read);
|
||||
MXFDemuxerTrack track = fast.getVideoTrack();
|
||||
TimecodeComponent timecode = fast.getTimecode();
|
||||
List<SourceClip> sourceClips = fast.getSourceClips(track.getTrackId());
|
||||
long tc = 0L;
|
||||
boolean dropFrame = false;
|
||||
Rational editRate = null;
|
||||
if (timecode != null) {
|
||||
editRate = track.getEditRate();
|
||||
dropFrame = (timecode.getDropFrame() != 0);
|
||||
tc = timecode.getStart();
|
||||
}
|
||||
for (SourceClip sourceClip : sourceClips)
|
||||
tc += sourceClip.getStartPosition();
|
||||
if (editRate != null)
|
||||
return TapeTimecode.tapeTimecode(tc, dropFrame, (int)Math.ceil(editRate.toDouble()));
|
||||
return null;
|
||||
} finally {
|
||||
read.close();
|
||||
}
|
||||
}
|
||||
|
||||
public List<MXFMetadata> getMetadata() {
|
||||
return Collections.unmodifiableList(this.metadata);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class AES3PCMDescriptor extends WaveAudioDescriptor {
|
||||
private byte emphasis;
|
||||
|
||||
private short blockStartOffset;
|
||||
|
||||
private byte auxBitsMode;
|
||||
|
||||
private ByteBuffer channelStatusMode;
|
||||
|
||||
private ByteBuffer fixedChannelStatusData;
|
||||
|
||||
private ByteBuffer userDataMode;
|
||||
|
||||
private ByteBuffer fixedUserData;
|
||||
|
||||
public AES3PCMDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 15629:
|
||||
this.emphasis = _bb.get();
|
||||
break;
|
||||
case 15631:
|
||||
this.blockStartOffset = _bb.getShort();
|
||||
break;
|
||||
case 15624:
|
||||
this.auxBitsMode = _bb.get();
|
||||
break;
|
||||
case 15632:
|
||||
this.channelStatusMode = _bb;
|
||||
break;
|
||||
case 15633:
|
||||
this.fixedChannelStatusData = _bb;
|
||||
break;
|
||||
case 15634:
|
||||
this.userDataMode = _bb;
|
||||
break;
|
||||
case 15635:
|
||||
this.fixedUserData = _bb;
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public byte getEmphasis() {
|
||||
return this.emphasis;
|
||||
}
|
||||
|
||||
public short getBlockStartOffset() {
|
||||
return this.blockStartOffset;
|
||||
}
|
||||
|
||||
public byte getAuxBitsMode() {
|
||||
return this.auxBitsMode;
|
||||
}
|
||||
|
||||
public ByteBuffer getChannelStatusMode() {
|
||||
return this.channelStatusMode;
|
||||
}
|
||||
|
||||
public ByteBuffer getFixedChannelStatusData() {
|
||||
return this.fixedChannelStatusData;
|
||||
}
|
||||
|
||||
public ByteBuffer getUserDataMode() {
|
||||
return this.userDataMode;
|
||||
}
|
||||
|
||||
public ByteBuffer getFixedUserData() {
|
||||
return this.fixedUserData;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import org.jcodec.common.io.NIOUtils;
|
||||
import org.jcodec.common.io.SeekableByteChannel;
|
||||
|
||||
public class BER {
|
||||
public static final byte ASN_LONG_LEN = -128;
|
||||
|
||||
public static final long decodeLength(SeekableByteChannel is) throws IOException {
|
||||
long length = 0L;
|
||||
int lengthbyte = NIOUtils.readByte(is) & 0xFF;
|
||||
if ((lengthbyte & 0xFFFFFF80) > 0) {
|
||||
lengthbyte &= 0x7F;
|
||||
if (lengthbyte == 0)
|
||||
throw new IOException("Indefinite lengths are not supported");
|
||||
if (lengthbyte > 8)
|
||||
throw new IOException("Data length > 4 bytes are not supported!");
|
||||
byte[] bb = NIOUtils.readNByte(is, lengthbyte);
|
||||
for (int i = 0; i < lengthbyte; i++)
|
||||
length = length << 8L | (long)(bb[i] & 0xFF);
|
||||
if (length < 0L)
|
||||
throw new IOException("mxflib does not support data lengths > 2^63");
|
||||
} else {
|
||||
length = (long)(lengthbyte & 0xFF);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
public static long decodeLengthBuf(ByteBuffer buffer) {
|
||||
long length = 0L;
|
||||
int lengthbyte = buffer.get() & 0xFF;
|
||||
if ((lengthbyte & 0xFFFFFF80) > 0) {
|
||||
lengthbyte &= 0x7F;
|
||||
if (lengthbyte == 0)
|
||||
throw new RuntimeException("Indefinite lengths are not supported");
|
||||
if (lengthbyte > 8)
|
||||
throw new RuntimeException("Data length > 8 bytes are not supported!");
|
||||
for (int i = 0; i < lengthbyte; i++)
|
||||
length = length << 8L | (long)(buffer.get() & 0xFF);
|
||||
if (length < 0L)
|
||||
throw new RuntimeException("mxflib does not support data lengths > 2^63");
|
||||
} else {
|
||||
length = (long)(lengthbyte & 0xFF);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class CDCIEssenceDescriptor extends GenericPictureEssenceDescriptor {
|
||||
private int componentDepth;
|
||||
|
||||
private int horizontalSubsampling;
|
||||
|
||||
private int verticalSubsampling;
|
||||
|
||||
private byte colorSiting;
|
||||
|
||||
private byte reversedByteOrder;
|
||||
|
||||
private short paddingBits;
|
||||
|
||||
private int alphaSampleDepth;
|
||||
|
||||
private int blackRefLevel;
|
||||
|
||||
private int whiteReflevel;
|
||||
|
||||
private int colorRange;
|
||||
|
||||
public CDCIEssenceDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 13057:
|
||||
this.componentDepth = _bb.getInt();
|
||||
break;
|
||||
case 13058:
|
||||
this.horizontalSubsampling = _bb.getInt();
|
||||
break;
|
||||
case 13064:
|
||||
this.verticalSubsampling = _bb.getInt();
|
||||
break;
|
||||
case 13059:
|
||||
this.colorSiting = _bb.get();
|
||||
break;
|
||||
case 13067:
|
||||
this.reversedByteOrder = _bb.get();
|
||||
break;
|
||||
case 13063:
|
||||
this.paddingBits = _bb.getShort();
|
||||
break;
|
||||
case 13065:
|
||||
this.alphaSampleDepth = _bb.getInt();
|
||||
break;
|
||||
case 13060:
|
||||
this.blackRefLevel = _bb.getInt();
|
||||
break;
|
||||
case 13061:
|
||||
this.whiteReflevel = _bb.getInt();
|
||||
break;
|
||||
case 13062:
|
||||
this.colorRange = _bb.getInt();
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public int getComponentDepth() {
|
||||
return this.componentDepth;
|
||||
}
|
||||
|
||||
public int getHorizontalSubsampling() {
|
||||
return this.horizontalSubsampling;
|
||||
}
|
||||
|
||||
public int getVerticalSubsampling() {
|
||||
return this.verticalSubsampling;
|
||||
}
|
||||
|
||||
public byte getColorSiting() {
|
||||
return this.colorSiting;
|
||||
}
|
||||
|
||||
public byte getReversedByteOrder() {
|
||||
return this.reversedByteOrder;
|
||||
}
|
||||
|
||||
public short getPaddingBits() {
|
||||
return this.paddingBits;
|
||||
}
|
||||
|
||||
public int getAlphaSampleDepth() {
|
||||
return this.alphaSampleDepth;
|
||||
}
|
||||
|
||||
public int getBlackRefLevel() {
|
||||
return this.blackRefLevel;
|
||||
}
|
||||
|
||||
public int getWhiteReflevel() {
|
||||
return this.whiteReflevel;
|
||||
}
|
||||
|
||||
public int getColorRange() {
|
||||
return this.colorRange;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class ContentStorage extends MXFInterchangeObject {
|
||||
private UL[] packageRefs;
|
||||
|
||||
private UL[] essenceContainerData;
|
||||
|
||||
public ContentStorage(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 6401:
|
||||
this.packageRefs = readULBatch(_bb);
|
||||
break;
|
||||
case 6402:
|
||||
this.essenceContainerData = readULBatch(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ ContentStorage: " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL[] getPackageRefs() {
|
||||
return this.packageRefs;
|
||||
}
|
||||
|
||||
public UL[] getEssenceContainerData() {
|
||||
return this.essenceContainerData;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import org.jcodec.common.io.NIOUtils;
|
||||
|
||||
public class DeltaEntries {
|
||||
private byte[] posTabIdx;
|
||||
|
||||
private byte[] slice;
|
||||
|
||||
private int[] elementData;
|
||||
|
||||
public DeltaEntries(byte[] posTabIdx, byte[] slice, int[] elementDelta) {
|
||||
this.posTabIdx = posTabIdx;
|
||||
this.slice = slice;
|
||||
this.elementData = elementDelta;
|
||||
}
|
||||
|
||||
public static DeltaEntries read(ByteBuffer bb) {
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
int n = bb.getInt();
|
||||
int len = bb.getInt();
|
||||
byte[] posTabIdx = new byte[n];
|
||||
byte[] slice = new byte[n];
|
||||
int[] elementDelta = new int[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
posTabIdx[i] = bb.get();
|
||||
slice[i] = bb.get();
|
||||
elementDelta[i] = bb.getInt();
|
||||
NIOUtils.skip(bb, len - 6);
|
||||
}
|
||||
return new DeltaEntries(posTabIdx, slice, elementDelta);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class EssenceContainerData extends MXFInterchangeObject {
|
||||
private UL linkedPackageUID;
|
||||
|
||||
private int indexSID;
|
||||
|
||||
private int bodySID;
|
||||
|
||||
public EssenceContainerData(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 9985:
|
||||
this.linkedPackageUID = UL.read(_bb);
|
||||
break;
|
||||
case 16134:
|
||||
this.indexSID = _bb.getInt();
|
||||
break;
|
||||
case 16135:
|
||||
this.bodySID = _bb.getInt();
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ EssenceContainerData: " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL getLinkedPackageUID() {
|
||||
return this.linkedPackageUID;
|
||||
}
|
||||
|
||||
public int getIndexSID() {
|
||||
return this.indexSID;
|
||||
}
|
||||
|
||||
public int getBodySID() {
|
||||
return this.bodySID;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
import org.jcodec.common.model.Rational;
|
||||
|
||||
public class FileDescriptor extends GenericDescriptor {
|
||||
private int linkedTrackId;
|
||||
|
||||
private Rational sampleRate;
|
||||
|
||||
private long containerDuration;
|
||||
|
||||
private UL essenceContainer;
|
||||
|
||||
private UL codec;
|
||||
|
||||
public FileDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 12294:
|
||||
this.linkedTrackId = _bb.getInt();
|
||||
break;
|
||||
case 12289:
|
||||
this.sampleRate = new Rational(_bb.getInt(), _bb.getInt());
|
||||
break;
|
||||
case 12290:
|
||||
this.containerDuration = _bb.getLong();
|
||||
break;
|
||||
case 12292:
|
||||
this.essenceContainer = UL.read(_bb);
|
||||
break;
|
||||
case 12293:
|
||||
this.codec = UL.read(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public int getLinkedTrackId() {
|
||||
return this.linkedTrackId;
|
||||
}
|
||||
|
||||
public Rational getSampleRate() {
|
||||
return this.sampleRate;
|
||||
}
|
||||
|
||||
public long getContainerDuration() {
|
||||
return this.containerDuration;
|
||||
}
|
||||
|
||||
public UL getEssenceContainer() {
|
||||
return this.essenceContainer;
|
||||
}
|
||||
|
||||
public UL getCodec() {
|
||||
return this.codec;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class GenericDataEssenceDescriptor extends FileDescriptor {
|
||||
private UL dataEssenceCoding;
|
||||
|
||||
public GenericDataEssenceDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 15873:
|
||||
this.dataEssenceCoding = UL.read(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ FileDescriptor: " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL getDataEssenceCoding() {
|
||||
return this.dataEssenceCoding;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class GenericDescriptor extends MXFInterchangeObject {
|
||||
private UL[] locators;
|
||||
|
||||
private UL[] subDescriptors;
|
||||
|
||||
public GenericDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 12033:
|
||||
this.locators = readULBatch(_bb);
|
||||
break;
|
||||
case 16129:
|
||||
this.subDescriptors = readULBatch(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL[] getLocators() {
|
||||
return this.locators;
|
||||
}
|
||||
|
||||
public UL[] getSubDescriptors() {
|
||||
return this.subDescriptors;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class GenericPackage extends MXFInterchangeObject {
|
||||
private UL[] tracks;
|
||||
|
||||
private UL packageUID;
|
||||
|
||||
private String name;
|
||||
|
||||
private Date packageModifiedDate;
|
||||
|
||||
private Date packageCreationDate;
|
||||
|
||||
public GenericPackage(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 17409:
|
||||
this.packageUID = UL.read(_bb);
|
||||
break;
|
||||
case 17410:
|
||||
this.name = readUtf16String(_bb);
|
||||
break;
|
||||
case 17411:
|
||||
this.tracks = readULBatch(_bb);
|
||||
break;
|
||||
case 17412:
|
||||
this.packageModifiedDate = readDate(_bb);
|
||||
break;
|
||||
case 17413:
|
||||
this.packageCreationDate = readDate(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL[] getTracks() {
|
||||
return this.tracks;
|
||||
}
|
||||
|
||||
public UL getPackageUID() {
|
||||
return this.packageUID;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public Date getPackageModifiedDate() {
|
||||
return this.packageModifiedDate;
|
||||
}
|
||||
|
||||
public Date getPackageCreationDate() {
|
||||
return this.packageCreationDate;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
import org.jcodec.common.model.Rational;
|
||||
|
||||
public class GenericPictureEssenceDescriptor extends FileDescriptor {
|
||||
private byte signalStandard;
|
||||
|
||||
private LayoutType frameLayout;
|
||||
|
||||
private int storedWidth;
|
||||
|
||||
private int storedHeight;
|
||||
|
||||
private int storedF2Offset;
|
||||
|
||||
private int sampledWidth;
|
||||
|
||||
private int sampledHeight;
|
||||
|
||||
private int sampledXOffset;
|
||||
|
||||
private int sampledYOffset;
|
||||
|
||||
private int displayHeight;
|
||||
|
||||
private int displayWidth;
|
||||
|
||||
private int displayXOffset;
|
||||
|
||||
private int displayYOffset;
|
||||
|
||||
private int displayF2Offset;
|
||||
|
||||
private Rational aspectRatio;
|
||||
|
||||
private byte activeFormatDescriptor;
|
||||
|
||||
private int[] videoLineMap;
|
||||
|
||||
private byte alphaTransparency;
|
||||
|
||||
private UL transferCharacteristic;
|
||||
|
||||
private int imageAlignmentOffset;
|
||||
|
||||
private int imageStartOffset;
|
||||
|
||||
private int imageEndOffset;
|
||||
|
||||
private byte fieldDominance;
|
||||
|
||||
private UL pictureEssenceCoding;
|
||||
|
||||
private UL codingEquations;
|
||||
|
||||
private UL colorPrimaries;
|
||||
|
||||
public enum LayoutType {
|
||||
FullFrame, SeparateFields, OneField, MixedFields, SegmentedFrame;
|
||||
}
|
||||
|
||||
public GenericPictureEssenceDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 12821:
|
||||
this.signalStandard = _bb.get();
|
||||
break;
|
||||
case 12812:
|
||||
this.frameLayout = LayoutType.values()[_bb.get()];
|
||||
break;
|
||||
case 12803:
|
||||
this.storedWidth = _bb.getInt();
|
||||
break;
|
||||
case 12802:
|
||||
this.storedHeight = _bb.getInt();
|
||||
break;
|
||||
case 12822:
|
||||
this.storedF2Offset = _bb.getInt();
|
||||
break;
|
||||
case 12805:
|
||||
this.sampledWidth = _bb.getInt();
|
||||
break;
|
||||
case 12804:
|
||||
this.sampledHeight = _bb.getInt();
|
||||
break;
|
||||
case 12806:
|
||||
this.sampledXOffset = _bb.getInt();
|
||||
break;
|
||||
case 12807:
|
||||
this.sampledYOffset = _bb.getInt();
|
||||
break;
|
||||
case 12808:
|
||||
this.displayHeight = _bb.getInt();
|
||||
break;
|
||||
case 12809:
|
||||
this.displayWidth = _bb.getInt();
|
||||
break;
|
||||
case 12810:
|
||||
this.displayXOffset = _bb.getInt();
|
||||
break;
|
||||
case 12811:
|
||||
this.displayYOffset = _bb.getInt();
|
||||
break;
|
||||
case 12823:
|
||||
this.displayF2Offset = _bb.getInt();
|
||||
break;
|
||||
case 12814:
|
||||
this.aspectRatio = new Rational(_bb.getInt(), _bb.getInt());
|
||||
break;
|
||||
case 12824:
|
||||
this.activeFormatDescriptor = _bb.get();
|
||||
break;
|
||||
case 12813:
|
||||
this.videoLineMap = readInt32Batch(_bb);
|
||||
break;
|
||||
case 12815:
|
||||
this.alphaTransparency = _bb.get();
|
||||
break;
|
||||
case 12816:
|
||||
this.transferCharacteristic = UL.read(_bb);
|
||||
break;
|
||||
case 12817:
|
||||
this.imageAlignmentOffset = _bb.getInt();
|
||||
break;
|
||||
case 12819:
|
||||
this.imageStartOffset = _bb.getInt();
|
||||
break;
|
||||
case 12820:
|
||||
this.imageEndOffset = _bb.getInt();
|
||||
break;
|
||||
case 12818:
|
||||
this.fieldDominance = _bb.get();
|
||||
break;
|
||||
case 12801:
|
||||
this.pictureEssenceCoding = UL.read(_bb);
|
||||
break;
|
||||
case 12826:
|
||||
this.codingEquations = UL.read(_bb);
|
||||
break;
|
||||
case 12825:
|
||||
this.colorPrimaries = UL.read(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public byte getSignalStandard() {
|
||||
return this.signalStandard;
|
||||
}
|
||||
|
||||
public LayoutType getFrameLayout() {
|
||||
return this.frameLayout;
|
||||
}
|
||||
|
||||
public int getStoredWidth() {
|
||||
return this.storedWidth;
|
||||
}
|
||||
|
||||
public int getStoredHeight() {
|
||||
return this.storedHeight;
|
||||
}
|
||||
|
||||
public int getStoredF2Offset() {
|
||||
return this.storedF2Offset;
|
||||
}
|
||||
|
||||
public int getSampledWidth() {
|
||||
return this.sampledWidth;
|
||||
}
|
||||
|
||||
public int getSampledHeight() {
|
||||
return this.sampledHeight;
|
||||
}
|
||||
|
||||
public int getSampledXOffset() {
|
||||
return this.sampledXOffset;
|
||||
}
|
||||
|
||||
public int getSampledYOffset() {
|
||||
return this.sampledYOffset;
|
||||
}
|
||||
|
||||
public int getDisplayHeight() {
|
||||
return this.displayHeight;
|
||||
}
|
||||
|
||||
public int getDisplayWidth() {
|
||||
return this.displayWidth;
|
||||
}
|
||||
|
||||
public int getDisplayXOffset() {
|
||||
return this.displayXOffset;
|
||||
}
|
||||
|
||||
public int getDisplayYOffset() {
|
||||
return this.displayYOffset;
|
||||
}
|
||||
|
||||
public int getDisplayF2Offset() {
|
||||
return this.displayF2Offset;
|
||||
}
|
||||
|
||||
public Rational getAspectRatio() {
|
||||
return this.aspectRatio;
|
||||
}
|
||||
|
||||
public byte getActiveFormatDescriptor() {
|
||||
return this.activeFormatDescriptor;
|
||||
}
|
||||
|
||||
public int[] getVideoLineMap() {
|
||||
return this.videoLineMap;
|
||||
}
|
||||
|
||||
public byte getAlphaTransparency() {
|
||||
return this.alphaTransparency;
|
||||
}
|
||||
|
||||
public UL getTransferCharacteristic() {
|
||||
return this.transferCharacteristic;
|
||||
}
|
||||
|
||||
public int getImageAlignmentOffset() {
|
||||
return this.imageAlignmentOffset;
|
||||
}
|
||||
|
||||
public int getImageStartOffset() {
|
||||
return this.imageStartOffset;
|
||||
}
|
||||
|
||||
public int getImageEndOffset() {
|
||||
return this.imageEndOffset;
|
||||
}
|
||||
|
||||
public byte getFieldDominance() {
|
||||
return this.fieldDominance;
|
||||
}
|
||||
|
||||
public UL getPictureEssenceCoding() {
|
||||
return this.pictureEssenceCoding;
|
||||
}
|
||||
|
||||
public UL getCodingEquations() {
|
||||
return this.codingEquations;
|
||||
}
|
||||
|
||||
public UL getColorPrimaries() {
|
||||
return this.colorPrimaries;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
import org.jcodec.common.model.Rational;
|
||||
|
||||
public class GenericSoundEssenceDescriptor extends FileDescriptor {
|
||||
private Rational audioSamplingRate;
|
||||
|
||||
private byte locked;
|
||||
|
||||
private byte audioRefLevel;
|
||||
|
||||
private byte electroSpatialFormulation;
|
||||
|
||||
private int channelCount;
|
||||
|
||||
private int quantizationBits;
|
||||
|
||||
private byte dialNorm;
|
||||
|
||||
private UL soundEssenceCompression;
|
||||
|
||||
public GenericSoundEssenceDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 15619:
|
||||
this.audioSamplingRate = new Rational(_bb.getInt(), _bb.getInt());
|
||||
break;
|
||||
case 15618:
|
||||
this.locked = _bb.get();
|
||||
break;
|
||||
case 15620:
|
||||
this.audioRefLevel = _bb.get();
|
||||
break;
|
||||
case 15621:
|
||||
this.electroSpatialFormulation = _bb.get();
|
||||
break;
|
||||
case 15623:
|
||||
this.channelCount = _bb.getInt();
|
||||
break;
|
||||
case 15617:
|
||||
this.quantizationBits = _bb.getInt();
|
||||
break;
|
||||
case 15628:
|
||||
this.dialNorm = _bb.get();
|
||||
break;
|
||||
case 15622:
|
||||
this.soundEssenceCompression = UL.read(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public Rational getAudioSamplingRate() {
|
||||
return this.audioSamplingRate;
|
||||
}
|
||||
|
||||
public byte getLocked() {
|
||||
return this.locked;
|
||||
}
|
||||
|
||||
public byte getAudioRefLevel() {
|
||||
return this.audioRefLevel;
|
||||
}
|
||||
|
||||
public byte getElectroSpatialFormulation() {
|
||||
return this.electroSpatialFormulation;
|
||||
}
|
||||
|
||||
public int getChannelCount() {
|
||||
return this.channelCount;
|
||||
}
|
||||
|
||||
public int getQuantizationBits() {
|
||||
return this.quantizationBits;
|
||||
}
|
||||
|
||||
public byte getDialNorm() {
|
||||
return this.dialNorm;
|
||||
}
|
||||
|
||||
public UL getSoundEssenceCompression() {
|
||||
return this.soundEssenceCompression;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class GenericTrack extends MXFInterchangeObject {
|
||||
private int trackId;
|
||||
|
||||
private String name;
|
||||
|
||||
private UL sequenceRef;
|
||||
|
||||
private int trackNumber;
|
||||
|
||||
public GenericTrack(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 18433:
|
||||
this.trackId = _bb.getInt();
|
||||
break;
|
||||
case 18434:
|
||||
this.name = readUtf16String(_bb);
|
||||
break;
|
||||
case 18435:
|
||||
this.sequenceRef = UL.read(_bb);
|
||||
break;
|
||||
case 18436:
|
||||
this.trackNumber = _bb.getInt();
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public int getTrackId() {
|
||||
return this.trackId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public UL getSequenceRef() {
|
||||
return this.sequenceRef;
|
||||
}
|
||||
|
||||
public int getTrackNumber() {
|
||||
return this.trackNumber;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class Identification extends MXFInterchangeObject {
|
||||
private UL thisGenerationUID;
|
||||
|
||||
private String companyName;
|
||||
|
||||
private String productName;
|
||||
|
||||
private short versionString;
|
||||
|
||||
private UL productUID;
|
||||
|
||||
private Date modificationDate;
|
||||
|
||||
private String platform;
|
||||
|
||||
public Identification(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 15369:
|
||||
this.thisGenerationUID = UL.read(_bb);
|
||||
break;
|
||||
case 15361:
|
||||
this.companyName = readUtf16String(_bb);
|
||||
break;
|
||||
case 15362:
|
||||
this.productName = readUtf16String(_bb);
|
||||
break;
|
||||
case 15364:
|
||||
this.versionString = _bb.getShort();
|
||||
break;
|
||||
case 15365:
|
||||
this.productUID = UL.read(_bb);
|
||||
break;
|
||||
case 15366:
|
||||
this.modificationDate = readDate(_bb);
|
||||
break;
|
||||
case 15368:
|
||||
this.platform = readUtf16String(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL getThisGenerationUID() {
|
||||
return this.thisGenerationUID;
|
||||
}
|
||||
|
||||
public String getCompanyName() {
|
||||
return this.companyName;
|
||||
}
|
||||
|
||||
public String getProductName() {
|
||||
return this.productName;
|
||||
}
|
||||
|
||||
public short getVersionString() {
|
||||
return this.versionString;
|
||||
}
|
||||
|
||||
public UL getProductUID() {
|
||||
return this.productUID;
|
||||
}
|
||||
|
||||
public Date getModificationDate() {
|
||||
return this.modificationDate;
|
||||
}
|
||||
|
||||
public String getPlatform() {
|
||||
return this.platform;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import org.jcodec.common.io.NIOUtils;
|
||||
|
||||
public class IndexEntries {
|
||||
private byte[] displayOff;
|
||||
|
||||
private byte[] flags;
|
||||
|
||||
private long[] fileOff;
|
||||
|
||||
private byte[] keyFrameOff;
|
||||
|
||||
public IndexEntries(byte[] displayOff, byte[] keyFrameOff, byte[] flags, long[] fileOff) {
|
||||
this.displayOff = displayOff;
|
||||
this.keyFrameOff = keyFrameOff;
|
||||
this.flags = flags;
|
||||
this.fileOff = fileOff;
|
||||
}
|
||||
|
||||
public byte[] getDisplayOff() {
|
||||
return this.displayOff;
|
||||
}
|
||||
|
||||
public byte[] getFlags() {
|
||||
return this.flags;
|
||||
}
|
||||
|
||||
public long[] getFileOff() {
|
||||
return this.fileOff;
|
||||
}
|
||||
|
||||
public byte[] getKeyFrameOff() {
|
||||
return this.keyFrameOff;
|
||||
}
|
||||
|
||||
public static IndexEntries read(ByteBuffer bb) {
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
int n = bb.getInt();
|
||||
int len = bb.getInt();
|
||||
int[] temporalOff = new int[n];
|
||||
byte[] flags = new byte[n];
|
||||
long[] fileOff = new long[n];
|
||||
byte[] keyFrameOff = new byte[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
temporalOff[i] = i + bb.get();
|
||||
keyFrameOff[i] = bb.get();
|
||||
flags[i] = bb.get();
|
||||
fileOff[i] = bb.getLong();
|
||||
NIOUtils.skip(bb, len - 11);
|
||||
}
|
||||
byte[] displayOff = new byte[n];
|
||||
for (int j = 0; j < n; j++) {
|
||||
for (int k = 0; k < n; k++) {
|
||||
if (temporalOff[k] == j) {
|
||||
displayOff[j] = (byte)(k - j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new IndexEntries(displayOff, keyFrameOff, flags, fileOff);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class IndexSegment extends MXFInterchangeObject {
|
||||
private IndexEntries ie;
|
||||
|
||||
private int editUnitByteCount;
|
||||
|
||||
private DeltaEntries deltaEntries;
|
||||
|
||||
private int indexSID;
|
||||
|
||||
private int bodySID;
|
||||
|
||||
private int indexEditRateNum;
|
||||
|
||||
private int indexEditRateDen;
|
||||
|
||||
private long indexStartPosition;
|
||||
|
||||
private long indexDuration;
|
||||
|
||||
private UL instanceUID;
|
||||
|
||||
private int sliceCount;
|
||||
|
||||
private int posTableCount;
|
||||
|
||||
public IndexSegment(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 15370:
|
||||
this.instanceUID = UL.read(_bb);
|
||||
break;
|
||||
case 16133:
|
||||
this.editUnitByteCount = _bb.getInt();
|
||||
break;
|
||||
case 16134:
|
||||
this.indexSID = _bb.getInt();
|
||||
break;
|
||||
case 16135:
|
||||
this.bodySID = _bb.getInt();
|
||||
break;
|
||||
case 16136:
|
||||
this.sliceCount = _bb.get() & 0xFF;
|
||||
break;
|
||||
case 16137:
|
||||
this.deltaEntries = DeltaEntries.read(_bb);
|
||||
break;
|
||||
case 16138:
|
||||
this.ie = IndexEntries.read(_bb);
|
||||
break;
|
||||
case 16139:
|
||||
this.indexEditRateNum = _bb.getInt();
|
||||
this.indexEditRateDen = _bb.getInt();
|
||||
break;
|
||||
case 16140:
|
||||
this.indexStartPosition = _bb.getLong();
|
||||
break;
|
||||
case 16141:
|
||||
this.indexDuration = _bb.getLong();
|
||||
break;
|
||||
case 16142:
|
||||
this.posTableCount = _bb.get() & 0xFF;
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [" + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public IndexEntries getIe() {
|
||||
return this.ie;
|
||||
}
|
||||
|
||||
public int getEditUnitByteCount() {
|
||||
return this.editUnitByteCount;
|
||||
}
|
||||
|
||||
public DeltaEntries getDeltaEntries() {
|
||||
return this.deltaEntries;
|
||||
}
|
||||
|
||||
public int getIndexSID() {
|
||||
return this.indexSID;
|
||||
}
|
||||
|
||||
public int getBodySID() {
|
||||
return this.bodySID;
|
||||
}
|
||||
|
||||
public int getIndexEditRateNum() {
|
||||
return this.indexEditRateNum;
|
||||
}
|
||||
|
||||
public int getIndexEditRateDen() {
|
||||
return this.indexEditRateDen;
|
||||
}
|
||||
|
||||
public long getIndexStartPosition() {
|
||||
return this.indexStartPosition;
|
||||
}
|
||||
|
||||
public long getIndexDuration() {
|
||||
return this.indexDuration;
|
||||
}
|
||||
|
||||
public UL getInstanceUID() {
|
||||
return this.instanceUID;
|
||||
}
|
||||
|
||||
public int getSliceCount() {
|
||||
return this.sliceCount;
|
||||
}
|
||||
|
||||
public int getPosTableCount() {
|
||||
return this.posTableCount;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class J2KPictureDescriptor extends MXFInterchangeObject {
|
||||
private short rsiz;
|
||||
|
||||
private int xsiz;
|
||||
|
||||
private int ysiz;
|
||||
|
||||
private int xOsiz;
|
||||
|
||||
private int yOsiz;
|
||||
|
||||
private int xTsiz;
|
||||
|
||||
private int yTsiz;
|
||||
|
||||
private int xTOsiz;
|
||||
|
||||
private int yTOsiz;
|
||||
|
||||
private short csiz;
|
||||
|
||||
public J2KPictureDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 24836:
|
||||
this.rsiz = _bb.getShort();
|
||||
break;
|
||||
case 24837:
|
||||
this.xsiz = _bb.getInt();
|
||||
break;
|
||||
case 24838:
|
||||
this.ysiz = _bb.getInt();
|
||||
break;
|
||||
case 24839:
|
||||
this.xOsiz = _bb.getInt();
|
||||
break;
|
||||
case 24840:
|
||||
this.yOsiz = _bb.getInt();
|
||||
break;
|
||||
case 24841:
|
||||
this.xTsiz = _bb.getInt();
|
||||
break;
|
||||
case 24842:
|
||||
this.yTsiz = _bb.getInt();
|
||||
break;
|
||||
case 24843:
|
||||
this.xTOsiz = _bb.getInt();
|
||||
break;
|
||||
case 24844:
|
||||
this.yTOsiz = _bb.getInt();
|
||||
break;
|
||||
case 24845:
|
||||
this.csiz = _bb.getShort();
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public short getRsiz() {
|
||||
return this.rsiz;
|
||||
}
|
||||
|
||||
public int getXsiz() {
|
||||
return this.xsiz;
|
||||
}
|
||||
|
||||
public int getYsiz() {
|
||||
return this.ysiz;
|
||||
}
|
||||
|
||||
public int getxOsiz() {
|
||||
return this.xOsiz;
|
||||
}
|
||||
|
||||
public int getyOsiz() {
|
||||
return this.yOsiz;
|
||||
}
|
||||
|
||||
public int getxTsiz() {
|
||||
return this.xTsiz;
|
||||
}
|
||||
|
||||
public int getyTsiz() {
|
||||
return this.yTsiz;
|
||||
}
|
||||
|
||||
public int getxTOsiz() {
|
||||
return this.xTOsiz;
|
||||
}
|
||||
|
||||
public int getyTOsiz() {
|
||||
return this.yTOsiz;
|
||||
}
|
||||
|
||||
public short getCsiz() {
|
||||
return this.csiz;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import org.jcodec.common.io.SeekableByteChannel;
|
||||
|
||||
public class KLV {
|
||||
public final long offset;
|
||||
|
||||
public final long dataOffset;
|
||||
|
||||
public final UL key;
|
||||
|
||||
public final long len;
|
||||
|
||||
ByteBuffer value;
|
||||
|
||||
public KLV(UL k, long len, long offset, long dataOffset) {
|
||||
this.key = k;
|
||||
this.len = len;
|
||||
this.offset = offset;
|
||||
this.dataOffset = dataOffset;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "KLV [offset=" + this.offset + ", dataOffset=" + this.dataOffset + ", key=" + String.valueOf(this.key) + ", len=" + this.len + ", value=" + String.valueOf(this.value) + "]";
|
||||
}
|
||||
|
||||
public static KLV readKL(SeekableByteChannel ch) throws IOException {
|
||||
long offset = ch.position();
|
||||
if (offset >= ch.size() - 1L)
|
||||
return null;
|
||||
byte[] key = new byte[16];
|
||||
ch.read(ByteBuffer.wrap(key));
|
||||
long len = BER.decodeLength(ch);
|
||||
long dataOffset = ch.position();
|
||||
return new KLV(new UL(key), len, offset, dataOffset);
|
||||
}
|
||||
|
||||
public int getLenByteCount() {
|
||||
int berlen = (int)(this.dataOffset - this.offset - 16L);
|
||||
return (berlen <= 0) ? 4 : berlen;
|
||||
}
|
||||
|
||||
public static boolean matches(byte[] key1, byte[] key2, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (key1[i] != key2[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static KLV readKLFromBuffer(ByteBuffer buffer, long baseOffset) {
|
||||
if (buffer.remaining() < 17)
|
||||
return null;
|
||||
long offset = baseOffset + (long)buffer.position();
|
||||
UL ul = UL.read(buffer);
|
||||
long len = BER.decodeLengthBuf(buffer);
|
||||
return new KLV(ul, len, offset, baseOffset + (long)buffer.position());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class MPEG2VideoDescriptor extends CDCIEssenceDescriptor {
|
||||
private byte singleSequence;
|
||||
|
||||
private byte constantBFrames;
|
||||
|
||||
private byte codedContentType;
|
||||
|
||||
private byte lowDelay;
|
||||
|
||||
private byte closedGOP;
|
||||
|
||||
private byte identicalGOP;
|
||||
|
||||
private short maxGOP;
|
||||
|
||||
private short bPictureCount;
|
||||
|
||||
private int bitRate;
|
||||
|
||||
private byte profileAndLevel;
|
||||
|
||||
public MPEG2VideoDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 32768:
|
||||
this.singleSequence = _bb.get();
|
||||
break;
|
||||
case 32769:
|
||||
this.constantBFrames = _bb.get();
|
||||
break;
|
||||
case 32770:
|
||||
this.codedContentType = _bb.get();
|
||||
break;
|
||||
case 32771:
|
||||
this.lowDelay = _bb.get();
|
||||
break;
|
||||
case 32772:
|
||||
this.closedGOP = _bb.get();
|
||||
break;
|
||||
case 32773:
|
||||
this.identicalGOP = _bb.get();
|
||||
break;
|
||||
case 32774:
|
||||
this.maxGOP = _bb.getShort();
|
||||
break;
|
||||
case 32775:
|
||||
this.bPictureCount = (short)(_bb.get() & 0xFF);
|
||||
break;
|
||||
case 32776:
|
||||
this.bitRate = _bb.getInt();
|
||||
break;
|
||||
case 32777:
|
||||
this.profileAndLevel = _bb.get();
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x + (" + _bb.remaining() + ")", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public byte getSingleSequence() {
|
||||
return this.singleSequence;
|
||||
}
|
||||
|
||||
public byte getConstantBFrames() {
|
||||
return this.constantBFrames;
|
||||
}
|
||||
|
||||
public byte getCodedContentType() {
|
||||
return this.codedContentType;
|
||||
}
|
||||
|
||||
public byte getLowDelay() {
|
||||
return this.lowDelay;
|
||||
}
|
||||
|
||||
public byte getClosedGOP() {
|
||||
return this.closedGOP;
|
||||
}
|
||||
|
||||
public byte getIdenticalGOP() {
|
||||
return this.identicalGOP;
|
||||
}
|
||||
|
||||
public short getMaxGOP() {
|
||||
return this.maxGOP;
|
||||
}
|
||||
|
||||
public short getbPictureCount() {
|
||||
return this.bPictureCount;
|
||||
}
|
||||
|
||||
public int getBitRate() {
|
||||
return this.bitRate;
|
||||
}
|
||||
|
||||
public byte getProfileAndLevel() {
|
||||
return this.profileAndLevel;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.io.NIOUtils;
|
||||
|
||||
public abstract class MXFInterchangeObject extends MXFMetadata {
|
||||
private UL generationUID;
|
||||
|
||||
private UL objectClass;
|
||||
|
||||
public MXFInterchangeObject(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
public void readBuf(ByteBuffer bb) {
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
Map<Integer, ByteBuffer> tags = new HashMap<>();
|
||||
while (bb.hasRemaining()) {
|
||||
int tag = bb.getShort() & 0xFFFF;
|
||||
int size = bb.getShort() & 0xFFFF;
|
||||
ByteBuffer _bb = NIOUtils.read(bb, size);
|
||||
switch (tag) {
|
||||
case 15370:
|
||||
this.uid = UL.read(_bb);
|
||||
continue;
|
||||
case 258:
|
||||
this.generationUID = UL.read(_bb);
|
||||
continue;
|
||||
case 257:
|
||||
this.objectClass = UL.read(_bb);
|
||||
continue;
|
||||
}
|
||||
tags.put(Integer.valueOf(tag), _bb);
|
||||
}
|
||||
if (tags.size() > 0)
|
||||
read(tags);
|
||||
}
|
||||
|
||||
protected abstract void read(Map<Integer, ByteBuffer> paramMap);
|
||||
|
||||
public UL getGenerationUID() {
|
||||
return this.generationUID;
|
||||
}
|
||||
|
||||
public UL getObjectClass() {
|
||||
return this.objectClass;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import org.jcodec.common.io.NIOUtils;
|
||||
import org.jcodec.platform.Platform;
|
||||
|
||||
public abstract class MXFMetadata {
|
||||
protected UL ul;
|
||||
|
||||
protected UL uid;
|
||||
|
||||
public MXFMetadata(UL ul) {
|
||||
this.ul = ul;
|
||||
}
|
||||
|
||||
public abstract void readBuf(ByteBuffer paramByteBuffer);
|
||||
|
||||
protected static UL[] readULBatch(ByteBuffer _bb) {
|
||||
int count = _bb.getInt();
|
||||
_bb.getInt();
|
||||
UL[] result = new UL[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
result[i] = UL.read(_bb);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected static int[] readInt32Batch(ByteBuffer _bb) {
|
||||
int count = _bb.getInt();
|
||||
_bb.getInt();
|
||||
int[] result = new int[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
result[i] = _bb.getInt();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected static Date readDate(ByteBuffer _bb) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(1, _bb.getShort());
|
||||
calendar.set(2, _bb.get());
|
||||
calendar.set(5, _bb.get());
|
||||
calendar.set(10, _bb.get());
|
||||
calendar.set(12, _bb.get());
|
||||
calendar.set(13, _bb.get());
|
||||
calendar.set(14, (_bb.get() & 0xFF) << 2);
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
protected String readUtf16String(ByteBuffer _bb) {
|
||||
byte[] array;
|
||||
if (_bb.getShort(_bb.limit() - 2) != 0) {
|
||||
array = NIOUtils.toArray(_bb);
|
||||
} else {
|
||||
array = NIOUtils.toArray(_bb.limit(_bb.limit() - 2));
|
||||
}
|
||||
return Platform.stringFromCharset(array, "UTF-16");
|
||||
}
|
||||
|
||||
public UL getUl() {
|
||||
return this.ul;
|
||||
}
|
||||
|
||||
public UL getUid() {
|
||||
return this.uid;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class MXFPartition {
|
||||
private MXFPartitionPack pack;
|
||||
|
||||
private long essenceFilePos;
|
||||
|
||||
private boolean closed;
|
||||
|
||||
private boolean complete;
|
||||
|
||||
private long essenceLength;
|
||||
|
||||
public MXFPartition(MXFPartitionPack pack, long essenceFilePos, boolean closed, boolean complete, long essenceLength) {
|
||||
this.pack = pack;
|
||||
this.essenceFilePos = essenceFilePos;
|
||||
this.closed = closed;
|
||||
this.complete = complete;
|
||||
this.essenceLength = essenceLength;
|
||||
}
|
||||
|
||||
public static MXFPartition read(UL ul, ByteBuffer bb, long packSize, long nextPartition) {
|
||||
boolean closed = ((ul.get(14) & 0x1) == 0);
|
||||
boolean complete = (ul.get(14) > 2);
|
||||
MXFPartitionPack pp = new MXFPartitionPack(ul);
|
||||
pp.readBuf(bb);
|
||||
long essenceFilePos = roundToKag(pp.getThisPartition() + packSize, pp.getKagSize()) +
|
||||
roundToKag(pp.getHeaderByteCount(), pp.getKagSize()) +
|
||||
roundToKag(pp.getIndexByteCount(), pp.getKagSize());
|
||||
return new MXFPartition(pp, essenceFilePos, closed, complete, nextPartition - essenceFilePos);
|
||||
}
|
||||
|
||||
static long roundToKag(long position, int kag_size) {
|
||||
long ret = position / (long)kag_size * (long)kag_size;
|
||||
return (ret == position) ? ret : (ret + (long)kag_size);
|
||||
}
|
||||
|
||||
public MXFPartitionPack getPack() {
|
||||
return this.pack;
|
||||
}
|
||||
|
||||
public long getEssenceFilePos() {
|
||||
return this.essenceFilePos;
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return this.closed;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return this.complete;
|
||||
}
|
||||
|
||||
public long getEssenceLength() {
|
||||
return this.essenceLength;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import org.jcodec.common.io.NIOUtils;
|
||||
|
||||
public class MXFPartitionPack extends MXFMetadata {
|
||||
private int kagSize;
|
||||
|
||||
private long thisPartition;
|
||||
|
||||
private long prevPartition;
|
||||
|
||||
private long footerPartition;
|
||||
|
||||
private long headerByteCount;
|
||||
|
||||
private long indexByteCount;
|
||||
|
||||
private int indexSid;
|
||||
|
||||
private int bodySid;
|
||||
|
||||
private UL op;
|
||||
|
||||
private int nbEssenceContainers;
|
||||
|
||||
public MXFPartitionPack(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
public void readBuf(ByteBuffer bb) {
|
||||
bb.order(ByteOrder.BIG_ENDIAN);
|
||||
NIOUtils.skip(bb, 4);
|
||||
this.kagSize = bb.getInt();
|
||||
this.thisPartition = bb.getLong();
|
||||
this.prevPartition = bb.getLong();
|
||||
this.footerPartition = bb.getLong();
|
||||
this.headerByteCount = bb.getLong();
|
||||
this.indexByteCount = bb.getLong();
|
||||
this.indexSid = bb.getInt();
|
||||
NIOUtils.skip(bb, 8);
|
||||
this.bodySid = bb.getInt();
|
||||
this.op = UL.read(bb);
|
||||
this.nbEssenceContainers = bb.getInt();
|
||||
}
|
||||
|
||||
public int getKagSize() {
|
||||
return this.kagSize;
|
||||
}
|
||||
|
||||
public long getThisPartition() {
|
||||
return this.thisPartition;
|
||||
}
|
||||
|
||||
public long getPrevPartition() {
|
||||
return this.prevPartition;
|
||||
}
|
||||
|
||||
public long getFooterPartition() {
|
||||
return this.footerPartition;
|
||||
}
|
||||
|
||||
public long getHeaderByteCount() {
|
||||
return this.headerByteCount;
|
||||
}
|
||||
|
||||
public long getIndexByteCount() {
|
||||
return this.indexByteCount;
|
||||
}
|
||||
|
||||
public int getIndexSid() {
|
||||
return this.indexSid;
|
||||
}
|
||||
|
||||
public int getBodySid() {
|
||||
return this.bodySid;
|
||||
}
|
||||
|
||||
public UL getOp() {
|
||||
return this.op;
|
||||
}
|
||||
|
||||
public int getNbEssenceContainers() {
|
||||
return this.nbEssenceContainers;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class MXFStructuralComponent extends MXFInterchangeObject {
|
||||
private long duration;
|
||||
|
||||
private UL dataDefinitionUL;
|
||||
|
||||
public MXFStructuralComponent(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 514:
|
||||
this.duration = entry.getValue().getLong();
|
||||
break;
|
||||
case 513:
|
||||
this.dataDefinitionUL = UL.read(entry.getValue());
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
public UL getDataDefinitionUL() {
|
||||
return this.dataDefinitionUL;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.jcodec.platform.Platform;
|
||||
|
||||
public class MXFUtil {
|
||||
public static <T> T resolveRef(List<MXFMetadata> metadata, UL refs, Class<T> class1) {
|
||||
List<T> res = resolveRefs(metadata, new UL[] { refs }, class1);
|
||||
return (res.size() > 0) ? res.get(0) : null;
|
||||
}
|
||||
|
||||
public static <T> List<T> resolveRefs(List<MXFMetadata> metadata, UL[] refs, Class<T> class1) {
|
||||
List<MXFMetadata> copy = new ArrayList<>(metadata);
|
||||
for (Iterator<MXFMetadata> iterator = copy.iterator(); iterator.hasNext(); ) {
|
||||
MXFMetadata next = iterator.next();
|
||||
if (next.getUid() == null || !Platform.isAssignableFrom(class1, next.getClass()))
|
||||
iterator.remove();
|
||||
}
|
||||
List<MXFMetadata> result = new ArrayList();
|
||||
for (int i = 0; i < refs.length; i++) {
|
||||
for (MXFMetadata meta : copy) {
|
||||
if (meta.getUid().equals(refs[i]))
|
||||
result.add(meta);
|
||||
}
|
||||
}
|
||||
return (List<T>)result;
|
||||
}
|
||||
|
||||
public static <T> T findMeta(Collection<MXFMetadata> metadata, Class<T> class1) {
|
||||
for (MXFMetadata mxfMetadata : metadata) {
|
||||
if (Platform.isAssignableFrom(mxfMetadata.getClass(), class1))
|
||||
return (T)mxfMetadata;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> List<T> findAllMeta(Collection<MXFMetadata> metadata, Class<T> class1) {
|
||||
List<MXFMetadata> result = new ArrayList();
|
||||
for (MXFMetadata mxfMetadata : metadata) {
|
||||
if (Platform.isAssignableFrom(class1, mxfMetadata.getClass()))
|
||||
result.add(mxfMetadata);
|
||||
}
|
||||
return (List<T>)result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
public class MaterialPackage extends GenericPackage {
|
||||
public MaterialPackage(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class Preface extends MXFInterchangeObject {
|
||||
private Date lastModifiedDate;
|
||||
|
||||
private int objectModelVersion;
|
||||
|
||||
private UL op;
|
||||
|
||||
private UL[] essenceContainers;
|
||||
|
||||
private UL[] dmSchemes;
|
||||
|
||||
public Preface(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 15106:
|
||||
this.lastModifiedDate = readDate(_bb);
|
||||
break;
|
||||
case 15111:
|
||||
this.objectModelVersion = _bb.getInt();
|
||||
break;
|
||||
case 15113:
|
||||
this.op = UL.read(_bb);
|
||||
break;
|
||||
case 15114:
|
||||
this.essenceContainers = readULBatch(_bb);
|
||||
break;
|
||||
case 15115:
|
||||
this.dmSchemes = readULBatch(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public Date getLastModifiedDate() {
|
||||
return this.lastModifiedDate;
|
||||
}
|
||||
|
||||
public int getObjectModelVersion() {
|
||||
return this.objectModelVersion;
|
||||
}
|
||||
|
||||
public UL getOp() {
|
||||
return this.op;
|
||||
}
|
||||
|
||||
public UL[] getEssenceContainers() {
|
||||
return this.essenceContainers;
|
||||
}
|
||||
|
||||
public UL[] getDmSchemes() {
|
||||
return this.dmSchemes;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class RGBAEssenceDescriptor extends GenericPictureEssenceDescriptor {
|
||||
private int componentMaxRef;
|
||||
|
||||
private int componentMinRef;
|
||||
|
||||
private int alphaMaxRef;
|
||||
|
||||
private int alphaMinRef;
|
||||
|
||||
private byte scanningDirection;
|
||||
|
||||
private ByteBuffer pixelLayout;
|
||||
|
||||
private ByteBuffer palette;
|
||||
|
||||
private ByteBuffer paletteLayout;
|
||||
|
||||
public RGBAEssenceDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 13318:
|
||||
this.componentMaxRef = _bb.getInt();
|
||||
break;
|
||||
case 13319:
|
||||
this.componentMinRef = _bb.getInt();
|
||||
break;
|
||||
case 13320:
|
||||
this.alphaMaxRef = _bb.getInt();
|
||||
break;
|
||||
case 13321:
|
||||
this.alphaMinRef = _bb.getInt();
|
||||
break;
|
||||
case 13317:
|
||||
this.scanningDirection = _bb.get();
|
||||
break;
|
||||
case 13313:
|
||||
this.pixelLayout = _bb;
|
||||
break;
|
||||
case 13315:
|
||||
this.palette = _bb;
|
||||
break;
|
||||
case 13316:
|
||||
this.paletteLayout = _bb;
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x",
|
||||
entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public int getComponentMaxRef() {
|
||||
return this.componentMaxRef;
|
||||
}
|
||||
|
||||
public int getComponentMinRef() {
|
||||
return this.componentMinRef;
|
||||
}
|
||||
|
||||
public int getAlphaMaxRef() {
|
||||
return this.alphaMaxRef;
|
||||
}
|
||||
|
||||
public int getAlphaMinRef() {
|
||||
return this.alphaMinRef;
|
||||
}
|
||||
|
||||
public byte getScanningDirection() {
|
||||
return this.scanningDirection;
|
||||
}
|
||||
|
||||
public ByteBuffer getPixelLayout() {
|
||||
return this.pixelLayout;
|
||||
}
|
||||
|
||||
public ByteBuffer getPalette() {
|
||||
return this.palette;
|
||||
}
|
||||
|
||||
public ByteBuffer getPaletteLayout() {
|
||||
return this.paletteLayout;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class Sequence extends MXFStructuralComponent {
|
||||
private UL[] structuralComponentsRefs;
|
||||
|
||||
public Sequence(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 4097:
|
||||
this.structuralComponentsRefs = readULBatch(entry.getValue());
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL[] getStructuralComponentsRefs() {
|
||||
return this.structuralComponentsRefs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class SourceClip extends MXFStructuralComponent {
|
||||
private long startPosition;
|
||||
|
||||
private int sourceTrackId;
|
||||
|
||||
private UL sourcePackageUid;
|
||||
|
||||
public SourceClip(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 4609:
|
||||
this.startPosition = _bb.getLong();
|
||||
break;
|
||||
case 4353:
|
||||
this.sourcePackageUid = UL.read(_bb);
|
||||
break;
|
||||
case 4354:
|
||||
this.sourceTrackId = _bb.getInt();
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL getSourcePackageUid() {
|
||||
return this.sourcePackageUid;
|
||||
}
|
||||
|
||||
public long getStartPosition() {
|
||||
return this.startPosition;
|
||||
}
|
||||
|
||||
public int getSourceTrackId() {
|
||||
return this.sourceTrackId;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class SourcePackage extends GenericPackage {
|
||||
private UL[] trackRefs;
|
||||
|
||||
private UL descriptorRef;
|
||||
|
||||
public SourcePackage(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 18177:
|
||||
this.descriptorRef = UL.read(_bb);
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public UL[] getTrackRefs() {
|
||||
return this.trackRefs;
|
||||
}
|
||||
|
||||
public UL getDescriptorRef() {
|
||||
return this.descriptorRef;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
|
||||
public class TimecodeComponent extends MXFStructuralComponent {
|
||||
private long start;
|
||||
|
||||
private int base;
|
||||
|
||||
private int dropFrame;
|
||||
|
||||
public TimecodeComponent(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 5377:
|
||||
this.start = _bb.getLong();
|
||||
break;
|
||||
case 5378:
|
||||
this.base = _bb.getShort();
|
||||
break;
|
||||
case 5379:
|
||||
this.dropFrame = _bb.get();
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public long getStart() {
|
||||
return this.start;
|
||||
}
|
||||
|
||||
public int getBase() {
|
||||
return this.base;
|
||||
}
|
||||
|
||||
public int getDropFrame() {
|
||||
return this.dropFrame;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import org.jcodec.common.logging.Logger;
|
||||
import org.jcodec.common.model.Rational;
|
||||
|
||||
public class TimelineTrack extends GenericTrack {
|
||||
private Rational editRate;
|
||||
|
||||
private long origin;
|
||||
|
||||
public TimelineTrack(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 19201:
|
||||
this.editRate = new Rational(_bb.getInt(), _bb.getInt());
|
||||
break;
|
||||
case 19202:
|
||||
this.origin = _bb.getLong();
|
||||
break;
|
||||
default:
|
||||
Logger.warn(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public Rational getEditRate() {
|
||||
return this.editRate;
|
||||
}
|
||||
|
||||
public long getOrigin() {
|
||||
return this.origin;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.jcodec.common.Preconditions;
|
||||
import org.jcodec.common.StringUtils;
|
||||
import org.jcodec.platform.Platform;
|
||||
|
||||
public class UL {
|
||||
private final byte[] bytes;
|
||||
|
||||
public UL(byte[] bytes) {
|
||||
Preconditions.checkNotNull(bytes);
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public static UL newULFromInts(int[] args) {
|
||||
byte[] bytes = new byte[args.length];
|
||||
for (int i = 0; i < args.length; i++)
|
||||
bytes[i] = (byte)args[i];
|
||||
return new UL(bytes);
|
||||
}
|
||||
|
||||
public static UL newUL(String ul) {
|
||||
Preconditions.checkNotNull(ul);
|
||||
String[] split = StringUtils.splitS(ul, ".");
|
||||
byte[] b = new byte[split.length];
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
int parseInt = Integer.parseInt(split[i], 16);
|
||||
b[i] = (byte)parseInt;
|
||||
}
|
||||
return new UL(b);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (this.bytes[4] & 0xFF) << 24 | (this.bytes[5] & 0xFF) << 16 | (this.bytes[6] & 0xFF) << 8 | this.bytes[7] & 0xFF;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof UL))
|
||||
return false;
|
||||
byte[] other = ((UL)obj).bytes;
|
||||
for (int i = 4; i < Math.min(this.bytes.length, other.length); i++) {
|
||||
if (this.bytes[i] != other[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean maskEquals(UL o, int mask) {
|
||||
if (o == null)
|
||||
return false;
|
||||
byte[] other = o.bytes;
|
||||
mask >>= 4;
|
||||
for (int i = 4; i < Math.min(this.bytes.length, other.length); i++, mask >>= 1) {
|
||||
if ((mask & 0x1) == 1 && this.bytes[i] != other[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final char[] hex = new char[] {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
|
||||
public String toString() {
|
||||
if (this.bytes.length == 0)
|
||||
return "";
|
||||
char[] str = new char[this.bytes.length * 3 - 1];
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
for (i = 0; i < this.bytes.length - 1; i++) {
|
||||
str[j++] = hex[this.bytes[i] >> 4 & 0xF];
|
||||
str[j++] = hex[this.bytes[i] & 0xF];
|
||||
str[j++] = '.';
|
||||
}
|
||||
str[j++] = hex[this.bytes[i] >> 4 & 0xF];
|
||||
str[j++] = hex[this.bytes[i] & 0xF];
|
||||
return Platform.stringFromChars(str);
|
||||
}
|
||||
|
||||
public int get(int i) {
|
||||
return this.bytes[i];
|
||||
}
|
||||
|
||||
public static UL read(ByteBuffer _bb) {
|
||||
byte[] umid = new byte[16];
|
||||
_bb.get(umid);
|
||||
return new UL(umid);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
package org.jcodec.containers.mxf.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public class WaveAudioDescriptor extends GenericSoundEssenceDescriptor {
|
||||
private short blockAlign;
|
||||
|
||||
private byte sequenceOffset;
|
||||
|
||||
private int avgBps;
|
||||
|
||||
private UL channelAssignment;
|
||||
|
||||
private int peakEnvelopeVersion;
|
||||
|
||||
private int peakEnvelopeFormat;
|
||||
|
||||
private int pointsPerPeakValue;
|
||||
|
||||
private int peakEnvelopeBlockSize;
|
||||
|
||||
private int peakChannels;
|
||||
|
||||
private int peakFrames;
|
||||
|
||||
private ByteBuffer peakOfPeaksPosition;
|
||||
|
||||
private ByteBuffer peakEnvelopeTimestamp;
|
||||
|
||||
private ByteBuffer peakEnvelopeData;
|
||||
|
||||
public WaveAudioDescriptor(UL ul) {
|
||||
super(ul);
|
||||
}
|
||||
|
||||
protected void read(Map<Integer, ByteBuffer> tags) {
|
||||
super.read(tags);
|
||||
for (Iterator<Map.Entry<Integer, ByteBuffer>> it = tags.entrySet().iterator(); it.hasNext(); ) {
|
||||
Map.Entry<Integer, ByteBuffer> entry = it.next();
|
||||
ByteBuffer _bb = entry.getValue();
|
||||
switch ((Integer)entry.getKey()) {
|
||||
case 15626:
|
||||
this.blockAlign = _bb.getShort();
|
||||
break;
|
||||
case 15627:
|
||||
this.sequenceOffset = _bb.get();
|
||||
break;
|
||||
case 15625:
|
||||
this.avgBps = _bb.getInt();
|
||||
break;
|
||||
case 15666:
|
||||
this.channelAssignment = UL.read(_bb);
|
||||
break;
|
||||
case 15657:
|
||||
this.peakEnvelopeVersion = _bb.getInt();
|
||||
break;
|
||||
case 15658:
|
||||
this.peakEnvelopeFormat = _bb.getInt();
|
||||
break;
|
||||
case 15659:
|
||||
this.pointsPerPeakValue = _bb.getInt();
|
||||
break;
|
||||
case 15660:
|
||||
this.peakEnvelopeBlockSize = _bb.getInt();
|
||||
break;
|
||||
case 15661:
|
||||
this.peakChannels = _bb.getInt();
|
||||
break;
|
||||
case 15662:
|
||||
this.peakFrames = _bb.getInt();
|
||||
break;
|
||||
case 15663:
|
||||
this.peakOfPeaksPosition = _bb;
|
||||
break;
|
||||
case 15664:
|
||||
this.peakEnvelopeTimestamp = _bb;
|
||||
break;
|
||||
case 15665:
|
||||
this.peakEnvelopeData = _bb;
|
||||
break;
|
||||
default:
|
||||
System.out.println(String.format("Unknown tag [ " + String.valueOf(this.ul) + "]: %04x", entry.getKey()));
|
||||
continue;
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public short getBlockAlign() {
|
||||
return this.blockAlign;
|
||||
}
|
||||
|
||||
public byte getSequenceOffset() {
|
||||
return this.sequenceOffset;
|
||||
}
|
||||
|
||||
public int getAvgBps() {
|
||||
return this.avgBps;
|
||||
}
|
||||
|
||||
public UL getChannelAssignment() {
|
||||
return this.channelAssignment;
|
||||
}
|
||||
|
||||
public int getPeakEnvelopeVersion() {
|
||||
return this.peakEnvelopeVersion;
|
||||
}
|
||||
|
||||
public int getPeakEnvelopeFormat() {
|
||||
return this.peakEnvelopeFormat;
|
||||
}
|
||||
|
||||
public int getPointsPerPeakValue() {
|
||||
return this.pointsPerPeakValue;
|
||||
}
|
||||
|
||||
public int getPeakEnvelopeBlockSize() {
|
||||
return this.peakEnvelopeBlockSize;
|
||||
}
|
||||
|
||||
public int getPeakChannels() {
|
||||
return this.peakChannels;
|
||||
}
|
||||
|
||||
public int getPeakFrames() {
|
||||
return this.peakFrames;
|
||||
}
|
||||
|
||||
public ByteBuffer getPeakOfPeaksPosition() {
|
||||
return this.peakOfPeaksPosition;
|
||||
}
|
||||
|
||||
public ByteBuffer getPeakEnvelopeTimestamp() {
|
||||
return this.peakEnvelopeTimestamp;
|
||||
}
|
||||
|
||||
public ByteBuffer getPeakEnvelopeData() {
|
||||
return this.peakEnvelopeData;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue