Regalamiunsorriso/decompiled-libs/www/acxent-videoj-1.0.0/org/jcodec/api/FrameGrab.java

202 lines
7.2 KiB
Java

package org.jcodec.api;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.jcodec.api.specific.AVCMP4Adaptor;
import org.jcodec.api.specific.ContainerAdaptor;
import org.jcodec.common.Codec;
import org.jcodec.common.DemuxerTrackMeta;
import org.jcodec.common.Format;
import org.jcodec.common.JCodecUtil;
import org.jcodec.common.SeekableDemuxerTrack;
import org.jcodec.common.io.FileChannelWrapper;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.common.io.SeekableByteChannel;
import org.jcodec.common.model.Packet;
import org.jcodec.common.model.Picture;
import org.jcodec.containers.mp4.demuxer.MP4Demuxer;
public class FrameGrab {
private SeekableDemuxerTrack videoTrack;
private ContainerAdaptor decoder;
private final ThreadLocal<byte[][]> buffers;
public static FrameGrab createFrameGrab(SeekableByteChannel _in) throws IOException, JCodecException {
SeekableDemuxerTrack videoTrack_;
ByteBuffer header = ByteBuffer.allocate(65536);
_in.read(header);
header.flip();
Format detectFormat = JCodecUtil.detectFormatBuffer(header);
if (detectFormat == null)
throw new UnsupportedFormatException("Could not detect the format of the input video.");
if (Format.MOV == detectFormat) {
MP4Demuxer d1 = MP4Demuxer.createMP4Demuxer(_in);
videoTrack_ = (SeekableDemuxerTrack)d1.getVideoTrack();
} else {
if (Format.MPEG_PS == detectFormat)
throw new UnsupportedFormatException("MPEG PS is temporarily unsupported.");
if (Format.MPEG_TS == detectFormat)
throw new UnsupportedFormatException("MPEG TS is temporarily unsupported.");
throw new UnsupportedFormatException("Container format is not supported by JCodec");
}
FrameGrab fg = new FrameGrab(videoTrack_, detectDecoder(videoTrack_));
fg.decodeLeadingFrames();
return fg;
}
public FrameGrab(SeekableDemuxerTrack videoTrack, ContainerAdaptor decoder) {
this.videoTrack = videoTrack;
this.decoder = decoder;
this.buffers = new ThreadLocal<>();
}
private SeekableDemuxerTrack sdt() throws JCodecException {
if (!(this.videoTrack instanceof SeekableDemuxerTrack))
throw new JCodecException("Not a seekable track");
return this.videoTrack;
}
public FrameGrab seekToSecondPrecise(double second) throws IOException, JCodecException {
sdt().seek(second);
decodeLeadingFrames();
return this;
}
public FrameGrab seekToFramePrecise(int frameNumber) throws IOException, JCodecException {
sdt().gotoFrame((long)frameNumber);
decodeLeadingFrames();
return this;
}
public FrameGrab seekToSecondSloppy(double second) throws IOException, JCodecException {
sdt().seek(second);
goToPrevKeyframe();
return this;
}
public FrameGrab seekToFrameSloppy(int frameNumber) throws IOException, JCodecException {
sdt().gotoFrame((long)frameNumber);
goToPrevKeyframe();
return this;
}
private void goToPrevKeyframe() throws IOException, JCodecException {
sdt().gotoFrame((long)detectKeyFrame((int)sdt().getCurFrame()));
}
private void decodeLeadingFrames() throws IOException, JCodecException {
SeekableDemuxerTrack sdt = sdt();
int curFrame = (int)sdt.getCurFrame();
int keyFrame = detectKeyFrame(curFrame);
sdt.gotoFrame((long)keyFrame);
Packet frame = sdt.nextFrame();
if (this.decoder == null)
this.decoder = detectDecoder(sdt);
while (frame.getFrameNo() < (long)curFrame) {
this.decoder.decodeFrame(frame, getBuffer());
frame = sdt.nextFrame();
}
sdt.gotoFrame((long)curFrame);
}
private byte[][] getBuffer() {
byte[][] buf = this.buffers.get();
if (buf == null) {
buf = this.decoder.allocatePicture();
this.buffers.set(buf);
}
return buf;
}
private int detectKeyFrame(int start) throws IOException {
int[] seekFrames = this.videoTrack.getMeta().getSeekFrames();
if (seekFrames == null)
return start;
int prev = seekFrames[0];
for (int i = 1; i < seekFrames.length &&
seekFrames[i] <= start; i++)
prev = seekFrames[i];
return prev;
}
private static ContainerAdaptor detectDecoder(SeekableDemuxerTrack videoTrack) throws JCodecException {
DemuxerTrackMeta meta = videoTrack.getMeta();
if (Codec.H264 == meta.getCodec())
return new AVCMP4Adaptor(meta);
throw new UnsupportedFormatException("Codec is not supported");
}
public PictureWithMetadata getNativeFrameWithMetadata() throws IOException {
Packet frame = this.videoTrack.nextFrame();
if (frame == null)
return null;
Picture picture = this.decoder.decodeFrame(frame, getBuffer());
return new PictureWithMetadata(picture, frame.getPtsD(), frame.getDurationD(), this.videoTrack.getMeta().getOrientation());
}
public Picture getNativeFrame() throws IOException {
Packet frame = this.videoTrack.nextFrame();
if (frame == null)
return null;
return this.decoder.decodeFrame(frame, getBuffer());
}
public static Picture getFrameAtSec(File file, double second) throws IOException, JCodecException {
FileChannelWrapper ch = null;
try {
ch = NIOUtils.readableChannel(file);
return createFrameGrab(ch).seekToSecondPrecise(second).getNativeFrame();
} finally {
NIOUtils.closeQuietly(ch);
}
}
public static Picture getFrameFromChannelAtSec(SeekableByteChannel file, double second) throws JCodecException, IOException {
return createFrameGrab(file).seekToSecondPrecise(second).getNativeFrame();
}
public static Picture getFrameFromFile(File file, int frameNumber) throws IOException, JCodecException {
FileChannelWrapper ch = null;
try {
ch = NIOUtils.readableChannel(file);
return createFrameGrab(ch).seekToFramePrecise(frameNumber).getNativeFrame();
} finally {
NIOUtils.closeQuietly(ch);
}
}
public static Picture getFrameFromChannel(SeekableByteChannel file, int frameNumber) throws JCodecException, IOException {
return createFrameGrab(file).seekToFramePrecise(frameNumber).getNativeFrame();
}
public static Picture getNativeFrameAtFrame(SeekableDemuxerTrack vt, ContainerAdaptor decoder, int frameNumber) throws IOException, JCodecException {
return new FrameGrab(vt, decoder).seekToFramePrecise(frameNumber).getNativeFrame();
}
public static Picture getNativeFrameAtSec(SeekableDemuxerTrack vt, ContainerAdaptor decoder, double second) throws IOException, JCodecException {
return new FrameGrab(vt, decoder).seekToSecondPrecise(second).getNativeFrame();
}
public static Picture getNativeFrameSloppy(SeekableDemuxerTrack vt, ContainerAdaptor decoder, int frameNumber) throws IOException, JCodecException {
return new FrameGrab(vt, decoder).seekToFrameSloppy(frameNumber).getNativeFrame();
}
public static Picture getNativeFrameAtSecSloppy(SeekableDemuxerTrack vt, ContainerAdaptor decoder, double second) throws IOException, JCodecException {
return new FrameGrab(vt, decoder).seekToSecondSloppy(second).getNativeFrame();
}
public MediaInfo getMediaInfo() {
return this.decoder.getMediaInfo();
}
public SeekableDemuxerTrack getVideoTrack() {
return this.videoTrack;
}
public ContainerAdaptor getDecoder() {
return this.decoder;
}
}