package org.jcodec.codecs.mpeg12; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.util.ArrayList; import java.util.List; import org.jcodec.codecs.mpeg12.bitstream.PictureHeader; import org.jcodec.common.io.NIOUtils; import org.jcodec.common.model.Packet.FrameType; import org.jcodec.containers.mps.MPEGPacket; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * Pulls frames from MPEG elementary stream * * @author The JCodec project * */ public class MPEGES extends SegmentReader { private int frameNo; public long lastKnownDuration; public MPEGES(ReadableByteChannel channel, int fetchSize) throws IOException { super(channel, fetchSize); } /** * Reads one MPEG1/2 video frame from MPEG1/2 elementary stream into a * provided buffer. * * @param buffer * A buffer to use for the data. * @return A packet with a video frame or null at for end of the stream. The * data buffer inside the packet will be a sub-buffer of a 'buffer' * provided as an argument. * @throws IOException */ public MPEGPacket getFrame(ByteBuffer buffer) throws IOException { ByteBuffer dup = buffer.duplicate(); while (curMarker != 0x100 && curMarker != 0x1b3 && skipToMarker()) ; while (curMarker != 0x100 && readToNextMarker(dup)) ; readToNextMarker(dup); while (curMarker != 0x100 && curMarker != 0x1b3 && readToNextMarker(dup)) ; dup.flip(); PictureHeader ph = MPEGDecoder.getPictureHeader(dup.duplicate()); return dup.hasRemaining() ? new MPEGPacket(dup, 0, 90000, 0, frameNo++, ph.picture_coding_type <= MPEGConst.IntraCoded ? FrameType.KEY : FrameType.INTER, null) : null; } /** * Reads one MPEG1/2 video frame from MPEG1/2 elementary stream. * * @return A packet with a video frame or null at the end of stream. * @throws IOException */ public MPEGPacket getFrame() throws IOException { while (curMarker != 0x100 && curMarker != 0x1b3 && skipToMarker()) ; List<ByteBuffer> buffers = new ArrayList<ByteBuffer>(); // Reading to the frame header, sequence header, sequence header // extensions and group header go in here while (curMarker != 0x100 && !done) readToNextMarkerBuffers(buffers); // Reading the frame header readToNextMarkerBuffers(buffers); // Reading the slices, will stop on encounter of a frame header of the // next frame or a sequence header while (curMarker != 0x100 && curMarker != 0x1b3 && !done) readToNextMarkerBuffers(buffers); ByteBuffer dup = NIOUtils.combineBuffers(buffers); PictureHeader ph = MPEGDecoder.getPictureHeader(dup.duplicate()); return dup.hasRemaining() ? new MPEGPacket(dup, 0, 90000, 0, frameNo++, ph.picture_coding_type <= MPEGConst.IntraCoded ? FrameType.KEY : FrameType.INTER, null) : null; } }