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,202 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue