package org.jcodec.codecs.mpeg12;
import static org.jcodec.common.io.NIOUtils.cloneBuffer;
import org.jcodec.common.AudioFormat;
import org.jcodec.common.Codec;
import org.jcodec.common.IntArrayList;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.common.io.SeekableByteChannel;
import org.jcodec.common.logging.Logger;
import org.jcodec.common.model.ChannelLabel;
import org.jcodec.common.model.Rational;
import org.jcodec.common.model.Size;
import org.jcodec.containers.mps.MPSUtils;
import org.jcodec.containers.mps.MPSUtils.PESReader;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* This class is part of JCodec ( www.jcodec.org ) This software is distributed
* under FreeBSD License
*
* Gets media info from MPEG PS file
*
* @author The JCodec project
*
*/
public class MPSMediaInfo extends PESReader {
private Map<Integer, MPEGTrackMetadata> infos;
private int pesTried;
private PSM psm;
public MPSMediaInfo() {
this.infos = new HashMap<Integer, MPSMediaInfo.MPEGTrackMetadata>();
}
public static class MPEGTimecodeMetadata {
public String getNumFrames() {
// TODO Auto-generated method stub
return null;
}
public String isDropFrame() {
// TODO Auto-generated method stub
return null;
}
public String getStartCounter() {
// TODO Auto-generated method stub
return null;
}
}
public static class MPEGTrackMetadata {
int streamId;
Codec codec;
ByteBuffer probeData;
public MPEGTrackMetadata(int streamId) {
this.streamId = streamId;
}
public AudioFormat getAudioFormat() {
// TODO Auto-generated method stub
return null;
}
public ChannelLabel[] getChannelLables() {
return null;
}
public Size getDisplaySize() {
// TODO Auto-generated method stub
return null;
}
public Size getCodedSize() {
// TODO Auto-generated method stub
return null;
}
public float getFps() {
// TODO Auto-generated method stub
return 0;
}
public float getDuration() {
// TODO Auto-generated method stub
return 0;
}
public String getFourcc() {
// TODO Auto-generated method stub
return null;
}
public Rational getFpsR() {
// TODO Auto-generated method stub
return null;
}
public int getNumFrames() {
// TODO Auto-generated method stub
return 0;
}
public MPEGTimecodeMetadata getTimecode() {
return null;
}
}
public List<MPEGTrackMetadata> getMediaInfo(File f) throws IOException {
try {
new NIOUtils.FileReader() {
@Override
protected void data(ByteBuffer data, long filePos) {
analyseBuffer(data, filePos);
}
@Override
protected void done() {
}
}.readFile(f, 0x10000, null);
} catch (MediaInfoDone e) {
Logger.info("Media info done");
}
return getInfos();
}
public static class MediaInfoDone extends RuntimeException {
};
@Override
protected void pes(ByteBuffer pesBuffer, long start, int pesLen, int stream) {
if (!MPSUtils.mediaStream(stream))
return;
MPEGTrackMetadata info = infos.get(stream);
if (info == null) {
info = new MPEGTrackMetadata(stream);
infos.put(stream, info);
}
if (info.probeData == null)
info.probeData = cloneBuffer(pesBuffer);
if (++pesTried >= 100) {
deriveMediaInfo();
throw new MediaInfoDone();
}
}
private void deriveMediaInfo() {
Collection<MPEGTrackMetadata> values = infos.values();
for (MPEGTrackMetadata stream : values) {
int streamId = 0x100 | stream.streamId;
if (streamId >= MPSUtils.AUDIO_MIN && streamId <= MPSUtils.AUDIO_MAX) {
stream.codec = Codec.MP2;
} else if (streamId == MPSUtils.PRIVATE_1) {
ByteBuffer dup = stream.probeData.duplicate();
MPSUtils.readPESHeader(dup, 0);
int type = dup.get() & 0xff;
if (type >= 0x80 && type <= 0x87) {
stream.codec = Codec.AC3;
} else if ((type >= 0x88 && type <= 0x8f) || (type >= 0x98 && type <= 0x9f)) {
stream.codec = Codec.DTS;
} else if (type >= 0xa0 && type <= 0xaf) {
stream.codec = Codec.PCM_DVD;
} else if (type >= 0xb0 && type <= 0xbf) {
stream.codec = Codec.TRUEHD;
} else if (type >= 0xc0 && type <= 0xcf) {
stream.codec = Codec.AC3;
}
} else if (streamId >= MPSUtils.VIDEO_MIN && streamId <= MPSUtils.VIDEO_MAX) {
stream.codec = Codec.MPEG2;
}
}
}
private int[] parseSystem(ByteBuffer pesBuffer) {
NIOUtils.skip(pesBuffer, 12);
IntArrayList result = IntArrayList.createIntArrayList();
while (pesBuffer.remaining() >= 3 && (pesBuffer.get(pesBuffer.position()) & 0x80) == 0x80) {
result.add(pesBuffer.get() & 0xff);
pesBuffer.getShort();
}
return result.toArray();
}
public static class PSM {
}
private PSM parsePSM(ByteBuffer pesBuffer) {
pesBuffer.getInt();
short psmLen = pesBuffer.getShort();
if (psmLen > 1018)
throw new RuntimeException("Invalid PSM");
byte b0 = pesBuffer.get();
byte b1 = pesBuffer.get();
if ((b1 & 1) != 1)
throw new RuntimeException("Invalid PSM");
short psiLen = pesBuffer.getShort();
ByteBuffer psi = NIOUtils.read(pesBuffer, psiLen & 0xffff);
short elStreamLen = pesBuffer.getShort();
parseElStreams(NIOUtils.read(pesBuffer, elStreamLen & 0xffff));
int crc = pesBuffer.getInt();
return new PSM();
}
private void parseElStreams(ByteBuffer buf) {
while (buf.hasRemaining()) {
byte streamType = buf.get();
byte streamId = buf.get();
short strInfoLen = buf.getShort();
ByteBuffer strInfo = NIOUtils.read(buf, strInfoLen & 0xffff);
}
}
public List<MPEGTrackMetadata> getInfos() {
return new ArrayList<MPEGTrackMetadata>(infos.values());
}
public static void main1(String[] args) throws IOException {
new MPSMediaInfo().getMediaInfo(new File(args[0]));
}
public static MPSMediaInfo extract(SeekableByteChannel input) {
// TODO Auto-generated method stub
return null;
}
public List<MPEGTrackMetadata> getAudioTracks() {
return null;
}
public MPEGTrackMetadata getVideoTrack() {
return null;
}
}