@Override public void transform(Picture src, Picture dst) { int lumaSize = src.getWidth() * src.getHeight(); arraycopy(src.getPlaneData(0), 0, dst.getPlaneData(0), 0, lumaSize); copyAvg(src.getPlaneData(1), dst.getPlaneData(1), src.getPlaneWidth(1), src.getPlaneHeight(1)); copyAvg(src.getPlaneData(2), dst.getPlaneData(2), src.getPlaneWidth(2), src.getPlaneHeight(2)); }
@Override public LoanerPicture getPicture(int width, int height, ColorSpace color) { for (Picture picture : buffers) { if (picture.getWidth() == width && picture.getHeight() == height && picture.getColor() == color) { buffers.remove(picture); return new LoanerPicture(picture, 1); } } return new LoanerPicture(Picture.create(width, height, color), 1); }
@Override public int estimateBufferSize(Picture frame) { int fullPlaneSize = frame.getWidth() * frame.getCroppedHeight(); ColorSpace color = frame.getColor(); int totalSize = 0; for (int i = 0; i < color.nComp; i++) { totalSize += (fullPlaneSize >> color.compWidth[i]) >> color.compHeight[i]; } return totalSize; }
@Override public Picture decodeField(ByteBuffer data, byte[][] data2, int field, int step) { Picture res = super.decodeField(data, data2, field, step); return new Picture(res.getWidth() >> 1, res.getHeight() >> 1, res.getData(), null, res.getColor(), 0, new Rect( 0, 0, res.getCroppedWidth() >> 1, res.getCroppedHeight() >> 1)); } }
public static BufferedImage toBufferedImage(Picture src) { if (src.getColor() != ColorSpace.BGR) { Picture bgr = Picture.createCropped(src.getWidth(), src.getHeight(), ColorSpace.BGR, src.getCrop()); if (src.getColor() == ColorSpace.RGB) { new RgbToBgr().transform(src, bgr); } else { Transform transform = ColorUtil.getTransform(src.getColor(), ColorSpace.RGB); transform.transform(src, bgr); new RgbToBgr().transform(bgr, bgr); } src = bgr; } BufferedImage dst = new BufferedImage(src.getCroppedWidth(), src.getCroppedHeight(), BufferedImage.TYPE_3BYTE_BGR); if (src.getCrop() == null) toBufferedImage(src, dst); else toBufferedImageCropped(src, dst); return dst; }
private boolean test(File coded, File ref) throws IOException { BufferH264ES es = new BufferH264ES(NIOUtils.fetchFromFile(coded)); Picture buf = Picture.create(1920, 1088, ColorSpace.YUV420); H264Decoder dec = new H264Decoder(); Packet nextFrame; ByteBuffer _yuv = NIOUtils.fetchFromFile(ref); while ((nextFrame = es.nextFrame()) != null) { Picture out = dec.decodeFrame(nextFrame.getData(), buf.getData()).cropped(); Picture pic = out.createCompatible(); pic.copyFrom(out); int lumaSize = pic.getWidth() * pic.getHeight(); int crSize = lumaSize >> 2; int cbSize = lumaSize >> 2; ByteBuffer yuv = NIOUtils.read(_yuv, lumaSize + crSize + cbSize); if (!Platform.arrayEqualsByte(ArrayUtil.toByteArrayShifted(JCodecUtil2.getAsIntArray(yuv, lumaSize)), pic.getPlaneData(0))) return false; if (!Platform.arrayEqualsByte(ArrayUtil.toByteArrayShifted(JCodecUtil2.getAsIntArray(yuv, crSize)), pic.getPlaneData(1))) return false; if (!Platform.arrayEqualsByte(ArrayUtil.toByteArrayShifted(JCodecUtil2.getAsIntArray(yuv, cbSize)), pic.getPlaneData(2))) return false; } return true; } }
@Override public void transform(Picture img, Picture dst) { byte[] y = img.getData()[0]; byte[] out1 = new byte[3]; byte[] out2 = new byte[3]; byte[][] dstData = dst.getData(); int off = 0, offSrc = 0; for (int i = 0; i < img.getHeight(); i++) { for (int j = 0; j < img.getWidth() >> 1; j++) { int offY = off << 1; RgbToYuv420p.rgb2yuv(y[offSrc++], y[offSrc++], y[offSrc++], out1); dstData[0][offY] = out1[0]; RgbToYuv420p.rgb2yuv(y[offSrc++], y[offSrc++], y[offSrc++], out2); dstData[0][offY + 1] = out2[0]; dstData[1][off] = (byte) ((out1[1] + out2[1] + 1) >> 1); dstData[2][off] = (byte) ((out1[2] + out2[2] + 1) >> 1); ++off; } } } }
final Picture rgb = Picture.create(pixelWidth, pixelHeight, ColorSpace.RGB); final BufferedImage bufferedImage = new BufferedImage(pixelWidth, pixelHeight, BufferedImage.TYPE_3BYTE_BGR); final AvcCBox avcC = AvcCBox.parseAvcCBox(ByteBuffer.wrap(codecPrivateData)); decoder.addSps(avcC.getSpsList()); decoder.addPps(avcC.getPpsList()); final Picture buf = Picture.create(pixelWidth + ((16 - (pixelWidth % 16)) % 16), pixelHeight + ((16 - (pixelHeight % 16)) % 16), ColorSpace.YUV420J); final List<ByteBuffer> byteBuffers = splitMOVPacket(frameBuffer, avcC); final Picture pic = decoder.decodeFrameFromNals(byteBuffers, buf.getData()); if (pic != null) { final byte[][] dataTemp = new byte[3][pic.getData().length]; dataTemp[0] = pic.getPlaneData(0); dataTemp[1] = pic.getPlaneData(2); dataTemp[2] = pic.getPlaneData(1); final Picture tmpBuf = Picture.createPicture(pixelWidth, pixelHeight, dataTemp, ColorSpace.YUV420J); transform.transform(tmpBuf, rgb); AWTUtil.toBufferedImage(rgb, bufferedImage);
@Override public void transform(Picture src, Picture dst) { copy(src.getPlaneData(0), dst.getPlaneData(0), src.getWidth(), dst.getWidth(), dst.getHeight()); _copy(src.getPlaneData(1), dst.getPlaneData(1), 0, 0, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1, src.getHeight() >> 1, dst.getHeight()); _copy(src.getPlaneData(1), dst.getPlaneData(1), 0, 1, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1, src.getHeight() >> 1, dst.getHeight()); _copy(src.getPlaneData(2), dst.getPlaneData(2), 0, 0, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1, src.getHeight() >> 1, dst.getHeight()); _copy(src.getPlaneData(2), dst.getPlaneData(2), 0, 1, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1, src.getHeight() >> 1, dst.getHeight()); }
public ByteBuffer doEncodeFrame(Picture pic, ByteBuffer _out, boolean idr, int frameNumber, SliceType frameType) { ByteBuffer dup = _out.duplicate(); int maxSize = Math.min(dup.remaining(), pic.getWidth() * pic.getHeight()); maxSize -= (maxSize >>> 6); // 1.5% to account for escaping int qp = rc.startPicture(pic.getSize(), maxSize, frameType); sps = initSPS(new Size(pic.getCroppedWidth(), pic.getCroppedHeight())); pps = initPPS(); picOut = Picture.create(mbWidth << 4, mbHeight << 4, ColorSpace.YUV420J);
@Override public LoanerPicture filter(Picture picture, PixelStore store) { if (transform == null) { transform = ColorUtil.getTransform(picture.getColor(), outputColor); Logger.debug("Creating transform: " + transform); } LoanerPicture outFrame = store.getPicture(picture.getWidth(), picture.getHeight(), outputColor); outFrame.getPicture().setCrop(picture.getCrop()); transform.transform(picture, outFrame.getPicture()); return outFrame; }
private boolean planeEquals(Picture other, int plane) { int cw = color.compWidth[plane]; int ch = color.compHeight[plane]; int offA = other.getCrop() == null ? 0 : ((other.getCrop().getX() >> cw) + (other.getCrop().getY() >> ch) * (other.getWidth() >> cw)); int offB = crop == null ? 0 : ((crop.getX() >> cw) + (crop.getY() >> ch) * (width >> cw)); byte[] planeData = other.getPlaneData(plane); for (int i = 0; i < getCroppedHeight() >> ch; i++, offA += (other.getWidth() >> cw), offB += (width >> cw)) { for (int j = 0; j < getCroppedWidth() >> cw; j++) { if (planeData[offA + j] != data[plane][offB + j]) return false; } } return true; }
public Picture decodeFrame(ByteBuffer data, byte[][] data2) { if (interlace) { Picture r1 = decodeField(data, data2, topFieldFirst ? 0 : 1, 2); Picture r2 = decodeField(data, data2, topFieldFirst ? 1 : 0, 2); return Picture.createPicture(r1.getWidth(), r1.getHeight() << 1, data2, r1.getColor()); } else { return decodeField(data, data2, 0, 1); } }
public void encodeNativeFrame(Picture pic) throws IOException { if (toEncode == null) { toEncode = Picture.create(pic.getWidth() , pic.getHeight() , encoder.getSupportedColorSpaces()[0]); } // Perform conversion transform.transform(pic, toEncode); // Encode image into H.264 frame, the result is stored in '_out' buffer _out.clear(); ByteBuffer result = encoder.encodeFrame(toEncode, _out); // Based on the frame above form correct MP4 packet spsList.clear(); ppsList.clear(); H264Utils.wipePS(result, spsList, ppsList); H264Utils.encodeMOVPacket(result); // Add packet to video track outTrack.addFrame(new MP4Packet(result, frameNo, timeScale, 1, frameNo, true, null, frameNo, 0)); frameNo++; }
@Override public void outputVideoFrame(VideoFrameWithPacket videoFrame) throws IOException { if (!outputFormat.isVideo() || outputVideoCodec == null) return; Packet outputVideoPacket; ByteBuffer buffer = bufferStore.get(); int bufferSize = videoEncoder.estimateBufferSize(videoFrame.getFrame().getPicture()); if (buffer == null || bufferSize < buffer.capacity()) { buffer = ByteBuffer.allocate(bufferSize); bufferStore.set(buffer); } buffer.clear(); Picture frame = videoFrame.getFrame().getPicture(); EncodedFrame enc = encodeVideo(frame, buffer); outputVideoPacket = Packet.createPacketWithData(videoFrame.getPacket(), NIOUtils.clone(enc.getData())); outputVideoPacket.setFrameType(enc.isKeyFrame() ? FrameType.KEY : FrameType.INTER); outputVideoPacket(outputVideoPacket, org.jcodec.common.VideoCodecMeta.createSimpleVideoCodecMeta(new Size(frame.getWidth(), frame.getHeight()), frame.getColor())); }
@Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof Picture)) return false; Picture other = (Picture) obj; if (other.getCroppedWidth() != getCroppedWidth() || other.getCroppedHeight() != getCroppedHeight() || other.getColor() != color) return false; for (int i = 0; i < getData().length; i++) if (!planeEquals(other, i)) return false; return true; }
public void predictMB(Picture ref, int refX, int vectX, int refY, int vectY, int blkW, int blkH, int refVertStep, int refVertOff, int[][] tgt, int tgtY, int tgtVertStep) { int ch = chromaFormat == Chroma420 ? 1 : 0; int cw = chromaFormat == Chroma444 ? 0 : 1; int sh = chromaFormat == Chroma420 ? 2 : 1; int sw = chromaFormat == Chroma444 ? 1 : 2; predictPlane(ref.getPlaneData(0), refX + vectX, refY + vectY, ref.getPlaneWidth(0), ref.getPlaneHeight(0), refVertStep, refVertOff, tgt[0], tgtY, blkW, blkH, tgtVertStep); predictPlane(ref.getPlaneData(1), (refX >> cw) + vectX / sw, (refY >> ch) + vectY / sh, ref.getPlaneWidth(1), ref.getPlaneHeight(1), refVertStep, refVertOff, tgt[1], tgtY, blkW >> cw, blkH >> ch, tgtVertStep); predictPlane(ref.getPlaneData(2), (refX >> cw) + vectX / sw, (refY >> ch) + vectY / sh, ref.getPlaneWidth(2), ref.getPlaneHeight(2), refVertStep, refVertOff, tgt[2], tgtY, blkW >> cw, blkH >> ch, tgtVertStep); }