Skip to content

Commit da0f4f6

Browse files
committed
Latest cumulative changes including:
* Addition of a received application ACK notification callback * Lifecycle management improvements * Exposed failure on progressive back-off/retry logic * Hardening/fixing various edge-cases
1 parent 80a58f7 commit da0f4f6

28 files changed

+581
-257
lines changed

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
11
.DS_Store
2+
CMakeCache.txt
3+
CMakeFiles/
4+
Makefile
5+
cmake_install.cmake
6+
kinesis-video-native-build/downloads/
7+
kinesis-video-native-build/kinesis_video_gstreamer_sample_app
8+
kinesis-video-native-build/libKinesisVideoProducerJNI.dylib
9+
kinesis-video-native-build/libproducer.dylib
10+
kinesis-video-native-build/start
11+
kinesis-video-native-build/test_h264_jpg.mkv
12+
kinesis-video-native-build/test_jpeg.mkv

README.md

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,22 @@ Amazon Kinesis Video Streams Producer SDK for C/C++ contains the following sub-d
1717
* kinesis-video-native-build - Native build directory with a build script for Mac OS/Linux/Raspberry PI. This is the directory that will contain the artifacts after the build.
1818

1919
## Building from Source
20+
There are few build-time tools/dependencies which need to be installed in order to build the core SDK libraries and the samples.
21+
22+
### Build Dependencies
23+
Please install the following additional build tools before proceeding (the example below is for Mac Os X).
24+
* autoconf 2.69 (License GPLv3+/Autoconf: GNU GPL version 3 or later) http://www.gnu.org/software/autoconf/autoconf.html
25+
* cmake 3.7/3.8 https://cmake.org/
26+
* flex 2.5.35 Apple(flex-31)
27+
* bison 2.4 (GNU License)
28+
* automake 1.15.1 (GNU License)
29+
* libtool (Apple Inc. version cctools-898)
30+
* xCode (Mac OS) / clang / gcc (xcode-select version 2347)
31+
* Java jdk (for Java JNI compilation)
32+
2033
After you've downloaded the code from GitHub, you can build it on Mac OS or Ubuntu using ./kinesis-video-native-build/install-script script. This will produce the core library, the JNI library, unit tests executable and the sample GStreamer application. The script will download and build the dependent open source components in the 'downloads' directory and link against it.
2134

22-
Important: Set the JAVA_HOME environment variable to your version of the JDK `export JAVA_HOME=<your java home directory>` in order to build and link JNI component.
35+
**Important:** Set the JAVA_HOME environment variable to your version of the JDK `export JAVA_HOME=<your java home directory>` in order to build and link JNI component.
2336

2437
The bulk of the install script is building the open source dependencies. The project is based on CMake so the open source components building can be skipped if the system versions can be used for linking. Running 'cmake . && make' from the kinesis-video-native-build directory will build and link the SDK.
2538

