in src/main/java/com/amazonaws/kinesisvideo/parser/utilities/H264BoundingBoxFrameRenderer.java [65:129]
private Optional<RekognizedOutput> getRekognizedOutput(final Frame frame,
final Optional<FragmentMetadata> fragmentMetadata) {
Optional<RekognizedOutput> rekognizedOutput = Optional.empty();
if (rekognizedFragmentsIndex != null && fragmentMetadata.isPresent()) {
final String fragmentNumber = fragmentMetadata.get().getFragmentNumberString();
int timeout = 0;
List<RekognizedOutput> rekognizedOutputs = null;
// if rekognizedOutputs is null then Rekognition did not return the results for this fragment.
// Wait until the results are received.
while (true) {
rekognizedOutputs = rekognizedFragmentsIndex.getRekognizedOutputList(fragmentNumber);
if (rekognizedOutputs != null) {
break;
} else {
timeout += waitForResults(WAIT_TIMEOUT);
if (timeout >= maxTimeout) {
log.warn("No rekognized result after waiting for {} ms ", timeout);
break;
}
}
}
if (rekognizedOutputs != null) {
// Currently Rekognition samples frames and calculates the frame offset from the fragment start time.
// So, in order to match with rekognition results, we have to compute the same frame offset from the
// beginning of the fragments.
if (frame.isKeyFrame()) {
keyFrameTimecode = frame.getTimeCode();
log.debug("Key frame timecode : {}", keyFrameTimecode);
}
final long frameOffset = (frame.getTimeCode() > keyFrameTimecode)
? frame.getTimeCode() - keyFrameTimecode : 0;
log.debug("Current Fragment Number : {} Computed Frame offset : {}", fragmentNumber, frameOffset);
if (log.isDebugEnabled()) {
rekognizedOutputs
.forEach(p -> log.debug("frameOffsetInSeconds from Rekognition : {}",
p.getFrameOffsetInSeconds()));
}
// Check whether the computed offset matches the rekognized output frame offset. Rekognition
// output is in seconds whereas the frame offset is calculated in milliseconds.
// NOTE: Rekognition frame offset doesn't exactly match with the computed offset below. So
// take the closest one possible within 10ms delta.
rekognizedOutput = rekognizedOutputs.stream()
.filter(p -> isOffsetDeltaWithinThreshold(frameOffset, p))
.findFirst();
// Remove from the index once the RekognizedOutput is processed. Else it would increase the memory
// footprint and blow up the JVM.
if (rekognizedOutput.isPresent()) {
log.debug("Computed offset matched with retrieved offset. Delta : {}",
Math.abs(frameOffset - (rekognizedOutput.get().getFrameOffsetInSeconds() * MILLIS_IN_SEC)));
rekognizedOutputs.remove(rekognizedOutput.get());
if (rekognizedOutputs.isEmpty()) {
log.debug("All frames processed for this fragment number : {}", fragmentNumber);
rekognizedFragmentsIndex.remove(fragmentNumber);
}
}
}
}
return rekognizedOutput;
}