in src/main/java/com/amazonaws/kinesisvideo/parser/utilities/H264FrameDecoder.java [55:91]
public BufferedImage decodeH264Frame(final Frame frame, final MkvTrackMetadata trackMetadata) {
final ByteBuffer frameBuffer = frame.getFrameData();
final int pixelWidth = trackMetadata.getPixelWidth().get().intValue();
final int pixelHeight = trackMetadata.getPixelHeight().get().intValue();
codecPrivateData = trackMetadata.getCodecPrivateData().array();
log.debug("Decoding frames ... ");
// Read the bytes that appear to comprise the header
// See: https://www.matroska.org/technical/specs/index.html#simpleblock_structure
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) {
// Work around for color issues in JCodec
// https://github.com/jcodec/jcodec/issues/59
// https://github.com/jcodec/jcodec/issues/192
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);
frameCount++;
}
return bufferedImage;
}