@@ -45,16 +58,6 @@ The projects depend on the following open source components. Running `install-sc
4558
* gst-plugins-ugly
4659
* x264 - https://www.videolan.org/developers/x264.html
4760

48-
### Build Dependencies
49-
Please install the following additional build tools before running install-script.
50-
* autoconf 2.69 (License GPLv3+/Autoconf: GNU GPL version 3 or later) http://www.gnu.org/software/autoconf/autoconf.html
51-
* cmake 3.7/3.8 https://cmake.org/
52-
* bison 2.4 (GNU License)
53-
* automake 1.15.1 (GNU License)
54-
* libtool (Apple Inc. version cctools-898)
55-
* xCode (Mac OS) / clang / gcc (xcode-select version 2347)
56-
* Java jdk (for Java JNI compilation)
57-
5861
## Certificate store integration
5962
Kinesis Video Streams Produicer SDK for C++ needs to establish trust with the backend service through TLS. This is done through validating the CAs in the public certificate store. On Linux-based models, this store is located in /etc/ssl/ directory by default.
6063

@@ -216,11 +219,29 @@ OpenJDK 64-Bit Server VM (build 25.151-b12, mixed mode)
216219

217220
* Raspberry PI failure to load the camera device. To check this is the case run `ls /dev/video*` - it should be file not found. The remedy is to run the following:
218221

219-
> vcgencmd get_camera
220-
supported=1 detected=1
222+
$ls /dev/video* {not found}
223+
224+
$vcgencmd get_camera {output is similar to supported=1 detected=1}
225+
226+
if the driver does not detect the camera then
227+
228+
* Check for the camera setup and whether it's connected properly
229+
* Run firmware update `$ sudo rpi-update` and restart
230+
231+
$sudo modprobe bcm2835-v4l2
232+
233+
$ls /dev/video* {lists the device}
234+
235+
236+
* Raspberry PI timestamp/range assertion at runtime. Update the Raspberry PI firmware.
237+
238+
$ sudo rpi-update
239+
240+
$ sudo reboot
241+
242+
243+
* Raspberry PI GStreamer assertion on gst_value_set_fraction_range_full: assertion 'gst_util_fraction_compare (numerator_start, denominator_start, numerator_end, denominator_end) < 0' failed. The uv4l service running in the background. Kill the service and restart the sample app.
221244

222-
> sudo modprobe bcm2835-v4l2
223-
> ls /dev/video*
224245

225246
* Raspberry PI seg fauls after some time running on libx264.so. Rebuilding the libx264.so library and re-linking the demo application fixes the issue.
226247

kinesis-video-pic/src/client/include/com/amazonaws/kinesis/video/client/Include.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,19 @@ typedef STATUS (*StreamErrorReportFunc)(UINT64,
12001200
UINT64,
12011201
STATUS);
12021202

1203+
/**
1204+
* Reports a received fragment ack for the stream.
1205+
*
1206+
* @param 1 UINT64 - Custom handle passed by the caller.
1207+
* @param 2 STREAM_HANDLE - The stream to report for.
1208+
* @param 3 PFragmentAck - The constructed fragment ack.
1209+
*
1210+
* @return Status of the callback
1211+
*/
1212+
typedef STATUS (*FragmentAckReceivedFunc)(UINT64,
1213+
STREAM_HANDLE,
1214+
PFragmentAck);
1215+
12031216
///////////////////////////////////////////////////////////////
12041217
// State transition callbacks
12051218
///////////////////////////////////////////////////////////////
@@ -1484,6 +1497,7 @@ struct __ClientCallbacks {
14841497
DroppedFrameReportFunc droppedFrameReportFn;
14851498
DroppedFragmentReportFunc droppedFragmentReportFn;
14861499
StreamErrorReportFunc streamErrorReportFn;
1500+
FragmentAckReceivedFunc fragmentAckReceivedFn;
14871501
StreamDataAvailableFunc streamDataAvailableFn;
14881502
StreamReadyFunc streamReadyFn;
14891503
StreamClosedFunc streamClosedFn;

kinesis-video-pic/src/client/src/Client.cpp

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ STATUS freeKinesisVideoClient(PCLIENT_HANDLE pClientHandle)
176176

177177
// Release the underlying objects
178178
for (i = 0; i < pKinesisVideoClient->deviceInfo.streamCount; i++) {
179-
// Call is indempotent so NULL is OK
179+
// Call is idempotent so NULL is OK
180180
retStatus = freeStream(pKinesisVideoClient->streams[i]);
181181
freeStreamStatus = STATUS_FAILED(retStatus) ? retStatus : freeStreamStatus;
182182
}
@@ -485,7 +485,7 @@ STATUS describeStreamResultEvent(UINT64 customData, SERVICE_CALL_RESULT callResu
485485
{
486486
ENTERS();
487487
STATUS retStatus = STATUS_SUCCESS;
488-
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(customData);
488+
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(customData);
489489

490490
DLOGI("Describe stream result event.");
491491

@@ -505,7 +505,7 @@ STATUS createStreamResultEvent(UINT64 customData, SERVICE_CALL_RESULT callResult
505505
{
506506
ENTERS();
507507
STATUS retStatus = STATUS_SUCCESS;
508-
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(customData);
508+
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(customData);
509509

510510
DLOGI("Create stream result event.");
511511

@@ -525,7 +525,7 @@ STATUS getStreamingTokenResultEvent(UINT64 customData, SERVICE_CALL_RESULT callR
525525
{
526526
ENTERS();
527527
STATUS retStatus = STATUS_SUCCESS;
528-
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(customData);
528+
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(customData);
529529

530530
DLOGI("Get streaming token result event.");
531531

@@ -545,7 +545,7 @@ STATUS getStreamingEndpointResultEvent(UINT64 customData, SERVICE_CALL_RESULT ca
545545
{
546546
ENTERS();
547547
STATUS retStatus = STATUS_SUCCESS;
548-
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(customData);
548+
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(customData);
549549

550550
DLOGI("Get streaming endpoint result event.");
551551

@@ -565,7 +565,7 @@ STATUS putStreamResultEvent(UINT64 customData, SERVICE_CALL_RESULT callResult, U
565565
{
566566
ENTERS();
567567
STATUS retStatus = STATUS_SUCCESS;
568-
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(customData);
568+
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(customData);
569569

570570
DLOGI("Put stream result event.");
571571

@@ -595,23 +595,20 @@ STATUS tagResourceResultEvent(UINT64 customData, SERVICE_CALL_RESULT callResult)
595595

596596
objectIdentifier = KINESIS_VIDEO_OBJECT_IDENTIFIER_FROM_CUSTOM_DATA(customData);
597597

598-
switch(objectIdentifier) {
599-
case KINESIS_VIDEO_OBJECT_IDENTIFIER_CLIENT:
600-
pKinesisVideoClient = CLIENT_FROM_CUSTOM_DATA(customData);
598+
// Check if it's a client
599+
if (objectIdentifier == KINESIS_VIDEO_OBJECT_IDENTIFIER_CLIENT) {
600+
pKinesisVideoClient = CLIENT_FROM_CUSTOM_DATA(customData);
601601

602-
// Call tagging result for client
603-
CHK_STATUS(tagClientResult(pKinesisVideoClient, callResult));
604-
break;
602+
// Call tagging result for client
603+
CHK_STATUS(tagClientResult(pKinesisVideoClient, callResult));
604+
} else {
605+
pKinesisVideoStream = FROM_STREAM_HANDLE(customData);
605606

606-
case KINESIS_VIDEO_OBJECT_IDENTIFIER_STREAM:
607-
pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(customData);
607+
// Validate it's a stream object
608+
CHK(pKinesisVideoStream->base.identifier == KINESIS_VIDEO_OBJECT_IDENTIFIER_STREAM, STATUS_INVALID_CUSTOM_DATA);
608609

609-
// Call tagging result for stream
610-
CHK_STATUS(tagStreamResult(pKinesisVideoStream, callResult));
611-
break;
612-
613-
default:
614-
CHK(FALSE, STATUS_INVALID_CUSTOM_DATA);
610+
// Call tagging result for stream
611+
CHK_STATUS(tagStreamResult(pKinesisVideoStream, callResult));
615612
}
616613

617614
CleanUp:
@@ -626,7 +623,7 @@ STATUS kinesisVideoStreamTerminated(STREAM_HANDLE streamHandle, SERVICE_CALL_RES
626623
{
627624
ENTERS();
628625
STATUS retStatus = STATUS_SUCCESS;
629-
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(streamHandle);
626+
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(streamHandle);
630627

631628
DLOGI("Stream terminated event.");
632629

@@ -646,7 +643,7 @@ STATUS kinesisVideoStreamFragmentAck(STREAM_HANDLE streamHandle, PFragmentAck pF
646643
{
647644
ENTERS();
648645
STATUS retStatus = STATUS_SUCCESS;
649-
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(streamHandle);
646+
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(streamHandle);
650647

651648
DLOGS("Stream fragment ACK event.");
652649

@@ -666,7 +663,7 @@ STATUS kinesisVideoStreamParseFragmentAck(STREAM_HANDLE streamHandle, PCHAR ackS
666663
{
667664
ENTERS();
668665
STATUS retStatus = STATUS_SUCCESS;
669-
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(streamHandle);
666+
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(streamHandle);
670667

671668
DLOGS("Parsing stream fragment ACK.");
672669

@@ -690,7 +687,7 @@ VOID viewItemRemoved(PContentView pContentView, UINT64 customData, PViewItem pVi
690687
{
691688
ENTERS();
692689
STATUS retStatus = STATUS_SUCCESS;
693-
PKinesisVideoStream pKinesisVideoStream = FROM_STREAM_HANDLE(customData);
690+
PKinesisVideoStream pKinesisVideoStream = STREAM_FROM_CUSTOM_DATA(customData);
694691
PKinesisVideoClient pKinesisVideoClient = NULL;
695692
BOOL streamLocked = FALSE;
696693

kinesis-video-pic/src/client/src/Include_i.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ typedef __KinesisVideoBase* PKinesisVideoBase;
104104
#define TO_CLIENT_HANDLE(p) ((CLIENT_HANDLE) (p))
105105
#define FROM_CLIENT_HANDLE(h) ((PKinesisVideoClient) (h))
106106

107-
#define TO_STREAM_HANDLE(p) ((STREAM_HANDLE) (p))
108-
#define FROM_STREAM_HANDLE(h) ((PKinesisVideoStream) (h))
107+
#define TO_STREAM_HANDLE(p) (toStreamHandle(p))
108+
#define FROM_STREAM_HANDLE(h) (fromStreamHandle(h))
109109

110110
#define TO_CUSTOM_DATA(p) ((UINT64) (p))
111111
#define STREAM_FROM_CUSTOM_DATA(h) ((PKinesisVideoStream) (h))
@@ -205,6 +205,16 @@ typedef __KinesisVideoClient* PKinesisVideoClient;
205205
////////////////////////////////////////////////////
206206
// Internal functionality
207207
////////////////////////////////////////////////////
208+
/**
209+
* Converts the stream to a stream handle
210+
*/
211+
STREAM_HANDLE toStreamHandle(PKinesisVideoStream);
212+
213+
/**
214+
* Converts handle to a stream
215+
*/
216+
PKinesisVideoStream fromStreamHandle(STREAM_HANDLE);
217+
208218
/**
209219
* Callback function which is invoked when an item gets purged from the view
210220
*/

kinesis-video-pic/src/client/src/Stream.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ STATUS createStream(PKinesisVideoClient pKinesisVideoClient, PStreamInfo pStream
181181
CHK_STATUS(createContentView(maxViewItems,
182182
pKinesisVideoStream->streamInfo.streamCaps.bufferDuration,
183183
viewItemRemoved,
184-
(UINT64) pKinesisVideoStream,
184+
TO_CUSTOM_DATA(pKinesisVideoStream),
185185
&pView));
186186
pKinesisVideoStream->pView = pView;
187187

@@ -1388,4 +1388,26 @@ STATUS checkStreamingTokenExpiration(PKinesisVideoStream pKinesisVideoStream) {
13881388

13891389
LEAVES();
13901390
return retStatus;
1391-
}
1391+
}
1392+
1393+
/**
1394+
* Converts the stream to a stream handle
1395+
*/
1396+
STREAM_HANDLE toStreamHandle(PKinesisVideoStream pKinesisVideoStream) {
1397+
if (pKinesisVideoStream == NULL) {
1398+
return INVALID_STREAM_HANDLE_VALUE;
1399+
} else {
1400+
return (STREAM_HANDLE) &pKinesisVideoStream->pKinesisVideoClient->streams[pKinesisVideoStream->streamId];
1401+
}
1402+
}
1403+
1404+
/**
1405+
* Converts handle to a stream
1406+
*/
1407+
PKinesisVideoStream fromStreamHandle(STREAM_HANDLE streamHandle) {
1408+
if (streamHandle == INVALID_STREAM_HANDLE_VALUE) {
1409+
return NULL;
1410+
} else {
1411+
return *((PKinesisVideoStream*) streamHandle);
1412+
}
1413+
}

kinesis-video-pic/src/client/src/StreamEvent.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,13 @@ STATUS streamFragmentAckEvent(PKinesisVideoStream pKinesisVideoStream, PFragment
639639

640640
CleanUp:
641641

642+
// Notify on success and if we have the callback
643+
if (STATUS_SUCCEEDED(retStatus) && pKinesisVideoClient->clientCallbacks.fragmentAckReceivedFn != NULL) {
644+
pKinesisVideoClient->clientCallbacks.fragmentAckReceivedFn(pKinesisVideoClient->clientCallbacks.customData,
645+
TO_STREAM_HANDLE(pKinesisVideoStream),
646+
pFragmentAck);
647+
}
648+
642649
// Unlock the stream
643650
if (locked) {
644651
pKinesisVideoClient->clientCallbacks.unlockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoStream->base.lock);

kinesis-video-pic/src/client/src/StreamState.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ STATUS executeDescribeStreamState(UINT64 customData, UINT64 time)
8484

8585
pKinesisVideoStream->base.serviceCallContext.pAuthInfo = &pKinesisVideoClient->tokenAuthInfo;
8686
pKinesisVideoStream->base.serviceCallContext.version = SERVICE_CALL_CONTEXT_CURRENT_VERSION;
87-
pKinesisVideoStream->base.serviceCallContext.customData = TO_CUSTOM_DATA(pKinesisVideoStream);
87+
pKinesisVideoStream->base.serviceCallContext.customData = TO_STREAM_HANDLE(pKinesisVideoStream);
8888
pKinesisVideoStream->base.serviceCallContext.timeout = SERVICE_CALL_DEFAULT_TIMEOUT;
8989
pKinesisVideoStream->base.serviceCallContext.callAfter = time;
9090

@@ -406,7 +406,7 @@ STATUS executeGetEndpointStreamState(UINT64 customData, UINT64 time)
406406

407407
pKinesisVideoStream->base.serviceCallContext.pAuthInfo = &pKinesisVideoClient->tokenAuthInfo;
408408
pKinesisVideoStream->base.serviceCallContext.version = SERVICE_CALL_CONTEXT_CURRENT_VERSION;
409-
pKinesisVideoStream->base.serviceCallContext.customData = TO_CUSTOM_DATA(pKinesisVideoStream);
409+
pKinesisVideoStream->base.serviceCallContext.customData = TO_STREAM_HANDLE(pKinesisVideoStream);
410410
pKinesisVideoStream->base.serviceCallContext.timeout = SERVICE_CALL_DEFAULT_TIMEOUT;
411411
pKinesisVideoStream->base.serviceCallContext.callAfter = time;
412412

@@ -442,7 +442,7 @@ STATUS executeGetTokenStreamState(UINT64 customData, UINT64 time)
442442

443443
pKinesisVideoStream->base.serviceCallContext.pAuthInfo = &pKinesisVideoClient->tokenAuthInfo;
444444
pKinesisVideoStream->base.serviceCallContext.version = SERVICE_CALL_CONTEXT_CURRENT_VERSION;
445-
pKinesisVideoStream->base.serviceCallContext.customData = TO_CUSTOM_DATA(pKinesisVideoStream);
445+
pKinesisVideoStream->base.serviceCallContext.customData = TO_STREAM_HANDLE(pKinesisVideoStream);
446446
pKinesisVideoStream->base.serviceCallContext.timeout = SERVICE_CALL_DEFAULT_TIMEOUT;
447447
pKinesisVideoStream->base.serviceCallContext.callAfter = time;
448448

@@ -478,7 +478,7 @@ STATUS executeCreateStreamState(UINT64 customData, UINT64 time)
478478

479479
pKinesisVideoStream->base.serviceCallContext.pAuthInfo = &pKinesisVideoClient->tokenAuthInfo;
480480
pKinesisVideoStream->base.serviceCallContext.version = SERVICE_CALL_CONTEXT_CURRENT_VERSION;
481-
pKinesisVideoStream->base.serviceCallContext.customData = TO_CUSTOM_DATA(pKinesisVideoStream);
481+
pKinesisVideoStream->base.serviceCallContext.customData = TO_STREAM_HANDLE(pKinesisVideoStream);
482482
pKinesisVideoStream->base.serviceCallContext.timeout = SERVICE_CALL_DEFAULT_TIMEOUT;
483483
pKinesisVideoStream->base.serviceCallContext.callAfter = time;
484484

@@ -518,7 +518,7 @@ STATUS executeTagStreamState(UINT64 customData, UINT64 time)
518518

519519
pKinesisVideoStream->base.serviceCallContext.pAuthInfo = &pKinesisVideoClient->tokenAuthInfo;
520520
pKinesisVideoStream->base.serviceCallContext.version = SERVICE_CALL_CONTEXT_CURRENT_VERSION;
521-
pKinesisVideoStream->base.serviceCallContext.customData = TO_CUSTOM_DATA(pKinesisVideoStream);
521+
pKinesisVideoStream->base.serviceCallContext.customData = TO_STREAM_HANDLE(pKinesisVideoStream);
522522
pKinesisVideoStream->base.serviceCallContext.timeout = SERVICE_CALL_DEFAULT_TIMEOUT;
523523
pKinesisVideoStream->base.serviceCallContext.callAfter = time;
524524

@@ -584,7 +584,7 @@ STATUS executePutStreamState(UINT64 customData, UINT64 time)
584584

585585
pKinesisVideoStream->base.serviceCallContext.pAuthInfo = &pKinesisVideoStream->streamingAuthInfo;
586586
pKinesisVideoStream->base.serviceCallContext.version = SERVICE_CALL_CONTEXT_CURRENT_VERSION;
587-
pKinesisVideoStream->base.serviceCallContext.customData = TO_CUSTOM_DATA(pKinesisVideoStream);
587+
pKinesisVideoStream->base.serviceCallContext.customData = TO_STREAM_HANDLE(pKinesisVideoStream);
588588
pKinesisVideoStream->base.serviceCallContext.timeout = SERVICE_CALL_DEFAULT_TIMEOUT;
589589
pKinesisVideoStream->base.serviceCallContext.callAfter = time;
590590

0 commit comments

Comments
 (0)