package org.jcodec.common; import java.io.File; import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.Callable; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.RunnableFuture; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.jcodec.codecs.h264.H264Decoder; import org.jcodec.codecs.mpeg12.MPEGDecoder; import org.jcodec.codecs.ppm.PPMEncoder; import org.jcodec.codecs.prores.ProresDecoder; import org.jcodec.common.model.ColorSpace; import org.jcodec.common.model.Picture; import org.jcodec.common.tools.MathUtil; import org.jcodec.containers.mp4.demuxer.MP4Demuxer; import org.jcodec.containers.mps.MPSDemuxer; import org.jcodec.containers.mps.MTSDemuxer; import org.jcodec.scale.ColorUtil; import org.jcodec.scale.Transform; /** * This class is part of JCodec ( www.jcodec.org ) This software is distributed * under FreeBSD License * * @author The JCodec project * */ public class JCodecUtil { private static final VideoDecoder[] knownDecoders = new VideoDecoder[] { new ProresDecoder(), new MPEGDecoder(), new H264Decoder() }; public enum Format { MOV, MPEG_PS, MPEG_TS } public static Format detectFormat(File f) throws IOException { return detectFormat(NIOUtils.fetchFrom(f, 200 * 1024)); } public static Format detectFormat(ByteBuffer b) { int movScore = MP4Demuxer.probe(b.duplicate()); int psScore = MPSDemuxer.probe(b.duplicate()); int tsScore = MTSDemuxer.probe(b.duplicate()); if (movScore == 0 && psScore == 0 && tsScore == 0) return null; return movScore > psScore ? (movScore > tsScore ? Format.MOV : Format.MPEG_TS) : (psScore > tsScore ? Format.MPEG_PS : Format.MPEG_TS); } public static VideoDecoder detectDecoder(ByteBuffer b) { int maxProbe = 0; VideoDecoder selected = null; for (VideoDecoder vd : knownDecoders) { int probe = vd.probe(b); if (probe > maxProbe) { selected = vd; maxProbe = probe; } } return selected; } public static VideoDecoder getVideoDecoder(String fourcc) { if ("apch".equals(fourcc) || "apcs".equals(fourcc) || "apco".equals(fourcc) || "apcn".equals(fourcc) || "ap4h".equals(fourcc)) return new ProresDecoder(); else if ("m2v1".equals(fourcc)) return new MPEGDecoder(); else return null; } public static void savePictureAsPPM(Picture pic, File file) throws IOException { Transform transform = ColorUtil.getTransform(pic.getColor(), ColorSpace.RGB); Picture rgb = Picture.create(pic.getWidth(), pic.getHeight(), ColorSpace.RGB); transform.transform(pic, rgb); NIOUtils.writeTo(new PPMEncoder().encodeFrame(rgb), file); } public static byte[] asciiString(String fourcc) { char[] ch = fourcc.toCharArray(); byte[] result = new byte[ch.length]; for (int i = 0; i < ch.length; i++) { result[i] = (byte) ch[i]; } return result; } public static void writeBER32(ByteBuffer buffer, int value) { buffer.put((byte) ((value >> 21) | 0x80)); buffer.put((byte) ((value >> 14) | 0x80)); buffer.put((byte) ((value >> 7) | 0x80)); buffer.put((byte) (value & 0x7F)); } public static void writeBER32Var(ByteBuffer bb, int value) { for (int i = 0, bits = MathUtil.log2(value); i < 4 && bits > 0; i++) { bits -= 7; int out = value >> bits; if(bits > 0) out |= 0x80; bb.put((byte)out); } } public static int readBER32(ByteBuffer input) { int size = 0; for (int i = 0; i < 4; i++) { byte b = input.get(); size = (size << 7) | (b & 0x7f); if (((b & 0xff) >> 7) == 0) break; } return size; } public static int[] getAsIntArray(ByteBuffer yuv, int size) { byte[] b = new byte[size]; int[] result = new int[size]; yuv.get(b); for (int i = 0; i < b.length; i++) { result[i] = b[i] & 0xff; } return result; } public static ThreadPoolExecutor getPriorityExecutor(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>(10, PriorityFuture.COMP)) { protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) { RunnableFuture<T> newTaskFor = super.newTaskFor(callable); return new PriorityFuture<T>(newTaskFor, ((PriorityCallable<T>) callable).getPriority()); } }; } public static String removeExtension(String name) { if(name == null) return null; return name.replaceAll("\\.[^\\.]+$", ""); } }