I try to load an video into an Vectorpublish document.
Everything works find so far. But at frame 150 the Video (huge mp4-file about 56.2 Gibibyte) decoder breaks.
This is the code.
package net.vectorpublish.desktop.vp.video;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import org.jcodec.api.FrameGrab;
import org.jcodec.codecs.h264.io.model.Frame;
import org.jcodec.common.io.FileChannelWrapper;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.common.model.Picture;
import org.jcodec.scale.AWTUtil;
import net.vectorpublish.desktop.vp.History;
import net.vectorpublish.desktop.vp.api.history.Redo;
import net.vectorpublish.desktop.vp.api.layer.LayerSelectionListener;
import net.vectorpublish.desktop.vp.api.ui.Dialog;
import net.vectorpublish.desktop.vp.api.ui.KeyframeSlider;
import net.vectorpublish.desktop.vp.api.ui.ToolBar;
import net.vectorpublish.desktop.vp.api.ui.VPAbstractAction;
import net.vectorpublish.desktop.vp.api.ui.kf.Keyframer;
import net.vectorpublish.desktop.vp.api.vpd.DocumentNode;
import net.vectorpublish.desktop.vp.api.vpd.VectorPublishNode;
import net.vectorpublish.desktop.vp.ui.ImageKey;
import net.vectorpublish.desktop.vp.video.hs.AddVideoStep;
import net.vectorpublish.desktop.vp.video.hs.data.AddVideoStepData;
@Named
@SuppressWarnings("restriction")
public class LoadVideoButton extends VPAbstractAction implements LayerSelectionListener {
public LoadVideoButton() {
super(VideoText.ADD_VIDEO, VideoText.ADD_VIDEO_DESC, true);
}
public DocumentNode doc = null;
@Inject
public Dialog dlg = null;
@Inject
public final KeyframeSlider ks = null;
@Inject
public final History h = null;
@Inject
public final Redo redo = null;
public void actionPerformed(final ActionEvent event) {
new Thread(new Runnable() {
public void run() {
File video = dlg.showOpenFile("mp4", "MP4 video").getAbsoluteFile();
try {
FileChannelWrapper channel = NIOUtils.readableChannel(video);
FrameGrab graber = FrameGrab.createFrameGrab(channel);
int count = graber.getVideoTrack().getMeta().getTotalFrames();
List<BufferedImage> images = new ArrayList<BufferedImage>(count);
for (int frameNo = 0; frameNo < count; frameNo++) {
System.out.println("load frame " + frameNo);
Picture nativeFrame = graber.getNativeFrame();
if (nativeFrame instanceof Frame) {
Frame frame = (Frame) nativeFrame;
BufferedImage bufferedImage = AWTUtil.toBufferedImage(frame);
images.add(bufferedImage);
}
}
NIOUtils.closeQuietly(channel);
AddVideoStepData data = new AddVideoStepData(images);
AddVideoStep step = new AddVideoStep(h, doc.getLastExecutedHistoryStep(), data);
redo.actionPerformed(event);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
@Inject
private final ToolBar tb = null;
@PostConstruct
public void setup() {
setIcons(VideoText.NS, ImageKey.get("add.video"));
tb.add(this);
}
public void notify(Set<VectorPublishNode> arg0) {
if (arg0.size() == 1 && arg0.iterator().next() instanceof DocumentNode) {
doc = (DocumentNode) arg0.iterator().next();
} else {
doc = null;
}
setEnabled(doc != null);
}
}
This is the log:
DefaultI8nImageFactory Found: Image for key net.vectorpublish:io/open/small in cache! (DefaultI8nImageFactory > OpenImpl)
DefaultI8nImageFactory Found: Image for key net.vectorpublish:io/open/large in cache! (DefaultI8nImageFactory > OpenImpl)
DefaultI8nImageFactory Found: Image for key de.e-nexus:video/add.video/small in cache! (DefaultI8nImageFactory > LoadVideoButton)
DefaultI8nImageFactory Found: Image for key de.e-nexus:video/add.video/large in cache! (DefaultI8nImageFactory > LoadVideoButton)
DefaultI8nImageFactory Found: Image for key net.vectorpublish:io/document/small in cache! (DefaultI8nImageFactory > IOContributions > LanguageController)
DefaultLogger Show dialog: Ask dialog. (unknown)
LayerSelectionManager Notify: 9 listeners about tree-selection. (LayerSelectionManager > LayerImpl > NewFile > FilesImpl > FilesImpl > FilesImpl)
AddKeyframe Method in: Check for Add/Modify Keyframe availability. evaluateEnableButton (AddKeyframe > AddKeyframe > LayerSelectionManager > LayerImpl > NewFile > FilesImpl > FilesImpl > FilesImpl)
AddKeyframe Found: 0 Keyframer and 1 non-Keyframer. (AddKeyframe > AddKeyframe > LayerSelectionManager > LayerImpl > NewFile > FilesImpl > FilesImpl > FilesImpl)
LayerSelectionManager Notify: 9 listeners about tree-selection. (LayerSelectionManager > LayerImpl)
AddKeyframe Method in: Check for Add/Modify Keyframe availability. evaluateEnableButton (AddKeyframe > AddKeyframe > LayerSelectionManager > LayerImpl)
AddKeyframe Found: 0 Keyframer and 0 non-Keyframer. (AddKeyframe > AddKeyframe > LayerSelectionManager > LayerImpl)
LayerSelectionManager Notify: 9 listeners about tree-selection. (LayerSelectionManager > LayerImpl)
AddKeyframe Method in: Check for Add/Modify Keyframe availability. evaluateEnableButton (AddKeyframe > AddKeyframe > LayerSelectionManager > LayerImpl)
AddKeyframe Found: 0 Keyframer and 1 non-Keyframer. (AddKeyframe > AddKeyframe > LayerSelectionManager > LayerImpl)
load frame 0
load frame 1
load frame 2
load frame ... (cut)
load frame 148
load frame 149
load frame 150
[WARN] . (:0): IPCM macroblock found. Not tested, may cause unpredictable behavior.
[WARN] . (:0): IPCM macroblock found. Not tested, may cause unpredictable behavior.
java.lang.NullPointerException
at org.jcodec.codecs.h264.decode.deblock.DeblockingFilter.calcBsH(DeblockingFilter.java:160)
at org.jcodec.codecs.h264.decode.deblock.DeblockingFilter.deblockFrame(DeblockingFilter.java:71)
at org.jcodec.codecs.h264.H264Decoder$FrameDecoder.decodeFrame(H264Decoder.java:156)
at org.jcodec.codecs.h264.H264Decoder.decodeFrameFromNals(H264Decoder.java:103)
at org.jcodec.codecs.h264.H264Decoder.decodeFrame(H264Decoder.java:99)
at org.jcodec.api.specific.AVCMP4Adaptor.decodeFrame(AVCMP4Adaptor.java:68)
at org.jcodec.api.FrameGrab.getNativeFrame(FrameGrab.java:242)
at net.vectorpublish.desktop.vp.video.LoadVideoButton$1.run(LoadVideoButton.java:68)
at java.lang.Thread.run(Thread.java:748)
IPCM macroblocks are unuasual, but completely legal. If your decoder doesn’t support it, use a different decoder, or convert this video first.