Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update kvsWebRTCClientMasterGstreamerSample.c - Provide Raspberry Pi hardware encode example #1398

Closed
wants to merge 16 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/close-stale-issues.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Close Stale Issues

# Controls when the action will be run
on:
schedule:
- cron: "0 0 * * *"

jobs:
cleanup:
runs-on: ubuntu-latest
name: Close stale issues
steps:
- uses: actions/[email protected]
with:
stale-issue-message: It looks like this issue has not been active for a long time. If the issue is not resolved, please add an update to the ticket, else it will be automatically resolved in a few days.
close-issue-message: The issue has been stale for a while and hence it has been auto-closed. If the issue persists, feel free to open a new issue with details.

# labels to be added
stale-issue-label: closing-soon
any-of-labels: question,bug

# SLAs
days-before-issue-stale: 7
days-before-issue-close: 3


repo-token: ${{ secrets.GITHUB_TOKEN }}
loglevel: DEBUG
# Set dry-run to true to not perform label or close actions.
dry-run: false


1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sudo: true
branches:
only:
- master
- develop

cache:
- directories:
Expand Down
2 changes: 1 addition & 1 deletion CMake/Dependencies/libkvsCommonLws-CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ include(ExternalProject)

ExternalProject_Add(libkvsCommonLws-download
GIT_REPOSITORY https://github.com/awslabs/amazon-kinesis-video-streams-producer-c.git
GIT_TAG 99c1a8cd8cec88f99c9c4ce3944b53ae341d1491
GIT_TAG c7fce9e06021452ff3c42dc70c8360606b22ad53
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/build
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${OPEN_SRC_INSTALL_PREFIX}
Expand Down
4 changes: 2 additions & 2 deletions CMake/Dependencies/libwebsockets-CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8)

project(libwebsocket-download NONE)

SET(PATCH_COMMAND git apply --ignore-whitespace ${CMAKE_CURRENT_LIST_DIR}/libwebsockets-old-gcc-fix-cast-cmakelists.patch)
SET(PATCH_COMMAND git apply --ignore-whitespace ${CMAKE_CURRENT_LIST_DIR}/libwebsockets-old-gcc-fix-cast-cmakelists.patch ${CMAKE_CURRENT_LIST_DIR}/libwebsockets-leak-pipe-fix.patch)

include(ExternalProject)

Expand All @@ -25,7 +25,7 @@ endif()

