ImageRotationStage extends PronghornStage { @Override public void run() { if (nextInputFrameTimestamp == NONE && PipeReader.tryReadFragment(imagePipeIn)) { assert PipeReader.getMsgIdx(imagePipeIn) == ImageSchema.MSG_FRAMESTART_1; nextInputFrameWidth = PipeReader.readInt(imagePipeIn, ImageSchema.MSG_FRAMESTART_1_FIELD_WIDTH_101); nextInputFrameHeight = PipeReader.readInt(imagePipeIn, ImageSchema.MSG_FRAMESTART_1_FIELD_HEIGHT_201); nextInputFrameTimestamp = PipeReader.readLong(imagePipeIn, ImageSchema.MSG_FRAMESTART_1_FIELD_TIMESTAMP_301); nextInputFrameSize = PipeReader.readInt(imagePipeIn, ImageSchema.MSG_FRAMESTART_1_FIELD_FRAMEBYTES_401); assert inputFrameHead == NONE || inputFrameHead == FRAME_BUFFERED; inputFrameHead = 0; PipeReader.releaseReadLock(imagePipeIn); } if (rotationRequestTimestamp == NONE && PipeReader.tryReadFragment(imageRotationPipeIn)) { assert PipeReader.getMsgIdx(imageRotationPipeIn) == ImageRotationSchema.MSG_ROTATIONREQUEST_1; long rotationRequestNumerator = PipeReader.readLong(imageRotationPipeIn, ImageRotationSchema.MSG_ROTATIONREQUEST_1_FIELD_NUMERATOR_101); long rotationRequestDenominator = PipeReader.readLong(imageRotationPipeIn, ImageRotationSchema.MSG_ROTATIONREQUEST_1_FIELD_DENOMINATOR_201); rotationRequestTimestamp = PipeReader.readLong(imageRotationPipeIn, ImageRotationSchema.MSG_ROTATIONREQUEST_1_FIELD_TIMESTAMP_301); double theta = rotationRequestNumerator / rotationRequestDenominator; rotationAlpha = -1 * Math.tan(theta / 2); rotationBeta = Math.sin(theta); PipeReader.releaseReadLock(imageRotationPipeIn); } if (nextInputFrameTimestamp != NONE && nextInputFrameTimestamp < rotationRequestTimestamp) { if (inputFrame == null || inputFrame.length != nextInputFrameSize) { inputFrame = new byte[nextInputFrameSize]; } while (PipeReader.tryReadFragment(imagePipeIn)) { assert PipeReader.getMsgIdx(imagePipeIn) == ImageSchema.MSG_FRAMECHUNK_2; inputFrameHead += PipeReader.readBytes(imagePipeIn, ImageSchema.MSG_FRAMECHUNK_2_FIELD_ROWBYTES_102, inputFrame, inputFrameHead); if (inputFrameHead >= inputFrame.length) { inputFrameTimestamp = nextInputFrameTimestamp; inputFrameWidth = nextInputFrameWidth; inputFrameHeight = nextInputFrameHeight; inputFrameHead = FRAME_BUFFERED; nextInputFrameTimestamp = NONE; break; } PipeReader.releaseReadLock(imagePipeIn); } } if (outputFrameHead != NONE || (inputFrameHead == FRAME_BUFFERED && rotationRequestTimestamp != NONE && inputFrameTimestamp < rotationRequestTimestamp)) { if (outputFrameHead == NONE && PipeWriter.tryWriteFragment(imagePipeOut, ImageSchema.MSG_FRAMESTART_1)) { PipeWriter.writeInt(imagePipeOut, ImageSchema.MSG_FRAMESTART_1_FIELD_WIDTH_101, cropWidth); PipeWriter.writeInt(imagePipeOut, ImageSchema.MSG_FRAMESTART_1_FIELD_HEIGHT_201, cropHeight); PipeWriter.writeLong(imagePipeOut, ImageSchema.MSG_FRAMESTART_1_FIELD_TIMESTAMP_301, System.currentTimeMillis()); PipeWriter.writeInt(imagePipeOut, ImageSchema.MSG_FRAMESTART_1_FIELD_FRAMEBYTES_401, outputFrame.length); PipeWriter.writeInt(imagePipeOut, ImageSchema.MSG_FRAMESTART_1_FIELD_BITSPERPIXEL_501, 24); PipeWriter.writeBytes(imagePipeOut, ImageSchema.MSG_FRAMESTART_1_FIELD_ENCODING_601, LinuxImageCaptureStage.OUTPUT_ENCODING); PipeWriter.publishWrites(imagePipeOut); outputFrameHead = 0; Arrays.fill(outputFrame, (byte) 0x00); shearRotateFrame(rotationAlpha, rotationBeta, inputFrame, inputFrameWidth, inputFrameHeight, outputFrame, cropWidth, cropHeight); } if (outputFrameHead >= 0 && PipeWriter.tryWriteFragment(imagePipeOut, ImageSchema.MSG_FRAMECHUNK_2)) { PipeWriter.writeBytes(imagePipeOut, ImageSchema.MSG_FRAMECHUNK_2_FIELD_ROWBYTES_102, outputFrame, outputFrameHead, outputFrameRowSize); PipeWriter.publishWrites(imagePipeOut); outputFrameHead += outputFrameRowSize; if (outputFrameHead >= outputFrame.length) { outputFrameHead = NONE; } } } } ImageRotationStage(GraphManager gm,
                              Pipe<ImageSchema> imagePipeIn,
                              Pipe<ImageRotationSchema> imageRotationPipeIn,
                              Pipe<ImageSchema> imagePipeOut);  ImageRotationStage(GraphManager gm,
                              Pipe<ImageSchema> imagePipeIn,
                              Pipe<ImageRotationSchema> imageRotationPipeIn,
                              Pipe<ImageSchema> imagePipeOut,
                              int cropWidth, int cropHeight); @Override void run(); @Override void shutdown(); static final int DEFAULT_CROP_WIDTH; static final int DEFAULT_CROP_HEIGHT; }
@Test @Ignore public void shouldDownscaleImagesTest() { int iterations = 5; int j = iterations; while (--j>=0) { setup(); NonThreadScheduler scheduler = new NonThreadScheduler(gm); scheduler.startup(); if (PipeWriter.tryWriteFragment(imageRotationInputPipe, ImageRotationSchema.MSG_ROTATIONREQUEST_1)) { PipeWriter.writeLong(imageRotationInputPipe, ImageRotationSchema.MSG_ROTATIONREQUEST_1_FIELD_NUMERATOR_101, ROTATION_ANGLE[0]); PipeWriter.writeLong(imageRotationInputPipe, ImageRotationSchema.MSG_ROTATIONREQUEST_1_FIELD_DENOMINATOR_201, ROTATION_ANGLE[1]); PipeWriter.writeLong(imageRotationInputPipe, ImageRotationSchema.MSG_ROTATIONREQUEST_1_FIELD_TIMESTAMP_301,Long.MAX_VALUE); PipeWriter.publishWrites(imageRotationInputPipe); } while (rotationPipeReaderState.framesProcessed <= 0) { scheduler.run(); readFromRotationPipe(rotationOutputPipe, rotationPipeReaderState, LinuxImageCaptureStage.OUTPUT_ENCODING); } try { Path filePath = Paths.get("src", "test", "images", "cat1-320-240.rotated"); byte[] fileBytes = Files.readAllBytes(filePath); Assert.assertTrue(Arrays.equals(fileBytes, rotationPipeReaderState.currentFrame)); } catch (IOException e) { Assert.fail(e.getMessage()); } } }