diff --git a/pom.xml b/pom.xml index 3523af1c69d78377ed4d271581250443599ede07..8511249b220af31f7fb522fe04acbf6c7b4b0b95 100644 --- a/pom.xml +++ b/pom.xml @@ -1884,7 +1884,12 @@ <dependency> <groupId>org.jcodec</groupId> <artifactId>jcodec</artifactId> - <version>0.1.6-3</version> + <version>0.2.3</version> + </dependency> + <dependency> + <groupId>org.jcodec</groupId> + <artifactId>jcodec-javase</artifactId> + <version>0.2.3</version> </dependency> <dependency> <groupId>org.mnode.ical4j</groupId> diff --git a/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java b/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java index 08dff59d4300c6f89952e64ff8caa999a842e38b..36d51ec0fc8ac142f606a2bc09ba977bfad230c2 100644 --- a/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java +++ b/src/main/java/org/olat/core/commons/services/video/MovieServiceImpl.java @@ -28,17 +28,19 @@ import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.List; +import org.apache.logging.log4j.Logger; import org.jcodec.api.FrameGrab; -import org.jcodec.common.FileChannelWrapper; +import org.jcodec.common.Codec; +import org.jcodec.common.io.FileChannelWrapper; import org.jcodec.containers.mp4.boxes.MovieBox; import org.jcodec.containers.mp4.demuxer.MP4Demuxer; +import org.jcodec.scale.AWTUtil; import org.olat.core.commons.services.image.Size; import org.olat.core.commons.services.image.spi.ImageHelperImpl; import org.olat.core.commons.services.thumbnail.CannotGenerateThumbnailException; import org.olat.core.commons.services.thumbnail.FinalSize; import org.olat.core.commons.services.thumbnail.ThumbnailSPI; import org.olat.core.commons.services.video.spi.FLVParser; -import org.apache.logging.log4j.Logger; import org.olat.core.logging.Tracing; import org.olat.core.util.FileUtils; import org.olat.core.util.WorkThreadInformations; @@ -59,18 +61,18 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI { private static final Logger log = Tracing.createLoggerFor(MovieServiceImpl.class); private static final List<String> extensions = new ArrayList<>(); - private static final List<String> fourCCs = new ArrayList<>(); + private static final List<Codec> supportedCodecs = new ArrayList<>(); static { // supported file extensions extensions.add("mp4"); extensions.add("m4v"); extensions.add("mov"); // supported fourCC for H264 codec - fourCCs.add("avc1"); - fourCCs.add("davc"); - fourCCs.add("h264"); - fourCCs.add("x264"); - fourCCs.add("vssh"); + supportedCodecs.add(Codec.codecByFourcc("avc1")); + supportedCodecs.add(Codec.codecByFourcc("davc")); + supportedCodecs.add(Codec.codecByFourcc("h264")); + supportedCodecs.add(Codec.codecByFourcc("x264")); + supportedCodecs.add(Codec.codecByFourcc("vssh")); } @@ -96,9 +98,10 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI { if(extensions.contains(suffix)) { try(RandomAccessFile accessFile = new RandomAccessFile(file, "r"); FileChannel ch = accessFile.getChannel(); - FileChannelWrapper in = new FileChannelWrapper(ch)) { + FileChannelWrapper in = new FileChannelWrapper(ch); + MP4Demuxer demuxer1 = MP4Demuxer.createMP4Demuxer(in)) { + - MP4Demuxer demuxer1 = new MP4Demuxer(in); org.jcodec.common.model.Size size = demuxer1.getMovie().getDisplaySize(); // Case 1: standard case, get dimension from movie int w = size.getWidth(); @@ -117,7 +120,7 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI { // flag of the movie. Those mp4 guys are really // secretive folks, did not find any documentation about // this. Best guess. - org.jcodec.common.model.Size size2 = demuxer1.getVideoTrack().getBox().getCodedSize(); + org.jcodec.common.model.Size size2 = demuxer1.getVideoTrack().getMeta().getVideoCodecMeta().getSize(); w = size2.getHeight(); h = size2.getWidth(); } catch(Exception e) { @@ -161,9 +164,9 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI { if(extensions.contains(suffix)) { try(RandomAccessFile accessFile = new RandomAccessFile(file, "r"); FileChannel ch = accessFile.getChannel(); - FileChannelWrapper in = new FileChannelWrapper(ch)) { - - MP4Demuxer demuxer1 = new MP4Demuxer(in); + FileChannelWrapper in = new FileChannelWrapper(ch); + MP4Demuxer demuxer1 = MP4Demuxer.createMP4Demuxer(in)) { + MovieBox movie = demuxer1.getMovie(); long duration = movie.getDuration(); int timescale = movie.getTimescale(); @@ -196,10 +199,9 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI { if(extensions.contains(suffix)) { try(RandomAccessFile accessFile = new RandomAccessFile(file, "r"); FileChannel ch = accessFile.getChannel(); - FileChannelWrapper in = new FileChannelWrapper(ch)) { - - MP4Demuxer demuxer1 = new MP4Demuxer(in); - return demuxer1.getVideoTrack().getFrameCount(); + FileChannelWrapper in = new FileChannelWrapper(ch); + MP4Demuxer demuxer1 = MP4Demuxer.createMP4Demuxer(in)) { + return demuxer1.getVideoTrack().getMeta().getTotalFrames(); } catch (Exception | AssertionError e) { log.error("Cannot extract num. of frames of: " + media, e); } @@ -226,12 +228,12 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI { FileChannel ch = accessFile.getChannel(); FileChannelWrapper in = new FileChannelWrapper(ch)) { - MP4Demuxer demuxer1 = new MP4Demuxer(in); - String fourCC = demuxer1.getVideoTrack().getFourcc(); - if (fourCCs.contains(fourCC.toLowerCase())) { + MP4Demuxer demuxer1 = MP4Demuxer.createMP4Demuxer(in); + Codec codec = demuxer1.getVideoTrack().getMeta().getCodec(); + if (supportedCodecs.contains(codec)) { return true; } - log.info("Movie file::" + fileName + " has correct suffix::" + suffix + " but fourCC::" + fourCC + " not in our list of supported codecs."); + log.info("Movie file::" + fileName + " has correct suffix::" + suffix + " but fourCC::" + codec + " not in our list of supported codecs."); } catch (Exception | Error e) { // anticipated exception, is not an mp4 file } @@ -251,7 +253,7 @@ public class MovieServiceImpl implements MovieService, ThumbnailSPI { File baseFile = ((LocalFileImpl)file).getBasefile(); File scaledImage = ((LocalFileImpl)thumbnailFile).getBasefile(); - BufferedImage frame = FrameGrab.getFrame(baseFile, 20); + BufferedImage frame = AWTUtil.toBufferedImage(FrameGrab.getFrameFromFile(baseFile, 20)); Size scaledSize = ImageHelperImpl.calcScaledSize(frame, maxWidth, maxHeight); if(ImageHelperImpl.writeTo(frame, scaledImage, scaledSize, "jpeg")) { size = new FinalSize(scaledSize.getWidth(), scaledSize.getHeight()); diff --git a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java index d54ef1081e39e8df7f3ee834401fd4a95686805e..3e6f70d96c254b12267cb45628c9be2be9899bcf 100644 --- a/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java +++ b/src/main/java/org/olat/ims/qti21/ui/components/AssessmentRenderFunctions.java @@ -31,8 +31,8 @@ import java.util.List; import java.util.Map; import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; import org.apache.logging.log4j.Logger; -import org.jcodec.common.IOUtils; import org.olat.core.CoreSpringFactory; import org.olat.core.gui.render.StringOutput; import org.olat.core.logging.Tracing; diff --git a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java index f63b6987aff74cc44fe34b768ee2ee619e56e6fc..7ccc6c0d3f3de2e404d237a3fcef6d9075c5207b 100644 --- a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java +++ b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java @@ -28,9 +28,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.RandomAccessFile; import java.math.RoundingMode; -import java.nio.channels.FileChannel; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -51,7 +49,9 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.logging.log4j.Logger; import org.jcodec.api.FrameGrab; -import org.jcodec.common.FileChannelWrapper; +import org.jcodec.common.io.FileChannelWrapper; +import org.jcodec.common.io.NIOUtils; +import org.jcodec.scale.AWTUtil; import org.olat.core.commons.services.image.Crop; import org.olat.core.commons.services.image.ImageService; import org.olat.core.commons.services.image.Size; @@ -280,19 +280,16 @@ public class VideoManagerImpl implements VideoManager { public boolean getFrame(VFSLeaf video, int frameNumber, VFSLeaf frame) { File videoFile = ((LocalFileImpl)video).getBasefile(); - try (RandomAccessFile randomAccessFile = new RandomAccessFile(videoFile, "r")) { - FileChannel ch = randomAccessFile.getChannel(); - FileChannelWrapper in = new FileChannelWrapper(ch); - FrameGrab frameGrab = new FrameGrab(in).seekToFrameSloppy(frameNumber); + try (FileChannelWrapper in = NIOUtils.readableChannel(videoFile)) { + FrameGrab frameGrab = FrameGrab.createFrameGrab(in).seekToFrameSloppy(frameNumber); OutputStream frameOutputStream = frame.getOutputStream(false); - BufferedImage bufImg = frameGrab.getFrame(); + BufferedImage bufImg = AWTUtil.toBufferedImage(frameGrab.getNativeFrame()); ImageIO.write(bufImg, "JPG", frameOutputStream); // close everything to prevent resource leaks frameOutputStream.close(); in.close(); - ch.close(); return true; } catch (Exception | AssertionError e) { @@ -307,14 +304,11 @@ public class VideoManagerImpl implements VideoManager { BufferedImage bufImg = null; boolean imgBlack = true; int countBlack = 0; - try (RandomAccessFile randomAccessFile = new RandomAccessFile(videoFile, "r")) { + try (FileChannelWrapper in = NIOUtils.readableChannel(videoFile)) { OutputStream frameOutputStream = frame.getOutputStream(false); - - FileChannel ch = randomAccessFile.getChannel(); - FileChannelWrapper in = new FileChannelWrapper(ch); - FrameGrab frameGrab = new FrameGrab(in).seekToFrameSloppy(frameNumber); + FrameGrab frameGrab = FrameGrab.createFrameGrab(in).seekToFrameSloppy(frameNumber); - bufImg = frameGrab.getFrame(); + bufImg = AWTUtil.toBufferedImage(frameGrab.getNativeFrame()); int xmin = bufImg.getMinX(); int ymin = bufImg.getMinY(); @@ -347,7 +341,6 @@ public class VideoManagerImpl implements VideoManager { // close everything to prevent resource leaks frameOutputStream.close(); in.close(); - ch.close(); return imgBlack; } catch (Exception | AssertionError e) {