ExternalProject_Add(project_libwebsockets
GIT_REPOSITORY https://github.com/warmcat/libwebsockets.git
GIT_TAG v4.2.1
GIT_TAG v4.2.2
PATCH_COMMAND ${PATCH_COMMAND}
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/build
CMAKE_ARGS
Expand Down
36 changes: 36 additions & 0 deletions CMake/Dependencies/libwebsockets-leak-pipe-fix.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Author: Andy Green <[email protected]>
Date: Wed Sep 08 12:25:47 2021 +0200

cancel pipe: make sure we closed it on destroy with no EVENTFD case


diff --git a/lib/core/context.c b/lib/core/context.c
index 6194801..4f3bb45 100644
--- a/lib/core/context.c
+++ b/lib/core/context.c
@@ -1625,11 +1625,25 @@ lws_pt_destroy(struct lws_context_per_thread *pt)
vpt->foreign_pfd_list = NULL;

lws_pt_lock(pt, __func__);
+
if (pt->pipe_wsi) {
lws_destroy_event_pipe(pt->pipe_wsi);
pt->pipe_wsi = NULL;
}

+ if (pt->dummy_pipe_fds[0]
+#if !defined(WIN32)
+ && (int)pt->dummy_pipe_fds[0] != -1
+#endif
+ ) {
+ struct lws wsi;
+
+ memset(&wsi, 0, sizeof(wsi));
+ wsi.a.context = pt->context;
+ wsi.tsi = (char)pt->tid;
+ lws_plat_pipe_close(&wsi);
+ }
+
#if defined(LWS_WITH_SECURE_STREAMS)
lws_dll2_foreach_safe(&pt->ss_owner, NULL, lws_ss_destroy_dll);

16 changes: 0 additions & 16 deletions CMake/Dependencies/libwebsockets-old-gcc-fix-cast-cmakelists.patch
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
diff --git a/lib/misc/base64-decode.c b/lib/misc/base64-decode.c
index f8e8e49a..9d18b33f 100644
--- a/lib/misc/base64-decode.c
+++ b/lib/misc/base64-decode.c
@@ -72,9 +72,9 @@ _lws_b64_encode_string(const char *encode, const char *in, int in_len,
*out++ = encode[triple[0] >> 2];
*out++ = encode[(((triple[0] & 0x03) << 4) & 0x30) |
(((triple[1] & 0xf0) >> 4) & 0x0f)];
- *out++ = (len > 1 ? encode[(((triple[1] & 0x0f) << 2) & 0x3c) |
+ *out++ = (char)(len > 1 ? encode[(((triple[1] & 0x0f) << 2) & 0x3c) |
(((triple[2] & 0xc0) >> 6) & 3)] : '=');
- *out++ = (len > 2 ? encode[triple[2] & 0x3f] : '=');
+ *out++ = (char)(len > 2 ? encode[triple[2] & 0x3f] : '=');

done += 4;
}
diff --git a/lib/roles/h2/hpack.c b/lib/roles/h2/hpack.c
index 68629e6f..6ef628b8 100644
--- a/lib/roles/h2/hpack.c
Expand Down
21 changes: 20 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,20 @@ option(THREAD_SANITIZER "Build with ThreadSanitizer." OFF)
option(UNDEFINED_BEHAVIOR_SANITIZER "Build with UndefinedBehaviorSanitizer." OFF)
option(LINK_PROFILER "Link gperftools profiler" OFF)

set(OPEN_SRC_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/open-source" CACHE PATH "Libraries will be downloaded and built in this directory.")
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE)

add_definitions(-DSDK_VERSION=\"${GIT_COMMIT_HASH}\")
add_definitions(-DDETECTED_GIT_HASH)

if(NOT OPEN_SRC_INSTALL_PREFIX OR OPEN_SRC_INSTALL_PREFIX STREQUAL "")
set(OPEN_SRC_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/open-source" CACHE PATH "Libraries will be downloaded and built in this directory.")
else()
set(OPEN_SRC_INSTALL_PREFIX ${OPEN_SRC_INSTALL_PREFIX} CACHE PATH "Libraries will be downloaded and built in this directory.")
endif()

if(NOT WIN32)
CHECK_INCLUDE_FILES(ifaddrs.h KVSWEBRTC_HAVE_IFADDRS_H)
Expand Down Expand Up @@ -342,3 +355,9 @@ endif()
if(BUILD_BENCHMARK)
add_subdirectory(bench)
endif()

get_directory_property(clean_files ADDITIONAL_CLEAN_FILES)
list(APPEND clean_files "${OPEN_SRC_INSTALL_PREFIX}")
list(APPEND clean_files "${CMAKE_CURRENT_SOURCE_DIR}/build")
set_directory_properties(PROPERTIES ADDITIONAL_CLEAN_FILES "${clean_files}")

6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ You can pass the following options to `cmake ..`.
* `-DUNDEFINED_BEHAVIOR_SANITIZER` -- Build with UndefinedBehaviorSanitizer
* `-DLINK_PROFILER` -- Link with gperftools (available profiler options are listed [here](https://github.com/gperftools/gperftools))

To clean up the `open-source` and `build` folders from previous build, use `cmake --build . --target clean` from the `build` folder

For windows builds, you will have to include additional flags for libwebsockets CMake. Add the following flags to your cmake command, or edit the CMake file in ./CMake/Dependencies/libwebsockets-CMakeLists.txt with the following:

```
Expand Down Expand Up @@ -299,6 +301,10 @@ All Public APIs are documented in our [Include.h](https://github.com/awslabs/ama

Refer to [related](#related) for more about WebRTC and KVS.

## Development

If you would like to contribute to the development of this project, please base your pull requests off of the `origin/develop` branch, and to the `origin/develop` branch. Commits from `develop` will be merged into master periodically as a part of each release cycle.

## Outbound hostname and port requirements
* KVS endpoint : TCP 443 (ex: kinesisvideo.us-west-2.amazonaws.com)
* HTTPS channel endpoint : TCP 443 (ex: r-2c136a55.kinesisvideo.us-west-2.amazonaws.com)
Expand Down
71 changes: 38 additions & 33 deletions samples/Common.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ VOID onDataChannelMessage(UINT64 customData, PRtcDataChannel pDataChannel, BOOL
} else {
DLOGI("DataChannel String Message: %.*s\n", pMessageLen, pMessage);
}
// Send a response to the message sent by the viewer
STATUS retStatus = STATUS_SUCCESS;
retStatus = dataChannelSend(pDataChannel, FALSE, (PBYTE) MASTER_DATA_CHANNEL_MESSAGE, STRLEN(MASTER_DATA_CHANNEL_MESSAGE));
if (retStatus != STATUS_SUCCESS) {
DLOGI("[KVS Master] dataChannelSend(): operation returned status code: 0x%08x \n", retStatus);
}
}

VOID onDataChannel(UINT64 customData, PRtcDataChannel pRtcDataChannel)
Expand Down Expand Up @@ -487,7 +493,7 @@ STATUS createSampleStreamingSession(PSampleConfiguration pSampleConfiguration, P
CHK_STATUS(transceiverOnBandwidthEstimation(pSampleStreamingSession->pVideoRtcRtpTransceiver, (UINT64) pSampleStreamingSession,
sampleBandwidthEstimationHandler));

// Add a SendRecv Transceiver of type video
// Add a SendRecv Transceiver of type audio
audioTrack.kind = MEDIA_STREAM_TRACK_KIND_AUDIO;
audioTrack.codec = RTC_CODEC_OPUS;
audioRtpTransceiverInit.direction = RTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV;
Expand Down Expand Up @@ -545,7 +551,7 @@ STATUS freeSampleStreamingSession(PSampleStreamingSession* ppSampleStreamingSess
// the running thread but it's OK as it's re-entrant
MUTEX_LOCK(pSampleConfiguration->sampleConfigurationObjLock);
if (pSampleConfiguration->iceCandidatePairStatsTimerId != MAX_UINT32 && pSampleConfiguration->streamingSessionCount == 0 &&
pSampleConfiguration->iceCandidatePairStatsTimerId != MAX_UINT32) {
pSampleConfiguration->iceCandidatePairStatsTimerId != MAX_UINT32 && IS_VALID_TIMER_QUEUE_HANDLE(pSampleConfiguration->timerQueueHandle)) {
CHK_LOG_ERR(timerQueueCancelTimer(pSampleConfiguration->timerQueueHandle, pSampleConfiguration->iceCandidatePairStatsTimerId,
(UINT64) pSampleConfiguration));
pSampleConfiguration->iceCandidatePairStatsTimerId = MAX_UINT32;
Expand Down Expand Up @@ -590,10 +596,10 @@ VOID sampleFrameHandler(UINT64 customData, PFrame pFrame)
}
}

VOID sampleBandwidthEstimationHandler(UINT64 customData, DOUBLE maxiumBitrate)
VOID sampleBandwidthEstimationHandler(UINT64 customData, DOUBLE maximumBitrate)
{
UNUSED_PARAM(customData);
DLOGV("received bitrate suggestion: %f", maxiumBitrate);
DLOGV("received bitrate suggestion: %f", maximumBitrate);
}

VOID sampleSenderBandwidthEstimationHandler(UINT64 customData, UINT32 txBytes, UINT32 rxBytes, UINT32 txPacketsCnt, UINT32 rxPacketsCnt,
Expand Down Expand Up @@ -776,6 +782,7 @@ STATUS createSampleConfiguration(PCHAR channelName, SIGNALING_CHANNEL_ROLE_TYPE
pSampleConfiguration->clientInfo.version = SIGNALING_CLIENT_INFO_CURRENT_VERSION;
pSampleConfiguration->clientInfo.loggingLevel = logLevel;
pSampleConfiguration->clientInfo.cacheFilePath = NULL; // Use the default path
pSampleConfiguration->clientInfo.signalingClientCreationMaxRetryAttempts = CREATE_SIGNALING_CLIENT_RETRY_ATTEMPTS_SENTINEL_VALUE;
pSampleConfiguration->iceCandidatePairStatsTimerId = MAX_UINT32;
pSampleConfiguration->pregenerateCertTimerId = MAX_UINT32;

Expand Down Expand Up @@ -832,6 +839,7 @@ STATUS logSignalingClientStats(PSignalingClientMetrics pSignalingClientMetrics)
// This gives the EMA of the getIceConfig() call.
DLOGD("Data Plane API call latency: %" PRIu64 " ms",
(pSignalingClientMetrics->signalingClientStats.dpApiCallLatency / HUNDREDS_OF_NANOS_IN_A_MILLISECOND));
DLOGD("API call retry count: %d", pSignalingClientMetrics->signalingClientStats.apiCallRetryCount);
CleanUp:
LEAVES();
return retStatus;
Expand Down Expand Up @@ -998,6 +1006,28 @@ STATUS freeSampleConfiguration(PSampleConfiguration* ppSampleConfiguration)

CHK(pSampleConfiguration != NULL, retStatus);

if (IS_VALID_TIMER_QUEUE_HANDLE(pSampleConfiguration->timerQueueHandle)) {
if (pSampleConfiguration->iceCandidatePairStatsTimerId != MAX_UINT32) {
retStatus = timerQueueCancelTimer(pSampleConfiguration->timerQueueHandle, pSampleConfiguration->iceCandidatePairStatsTimerId,
(UINT64) pSampleConfiguration);
if (STATUS_FAILED(retStatus)) {
DLOGE("Failed to cancel stats timer with: 0x%08x", retStatus);
}
pSampleConfiguration->iceCandidatePairStatsTimerId = MAX_UINT32;
}

if (pSampleConfiguration->pregenerateCertTimerId != MAX_UINT32) {
retStatus = timerQueueCancelTimer(pSampleConfiguration->timerQueueHandle, pSampleConfiguration->pregenerateCertTimerId,
(UINT64) pSampleConfiguration);
if (STATUS_FAILED(retStatus)) {
DLOGE("Failed to cancel certificate pre-generation timer with: 0x%08x", retStatus);
}
pSampleConfiguration->pregenerateCertTimerId = MAX_UINT32;
}

timerQueueFree(&pSampleConfiguration->timerQueueHandle);
}

if (pSampleConfiguration->pPendingSignalingMessageForRemoteClient != NULL) {
// Iterate and free all the pending queues
stackQueueGetIterator(pSampleConfiguration->pPendingSignalingMessageForRemoteClient, &iterator);
Expand All @@ -1019,6 +1049,7 @@ STATUS freeSampleConfiguration(PSampleConfiguration* ppSampleConfiguration)
MUTEX_LOCK(pSampleConfiguration->sampleConfigurationObjLock);
locked = TRUE;
}

for (i = 0; i < pSampleConfiguration->streamingSessionCount; ++i) {
retStatus = gatherIceServerStats(pSampleConfiguration->sampleStreamingSessionList[i]);
if (STATUS_FAILED(retStatus)) {
Expand Down Expand Up @@ -1062,28 +1093,6 @@ STATUS freeSampleConfiguration(PSampleConfiguration* ppSampleConfiguration)
freeStaticCredentialProvider(&pSampleConfiguration->pCredentialProvider);
#endif

if (IS_VALID_TIMER_QUEUE_HANDLE(pSampleConfiguration->timerQueueHandle)) {
if (pSampleConfiguration->iceCandidatePairStatsTimerId != MAX_UINT32) {
retStatus = timerQueueCancelTimer(pSampleConfiguration->timerQueueHandle, pSampleConfiguration->iceCandidatePairStatsTimerId,
(UINT64) pSampleConfiguration);
if (STATUS_FAILED(retStatus)) {
DLOGE("Failed to cancel stats timer with: 0x%08x", retStatus);
}
pSampleConfiguration->iceCandidatePairStatsTimerId = MAX_UINT32;
}

if (pSampleConfiguration->pregenerateCertTimerId != MAX_UINT32) {
retStatus = timerQueueCancelTimer(pSampleConfiguration->timerQueueHandle, pSampleConfiguration->pregenerateCertTimerId,
(UINT64) pSampleConfiguration);
if (STATUS_FAILED(retStatus)) {
DLOGE("Failed to cancel certificate pre-generation timer with: 0x%08x", retStatus);
}
pSampleConfiguration->pregenerateCertTimerId = MAX_UINT32;
}

timerQueueFree(&pSampleConfiguration->timerQueueHandle);
}

if (pSampleConfiguration->pregeneratedCertificates != NULL) {
stackQueueGetIterator(pSampleConfiguration->pregeneratedCertificates, &iterator);
while (IS_VALID_ITERATOR(iterator)) {
Expand All @@ -1097,8 +1106,7 @@ STATUS freeSampleConfiguration(PSampleConfiguration* ppSampleConfiguration)
pSampleConfiguration->pregeneratedCertificates = NULL;
}

MEMFREE(*ppSampleConfiguration);
*ppSampleConfiguration = NULL;
SAFE_MEMFREE(*ppSampleConfiguration);

CleanUp:

Expand Down Expand Up @@ -1149,10 +1157,7 @@ STATUS sessionCleanupWait(PSampleConfiguration pSampleConfiguration)

// Check if we need to re-create the signaling client on-the-fly
if (ATOMIC_LOAD_BOOL(&pSampleConfiguration->recreateSignalingClient) &&
STATUS_SUCCEEDED(freeSignalingClient(&pSampleConfiguration->signalingClientHandle)) &&
STATUS_SUCCEEDED(createSignalingClientSync(&pSampleConfiguration->clientInfo, &pSampleConfiguration->channelInfo,
&pSampleConfiguration->signalingClientCallbacks, pSampleConfiguration->pCredentialProvider,
&pSampleConfiguration->signalingClientHandle))) {
STATUS_SUCCEEDED(signalingClientFetchSync(pSampleConfiguration->signalingClientHandle))) {
// Re-set the variable again
ATOMIC_STORE_BOOL(&pSampleConfiguration->recreateSignalingClient, FALSE);
}
Expand Down Expand Up @@ -1222,7 +1227,7 @@ STATUS signalingMessageReceived(UINT64 customData, PReceivedSignalingMessage pRe
{
STATUS retStatus = STATUS_SUCCESS;
PSampleConfiguration pSampleConfiguration = (PSampleConfiguration) customData;
BOOL peerConnectionFound = FALSE, locked = TRUE, startStats = FALSE;
BOOL peerConnectionFound = FALSE, locked = FALSE, startStats = FALSE;
UINT32 clientIdHash;
UINT64 hashValue = 0;
PPendingMessageQueue pPendingMessageQueue = NULL;
Expand Down
3 changes: 3 additions & 0 deletions samples/Samples.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ extern "C" {
#define IOT_CORE_ROLE_ALIAS ((PCHAR) "AWS_IOT_CORE_ROLE_ALIAS")
#define IOT_CORE_THING_NAME ((PCHAR) "AWS_IOT_CORE_THING_NAME")

#define MASTER_DATA_CHANNEL_MESSAGE "This message is from the KVS Master"
#define VIEWER_DATA_CHANNEL_MESSAGE "This message is from the KVS Viewer"

/* Uncomment the following line in order to enable IoT credentials checks in the provided samples */
//#define IOT_CORE_ENABLE_CREDENTIALS 1

Expand Down
Loading