/** * Position frame grabber to a specific frame in a movie * * Performs a sloppy seek, meaning that it may actually not seek to exact * frame requested, instead it will seek to the closest key frame * * NOTE: fast, as it just seeks to the closest previous key frame and * doesn't try to decode frames in the middle * * @param frameNumber * @return * @throws IOException * @throws JCodecException */ public FrameGrab seekToFrameSloppy(int frameNumber) throws IOException, JCodecException { sdt().gotoFrame(frameNumber); goToPrevKeyframe(); return this; }
/** * Position frame grabber to a specific frame in a movie. As a result the * next decoded frame will be precisely the requested frame number. * * WARNING: potentially very slow. Use only when you absolutely need precise * seek. Tries to seek to exactly the requested frame and for this it might * have to decode a sequence of frames from the closes key frame. Depending * on GOP structure this may be as many as 500 frames. * * @param frameNumber * @return * @throws IOException * @throws JCodecException */ public FrameGrab seekToFramePrecise(int frameNumber) throws IOException, JCodecException { sdt().gotoFrame(frameNumber); decodeLeadingFrames(); return this; }
private void goToPrevKeyframe() throws IOException, JCodecException { sdt().gotoFrame(detectKeyFrame((int) sdt().getCurFrame())); }
private void decodeLeadingFrames() throws IOException, JCodecException { SeekableDemuxerTrack sdt = sdt(); int curFrame = (int) sdt.getCurFrame(); int keyFrame = detectKeyFrame(curFrame); sdt.gotoFrame(keyFrame); Packet frame = sdt.nextFrame(); if (decoder == null) decoder = detectDecoder(sdt); while (frame.getFrameNo() < curFrame) { decoder.decodeFrame(frame, getBuffer()); frame = sdt.nextFrame(); } sdt.gotoFrame(curFrame); }