@@ -340,6 +340,81 @@ public void fragmentAckReceived(final long uploadHandle, @Nonnull final KinesisV
340340 executorService .shutdownNow ();
341341 }
342342
343+ @ Test
344+ @ SuppressWarnings ({"ConstantConditions" })
345+ public void whenRawPutFrameCalledAfterJniFreed_thenExceptionThrown () throws Exception {
346+ final ScheduledExecutorService executorService = Executors .newScheduledThreadPool (2 );
347+ final KinesisVideoCredentialsProvider credentialsProvider = JavaCredentialsFactory
348+ .createKinesisVideoCredentialsProvider (DefaultAWSCredentialsProviderChain .getInstance ());
349+ final KinesisVideoClientConfiguration configuration = KinesisVideoClientConfiguration .builder ()
350+ .withCredentialsProvider (credentialsProvider )
351+ .build ();
352+
353+ final NativeKinesisVideoProducerJni jni = new NativeKinesisVideoProducerJni (
354+ new DefaultAuthCallbacks (credentialsProvider , executorService ,
355+ LogManager .getLogger (NativeKinesisVideoProducerJni .class )),
356+ new DefaultStorageCallbacks (),
357+ new DefaultServiceCallbacksImpl (
358+ LogManager .getLogger (DefaultServiceCallbacksImpl .class ),
359+ executorService , configuration , new JavaKinesisVideoServiceClient ())
360+ );
361+
362+ final String deviceName = "whenRawPutFrameCalledAfterStreamFreed_thenExceptionThrown" ;
363+ jni .createSync (createTestDeviceInfo (deviceName ));
364+ assertTrue (jni .isInitialized ());
365+ assertTrue (jni .isReady ());
366+
367+ final StreamInfo streamInfo = createStreamInfo (this .streamName );
368+ final List <KinesisVideoFragmentAck > acksReceived = new ArrayList <>();
369+
370+ final CountDownLatch streamReady = new CountDownLatch (1 );
371+ final KinesisVideoProducerStream stream = jni .createStream (streamInfo , new DefaultStreamCallbacks () {
372+ @ Override
373+ public void streamReady () throws ProducerException {
374+ super .streamReady ();
375+ streamReady .countDown ();
376+ }
377+
378+ @ Override
379+ public void fragmentAckReceived (final long uploadHandle , @ Nonnull final KinesisVideoFragmentAck fragmentAck )
380+ throws ProducerException {
381+ super .fragmentAckReceived (uploadHandle , fragmentAck );
382+ acksReceived .add (fragmentAck );
383+ }
384+ });
385+ assertTrue ("Timed out while waiting for stream to be created!" ,
386+ streamReady .await (TEN_SECONDS , TimeUnit .SECONDS ));
387+ final long streamHandle = stream .getStreamHandle ();
388+
389+ final KinesisVideoFrame [] frames = createFrameset ();
390+
391+ for (int i = 0 ; i < NUMBER_OF_FRAMES_TO_STREAM ; i ++) {
392+ final KinesisVideoFrame frame = frames [i ];
393+ jni .putFrame (streamHandle , frame );
394+
395+ Thread .sleep (FRAME_DURATION_MS );
396+ }
397+
398+ stream .stopStreamSync ();
399+ jni .freeStream (stream );
400+ jni .free ();
401+
402+ final KinesisVideoFrame frameAfterFree = frames [NUMBER_OF_FRAMES_TO_STREAM ];
403+ try {
404+ jni .putFrame (streamHandle , frameAfterFree );
405+ } catch (final IllegalStateException e ) {
406+ // Expected
407+ log .info ("Received expected IllegalStateException from putFrame" , e );
408+ } catch (final Exception e ) {
409+ log .error ("PutFrame after free threw an unexpected exception" , e );
410+ fail ("Unexpected exception: " + e );
411+ }
412+
413+ assertFalse ("Did not receive any acks!" , acksReceived .isEmpty ());
414+
415+ executorService .shutdownNow ();
416+ }
417+
343418 @ Test
344419 @ SuppressWarnings ({"ConstantConditions" })
345420 public void whenRawPutFrameCalledWithInvalidHandle_thenExceptionThrown () throws Exception {
0 commit comments