From bc1b4ee37031cc0a830ed85fa3351ba52b0fe098 Mon Sep 17 00:00:00 2001 From: Philip Stroffolino Date: Fri, 26 Sep 2025 13:13:26 -0400 Subject: [PATCH 01/21] VPLAY-11066 Direct Rialto Wrapper/Simulator for OSX/Ubuntu AAMP integration/testing Reason for Change: new rialtoTest app Test Guidance: see ticket Risk: low Signed-off-by: Philip Stroffolino --- CMakeLists.txt | 29 ++- test/gstTestHarness/mp4demux.hpp | 2 +- test/gstTestHarness/rialto-api-test.cpp | 291 ++++++++++++++++++++++++ 3 files changed, 320 insertions(+), 2 deletions(-) create mode 100644 test/gstTestHarness/rialto-api-test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 27a3ac1f2..115a500d4 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,8 @@ function(xcode_define_schema new_schema) endfunction() project (AAMP) -set(CMAKE_CXX_STANDARD 11) +#set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=format -Wno-multichar -Wno-non-virtual-dtor -Wno-psabi") @@ -128,6 +129,8 @@ if(CMAKE_PLATFORM_UBUNTU OR CMAKE_SYSTEM_NAME STREQUAL Darwin) endif(CMAKE_SYSTEM_NAME STREQUAL Darwin) endif() +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../rialto-master/media/public/include) + include_directories(${GSTREAMER_INCLUDE_DIRS}) include_directories(${CURL_INCLUDE_DIRS}) include_directories(${GSTREAMERBASE_INCLUDE_DIRS}) @@ -665,6 +668,30 @@ install(TARGETS gstTestHarness # XCode schema target xcode_define_schema(gstTestHarness) +set(RIALTO_TEST_DEPENDS + ${OS_LD_FLAGS} + ${CMAKE_THREAD_LIBS_INIT} + ${GSTREAMER_LINK_LIBRARIES} + ${GSTREAMERBASE_LINK_LIBRARIES} + ${LIBDASH_LIBRARIES} + ${CURL_LINK_LIBRARIES} +) +set(RIALTO_TEST_SOURCES + test/gstTestHarness/rialto-api-test.cpp + test/gstTestHarness/gst-port.cpp + test/gstTestHarness/gst-port.h + test/gstTestHarness/gst-utils.cpp + test/gstTestHarness/gst-utils.h + test/gstTestHarness/mp4demux.hpp +) +add_executable(rialtoTest ${RIALTO_TEST_SOURCES}) +target_link_libraries(rialtoTest ${RIALTO_TEST_DEPENDS} "-lreadline") +install(TARGETS rialtoTest + DESTINATION bin +) +# XCode schema target +xcode_define_schema(rialtoTest) + #TODO: Decide which are the actual public headers install(FILES Accessibility.hpp AampEvent.h AampConfig.h AampCMCDCollector.h AampEventManager.h diff --git a/test/gstTestHarness/mp4demux.hpp b/test/gstTestHarness/mp4demux.hpp index f28258deb..5cc14f23e 100644 --- a/test/gstTestHarness/mp4demux.hpp +++ b/test/gstTestHarness/mp4demux.hpp @@ -53,7 +53,7 @@ struct Mp4Sample class Mp4Demux { -private: +public: // temp workaround - used directly in rialtoTest struct { uint16_t channel_count; diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp new file mode 100644 index 000000000..7845d35da --- /dev/null +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -0,0 +1,291 @@ +// +// main.cpp +// RialtoSim +// +// Created by Stroffolino, Philip on 9/19/25. +// +#include +#include +#include +#include "mp4demux.hpp" +#include "IMediaPipeline.h" +//#include "MediaPipelineIpc.h" + +using namespace firebolt::rialto; + +class MyMediaPipeline:IMediaPipeline +{ +protected: + std::weak_ptr client; + std::weak_ptr getClient(){ return client; } + + bool attachSource(const std::unique_ptr &source){ + printf( "attachSource\n" ); + return true; + } + bool attachSource(const std::unique_ptr &source, int32_t &sourceId ){ + static int32_t id; + sourceId = ++id; + printf( "attachSource() -> sourceId=%" PRId32 "\n", sourceId ); + return true; + }; + bool removeSource(int32_t id){ + printf( "removeSource(sourceId=%" PRId32 ")\n", id ); + return false; + }; + bool allSourcesAttached(){ + return true; + }; + bool load(MediaType type, const std::string &mimeType, const std::string &url){ return true; } + bool play(){ + printf( "play\n" ); + return true; + }; + bool pause(){ return false; }; + bool stop(){ return false; }; + bool setPlaybackRate(double rate){ return false; }; + bool setPosition(int64_t position){ return false; }; + bool getPosition(int64_t &position){ return false; }; + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames){ return false; }; + bool setImmediateOutput(int32_t sourceId, bool immediateOutput){ return false; }; + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput){ return false; }; + bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height){ return false; }; + bool haveData(MediaSourceStatus status, uint32_t needDataRequestId){ return false; }; + AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment){ + //printf( "addSegment(%" PRIu32 ")\n", needDataRequestId ); + return AddSegmentStatus::OK; + } + bool renderFrame(){ return false; }; + bool setVolume(double targetVolume, uint32_t volumeDuration = 0, EaseType easeType = EaseType::EASE_LINEAR){ return false; }; + bool getVolume(double ¤tVolume){ return false; }; + bool setMute(int32_t sourceId, bool mute){ return false; }; + bool getMute(int32_t sourceId, bool &mute){ return false; }; + bool setTextTrackIdentifier(const std::string &textTrackIdentifier){ return false; }; + bool getTextTrackIdentifier(std::string &textTrackIdentifier){ return false; }; + bool setLowLatency(bool lowLatency){ return false; }; + bool setSync(bool sync){ return false; }; + bool getSync(bool &sync){ return false; }; + bool setSyncOff(bool syncOff){ return false; }; + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode){ return false; }; + bool getStreamSyncMode(int32_t &streamSyncMode){ return false; }; + bool flush(int32_t sourceId, bool resetTime, bool &async){ return false; }; + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, uint64_t stopPosition = kUndefinedPosition){ return false; }; + bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac){ return false; }; + bool setBufferingLimit(uint32_t limitBufferingMs){ return false; }; + bool getBufferingLimit(uint32_t &limitBufferingMs){ return false; }; + bool setUseBuffering(bool useBuffering){ return false; }; + bool getUseBuffering(bool &useBuffering){ return false; }; + bool switchSource(const std::unique_ptr &source){ return false; }; + +public: + int userPathLen; + const char *userPathPtr; + +private: + const int64_t nanoseconds_per_second = 1e+9; + uint32_t needDataRequestId; + + Mp4Demux trackAudio; + Mp4Demux trackVideo; + int32_t sourceIdVideo; + int32_t sourceIdAudio; + + void LoadAndDemuxSegment( Mp4Demux &mp4Demux, const char *path ) + { // using generated bipbop content for initial test + char fullpath[256]; + snprintf( fullpath, sizeof(fullpath), "%.*s/Documents/r" "d" "k" "e/aamp_test_internal/test/VideoTestStream/bipbop-gen/%s", + userPathLen, userPathPtr, path ); + FILE *f = fopen(fullpath,"rb"); + assert( f ); + if( f ) + { + fseek( f,0,SEEK_END ); + size_t len = ftell(f); + unsigned char *ptr = (unsigned char *)malloc(len); + assert( ptr ); + if( ptr ) + { + fseek( f, 0, SEEK_SET ); + size_t n = fread( ptr, 1, len, f ); + assert( n == len ); + if( n==len ) + { + mp4Demux.Parse( ptr, len ); + } + } + fclose( f ); + } + } + +public: + MyMediaPipeline() : needDataRequestId(0), sourceIdVideo(-1), sourceIdAudio(-1) + { + printf( "constructing MyMediaPipeline\n" ); + } + + ~MyMediaPipeline() + { + printf( "destructing MyMediaPipeline\n" ); + } + + void ConfigureAudio( void ) + { + LoadAndDemuxSegment( trackAudio,"audio/init-stream0.m4s" ); + + bool hasDrm = false; + std::string mimeType; + StreamFormat streamFormat; + AudioConfig audioConfig; + audioConfig.numberOfChannels = trackAudio.audio.channel_count; + audioConfig.sampleRate = trackAudio.audio.samplerate; + + switch( trackAudio.codec_type ) + { + case MultiChar_Constant("esds"): + mimeType = "audio/mpeg"; + streamFormat = StreamFormat::RAW; + break; + case MultiChar_Constant("dec3"): + mimeType = "audio/x-eac3"; + streamFormat = StreamFormat::UNDEFINED; + break; + default: + assert(0); + break; + } + std::unique_ptr sourceAudio = std::make_unique( + mimeType, + hasDrm, + audioConfig, + SegmentAlignment::UNDEFINED, + streamFormat, + nullptr /* codecData*/ ); + attachSource( std::move(sourceAudio), sourceIdAudio ); + } + + void ConfigureVideo( void ) + { + LoadAndDemuxSegment( trackVideo, "video/init-stream0.m4s" ); + + bool hasDrm = false; + std::string mimeType; + StreamFormat streamFormat; + int32_t width = trackVideo.video.width; + int32_t height = trackVideo.video.height; + SegmentAlignment alignment = SegmentAlignment::AU; + + switch( trackVideo.codec_type ) + { + case MultiChar_Constant("hvcC"): + mimeType = "video/x-h265"; + streamFormat = StreamFormat::HVC1; + break; + case MultiChar_Constant("avcC"): + mimeType = "video/x-h264"; + streamFormat = StreamFormat::AVC; + break; + default: + assert(0); + break; + } + CodecData codecData; + const char *codec_ptr = trackVideo.codec_data.c_str(); + codecData.data = std::vector( codec_ptr, &codec_ptr[trackVideo.codec_data.size()] ); + std::unique_ptr sourceVideo = std::make_unique( + mimeType, + hasDrm, + width, + height, + alignment, + streamFormat, + std::make_shared(codecData) ); + attachSource( std::move(sourceVideo), sourceIdVideo ); + } + + void ConfigurenComplete() + { + allSourcesAttached(); + } + + void InjectAudio( void ) + { + LoadAndDemuxSegment( trackAudio, "audio/chunk-stream0-00001.m4s"); + int count = trackAudio.count(); + printf( "adding %d audio frames\n", count ); + for( int i=0; i audioSegment = + std::make_unique( + sourceIdAudio, + (int64_t)(pts*nanoseconds_per_second), // timestamp + (int64_t)(dur*nanoseconds_per_second), + trackAudio.audio.samplerate, + trackAudio.audio.channel_count ); + + audioSegment->setData( (uint32_t)trackAudio.getLen(i), trackAudio.getPtr(i) ); + + std::unique_ptr segment = std::move(audioSegment); + AddSegmentStatus status = addSegment(++needDataRequestId,segment); + assert( status == AddSegmentStatus::OK ); + } + } + + void InjectVideo( void ) + { + LoadAndDemuxSegment( trackVideo, "video/chunk-stream0-00001.m4s" ); + int count = trackVideo.count(); + printf( "adding %d video frames\n", count ); + for( int i=0; i videoSegment = + std::make_unique( + sourceIdVideo, + (int64_t)(pts*nanoseconds_per_second), + (int64_t)(dur*nanoseconds_per_second), + trackVideo.video.width, + trackVideo.video.height ); + + videoSegment->setData( (uint32_t)trackVideo.getLen(i), trackVideo.getPtr(i) ); + + std::unique_ptr segment = std::move(videoSegment); + AddSegmentStatus status = addSegment(++needDataRequestId,segment); + assert( status == AddSegmentStatus::OK ); + } + } + + void Play( void ) + { + play(); + } +}; + +int main(int argc, const char * argv[]) +{ + auto pipeline = new MyMediaPipeline(); + + { + const char *executablePath = argv[0]; + const char *prefix = "/Users/"; + size_t prefixLen = strlen(prefix); + pipeline->userPathPtr = strstr(executablePath,prefix); + assert( pipeline->userPathPtr ); + const char *delim = strchr( &pipeline->userPathPtr[prefixLen],'/' ); + assert( delim ); + pipeline->userPathLen = (int)(delim - pipeline->userPathPtr); + printf( "'%.*s'\n", pipeline->userPathLen, pipeline->userPathPtr ); + } + + pipeline->ConfigureAudio(); + pipeline->ConfigureVideo(); + pipeline->ConfigurenComplete(); + pipeline->InjectAudio(); + pipeline->InjectVideo(); + pipeline->Play(); + sleep(2); + delete pipeline; + return EXIT_SUCCESS; +} From 52ea8325113303d07ccdef4387e45c0b0733a6bf Mon Sep 17 00:00:00 2001 From: Philip Stroffolino Date: Sat, 27 Sep 2025 04:27:40 -0400 Subject: [PATCH 02/21] Reason for Change: completed basic mapping to gst Signed-off-by: Philip Stroffolino --- test/gstTestHarness/rialto-api-test.cpp | 269 +++++++++++++++++++----- 1 file changed, 212 insertions(+), 57 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 7845d35da..3fb3135c5 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -9,38 +9,146 @@ #include #include "mp4demux.hpp" #include "IMediaPipeline.h" -//#include "MediaPipelineIpc.h" + +// TODO: move implementation to own class +// plug api gaps? +// explore suite of real rialto impl +// missing codec mappings? +#include + +// TBR +static int gUserPathLen; +static const char *gUserPathPtr; using namespace firebolt::rialto; -class MyMediaPipeline:IMediaPipeline +static void found_video_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ); +static void found_audio_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ); + +#define TRACK_VIDEO 0 +#define TRACK_AUDIO 1 + +class GstMediaPipeline:IMediaPipeline { +private: + friend void found_video_source_cb( GObject *, GObject *, GParamSpec *, class GstMediaPipeline * ); + friend void found_audio_source_cb( GObject *, GObject *, GParamSpec *, class GstMediaPipeline * ); + + void found_source( GObject *orig, GParamSpec *pspec, int sourceId ) + { + g_object_get( orig, pspec->name, &track[sourceId].appsrc, nullptr ); + } + + GstElement *pipeline; + + struct + { + GstElement *playbin; + GstElement *appsrc; + } track[2]; + protected: std::weak_ptr client; std::weak_ptr getClient(){ return client; } bool attachSource(const std::unique_ptr &source){ - printf( "attachSource\n" ); return true; } + bool attachSource(const std::unique_ptr &source, int32_t &sourceId ){ - static int32_t id; - sourceId = ++id; + MediaSourceType sourceType = source->getType(); + GstCaps * caps = gst_caps_new_empty_simple( source->getMimeType().c_str() ); + + if( sourceType == MediaSourceType::VIDEO || sourceType == MediaSourceType::AUDIO ) + { + const IMediaPipeline::MediaSourceAV *mediaSourceAV = dynamic_cast(source.get()); + const char *streamFormat = nullptr; + switch( mediaSourceAV->getStreamFormat() ) + { + case StreamFormat::HVC1: + streamFormat = "hvc1"; + break; + case StreamFormat::AVC: + streamFormat = "avc"; + break; + case StreamFormat::RAW: + streamFormat = "raw"; + break; + default: + break; + } + if( streamFormat ) + { + gst_caps_set_simple( caps, "stream-format", G_TYPE_STRING, streamFormat, nullptr ); + } + const std::shared_ptr codecData = mediaSourceAV->getCodecData(); + GstBuffer *buf = nullptr; + if( codecData ) + { + buf = gst_buffer_new_and_alloc(codecData->data.size()); + gst_buffer_fill(buf, 0, codecData->data.data(), codecData->data.size() ); + gst_caps_set_simple( caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr ); + } + + if( sourceType == MediaSourceType::VIDEO ) + { + sourceId = TRACK_VIDEO; + const IMediaPipeline::MediaSourceVideo *mediaSourceVideo = dynamic_cast(source.get()); + gst_caps_set_simple( caps, + "alignment", G_TYPE_STRING, "au", + "width", G_TYPE_INT, mediaSourceVideo->getWidth(), + "height", G_TYPE_INT, mediaSourceVideo->getHeight(), + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, + nullptr); + } + else if( sourceType == MediaSourceType::AUDIO ) + { + sourceId = TRACK_AUDIO; + const IMediaPipeline::MediaSourceAudio *mediaSourceAudio = dynamic_cast(source.get()); + auto audioConfig = mediaSourceAudio->getAudioConfig();//.numberOfChannels ); + gst_caps_set_simple( caps, + "framed", G_TYPE_BOOLEAN, TRUE, + "rate", G_TYPE_INT, audioConfig.sampleRate, + "channels", G_TYPE_INT, audioConfig.numberOfChannels, + nullptr ); + } + else + { + assert(0); + } + + gchar *caps_string = gst_caps_to_string(caps); + g_print("Negotiated caps: %s\n", caps_string); + g_free(caps_string); + + gst_app_src_set_caps(GST_APP_SRC(track[sourceId].appsrc), caps); + gst_caps_unref(caps); + if( buf ) + { + gst_buffer_unref(buf); + } + } printf( "attachSource() -> sourceId=%" PRId32 "\n", sourceId ); return true; }; + bool removeSource(int32_t id){ printf( "removeSource(sourceId=%" PRId32 ")\n", id ); return false; }; + bool allSourcesAttached(){ return true; }; + bool load(MediaType type, const std::string &mimeType, const std::string &url){ return true; } + bool play(){ printf( "play\n" ); + gst_element_set_state( pipeline, GST_STATE_PLAYING ); return true; }; + bool pause(){ return false; }; bool stop(){ return false; }; bool setPlaybackRate(double rate){ return false; }; @@ -51,8 +159,14 @@ class MyMediaPipeline:IMediaPipeline bool getImmediateOutput(int32_t sourceId, bool &immediateOutput){ return false; }; bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height){ return false; }; bool haveData(MediaSourceStatus status, uint32_t needDataRequestId){ return false; }; - AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment){ - //printf( "addSegment(%" PRIu32 ")\n", needDataRequestId ); + AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) + { + GstBuffer *gstBuffer = gst_buffer_new_wrapped( + (gpointer)mediaSegment->getData(), + (gsize)mediaSegment->getDataLength() ); + GST_BUFFER_PTS(gstBuffer) = (GstClockTime)(mediaSegment->getTimeStamp()); + GST_BUFFER_DURATION(gstBuffer) = (GstClockTime)(mediaSegment->getDuration()); + gst_app_src_push_buffer(GST_APP_SRC(track[mediaSegment->getId()].appsrc), gstBuffer ); return AddSegmentStatus::OK; } bool renderFrame(){ return false; }; @@ -76,13 +190,8 @@ class MyMediaPipeline:IMediaPipeline bool setUseBuffering(bool useBuffering){ return false; }; bool getUseBuffering(bool &useBuffering){ return false; }; bool switchSource(const std::unique_ptr &source){ return false; }; - -public: - int userPathLen; - const char *userPathPtr; private: - const int64_t nanoseconds_per_second = 1e+9; uint32_t needDataRequestId; Mp4Demux trackAudio; @@ -94,7 +203,7 @@ class MyMediaPipeline:IMediaPipeline { // using generated bipbop content for initial test char fullpath[256]; snprintf( fullpath, sizeof(fullpath), "%.*s/Documents/r" "d" "k" "e/aamp_test_internal/test/VideoTestStream/bipbop-gen/%s", - userPathLen, userPathPtr, path ); + gUserPathLen, gUserPathPtr, path ); FILE *f = fopen(fullpath,"rb"); assert( f ); if( f ) @@ -118,14 +227,36 @@ class MyMediaPipeline:IMediaPipeline } public: - MyMediaPipeline() : needDataRequestId(0), sourceIdVideo(-1), sourceIdAudio(-1) + GstMediaPipeline() { - printf( "constructing MyMediaPipeline\n" ); + printf( "constructing GstMediaPipeline\n" ); + pipeline = gst_pipeline_new( "rialtoTest" ); + for( int i=0; i<2; i++ ) + { + printf( "creating playbin for track#%d\n", i ); + GstElement *playbin = gst_element_factory_make("playbin", nullptr); + track[i].playbin = playbin; + track[i].appsrc = nullptr; + gboolean rc = gst_bin_add(GST_BIN(pipeline), playbin ); + assert( rc ); + g_object_set( playbin, "uri", "appsrc://", nullptr ); + switch( i ) + { + case TRACK_VIDEO: + g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_video_source_cb), this ); + break; + case TRACK_AUDIO: + g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_audio_source_cb), this ); + break; + default: + break; + } + } } - ~MyMediaPipeline() + ~GstMediaPipeline() { - printf( "destructing MyMediaPipeline\n" ); + printf( "destructing GstMediaPipeline\n" ); } void ConfigureAudio( void ) @@ -191,14 +322,15 @@ class MyMediaPipeline:IMediaPipeline CodecData codecData; const char *codec_ptr = trackVideo.codec_data.c_str(); codecData.data = std::vector( codec_ptr, &codec_ptr[trackVideo.codec_data.size()] ); - std::unique_ptr sourceVideo = std::make_unique( - mimeType, - hasDrm, - width, - height, - alignment, - streamFormat, - std::make_shared(codecData) ); + std::unique_ptr sourceVideo = + std::make_unique( + mimeType, + hasDrm, + width, + height, + alignment, + streamFormat, + std::make_shared(codecData) ); attachSource( std::move(sourceVideo), sourceIdVideo ); } @@ -219,13 +351,14 @@ class MyMediaPipeline:IMediaPipeline std::unique_ptr audioSegment = std::make_unique( sourceIdAudio, - (int64_t)(pts*nanoseconds_per_second), // timestamp - (int64_t)(dur*nanoseconds_per_second), + (int64_t)(pts*GST_SECOND), // timestamp + (int64_t)(dur*GST_SECOND), trackAudio.audio.samplerate, trackAudio.audio.channel_count ); - - audioSegment->setData( (uint32_t)trackAudio.getLen(i), trackAudio.getPtr(i) ); - + size_t len = trackAudio.getLen(i); + uint8_t *data = new uint8_t[len]; + std::memcpy(data, trackAudio.getPtr(i),len); + audioSegment->setData( (uint32_t)len, data ); std::unique_ptr segment = std::move(audioSegment); AddSegmentStatus status = addSegment(++needDataRequestId,segment); assert( status == AddSegmentStatus::OK ); @@ -244,13 +377,14 @@ class MyMediaPipeline:IMediaPipeline std::unique_ptr videoSegment = std::make_unique( sourceIdVideo, - (int64_t)(pts*nanoseconds_per_second), - (int64_t)(dur*nanoseconds_per_second), + (int64_t)(pts*GST_SECOND), + (int64_t)(dur*GST_SECOND), trackVideo.video.width, trackVideo.video.height ); - - videoSegment->setData( (uint32_t)trackVideo.getLen(i), trackVideo.getPtr(i) ); - + size_t len = trackVideo.getLen(i); + uint8_t *data = new uint8_t[len]; + std::memcpy(data, trackVideo.getPtr(i),len); + videoSegment->setData( (uint32_t)len, data ); std::unique_ptr segment = std::move(videoSegment); AddSegmentStatus status = addSegment(++needDataRequestId,segment); assert( status == AddSegmentStatus::OK ); @@ -263,29 +397,50 @@ class MyMediaPipeline:IMediaPipeline } }; -int main(int argc, const char * argv[]) +static void found_video_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ) { - auto pipeline = new MyMediaPipeline(); + printf( "found_video_source_cb\n" ); + gstMediaPipeline->found_source(orig,pspec,TRACK_VIDEO); +} - { - const char *executablePath = argv[0]; - const char *prefix = "/Users/"; - size_t prefixLen = strlen(prefix); - pipeline->userPathPtr = strstr(executablePath,prefix); - assert( pipeline->userPathPtr ); - const char *delim = strchr( &pipeline->userPathPtr[prefixLen],'/' ); - assert( delim ); - pipeline->userPathLen = (int)(delim - pipeline->userPathPtr); - printf( "'%.*s'\n", pipeline->userPathLen, pipeline->userPathPtr ); - } +static void found_audio_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ) +{ + printf( "found_audio_source_cb\n" ); + gstMediaPipeline->found_source(orig,pspec,TRACK_AUDIO); +} + +int my_main(int argc, char **argv) +{ + const char *executablePath = argv[0]; + const char *prefix = "/Users/"; + size_t prefixLen = strlen(prefix); + gUserPathPtr = strstr(executablePath,prefix); + assert( gUserPathPtr ); + const char *delim = strchr( &gUserPathPtr[prefixLen],'/' ); + assert( delim ); + gUserPathLen = (int)(delim - gUserPathPtr); + + gst_init(&argc, &argv); - pipeline->ConfigureAudio(); - pipeline->ConfigureVideo(); - pipeline->ConfigurenComplete(); - pipeline->InjectAudio(); - pipeline->InjectVideo(); - pipeline->Play(); - sleep(2); - delete pipeline; - return EXIT_SUCCESS; + GstMediaPipeline *gstMediaPipeline = new GstMediaPipeline(); + gstMediaPipeline->Play(); + gstMediaPipeline->ConfigureAudio(); + gstMediaPipeline->ConfigureVideo(); + gstMediaPipeline->ConfigurenComplete(); + gstMediaPipeline->InjectAudio(); + gstMediaPipeline->InjectVideo(); + + GMainLoop *main_loop = g_main_loop_new(nullptr, FALSE); + g_main_loop_run(main_loop); + g_main_loop_unref(main_loop); + return 0; +} + +int main(int argc, char **argv) +{ +#if defined(__APPLE__) && defined (__GST_MACOS_H__) + return gst_macos_main((GstMainFunc)my_main, argc, argv, nullptr); +#else + return my_main(argc,argv); +#endif } From 9a56876ff1ebea8381937446bf5450c6c5072b68 Mon Sep 17 00:00:00 2001 From: Philip Stroffolino Date: Sat, 27 Sep 2025 07:29:08 -0400 Subject: [PATCH 03/21] Reason for Change: cleanup Signed-off-by: Philip Stroffolino --- CMakeLists.txt | 6 +- test/gstTestHarness/rialto-api-test.cpp | 536 ++++++-------------- test/gstTestHarness/rialto-gst-pipeline.cpp | 161 ++++++ test/gstTestHarness/rialto-gst-pipeline.h | 70 +++ 4 files changed, 384 insertions(+), 389 deletions(-) create mode 100644 test/gstTestHarness/rialto-gst-pipeline.cpp create mode 100644 test/gstTestHarness/rialto-gst-pipeline.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 115a500d4..815185fdb 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -678,10 +678,8 @@ set(RIALTO_TEST_DEPENDS ) set(RIALTO_TEST_SOURCES test/gstTestHarness/rialto-api-test.cpp - test/gstTestHarness/gst-port.cpp - test/gstTestHarness/gst-port.h - test/gstTestHarness/gst-utils.cpp - test/gstTestHarness/gst-utils.h + test/gstTestHarness/rialto-gst-pipeline.cpp + test/gstTestHarness/rialto-gst-pipeline.h test/gstTestHarness/mp4demux.hpp ) add_executable(rialtoTest ${RIALTO_TEST_SOURCES}) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 3fb3135c5..59b701cce 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -4,409 +4,175 @@ // // Created by Stroffolino, Philip on 9/19/25. // -#include -#include #include #include "mp4demux.hpp" -#include "IMediaPipeline.h" +#include "rialto-gst-pipeline.h" -// TODO: move implementation to own class -// plug api gaps? -// explore suite of real rialto impl -// missing codec mappings? -#include - -// TBR +static Mp4Demux trackAudio; +static Mp4Demux trackVideo; +static GstMediaPipeline *gstMediaPipeline; static int gUserPathLen; static const char *gUserPathPtr; +static int32_t sourceIdAudio; +static int32_t sourceIdVideo; -using namespace firebolt::rialto; - -static void found_video_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ); -static void found_audio_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ); - -#define TRACK_VIDEO 0 -#define TRACK_AUDIO 1 - -class GstMediaPipeline:IMediaPipeline -{ -private: - friend void found_video_source_cb( GObject *, GObject *, GParamSpec *, class GstMediaPipeline * ); - friend void found_audio_source_cb( GObject *, GObject *, GParamSpec *, class GstMediaPipeline * ); - - void found_source( GObject *orig, GParamSpec *pspec, int sourceId ) - { - g_object_get( orig, pspec->name, &track[sourceId].appsrc, nullptr ); - } - - GstElement *pipeline; - - struct - { - GstElement *playbin; - GstElement *appsrc; - } track[2]; - -protected: - std::weak_ptr client; - std::weak_ptr getClient(){ return client; } - - bool attachSource(const std::unique_ptr &source){ - return true; - } - - bool attachSource(const std::unique_ptr &source, int32_t &sourceId ){ - MediaSourceType sourceType = source->getType(); - GstCaps * caps = gst_caps_new_empty_simple( source->getMimeType().c_str() ); - - if( sourceType == MediaSourceType::VIDEO || sourceType == MediaSourceType::AUDIO ) - { - const IMediaPipeline::MediaSourceAV *mediaSourceAV = dynamic_cast(source.get()); - const char *streamFormat = nullptr; - switch( mediaSourceAV->getStreamFormat() ) - { - case StreamFormat::HVC1: - streamFormat = "hvc1"; - break; - case StreamFormat::AVC: - streamFormat = "avc"; - break; - case StreamFormat::RAW: - streamFormat = "raw"; - break; - default: - break; - } - if( streamFormat ) - { - gst_caps_set_simple( caps, "stream-format", G_TYPE_STRING, streamFormat, nullptr ); - } - const std::shared_ptr codecData = mediaSourceAV->getCodecData(); - GstBuffer *buf = nullptr; - if( codecData ) - { - buf = gst_buffer_new_and_alloc(codecData->data.size()); - gst_buffer_fill(buf, 0, codecData->data.data(), codecData->data.size() ); - gst_caps_set_simple( caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr ); - } - - if( sourceType == MediaSourceType::VIDEO ) - { - sourceId = TRACK_VIDEO; - const IMediaPipeline::MediaSourceVideo *mediaSourceVideo = dynamic_cast(source.get()); - gst_caps_set_simple( caps, - "alignment", G_TYPE_STRING, "au", - "width", G_TYPE_INT, mediaSourceVideo->getWidth(), - "height", G_TYPE_INT, mediaSourceVideo->getHeight(), - "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, - nullptr); - } - else if( sourceType == MediaSourceType::AUDIO ) - { - sourceId = TRACK_AUDIO; - const IMediaPipeline::MediaSourceAudio *mediaSourceAudio = dynamic_cast(source.get()); - auto audioConfig = mediaSourceAudio->getAudioConfig();//.numberOfChannels ); - gst_caps_set_simple( caps, - "framed", G_TYPE_BOOLEAN, TRUE, - "rate", G_TYPE_INT, audioConfig.sampleRate, - "channels", G_TYPE_INT, audioConfig.numberOfChannels, - nullptr ); - } - else - { - assert(0); - } - - gchar *caps_string = gst_caps_to_string(caps); - g_print("Negotiated caps: %s\n", caps_string); - g_free(caps_string); - - gst_app_src_set_caps(GST_APP_SRC(track[sourceId].appsrc), caps); - gst_caps_unref(caps); - if( buf ) - { - gst_buffer_unref(buf); - } - } - printf( "attachSource() -> sourceId=%" PRId32 "\n", sourceId ); - return true; - }; - - bool removeSource(int32_t id){ - printf( "removeSource(sourceId=%" PRId32 ")\n", id ); - return false; - }; - - bool allSourcesAttached(){ - return true; - }; - - bool load(MediaType type, const std::string &mimeType, const std::string &url){ return true; } - - bool play(){ - printf( "play\n" ); - gst_element_set_state( pipeline, GST_STATE_PLAYING ); - return true; - }; - - bool pause(){ return false; }; - bool stop(){ return false; }; - bool setPlaybackRate(double rate){ return false; }; - bool setPosition(int64_t position){ return false; }; - bool getPosition(int64_t &position){ return false; }; - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames){ return false; }; - bool setImmediateOutput(int32_t sourceId, bool immediateOutput){ return false; }; - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput){ return false; }; - bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height){ return false; }; - bool haveData(MediaSourceStatus status, uint32_t needDataRequestId){ return false; }; - AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) - { - GstBuffer *gstBuffer = gst_buffer_new_wrapped( - (gpointer)mediaSegment->getData(), - (gsize)mediaSegment->getDataLength() ); - GST_BUFFER_PTS(gstBuffer) = (GstClockTime)(mediaSegment->getTimeStamp()); - GST_BUFFER_DURATION(gstBuffer) = (GstClockTime)(mediaSegment->getDuration()); - gst_app_src_push_buffer(GST_APP_SRC(track[mediaSegment->getId()].appsrc), gstBuffer ); - return AddSegmentStatus::OK; - } - bool renderFrame(){ return false; }; - bool setVolume(double targetVolume, uint32_t volumeDuration = 0, EaseType easeType = EaseType::EASE_LINEAR){ return false; }; - bool getVolume(double ¤tVolume){ return false; }; - bool setMute(int32_t sourceId, bool mute){ return false; }; - bool getMute(int32_t sourceId, bool &mute){ return false; }; - bool setTextTrackIdentifier(const std::string &textTrackIdentifier){ return false; }; - bool getTextTrackIdentifier(std::string &textTrackIdentifier){ return false; }; - bool setLowLatency(bool lowLatency){ return false; }; - bool setSync(bool sync){ return false; }; - bool getSync(bool &sync){ return false; }; - bool setSyncOff(bool syncOff){ return false; }; - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode){ return false; }; - bool getStreamSyncMode(int32_t &streamSyncMode){ return false; }; - bool flush(int32_t sourceId, bool resetTime, bool &async){ return false; }; - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, uint64_t stopPosition = kUndefinedPosition){ return false; }; - bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac){ return false; }; - bool setBufferingLimit(uint32_t limitBufferingMs){ return false; }; - bool getBufferingLimit(uint32_t &limitBufferingMs){ return false; }; - bool setUseBuffering(bool useBuffering){ return false; }; - bool getUseBuffering(bool &useBuffering){ return false; }; - bool switchSource(const std::unique_ptr &source){ return false; }; - -private: - uint32_t needDataRequestId; - - Mp4Demux trackAudio; - Mp4Demux trackVideo; - int32_t sourceIdVideo; - int32_t sourceIdAudio; - - void LoadAndDemuxSegment( Mp4Demux &mp4Demux, const char *path ) - { // using generated bipbop content for initial test - char fullpath[256]; - snprintf( fullpath, sizeof(fullpath), "%.*s/Documents/r" "d" "k" "e/aamp_test_internal/test/VideoTestStream/bipbop-gen/%s", - gUserPathLen, gUserPathPtr, path ); - FILE *f = fopen(fullpath,"rb"); - assert( f ); - if( f ) - { - fseek( f,0,SEEK_END ); - size_t len = ftell(f); - unsigned char *ptr = (unsigned char *)malloc(len); - assert( ptr ); - if( ptr ) - { - fseek( f, 0, SEEK_SET ); - size_t n = fread( ptr, 1, len, f ); - assert( n == len ); - if( n==len ) - { - mp4Demux.Parse( ptr, len ); - } - } - fclose( f ); - } - } - -public: - GstMediaPipeline() +void LoadAndDemuxSegment( Mp4Demux &mp4Demux, const char *path ) +{ // using generated bipbop content for initial test + char fullpath[256]; + snprintf( fullpath, sizeof(fullpath), "%.*s/Documents/r" "d" "k" "e/aamp_test_internal/test/VideoTestStream/bipbop-gen/%s", + gUserPathLen, gUserPathPtr, path ); + FILE *f = fopen(fullpath,"rb"); + assert( f ); + if( f ) { - printf( "constructing GstMediaPipeline\n" ); - pipeline = gst_pipeline_new( "rialtoTest" ); - for( int i=0; i<2; i++ ) + fseek( f,0,SEEK_END ); + size_t len = ftell(f); + unsigned char *ptr = (unsigned char *)malloc(len); + assert( ptr ); + if( ptr ) { - printf( "creating playbin for track#%d\n", i ); - GstElement *playbin = gst_element_factory_make("playbin", nullptr); - track[i].playbin = playbin; - track[i].appsrc = nullptr; - gboolean rc = gst_bin_add(GST_BIN(pipeline), playbin ); - assert( rc ); - g_object_set( playbin, "uri", "appsrc://", nullptr ); - switch( i ) + fseek( f, 0, SEEK_SET ); + size_t n = fread( ptr, 1, len, f ); + assert( n == len ); + if( n==len ) { - case TRACK_VIDEO: - g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_video_source_cb), this ); - break; - case TRACK_AUDIO: - g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_audio_source_cb), this ); - break; - default: - break; + mp4Demux.Parse( ptr, len ); } } + fclose( f ); } +} + +void ConfigureAudio( void ) +{ + LoadAndDemuxSegment( trackAudio,"audio/init-stream0.m4s" ); - ~GstMediaPipeline() - { - printf( "destructing GstMediaPipeline\n" ); - } - - void ConfigureAudio( void ) - { - LoadAndDemuxSegment( trackAudio,"audio/init-stream0.m4s" ); - - bool hasDrm = false; - std::string mimeType; - StreamFormat streamFormat; - AudioConfig audioConfig; - audioConfig.numberOfChannels = trackAudio.audio.channel_count; - audioConfig.sampleRate = trackAudio.audio.samplerate; - - switch( trackAudio.codec_type ) - { - case MultiChar_Constant("esds"): - mimeType = "audio/mpeg"; - streamFormat = StreamFormat::RAW; - break; - case MultiChar_Constant("dec3"): - mimeType = "audio/x-eac3"; - streamFormat = StreamFormat::UNDEFINED; - break; - default: - assert(0); - break; - } - std::unique_ptr sourceAudio = std::make_unique( - mimeType, - hasDrm, - audioConfig, - SegmentAlignment::UNDEFINED, - streamFormat, - nullptr /* codecData*/ ); - attachSource( std::move(sourceAudio), sourceIdAudio ); - } - - void ConfigureVideo( void ) - { - LoadAndDemuxSegment( trackVideo, "video/init-stream0.m4s" ); - - bool hasDrm = false; - std::string mimeType; - StreamFormat streamFormat; - int32_t width = trackVideo.video.width; - int32_t height = trackVideo.video.height; - SegmentAlignment alignment = SegmentAlignment::AU; - - switch( trackVideo.codec_type ) - { - case MultiChar_Constant("hvcC"): - mimeType = "video/x-h265"; - streamFormat = StreamFormat::HVC1; - break; - case MultiChar_Constant("avcC"): - mimeType = "video/x-h264"; - streamFormat = StreamFormat::AVC; - break; - default: - assert(0); - break; - } - CodecData codecData; - const char *codec_ptr = trackVideo.codec_data.c_str(); - codecData.data = std::vector( codec_ptr, &codec_ptr[trackVideo.codec_data.size()] ); - std::unique_ptr sourceVideo = - std::make_unique( - mimeType, - hasDrm, - width, - height, - alignment, - streamFormat, - std::make_shared(codecData) ); - attachSource( std::move(sourceVideo), sourceIdVideo ); - } - - void ConfigurenComplete() - { - allSourcesAttached(); - } + bool hasDrm = false; + std::string mimeType; + StreamFormat streamFormat; + AudioConfig audioConfig; + audioConfig.numberOfChannels = trackAudio.audio.channel_count; + audioConfig.sampleRate = trackAudio.audio.samplerate; - void InjectAudio( void ) + switch( trackAudio.codec_type ) { - LoadAndDemuxSegment( trackAudio, "audio/chunk-stream0-00001.m4s"); - int count = trackAudio.count(); - printf( "adding %d audio frames\n", count ); - for( int i=0; i audioSegment = - std::make_unique( - sourceIdAudio, - (int64_t)(pts*GST_SECOND), // timestamp - (int64_t)(dur*GST_SECOND), - trackAudio.audio.samplerate, - trackAudio.audio.channel_count ); - size_t len = trackAudio.getLen(i); - uint8_t *data = new uint8_t[len]; - std::memcpy(data, trackAudio.getPtr(i),len); - audioSegment->setData( (uint32_t)len, data ); - std::unique_ptr segment = std::move(audioSegment); - AddSegmentStatus status = addSegment(++needDataRequestId,segment); - assert( status == AddSegmentStatus::OK ); - } + case MultiChar_Constant("esds"): + mimeType = "audio/mpeg"; + streamFormat = StreamFormat::RAW; + break; + case MultiChar_Constant("dec3"): + mimeType = "audio/x-eac3"; + streamFormat = StreamFormat::UNDEFINED; + break; + default: + assert(0); + break; } + std::unique_ptr sourceAudio = std::make_unique( + mimeType, + hasDrm, + audioConfig, + SegmentAlignment::UNDEFINED, + streamFormat, + nullptr /* codecData*/ ); + gstMediaPipeline->attachSource( std::move(sourceAudio), sourceIdAudio ); +} + +void ConfigureVideo( void ) +{ + LoadAndDemuxSegment( trackVideo, "video/init-stream0.m4s" ); - void InjectVideo( void ) - { - LoadAndDemuxSegment( trackVideo, "video/chunk-stream0-00001.m4s" ); - int count = trackVideo.count(); - printf( "adding %d video frames\n", count ); - for( int i=0; i videoSegment = - std::make_unique( - sourceIdVideo, - (int64_t)(pts*GST_SECOND), - (int64_t)(dur*GST_SECOND), - trackVideo.video.width, - trackVideo.video.height ); - size_t len = trackVideo.getLen(i); - uint8_t *data = new uint8_t[len]; - std::memcpy(data, trackVideo.getPtr(i),len); - videoSegment->setData( (uint32_t)len, data ); - std::unique_ptr segment = std::move(videoSegment); - AddSegmentStatus status = addSegment(++needDataRequestId,segment); - assert( status == AddSegmentStatus::OK ); - } - } + bool hasDrm = false; + std::string mimeType; + StreamFormat streamFormat; + int32_t width = trackVideo.video.width; + int32_t height = trackVideo.video.height; + SegmentAlignment alignment = SegmentAlignment::AU; - void Play( void ) + switch( trackVideo.codec_type ) { - play(); + case MultiChar_Constant("hvcC"): + mimeType = "video/x-h265"; + streamFormat = StreamFormat::HVC1; + break; + case MultiChar_Constant("avcC"): + mimeType = "video/x-h264"; + streamFormat = StreamFormat::AVC; + break; + default: + assert(0); + break; } -}; + CodecData codecData; + const char *codec_ptr = trackVideo.codec_data.c_str(); + codecData.data = std::vector( codec_ptr, &codec_ptr[trackVideo.codec_data.size()] ); + std::unique_ptr sourceVideo = + std::make_unique( + mimeType, + hasDrm, + width, + height, + alignment, + streamFormat, + std::make_shared(codecData) ); + gstMediaPipeline->attachSource( std::move(sourceVideo), sourceIdVideo ); +} + +void ConfigurenComplete() +{ + gstMediaPipeline->allSourcesAttached(); +} -static void found_video_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ) +void InjectAudio( void ) { - printf( "found_video_source_cb\n" ); - gstMediaPipeline->found_source(orig,pspec,TRACK_VIDEO); + LoadAndDemuxSegment( trackAudio, "audio/chunk-stream0-00001.m4s"); + int count = trackAudio.count(); + printf( "adding %d audio frames\n", count ); + for( int i=0; i audioSegment = + std::make_unique( + sourceIdAudio, + (int64_t)(pts*GST_SECOND), // timestamp + (int64_t)(dur*GST_SECOND), + trackAudio.audio.samplerate, + trackAudio.audio.channel_count ); + size_t len = trackAudio.getLen(i); + uint8_t *data = new uint8_t[len]; + std::memcpy(data, trackAudio.getPtr(i),len); + audioSegment->setData( (uint32_t)len, data ); + std::unique_ptr segment = std::move(audioSegment); + AddSegmentStatus status = gstMediaPipeline->addSegment(0,segment); + assert( status == AddSegmentStatus::OK ); + } } -static void found_audio_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ) +void InjectVideo( void ) { - printf( "found_audio_source_cb\n" ); - gstMediaPipeline->found_source(orig,pspec,TRACK_AUDIO); + LoadAndDemuxSegment( trackVideo, "video/chunk-stream0-00001.m4s" ); + int count = trackVideo.count(); + printf( "adding %d video frames\n", count ); + for( int i=0; i videoSegment = + std::make_unique( + sourceIdVideo, + (int64_t)(pts*GST_SECOND), + (int64_t)(dur*GST_SECOND), + trackVideo.video.width, + trackVideo.video.height ); + size_t len = trackVideo.getLen(i); + uint8_t *data = new uint8_t[len]; + std::memcpy(data, trackVideo.getPtr(i),len); + videoSegment->setData( (uint32_t)len, data ); + std::unique_ptr segment = std::move(videoSegment); + AddSegmentStatus status = gstMediaPipeline->addSegment(0,segment); + assert( status == AddSegmentStatus::OK ); + } } int my_main(int argc, char **argv) @@ -422,13 +188,13 @@ int my_main(int argc, char **argv) gst_init(&argc, &argv); - GstMediaPipeline *gstMediaPipeline = new GstMediaPipeline(); - gstMediaPipeline->Play(); - gstMediaPipeline->ConfigureAudio(); - gstMediaPipeline->ConfigureVideo(); - gstMediaPipeline->ConfigurenComplete(); - gstMediaPipeline->InjectAudio(); - gstMediaPipeline->InjectVideo(); + gstMediaPipeline = new GstMediaPipeline(); + gstMediaPipeline->play(); + ConfigureAudio(); + ConfigureVideo(); + ConfigurenComplete(); + InjectAudio(); + InjectVideo(); GMainLoop *main_loop = g_main_loop_new(nullptr, FALSE); g_main_loop_run(main_loop); diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp new file mode 100644 index 000000000..2328d3824 --- /dev/null +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -0,0 +1,161 @@ +#include "rialto-gst-pipeline.h" +#include +#include +#include + +static const int32_t TRACK_VIDEO = 0; +static const int32_t TRACK_AUDIO = 1; + +static void found_video_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ) +{ + printf( "found_video_source_cb\n" ); + gstMediaPipeline->found_source(orig,pspec,TRACK_VIDEO); +} + +static void found_audio_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ) +{ + printf( "found_audio_source_cb\n" ); + gstMediaPipeline->found_source(orig,pspec,TRACK_AUDIO); +} + +void GstMediaPipeline::found_source( GObject *orig, GParamSpec *pspec, int sourceId ) +{ + g_object_get( orig, pspec->name, &track[sourceId].appsrc, NULL ); +} + +bool GstMediaPipeline::attachSource(const std::unique_ptr &source, int32_t &sourceId ){ + MediaSourceType sourceType = source->getType(); + GstCaps * caps = gst_caps_new_empty_simple( source->getMimeType().c_str() ); + + if( sourceType == MediaSourceType::VIDEO || sourceType == MediaSourceType::AUDIO ) + { + const IMediaPipeline::MediaSourceAV *mediaSourceAV = dynamic_cast(source.get()); + const char *streamFormat = nullptr; + switch( mediaSourceAV->getStreamFormat() ) + { + case StreamFormat::HVC1: + streamFormat = "hvc1"; + break; + case StreamFormat::AVC: + streamFormat = "avc"; + break; + case StreamFormat::RAW: + streamFormat = "raw"; + break; + default: + break; + } + if( streamFormat ) + { + gst_caps_set_simple( caps, "stream-format", G_TYPE_STRING, streamFormat, nullptr ); + } + const std::shared_ptr codecData = mediaSourceAV->getCodecData(); + GstBuffer *buf = nullptr; + if( codecData ) + { + buf = gst_buffer_new_and_alloc(codecData->data.size()); + gst_buffer_fill(buf, 0, codecData->data.data(), codecData->data.size() ); + gst_caps_set_simple( caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr ); + } + + if( sourceType == MediaSourceType::VIDEO ) + { + sourceId = TRACK_VIDEO; + const IMediaPipeline::MediaSourceVideo *mediaSourceVideo = dynamic_cast(source.get()); + gst_caps_set_simple( caps, + "alignment", G_TYPE_STRING, "au", + "width", G_TYPE_INT, mediaSourceVideo->getWidth(), + "height", G_TYPE_INT, mediaSourceVideo->getHeight(), + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, + nullptr); + } + else if( sourceType == MediaSourceType::AUDIO ) + { + sourceId = TRACK_AUDIO; + const IMediaPipeline::MediaSourceAudio *mediaSourceAudio = dynamic_cast(source.get()); + auto audioConfig = mediaSourceAudio->getAudioConfig();//.numberOfChannels ); + gst_caps_set_simple( caps, + "framed", G_TYPE_BOOLEAN, TRUE, + "rate", G_TYPE_INT, audioConfig.sampleRate, + "channels", G_TYPE_INT, audioConfig.numberOfChannels, + nullptr ); + } + else + { + assert(0); + } + + gchar *caps_string = gst_caps_to_string(caps); + g_print("Negotiated caps: %s\n", caps_string); + g_free(caps_string); + + gst_app_src_set_caps(GST_APP_SRC(track[sourceId].appsrc), caps); + gst_caps_unref(caps); + if( buf ) + { + gst_buffer_unref(buf); + } + } + printf( "attachSource() -> sourceId=%" PRId32 "\n", sourceId ); + return true; +}; + +bool GstMediaPipeline::removeSource(int32_t id){ + printf( "removeSource(sourceId=%" PRId32 ")\n", id ); + return false; +}; + +bool GstMediaPipeline::allSourcesAttached(){ + return true; +}; + +bool GstMediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url){ return true; } + +bool GstMediaPipeline::play(){ + printf( "play\n" ); + gst_element_set_state( pipeline, GST_STATE_PLAYING ); + return true; +}; + +AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) +{ + GstBuffer *gstBuffer = gst_buffer_new_wrapped( + (gpointer)mediaSegment->getData(), + (gsize)mediaSegment->getDataLength() ); + GST_BUFFER_PTS(gstBuffer) = (GstClockTime)(mediaSegment->getTimeStamp()); + GST_BUFFER_DURATION(gstBuffer) = (GstClockTime)(mediaSegment->getDuration()); + gst_app_src_push_buffer(GST_APP_SRC(track[mediaSegment->getId()].appsrc), gstBuffer ); + return AddSegmentStatus::OK; +} + +GstMediaPipeline::GstMediaPipeline() +{ + printf( "constructing GstMediaPipeline\n" ); + pipeline = gst_pipeline_new( "rialtoTest" ); + for( int i=0; i<2; i++ ) + { + printf( "creating playbin for track#%d\n", i ); + GstElement *playbin = gst_element_factory_make("playbin", nullptr); + track[i].playbin = playbin; + track[i].appsrc = nullptr; + gboolean rc = gst_bin_add(GST_BIN(pipeline), playbin ); + assert( rc ); + g_object_set( playbin, "uri", "appsrc://", nullptr ); + switch( i ) + { + case TRACK_VIDEO: + g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_video_source_cb), this ); + break; + case TRACK_AUDIO: + g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_audio_source_cb), this ); + break; + default: + break; + } + } +} + +GstMediaPipeline::~GstMediaPipeline() +{ + printf( "destructing GstMediaPipeline\n" ); +} diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h new file mode 100644 index 000000000..30a498351 --- /dev/null +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -0,0 +1,70 @@ +#ifndef GST_MEDIA_PIPELINE_H +#define GST_MEDIA_PIPELINE_H + +#include "IMediaPipeline.h" +#include + +using namespace firebolt::rialto; + +class GstMediaPipeline:IMediaPipeline +{ +private: + GstElement *pipeline; + + struct + { + GstElement *playbin; + GstElement *appsrc; + } track[2]; + +protected: + std::weak_ptr client; + std::weak_ptr getClient(){ return client; } + +public: + void found_source( GObject *orig, GParamSpec *pspec, int sourceId ); + GstMediaPipeline(); + ~GstMediaPipeline(); + + bool pause(){ return false; }; + bool stop(){ return false; }; + bool setPlaybackRate(double rate){ return false; }; + bool setPosition(int64_t position){ return false; }; + bool getPosition(int64_t &position){ return false; }; + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames){ return false; }; + bool setImmediateOutput(int32_t sourceId, bool immediateOutput){ return false; }; + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput){ return false; }; + bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height){ return false; }; + bool haveData(MediaSourceStatus status, uint32_t needDataRequestId){ return false; }; + bool attachSource(const std::unique_ptr &source){ return true; } + bool renderFrame(){ return false; }; + bool setVolume(double targetVolume, uint32_t volumeDuration = 0, EaseType easeType = EaseType::EASE_LINEAR){ return false; }; + bool getTextTrackIdentifier(std::string &textTrackIdentifier){ return false; }; + bool setLowLatency(bool lowLatency){ return false; }; + bool setSync(bool sync){ return false; }; + bool getSync(bool &sync){ return false; }; + bool setSyncOff(bool syncOff){ return false; }; + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode){ return false; }; + bool getStreamSyncMode(int32_t &streamSyncMode){ return false; }; + bool flush(int32_t sourceId, bool resetTime, bool &async){ return false; }; + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, uint64_t stopPosition = kUndefinedPosition){ return false; }; + bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac){ return false; }; + bool setBufferingLimit(uint32_t limitBufferingMs){ return false; }; + bool getBufferingLimit(uint32_t &limitBufferingMs){ return false; }; + bool setUseBuffering(bool useBuffering){ return false; }; + bool getUseBuffering(bool &useBuffering){ return false; }; + bool switchSource(const std::unique_ptr &source){ return false; }; + bool getVolume(double ¤tVolume){ return false; } + bool setMute(int32_t sourceId, bool mute){ return false; } + bool getMute(int32_t sourceId, bool &mute){ return false; } + bool setTextTrackIdentifier(const std::string &textTrackIdentifier){ return false; } + + bool attachSource(const std::unique_ptr &source, int32_t &sourceId ); + bool removeSource(int32_t id); + bool allSourcesAttached(); + bool load(MediaType type, const std::string &mimeType, const std::string &url); + bool play(); + AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment); +}; + +#endif // GST_MEDIA_PIPELINE_H From df0b3f5ad03b1bb3f68d72135ac67b3db937704d Mon Sep 17 00:00:00 2001 From: Philip Stroffolino Date: Tue, 30 Sep 2025 11:52:29 -0400 Subject: [PATCH 04/21] Reason for Change: add public rialto apis (temporarily) to make building easier Signed-off-by: Philip Stroffolino --- CMakeLists.txt | 2 +- .../media/public/include/ControlCommon.h | 44 + .../media/public/include/IClientLogControl.h | 101 ++ .../media/public/include/IClientLogHandler.h | 82 + rialto-master/media/public/include/IControl.h | 97 ++ .../media/public/include/IControlClient.h | 59 + .../media/public/include/IMediaKeys.h | 304 ++++ .../public/include/IMediaKeysCapabilities.h | 120 ++ .../media/public/include/IMediaKeysClient.h | 81 + .../media/public/include/IMediaPipeline.h | 1528 +++++++++++++++++ .../include/IMediaPipelineCapabilities.h | 121 ++ .../public/include/IMediaPipelineClient.h | 220 +++ .../media/public/include/IWebAudioPlayer.h | 214 +++ .../public/include/IWebAudioPlayerClient.h | 66 + .../media/public/include/MediaCommon.h | 468 +++++ 15 files changed, 3506 insertions(+), 1 deletion(-) create mode 100644 rialto-master/media/public/include/ControlCommon.h create mode 100644 rialto-master/media/public/include/IClientLogControl.h create mode 100644 rialto-master/media/public/include/IClientLogHandler.h create mode 100644 rialto-master/media/public/include/IControl.h create mode 100644 rialto-master/media/public/include/IControlClient.h create mode 100644 rialto-master/media/public/include/IMediaKeys.h create mode 100644 rialto-master/media/public/include/IMediaKeysCapabilities.h create mode 100644 rialto-master/media/public/include/IMediaKeysClient.h create mode 100644 rialto-master/media/public/include/IMediaPipeline.h create mode 100644 rialto-master/media/public/include/IMediaPipelineCapabilities.h create mode 100644 rialto-master/media/public/include/IMediaPipelineClient.h create mode 100644 rialto-master/media/public/include/IWebAudioPlayer.h create mode 100644 rialto-master/media/public/include/IWebAudioPlayerClient.h create mode 100644 rialto-master/media/public/include/MediaCommon.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 815185fdb..8bbb44de0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,7 +129,7 @@ if(CMAKE_PLATFORM_UBUNTU OR CMAKE_SYSTEM_NAME STREQUAL Darwin) endif(CMAKE_SYSTEM_NAME STREQUAL Darwin) endif() -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../rialto-master/media/public/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rialto-master/media/public/include) include_directories(${GSTREAMER_INCLUDE_DIRS}) include_directories(${CURL_INCLUDE_DIRS}) diff --git a/rialto-master/media/public/include/ControlCommon.h b/rialto-master/media/public/include/ControlCommon.h new file mode 100644 index 000000000..133639fc4 --- /dev/null +++ b/rialto-master/media/public/include/ControlCommon.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CONTROL_COMMON_H_ +#define FIREBOLT_RIALTO_CONTROL_COMMON_H_ + +/** + * @file ControlCommon.h + * + * The definition of the Control Common types + * + */ + +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief The application state. + */ +enum class ApplicationState +{ + UNKNOWN, + RUNNING, + INACTIVE +}; +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_CONTROL_COMMON_H_ diff --git a/rialto-master/media/public/include/IClientLogControl.h b/rialto-master/media/public/include/IClientLogControl.h new file mode 100644 index 000000000..311b7eb4d --- /dev/null +++ b/rialto-master/media/public/include/IClientLogControl.h @@ -0,0 +1,101 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ +#define FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ + +/** + * @file IClientLogControl.h + * + * The definition of the IClientLogControl interface. + * + * Via this interface the logging of the Rialto Client can + * be redirected to a user specified call handler + */ + +#include +#include + +#include "ControlCommon.h" +#include "IClientLogHandler.h" +#include "IControlClient.h" + +namespace firebolt::rialto +{ +class IClientLogControl; + +/** + * @brief IClientLogControl factory class, returns a concrete implementation of IClientLogControl + */ +class IClientLogControlFactory +{ +public: + IClientLogControlFactory() = default; + virtual ~IClientLogControlFactory() = default; + + /** + * @brief Creates the IClientLogControlFactory + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IClientLogControl factory method, returns a concrete singleton implementation of IClientLogControl + * + * @retval the new IClientLogControl instance or null on error. + */ + virtual IClientLogControl &createClientLogControl() = 0; +}; + +/** + * @brief The definition of the IClientLogControl interface. + * + * This interface defines the public API for controlling Rialto client's + * log handling. This class is a singleton + * + */ +class IClientLogControl +{ +public: + IClientLogControl() = default; + virtual ~IClientLogControl() = default; + + IClientLogControl(const IClientLogControl &) = delete; + IClientLogControl &operator=(const IClientLogControl &) = delete; + IClientLogControl(IClientLogControl &&) = delete; + IClientLogControl &operator=(IClientLogControl &&) = delete; + + /** + * @brief Register a new log handler + * + * @param[in] handler : The user can pass in an object that will henceforth + * receive callbacks to it's log(...) method for rialto client log events. + * Please see IClientLogHandler for the parameters that log() must accept. + * To cancel callbacks then call this method again but pass a nullptr for + * the handler. + * @param[in] ignoreLogLevels : If true then the handler will receive ALL log level messages regardless of the + * currently configured log level + * + * @retval true if successful + */ + virtual bool registerLogHandler(const std::shared_ptr &handler, bool ignoreLogLevels) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ diff --git a/rialto-master/media/public/include/IClientLogHandler.h b/rialto-master/media/public/include/IClientLogHandler.h new file mode 100644 index 000000000..c93aad816 --- /dev/null +++ b/rialto-master/media/public/include/IClientLogHandler.h @@ -0,0 +1,82 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file ILogHandler.h + * + * This file comprises the class definition of ILogHandler. + * An interface, which provides API of custom server manager logging handler + */ + +#ifndef FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ +#define FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ + +/** + * @file IClientLogHandler.h + * + * The definition of the IClientLogHandler interface. + * + * This interface allows the user to define their own log handler for + * any messages generated by the rialto client library + */ + +#include + +namespace firebolt::rialto +{ +/** + * @brief IClientLogHandler allows the user to define their own log handler for + * any messages generated by the rialto client library + */ +class IClientLogHandler +{ +public: + IClientLogHandler() = default; + virtual ~IClientLogHandler() = default; + IClientLogHandler(const IClientLogHandler &) = delete; + IClientLogHandler &operator=(const IClientLogHandler &) = delete; + IClientLogHandler(IClientLogHandler &&) = delete; + IClientLogHandler &operator=(IClientLogHandler &&) = delete; + + /** + * @brief All possible log levels that could be used in the log callback + */ + + enum class Level + { + Fatal, + Error, + Warning, + Milestone, + Info, + Debug, + External + }; + + /** + * @brief A callback method for every log item generated by the rialto client library + * + * @param[in] level : The log level + * @param[in] file : The source code file where the log is defined + * @param[in] line : The line number within the file where the log is defined + * @param[in] function : The source code function within which the log is defined + * @param[in] message : The message of the log + */ + virtual void log(Level level, const std::string &file, int line, const std::string &function, + const std::string &message) = 0; +}; +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ diff --git a/rialto-master/media/public/include/IControl.h b/rialto-master/media/public/include/IControl.h new file mode 100644 index 000000000..007bff7e9 --- /dev/null +++ b/rialto-master/media/public/include/IControl.h @@ -0,0 +1,97 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_CONTROL_H_ +#define FIREBOLT_RIALTO_I_CONTROL_H_ + +/** + * @file IControl.h + * + * The definition of the IControl interface. + * + * This interface defines the public API of Rialto for control of Rialto, + * including the IPC connection and shared memory. + */ + +#include +#include + +#include "ControlCommon.h" +#include "IControlClient.h" + +namespace firebolt::rialto +{ +class IControl; + +/** + * @brief IControl factory class, returns a concrete implementation of IControl + */ +class IControlFactory +{ +public: + IControlFactory() = default; + virtual ~IControlFactory() = default; + + /** + * @brief Creates a IControlFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IControl factory method, returns a concrete implementation of IControl + * + * @retval the new IControl instance or null on error. + */ + virtual std::shared_ptr createControl() const = 0; +}; + +/** + * @brief The definition of the IControl interface. + * + * This interface defines the public API for control of the ipc and shared memory. + * + */ +class IControl +{ +public: + IControl() = default; + virtual ~IControl() = default; + + IControl(const IControl &) = delete; + IControl &operator=(const IControl &) = delete; + IControl(IControl &&) = delete; + IControl &operator=(IControl &&) = delete; + + /** + * @brief Register new IControlClient. This method will hold a shared_ptr + * to the client until the destruction of the IControl object. + * At destruction the client will be unregistered and the + * shared_ptr will be released. + * + * @param[in] client : Client object for callbacks + * @param[out] appState : Current application state + * + * @retval true on success, false otherwise. + */ + virtual bool registerClient(std::weak_ptr client, ApplicationState &appState) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_CONTROL_H_ diff --git a/rialto-master/media/public/include/IControlClient.h b/rialto-master/media/public/include/IControlClient.h new file mode 100644 index 000000000..6b60b6e4c --- /dev/null +++ b/rialto-master/media/public/include/IControlClient.h @@ -0,0 +1,59 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ +#define FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ + +/** + * @file IControlClient.h + * + * The definition of the IControlClient interface. + * + * This file comprises the definition of the IControlClient abstract + * class. This is the API by which a IControl implementation will + * pass notifications to its client. + */ + +#include "ControlCommon.h" + +namespace firebolt::rialto +{ +/** + * @brief The Rialto control client interface. + * + * This is The Rialto control client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the + * state of the rialto server. + */ +class IControlClient +{ +public: + /** + * @brief Virtual destructor + */ + virtual ~IControlClient() = default; + + /** + * @brief Notifies the client that rialto server reached new application state + * + * @param[in] state: The new application state. + */ + virtual void notifyApplicationState(ApplicationState state) = 0; +}; +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ diff --git a/rialto-master/media/public/include/IMediaKeys.h b/rialto-master/media/public/include/IMediaKeys.h new file mode 100644 index 000000000..43cd1a718 --- /dev/null +++ b/rialto-master/media/public/include/IMediaKeys.h @@ -0,0 +1,304 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ +#define FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ + +/** + * @file IMediaKeys.h + * + * The definition of the IMediaKeys interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content. + */ + +#include +#include +#include + +#include "IMediaKeysClient.h" +#include "MediaCommon.h" + +namespace firebolt::rialto +{ +class IMediaKeys; + +/** + * @brief IMediaKeys factory class, returns a concrete implementation of IMediaKeys + */ +class IMediaKeysFactory +{ +public: + IMediaKeysFactory() = default; + virtual ~IMediaKeysFactory() = default; + + /** + * @brief Create a IMediaKeysFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMediaKeys factory method, returns a concrete implementation of IMediaKeys + * + * @param[in] keySystem : The key system for which to create a Media Keys instance. + * + * @retval the new media keys instance or null on error. + */ + virtual std::unique_ptr createMediaKeys(const std::string &keySystem) const = 0; +}; + +/** + * @brief The definition of the IMediaKeys interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content + * which should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaKeys +{ +public: + IMediaKeys() = default; + virtual ~IMediaKeys() = default; + + IMediaKeys(const IMediaKeys &) = delete; + IMediaKeys &operator=(const IMediaKeys &) = delete; + IMediaKeys(IMediaKeys &&) = delete; + IMediaKeys &operator=(IMediaKeys &&) = delete; + + /** + * @brief Selects the specified keyId for the key session. Netflix specific API. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] keyId : The key id to select. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) = 0; + + /** + * @brief Returns true if the Key Session object contains the specified key. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] keyId : The key id. + * + * @retval true if it contains the key. + */ + virtual bool containsKey(int32_t keySessionId, const std::vector &keyId) = 0; + + /** + * @brief Creates a session and returns the session id. + * + * This method creates a new session and returns the session id in + * the specified string. Any other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] sessionType : The session type. + * @param[in] client : Client object for callbacks + * @param[in] isLDL : Is this an LDL + * @param[out] keySessionId: The key session id + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, + bool isLDL, int32_t &keySessionId) = 0; + + /** + * @brief Generates a licence request. + * + * This method triggers generation of a licence request. If the session + * id does not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the + * session type or init data type is not supported a + * MediaKeyErrorStatus:NOT_SUPPORTED value is be returned. Any other + * errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] initDataType : The init data type. + * @param[in] initData : The init data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) = 0; + + /** + * @brief Loads an existing key session + * + * This method loads an existing key session. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the + * session type or init data type is not supported a + * MediaKeyErrorStatus:NOT_SUPPORTED value must be returned. If the session + * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any + * other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id for the session. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus loadSession(int32_t keySessionId) = 0; + + /** + * @brief Updates a key session's state. + * + * This method updates a session's state. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the session + * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any + * other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] responseData : The license response data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) = 0; + + /** + * @brief Set DRM Header for a key session + * + * This method updates a key session's DRM header. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned.If the session + * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any + * other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The session id for the session. + * @param[in] requestData : The request data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) = 0; + + /** + * @brief Closes a key session + * + * This method closes an open session. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other + * errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus closeKeySession(int32_t keySessionId) = 0; + + /** + * @brief Removes a key session + * + * This method removes an open session. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other + * errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus removeKeySession(int32_t keySessionId) = 0; + + /** + * @brief Delete the DRM store for the object's key system + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus deleteDrmStore() = 0; + + /** + * @brief Delete the key store for the object's key system + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus deleteKeyStore() = 0; + + /** + * @brief Gets a hash of the DRM store for the object's key system + * + * @param[out] drmStoreHash : the hash value + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) = 0; + + /** + * @brief Gets a hash of the Key store for the object's key system + * + * @param[out] keyStoreHash : the hash value + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) = 0; + + /** + * @brief Get the limit on the number of ldl key sessions for the object's key system + * + * @param[out] ldlLimit : the limit on the number of ldl key sessions. + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) = 0; + + /** + * @brief Get the last cdm specific DRM error code + * + * @param[in] keySessionId : The key session id. + * @param[out] errorCode : the error code. + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) = 0; + + /** + * @brief Get the DRM system time for the object's key system + * + * @param[out] drmTime : the DRM system time + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) = 0; + + /** + * @brief Get the internal CDM key session ID + * + * @param[in] keySessionId : The key session id for the session. + * @param[out] cdmKeySessionId : The internal CDM key session ID + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) = 0; + + /** + * @brief Releases a key session + * + * This method releases an open session. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other + * errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) = 0; + + /** + * @brief Get metrics for a DRM system + * + * @param[out] buffer : Buffer that can hold the metric data + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ diff --git a/rialto-master/media/public/include/IMediaKeysCapabilities.h b/rialto-master/media/public/include/IMediaKeysCapabilities.h new file mode 100644 index 000000000..41747e8b1 --- /dev/null +++ b/rialto-master/media/public/include/IMediaKeysCapabilities.h @@ -0,0 +1,120 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ + +/** + * @file IMediaKeysCapabilities.h + * + * The definition of the IMediaKeysCapabilities interface. + */ + +#include +#include +#include + +namespace firebolt::rialto +{ +class IMediaKeysCapabilities; + +/** + * @brief IMediaKeysCapabilities factory class, for getting the IMediaKeysCapabilities singleton object. + */ +class IMediaKeysCapabilitiesFactory +{ +public: + IMediaKeysCapabilitiesFactory() = default; + virtual ~IMediaKeysCapabilitiesFactory() = default; + + /** + * @brief Gets the IMediaKeysCapabilitiesFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Gets the IMediaKeysCapabilities singleton object. + * + * @retval the MediaKeysCapabilities instance or null on error. + */ + virtual std::shared_ptr getMediaKeysCapabilities() const = 0; +}; + +/** + * @brief The definition of the IMediaKeysCapabilities interface. + * + * This interface defines the public API of Rialto for querying EME decryption capabilities. + * It should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaKeysCapabilities +{ +public: + IMediaKeysCapabilities() = default; + virtual ~IMediaKeysCapabilities() = default; + + IMediaKeysCapabilities(const IMediaKeysCapabilities &) = delete; + IMediaKeysCapabilities &operator=(const IMediaKeysCapabilities &) = delete; + IMediaKeysCapabilities(IMediaKeysCapabilities &&) = delete; + IMediaKeysCapabilities &operator=(IMediaKeysCapabilities &&) = delete; + + /** + * @brief Returns the EME key systems supported by Rialto + * + * @retval The supported key systems. + */ + virtual std::vector getSupportedKeySystems() = 0; + + /** + * @brief Indicates if the specified key system is supported. + * + * This method should be called to ensure that the specified key + * system is supported by Rialto. + * + * @param[in] keySystem : The key system. + * + * @retval true if supported. + */ + virtual bool supportsKeySystem(const std::string &keySystem) = 0; + + /** + * @brief Returns version of supported key system + * + * @param[in] keySystem : The key system. + * @param[out] version : The supported version of the key system + * + * @retval true if operation was successful + */ + virtual bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) = 0; + + /** + * @brief Gets support server certificate. + * + * Some DRMs (e.g. WideVine) use a system-wide server certificate. This method + * gets if system has support for that certificate. + * + * @param[in] keySystem : The key system. + * + * @retval true if server certificate is supported + */ + virtual bool isServerCertificateSupported(const std::string &keySystem) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ diff --git a/rialto-master/media/public/include/IMediaKeysClient.h b/rialto-master/media/public/include/IMediaKeysClient.h new file mode 100644 index 000000000..c4aade608 --- /dev/null +++ b/rialto-master/media/public/include/IMediaKeysClient.h @@ -0,0 +1,81 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ +#define FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ + +/** + * @file IMediaKeysClient.h + * + * The definition of the IMediaKeysClient interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content. + * This is the Rialto media keys client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the state + * of a key session. + */ + +#include "MediaCommon.h" +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief The definition of the IMediaKeysClient interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content + * which should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaKeysClient +{ +public: + /** + * @brief The virtual destructor. + */ + virtual ~IMediaKeysClient() {} + + /** + * @brief Notification that a license is required + * + * @param[in] keySessionId : The idea of the session triggering the callback + * @param[in] licenseRequestMessage : The license request message blob + * @param[in] url : URL to which the message should be sent or empty string + */ + virtual void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, + const std::string &url) = 0; + + /** + * @brief Notification that a license renewal is required + * + * @param[in] keySessionId : The idea of the session triggering the callback + * @param[in] licenseRenewalMessage : The license renewal message blob + */ + virtual void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) = 0; + + /** + * @brief Notification that the status of one or more keys in the key session has changed + * + * @param[in] keySessionId : The idea of the session triggering the callback + * @param[in] keyStatuses : Vector of key ID/key status pairs + */ + virtual void onKeyStatusesChanged(int32_t keySessionId, const KeyStatusVector &keyStatuses) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ diff --git a/rialto-master/media/public/include/IMediaPipeline.h b/rialto-master/media/public/include/IMediaPipeline.h new file mode 100644 index 000000000..0e7ce629f --- /dev/null +++ b/rialto-master/media/public/include/IMediaPipeline.h @@ -0,0 +1,1528 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ +#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ + +/** + * @file IMediaPipeline.h + * + * The definition of the IMediaPipeline interface. + * + * This interface defines the public API of Rialto for playback of AV content. + */ + +#include + +#include +#include +#include +#include +#include + +#include "IMediaPipelineClient.h" +#include "MediaCommon.h" + +namespace firebolt::rialto +{ +class IMediaPipeline; + +/** + * @brief IMediaPipeline factory class, returns a concrete implementation of IMediaPipeline + */ +class IMediaPipelineFactory +{ +public: + IMediaPipelineFactory() = default; + virtual ~IMediaPipelineFactory() = default; + + /** + * @brief Create a IMediaPipelineFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMediaPipeline factory method, returns a concrete implementation of IMediaPipeline + * + * @param[in] client : The Rialto media player client. + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session + * + * @retval the new backend instance or null on error. + */ + virtual std::unique_ptr createMediaPipeline(std::weak_ptr client, + const VideoRequirements &videoRequirements) const = 0; +}; // IMediaPipelineFactory + +/** + * @brief The definition of the IMediaPipeline interface. + * + * This interface defines the public API of Rialto for playback of AV content which + * should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaPipeline +{ +public: + IMediaPipeline() = default; + virtual ~IMediaPipeline() = default; + + IMediaPipeline(const IMediaPipeline &) = delete; + IMediaPipeline &operator=(const IMediaPipeline &) = delete; + IMediaPipeline(IMediaPipeline &&) = delete; + IMediaPipeline &operator=(IMediaPipeline &&) = delete; + + /** + * @brief A class that represents a source of media data. + */ + class MediaSource + { + public: + /** + * @brief Virtual destructor. + */ + virtual ~MediaSource() {} + + /** + * @brief Create a copy + */ + virtual std::unique_ptr copy() const = 0; + + /** + * @brief Return the source type. + */ + virtual MediaSourceType getType() const { return MediaSourceType::UNKNOWN; } + + /** + * @brief Return the MIME type. + */ + std::string getMimeType() const { return m_mimeType; } + + /** + * @brief Return if source has drm + */ + bool getHasDrm() const { return m_hasDrm; } + + /** + * @brief Return the source config type. + */ + SourceConfigType getConfigType() const { return m_configType; } + + /** + * @brief Return the source id. + */ + int32_t getId() const { return m_id; } + + /** + * @brief Set the source id. + */ + void setId(int32_t id) { m_id = id; } + + protected: + /** + * @brief Default constructor. + * + * @param[in] configType : The source config type. + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + */ + explicit MediaSource(SourceConfigType configType = SourceConfigType::UNKNOWN, + const std::string &mimeType = std::string(), bool hasDrm = true) + : m_id(0), m_configType(configType), m_mimeType(mimeType), m_hasDrm(hasDrm) + { + } + /** + * @brief The source id. Parameter will be set by a successful call to attachSource() + */ + int32_t m_id; + + /** + * @brief The source config type. + */ + SourceConfigType m_configType; + + /** + * @brief The MIME type. + */ + std::string m_mimeType; + + /** + * @brief Parameter to check if encrypted frames will be used for this source. + */ + bool m_hasDrm; + }; // MediaSource + + /** + * @brief A class that represents media source audio and video derived from MediaSource class, which represents the + * source of media data + */ + class MediaSourceAV : public MediaSource + { + public: + ~MediaSourceAV() {} + std::unique_ptr copy() const { return std::make_unique(*this); } + + /** + * @brief Gets the segment alignment + */ + SegmentAlignment getSegmentAlignment() const { return m_alignment; } + + /** + * @brief Gets the codec data + */ + const std::shared_ptr &getCodecData() const { return m_codecData; } + + /** + * @brief Gets the stream format + */ + StreamFormat getStreamFormat() const { return m_streamFormat; } + + protected: + /** + * @brief Default constructor. + * + * @param[in] configType : The source config type. + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + explicit MediaSourceAV(SourceConfigType configType = SourceConfigType::UNKNOWN, + const std::string &mimeType = std::string(), bool hasDrm = true, + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSource(configType, mimeType, hasDrm), m_alignment(alignment), m_streamFormat(streamFormat), + m_codecData(codecData) + { + } + /** + * @brief The alignment of media segment + */ + SegmentAlignment m_alignment; + + /** + * @brief The stream format + */ + StreamFormat m_streamFormat; + + /** + * @brief Additional data for decoder + */ + std::shared_ptr m_codecData; + }; // MediaSourceAV + + /** + * @brief A class that represents media source audio derived from MediaSource class, which represents the source of + * media data + */ + + class MediaSourceAudio : public MediaSourceAV + { + public: + /** + * @brief Constructor for audio specific configuration. + * + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + * @param[in] audioConfig : The audio specific configuration. + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + MediaSourceAudio(const std::string &mimeType, bool hasDrm = true, const AudioConfig &audioConfig = AudioConfig(), + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSourceAV(SourceConfigType::AUDIO, mimeType, hasDrm, alignment, streamFormat, codecData), + m_audioConfig(audioConfig) + { + } + + ~MediaSourceAudio() {} + + MediaSourceType getType() const override { return MediaSourceType::AUDIO; } + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Gets the audio specific configuration + * + * @retval audio specific configuration + */ + const AudioConfig &getAudioConfig() const { return m_audioConfig; } + + protected: + /** + * @brief Variable that stores the audio specific configuration + */ + AudioConfig m_audioConfig; + }; // MediaSourceAudio + + /** + * @brief A class that represents media source video derived from MediaSource class, which represents the source of + * media data + */ + + class MediaSourceVideo : public MediaSourceAV + { + public: + /** + * @brief Constructor for video specific configuration. + * + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + * @param[in] width : The width of the video + * @param[in] height : The height of the video + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + MediaSourceVideo(const std::string &mimeType, bool hasDrm = true, + int32_t width = firebolt::rialto::kUndefinedSize, + int32_t height = firebolt::rialto::kUndefinedSize, + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSourceAV(SourceConfigType::VIDEO, mimeType, hasDrm, alignment, streamFormat, codecData), + m_width(width), m_height(height) + { + } + ~MediaSourceVideo() {} + + MediaSourceType getType() const override { return MediaSourceType::VIDEO; } + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Gets the width of the video + * + * @retval width of the video + */ + int32_t getWidth() const { return m_width; } + + /** + * @brief Gets the height of the video + * + * @retval height of the video + */ + int32_t getHeight() const { return m_height; } + + protected: + /** + * @brief Constructor for video specific configuration. + * + * @param[in] sourceConfigType : The source config type + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + * @param[in] width : The width of the video + * @param[in] height : The height of the video + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + MediaSourceVideo(SourceConfigType sourceConfigType, const std::string &mimeType, bool hasDrm = true, + int32_t width = firebolt::rialto::kUndefinedSize, + int32_t height = firebolt::rialto::kUndefinedSize, + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSourceAV(sourceConfigType, mimeType, hasDrm, alignment, streamFormat, codecData), m_width(width), + m_height(height) + { + } + + private: + /** + * @brief The video width + */ + int m_width; + + /** + * @brief The video height + */ + int m_height; + }; // MediaSourceVideo + + /** + * @brief A class that represents media source video dolby vision derived from media source video data + */ + + class MediaSourceVideoDolbyVision : public MediaSourceVideo + { + public: + /** + * @brief Constructor for dolby vision specific configuration. + * + * @param[in] mimeType : The mime type string. + * @param[in] dolbyVisionProfile : The dolby vision profile + * @param[in] hasDrm : Information if source will use drm + * @param[in] width : The width of the video + * @param[in] height : The height of the video + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + MediaSourceVideoDolbyVision(const std::string &mimeType, int32_t dolbyVisionProfile, bool hasDrm = true, + int32_t width = firebolt::rialto::kUndefinedSize, + int32_t height = firebolt::rialto::kUndefinedSize, + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSourceVideo(SourceConfigType::VIDEO_DOLBY_VISION, mimeType, hasDrm, width, height, alignment, + streamFormat, codecData), + m_dolbyVisionProfile(dolbyVisionProfile) + { + } + ~MediaSourceVideoDolbyVision() {} + std::unique_ptr copy() const { return std::make_unique(*this); } + + /** + * @brief Gets the dolby vision profile + * + * @retval dolby vision profile + */ + uint32_t getDolbyVisionProfile() const { return m_dolbyVisionProfile; } + + protected: + /** + * @brief Variable that stores the Dolby Vision Profile + */ + uint32_t m_dolbyVisionProfile; + }; // MediaSourceVideoDolbyVision + + /** + * @brief A class that represents media source subtitle derived from media source video data + */ + class MediaSourceSubtitle : public MediaSource + { + public: + /** + * @brief Construct a new Media Source Subtitle object + * + * @param mimeType : The mime type string + * @param textTrackIdentifier : The text track identifier string + */ + MediaSourceSubtitle(const std::string &mimeType, const std::string &textTrackIdentifier) + : MediaSource(SourceConfigType::SUBTITLE, mimeType, false), m_textTrackIdentifier(textTrackIdentifier) + { + } + + ~MediaSourceSubtitle() {} + + MediaSourceType getType() const override { return MediaSourceType::SUBTITLE; } + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Get the Text Track Identifier object + * + * @return the text track identifier + */ + const std::string &getTextTrackIdentifier() const { return m_textTrackIdentifier; } + + protected: + /** + * @brief Variable that stores the text track identifier + */ + std::string m_textTrackIdentifier; + }; // MediaSourceSubtitle + + /** + * @brief A class that represents a media segment + */ + class MediaSegment + { + public: + /** + * @brief Default constructor. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] type : The source type. + * @param[in] timeStamp : The timestamp in nanoseconds. + * @param[in] duration : The duration in nanoseconds. + */ + MediaSegment(int32_t sourceId = 0, MediaSourceType type = MediaSourceType::UNKNOWN, int64_t timeStamp = 0, + int64_t duration = 0) + : m_sourceId(sourceId), m_type(type), m_data(nullptr), m_dataLength(0u), m_timeStamp(timeStamp), + m_duration(duration), m_encrypted(false), m_mediaKeySessionId(0), m_initWithLast15(0), + m_alignment(SegmentAlignment::UNDEFINED), m_cipherMode(CipherMode::UNKNOWN), m_crypt(0), m_skip(0), + m_encryptionPatternSet(false), m_displayOffset(std::nullopt) + { + } + + /** + * @brief Virtual destructor. + */ + virtual ~MediaSegment() {} + + /** + * @brief Makes a shallow copy of the segment + * + * @retval Shallow copy of the segment + */ + virtual std::unique_ptr copy() const { return std::make_unique(*this); } + + /** + * @brief Return the source id. + * + * @retval the source id. + */ + int32_t getId() const { return m_sourceId; } + + /** + * @brief The source type for the data. + * + * @retval the source type. + */ + MediaSourceType getType() const { return m_type; } + + /** + * @brief Returns a pointer to the data. + * + * @retval the data. + */ + const uint8_t *getData() const { return m_data; } + + /** + * @brief Returns a the data length. + * + * @retval the data. + */ + uint32_t getDataLength() const { return m_dataLength; } + + /** + * @brief Returns the time stamp. + * + * @retval the timestamp in nanoseconds. + */ + int64_t getTimeStamp() const { return m_timeStamp; } + + /** + * @brief Sets the time stamp (value in nanoseconds). + */ + void setTimeStamp(int64_t timeStamp) { m_timeStamp = timeStamp; } + + /** + * @brief Returns the duration. + * + * @retval the duration in nanoseconds. + */ + int64_t getDuration() const { return m_duration; } + + /** + * @brief Returns a pointer to the extra data. + * + * @retval the data. + */ + const std::vector &getExtraData() const { return m_extraData; } + + /** + * @brief Indicates that the data is encrypted. + * + * @retval true if the data is encrypted. + */ + bool isEncrypted() const { return m_encrypted; } + + /** + * @brief Returns the media key session id. Empty if unencrypted. + * + * @retval the media key session id. + */ + const int32_t getMediaKeySessionId() const { return m_mediaKeySessionId; } + + /** + * @brief Returns the key id. Empty if unencrypted. + * + * @retval the key id. + */ + const std::vector &getKeyId() const { return m_keyId; } + + /** + * @brief Returns the initialisation vector. Empty if unencrypted. + * + * @retval the initialisation vector. + */ + const std::vector &getInitVector() const { return m_initVector; } + + /** + * @brief Returns the sub samples. Empty if unencrypted. + * + * @retval the sub samples. + */ + const std::vector &getSubSamples() const { return m_subSamples; } + + /** + * @brief Returns the initWithLast15 value + * + * @retval the initWithLast15 value. + */ + const uint32_t getInitWithLast15() const { return m_initWithLast15; } + + /** + * @brief Returns the segment alignment + * + * @retval the segment alignment + */ + const SegmentAlignment getSegmentAlignment() const { return m_alignment; } + + /** + * @brief Gets the codec data + * + * @retval the codec data + */ + const std::shared_ptr &getCodecData() const { return m_codecData; } + + /** + * @brief Gets the cipher mode for common encryption + * + * @retval cipher mode uses for this sample + */ + const CipherMode &getCipherMode() const { return m_cipherMode; } + + /** + * @brief Gets the crypt & skip byte block for pattern encryption + * + * @param[out] crypt : Crypt byte block value + * @param[out] skip : Skip byte block value + * + * @retval if the encryption pattern has been set + */ + const bool getEncryptionPattern(uint32_t &crypt, uint32_t &skip) const + { + crypt = m_crypt; + skip = m_skip; + return m_encryptionPatternSet; + } + + /** + * @brief Gets the display offset + * + * @retval The offset in the source file of the beginning of the media segment. + */ + std::optional getDisplayOffset() const { return m_displayOffset; } + + protected: + /** + * @brief The source id. + */ + int32_t m_sourceId; + + /** + * @brief The source type. + */ + MediaSourceType m_type; + + /** + * @brief The data + */ + const uint8_t *m_data; + + /** + * @brief The data length + */ + uint32_t m_dataLength; + + /** + * @brief The time stamp. + */ + int64_t m_timeStamp; + + /** + * @brief The duration. + */ + int64_t m_duration; + + /** + * @brief Additional data for decoder + */ + std::shared_ptr m_codecData; + + /** + * @brief The data + */ + std::vector m_extraData; + + /** + * @brief Indicates the data is encrypted. + */ + bool m_encrypted; + + /** + * @brief Key session ID to use for decryption - only required for Netflix. + */ + int32_t m_mediaKeySessionId; + + /** + * @brief The encryption key id. + */ + std::vector m_keyId; + + /** + * @brief The encryption key initialisation vector. + */ + std::vector m_initVector; + + /** + * @brief The sub-sample pairs. + */ + std::vector m_subSamples; + + /** + * @brief Whether decryption context needs to be initialized with + * last 15 bytes. Currently this only applies to PlayReady DRM. + */ + uint32_t m_initWithLast15; + + /** + * @brief The alignment of media segment + */ + SegmentAlignment m_alignment; + + /** + * @brief Cipher mode of the sample. + */ + CipherMode m_cipherMode; + + /** + * @brief Crypt byte block value. + */ + uint32_t m_crypt; + + /** + * @brief Skip byte block value. + */ + uint32_t m_skip; + + /** + * @brief Whether the encryption pattern has been set. + */ + bool m_encryptionPatternSet; + + /** + * @brief The offset in the source file of the beginning of the media segment. + */ + std::optional m_displayOffset; + + public: + /** + * @brief Sets the segment data. + * + * @warning Note that the caller must guarantee that the buffer referenced by 'data' must remain + * valid until the corresponding call to haveData() has completed (at which point the data will + * have been copied out). + * + * @note This is for performance reasons to avoid multiple copies of AV data. A raw pointer is + * used for the same reason since most runtimes will expose a raw pointer to the data. + * + * @retval true on success. + */ + bool setData(uint32_t dataLength, const uint8_t *data) + { + m_dataLength = dataLength; + m_data = data; + return true; + } + + /** + * @brief Sets the extra data. + * + * @retval true on success. + */ + bool setExtraData(const std::vector &extraData) + { + m_extraData = extraData; + return true; + } + + /** + * @brief Sets the segment alignment + * + * @param[in] alignment : The new segment alignment + */ + void setSegmentAlignment(const SegmentAlignment &alignment) { m_alignment = alignment; } + + /** + * @brief Sets new codec_data for the segment. + * + * @note Should only be called if the codec data changes + * + * @param[in] codecData The updated codec data for the source + */ + void setCodecData(const std::shared_ptr &codecData) { m_codecData = codecData; } + + /** + * @brief Sets the encrypted flag. + * + * @param[in] encrypted : Set true to indicated encrypted data. + */ + void setEncrypted(bool encrypted) { m_encrypted = encrypted; } + + /** + * @brief Sets the media key session id. + * + * @param[in] mksId : the media key session id. + */ + void setMediaKeySessionId(int32_t mksId) { m_mediaKeySessionId = mksId; } + + /** + * @brief Sets the key id. + * + * @param[in] keyId : The key id. + */ + void setKeyId(const std::vector &keyId) { m_keyId = keyId; } + + /** + * @brief Sets the encryption initialisation vector. + * + * @param[in] initVector : The initialisation vector. + */ + void setInitVector(const std::vector &initVector) { m_initVector = initVector; } + + /** + * @brief Adds a sub-sample pair to the sub samples. + * + * @param[in] numClearBytes : The number of clear bytes. + * @param[in] numEncryptedBytes : The number of encrypted bytes. + */ + void addSubSample(size_t numClearBytes, size_t numEncryptedBytes) + { + m_subSamples.emplace_back(SubSamplePair{numClearBytes, numEncryptedBytes}); + } + + /** + * @brief Sets initWithLast15 value + * + * @param[in] initWithLast15 : initWithLast15 value + */ + void setInitWithLast15(uint32_t initWithLast15) { m_initWithLast15 = initWithLast15; } + + /** + * @brief Sets the cipher mode for common encryption. + * + * @param[in] cipherMode : Specifies cipher mode uses for this sample. + */ + void setCipherMode(CipherMode cipherMode) { m_cipherMode = cipherMode; } + + /** + * @brief Sets the crypt & skip byte block for pattern encryption + * + * @param[in] crypt : Crypt byte block value + * @param[in] skip : Skip byte block value + */ + void setEncryptionPattern(uint32_t crypt, uint32_t skip) + { + m_crypt = crypt; + m_skip = skip; + m_encryptionPatternSet = true; + } + + /** + * @brief Sets the display offset + * + * @param[in] displayOffset : The offset in the source file of the beginning of the media segment. + */ + void setDisplayOffset(uint64_t displayOffset) { m_displayOffset = displayOffset; } + + /** + * @brief Copies the data from other to this. + */ + void copy(const MediaSegment &other); + }; // MediaSegment + + /** + * @brief A class that represents media source audio data + */ + class MediaSegmentAudio : public MediaSegment + { + public: + /** + * @brief Default constructor. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] timeStamp : The timestamp in nanoseconds. + * @param[in] duration : The duration in nanoseconds. + * @param[in] sampleRate : The sample rate in samples per second. + * @param[in] numberOfChannels : The number of audio channels. + * @param[in] clippingStart : The amount of audio to clip from start of buffer + * @param[in] clippingEnd : The amount of audio to clip from end of buffer + */ + MediaSegmentAudio(int32_t sourceId = 0, int64_t timeStamp = 0, int64_t duration = 0, int32_t sampleRate = 0, + int32_t numberOfChannels = 0, uint64_t clippingStart = 0, uint64_t clippingEnd = 0) + : MediaSegment(sourceId, MediaSourceType::AUDIO, timeStamp, duration), m_sampleRate(sampleRate), + m_numberOfChannels(numberOfChannels), m_clippingStart(clippingStart), m_clippingEnd(clippingEnd) + { + } + + /** + * @brief Copy constructor. + */ + MediaSegmentAudio(const MediaSegmentAudio &other) : MediaSegment(other) + { + m_sampleRate = other.m_sampleRate; + m_numberOfChannels = other.m_numberOfChannels; + } + + /** + * @brief Makes a shallow copy of the segment + * + * @retval Shallow copy of the segment + */ + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Return the audio sample rate. + * + * @retval the sample rate in samples per second. + */ + int32_t getSampleRate() const { return m_sampleRate; } + + /** + * @brief Return the number of audio channels. + * + * @retval the number of channels. + */ + int32_t getNumberOfChannels() const { return m_numberOfChannels; } + + /** + * @brief Return the amount of audio to clip from start of buffer + * + * @retval the amount of audio to clip from start of buffer + */ + uint64_t getClippingStart() const { return m_clippingStart; } + + /** + * @brief Return the amount of audio to clip from end of buffer + * + * @retval the amount of audio to clip from end of buffer + */ + uint64_t getClippingEnd() const { return m_clippingEnd; } + + /** + * @brief Copy assignment operator. + * + * @retval the copy. + */ + MediaSegmentAudio &operator=(const MediaSegmentAudio &other) + { + copy(other); + return *this; + } + + protected: + /** + * @brief Copies the data from other to this. + */ + void copy(const MediaSegmentAudio &other); + + /** + * @brief The audio sample rate. + */ + int32_t m_sampleRate; + + /** + * @brief The number of audio channels. + */ + int32_t m_numberOfChannels; + + /** + * @brief The amount of audio to clip from start of buffer + */ + uint64_t m_clippingStart; + + /** + * @brief The amount of audio to clip from end of buffer + */ + uint64_t m_clippingEnd; + }; // MediaSegmentAudio + + /** + * @brief A class that represents media source video data + */ + class MediaSegmentVideo : public MediaSegment + { + public: + /** + * @brief Default constructor. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] timeStamp : The timestamp in nanoseconds. + * @param[in] duration : The duration in nanoseconds. + * @param[in] width : The video width in pixels. + * @param[in] height : The video height in pixels. + * @param[in] frameRate : The fractional framerate of the sample. + */ + MediaSegmentVideo(int32_t sourceId = 0, int64_t timeStamp = 0, int64_t duration = 0, + int32_t width = firebolt::rialto::kUndefinedSize, + int32_t height = firebolt::rialto::kUndefinedSize, + firebolt::rialto::Fraction frameRate = {firebolt::rialto::kUndefinedSize, + firebolt::rialto::kUndefinedSize}) + : MediaSegment(sourceId, MediaSourceType::VIDEO, timeStamp, duration), m_width(width), m_height(height), + m_frameRate(frameRate) + { + } + + /** + * @brief Copy constructor. + */ + MediaSegmentVideo(const MediaSegmentVideo &other) : MediaSegment(other) + { + m_width = other.m_width; + m_height = other.m_height; + m_frameRate = other.m_frameRate; + } + + /** + * @brief Makes a shallow copy of the segment + * + * @retval Shallow copy of the segment + */ + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Return the video width. + * + * @retval the video width in pixels. + */ + int32_t getWidth() const { return m_width; } + + /** + * @brief Return the video height. + * + * @retval the video height in pixels. + */ + int32_t getHeight() const { return m_height; } + + /** + * @brief Return the video frameRate. + * + * @retval the fractional framerate of the sample. + */ + firebolt::rialto::Fraction getFrameRate() const { return m_frameRate; } + + /** + * @brief Copy assignment operator. + * + * @retval the copy. + */ + MediaSegmentVideo &operator=(const MediaSegmentVideo &other) + { + copy(other); + return *this; + } + + protected: + /** + * @brief Copies the data from other to this. + */ + void copy(const MediaSegmentVideo &other); + + /** + * @brief The video width in pixels. + */ + int32_t m_width; + + /** + * @brief The video height in pixels. + */ + int32_t m_height; + + /** + * @brief The fractional framerate of the sample. + */ + firebolt::rialto::Fraction m_frameRate; + }; // MediaSegmentVideo + + /** + * @brief A vector that contains one or more media segments. + */ + typedef std::vector> MediaSegmentVector; + + /** + * @brief Returns the media player client. + * + * @retval The media player client. + */ + virtual std::weak_ptr getClient() = 0; + + /** + * @brief Loads the media and backend delegate. + * + * This method loads the media and backend appropriate for the media. + * The media type determines the backend delegate to use to play back + * the media. The MIME type confirms the type and CODECs for the media. + * The URL will comprise the media URL for types MediaType::URL and + * MediaType::HLS. For MediaType::MSE the URL will comprise a blob URL + * as the data is loaded by the browser. + * + * @param[in] type : The media type. + * @param[in] mimeType : The MIME type. + * @param[in] url : The URL. + */ + virtual bool load(MediaType type, const std::string &mimeType, const std::string &url) = 0; + + /** + * @brief Attaches a source stream to the backend. + * + * This method is called by Rialto Client to attach a media source stream to + * the backend. It is only called when Media Source Extensions are + * being used. I.e. if the MediaType value in load() is + * MediaType::MSE. + * + * @param[in] source : The source. + * + * @retval true on success. + */ + virtual bool attachSource(const std::unique_ptr &source) = 0; + + /** + * @brief Unattaches a source. + * + * This method is called by Rialto Client to detach a media source stream from + * the backend. It is only called when Media Source Extensions are + * being used. I.e. if the MediaType value in load() is + * MediaType::MSE. + * + * @param[in] id : The source id. Value should be set to the MediaSource.id returned after attachSource() + * + * @retval true on success. + */ + virtual bool removeSource(int32_t id) = 0; + + /** + * @brief Notifies Rialto Server that all sources were attached + * + * This method is called by Rialto Client to notify the RialtoServer + * that all sources were attached. + * + * Must be called, otherwise streaming cannot commence. + * Can be called only once. + * + * @retval true on success. + */ + virtual bool allSourcesAttached() = 0; + + /** + * @brief Starts playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request playback and then return. + * + * Once the backend is successfully playing it should notify the + * media player client of playback state + * IMediaPipelineClient::PlaybackState::PLAYING. + * + * @retval true on success. + */ + virtual bool play() = 0; + + /** + * @brief Pauses playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the playback pause and then return. + * + * Once the backend is successfully playing it should notify the + * media player client of playback state + *IMediaPipelineClient::PlaybackState::PAUSED. + * + * @retval true on success. + */ + virtual bool pause() = 0; + + /** + * @brief Stops playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the playback stop and then return. + * + * Once the backend is successfully stopped it should notify the + * media player client of playback state + * IMediaPipelineClient::PlaybackState::STOPPED. + * + * @retval true on success. + */ + virtual bool stop() = 0; + + /** + * @brief Set the playback rate + * + * This method sets the playback rate. The supported playback rates + * are dependent upon the backend playback method. + * + * @param[in] rate : The playback rate. + * + * @retval true on success. + */ + virtual bool setPlaybackRate(double rate) = 0; + + /** + * @brief Set the playback position in nanoseconds. + * + * If playback has not started this method sets the start position + * for playback. If playback has started this method performs a seek. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the new playback position and then return. + * + * Once the backend is seeking it should notify the media player + * client of playback state + * IMediaPipelineClient::PlaybackState::SEEKING. When seeking has + * completed the state IMediaPipelineClient::PlaybackState::SEEK_DONE + * should be notified followed by + * IMediaPipelineClient::PlaybackState::PLAYING. + * + * @param[in] position : The playback position in nanoseconds. + * + * @retval true on success. + */ + virtual bool setPosition(int64_t position) = 0; + + /** + * @brief Get the playback position in nanoseconds. + * + * This method is sychronous, it returns current playback position + * + * @param[out] position : The playback position in nanoseconds + * + * @retval true on success. + */ + virtual bool getPosition(int64_t &position) = 0; + + /** + * @brief Get stats for this source. + * + * This method is sychronous, it returns dropped frames and rendered frames + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[out] renderedFrames : The number of rendered frames + * @param[out] droppedFrames : The number of dropped frames + * + * @retval true on success. + */ + virtual bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; + + /** + * @brief Sets the "Immediate Output" property for this source. + * + * This method is asynchronous, it will set the "Immediate Output" property + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] immediateOutput : Set immediate output mode on the sink + * + * @retval true on success. + */ + virtual bool setImmediateOutput(int32_t sourceId, bool immediateOutput) = 0; + + /** + * @brief Gets the "Immediate Output" property for this source. + * + * This method is sychronous, it gets the "Immediate Output" property + * + * @param[in] sourceId : The source id. Value should be get to the MediaSource.id returned after attachSource() + * @param[out] immediateOutput : Get immediate output mode on the sink + * + * @retval true on success. + */ + virtual bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) = 0; + + /** + * @brief Sets the coordinates of where the video should be displayed. + * + * @param[in] x : The x position in pixels. + * @param[in] y : The y position in pixels. + * @param[in] width : The width in pixels. + * @param[in] height : The height in pixels. + * + * @retval true on success. + */ + virtual bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; + + /** + * @brief Returns data requested using notifyNeedMediaData(). + * + * This method is called as a result of calling notifyNeedMediaData() on + * the media client. The status value indicates the success or + * otherwise of the request. The client must first call addSegment() for + * for each media segment to be sent. + * A status of MediaSourceStatus::OK indicates success and there will + * be data within the data vector. A status of MediaSourceStatus::EOS + * indicates success but the end of the stream was reached. Again + * there will be data in the vector. A status of + * MediaSourceStatus::ERROR indicates an error occurred and no data + * was returned. + * + * + * @param[in] status : The status + * @param[in] needDataRequestId : Need data request id + */ + virtual bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) = 0; + + /** + * @brief Adds a single segment to Rialto in response to notifyNeedData() + * + * This method is should be called by the client as a result of a notifyNeedData() + * notification. The client should call this API for each segment to be sent in + * response to the notification and then call haveData() when all segments + * have been 'added'. + * + * If the return code is NO_SPACE the segment has not been accepted but this is + * not an error. The client should retain the segment until the next notifyNeedData() + * is received for the source and immediately call haveData() to trigger Rialto + * to start processing the segments already added. + * + * @param[in] needDataRequestId : The status + * @param[in] mediaSegment : The data returned. + * + * @retval status of adding segment + */ + virtual AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) = 0; + + /** + * @brief Requests to render a prerolled frame + */ + virtual bool renderFrame() = 0; + + /** + * @brief Set the target volume level and transition duration with easing type. + * By default volume is set immediately if duration and type are not set. + * + * @param[in] targetVolume : Target volume level (0.0 - 1.0) + * @param[in] volumeDuration : (Optional) Duration of the volume transition in milliseconds + * @param[in] easeType : (Optional) Easing type for the volume transition + * + * @retval true on success, false otherwise. + */ + virtual bool setVolume(double targetVolume, uint32_t volumeDuration = 0, + EaseType easeType = EaseType::EASE_LINEAR) = 0; + + /** + * @brief Get current audio level. Fetches the current volume level for the pipeline. + * + * @param[out] currentVolume : Current volume level (range 0.0 - 1.0) + * + * @retval true on success, false otherwise. + */ + virtual bool getVolume(double ¤tVolume) = 0; + + /** + * @brief Set mute status of pipeline. + * + * Change mute status of media source + * + * @param[in] sourceId Source, which mute status should be changed + * @param[in] mute Desired mute state, true=muted, false=not muted + * + * @retval true on success false otherwise + */ + virtual bool setMute(int32_t sourceId, bool mute) = 0; + + /** + * @brief Get current mute status of the media source + * + * @param[in] sourceId Source, which mute status should be fetched + * @param[out] mute Current mute state + * + * @retval true on success false otherwise + */ + virtual bool getMute(int32_t sourceId, bool &mute) = 0; + + /** + * @brief Change Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + virtual bool setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; + + /** + * @brief Get Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; + + /** + * @brief Set low latency property on the audio sink. Default false. + * + * For use with gaming (no audio decoding, no a/v sync). + * + * @param[in] lowLatency : The low latency value to set. + * + * @retval true on success false otherwise + */ + virtual bool setLowLatency(bool lowLatency) = 0; + + /** + * @brief Set sync property on the audio sink. Default false. + * + * Syncs the stream on the clock. + * + * @param[in] sync : The sync value to set. + * + * @retval true on success false otherwise + */ + virtual bool setSync(bool sync) = 0; + + /** + * @brief Get sync property on the audio sink. + * + * @param[out] sync : Current sync value. + * + * @retval true on success false otherwise + */ + virtual bool getSync(bool &sync) = 0; + + /** + * @brief Set sync off property on the audio decoder. Default false. + * + * Turn on free running audio. Must be set before pipeline is PLAYING state. + * + * @param[in] syncOff : The sync off value to set. + * + * @retval true on success false otherwise + */ + virtual bool setSyncOff(bool syncOff) = 0; + + /** + * @brief Set stream sync mode property on the audio decoder or video filter. Default 0. + * + * 1 - Frame to decode frame will immediately proceed next frame sync. + * 0 - Frame decoded with no frame sync. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] streamSyncMode : The stream sync mode value to set. + * + * @retval true on success false otherwise + */ + virtual bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) = 0; + + /** + * @brief Get stream sync mode property on the audio decoder. + * + * @param[out] streamSyncMode : Current stream sync mode value. + * + * @retval true on success false otherwise + */ + virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; + + /** + * @brief Flushes a source. + * + * This method is called by Rialto Client to flush out all queued data for a media source stream. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] resetTime : True if time should be reset + * @param[out] async : True if flushed source is asynchronous (will preroll after flush) + * + * @retval true on success. + */ + virtual bool flush(int32_t sourceId, bool resetTime, bool &async) = 0; + + /** + * @brief Set the source position in nanoseconds. + * + * This method sets the start position for a source. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] position : The position in nanoseconds. + * @param[in] resetTime : True if time should be reset + * @param[in] appliedRate : The applied rate after seek. Default value is 1.0. + * @param[in] stopPosition : The position of last pushed buffer + * + * @retval true on success. + */ + virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, + uint64_t stopPosition = kUndefinedPosition) = 0; + + /** + * @brief Process audio gap + * + * This method handles audio gap in order to avoid audio pops during transitions. + * + * @param[in] position : Audio pts fade position + * @param[in] duration : Audio pts fade duration + * @param[in] discontinuityGap : Audio discontinuity gap + * @param[in] audioAac : True if audio codec is AAC + * + * @retval true on success. + */ + virtual bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; + + /** + * @brief Set buffering limit + * + * This method enables/disables limit buffering and sets millisecond threshold used. + * Use kInvalidLimitBuffering to disable limit buffering + * + * @param[in] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + virtual bool setBufferingLimit(uint32_t limitBufferingMs) = 0; + + /** + * @brief Get buffering limit + * + * This method returns current value of buffering limit in milliseconds + * Method will return kInvalidLimitBuffering limit buffering is disabled + * + * @param[out] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; + + /** + * @brief Enables/disables the buffering option + * + * This method enables the buffering option so that BUFFERING messages are + * emitted based on low-/high-percent thresholds. + * + * @param[in] useBuffering : true if buffering option enabled. + * + * @retval true on success. + */ + virtual bool setUseBuffering(bool useBuffering) = 0; + + /** + * @brief Checks, if buffering is enabled + * + * This method returns true, if buffering is enabled + * + * @param[out] useBuffering : true if buffering option is enabled. + * + * @retval true on success. + */ + virtual bool getUseBuffering(bool &useBuffering) = 0; + + /** + * @brief Switches a source stream. + * + * This method is called to switch a media source stream. + * + * @param[in] source : The source. + * + * @retval true on success. + */ + virtual bool switchSource(const std::unique_ptr &source) = 0; +}; // IMediaPipeline + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ diff --git a/rialto-master/media/public/include/IMediaPipelineCapabilities.h b/rialto-master/media/public/include/IMediaPipelineCapabilities.h new file mode 100644 index 000000000..63a26c611 --- /dev/null +++ b/rialto-master/media/public/include/IMediaPipelineCapabilities.h @@ -0,0 +1,121 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ + +/** + * @file IMediaPipelineCapabilities.h + * + * The definition of the IMediaPipelineCapabilities interface. + */ + +#include "MediaCommon.h" +#include +#include +#include + +namespace firebolt::rialto +{ +class IMediaPipelineCapabilities; + +/** + * @brief IMediaPipelineCapabilities factory class, for getting the IMediaPipelineCapabilities object. + */ +class IMediaPipelineCapabilitiesFactory +{ +public: + IMediaPipelineCapabilitiesFactory() = default; + virtual ~IMediaPipelineCapabilitiesFactory() = default; + + /** + * @brief Gets the IMediaPipelineCapabilitiesFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates the IMediaPipelineCapabilities object. + * + * @retval the MediaPipelineCapabilities instance or null on error. + */ + virtual std::unique_ptr createMediaPipelineCapabilities() const = 0; +}; + +/** + * @brief The definition of the IMediaPipelineCapabilities interface. + * + * This interface defines the public API of Rialto for querying EME decryption capabilities. + * It should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaPipelineCapabilities +{ +public: + IMediaPipelineCapabilities() = default; + virtual ~IMediaPipelineCapabilities() = default; + + IMediaPipelineCapabilities(const IMediaPipelineCapabilities &) = delete; + IMediaPipelineCapabilities &operator=(const IMediaPipelineCapabilities &) = delete; + IMediaPipelineCapabilities(IMediaPipelineCapabilities &&) = delete; + IMediaPipelineCapabilities &operator=(IMediaPipelineCapabilities &&) = delete; + + /** + * @brief Returns the MSE mime types supported by Rialto for \a sourceType + * + * @param[in] sourceType : source type + * + * @retval The supported mime types. + */ + virtual std::vector getSupportedMimeTypes(MediaSourceType sourceType) = 0; + + /** + * @brief Indicates if the specified mime type is supported. + * + * This method should be called to ensure that the specified mime + * type is supported by Rialto. + * + * @param[in] mimeType : The mime type to check. + * + * @retval true if supported. + */ + virtual bool isMimeTypeSupported(const std::string &mimeType) = 0; + + /** + * @brief Check sinks and decoders for supported properties + * + * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched + * @param[in] propertyNames : A vector of property names to look for + * + * @retval Returns the subset of propertyNames that are supported by the mediaType + */ + virtual std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) = 0; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + virtual bool isVideoMaster(bool &isVideoMaster) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ diff --git a/rialto-master/media/public/include/IMediaPipelineClient.h b/rialto-master/media/public/include/IMediaPipelineClient.h new file mode 100644 index 000000000..34dcac76a --- /dev/null +++ b/rialto-master/media/public/include/IMediaPipelineClient.h @@ -0,0 +1,220 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ +#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ + +#include +#include +#include +#include + +/** + * @file IMediaPipelineClient.h + * + * The definition of the IMediaPipelineClient interface. + * + * This file comprises the definition of the IMediaPipelineClient abstract + * class. This is the API by which a IMediaPipeline implementation will + * pass notifications to its client. + */ + +namespace firebolt::rialto +{ +/* Values representing custom duration values, used by IMediaPipelineClient::notifyDuration() method*/ +/** + * @brief Stream duration is unknown or undefined + * + */ +constexpr int64_t kDurationUnknown{-1}; +/** + * @brief Stream duration is unending or live + */ +constexpr int64_t kDurationUnending{-2}; + +/** + * @brief The Rialto media player client interface. + * + * This is The Rialto media player client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the + * state of the player or that provides data for media playback. + */ +class IMediaPipelineClient +{ +public: + /** + * @brief Virtual destructor + */ + virtual ~IMediaPipelineClient() {} + + /** + * @brief Notifies the client of the total duration of the media. + * + * This method notifies the client of the total duration of the + * media in nanoseconds. If this is unknown or undefined then a value + * of kDurationUnknown. If the stream is unending, for example + * live, then a value of kDurationUnending should be used. + * + * @param[in] duration : The duration of the media in seconds. + */ + virtual void notifyDuration(int64_t duration) = 0; + + /** + * @brief Notifies the client of the current playback position. + * + * This method notifies the client of the current playback position + * in nanoseconds. + * + * When playing this should be called often enough to provide + * sufficient granularity of position reporting. Typically this will + * be every 0.25s. + * + * @param[in] position : The playback position in nanoseconds. + */ + virtual void notifyPosition(int64_t position) = 0; + + /** + * @brief Notifies the client of the native size of the video and + the pixel aspect ratio. + * + * This method should be called one or more times to reporting the + * native video size. If the video size changes the method should be + * called with the updated size or aspect ratio. + * + * @param[in] width : The width in pixels. + * @param[in] height : The height in pixels. + * @param[in] aspect : The pixel aspect ratio. + */ + virtual void notifyNativeSize(uint32_t width, uint32_t height, double aspect = 1.0) = 0; + + /** + * @brief Notifies the client of the network state. + * + * The network state reflects the state of the network. For backend + * streaming, this is important as the backend uses the network to obtain the media data directly. + * + * For streaming that uses the browser to obtain data, say Media Source + * Extensions playback, only the states NetworkState::IDLE, + * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be + * indicated by the backend. + * + * @param[in] state : The new network state. + */ + virtual void notifyNetworkState(NetworkState state) = 0; + + /** + * @brief Notifies the client of the playback state. + * + * The player will start IDLE. Once play() has been called the player + * will be PLAYING, or once pause() has been called the player will be + * PAUSED. A seek() request will result in SEEKING and once the seek + * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED + * state will be issued after a stop() request. + * + * @param[in] state : The new playback state. + */ + virtual void notifyPlaybackState(PlaybackState state) = 0; + + /** + * @brief Notifies the client that video data is available + * + * @param[in] hasData true if video data is available. + */ + virtual void notifyVideoData(bool hasData) = 0; + + /** + * @brief Notifies the client that audio data is available + * + * @param[in] hasData true if audio data is available. + */ + virtual void notifyAudioData(bool hasData) = 0; + + /** + * @brief Notifies the client that we need media data. + * + * This method notifies the client that we need media data from the + * client. This is only used when Media Source Extensions are used. + * In that case media is read by JavaScript and buffered by the + * browser before being passed to this API for decoding. + * + * You cannot request data if a data request is currently pending. + * + * The frames the client sends should meet the criteria: + * numFramesSent <= frameCount + * numBytesSent <= maxMediaBytes + * + * @param[in] sourceId : The source to read data from. + * @param[in] frameCount : The number of frames to read. + * @param[in] needDataRequestId : Need data request id. + * @param[in] shmInfo : Information for populating the shared memory (null if not applicable to the client). + */ + virtual void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, + const std::shared_ptr &shmInfo) = 0; + + /** + * @brief Notifies the client to cancel any outstand need request. + * + * This method notifies the client to cancel any data request made using + * notifyNeedMediaData(). It is not an error to cancel a request for data + * when one is not pending. + * + * @param[in] sourceId : The source id to cancel the request for. + */ + virtual void notifyCancelNeedMediaData(int32_t sourceId) = 0; + + /** + * @brief Notifies the client of a Quality Of Service update from the Player. + * + * Notification shall be sent whenever a video/audio buffer drops a frame/sample. + * + * @param[in] sourceId : The id of the source that produced the Qos. + * @param[in] qosInfo : The information provided in the update. + */ + virtual void notifyQos(int32_t sourceId, const QosInfo &qosInfo) = 0; + + /** + * @brief Notifies the client that buffer underflow occurred. + * + * Notification shall be sent whenever a video/audio buffer underflow occurs + * + * @param[in] sourceId : The id of the source that produced the buffer underflow + */ + virtual void notifyBufferUnderflow(int32_t sourceId) = 0; + + /** + * @brief Notifies the client that a non-fatal error has occurred in the player. + * + * PlaybackState remains unchanged when an error occurs. + * + * @param[in] sourceId : The id of the source that produced the error. + * @param[in] error : The type of error that occured. + */ + virtual void notifyPlaybackError(int32_t sourceId, PlaybackError error) = 0; + + /** + * @brief Notifies the client that the source has been flushed. + * + * Notification shall be sent whenever a flush procedure is finished. + * + * @param[in] sourceId : The id of the source that has been flushed. + */ + virtual void notifySourceFlushed(int32_t sourceId) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ diff --git a/rialto-master/media/public/include/IWebAudioPlayer.h b/rialto-master/media/public/include/IWebAudioPlayer.h new file mode 100644 index 000000000..b61993910 --- /dev/null +++ b/rialto-master/media/public/include/IWebAudioPlayer.h @@ -0,0 +1,214 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ +#define FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ + +/** + * @file IWebAudioPlayer.h + * + * The definition of the IWebAudioPlayer interface. + * + * This interface defines the public API of Rialto for mixing PCM audio with + * current audio output. + */ + +#include +#include +#include + +#include "IWebAudioPlayerClient.h" +#include "MediaCommon.h" + +namespace firebolt::rialto +{ +class IWebAudioPlayer; + +/** + * @brief IWebAudioPlayer factory class, returns a concrete implementation of IWebAudioPlayer + */ +class IWebAudioPlayerFactory +{ +public: + IWebAudioPlayerFactory() = default; + virtual ~IWebAudioPlayerFactory() = default; + + /** + * @brief Create a IWebAudioPlayerFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IWebAudioPlayer factory method, returns a concrete implementation of + * IWebAudioPlayer for playback of audio. + * + * @param[in] client: The Web Audio Player client + * @param[in] audioMimeType: The audio encoding format, currently only "audio/x-raw" (PCM) + * @param[in] priority: Priority value for this pipeline. + * @param[in] config: Additional type dependent configuration data or nullptr + * + * Some platforms have limited numbers of audio playbacks that can be mixed. The client application + * should therefore assign a priority to each audio player it creates, starting with priority 1 for + * the most important, priority 2 for the next etc. If a platform supports 'n' players, then any + * player with priority>n will appear to function normally by but the audio data will be silently + * discarded. + * + * @retval the new Web Audio Player instance or null on error. + */ + virtual std::unique_ptr createWebAudioPlayer(std::weak_ptr client, + const std::string &audioMimeType, + const uint32_t priority, + std::weak_ptr config) const = 0; +}; + +/** + * @brief The definition of the IWebAudioPlayer interface. + * + * This interface defines the public API of Rialto for mixing PCM audio with + * current audio output. It should be implemented by both Rialto Client & + * Rialto Server. + */ +class IWebAudioPlayer +{ +public: + IWebAudioPlayer() = default; + virtual ~IWebAudioPlayer() = default; + + IWebAudioPlayer(const IWebAudioPlayer &) = delete; + IWebAudioPlayer &operator=(const IWebAudioPlayer &) = delete; + IWebAudioPlayer(IWebAudioPlayer &&) = delete; + IWebAudioPlayer &operator=(IWebAudioPlayer &&) = delete; + + /** + * @brief Play the web audio. + * + * Sets the player to the PLAYING state (it is IDLE when created). + * + * @retval true on success. + */ + virtual bool play() = 0; + + /** + * @brief Pause the web audio. + * + * Sets the player to the PAUSED state (it is IDLE when created). + * + * @retval true on success. + */ + virtual bool pause() = 0; + + /** + * @brief Notify EOS. + * + * Notifies the player that no further frames will be provided. When + * all buffered frames are played the player will enter the EOS state. + * + * @retval true on success. + */ + virtual bool setEos() = 0; + + /** + * @brief Get the available frames. + * + * Gets the available buffer space for sending more frames. Client should not + * write more than the number of frames returned by this API. + * + * webAudioShmInfo is not required by the client application and can be ignored. + * + * @param[out] availableFrames : Number of frames available to be written. + * @param[out] webAudioShmInfo : Location in shm to write the data (Server only). + * + * @retval true on success. + */ + virtual bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) = 0; + + /** + * @brief Get the delay frames. + * + * Gets the frame delay of the playback from Rialto. Frame delay is the number + * of frames left to play by the server. + * + * @param[out] delayFrames : Number of frames to be played. + * + * @retval true on success. + */ + virtual bool getBufferDelay(uint32_t &delayFrames) = 0; + + /** + * @brief Write audio frames + * + * Sends a buffer of audio data for playback + * + * @param[in] numberOfFrames : Number of frames of audio in 'data'. + * @param[in] data : Pointer to the data, byte length = numberOfFrames*sampleSize + * + * @retval true on success. + */ + virtual bool writeBuffer(const uint32_t numberOfFrames, void *data) = 0; + + /** + * @brief Get device information. + * + * Gets information for the web audio playback. + * This information is used to determine the preferred buffer size to commit, + * the maximum buffer size an application can commit and whether buffers can + * be committed before a Play request. + * + * @param[out] preferredFrames : preferred number of frames to be commited. + * @param[out] maximumFrames : Maximum number of frames that can be commited. + * @param[out] supportDeferredPlay : Whether defered play is supported. + * + * @retval true on success. + */ + virtual bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) = 0; + + /** + * + * @brief Set level and transition of audio attenuation + * + * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume) + * + * @param[in] volume : Target volume level (0.0 - 1.0) + * + * @retval true on success false otherwise + */ + virtual bool setVolume(double volume) = 0; + + /** + * @brief Get current audio level + * + * Fetches the current volume level for the pipeline. + * + * @param[out] volume : Current volume level (range 0.0 - 1.0) + * + * @retval true on success false otherwise + */ + virtual bool getVolume(double &volume) = 0; + + /** + * @brief Returns the web audio player client. + * + * @retval The web audio player client. + */ + virtual std::weak_ptr getClient() = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ diff --git a/rialto-master/media/public/include/IWebAudioPlayerClient.h b/rialto-master/media/public/include/IWebAudioPlayerClient.h new file mode 100644 index 000000000..8820bf26c --- /dev/null +++ b/rialto-master/media/public/include/IWebAudioPlayerClient.h @@ -0,0 +1,66 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ +#define FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ + +/** + * @file IWebAudioPlayerClient.h + * + * The definition of the IWebAudioPlayerClient interface. + * + * This is the API by which a IWebAudioPlayer implementation will + * pass notifications to its client. + */ + +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief The Rialto web audio client interface. + * + * This is The Rialto web audio player client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the + * state of the web audio player. + */ +class IWebAudioPlayerClient +{ +public: + /** + * @brief Virtual destructor + */ + virtual ~IWebAudioPlayerClient() {} + + /** + * @brief Notifies the client of the playback state. + * + * The player will start IDLE. Once play() has been called the player + * will be PLAYING. When pause() is call3d the player will be PAUSED. + * When no further frames available for playout and setEos() has been + * called the player will be END_OF_STREAM. + * + * @param[in] state : The new playback state. + */ + virtual void notifyState(WebAudioPlayerState state) = 0; +}; + +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ diff --git a/rialto-master/media/public/include/MediaCommon.h b/rialto-master/media/public/include/MediaCommon.h new file mode 100644 index 000000000..2e783e032 --- /dev/null +++ b/rialto-master/media/public/include/MediaCommon.h @@ -0,0 +1,468 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_MEDIA_COMMON_H_ +#define FIREBOLT_RIALTO_MEDIA_COMMON_H_ + +/** + * @file MediaCommon.h + * + * The definition of the Rialto Common types + * + */ + +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief The value of an invalid key session. + */ +constexpr int32_t kInvalidSessionId{-1}; + +/** + * @brief The value of an invalid audio channels number. + */ +constexpr uint32_t kInvalidAudioChannels{0}; + +/** + * @brief The value of an invalid audio sampling rate. + */ +constexpr uint32_t kInvalidAudioSampleRate{0}; + +/** + * @brief The value of an undefined size + */ +constexpr int32_t kUndefinedSize{0}; + +/** + * @brief The value of an invalid limitBuffering + */ +constexpr uint32_t kInvalidLimitBuffering{std::numeric_limits::max()}; + +/** + * @brief The value of undefined position + */ +constexpr uint64_t kUndefinedPosition{std::numeric_limits::max()}; + +/** + * @brief The supported types of media source. + */ +enum class MediaSourceType +{ + UNKNOWN, + AUDIO, + VIDEO, + SUBTITLE +}; + +/** + * @brief Shows the types of source configuration. + */ +enum class SourceConfigType +{ + UNKNOWN, + AUDIO, + VIDEO, + VIDEO_DOLBY_VISION, + SUBTITLE +}; + +/** + * @brief The supported audio ease types. + */ +enum class AudioEaseType +{ + LINEAR = 0, + INCUBIC, + OUTCUBIC +}; + +/** + * @brief The media type of media to be played. + */ +enum class MediaType +{ + UNKNOWN, /**< Media type not known. */ + MSE /**< Media is MSE and will request data. */ +}; + +/** + * @brief The media source status. This is the status of the source + * after a read. + */ +enum class MediaSourceStatus +{ + OK, /**< Source data provided without error. */ + EOS, /**< Source reached the end of stream. */ + ERROR, /**< There was an error providing source data. */ + CODEC_CHANGED, /**< The codec has changed and the decoder must be reconfigured */ + NO_AVAILABLE_SAMPLES /**< Could not retrieve media samples. */ +}; + +/** + * @brief The Network State + * + * The network state reflects the state of the network. For backend + * streaming, say using MediaPipelineURLDelegate, this is important + * as the backend uses the network to obtain the media data directly. + * + * For streaming that uses the browser to obtain data, say Media Source + * Extensions playback, only the states NetworkState::IDLE, + * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be + * indicated by the backend. + */ +enum class NetworkState +{ + UNKNOWN, /**< An unknown or undefined network state. */ + IDLE, /**< The network is idle. */ + BUFFERING, /**< The network is buffering data before playing. */ + BUFFERING_PROGRESS, /**< The network is buffering data whilst playing. */ + BUFFERED, /**< All the data is buffered. */ + STALLED, /**< The network has stalled but may recover. */ + FORMAT_ERROR, /**< The data is the wrong format. */ + NETWORK_ERROR, /**< There has been a network error. Playback stops. */ + DECODE_ERROR /**< There has been a decode error of the data. */ +}; + +/** + * @brief The Playback State + * + * The player will start IDLE. Once play() has been called the player + * will be PLAYING, or once pause() has been called the player will be + * PAUSED. A seek() request will result in SEEKING and once the seek + * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED + * state will be issued after a stop() request. + */ +enum class PlaybackState +{ + UNKNOWN, /**< An unknown or undefined playback state. */ + IDLE, /**< The backend player is idle. */ + PLAYING, /**< The backend player is playing media. */ + PAUSED, /**< The backend player is paused. */ + SEEKING, /**< The backend player is seeking a new playback position. */ + SEEK_DONE, /**< The backend player has finished seek. */ + STOPPED, /**< The backend player has stopped playback. */ + END_OF_STREAM, /**< The backend player has got to the end of playback. */ + FAILURE /**< The backend player failed to set playback state. */ +}; + +/** + * @brief The Format of the audio samples. Used by the raw audio media types + */ +enum class Format +{ + S8, + U8, + S16LE, + S16BE, + U16LE, + U16BE, + S24_32LE, + S24_32BE, + U24_32LE, + U24_32BE, + S32LE, + S32BE, + U32LE, + U32BE, + S24LE, + S24BE, + U24LE, + U24BE, + S20LE, + S20BE, + U20LE, + U20BE, + S18LE, + S18BE, + U18LE, + U18BE, + F32LE, + F32BE, + F64LE, + F64BE +}; + +/** + * @brief The layout of channels within a buffer. Used by the raw audio media types + */ +enum class Layout +{ + INTERLEAVED, + NON_INTERLEAVED +}; + +/** + * @brief Audio specific configuration + */ +struct AudioConfig +{ + uint32_t numberOfChannels = kInvalidAudioChannels; /**< The number of channels. */ + uint32_t sampleRate = kInvalidAudioSampleRate; /**< The sampling rate.*/ + std::vector codecSpecificConfig; /**< The audio specific config. Zero length if no specific config*/ + std::optional format; /**< The Format of the audio samples.*/ + std::optional layout; /**< The layout of channels within a buffer.*/ + std::optional channelMask; /**< Bitmask of channel positions present. */ + std::vector> streamHeader; /**< Stream header. Zero length if not present.*/ + std::optional + framed; /**< True if each buffer passed through the pipeline contains a complete, self-contained media unit*/ +}; + +/** + * @brief AddSegmentStatus + * + * The add segment status. This is the status adding new segment to Rialto + */ +enum class AddSegmentStatus +{ + OK, /**< Segment accepted. */ + NO_SPACE, /**< Too many frames sent or Rialto does not currently have space for this segment. */ + ERROR /**< Unexpected error. */ +}; + +/** + * @brief A pair describing the clear and encrypted bytes + * in a sub-sample. + */ +struct SubSamplePair +{ + size_t numClearBytes; /**< The number of clear bytes in the sample. */ + size_t numEncryptedBytes; /**< The number of encrypted bytes in the sample. */ +}; + +/** + * @brief Video decoder requirements used to allocate a suitable decoder for a MediaPipeline session + */ +struct VideoRequirements +{ + uint32_t maxWidth; /**< Maximum width of video frames to be decoded. */ + uint32_t maxHeight; /**< Maximum height of video frames to be decoded. */ +}; + +/** + * @brief Information about the shared memory required for writting data. + */ +struct MediaPlayerShmInfo +{ + uint32_t maxMetadataBytes; /**< The maximum amount of metadata that can be written. */ + uint32_t metadataOffset; /**< The offset to write the metadata. */ + uint32_t mediaDataOffset; /**< The offset to write the media data. */ + uint32_t maxMediaBytes; /**< The maximum amount of mediadata that can be written. */ +}; + +/** + * @brief The information provided in a QOS update. + */ +struct QosInfo +{ + uint64_t processed; /**< The total number of video frames/audio samples processed since MediaPipeline:load. */ + uint64_t dropped; /**< The total number of video frames/audio samples dropped since MediaPipeline:load. */ +}; + +/** + * @brief The error return status for session management methods. + */ +enum class MediaKeyErrorStatus +{ + OK, /**< No error. */ + FAIL, /**< An unspecified error occurred. */ + BAD_SESSION_ID, /**< The session id is not recognised. */ + NOT_SUPPORTED, /**< The request parameters are not supported. */ + INVALID_STATE, /**< The object is in an invalid state for the operation. */ + INTERFACE_NOT_IMPLEMENTED, /**< The interface is not implemented. */ + BUFFER_TOO_SMALL /**< The size of the buffer is too small. */ +}; + +/** + * @brief The media key session type. + */ +enum class KeySessionType +{ + UNKNOWN, /**< The session type is unknown. */ + TEMPORARY, /**< The session is a temporary session. */ + PERSISTENT_LICENCE, /**< The session is a persistent session. */ + PERSISTENT_RELEASE_MESSAGE /**< The session's persistent licence should be released. */ +}; + +/** + * @brief The init data type. + */ +enum class InitDataType +{ + UNKNOWN, /**< The init data type is unknown. */ + CENC, /**< The init data is in CENC format. */ + KEY_IDS, /**< The init data is key ids. */ + WEBM, /**< The init data is in WEBM format. */ + DRMHEADER /**< The init data is in DrmHeader format. */ +}; + +/** + * @brief The key status. + */ +enum class KeyStatus +{ + USABLE, + EXPIRED, + OUTPUT_RESTRICTED, + PENDING, + INTERNAL_ERROR, + RELEASED +}; + +/** + * @brief The alignment of media segment + */ +enum class SegmentAlignment +{ + UNDEFINED, + NAL, + AU +}; + +/** + * @brief The Stream Format of media segment + */ +enum class StreamFormat +{ + UNDEFINED, + RAW, + AVC, + BYTE_STREAM, + HVC1, + HEV1 +}; + +/** + * @brief A vector of key ID/key status pairs. + */ +typedef std::vector, KeyStatus>> KeyStatusVector; + +/** + * @brief Information about the shared memory required for writting data for the web audio playback. + */ +struct WebAudioShmInfo +{ + uint32_t offsetMain; /**< The offset to start writing the audio data. */ + uint32_t lengthMain; /**< The maximum number of bytes to write at offsetMain. */ + uint32_t offsetWrap; /**< The offset to continue writing the audio data if buffer wrapped. */ + uint32_t lengthWrap; /**< The maximum number of bytes to write at offsetWrap. */ +}; + +/** + * @brief Pcm config information. + */ +struct WebAudioPcmConfig +{ + uint32_t rate; /**< Rate of web audio (Hz) */ + uint32_t channels; /**< Number of channels */ + uint32_t sampleSize; /**< Size of each sample (bits) */ + bool isBigEndian; /**< Specifies if sample is stored as big-endian or little-endian format */ + bool isSigned; /**< Specifies if samples are signed or unsigned */ + bool isFloat; /**< Specifies if samples are float values or interger values*/ +}; + +/** + * @brief Type dependent configuration data. + */ +union WebAudioConfig +{ + /** + * @brief PCM audio configuration. + */ + WebAudioPcmConfig pcm; +}; + +/** + * @brief The Web Audio Player State. + */ +enum class WebAudioPlayerState +{ + UNKNOWN, /**< An unknown or undefined playback state. */ + IDLE, /**< The player is ready to play media. */ + PLAYING, /**< The player is playing media. */ + PAUSED, /**< The player is has paused media playback. */ + END_OF_STREAM, /**< The player has got to the end of playback. */ + FAILURE /**< The player failed to set playback state. */ +}; + +/** + * @brief Cipher mode for common encryption, see https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-3:v1:en + */ +enum class CipherMode +{ + UNKNOWN, + CENC, /* AES-CTR scheme */ + CBC1, /* AES-CBC scheme */ + CENS, /* AES-CTR subsample pattern encryption scheme */ + CBCS /* AES-CBC subsample pattern encryption scheme */ +}; + +/** + * @brief Fraction type. + */ +struct Fraction +{ + int32_t numerator; /**< The numerator */ + int32_t denominator; /**< The denominator */ +}; + +/** + * @brief Codec data type. + */ +enum class CodecDataType +{ + BUFFER, + STRING +}; + +/** + * @brief Codec data with type. + */ +struct CodecData +{ + std::vector data{}; /**< The codec data */ + CodecDataType type{CodecDataType::BUFFER}; /**< The codec data type */ +}; + +/** + * @brief None fatal asynchronous errors reported by the player. + */ +enum class PlaybackError +{ + UNKNOWN, + DECRYPTION, /* Player failed to decrypt a buffer and the frame has been dropped */ +}; + +/** + * @brief Ease type for audio volume changes. + */ +enum class EaseType +{ + EASE_LINEAR, + EASE_IN_CUBIC, + EASE_OUT_CUBIC +}; + +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_MEDIA_COMMON_H_ From ed0190846c805b8a694a70c32ae6e951b4e4612c Mon Sep 17 00:00:00 2001 From: Philip Stroffolino Date: Wed, 1 Oct 2025 12:05:55 -0400 Subject: [PATCH 05/21] Reason for Change: coverity fixes Signed-off-by: Philip Stroffolino --- test/gstTestHarness/rialto-api-test.cpp | 21 +-- test/gstTestHarness/rialto-gst-pipeline.cpp | 139 ++++++++++---------- 2 files changed, 85 insertions(+), 75 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 59b701cce..dc98ff6c0 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -26,17 +26,20 @@ void LoadAndDemuxSegment( Mp4Demux &mp4Demux, const char *path ) if( f ) { fseek( f,0,SEEK_END ); - size_t len = ftell(f); - unsigned char *ptr = (unsigned char *)malloc(len); - assert( ptr ); - if( ptr ) + long len = ftell(f); + if( len>0 ) { - fseek( f, 0, SEEK_SET ); - size_t n = fread( ptr, 1, len, f ); - assert( n == len ); - if( n==len ) + unsigned char *ptr = (unsigned char *)malloc(len); + assert( ptr ); + if( ptr ) { - mp4Demux.Parse( ptr, len ); + fseek( f, 0, SEEK_SET ); + size_t n = fread( ptr, 1, len, f ); + assert( n == len ); + if( n==len ) + { + mp4Demux.Parse( ptr, len ); + } } } fclose( f ); diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index 2328d3824..09e06c331 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -30,73 +30,82 @@ bool GstMediaPipeline::attachSource(const std::unique_ptr &source, if( sourceType == MediaSourceType::VIDEO || sourceType == MediaSourceType::AUDIO ) { const IMediaPipeline::MediaSourceAV *mediaSourceAV = dynamic_cast(source.get()); - const char *streamFormat = nullptr; - switch( mediaSourceAV->getStreamFormat() ) + if( mediaSourceAV ) { - case StreamFormat::HVC1: - streamFormat = "hvc1"; - break; - case StreamFormat::AVC: - streamFormat = "avc"; - break; - case StreamFormat::RAW: - streamFormat = "raw"; - break; - default: - break; - } - if( streamFormat ) - { - gst_caps_set_simple( caps, "stream-format", G_TYPE_STRING, streamFormat, nullptr ); - } - const std::shared_ptr codecData = mediaSourceAV->getCodecData(); - GstBuffer *buf = nullptr; - if( codecData ) - { - buf = gst_buffer_new_and_alloc(codecData->data.size()); - gst_buffer_fill(buf, 0, codecData->data.data(), codecData->data.size() ); - gst_caps_set_simple( caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr ); - } - - if( sourceType == MediaSourceType::VIDEO ) - { - sourceId = TRACK_VIDEO; - const IMediaPipeline::MediaSourceVideo *mediaSourceVideo = dynamic_cast(source.get()); - gst_caps_set_simple( caps, - "alignment", G_TYPE_STRING, "au", - "width", G_TYPE_INT, mediaSourceVideo->getWidth(), - "height", G_TYPE_INT, mediaSourceVideo->getHeight(), - "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, - nullptr); - } - else if( sourceType == MediaSourceType::AUDIO ) - { - sourceId = TRACK_AUDIO; - const IMediaPipeline::MediaSourceAudio *mediaSourceAudio = dynamic_cast(source.get()); - auto audioConfig = mediaSourceAudio->getAudioConfig();//.numberOfChannels ); - gst_caps_set_simple( caps, - "framed", G_TYPE_BOOLEAN, TRUE, - "rate", G_TYPE_INT, audioConfig.sampleRate, - "channels", G_TYPE_INT, audioConfig.numberOfChannels, - nullptr ); - } - else - { - assert(0); - } - - gchar *caps_string = gst_caps_to_string(caps); - g_print("Negotiated caps: %s\n", caps_string); - g_free(caps_string); - - gst_app_src_set_caps(GST_APP_SRC(track[sourceId].appsrc), caps); - gst_caps_unref(caps); - if( buf ) - { - gst_buffer_unref(buf); + const char *streamFormat = nullptr; + switch( mediaSourceAV->getStreamFormat() ) + { + case StreamFormat::HVC1: + streamFormat = "hvc1"; + break; + case StreamFormat::AVC: + streamFormat = "avc"; + break; + case StreamFormat::RAW: + streamFormat = "raw"; + break; + default: + break; + } + if( streamFormat ) + { + gst_caps_set_simple( caps, "stream-format", G_TYPE_STRING, streamFormat, nullptr ); + } + const std::shared_ptr codecData = mediaSourceAV->getCodecData(); + GstBuffer *buf = nullptr; + if( codecData ) + { + buf = gst_buffer_new_and_alloc(codecData->data.size()); + gst_buffer_fill(buf, 0, codecData->data.data(), codecData->data.size() ); + gst_caps_set_simple( caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr ); + } + + if( sourceType == MediaSourceType::VIDEO ) + { + sourceId = TRACK_VIDEO; + const IMediaPipeline::MediaSourceVideo *mediaSourceVideo = dynamic_cast(source.get()); + if( mediaSourceVideo ) + { + gst_caps_set_simple( caps, + "alignment", G_TYPE_STRING, "au", + "width", G_TYPE_INT, mediaSourceVideo->getWidth(), + "height", G_TYPE_INT, mediaSourceVideo->getHeight(), + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, + nullptr); + } + } + else if( sourceType == MediaSourceType::AUDIO ) + { + sourceId = TRACK_AUDIO; + const IMediaPipeline::MediaSourceAudio *mediaSourceAudio = dynamic_cast(source.get()); + if( mediaSourceAudio ) + { + const auto &audioConfig = mediaSourceAudio->getAudioConfig(); + gst_caps_set_simple( caps, + "framed", G_TYPE_BOOLEAN, TRUE, + "rate", G_TYPE_INT, audioConfig.sampleRate, + "channels", G_TYPE_INT, audioConfig.numberOfChannels, + nullptr ); + } + } + else + { + assert(0); + } + + gchar *caps_string = gst_caps_to_string(caps); + g_print("Negotiated caps: %s\n", caps_string); + g_free(caps_string); + + gst_app_src_set_caps(GST_APP_SRC(track[sourceId].appsrc), caps); + gst_caps_unref(caps); + if( buf ) + { + gst_buffer_unref(buf); + } } + printf( "attachSource() -> sourceId=%" PRId32 "\n", sourceId ); } - printf( "attachSource() -> sourceId=%" PRId32 "\n", sourceId ); return true; }; @@ -149,8 +158,6 @@ GstMediaPipeline::GstMediaPipeline() case TRACK_AUDIO: g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_audio_source_cb), this ); break; - default: - break; } } } From 7286105c1d0b43e217e751f1838903a8f181aade Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Thu, 16 Oct 2025 09:25:54 -0400 Subject: [PATCH 06/21] VPLAY-11066 Direct Rialto Wrapper/Simulator for OSX/Ubuntu AAMP integration/testing Reason for change: Do Not Merge - Device test Risks: Low Priority: P1 Signed-off-by: ryadav698 --- CMakeLists.txt | 19 +++---------------- test/gstTestHarness/rialto-api-test.cpp | 15 +++++++++------ 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31f9a858e..35636d500 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -459,23 +459,10 @@ set(GSTTESTHARNESS_DEPENDS ${CURL_LINK_LIBRARIES} ) set(GSTTESTHARNESS_SOURCES - test/gstTestHarness/gst-port.cpp - test/gstTestHarness/gst-port.h - test/gstTestHarness/gst-utils.cpp - test/gstTestHarness/gst-utils.h - test/gstTestHarness/gst-test.cpp - test/gstTestHarness/gst-test.h + test/gstTestHarness/rialto-api-test.cpp + test/gstTestHarness/rialto-gst-pipeline.cpp + test/gstTestHarness/rialto-gst-pipeline.h test/gstTestHarness/mp4demux.hpp - test/gstTestHarness/dash_adapter.cpp - test/gstTestHarness/dash_adapter.hpp - test/gstTestHarness/downloader.cpp - test/gstTestHarness/downloader.hpp - test/gstTestHarness/stream_utils.cpp - test/gstTestHarness/stream_utils.hpp - test/gstTestHarness/string_utils.cpp - test/gstTestHarness/string_utils.hpp - test/gstTestHarness/tsdemux.hpp - test/gstTestHarness/turbo_xml.hpp ) add_executable(gstTestHarness ${GSTTESTHARNESS_SOURCES}) target_link_libraries(gstTestHarness ${GSTTESTHARNESS_DEPENDS} "-lreadline") diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index dc98ff6c0..b7a2cb278 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -18,10 +18,13 @@ static int32_t sourceIdVideo; void LoadAndDemuxSegment( Mp4Demux &mp4Demux, const char *path ) { // using generated bipbop content for initial test - char fullpath[256]; - snprintf( fullpath, sizeof(fullpath), "%.*s/Documents/r" "d" "k" "e/aamp_test_internal/test/VideoTestStream/bipbop-gen/%s", - gUserPathLen, gUserPathPtr, path ); - FILE *f = fopen(fullpath,"rb"); + // char fullpath[256]; + // snprintf( fullpath, sizeof(fullpath), "%.*s/Documents/r" "d" "k" "e/aamp_test_internal/test/VideoTestStream/bipbop-gen/%s", + // gUserPathLen, gUserPathPtr, path ); + char fullpath[512]; + snprintf(fullpath, sizeof(fullpath), "/tmp/data/bipbop-gen/%s", path); + printf( "loading rialtotest %s\n", fullpath ); + FILE *f = fopen(fullpath, "rb"); assert( f ); if( f ) { @@ -184,9 +187,9 @@ int my_main(int argc, char **argv) const char *prefix = "/Users/"; size_t prefixLen = strlen(prefix); gUserPathPtr = strstr(executablePath,prefix); - assert( gUserPathPtr ); + // assert( gUserPathPtr ); const char *delim = strchr( &gUserPathPtr[prefixLen],'/' ); - assert( delim ); + // assert( delim ); gUserPathLen = (int)(delim - gUserPathPtr); gst_init(&argc, &argv); From 4af68b5f54eb521f411d21bde38007580662c5db Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Tue, 11 Nov 2025 11:34:56 -0500 Subject: [PATCH 07/21] TEST - DO NOT MERGE Signed-off-by: ryadav698 --- CMakeLists.txt | 18 +- .../rialto-gstreamer/source/BufferParser.cpp | 207 +++ .../rialto-gstreamer/source/BufferParser.h | 76 + .../rialto-gstreamer/source/CMakeLists.txt | 96 ++ .../rialto-gstreamer/source/Constants.h | 35 + .../rialto-gstreamer/source/ControlBackend.h | 97 ++ .../source/ControlBackendInterface.h | 32 + .../source/GStreamerEMEUtils.cpp | 211 +++ .../source/GStreamerEMEUtils.h | 46 + .../source/GStreamerMSEMediaPlayerClient.cpp | 1280 +++++++++++++++++ .../source/GStreamerMSEMediaPlayerClient.h | 355 +++++ .../source/GStreamerMSEUtils.cpp | 223 +++ .../source/GStreamerMSEUtils.h | 38 + .../source/GStreamerUtils.cpp | 88 ++ .../rialto-gstreamer/source/GStreamerUtils.h | 56 + .../source/GStreamerWebAudioPlayerClient.cpp | 481 +++++++ .../source/GStreamerWebAudioPlayerClient.h | 243 ++++ .../source/GstreamerCatLog.cpp | 22 + .../rialto-gstreamer/source/GstreamerCatLog.h | 31 + .../rialto-gstreamer/source/IMessageQueue.h | 52 + .../source/IPlaybackDelegate.h | 90 ++ .../source/IPullModePlaybackDelegate.h | 41 + middleware/rialto-gstreamer/source/ITimer.h | 88 ++ .../source/LogToGstHandler.cpp | 112 ++ .../rialto-gstreamer/source/LogToGstHandler.h | 35 + .../source/MediaPlayerClientBackend.h | 188 +++ .../MediaPlayerClientBackendInterface.h | 76 + .../source/MediaPlayerManager.cpp | 178 +++ .../source/MediaPlayerManager.h | 56 + .../rialto-gstreamer/source/MessageQueue.cpp | 187 +++ .../rialto-gstreamer/source/MessageQueue.h | 92 ++ .../source/PullModeAudioPlaybackDelegate.cpp | 715 +++++++++ .../source/PullModeAudioPlaybackDelegate.h | 66 + .../source/PullModePlaybackDelegate.cpp | 962 +++++++++++++ .../source/PullModePlaybackDelegate.h | 104 ++ .../PullModeSubtitlePlaybackDelegate.cpp | 305 ++++ .../source/PullModeSubtitlePlaybackDelegate.h | 50 + .../source/PullModeVideoPlaybackDelegate.cpp | 386 +++++ .../source/PullModeVideoPlaybackDelegate.h | 57 + .../source/PushModeAudioPlaybackDelegate.cpp | 365 +++++ .../source/PushModeAudioPlaybackDelegate.h | 59 + .../source/RialtoGSteamerPlugin.cpp | 83 ++ .../source/RialtoGStreamerMSEAudioSink.cpp | 374 +++++ .../source/RialtoGStreamerMSEAudioSink.h | 52 + .../source/RialtoGStreamerMSEBaseSink.cpp | 331 +++++ .../source/RialtoGStreamerMSEBaseSink.h | 73 + .../RialtoGStreamerMSEBaseSinkPrivate.h | 54 + .../source/RialtoGStreamerMSESubtitleSink.cpp | 191 +++ .../source/RialtoGStreamerMSESubtitleSink.h | 53 + .../source/RialtoGStreamerMSEVideoSink.cpp | 291 ++++ .../source/RialtoGStreamerMSEVideoSink.h | 52 + .../source/RialtoGStreamerWebAudioSink.cpp | 297 ++++ .../source/RialtoGStreamerWebAudioSink.h | 59 + middleware/rialto-gstreamer/source/Timer.cpp | 97 ++ middleware/rialto-gstreamer/source/Timer.h | 70 + .../source/WebAudioClientBackend.h | 73 + .../source/WebAudioClientBackendInterface.h | 43 + .../rialto-ocdm/include/ActiveSessions.h | 55 + middleware/rialto-ocdm/include/CdmBackend.h | 80 ++ middleware/rialto-ocdm/include/ICdmBackend.h | 59 + .../rialto-ocdm/include/IMessageDispatcher.h | 39 + middleware/rialto-ocdm/include/Logger.h | 87 ++ .../include/MediaKeysCapabilitiesBackend.h | 47 + .../rialto-ocdm/include/MessageDispatcher.h | 63 + .../rialto-ocdm/include/OpenCDMSession.h | 68 + .../include/OpenCDMSessionPrivate.h | 104 ++ .../rialto-ocdm/include/OpenCDMSystem.h | 52 + .../include/OpenCDMSystemPrivate.h | 66 + .../RialtoGStreamerEMEProtectionMetadata.h | 47 + .../rialto-ocdm/source/ActiveSessions.cpp | 68 + middleware/rialto-ocdm/source/CPPLINT.cfg | 21 + middleware/rialto-ocdm/source/CdmBackend.cpp | 286 ++++ middleware/rialto-ocdm/source/Logger.cpp | 227 +++ .../source/MediaKeysCapabilitiesBackend.cpp | 85 ++ .../rialto-ocdm/source/MessageDispatcher.cpp | 77 + .../source/OpenCDMSessionPrivate.cpp | 554 +++++++ .../source/OpenCDMSystemPrivate.cpp | 136 ++ .../rialto-ocdm/source/RialtoFactoryStubs.cpp | 72 + .../RialtoGStreamerEMEProtectionMetadata.cpp | 87 ++ middleware/rialto-ocdm/source/open_cdm.cpp | 453 ++++++ .../rialto-ocdm/source/open_cdm_adapter.cpp | 70 + .../rialto-ocdm/source/open_cdm_ext.cpp | 285 ++++ .../media/public/include/IMediaPipeline.h | 2 + test/gstTestHarness/rialto-api-test.cpp | 47 +- test/gstTestHarness/rialto-gst-pipeline.cpp | 228 ++- test/gstTestHarness/rialto-gst-pipeline.h | 33 +- 86 files changed, 13408 insertions(+), 182 deletions(-) create mode 100644 middleware/rialto-gstreamer/source/BufferParser.cpp create mode 100644 middleware/rialto-gstreamer/source/BufferParser.h create mode 100644 middleware/rialto-gstreamer/source/CMakeLists.txt create mode 100644 middleware/rialto-gstreamer/source/Constants.h create mode 100644 middleware/rialto-gstreamer/source/ControlBackend.h create mode 100644 middleware/rialto-gstreamer/source/ControlBackendInterface.h create mode 100644 middleware/rialto-gstreamer/source/GStreamerEMEUtils.cpp create mode 100644 middleware/rialto-gstreamer/source/GStreamerEMEUtils.h create mode 100644 middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.cpp create mode 100644 middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.h create mode 100644 middleware/rialto-gstreamer/source/GStreamerMSEUtils.cpp create mode 100644 middleware/rialto-gstreamer/source/GStreamerMSEUtils.h create mode 100644 middleware/rialto-gstreamer/source/GStreamerUtils.cpp create mode 100644 middleware/rialto-gstreamer/source/GStreamerUtils.h create mode 100644 middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.cpp create mode 100644 middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.h create mode 100644 middleware/rialto-gstreamer/source/GstreamerCatLog.cpp create mode 100644 middleware/rialto-gstreamer/source/GstreamerCatLog.h create mode 100644 middleware/rialto-gstreamer/source/IMessageQueue.h create mode 100644 middleware/rialto-gstreamer/source/IPlaybackDelegate.h create mode 100644 middleware/rialto-gstreamer/source/IPullModePlaybackDelegate.h create mode 100644 middleware/rialto-gstreamer/source/ITimer.h create mode 100644 middleware/rialto-gstreamer/source/LogToGstHandler.cpp create mode 100644 middleware/rialto-gstreamer/source/LogToGstHandler.h create mode 100644 middleware/rialto-gstreamer/source/MediaPlayerClientBackend.h create mode 100644 middleware/rialto-gstreamer/source/MediaPlayerClientBackendInterface.h create mode 100644 middleware/rialto-gstreamer/source/MediaPlayerManager.cpp create mode 100644 middleware/rialto-gstreamer/source/MediaPlayerManager.h create mode 100644 middleware/rialto-gstreamer/source/MessageQueue.cpp create mode 100644 middleware/rialto-gstreamer/source/MessageQueue.h create mode 100644 middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.cpp create mode 100644 middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.h create mode 100644 middleware/rialto-gstreamer/source/PullModePlaybackDelegate.cpp create mode 100644 middleware/rialto-gstreamer/source/PullModePlaybackDelegate.h create mode 100644 middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.cpp create mode 100644 middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.h create mode 100644 middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.cpp create mode 100644 middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.h create mode 100644 middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.cpp create mode 100644 middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.h create mode 100644 middleware/rialto-gstreamer/source/RialtoGSteamerPlugin.cpp create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.cpp create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.h create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.cpp create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.h create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSinkPrivate.h create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.cpp create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.h create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.cpp create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.h create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.cpp create mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.h create mode 100644 middleware/rialto-gstreamer/source/Timer.cpp create mode 100644 middleware/rialto-gstreamer/source/Timer.h create mode 100644 middleware/rialto-gstreamer/source/WebAudioClientBackend.h create mode 100644 middleware/rialto-gstreamer/source/WebAudioClientBackendInterface.h create mode 100644 middleware/rialto-ocdm/include/ActiveSessions.h create mode 100644 middleware/rialto-ocdm/include/CdmBackend.h create mode 100644 middleware/rialto-ocdm/include/ICdmBackend.h create mode 100644 middleware/rialto-ocdm/include/IMessageDispatcher.h create mode 100644 middleware/rialto-ocdm/include/Logger.h create mode 100644 middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h create mode 100644 middleware/rialto-ocdm/include/MessageDispatcher.h create mode 100644 middleware/rialto-ocdm/include/OpenCDMSession.h create mode 100644 middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h create mode 100644 middleware/rialto-ocdm/include/OpenCDMSystem.h create mode 100644 middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h create mode 100644 middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h create mode 100644 middleware/rialto-ocdm/source/ActiveSessions.cpp create mode 100644 middleware/rialto-ocdm/source/CPPLINT.cfg create mode 100644 middleware/rialto-ocdm/source/CdmBackend.cpp create mode 100644 middleware/rialto-ocdm/source/Logger.cpp create mode 100644 middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp create mode 100644 middleware/rialto-ocdm/source/MessageDispatcher.cpp create mode 100644 middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp create mode 100644 middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp create mode 100644 middleware/rialto-ocdm/source/RialtoFactoryStubs.cpp create mode 100644 middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp create mode 100644 middleware/rialto-ocdm/source/open_cdm.cpp create mode 100644 middleware/rialto-ocdm/source/open_cdm_adapter.cpp create mode 100644 middleware/rialto-ocdm/source/open_cdm_ext.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 35636d500..6e12ebd94 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,8 +96,8 @@ if(CMAKE_PLATFORM_UBUNTU OR CMAKE_SYSTEM_NAME STREQUAL Darwin) COMMAND bash -c "xcrun --show-sdk-path" OUTPUT_VARIABLE osxSdkPath OUTPUT_STRIP_TRAILING_WHITESPACE ) set(OS_CXX_FLAGS "${OS_CXX_FLAGS} -g -x objective-c++ -Wno-inconsistent-missing-override -F${osxSdkPath}/System/Library/Frameworks") - set(OS_LD_FLAGS "${OS_LD_FLAGS} -F${osxSdkPath}/System/Library/Frameworks -framework Cocoa -L${osxSdkPath}/../MacOSX.sdk/usr/lib -L.libs/lib -L/usr/local/lib/") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isysroot ${osxSdkPath}/../MacOSX.sdk -I/usr/local/include") + set(OS_LD_FLAGS "${OS_LD_FLAGS} -F${osxSdkPath}/System/Library/Frameworks -framework Cocoa -L${osxSdkPath}/../MacOSX26.1.sdk/usr/lib -L.libs/lib -L/usr/local/lib/") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isysroot ${osxSdkPath}/../MacOSX26.1.sdk -I/usr/local/include") string(STRIP ${OS_LD_FLAGS} OS_LD_FLAGS) pkg_check_modules(GSTREAMERVIDEO REQUIRED gstreamer-video-1.0) set(AAMP_CLI_LD_FLAGS ${AAMP_CLI_LD_FLAGS} ${GSTREAMERVIDEO_LINK_LIBRARIES}) @@ -130,6 +130,8 @@ if(CMAKE_PLATFORM_UBUNTU OR CMAKE_SYSTEM_NAME STREQUAL Darwin) endif() include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rialto-master/media/public/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-gstreamer/source) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-ocdm/include) include_directories(${GSTREAMER_INCLUDE_DIRS}) include_directories(${CURL_INCLUDE_DIRS}) @@ -464,6 +466,15 @@ set(GSTTESTHARNESS_SOURCES test/gstTestHarness/rialto-gst-pipeline.h test/gstTestHarness/mp4demux.hpp ) + +file(GLOB RIALTO_GST_CPP_FILES middleware/rialto-gstreamer/source/*.cpp) +file(GLOB RIALTO_OCDM_CPP_FILES middleware/rialto-ocdm/source/*.cpp) +file(GLOB RIALTO_GST_H_FILES middleware/rialto-gstreamer/source/*.h) +message("TEST START") +message(${RIALTO_GST_CPP_FILES}) +message(${RIALTO_GST_H_FILES}) +list(APPEND GSTTESTHARNESS_SOURCES ${RIALTO_GST_CPP_FILES} ${RIALTO_OCDM_CPP_FILES} ${RIALTO_GST_H_FILES}) + add_executable(gstTestHarness ${GSTTESTHARNESS_SOURCES}) target_link_libraries(gstTestHarness ${GSTTESTHARNESS_DEPENDS} "-lreadline") install(TARGETS gstTestHarness @@ -486,7 +497,10 @@ set(RIALTO_TEST_SOURCES test/gstTestHarness/rialto-gst-pipeline.h test/gstTestHarness/mp4demux.hpp ) +file(GLOB RIALTO_CPP_FILES middleware/rialto-gstreamer/source/*.cpp) +list(APPEND RIALTO_TEST_SOURCES ${RIALTO_CPP_FILES}) add_executable(rialtoTest ${RIALTO_TEST_SOURCES}) + target_link_libraries(rialtoTest ${RIALTO_TEST_DEPENDS} "-lreadline") install(TARGETS rialtoTest DESTINATION bin diff --git a/middleware/rialto-gstreamer/source/BufferParser.cpp b/middleware/rialto-gstreamer/source/BufferParser.cpp new file mode 100644 index 000000000..1a150a36b --- /dev/null +++ b/middleware/rialto-gstreamer/source/BufferParser.cpp @@ -0,0 +1,207 @@ +/* + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "BufferParser.h" +#include "GStreamerEMEUtils.h" +#include "GStreamerUtils.h" +#include "GstreamerCatLog.h" +#include +#include +#include +#include + +using namespace firebolt::rialto; +#define GST_CAT_DEFAULT rialtoGStreamerCat + +std::unique_ptr BufferParser::parseBuffer(const GstRefSample &sample, GstBuffer *buffer, + GstMapInfo map, int streamId) +{ + int64_t timeStamp = static_cast(GST_BUFFER_PTS(buffer)); + int64_t duration = static_cast(GST_BUFFER_DURATION(buffer)); + GstCaps *caps = sample.getCaps(); + GstStructure *structure = gst_caps_get_structure(caps, 0); + + std::unique_ptr mseData = + parseSpecificPartOfBuffer(buffer, streamId, structure, timeStamp, duration); + + mseData->setData(map.size, map.data); + + addCodecDataToSegment(mseData, structure); + addProtectionMetadataToSegment(mseData, buffer, map, structure); + addDisplayOffsetToSegment(mseData, GST_BUFFER_OFFSET(buffer)); + + return mseData; +} + +void BufferParser::addProtectionMetadataToSegment(std::unique_ptr &segment, + GstBuffer *buffer, const GstMapInfo &map, GstStructure *structure) +{ + EncryptionFormat encryptionFormat = EncryptionFormat::CLEAR; + BufferProtectionMetadata metadata; + ProcessProtectionMetadata(buffer, metadata); + + std::string mediaType = gst_structure_get_name(structure); + if (mediaType == "application/x-cenc") + { + encryptionFormat = EncryptionFormat::CENC; + } + else if (mediaType == "application/x-webm-enc") + { + encryptionFormat = EncryptionFormat::WEBM; + } + + // For WEBM encrypted sample without partitioning: add subsample which contains only encrypted data. + // More details: https://www.webmproject.org/docs/webm-encryption/#45-full-sample-encrypted-block-format + // For CENC see CENC specification, section 9.2 + if ((encryptionFormat == EncryptionFormat::WEBM) || (encryptionFormat == EncryptionFormat::CENC)) + { + if ((metadata.encrypted) && (metadata.subsamples.size() == 0)) + { + metadata.subsamples.push_back(std::make_pair((uint32_t)0, (uint32_t)map.size)); + } + } + + if (metadata.encrypted) + { + GST_DEBUG("encrypted: %d mksId: %d key len: %zu iv len: %zu SUBSAMPLES: %zu, initWithLast15: %u", + metadata.encrypted, metadata.mediaKeySessionId, metadata.kid.size(), metadata.iv.size(), + metadata.subsamples.size(), metadata.initWithLast15); + + segment->setEncrypted(true); + segment->setMediaKeySessionId(metadata.mediaKeySessionId); + segment->setKeyId(metadata.kid); + segment->setInitVector(metadata.iv); + segment->setInitWithLast15(metadata.initWithLast15); + segment->setCipherMode(metadata.cipherMode); + if (metadata.encryptionPatternSet) + { + segment->setEncryptionPattern(metadata.cryptBlocks, metadata.skipBlocks); + } + + size_t subSampleCount = metadata.subsamples.size(); + for (size_t subSampleIdx = 0; subSampleIdx < subSampleCount; ++subSampleIdx) + { + GST_DEBUG("SUBSAMPLE: %zu/%zu C: %d E: %d", subSampleIdx, subSampleCount, + metadata.subsamples[subSampleIdx].first, metadata.subsamples[subSampleIdx].second); + segment->addSubSample(metadata.subsamples[subSampleIdx].first, metadata.subsamples[subSampleIdx].second); + } + } +} + +void BufferParser::addCodecDataToSegment(std::unique_ptr &segment, + GstStructure *structure) +{ + const GValue *codec_data; + codec_data = gst_structure_get_value(structure, "codec_data"); + if (codec_data) + { + GstBuffer *buf = gst_value_get_buffer(codec_data); + if (buf) + { + GstMappedBuffer mappedBuf(buf, GST_MAP_READ); + if (mappedBuf) + { + auto codecData = std::make_shared(); + codecData->data = std::vector(mappedBuf.data(), mappedBuf.data() + mappedBuf.size()); + codecData->type = firebolt::rialto::CodecDataType::BUFFER; + segment->setCodecData(codecData); + } + else + { + GST_ERROR("Failed to read codec_data"); + } + return; + } + const gchar *str = g_value_get_string(codec_data); + if (str) + { + auto codecData = std::make_shared(); + codecData->data = std::vector(str, str + std::strlen(str)); + codecData->type = firebolt::rialto::CodecDataType::STRING; + segment->setCodecData(codecData); + } + } +} + +void BufferParser::addDisplayOffsetToSegment(std::unique_ptr &segment, + guint64 displayOffset) +{ + if (GST_BUFFER_OFFSET_NONE != displayOffset) + { + segment->setDisplayOffset(displayOffset); + } +} + +std::unique_ptr +AudioBufferParser::parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, + int64_t timeStamp, int64_t duration) +{ + gint sampleRate = 0; + gint numberOfChannels = 0; + guint64 clippingStart = 0; + guint64 clippingEnd = 0; + gst_structure_get_int(structure, "rate", &sampleRate); + gst_structure_get_int(structure, "channels", &numberOfChannels); + + const GstAudioClippingMeta *clippingMeta = gst_buffer_get_audio_clipping_meta(buffer); + if (clippingMeta) + { + clippingStart = clippingMeta->start; + clippingEnd = clippingMeta->end; + } + + GST_LOG("New audio frame; buffer %p, pts=%" PRId64 " duration=%" PRId64 + " sampleRate=%d numberOfChannels=%d, clippingStart=%" PRIu64 ", clippingEnd=%" PRIu64, + buffer, timeStamp, duration, sampleRate, numberOfChannels, clippingStart, clippingEnd); + + std::unique_ptr mseData = + std::make_unique(streamId, timeStamp, duration, sampleRate, numberOfChannels, + clippingStart, clippingEnd); + + return mseData; +} + +std::unique_ptr +VideoBufferParser::parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, + int64_t timeStamp, int64_t duration) +{ + gint width = 0; + gint height = 0; + firebolt::rialto::Fraction frameRate{firebolt::rialto::kUndefinedSize, firebolt::rialto::kUndefinedSize}; + gst_structure_get_int(structure, "width", &width); + gst_structure_get_int(structure, "height", &height); + gst_structure_get_fraction(structure, "framerate", &frameRate.numerator, &frameRate.denominator); + + GST_LOG("New video frame; buffer %p, pts=%" PRId64 " duration=%" PRId64 " width=%d height=%d framerate=%d/%d", + buffer, timeStamp, duration, width, height, frameRate.numerator, frameRate.denominator); + + std::unique_ptr mseData = + std::make_unique(streamId, timeStamp, duration, width, height, frameRate); + + return mseData; +} + +std::unique_ptr +SubtitleBufferParser::parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, + int64_t timeStamp, int64_t duration) +{ + std::unique_ptr mseData = + std::make_unique(streamId, MediaSourceType::SUBTITLE, timeStamp, duration); + + return mseData; +} diff --git a/middleware/rialto-gstreamer/source/BufferParser.h b/middleware/rialto-gstreamer/source/BufferParser.h new file mode 100644 index 000000000..cd5e9b244 --- /dev/null +++ b/middleware/rialto-gstreamer/source/BufferParser.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BUFFERPARSER_H +#define BUFFERPARSER_H + +#include "GStreamerUtils.h" +#include +#include + +class BufferParser +{ + enum class EncryptionFormat + { + CLEAR, + CENC, + WEBM + }; + +public: + std::unique_ptr + parseBuffer(const GstRefSample &sample, GstBuffer *buffer, GstMapInfo map, int streamId); + +private: + virtual std::unique_ptr + parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, int64_t timeStamp, + int64_t duration) = 0; + + void addProtectionMetadataToSegment(std::unique_ptr &segment, + GstBuffer *buffer, const GstMapInfo &map, GstStructure *structure); + void addCodecDataToSegment(std::unique_ptr &segment, + GstStructure *structure); + void addDisplayOffsetToSegment(std::unique_ptr &segment, + guint64 displayOffset); +}; + +class AudioBufferParser : public BufferParser +{ +private: + std::unique_ptr + parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, int64_t timeStamp, + int64_t duration) override; +}; + +class VideoBufferParser : public BufferParser +{ +private: + std::unique_ptr + parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, int64_t timeStamp, + int64_t duration) override; +}; + +class SubtitleBufferParser : public BufferParser +{ +private: + std::unique_ptr + parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, int64_t timeStamp, + int64_t duration) override; +}; + +#endif // BUFFERPARSER_H diff --git a/middleware/rialto-gstreamer/source/CMakeLists.txt b/middleware/rialto-gstreamer/source/CMakeLists.txt new file mode 100644 index 000000000..241350de7 --- /dev/null +++ b/middleware/rialto-gstreamer/source/CMakeLists.txt @@ -0,0 +1,96 @@ +# Copyright (C) 2023 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; +# version 2.1 of the License. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# RIALTO-197: deprecated-declarations error in the latest stable2 for gstreamer. +# Should be removed once the issue is fixed. +add_compile_options( + "-Wno-deprecated-declarations" +) + +find_package(Rialto 1.0 REQUIRED) +find_package(ocdmRialto 1.0 REQUIRED) + +add_library(gstrialtosinks + + SHARED + GstreamerCatLog.cpp + RialtoGStreamerMSEVideoSink.cpp + RialtoGStreamerMSEAudioSink.cpp + RialtoGStreamerWebAudioSink.cpp + RialtoGStreamerMSESubtitleSink.cpp + GStreamerUtils.cpp + GStreamerEMEUtils.cpp + GStreamerMSEUtils.cpp + GStreamerMSEMediaPlayerClient.cpp + GStreamerWebAudioPlayerClient.cpp + MessageQueue.cpp + PullModeAudioPlaybackDelegate.cpp + PullModePlaybackDelegate.cpp + PullModeSubtitlePlaybackDelegate.cpp + PullModeVideoPlaybackDelegate.cpp + PushModeAudioPlaybackDelegate.cpp + RialtoGSteamerPlugin.cpp + RialtoGStreamerMSEBaseSink.cpp + MediaPlayerManager.cpp + Timer.cpp + BufferParser.cpp + LogToGstHandler.cpp + ) + +target_include_directories(gstrialtosinks + PUBLIC + $ + + PRIVATE + ${RIALTO_INCLUDE_DIR} + ${RIALTOOCDM_INCLUDE_DIR} + ${GSTREAMER_APP_INCLUDE_DIRS} + ) + +target_link_libraries(gstrialtosinks + PUBLIC + ${GSTREAMER_APP_LIBRARIES} + + PRIVATE + Rialto::ocdmRialto + Rialto::RialtoClient + Threads::Threads + ) + +#needed by GST_PLUGIN_DEFINE +target_compile_options(gstrialtosinks + PRIVATE + -DPACKAGE="gstrialtosinks" + -DVERSION="1.0" + ) + +set_target_properties(gstrialtosinks + PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" + ) + +find_package(EthanLog) +if (RIALTO_ENABLE_ETHAN_LOG AND EthanLog_FOUND) + message(STATUS "EthanLog is enabled") + target_compile_definitions(gstrialtosinks PRIVATE USE_ETHANLOG) + target_link_libraries(gstrialtosinks PRIVATE EthanLog::EthanLog) +else () + message(STATUS "EthanLog is disabled") +endif () + +install( + TARGETS gstrialtosinks + DESTINATION lib/gstreamer-1.0 + ) diff --git a/middleware/rialto-gstreamer/source/Constants.h b/middleware/rialto-gstreamer/source/Constants.h new file mode 100644 index 000000000..8edf84a5a --- /dev/null +++ b/middleware/rialto-gstreamer/source/Constants.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once +#include + +#include + +constexpr double kDefaultVolume{1.0}; +constexpr uint32_t kDefaultVolumeDuration{0}; +constexpr firebolt::rialto::EaseType kDefaultEaseType{firebolt::rialto::EaseType::EASE_LINEAR}; +constexpr bool kDefaultMute{false}; +constexpr bool kDefaultLowLatency{false}; +constexpr bool kDefaultSync{false}; +constexpr bool kDefaultSyncOff{false}; +constexpr int32_t kDefaultStreamSyncMode{0}; +constexpr uint32_t kDefaultFadeVolume{0}; +constexpr const char *kDefaultAudioFade = "100,0,L"; +constexpr uint32_t kDefaultBufferingLimit{750}; +constexpr bool kDefaultUseBuffering{false}; diff --git a/middleware/rialto-gstreamer/source/ControlBackend.h b/middleware/rialto-gstreamer/source/ControlBackend.h new file mode 100644 index 000000000..abd6b9733 --- /dev/null +++ b/middleware/rialto-gstreamer/source/ControlBackend.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include +#include +#include + +#include "ControlBackendInterface.h" +#include "IControl.h" + +namespace firebolt::rialto::client +{ +class ControlBackend final : public ControlBackendInterface +{ + class ControlClient : public IControlClient + { + public: + explicit ControlClient(ControlBackend &backend) : mBackend{backend} {} + ~ControlClient() override = default; + void notifyApplicationState(ApplicationState state) override + { + GST_INFO("ApplicationStateChanged received by rialto sink"); + mBackend.onApplicationStateChanged(state); + } + + private: + ControlBackend &mBackend; + }; + +public: + ControlBackend() + : m_rialtoClientState{ApplicationState::UNKNOWN}, m_controlClient{std::make_shared(*this)}, + m_control{IControlFactory::createFactory()->createControl()} + { + if (!m_control) + { + GST_ERROR("Unable to create control"); + return; + } + if (!m_control->registerClient(m_controlClient, m_rialtoClientState)) + { + GST_ERROR("Unable to register client"); + return; + } + } + + ~ControlBackend() final { m_control.reset(); } + + void removeControlBackend() override { m_control.reset(); } + + bool waitForRunning() override + { + std::unique_lock lock{m_mutex}; + if (ApplicationState::RUNNING == m_rialtoClientState) + { + return true; + } + m_stateCv.wait_for(lock, std::chrono::seconds{1}, + [&]() { return m_rialtoClientState == ApplicationState::RUNNING; }); + return ApplicationState::RUNNING == m_rialtoClientState; + } + +private: + void onApplicationStateChanged(ApplicationState state) + { + GST_INFO("Rialto Client application state changed to: %s", + state == ApplicationState::RUNNING ? "Active" : "Inactive/Unknown"); + std::unique_lock lock{m_mutex}; + m_rialtoClientState = state; + m_stateCv.notify_one(); + } + +private: + ApplicationState m_rialtoClientState; + std::shared_ptr m_controlClient; + std::shared_ptr m_control; + std::mutex m_mutex; + std::condition_variable m_stateCv; +}; +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/ControlBackendInterface.h b/middleware/rialto-gstreamer/source/ControlBackendInterface.h new file mode 100644 index 000000000..1d74933ae --- /dev/null +++ b/middleware/rialto-gstreamer/source/ControlBackendInterface.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "ControlCommon.h" + +namespace firebolt::rialto::client +{ +class ControlBackendInterface +{ +public: + virtual ~ControlBackendInterface() = default; + virtual void removeControlBackend() = 0; + virtual bool waitForRunning() = 0; +}; +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/GStreamerEMEUtils.cpp b/middleware/rialto-gstreamer/source/GStreamerEMEUtils.cpp new file mode 100644 index 000000000..e05d44e5d --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerEMEUtils.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include + +#include "GStreamerEMEUtils.h" +#include "GStreamerUtils.h" +#include "GstreamerCatLog.h" +#include "RialtoGStreamerEMEProtectionMetadata.h" + +#define GST_CAT_DEFAULT rialtoGStreamerCat +void getEncryptedFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata) +{ + gboolean encrypted = FALSE; + gst_structure_get_boolean(protectionMeta->info, "encrypted", &encrypted); + metadata.encrypted = encrypted; +} + +void getMediaKeySessionIdFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, + BufferProtectionMetadata &metadata) +{ + gint mediaKeySessionId = 0; + gst_structure_get_int(protectionMeta->info, "mks_id", &mediaKeySessionId); + metadata.mediaKeySessionId = mediaKeySessionId; +} + +void getKIDFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata) +{ + const GValue *value = gst_structure_get_value(protectionMeta->info, "kid"); + if (value) + { + GstBuffer *keyIDBuffer = gst_value_get_buffer(value); + if (keyIDBuffer) + { + GstMappedBuffer mappedKeyID(keyIDBuffer, GST_MAP_READ); + if (mappedKeyID) + { + metadata.kid = std::vector(mappedKeyID.data(), mappedKeyID.data() + mappedKeyID.size()); + } + } + } +} + +void getIVFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata) +{ + unsigned ivSize = 0; + gst_structure_get_uint(protectionMeta->info, "iv_size", &ivSize); + if (!ivSize && !g_strcmp0(gst_structure_get_string(protectionMeta->info, "cipher-mode"), "cbcs")) + { + // in case of cbcs, the same initialization vector is used to decrypt all the blocks + gst_structure_get_uint(protectionMeta->info, "constant_iv_size", &ivSize); + } + const GValue *value = gst_structure_get_value(protectionMeta->info, "iv"); + if (value) + { + GstBuffer *ivBuffer = gst_value_get_buffer(value); + if (ivBuffer) + { + GstMappedBuffer mappedIV(ivBuffer, GST_MAP_READ); + if (mappedIV && (ivSize == mappedIV.size())) + { + metadata.iv = std::vector(mappedIV.data(), mappedIV.data() + mappedIV.size()); + } + } + } +} + +void getSubSamplesFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata) +{ + unsigned int subSampleCount = 0; + gst_structure_get_uint(protectionMeta->info, "subsample_count", &subSampleCount); + + if (subSampleCount) + { + const GValue *value = gst_structure_get_value(protectionMeta->info, "subsamples"); + if (value) + { + GstBuffer *subSamplesBuffer = gst_value_get_buffer(value); + if (subSamplesBuffer) + { + GstMappedBuffer mappedSubSamples(subSamplesBuffer, GST_MAP_READ); + if (mappedSubSamples && + ((mappedSubSamples.size() / (sizeof(int16_t) + sizeof(int32_t))) == subSampleCount)) + { + std::vector subSamples(mappedSubSamples.data(), + mappedSubSamples.data() + mappedSubSamples.size()); + //'senc' atom + // unsigned int(16) subsample_count; + //{ + // unsigned int(16) BytesOfClearData; + // unsigned int(32) BytesOfEncryptedData; + //}[subsample_count] + size_t subSampleOffset = 0; + for (unsigned int subSampleIdx = 0; subSampleIdx < subSampleCount; ++subSampleIdx) + { + uint16_t bytesOfClearData = (uint16_t)subSamples[subSampleOffset] << 8 | + (uint16_t)subSamples[subSampleOffset + 1]; + uint32_t bytesOfEncryptedData = (uint32_t)subSamples[subSampleOffset + 2] << 24 | + (uint32_t)subSamples[subSampleOffset + 3] << 16 | + (uint32_t)subSamples[subSampleOffset + 4] << 8 | + (uint32_t)subSamples[subSampleOffset + 5]; + metadata.subsamples.push_back( + std::make_pair((uint32_t)bytesOfClearData, (uint32_t)bytesOfEncryptedData)); + subSampleOffset += sizeof(int16_t) + sizeof(int32_t); + } + } + } + } + } +} + +void getInitWithLast15FromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, + BufferProtectionMetadata &metadata) +{ + guint initWithLast15 = 0; + gst_structure_get_uint(protectionMeta->info, "init_with_last_15", &initWithLast15); + metadata.initWithLast15 = initWithLast15; +} + +void getEncryptionSchemeFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, + BufferProtectionMetadata &metadata) +{ + const char *cipherModeBuf = gst_structure_get_string(protectionMeta->info, "cipher-mode"); + GST_INFO("Retrieved encryption scheme '%s' from protection metadata.", cipherModeBuf ? cipherModeBuf : "unknown"); + if (g_strcmp0(cipherModeBuf, "cbcs") == 0) + { + metadata.cipherMode = firebolt::rialto::CipherMode::CBCS; + } + else if (g_strcmp0(cipherModeBuf, "cenc") == 0) + { + metadata.cipherMode = firebolt::rialto::CipherMode::CENC; + } + else if (g_strcmp0(cipherModeBuf, "cbc1") == 0) + { + metadata.cipherMode = firebolt::rialto::CipherMode::CBC1; + } + else if (g_strcmp0(cipherModeBuf, "cens") == 0) + { + metadata.cipherMode = firebolt::rialto::CipherMode::CENS; + } + else + { + if (cipherModeBuf) + { + GST_ERROR("Unknown encryption scheme '%s'!", cipherModeBuf); + } + else + { + GST_ERROR("Missing encryption scheme!"); + } + metadata.cipherMode = firebolt::rialto::CipherMode::UNKNOWN; + } +} + +void getEncryptionPatternFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, + BufferProtectionMetadata &metadata) +{ + if (gst_structure_get_uint(protectionMeta->info, "crypt_byte_block", &metadata.cryptBlocks) == false) + { + GST_INFO("Failed to get crypt_byte_block value!"); + return; + } + if (gst_structure_get_uint(protectionMeta->info, "skip_byte_block", &metadata.skipBlocks) == false) + { + GST_INFO("Failed to get skip_byte_block value!"); + return; + } + + GST_INFO("Successful retrieval of 'crypt_byte_block' and 'skip_byte_block'."); + metadata.encryptionPatternSet = true; +} + +void ProcessProtectionMetadata(GstBuffer *buffer, BufferProtectionMetadata &metadata) +{ + if (buffer == nullptr) + return; + + GstRialtoProtectionMetadata *protectionMeta = reinterpret_cast( + gst_buffer_get_meta(buffer, GST_RIALTO_PROTECTION_METADATA_GET_TYPE)); + if (protectionMeta) + { + getEncryptedFromProtectionMetadata(protectionMeta, metadata); + if (metadata.encrypted) + { + getMediaKeySessionIdFromProtectionMetadata(protectionMeta, metadata); + getKIDFromProtectionMetadata(protectionMeta, metadata); + getIVFromProtectionMetadata(protectionMeta, metadata); + getSubSamplesFromProtectionMetadata(protectionMeta, metadata); + getInitWithLast15FromProtectionMetadata(protectionMeta, metadata); + getEncryptionSchemeFromProtectionMetadata(protectionMeta, metadata); + getEncryptionPatternFromProtectionMetadata(protectionMeta, metadata); + } + } +} diff --git a/middleware/rialto-gstreamer/source/GStreamerEMEUtils.h b/middleware/rialto-gstreamer/source/GStreamerEMEUtils.h new file mode 100644 index 000000000..5a5a2b5aa --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerEMEUtils.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once +#include +#include +#include + +#include +#include + +struct BufferProtectionMetadata +{ + BufferProtectionMetadata() : encrypted(false) {} + + bool encrypted{false}; + int mediaKeySessionId{-1}; + std::vector iv; + std::vector kid; + // vector of bytesOfClearData, bytesOfEncryptedData + std::vector> subsamples; + uint32_t initWithLast15{0}; + + // Encryption scheme + firebolt::rialto::CipherMode cipherMode{firebolt::rialto::CipherMode::UNKNOWN}; + uint32_t cryptBlocks{0}; + uint32_t skipBlocks{0}; + bool encryptionPatternSet{false}; +}; + +void ProcessProtectionMetadata(GstBuffer *buffer, BufferProtectionMetadata &metadata); diff --git a/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.cpp b/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.cpp new file mode 100644 index 000000000..f330f102d --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.cpp @@ -0,0 +1,1280 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "GStreamerMSEMediaPlayerClient.h" +#include "Constants.h" +#include "GstreamerCatLog.h" +#include "RialtoGStreamerMSEBaseSink.h" +#include "RialtoGStreamerMSEBaseSinkPrivate.h" +#include "RialtoGStreamerMSEVideoSink.h" + +#include +#include +#include + +namespace +{ +// The start time of segment might differ from the first sample which is injected. +// That difference should not be bigger than 1 video / audio frame. +// 1 second is probably erring on the side of caution, but should not have side effect. +const int64_t segmentStartMaximumDiff = 1000000000; +const int32_t UNKNOWN_STREAMS_NUMBER = -1; + +const char *toString(const firebolt::rialto::PlaybackError &error) +{ + switch (error) + { + case firebolt::rialto::PlaybackError::DECRYPTION: + return "DECRYPTION"; + case firebolt::rialto::PlaybackError::UNKNOWN: + return "UNKNOWN"; + } + return "UNKNOWN"; +} +const char *toString(const firebolt::rialto::MediaSourceType &src) +{ + switch (src) + { + case firebolt::rialto::MediaSourceType::AUDIO: + return "AUDIO"; + case firebolt::rialto::MediaSourceType::VIDEO: + return "VIDEO"; + case firebolt::rialto::MediaSourceType::SUBTITLE: + return "SUBTITLE"; + case firebolt::rialto::MediaSourceType::UNKNOWN: + return "UNKNOWN"; + } + return "UNKNOWN"; +} +} // namespace +#define GST_CAT_DEFAULT rialtoGStreamerCat +GStreamerMSEMediaPlayerClient::GStreamerMSEMediaPlayerClient( + const std::shared_ptr &messageQueueFactory, + const std::shared_ptr &MediaPlayerClientBackend, + const uint32_t maxVideoWidth, const uint32_t maxVideoHeight) + : m_backendQueue{messageQueueFactory->createMessageQueue()}, m_messageQueueFactory{messageQueueFactory}, + m_clientBackend(MediaPlayerClientBackend), m_duration(0), m_audioStreams{UNKNOWN_STREAMS_NUMBER}, + m_videoStreams{UNKNOWN_STREAMS_NUMBER}, m_subtitleStreams{UNKNOWN_STREAMS_NUMBER}, + m_videoRectangle{0, 0, 1920, 1080}, m_streamingStopped(false), + m_maxWidth(maxVideoWidth == 0 ? DEFAULT_MAX_VIDEO_WIDTH : maxVideoWidth), + m_maxHeight(maxVideoHeight == 0 ? DEFAULT_MAX_VIDEO_HEIGHT : maxVideoHeight) +{ + m_backendQueue->start(); +} + +GStreamerMSEMediaPlayerClient::~GStreamerMSEMediaPlayerClient() +{ + stopStreaming(); +} + +void GStreamerMSEMediaPlayerClient::stopStreaming() +{ + if (!m_streamingStopped) + { + m_backendQueue->stop(); + + for (auto &source : m_attachedSources) + { + source.second.m_bufferPuller->stop(); + } + + m_streamingStopped = true; + } +} + +// Deletes client backend -> this deletes mediapipeline object +void GStreamerMSEMediaPlayerClient::destroyClientBackend() +{ + m_clientBackend.reset(); +} + +void GStreamerMSEMediaPlayerClient::notifyDuration(int64_t duration) +{ + m_backendQueue->postMessage(std::make_shared(duration, m_duration)); +} + +void GStreamerMSEMediaPlayerClient::notifyPosition(int64_t position) +{ + m_backendQueue->postMessage(std::make_shared(position, m_attachedSources)); +} + +void GStreamerMSEMediaPlayerClient::notifyNativeSize(uint32_t width, uint32_t height, double aspect) {} + +void GStreamerMSEMediaPlayerClient::notifyNetworkState(firebolt::rialto::NetworkState state) {} + +void GStreamerMSEMediaPlayerClient::notifyPlaybackState(firebolt::rialto::PlaybackState state) +{ + m_backendQueue->postMessage(std::make_shared(state, this)); +} + +void GStreamerMSEMediaPlayerClient::notifyVideoData(bool hasData) {} + +void GStreamerMSEMediaPlayerClient::notifyAudioData(bool hasData) {} + +void GStreamerMSEMediaPlayerClient::notifyNeedMediaData( + int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, + const std::shared_ptr & /*shmInfo*/) +{ + m_backendQueue->postMessage(std::make_shared(sourceId, frameCount, needDataRequestId, this)); + + return; +} + +void GStreamerMSEMediaPlayerClient::notifyCancelNeedMediaData(int sourceId) {} + +void GStreamerMSEMediaPlayerClient::notifyQos(int32_t sourceId, const firebolt::rialto::QosInfo &qosInfo) +{ + m_backendQueue->postMessage(std::make_shared(sourceId, qosInfo, this)); +} + +void GStreamerMSEMediaPlayerClient::notifyBufferUnderflow(int32_t sourceId) +{ + m_backendQueue->postMessage(std::make_shared(sourceId, this)); +} + +void GStreamerMSEMediaPlayerClient::notifyPlaybackError(int32_t sourceId, firebolt::rialto::PlaybackError error) +{ + m_backendQueue->postMessage(std::make_shared(sourceId, error, this)); +} + +void GStreamerMSEMediaPlayerClient::notifySourceFlushed(int32_t sourceId) +{ + m_backendQueue->postMessage(std::make_shared(sourceId, this)); +} + +void GStreamerMSEMediaPlayerClient::getPositionDo(int64_t *position, int32_t sourceId) +{ + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + *position = -1; + return; + } + + if (m_clientBackend && m_clientBackend->getPosition(*position)) + { + sourceIt->second.m_position = *position; + } + else + { + *position = sourceIt->second.m_position; + } +} + +int64_t GStreamerMSEMediaPlayerClient::getPosition(int32_t sourceId) +{ + int64_t position; + m_backendQueue->callInEventLoop([&]() { getPositionDo(&position, sourceId); }); + return position; +} + +bool GStreamerMSEMediaPlayerClient::setImmediateOutput(int32_t sourceId, bool immediateOutput) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setImmediateOutput(sourceId, immediateOutput); }); + return status; +} + +bool GStreamerMSEMediaPlayerClient::getImmediateOutput(int32_t sourceId, bool &immediateOutput) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getImmediateOutput(sourceId, immediateOutput); }); + return status; +} + +bool GStreamerMSEMediaPlayerClient::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() + { status = m_clientBackend->getStats(sourceId, renderedFrames, droppedFrames); }); + return status; +} + +bool GStreamerMSEMediaPlayerClient::createBackend() +{ + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + if (!m_clientBackend) + { + GST_ERROR("Client backend is NULL"); + result = false; + return; + } + m_clientBackend->createMediaPlayerBackend(shared_from_this(), m_maxWidth, m_maxHeight); + + if (m_clientBackend->isMediaPlayerBackendCreated()) + { + std::string utf8url = "mse://1"; + firebolt::rialto::MediaType mediaType = firebolt::rialto::MediaType::MSE; + if (!m_clientBackend->load(mediaType, "", utf8url)) + { + GST_ERROR("Could not load RialtoClient"); + return; + } + result = true; + } + else + { + GST_ERROR("Media player backend could not be created"); + } + }); + + return result; +} + +StateChangeResult GStreamerMSEMediaPlayerClient::play(int32_t sourceId) +{ + StateChangeResult result = StateChangeResult::NOT_ATTACHED; + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + GST_ERROR("Cannot play - there's no attached source with id %d", sourceId); + result = StateChangeResult::NOT_ATTACHED; + return; + } + + if (m_serverPlaybackState == firebolt::rialto::PlaybackState::PLAYING) + { + GST_INFO("Server is already playing"); + sourceIt->second.m_state = ClientState::PLAYING; + + if (checkIfAllAttachedSourcesInStates({ClientState::PLAYING})) + { + m_clientState = ClientState::PLAYING; + } + + result = StateChangeResult::SUCCESS_SYNC; + return; + } + + sourceIt->second.m_state = ClientState::AWAITING_PLAYING; + + if (m_clientState == ClientState::PAUSED) + { + // If one source is AWAITING_PLAYING, the other source can still be PLAYING. + // This happends when we are switching out audio. + if (checkIfAllAttachedSourcesInStates({ClientState::AWAITING_PLAYING, ClientState::PLAYING})) + { + GST_INFO("Sending play command"); + m_clientBackend->play(); + m_clientState = ClientState::AWAITING_PLAYING; + } + else + { + GST_DEBUG("Not all sources are ready to play"); + } + } + else + { + GST_WARNING("Not in PAUSED state in %u state", static_cast(m_clientState)); + } + + result = StateChangeResult::SUCCESS_ASYNC; + sourceIt->second.m_delegate->postAsyncStart(); + }); + + return result; +} + +StateChangeResult GStreamerMSEMediaPlayerClient::pause(int32_t sourceId) +{ + StateChangeResult result = StateChangeResult::NOT_ATTACHED; + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + GST_WARNING("Cannot pause - there's no attached source with id %d", sourceId); + + result = StateChangeResult::NOT_ATTACHED; + return; + } + + if (m_serverPlaybackState == firebolt::rialto::PlaybackState::PAUSED && + m_clientState != ClientState::AWAITING_PLAYING && m_clientState != ClientState::AWAITING_PAUSED) + { + // if the server is already paused and we are not in async, we don't need to send pause command + GST_INFO("Server is already paused"); + sourceIt->second.m_state = ClientState::PAUSED; + + if (checkIfAllAttachedSourcesInStates({ClientState::PAUSED})) + { + m_clientState = ClientState::PAUSED; + } + + result = StateChangeResult::SUCCESS_SYNC; + } + else + { + sourceIt->second.m_state = ClientState::AWAITING_PAUSED; + + bool shouldPause = false; + if (m_clientState == ClientState::READY) + { + if (checkIfAllAttachedSourcesInStates({ClientState::AWAITING_PAUSED})) + { + shouldPause = true; + } + else + { + GST_DEBUG("Not all attached sources are ready to pause"); + } + } + else if (m_clientState == ClientState::AWAITING_PLAYING || m_clientState == ClientState::PLAYING) + { + shouldPause = true; + } + else + { + GST_DEBUG("Cannot pause in %u state", static_cast(m_clientState)); + } + + if (shouldPause) + { + GST_INFO("Sending pause command in %u state", static_cast(m_clientState)); + m_clientBackend->pause(); + m_clientState = ClientState::AWAITING_PAUSED; + } + + result = StateChangeResult::SUCCESS_ASYNC; + sourceIt->second.m_delegate->postAsyncStart(); + } + }); + + return result; +} + +void GStreamerMSEMediaPlayerClient::stop() +{ + m_backendQueue->callInEventLoop([&]() { m_clientBackend->stop(); }); +} + +void GStreamerMSEMediaPlayerClient::setPlaybackRate(double rate) +{ + m_backendQueue->callInEventLoop([&]() { m_clientBackend->setPlaybackRate(rate); }); +} + +void GStreamerMSEMediaPlayerClient::flush(int32_t sourceId, bool resetTime) +{ + m_backendQueue->callInEventLoop( + [&]() + { + bool async{true}; + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + GST_ERROR("Cannot flush - there's no attached source with id %d", sourceId); + return; + } + if (!m_clientBackend->flush(sourceId, resetTime, async)) + { + GST_ERROR("Flush operation failed for source with id %d", sourceId); + return; + } + sourceIt->second.m_isFlushing = true; + sourceIt->second.m_bufferPuller->stop(); + + if (async) + { + GST_INFO("Flush request sent for async source %d. Sink will lose state now", sourceId); + sourceIt->second.m_delegate->lostState(); + + sourceIt->second.m_state = ClientState::AWAITING_PAUSED; + if (m_clientState == ClientState::PLAYING) + { + m_clientState = ClientState::AWAITING_PLAYING; + } + else if (m_clientState == ClientState::PAUSED) + { + m_clientState = ClientState::AWAITING_PAUSED; + } + } + }); +} + +void GStreamerMSEMediaPlayerClient::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) +{ + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + GST_ERROR("Cannot Set Source Position - there's no attached source with id %d", sourceId); + return; + } + if (!m_clientBackend->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition)) + { + GST_ERROR("Set Source Position operation failed for source with id %d", sourceId); + return; + } + sourceIt->second.m_position = position; + }); +} + +void GStreamerMSEMediaPlayerClient::setSubtitleOffset(int32_t sourceId, int64_t position) +{ + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + GST_ERROR("Cannot Set Subtitle Offset - there's no attached source with id %d", sourceId); + return; + } + if (!m_clientBackend->setSubtitleOffset(sourceId, position)) + { + GST_ERROR("Set Subtitle Offset operation failed for source with id %d", sourceId); + return; + } + }); +} + +void GStreamerMSEMediaPlayerClient::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, + bool audioAac) +{ + m_backendQueue->callInEventLoop( + [&]() + { + if (!m_clientBackend->processAudioGap(position, duration, discontinuityGap, audioAac)) + { + GST_ERROR("Process Audio Gap operation failed"); + return; + } + }); +} + +bool GStreamerMSEMediaPlayerClient::attachSource(std::unique_ptr &source, + RialtoMSEBaseSink *rialtoSink, + const std::shared_ptr &delegate) +{ + if (source->getType() != firebolt::rialto::MediaSourceType::AUDIO && + source->getType() != firebolt::rialto::MediaSourceType::VIDEO && + source->getType() != firebolt::rialto::MediaSourceType::SUBTITLE) + { + GST_WARNING_OBJECT(rialtoSink, "Invalid source type %u", static_cast(source->getType())); + return false; + } + + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + result = m_clientBackend->attachSource(source); + + if (result) + { + std::shared_ptr bufferParser; + if (source->getType() == firebolt::rialto::MediaSourceType::AUDIO) + { + bufferParser = std::make_shared(); + } + else if (source->getType() == firebolt::rialto::MediaSourceType::VIDEO) + { + bufferParser = std::make_shared(); + } + else if (source->getType() == firebolt::rialto::MediaSourceType::SUBTITLE) + { + bufferParser = std::make_shared(); + } + + std::shared_ptr bufferPuller = std::make_shared(m_messageQueueFactory, + GST_ELEMENT_CAST(rialtoSink), + bufferParser, delegate); + + if (m_attachedSources.find(source->getId()) == m_attachedSources.end()) + { + m_attachedSources.emplace(source->getId(), + AttachedSource(rialtoSink, bufferPuller, delegate, source->getType())); + + delegate->setSourceId(source->getId()); + bufferPuller->start(); + } + } + + sendAllSourcesAttachedIfPossibleInternal(); + }); + + return result; +} + +void GStreamerMSEMediaPlayerClient::sendAllSourcesAttachedIfPossible() +{ + m_backendQueue->callInEventLoop([&]() { sendAllSourcesAttachedIfPossibleInternal(); }); +} + +void GStreamerMSEMediaPlayerClient::sendAllSourcesAttachedIfPossibleInternal() +{ + if (!m_wasAllSourcesAttachedSent && areAllStreamsAttached()) + { + // RialtoServer doesn't support dynamic source attachment. + // It means that when we notify that all sources were attached, we cannot add any more sources in the current session + GST_INFO("All sources attached"); + m_clientBackend->allSourcesAttached(); + m_wasAllSourcesAttachedSent = true; + m_clientState = ClientState::READY; + + // In playbin3 streams, confirmation about number of available sources comes after attaching the source, + // so we need to check if all sources are ready to pause + if (checkIfAllAttachedSourcesInStates({ClientState::AWAITING_PAUSED})) + { + GST_INFO("Sending pause command, because all attached sources are ready to pause"); + m_clientBackend->pause(); + m_clientState = ClientState::AWAITING_PAUSED; + } + } +} + +void GStreamerMSEMediaPlayerClient::removeSource(int32_t sourceId) +{ + m_backendQueue->callInEventLoop( + [&]() + { + if (!m_clientBackend->removeSource(sourceId)) + { + GST_WARNING("Remove source %d failed", sourceId); + } + m_attachedSources.erase(sourceId); + }); +} + +void GStreamerMSEMediaPlayerClient::handlePlaybackStateChange(firebolt::rialto::PlaybackState state) +{ + GST_DEBUG("Received state change to state %u", static_cast(state)); + m_backendQueue->callInEventLoop( + [&]() + { + m_serverPlaybackState = state; + switch (state) + { + case firebolt::rialto::PlaybackState::PAUSED: + case firebolt::rialto::PlaybackState::PLAYING: + { + if (state == firebolt::rialto::PlaybackState::PAUSED && m_clientState == ClientState::AWAITING_PAUSED) + { + m_clientState = ClientState::PAUSED; + } + else if (state == firebolt::rialto::PlaybackState::PLAYING && + m_clientState == ClientState::AWAITING_PLAYING) + { + m_clientState = ClientState::PLAYING; + } + else if (state == firebolt::rialto::PlaybackState::PLAYING && + m_clientState == ClientState::AWAITING_PAUSED) + { + GST_WARNING("Outdated Playback State change to PLAYING received. Discarding..."); + break; + } + + for (auto &source : m_attachedSources) + { + if (state == firebolt::rialto::PlaybackState::PAUSED && + source.second.m_state == ClientState::AWAITING_PAUSED) + { + source.second.m_state = ClientState::PAUSED; + } + else if (state == firebolt::rialto::PlaybackState::PLAYING && + source.second.m_state == ClientState::AWAITING_PLAYING) + { + source.second.m_state = ClientState::PLAYING; + } + source.second.m_delegate->handleStateChanged(state); + } + + break; + } + case firebolt::rialto::PlaybackState::END_OF_STREAM: + { + for (const auto &source : m_attachedSources) + { + source.second.m_delegate->handleEos(); + } + } + break; + case firebolt::rialto::PlaybackState::SEEK_DONE: + { + GST_WARNING("firebolt::rialto::PlaybackState::SEEK_DONE notification not supported"); + break; + } + case firebolt::rialto::PlaybackState::FAILURE: + { + for (const auto &source : m_attachedSources) + { + source.second.m_delegate->handleError("Rialto server playback failed"); + } + for (auto &source : m_attachedSources) + { + source.second.m_position = 0; + } + + break; + } + break; + default: + break; + } + }); +} + +void GStreamerMSEMediaPlayerClient::handleSourceFlushed(int32_t sourceId) +{ + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + GST_ERROR("Cannot finish flush - there's no attached source with id %d", sourceId); + return; + } + if (!sourceIt->second.m_isFlushing) + { + GST_ERROR("Cannot finish flush - source with id %d is not flushing!", sourceId); + return; + } + sourceIt->second.m_isFlushing = false; + sourceIt->second.m_bufferPuller->start(); + sourceIt->second.m_delegate->handleFlushCompleted(); + }); +} + +void GStreamerMSEMediaPlayerClient::setVideoRectangle(const std::string &rectangleString) +{ + m_backendQueue->callInEventLoop( + [&]() + { + if (!m_clientBackend || !m_clientBackend->isMediaPlayerBackendCreated()) + { + GST_WARNING("Missing RialtoClient backend - can't set video window now"); + return; + } + + if (rectangleString.empty()) + { + GST_WARNING("Empty video rectangle string"); + return; + } + + Rectangle rect = {0, 0, 0, 0}; + if (sscanf(rectangleString.c_str(), "%u,%u,%u,%u", &rect.x, &rect.y, &rect.width, &rect.height) != 4) + { + GST_WARNING("Invalid video rectangle values"); + return; + } + + m_clientBackend->setVideoWindow(rect.x, rect.y, rect.width, rect.height); + m_videoRectangle = rect; + }); +} + +std::string GStreamerMSEMediaPlayerClient::getVideoRectangle() +{ + char rectangle[64]; + m_backendQueue->callInEventLoop( + [&]() + { + sprintf(rectangle, "%u,%u,%u,%u", m_videoRectangle.x, m_videoRectangle.y, m_videoRectangle.width, + m_videoRectangle.height); + }); + + return std::string(rectangle); +} + +bool GStreamerMSEMediaPlayerClient::renderFrame(int32_t sourceId) +{ + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + result = m_clientBackend->renderFrame(); + if (result) + { + // RialtoServer's video sink should drop PAUSED state due to skipping prerolled buffer in PAUSED state + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt != m_attachedSources.end()) + { + sourceIt->second.m_delegate->lostState(); + } + } + }); + return result; +} + +void GStreamerMSEMediaPlayerClient::setVolume(double targetVolume, uint32_t volumeDuration, + firebolt::rialto::EaseType easeType) +{ + m_backendQueue->callInEventLoop([&]() { m_clientBackend->setVolume(targetVolume, volumeDuration, easeType); }); +} + +bool GStreamerMSEMediaPlayerClient::getVolume(double &volume) +{ + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getVolume(volume); }); + return status; +} + +void GStreamerMSEMediaPlayerClient::setMute(bool mute, int32_t sourceId) +{ + m_backendQueue->callInEventLoop([&]() { m_clientBackend->setMute(mute, sourceId); }); +} + +bool GStreamerMSEMediaPlayerClient::getMute(int sourceId) +{ + bool mute{false}; + m_backendQueue->callInEventLoop([&]() { m_clientBackend->getMute(mute, sourceId); }); + + return mute; +} + +void GStreamerMSEMediaPlayerClient::setTextTrackIdentifier(const std::string &textTrackIdentifier) +{ + m_backendQueue->callInEventLoop([&]() { m_clientBackend->setTextTrackIdentifier(textTrackIdentifier); }); +} + +std::string GStreamerMSEMediaPlayerClient::getTextTrackIdentifier() +{ + std::string getTextTrackIdentifier; + m_backendQueue->callInEventLoop([&]() { m_clientBackend->getTextTrackIdentifier(getTextTrackIdentifier); }); + return getTextTrackIdentifier; +} + +bool GStreamerMSEMediaPlayerClient::setLowLatency(bool lowLatency) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setLowLatency(lowLatency); }); + return status; +} + +bool GStreamerMSEMediaPlayerClient::setSync(bool sync) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setSync(sync); }); + return status; +} + +bool GStreamerMSEMediaPlayerClient::getSync(bool &sync) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getSync(sync); }); + return status; +} + +bool GStreamerMSEMediaPlayerClient::setSyncOff(bool syncOff) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setSyncOff(syncOff); }); + return status; +} + +bool GStreamerMSEMediaPlayerClient::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setStreamSyncMode(sourceId, streamSyncMode); }); + return status; +} + +bool GStreamerMSEMediaPlayerClient::getStreamSyncMode(int32_t &streamSyncMode) +{ + if (!m_clientBackend) + { + return false; + } + + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getStreamSyncMode(streamSyncMode); }); + return status; +} + +ClientState GStreamerMSEMediaPlayerClient::getClientState() +{ + ClientState state{ClientState::IDLE}; + m_backendQueue->callInEventLoop([&]() { state = m_clientState; }); + return state; +} + +void GStreamerMSEMediaPlayerClient::handleStreamCollection(int32_t audioStreams, int32_t videoStreams, + int32_t subtitleStreams) +{ + m_backendQueue->callInEventLoop( + [&]() + { + if (m_audioStreams == UNKNOWN_STREAMS_NUMBER) + m_audioStreams = audioStreams; + if (m_videoStreams == UNKNOWN_STREAMS_NUMBER) + m_videoStreams = videoStreams; + if (m_subtitleStreams == UNKNOWN_STREAMS_NUMBER) + m_subtitleStreams = subtitleStreams; + + GST_INFO("Updated number of streams. New streams' numbers; video=%d, audio=%d, text=%d", m_videoStreams, + m_audioStreams, m_subtitleStreams); + }); +} + +void GStreamerMSEMediaPlayerClient::setBufferingLimit(uint32_t limitBufferingMs) +{ + if (!m_clientBackend) + { + return; + } + m_backendQueue->callInEventLoop([&]() { m_clientBackend->setBufferingLimit(limitBufferingMs); }); +} + +uint32_t GStreamerMSEMediaPlayerClient::getBufferingLimit() +{ + if (!m_clientBackend) + { + return kDefaultBufferingLimit; + } + + uint32_t result{kDefaultBufferingLimit}; + m_backendQueue->callInEventLoop([&]() { m_clientBackend->getBufferingLimit(result); }); + return result; +} + +void GStreamerMSEMediaPlayerClient::setUseBuffering(bool useBuffering) +{ + if (!m_clientBackend) + { + return; + } + m_backendQueue->callInEventLoop([&]() { m_clientBackend->setUseBuffering(useBuffering); }); +} + +bool GStreamerMSEMediaPlayerClient::getUseBuffering() +{ + if (!m_clientBackend) + { + return kDefaultUseBuffering; + } + + bool result{kDefaultUseBuffering}; + m_backendQueue->callInEventLoop([&]() { m_clientBackend->getUseBuffering(result); }); + return result; +} + +bool GStreamerMSEMediaPlayerClient::switchSource(const std::unique_ptr &source) +{ + bool result = false; + m_backendQueue->callInEventLoop([&]() { result = m_clientBackend->switchSource(source); }); + + return result; +} + +bool GStreamerMSEMediaPlayerClient::checkIfAllAttachedSourcesInStates(const std::vector &states) +{ + return std::all_of(m_attachedSources.begin(), m_attachedSources.end(), [states](const auto &source) + { return std::find(states.begin(), states.end(), source.second.m_state) != states.end(); }); +} + +bool GStreamerMSEMediaPlayerClient::areAllStreamsAttached() +{ + int32_t attachedVideoSources = 0; + int32_t attachedAudioSources = 0; + int32_t attachedSubtitleSources = 0; + for (auto &source : m_attachedSources) + { + if (source.second.getType() == firebolt::rialto::MediaSourceType::VIDEO) + { + attachedVideoSources++; + } + else if (source.second.getType() == firebolt::rialto::MediaSourceType::AUDIO) + { + attachedAudioSources++; + } + else if (source.second.getType() == firebolt::rialto::MediaSourceType::SUBTITLE) + { + attachedSubtitleSources++; + } + } + + return attachedVideoSources == m_videoStreams && attachedAudioSources == m_audioStreams && + attachedSubtitleSources == m_subtitleStreams; +} + +bool GStreamerMSEMediaPlayerClient::requestPullBuffer(int streamId, size_t frameCount, unsigned int needDataRequestId) +{ + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(streamId); + if (sourceIt == m_attachedSources.end()) + { + GST_ERROR("There's no attached source with id %d", streamId); + + result = false; + return; + } + result = sourceIt->second.m_bufferPuller->requestPullBuffer(streamId, frameCount, needDataRequestId, this); + }); + + return result; +} + +bool GStreamerMSEMediaPlayerClient::handleQos(int sourceId, firebolt::rialto::QosInfo qosInfo) +{ + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + result = false; + return; + } + sourceIt->second.m_delegate->handleQos(qosInfo.processed, qosInfo.dropped); + result = true; + }); + + return result; +} + +bool GStreamerMSEMediaPlayerClient::handleBufferUnderflow(int sourceId) +{ + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + result = false; + return; + } + + rialto_mse_base_handle_rialto_server_sent_buffer_underflow(sourceIt->second.m_rialtoSink); + + result = true; + }); + + return result; +} + +bool GStreamerMSEMediaPlayerClient::handlePlaybackError(int sourceId, firebolt::rialto::PlaybackError error) +{ + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + auto sourceIt = m_attachedSources.find(sourceId); + if (sourceIt == m_attachedSources.end()) + { + result = false; + return; + } + + // Even though rialto has only reported a non-fatal error, still fail the pipeline from rialto-gstreamer + GST_ERROR("Received Playback error '%s', posting error on %s sink", toString(error), + toString(sourceIt->second.getType())); + if (firebolt::rialto::PlaybackError::DECRYPTION == error) + { + sourceIt->second.m_delegate->handleError("Rialto dropped a frame that failed to decrypt", + GST_STREAM_ERROR_DECRYPT); + } + else + { + sourceIt->second.m_delegate->handleError("Rialto server playback failed"); + } + + result = true; + }); + + return result; +} + +firebolt::rialto::AddSegmentStatus GStreamerMSEMediaPlayerClient::addSegment( + unsigned int needDataRequestId, const std::unique_ptr &mediaSegment) +{ + // rialto client's addSegment call is MT safe, so it's ok to call it from the Puller's thread + return m_clientBackend->addSegment(needDataRequestId, mediaSegment); +} + +BufferPuller::BufferPuller(const std::shared_ptr &messageQueueFactory, GstElement *rialtoSink, + const std::shared_ptr &bufferParser, + const std::shared_ptr &delegate) + : m_queue{messageQueueFactory->createMessageQueue()}, m_rialtoSink(rialtoSink), m_bufferParser(bufferParser), + m_delegate{delegate} +{ +} + +void BufferPuller::start() +{ + m_queue->start(); +} + +void BufferPuller::stop() +{ + m_queue->stop(); +} + +bool BufferPuller::requestPullBuffer(int sourceId, size_t frameCount, unsigned int needDataRequestId, + GStreamerMSEMediaPlayerClient *player) +{ + return m_queue->postMessage(std::make_shared(sourceId, frameCount, needDataRequestId, m_rialtoSink, + m_bufferParser, *m_queue, player, m_delegate)); +} + +HaveDataMessage::HaveDataMessage(firebolt::rialto::MediaSourceStatus status, int sourceId, + unsigned int needDataRequestId, GStreamerMSEMediaPlayerClient *player) + : m_status(status), m_sourceId(sourceId), m_needDataRequestId(needDataRequestId), m_player(player) +{ +} + +void HaveDataMessage::handle() +{ + if (m_player->m_attachedSources.find(m_sourceId) == m_player->m_attachedSources.end()) + { + GST_WARNING("Source id %d is invalid", m_sourceId); + return; + } + + m_player->m_clientBackend->haveData(m_status, m_needDataRequestId); +} + +PullBufferMessage::PullBufferMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, + GstElement *rialtoSink, const std::shared_ptr &bufferParser, + IMessageQueue &pullerQueue, GStreamerMSEMediaPlayerClient *player, + const std::shared_ptr &delegate) + : m_sourceId(sourceId), m_frameCount(frameCount), m_needDataRequestId(needDataRequestId), m_rialtoSink(rialtoSink), + m_bufferParser(bufferParser), m_pullerQueue(pullerQueue), m_player(player), m_delegate{delegate} +{ +} + +void PullBufferMessage::handle() +{ + bool isEos = false; + unsigned int addedSegments = 0; + + for (unsigned int frame = 0; frame < m_frameCount; ++frame) + { + if (!m_delegate->isReadyToSendData()) + { + GST_INFO_OBJECT(m_rialtoSink, "Not ready to send data - segment or eos not received yet"); + break; + } + GstRefSample sample = m_delegate->getFrontSample(); + if (!sample) + { + if (m_delegate->isEos()) + { + isEos = true; + } + else + { + // it's not a critical issue. It might be caused by receiving too many need data requests. + GST_INFO_OBJECT(m_rialtoSink, "Could not get a sample"); + } + break; + } + + // we pass GstMapInfo's pointers on data buffers to RialtoClient + // so we need to hold it until RialtoClient copies them to shm + GstBuffer *buffer = sample.getBuffer(); + GstMapInfo map; + if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) + { + GST_ERROR_OBJECT(m_rialtoSink, "Could not map buffer"); + m_delegate->popSample(); + continue; + } + + std::unique_ptr mseData = + m_bufferParser->parseBuffer(sample, buffer, map, m_sourceId); + if (!mseData) + { + GST_ERROR_OBJECT(m_rialtoSink, "No data returned from the parser"); + gst_buffer_unmap(buffer, &map); + m_delegate->popSample(); + continue; + } + + firebolt::rialto::AddSegmentStatus addSegmentStatus = m_player->addSegment(m_needDataRequestId, mseData); + if (addSegmentStatus == firebolt::rialto::AddSegmentStatus::NO_SPACE) + { + gst_buffer_unmap(buffer, &map); + GST_INFO_OBJECT(m_rialtoSink, "There's no space to add sample"); + break; + } + + gst_buffer_unmap(buffer, &map); + m_delegate->popSample(); + addedSegments++; + } + + firebolt::rialto::MediaSourceStatus status = firebolt::rialto::MediaSourceStatus::OK; + if (isEos) + { + status = firebolt::rialto::MediaSourceStatus::EOS; + } + else if (addedSegments == 0) + { + status = firebolt::rialto::MediaSourceStatus::NO_AVAILABLE_SAMPLES; + } + + m_player->m_backendQueue->postMessage( + std::make_shared(status, m_sourceId, m_needDataRequestId, m_player)); +} + +NeedDataMessage::NeedDataMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, + GStreamerMSEMediaPlayerClient *player) + : m_sourceId(sourceId), m_frameCount(frameCount), m_needDataRequestId(needDataRequestId), m_player(player) +{ +} + +void NeedDataMessage::handle() +{ + if (!m_player->requestPullBuffer(m_sourceId, m_frameCount, m_needDataRequestId)) + { + GST_ERROR("Failed to pull buffer for sourceId=%d and NeedDataRequestId %u", m_sourceId, m_needDataRequestId); + m_player->m_backendQueue->postMessage( + std::make_shared(firebolt::rialto::MediaSourceStatus::ERROR, m_sourceId, + m_needDataRequestId, m_player)); + } +} + +PlaybackStateMessage::PlaybackStateMessage(firebolt::rialto::PlaybackState state, GStreamerMSEMediaPlayerClient *player) + : m_state(state), m_player(player) +{ +} + +void PlaybackStateMessage::handle() +{ + m_player->handlePlaybackStateChange(m_state); +} + +QosMessage::QosMessage(int sourceId, firebolt::rialto::QosInfo qosInfo, GStreamerMSEMediaPlayerClient *player) + : m_sourceId(sourceId), m_qosInfo(qosInfo), m_player(player) +{ +} + +void QosMessage::handle() +{ + if (!m_player->handleQos(m_sourceId, m_qosInfo)) + { + GST_ERROR("Failed to handle qos for sourceId=%d", m_sourceId); + } +} + +BufferUnderflowMessage::BufferUnderflowMessage(int sourceId, GStreamerMSEMediaPlayerClient *player) + : m_sourceId(sourceId), m_player(player) +{ +} + +void BufferUnderflowMessage::handle() +{ + if (!m_player->handleBufferUnderflow(m_sourceId)) + { + GST_ERROR("Failed to handle buffer underflow for sourceId=%d", m_sourceId); + } +} + +PlaybackErrorMessage::PlaybackErrorMessage(int sourceId, firebolt::rialto::PlaybackError error, + GStreamerMSEMediaPlayerClient *player) + : m_sourceId(sourceId), m_error(error), m_player(player) +{ +} + +void PlaybackErrorMessage::handle() +{ + if (!m_player->handlePlaybackError(m_sourceId, m_error)) + { + GST_ERROR("Failed to handle playback error for sourceId=%d, error %s", m_sourceId, toString(m_error)); + } +} + +SetPositionMessage::SetPositionMessage(int64_t newPosition, std::unordered_map &attachedSources) + : m_newPosition(newPosition), m_attachedSources(attachedSources) +{ +} + +void SetPositionMessage::handle() +{ + for (auto &source : m_attachedSources) + { + source.second.setPosition(m_newPosition); + } +} + +SetDurationMessage::SetDurationMessage(int64_t newDuration, int64_t &targetDuration) + : m_newDuration(newDuration), m_targetDuration(targetDuration) +{ +} + +void SetDurationMessage::handle() +{ + m_targetDuration = m_newDuration; +} + +SourceFlushedMessage::SourceFlushedMessage(int32_t sourceId, GStreamerMSEMediaPlayerClient *player) + : m_sourceId{sourceId}, m_player{player} +{ +} + +void SourceFlushedMessage::handle() +{ + m_player->handleSourceFlushed(m_sourceId); +} diff --git a/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.h b/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.h new file mode 100644 index 000000000..3c91a1a52 --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.h @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "BufferParser.h" +#include "Constants.h" +#include "IMediaPipeline.h" +#include "IMessageQueue.h" +#include "IPullModePlaybackDelegate.h" +#include "MediaCommon.h" +#include "MediaPlayerClientBackendInterface.h" +#include "RialtoGStreamerMSEBaseSink.h" + +#define DEFAULT_MAX_VIDEO_WIDTH 3840 +#define DEFAULT_MAX_VIDEO_HEIGHT 2160 + +class GStreamerMSEMediaPlayerClient; + +enum class ClientState +{ + IDLE, + READY, + AWAITING_PAUSED, + PAUSED, + AWAITING_PLAYING, + PLAYING +}; + +class BufferPuller +{ +public: + BufferPuller(const std::shared_ptr &messageQueueFactory, GstElement *rialtoSink, + const std::shared_ptr &bufferParser, + const std::shared_ptr &delegate); + + void start(); + void stop(); + bool requestPullBuffer(int sourceId, size_t frameCount, unsigned int needDataRequestId, + GStreamerMSEMediaPlayerClient *player); + +private: + std::unique_ptr m_queue; + GstElement *m_rialtoSink; + std::shared_ptr m_bufferParser; + std::shared_ptr m_delegate; +}; + +class AttachedSource +{ + friend class GStreamerMSEMediaPlayerClient; + +public: + AttachedSource(RialtoMSEBaseSink *rialtoSink, std::shared_ptr puller, + const std::shared_ptr &delegate, firebolt::rialto::MediaSourceType type, + ClientState state = ClientState::READY) + : m_rialtoSink(rialtoSink), m_bufferPuller(puller), m_delegate{delegate}, m_type(type), m_state(state) + { + } + + firebolt::rialto::MediaSourceType getType() const { return m_type; } + void setPosition(int64_t position) { m_position = position; } + +private: + RialtoMSEBaseSink *m_rialtoSink; + std::shared_ptr m_bufferPuller; + std::shared_ptr m_delegate; + std::unordered_set m_ongoingNeedDataRequests; + firebolt::rialto::MediaSourceType m_type = firebolt::rialto::MediaSourceType::UNKNOWN; + int64_t m_position = 0; + bool m_isFlushing = false; + ClientState m_state = ClientState::READY; +}; + +class HaveDataMessage : public Message +{ +public: + HaveDataMessage(firebolt::rialto::MediaSourceStatus status, int sourceId, unsigned int needDataRequestId, + GStreamerMSEMediaPlayerClient *player); + void handle() override; + +private: + firebolt::rialto::MediaSourceStatus m_status; + int m_sourceId; + unsigned int m_needDataRequestId; + GStreamerMSEMediaPlayerClient *m_player; +}; + +class PullBufferMessage : public Message +{ +public: + PullBufferMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, GstElement *rialtoSink, + const std::shared_ptr &bufferParser, IMessageQueue &pullerQueue, + GStreamerMSEMediaPlayerClient *player, const std::shared_ptr &delegate); + void handle() override; + +private: + int m_sourceId; + size_t m_frameCount; + unsigned int m_needDataRequestId; + GstElement *m_rialtoSink; + std::shared_ptr m_bufferParser; + IMessageQueue &m_pullerQueue; + GStreamerMSEMediaPlayerClient *m_player; + std::shared_ptr m_delegate; +}; + +class NeedDataMessage : public Message +{ +public: + NeedDataMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, + GStreamerMSEMediaPlayerClient *player); + void handle() override; + +private: + int m_sourceId; + size_t m_frameCount; + unsigned int m_needDataRequestId; + GStreamerMSEMediaPlayerClient *m_player; +}; + +class PlaybackStateMessage : public Message +{ +public: + PlaybackStateMessage(firebolt::rialto::PlaybackState state, GStreamerMSEMediaPlayerClient *player); + void handle() override; + +private: + firebolt::rialto::PlaybackState m_state; + GStreamerMSEMediaPlayerClient *m_player; +}; + +class QosMessage : public Message +{ +public: + QosMessage(int sourceId, firebolt::rialto::QosInfo qosInfo, GStreamerMSEMediaPlayerClient *player); + void handle() override; + +private: + int m_sourceId; + firebolt::rialto::QosInfo m_qosInfo; + GStreamerMSEMediaPlayerClient *m_player; +}; + +class BufferUnderflowMessage : public Message +{ +public: + BufferUnderflowMessage(int sourceId, GStreamerMSEMediaPlayerClient *player); + void handle() override; + +private: + int m_sourceId; + GStreamerMSEMediaPlayerClient *m_player; +}; + +class PlaybackErrorMessage : public Message +{ +public: + PlaybackErrorMessage(int sourceId, firebolt::rialto::PlaybackError error, GStreamerMSEMediaPlayerClient *player); + void handle() override; + +private: + int m_sourceId; + firebolt::rialto::PlaybackError m_error; + GStreamerMSEMediaPlayerClient *m_player; +}; + +class SetPositionMessage : public Message +{ +public: + SetPositionMessage(int64_t newPosition, std::unordered_map &attachedSources); + void handle() override; + +private: + int64_t m_newPosition; + std::unordered_map &m_attachedSources; +}; + +class SetDurationMessage : public Message +{ +public: + SetDurationMessage(int64_t newDuration, int64_t &targetDuration); + void handle() override; + +private: + int64_t m_newDuration; + int64_t &m_targetDuration; +}; + +class SourceFlushedMessage : public Message +{ +public: + SourceFlushedMessage(int32_t sourceId, GStreamerMSEMediaPlayerClient *player); + void handle() override; + +private: + int32_t m_sourceId; + GStreamerMSEMediaPlayerClient *m_player; +}; + +enum class StateChangeResult +{ + SUCCESS_ASYNC, + SUCCESS_SYNC, + NOT_ATTACHED +}; + +class GStreamerMSEMediaPlayerClient : public firebolt::rialto::IMediaPipelineClient, + public std::enable_shared_from_this +{ + friend class NeedDataMessage; + friend class PullBufferMessage; + friend class HaveDataMessage; + friend class QosMessage; + +public: + GStreamerMSEMediaPlayerClient( + const std::shared_ptr &messageQueueFactory, + const std::shared_ptr &MediaPlayerClientBackend, + const uint32_t maxVideoWidth, const uint32_t maxVideoHeight); + virtual ~GStreamerMSEMediaPlayerClient(); + + void notifyDuration(int64_t duration) override; + void notifyPosition(int64_t position) override; + void notifyNativeSize(uint32_t width, uint32_t height, double aspect) override; + void notifyNetworkState(firebolt::rialto::NetworkState state) override; + void notifyPlaybackState(firebolt::rialto::PlaybackState state) override; + void notifyVideoData(bool hasData) override; + void notifyAudioData(bool hasData) override; + void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, + const std::shared_ptr &shmInfo) override; + void notifyCancelNeedMediaData(int32_t sourceId) override; + void notifyQos(int32_t sourceId, const firebolt::rialto::QosInfo &qosInfo) override; + void notifyBufferUnderflow(int32_t sourceId) override; + void notifyPlaybackError(int32_t sourceId, firebolt::rialto::PlaybackError error) override; + void notifySourceFlushed(int32_t sourceId) override; + + void getPositionDo(int64_t *position, int32_t sourceId); + int64_t getPosition(int32_t sourceId); + bool setImmediateOutput(int32_t sourceId, bool immediateOutput); + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput); + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames); + + firebolt::rialto::AddSegmentStatus + addSegment(unsigned int needDataRequestId, + const std::unique_ptr &mediaSegment); + + bool createBackend(); + StateChangeResult play(int32_t sourceId); + StateChangeResult pause(int32_t sourceId); + void stop(); + void setPlaybackRate(double rate); + void flush(int32_t sourceId, bool resetTime); + void setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate = 1.0, + uint64_t stopPosition = GST_CLOCK_TIME_NONE); + void setSubtitleOffset(int32_t sourceId, int64_t position); + void processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac); + + bool attachSource(std::unique_ptr &source, + RialtoMSEBaseSink *rialtoSink, const std::shared_ptr &delegate); + void removeSource(int32_t sourceId); + void handlePlaybackStateChange(firebolt::rialto::PlaybackState state); + void handleSourceFlushed(int32_t sourceId); + void sendAllSourcesAttachedIfPossible(); + + void setVideoRectangle(const std::string &rectangleString); + std::string getVideoRectangle(); + + bool requestPullBuffer(int streamId, size_t frameCount, unsigned int needDataRequestId); + bool handleQos(int sourceId, firebolt::rialto::QosInfo qosInfo); + bool handleBufferUnderflow(int sourceId); + bool handlePlaybackError(int sourceId, firebolt::rialto::PlaybackError error); + void stopStreaming(); + void destroyClientBackend(); + bool renderFrame(int32_t sourceId); + void setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType); + bool getVolume(double &volume); + void setMute(bool mute, int32_t sourceId); + bool getMute(int sourceId); + void setTextTrackIdentifier(const std::string &textTrackIdentifier); + std::string getTextTrackIdentifier(); + bool setLowLatency(bool lowLatency); + bool setSync(bool sync); + bool getSync(bool &sync); + bool setSyncOff(bool syncOff); + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode); + bool getStreamSyncMode(int32_t &streamSyncMode); + ClientState getClientState(); + void handleStreamCollection(int32_t audioStreams, int32_t videoStreams, int32_t subtitleStreams); + void setBufferingLimit(uint32_t limitBufferingMs); + uint32_t getBufferingLimit(); + void setUseBuffering(bool useBuffering); + bool getUseBuffering(); + bool switchSource(const std::unique_ptr &source); + +private: + bool areAllStreamsAttached(); + void sendAllSourcesAttachedIfPossibleInternal(); + bool checkIfAllAttachedSourcesInStates(const std::vector &states); + + std::unique_ptr m_backendQueue; + std::shared_ptr m_messageQueueFactory; + std::shared_ptr m_clientBackend; + int64_t m_position; + int64_t m_duration; + std::mutex m_playerMutex; + std::unordered_map m_attachedSources; + bool m_wasAllSourcesAttachedSent = false; + int32_t m_audioStreams; + int32_t m_videoStreams; + int32_t m_subtitleStreams; + + struct Rectangle + { + unsigned int x, y, width, height; + } m_videoRectangle; + + firebolt::rialto::PlaybackState m_serverPlaybackState = firebolt::rialto::PlaybackState::IDLE; + ClientState m_clientState = ClientState::IDLE; + // To check if the backend message queue and pulling of data to serve backend is stopped or not + bool m_streamingStopped; + + const uint32_t m_maxWidth; + const uint32_t m_maxHeight; +}; diff --git a/middleware/rialto-gstreamer/source/GStreamerMSEUtils.cpp b/middleware/rialto-gstreamer/source/GStreamerMSEUtils.cpp new file mode 100644 index 000000000..1eeadc104 --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerMSEUtils.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "GStreamerMSEUtils.h" +#include "GStreamerUtils.h" +#include "GstreamerCatLog.h" + +#include +#include +#include +#include + +#define GST_CAT_DEFAULT rialtoGStreamerCat + +void rialto_mse_sink_setup_supported_caps(GstElementClass *elementClass, + const std::vector &supportedMimeTypes) +{ + static const std::unordered_map> kMimeToCaps = + {{"audio/mp4", {"audio/mpeg, mpegversion=1", "audio/mpeg, mpegversion=2", "audio/mpeg, mpegversion=4"}}, + {"audio/mp3", {"audio/mpeg, mpegversion=1", "audio/mpeg, mpegversion=2"}}, + {"audio/aac", {"audio/mpeg, mpegversion=2", "audio/mpeg, mpegversion=4"}}, + {"audio/x-eac3", {"audio/x-ac3", "audio/x-eac3"}}, + {"audio/x-opus", {"audio/x-opus"}}, + {"audio/b-wav", {"audio/b-wav"}}, + {"audio/x-flac", {"audio/x-flac"}}, + {"audio/x-raw", {"audio/x-raw"}}, + {"video/h264", {"video/x-h264"}}, + {"video/h265", {"video/x-h265"}}, + {"video/x-av1", {"video/x-av1"}}, + {"video/x-vp9", {"video/x-vp9"}}, + {"text/vtt", {"text/vtt", "application/x-subtitle-vtt"}}, + {"text/ttml", {"application/ttml+xml"}}, + {"text/cc", + {"closedcaption/x-cea-608", "closedcaption/x-cea-708", "application/x-cea-608", "application/x-cea-708", + "application/x-subtitle-cc"}}}; + + std::unordered_set addedCaps; // keep track what caps were added to avoid duplicates + GstCaps *caps = gst_caps_new_empty(); + for (const std::string &mime : supportedMimeTypes) + { + auto mimeToCapsIt = kMimeToCaps.find(mime); + if (mimeToCapsIt != kMimeToCaps.end()) + { + for (const std::string &capsStr : mimeToCapsIt->second) + { + if (addedCaps.find(capsStr) == addedCaps.end()) + { + GST_INFO("Caps '%s' is supported", capsStr.c_str()); + GstCaps *newCaps = gst_caps_from_string(capsStr.c_str()); + gst_caps_append(caps, newCaps); + addedCaps.insert(capsStr); + } + } + } + else + { + GST_WARNING("Mime '%s' is not supported", mime.c_str()); + } + } + + GstPadTemplate *sinktempl = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps); + gst_element_class_add_pad_template(elementClass, sinktempl); + gst_caps_unref(caps); +} + +std::optional rialto_mse_sink_convert_layout(const gchar *layoutStr) +{ + if (g_strcmp0(layoutStr, "interleaved") == 0) + { + return firebolt::rialto::Layout::INTERLEAVED; + } + if (g_strcmp0(layoutStr, "non-interleaved") == 0) + { + return firebolt::rialto::Layout::NON_INTERLEAVED; + } + return std::nullopt; +} + +std::optional rialto_mse_sink_convert_format(const gchar *formatStr) +{ + static const std::unordered_map + kStringToFormat{{"S8", firebolt::rialto::Format::S8}, + {"U8", firebolt::rialto::Format::U8}, + {"S16LE", firebolt::rialto::Format::S16LE}, + {"S16BE", firebolt::rialto::Format::S16BE}, + {"U16LE", firebolt::rialto::Format::U16LE}, + {"U16BE", firebolt::rialto::Format::U16BE}, + {"S24_32LE", firebolt::rialto::Format::S24_32LE}, + {"S24_32BE", firebolt::rialto::Format::S24_32BE}, + {"U24_32LE", firebolt::rialto::Format::U24_32LE}, + {"U24_32BE", firebolt::rialto::Format::U24_32BE}, + {"S32LE", firebolt::rialto::Format::S32LE}, + {"S32BE", firebolt::rialto::Format::S32BE}, + {"U32LE", firebolt::rialto::Format::U32LE}, + {"U32BE", firebolt::rialto::Format::U32BE}, + {"S24LE", firebolt::rialto::Format::S24LE}, + {"S24BE", firebolt::rialto::Format::S24BE}, + {"U24LE", firebolt::rialto::Format::U24LE}, + {"U24BE", firebolt::rialto::Format::U24BE}, + {"S20LE", firebolt::rialto::Format::S20LE}, + {"S20BE", firebolt::rialto::Format::S20BE}, + {"U20LE", firebolt::rialto::Format::U20LE}, + {"U20BE", firebolt::rialto::Format::U20BE}, + {"S18LE", firebolt::rialto::Format::S18LE}, + {"S18BE", firebolt::rialto::Format::S18BE}, + {"U18LE", firebolt::rialto::Format::U18LE}, + {"U18BE", firebolt::rialto::Format::U18BE}, + {"F32LE", firebolt::rialto::Format::F32LE}, + {"F32BE", firebolt::rialto::Format::F32BE}, + {"F64LE", firebolt::rialto::Format::F64LE}, + {"F64BE", firebolt::rialto::Format::F64BE}}; + const auto it = kStringToFormat.find(formatStr); + if (it != kStringToFormat.end()) + { + return it->second; + } + return std::nullopt; +} + +std::shared_ptr get_codec_data(const GstStructure *structure) +{ + const GValue *codec_data = gst_structure_get_value(structure, "codec_data"); + if (codec_data) + { + GstBuffer *buf = gst_value_get_buffer(codec_data); + if (buf) + { + GstMappedBuffer mappedBuf(buf, GST_MAP_READ); + if (mappedBuf) + { + auto codecData = std::make_shared(); + codecData->data = std::vector(mappedBuf.data(), mappedBuf.data() + mappedBuf.size()); + codecData->type = firebolt::rialto::CodecDataType::BUFFER; + return codecData; + } + else + { + GST_ERROR("Failed to read codec_data"); + return nullptr; + } + } + const gchar *str = g_value_get_string(codec_data); + if (str) + { + auto codecData = std::make_shared(); + codecData->data = std::vector(str, str + std::strlen(str)); + codecData->type = firebolt::rialto::CodecDataType::STRING; + return codecData; + } + } + + return nullptr; +} + +firebolt::rialto::SegmentAlignment get_segment_alignment(const GstStructure *s) +{ + const gchar *alignment = gst_structure_get_string(s, "alignment"); + if (alignment) + { + GST_DEBUG("Alignment found %s", alignment); + if (strcmp(alignment, "au") == 0) + { + return firebolt::rialto::SegmentAlignment::AU; + } + else if (strcmp(alignment, "nal") == 0) + { + return firebolt::rialto::SegmentAlignment::NAL; + } + } + + return firebolt::rialto::SegmentAlignment::UNDEFINED; +} + +bool get_dv_profile(const GstStructure *s, uint32_t &dvProfile) +{ + gboolean isDolbyVisionEnabled = false; + if (gst_structure_get_boolean(s, "dovi-stream", &isDolbyVisionEnabled) && isDolbyVisionEnabled) + { + if (gst_structure_get_uint(s, "dv_profile", &dvProfile)) + { + return true; + } + } + return false; +} + +firebolt::rialto::StreamFormat get_stream_format(const GstStructure *structure) +{ + const gchar *streamFormat = gst_structure_get_string(structure, "stream-format"); + firebolt::rialto::StreamFormat format = firebolt::rialto::StreamFormat::UNDEFINED; + if (streamFormat) + { + static const std::unordered_map stringToStreamFormatMap = + {{"raw", firebolt::rialto::StreamFormat::RAW}, + {"avc", firebolt::rialto::StreamFormat::AVC}, + {"byte-stream", firebolt::rialto::StreamFormat::BYTE_STREAM}, + {"hvc1", firebolt::rialto::StreamFormat::HVC1}, + {"hev1", firebolt::rialto::StreamFormat::HEV1}}; + + auto strToStreamFormatIt = stringToStreamFormatMap.find(streamFormat); + if (strToStreamFormatIt != stringToStreamFormatMap.end()) + { + format = strToStreamFormatIt->second; + } + } + + return format; +} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/GStreamerMSEUtils.h b/middleware/rialto-gstreamer/source/GStreamerMSEUtils.h new file mode 100644 index 000000000..38a80363e --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerMSEUtils.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef GSTREAMERMSEUTILS_H +#define GSTREAMERMSEUTILS_H + +#include + +#include + +#include +#include +#include +#include +void rialto_mse_sink_setup_supported_caps(GstElementClass *elementClass, + const std::vector &supportedMimeType); +std::optional rialto_mse_sink_convert_layout(const gchar *layoutStr); +std::optional rialto_mse_sink_convert_format(const gchar *formatStr); +std::shared_ptr get_codec_data(const GstStructure *structure); +firebolt::rialto::SegmentAlignment get_segment_alignment(const GstStructure *s); +bool get_dv_profile(const GstStructure *s, uint32_t &dvProfile); +firebolt::rialto::StreamFormat get_stream_format(const GstStructure *structure); +#endif // GSTREAMERMSEUTILS_H diff --git a/middleware/rialto-gstreamer/source/GStreamerUtils.cpp b/middleware/rialto-gstreamer/source/GStreamerUtils.cpp new file mode 100644 index 000000000..b9e3c1fa6 --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerUtils.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "GStreamerUtils.h" + +#define GST_CAT_DEFAULT rialtoGStreamerCat + +GstMappedBuffer::GstMappedBuffer(GstBuffer *buffer, GstMapFlags flags) + : m_buffer(buffer), m_isMapped(gst_buffer_map(m_buffer, &m_info, flags)) +{ +} + +GstMappedBuffer::~GstMappedBuffer() +{ + if (m_isMapped) + { + gst_buffer_unmap(m_buffer, &m_info); + } +} + +uint8_t *GstMappedBuffer::data() +{ + if (m_isMapped) + { + return static_cast(m_info.data); + } + else + { + return nullptr; + } +} + +size_t GstMappedBuffer::size() const +{ + if (m_isMapped) + { + return static_cast(m_info.size); + } + else + { + return 0; + } +} + +GstMappedBuffer::operator bool() const +{ + return m_isMapped; +} + +GstRefSample::GstRefSample(GstSample *sample) : m_sample{sample ? gst_sample_ref(sample) : nullptr} {} + +GstRefSample::~GstRefSample() +{ + if (m_sample) + { + gst_sample_unref(m_sample); + } +} + +GstRefSample::operator bool() const +{ + return m_sample; +} + +GstBuffer *GstRefSample::getBuffer() const +{ + return gst_sample_get_buffer(m_sample); +} + +GstCaps *GstRefSample::getCaps() const +{ + return gst_sample_get_caps(m_sample); +} diff --git a/middleware/rialto-gstreamer/source/GStreamerUtils.h b/middleware/rialto-gstreamer/source/GStreamerUtils.h new file mode 100644 index 000000000..dc0fe96b5 --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerUtils.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef GSTREAMERUTILS_H +#define GSTREAMERUTILS_H + +#include +#include + +class GstMappedBuffer +{ +public: + explicit GstMappedBuffer(GstBuffer *buffer, GstMapFlags flags); + ~GstMappedBuffer(); + uint8_t *data(); + size_t size() const; + explicit operator bool() const; + +private: + GstBuffer *m_buffer; + GstMapInfo m_info; + bool m_isMapped; +}; + +class GstRefSample +{ +public: + explicit GstRefSample(GstSample *sample = nullptr); + GstRefSample(const GstRefSample &) = delete; + GstRefSample(GstRefSample &&) = delete; + GstRefSample &operator=(const GstRefSample &) = delete; + GstRefSample &operator=(GstRefSample &&) = delete; + ~GstRefSample(); + explicit operator bool() const; + GstBuffer *getBuffer() const; + GstCaps *getCaps() const; + +private: + GstSample *m_sample; +}; +#endif // GSTREAMERUTILS_H \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.cpp b/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.cpp new file mode 100644 index 000000000..a71a5be6b --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.cpp @@ -0,0 +1,481 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "GStreamerWebAudioPlayerClient.h" +#include "GstreamerCatLog.h" + +#include + +#include +#include +#include +#include + +#define GST_CAT_DEFAULT rialtoGStreamerCat + +namespace +{ +constexpr std::size_t kMaxQueueSize{40}; +bool parseGstStructureFormat(const std::string &format, uint32_t &sampleSize, bool &isBigEndian, bool &isSigned, + bool &isFloat) +{ + if (format.size() != 5) + { + return false; + } + std::string sampleSizeStr = format.substr(1, 2); + char *pEnd = NULL; + errno = 0; + sampleSize = strtoul(sampleSizeStr.c_str(), &pEnd, 10); + if (errno == ERANGE) + { + return false; + } + + isBigEndian = format.substr(3) == "BE"; + + switch (format[0]) + { + case 'S': + isSigned = true; + isFloat = false; + break; + case 'U': + isSigned = false; + isFloat = false; + break; + case 'F': + isSigned = false; + isFloat = true; + break; + default: + return false; + break; + } + return true; +} + +bool operator!=(const firebolt::rialto::WebAudioPcmConfig &lac, const firebolt::rialto::WebAudioPcmConfig &rac) +{ + return lac.rate != rac.rate || lac.channels != rac.channels || lac.sampleSize != rac.sampleSize || + lac.isBigEndian != rac.isBigEndian || lac.isSigned != rac.isSigned || lac.isFloat != rac.isFloat; +} +} // namespace + +GStreamerWebAudioPlayerClient::GStreamerWebAudioPlayerClient( + std::unique_ptr &&webAudioClientBackend, + std::unique_ptr &&backendQueue, IPlaybackDelegate &delegate, + std::shared_ptr timerFactory) + : m_backendQueue{std::move(backendQueue)}, m_clientBackend{std::move(webAudioClientBackend)}, m_isOpen{false}, + m_dataBuffers{}, m_timerFactory{timerFactory}, m_pushSamplesTimer{nullptr}, m_preferredFrames{0}, + m_maximumFrames{0}, m_supportDeferredPlay{false}, m_isEos{false}, m_frameSize{0}, m_mimeType{}, m_config{{}}, + m_delegate{delegate} +{ + m_backendQueue->start(); +} + +GStreamerWebAudioPlayerClient::~GStreamerWebAudioPlayerClient() +{ + m_backendQueue->stop(); +} + +bool GStreamerWebAudioPlayerClient::open(GstCaps *caps) +{ + GST_DEBUG("entry:"); + + bool result = false; + GstStructure *structure = gst_caps_get_structure(caps, 0); + std::string audioMimeType = gst_structure_get_name(structure); + const auto spacePosition = audioMimeType.find(' '); + if (spacePosition != std::string::npos) + { + audioMimeType.resize(spacePosition); + } + const gchar *formatCStr{gst_structure_get_string(structure, "format")}; + std::string format{formatCStr ? formatCStr : ""}; + firebolt::rialto::WebAudioPcmConfig pcm; + gint tmp; + + if (format.empty()) + { + GST_ERROR("Format not found in caps"); + return result; + } + + if (!gst_structure_get_int(structure, "rate", &tmp)) + { + GST_ERROR("Rate not found in caps"); + return result; + } + pcm.rate = tmp; + + if (!gst_structure_get_int(structure, "channels", &tmp)) + { + GST_ERROR("Rate not found in caps"); + return result; + } + pcm.channels = tmp; + + if (!parseGstStructureFormat(format, pcm.sampleSize, pcm.isBigEndian, pcm.isSigned, pcm.isFloat)) + { + GST_ERROR("Can't parse format or it is not supported: %s", format.c_str()); + return result; + } + + m_backendQueue->callInEventLoop( + [&]() + { + // "configWorkaround" is used because there doesn't seem to be an easy way to use + // make_shared in conjunction with an initalizer list, and adding a constructor to + // WebAudioConfig stops initalizer lists (used elsewhere in the code) from working... + firebolt::rialto::WebAudioConfig configWorkaround{pcm}; + std::shared_ptr config = + std::make_shared(configWorkaround); + + // Only recreate player if the config has changed + if (!m_isOpen || isNewConfig(audioMimeType, config)) + { + if (m_isOpen) + { + // Destroy the previously created player + m_clientBackend->destroyWebAudioBackend(); + } + + uint32_t priority = 1; + if (m_clientBackend->createWebAudioBackend(shared_from_this(), audioMimeType, priority, config)) + { + if (!m_clientBackend->getDeviceInfo(m_preferredFrames, m_maximumFrames, m_supportDeferredPlay)) + { + GST_ERROR("GetDeviceInfo failed, could not process samples"); + } + m_frameSize = (pcm.sampleSize * pcm.channels) / CHAR_BIT; + m_isOpen = true; + + // Store config + m_config.pcm = pcm; + m_mimeType = audioMimeType; + } + else + { + GST_ERROR("Could not create web audio backend"); + m_isOpen = false; + } + result = m_isOpen; + } + }); + + return result; +} + +bool GStreamerWebAudioPlayerClient::close() +{ + GST_DEBUG("entry:"); + + m_backendQueue->callInEventLoop( + [&]() + { + m_clientBackend->destroyWebAudioBackend(); + m_pushSamplesTimer.reset(); + m_isOpen = false; + }); + + return true; +} + +bool GStreamerWebAudioPlayerClient::play() +{ + GST_DEBUG("entry:"); + + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + if (m_isOpen) + { + result = m_clientBackend->play(); + } + else + { + GST_ERROR("No web audio backend"); + } + }); + + return result; +} + +bool GStreamerWebAudioPlayerClient::pause() +{ + GST_DEBUG("entry:"); + + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + if (m_isOpen) + { + result = m_clientBackend->pause(); + } + else + { + GST_ERROR("No web audio backend"); + } + }); + + return result; +} + +bool GStreamerWebAudioPlayerClient::setEos() +{ + GST_DEBUG("entry:"); + + bool result = false; + m_backendQueue->callInEventLoop( + [&]() + { + if (m_isOpen && !m_isEos) + { + m_isEos = true; + if (m_dataBuffers.empty()) + { + result = m_clientBackend->setEos(); + } + else + { + pushSamples(); + result = true; + } + } + else + { + GST_DEBUG("No web audio backend, valid scenario"); + } + }); + + return result; +} + +bool GStreamerWebAudioPlayerClient::isOpen() +{ + GST_DEBUG("entry:"); + + bool result = false; + m_backendQueue->callInEventLoop([&]() { result = m_isOpen; }); + + return result; +} + +void GStreamerWebAudioPlayerClient::notifyPushSamplesTimerExpired() +{ + m_backendQueue->scheduleInEventLoop([&]() { pushSamples(); }); +} + +bool GStreamerWebAudioPlayerClient::notifyNewSample(GstBuffer *buf) +{ + GST_DEBUG("entry:"); + + bool result = false; + + { + std::unique_lock lock{m_queueSizeMutex}; + m_queueSizeCv.wait(lock, [&]() { return m_dataBuffers.size() < kMaxQueueSize; }); + } + + m_backendQueue->callInEventLoop( + [&]() + { + if (buf) + { + if (m_pushSamplesTimer) + { + m_pushSamplesTimer->cancel(); + m_pushSamplesTimer.reset(); + } + { + std::unique_lock lock{m_queueSizeMutex}; + m_dataBuffers.push(buf); + } + pushSamples(); + result = true; + } + }); + + return result; +} + +void GStreamerWebAudioPlayerClient::pushSamples() +{ + GST_DEBUG("entry:"); + if (!m_isOpen || m_dataBuffers.empty()) + { + return; + } + + uint32_t availableFrames = 0u; + do + { + if (!m_clientBackend->getBufferAvailable(availableFrames)) + { + GST_ERROR("getBufferAvailable failed, could not process the samples"); + // clear the queue if getBufferAvailable failed + std::queue empty; + std::unique_lock lock{m_queueSizeMutex}; + std::swap(m_dataBuffers, empty); + m_queueSizeCv.notify_one(); + } + else if (0 != availableFrames) + { + bool writeFailure = false; + GstBuffer *buffer = m_dataBuffers.front(); + gsize bufferSize = gst_buffer_get_size(buffer); + auto framesToWrite = std::min(availableFrames, static_cast(bufferSize / m_frameSize)); + if (framesToWrite > 0) + { + GstMapInfo bufferMap; + if (!gst_buffer_map(buffer, &bufferMap, GST_MAP_READ)) + { + GST_ERROR("Could not map audio buffer, discarding buffer!"); + writeFailure = true; + } + else + { + if (!m_clientBackend->writeBuffer(framesToWrite, bufferMap.data)) + { + GST_ERROR("Could not map audio buffer, discarding buffer!"); + writeFailure = true; + } + gst_buffer_unmap(buffer, &bufferMap); + } + } + + if ((!writeFailure) && (framesToWrite * m_frameSize < bufferSize)) + { + // Handle any leftover data + uint32_t leftoverData = bufferSize - (availableFrames * m_frameSize); + gst_buffer_resize(buffer, framesToWrite * m_frameSize, leftoverData); + if ((leftoverData / m_frameSize == 0) && (m_dataBuffers.size() > 1)) + { + // If the leftover data is smaller than a frame, it must be processed with the next buffer + std::unique_lock lock{m_queueSizeMutex}; + m_dataBuffers.pop(); + m_dataBuffers.front() = gst_buffer_append(buffer, m_dataBuffers.front()); + gst_buffer_unref(buffer); + m_queueSizeCv.notify_one(); + } + } + else + { + std::unique_lock lock{m_queueSizeMutex}; + m_dataBuffers.pop(); + gst_buffer_unref(buffer); + m_queueSizeCv.notify_one(); + } + } + } while (!m_dataBuffers.empty() && availableFrames != 0); + + // If we still have samples stored that could not be pushed + // This avoids any stoppages in the pushing of samples to the server if the consumption of + // samples is slow. + if (m_dataBuffers.size()) + { + m_pushSamplesTimer = + m_timerFactory->createTimer(std::chrono::milliseconds(10), [this]() { notifyPushSamplesTimerExpired(); }); + } + else if (m_isEos) + { + m_clientBackend->setEos(); + } +} + +bool GStreamerWebAudioPlayerClient::isNewConfig(const std::string &audioMimeType, + std::weak_ptr webAudioConfig) +{ + if (audioMimeType != m_mimeType) + { + return true; + } + + if (audioMimeType != "audio/x-raw") + { + GST_ERROR("Cannot compare none pcm config"); + return true; + } + + std::shared_ptr config = webAudioConfig.lock(); + if (!config || config->pcm != m_config.pcm) + { + return true; + } + + return false; +} + +void GStreamerWebAudioPlayerClient::notifyState(firebolt::rialto::WebAudioPlayerState state) +{ + switch (state) + { + case firebolt::rialto::WebAudioPlayerState::END_OF_STREAM: + { + GST_INFO("Notify end of stream."); + m_delegate.handleEos(); + m_isEos = false; + break; + } + case firebolt::rialto::WebAudioPlayerState::FAILURE: + { + std::string errMessage = "Rialto server webaudio playback failed"; + GST_ERROR("%s", errMessage.c_str()); + m_delegate.handleError(errMessage); + break; + } + case firebolt::rialto::WebAudioPlayerState::IDLE: + { + m_delegate.handleStateChanged(firebolt::rialto::PlaybackState::IDLE); + break; + } + case firebolt::rialto::WebAudioPlayerState::PLAYING: + { + m_delegate.handleStateChanged(firebolt::rialto::PlaybackState::PLAYING); + break; + } + case firebolt::rialto::WebAudioPlayerState::PAUSED: + { + m_delegate.handleStateChanged(firebolt::rialto::PlaybackState::PAUSED); + break; + } + case firebolt::rialto::WebAudioPlayerState::UNKNOWN: + default: + { + GST_WARNING("Web audio player sent unknown state"); + break; + } + } +} + +bool GStreamerWebAudioPlayerClient::setVolume(double volume) +{ + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setVolume(volume); }); + return status; +} + +bool GStreamerWebAudioPlayerClient::getVolume(double &volume) +{ + bool status{false}; + m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getVolume(volume); }); + return status; +} diff --git a/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.h b/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.h new file mode 100644 index 000000000..9aea04049 --- /dev/null +++ b/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.h @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "Constants.h" +#include "IMessageQueue.h" +#include "IPlaybackDelegate.h" +#include "ITimer.h" +#include "MediaCommon.h" +#include "WebAudioClientBackendInterface.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +class GStreamerWebAudioPlayerClient : public firebolt::rialto::IWebAudioPlayerClient, + public std::enable_shared_from_this +{ +public: + /** + * @brief Constructor. + * + * @param[in] callbacks : The callbacks for the sink. + */ + GStreamerWebAudioPlayerClient( + std::unique_ptr &&webAudioClientBackend, + std::unique_ptr &&backendQueue, IPlaybackDelegate &delegate, + std::shared_ptr timerFactory); + + /** + * @brief Destructor. + */ + virtual ~GStreamerWebAudioPlayerClient(); + + /** + * @brief Extracts the sample info from the gstreamer capabilities + * and opens the web audio. + * + * @param[in] caps : Sample gstreamer capabilities. + * + * @retval true on success. + */ + bool open(GstCaps *caps); + + /** + * @brief Closes the web audio player. + * + * @retval true on success. + */ + bool close(); + + /** + * @brief Play the web audio. + * + * @retval true on success. + */ + bool play(); + + /** + * @brief Pause the web audio. + * + * @retval true on success. + */ + bool pause(); + + /** + * @brief Notify EOS. + * + * @retval true on success. + */ + bool setEos(); + + /** + * @brief Get the volume. + * + * @param[out] volume : The volume level + * + * @retval true on success. + */ + bool getVolume(double &volume); + + /** + * @brief Set the volume. + * + * @param[in] volume : The volume level + * + * @retval true on success. + */ + bool setVolume(double volume); + + /** + * @brief Whether the backend has been opened or not. + * + * @retval true if open. + */ + bool isOpen(); + + /** + * @brief Notifies that there is a new sample in gstreamer. + * + * @param[in] buf : The new sample buffer. + * + * @retval true on success. + */ + bool notifyNewSample(GstBuffer *buf); + + /** + * @brief Notify push sample timer expiry. + */ + void notifyPushSamplesTimerExpired(); + + /** + * @brief Implements the player state change notification. + * + * @param[in] state : The new playback state. + */ + void notifyState(firebolt::rialto::WebAudioPlayerState state) override; + +private: + /** + * @brief Perform the next push operation. + * + * The samples are pushed only when there is the available buffer + * in RialtoServer. + */ + void pushSamples(); + + /** + * @brief Checks the config against that previously stored in the object. + * + * @retval true if this is a new config. + */ + bool isNewConfig(const std::string &audioMimeType, std::weak_ptr config); + + /** + * @brief Backend message queue. + */ + std::unique_ptr m_backendQueue; + + /** + * @brief The web audio client backend interface. + */ + std::unique_ptr m_clientBackend; + + /** + * @brief Whether the web audio backend is currently open. + */ + std::atomic m_isOpen; + + /** + * @brief Vector to store the gst sample buffers. + */ + std::queue m_dataBuffers; + + /** + * @brief The timer factory. + */ + std::shared_ptr m_timerFactory; + + /** + * @brief The push samples timer. + */ + std::unique_ptr m_pushSamplesTimer; + + /** + * @brief The preferred number of frames to be written. + */ + uint32_t m_preferredFrames; + + /** + * @brief The maximum number of frames that can be written. + */ + uint32_t m_maximumFrames; + + /** + * @brief Whether defered play is supported. + */ + bool m_supportDeferredPlay; + + /** + * @brief Whether the sink element has received EOS. + */ + bool m_isEos; + + /** + * @brief The number of bytes in the frame. + */ + uint32_t m_frameSize; + + /** + * @brief The mutex protecting m_dataBuffers size reads + */ + std::mutex m_queueSizeMutex; + + /** + * @brief The condition variable used to block webaudio chain function + * when m_dataBuffers queue size is too large + */ + std::condition_variable m_queueSizeCv; + + /** + * @brief The current web audio player mime type. + */ + std::string m_mimeType; + + /** + * @brief The current web audio player config. + */ + firebolt::rialto::WebAudioConfig m_config; + + /** + * @brief The reference to delegate object. + */ + IPlaybackDelegate &m_delegate; +}; diff --git a/middleware/rialto-gstreamer/source/GstreamerCatLog.cpp b/middleware/rialto-gstreamer/source/GstreamerCatLog.cpp new file mode 100644 index 000000000..911d0c8d9 --- /dev/null +++ b/middleware/rialto-gstreamer/source/GstreamerCatLog.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2024 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "GstreamerCatLog.h" +#include + +GST_DEBUG_CATEGORY(rialtoGStreamerCat); diff --git a/middleware/rialto-gstreamer/source/GstreamerCatLog.h b/middleware/rialto-gstreamer/source/GstreamerCatLog.h new file mode 100644 index 000000000..9940113cc --- /dev/null +++ b/middleware/rialto-gstreamer/source/GstreamerCatLog.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef GSTREAMER_CAT_LOG_H +#define GSTREAMER_CAT_LOG_H + +#include + +GST_DEBUG_CATEGORY_EXTERN(rialtoGStreamerCat); + +inline void init_gst_debug_category() +{ + GST_DEBUG_CATEGORY_INIT(rialtoGStreamerCat, "rialtogstreamer", 0, "Messages from non-gstreamer objects"); +} + +#endif // GSTREAMER_CAT_LOG_H \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/IMessageQueue.h b/middleware/rialto-gstreamer/source/IMessageQueue.h new file mode 100644 index 000000000..1f956b8c8 --- /dev/null +++ b/middleware/rialto-gstreamer/source/IMessageQueue.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include +#include + +class Message +{ +public: + virtual ~Message() {} + virtual void handle() = 0; + virtual void skip() {}; +}; + +class IMessageQueue +{ +public: + virtual ~IMessageQueue() = default; + virtual void start() = 0; + virtual void stop() = 0; + virtual void clear() = 0; + virtual std::shared_ptr waitForMessage() = 0; + virtual bool postMessage(const std::shared_ptr &msg) = 0; + virtual void processMessages() = 0; + virtual bool scheduleInEventLoop(const std::function &func) = 0; + virtual bool callInEventLoop(const std::function &func) = 0; +}; + +class IMessageQueueFactory +{ +public: + virtual ~IMessageQueueFactory() = default; + static std::shared_ptr createFactory(); + virtual std::unique_ptr createMessageQueue() const = 0; +}; diff --git a/middleware/rialto-gstreamer/source/IPlaybackDelegate.h b/middleware/rialto-gstreamer/source/IPlaybackDelegate.h new file mode 100644 index 000000000..5c927d131 --- /dev/null +++ b/middleware/rialto-gstreamer/source/IPlaybackDelegate.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "GStreamerUtils.h" +#include "MediaCommon.h" +#include +#include +#include + +class IPlaybackDelegate +{ +public: + enum class Property + { + // PullModePlaybackDelegate Properties + IsSinglePathStream, + NumberOfStreams, + HasDrm, + Stats, + + // PullModeAudioPlaybackDelegate Properties + Volume, + Mute, + Gap, + LowLatency, + Sync, + SyncOff, + StreamSyncMode, + AudioFade, + FadeVolume, + LimitBufferingMs, + UseBuffering, + Async, + + // PullModeVideoPlaybackDelegate Properties + WindowSet, + MaxVideoWidth, + MaxVideoHeight, + FrameStepOnPreroll, + ImmediateOutput, + SyncmodeStreaming, + ShowVideoWindow, + + // PullModeSubtitlePlaybackDelegate Properties + TextTrackIdentifier, + WindowId, + + // PushModeAudioPlaybackDelegate Properties + TsOffset, + }; + + IPlaybackDelegate() = default; + virtual ~IPlaybackDelegate() = default; + + IPlaybackDelegate(const IPlaybackDelegate &) = delete; + IPlaybackDelegate(IPlaybackDelegate &&) = delete; + IPlaybackDelegate &operator=(const IPlaybackDelegate &) = delete; + IPlaybackDelegate &operator=(IPlaybackDelegate &&) = delete; + + virtual void handleEos() = 0; + virtual void handleStateChanged(firebolt::rialto::PlaybackState state) = 0; + virtual void handleError(const std::string &message, gint code = 0) = 0; + virtual void handleQos(uint64_t processed, uint64_t dropped) const = 0; + + virtual GstStateChangeReturn changeState(GstStateChange transition) = 0; + virtual void postAsyncStart() = 0; + virtual void setProperty(const Property &type, const GValue *value) = 0; + virtual void getProperty(const Property &type, GValue *value) = 0; + virtual std::optional handleQuery(GstQuery *query) const = 0; + virtual gboolean handleSendEvent(GstEvent *event) = 0; + virtual gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) = 0; + virtual GstFlowReturn handleBuffer(GstBuffer *buffer) = 0; +}; diff --git a/middleware/rialto-gstreamer/source/IPullModePlaybackDelegate.h b/middleware/rialto-gstreamer/source/IPullModePlaybackDelegate.h new file mode 100644 index 000000000..a60f36f71 --- /dev/null +++ b/middleware/rialto-gstreamer/source/IPullModePlaybackDelegate.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "IPlaybackDelegate.h" + +class IPullModePlaybackDelegate : public IPlaybackDelegate +{ +public: + IPullModePlaybackDelegate() = default; + ~IPullModePlaybackDelegate() override = default; + + IPullModePlaybackDelegate(const IPullModePlaybackDelegate &) = delete; + IPullModePlaybackDelegate(IPullModePlaybackDelegate &&) = delete; + IPullModePlaybackDelegate &operator=(const IPullModePlaybackDelegate &) = delete; + IPullModePlaybackDelegate &operator=(IPullModePlaybackDelegate &&) = delete; + + virtual void setSourceId(int32_t sourceId) = 0; + virtual void handleFlushCompleted() = 0; + virtual GstRefSample getFrontSample() const = 0; + virtual void popSample() = 0; + virtual bool isEos() const = 0; + virtual void lostState() = 0; + virtual bool isReadyToSendData() const = 0; +}; diff --git a/middleware/rialto-gstreamer/source/ITimer.h b/middleware/rialto-gstreamer/source/ITimer.h new file mode 100644 index 000000000..3947634e6 --- /dev/null +++ b/middleware/rialto-gstreamer/source/ITimer.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef I_TIMER_H_ +#define I_TIMER_H_ + +#include +#include +#include + +class ITimer; + +enum class TimerType +{ + ONE_SHOT, + PERIODIC +}; + +/** + * @brief ITimerFactory factory class, returns a concrete implementation of ITimer + */ +class ITimerFactory +{ +public: + ITimerFactory() = default; + virtual ~ITimerFactory() = default; + + /** + * @brief Gets the ITimerFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Creates an ITimer object. + * + * @param[in] timeout : Timeout after which callback will be called + * @param[in] callback : Function which is called after timeout + * @param[in] timerType : Type of timer + * + * @retval the new timer instance or null on error. + */ + virtual std::unique_ptr createTimer(const std::chrono::milliseconds &timeout, + const std::function &callback, + TimerType timerType = TimerType::ONE_SHOT) const = 0; +}; + +class ITimer +{ +public: + ITimer() = default; + virtual ~ITimer() = default; + + ITimer(const ITimer &) = delete; + ITimer &operator=(const ITimer &) = delete; + ITimer(ITimer &&) = delete; + ITimer &operator=(ITimer &&) = delete; + + /** + * @brief Cancels the timer + */ + virtual void cancel() = 0; + + /** + * @brief Checks if timer is active + * + * @retval true if timer is active, false otherwise + */ + virtual bool isActive() const = 0; +}; + +#endif // I_TIMER_H_ diff --git a/middleware/rialto-gstreamer/source/LogToGstHandler.cpp b/middleware/rialto-gstreamer/source/LogToGstHandler.cpp new file mode 100644 index 000000000..b7bbf77fa --- /dev/null +++ b/middleware/rialto-gstreamer/source/LogToGstHandler.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2024 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// +// This allows, for example, passing the following environment variable +// to the client app which will enable rialto logging via gstreamer... +// GST_DEBUG=6 +// + +#include + +#include "LogToGstHandler.h" + +#ifdef USE_ETHANLOG + +#include + +#define SYSTEM_LOG_FATAL(filename, function, line, ...) ethanlog(ETHAN_LOG_FATAL, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_ERROR(filename, function, line, ...) ethanlog(ETHAN_LOG_ERROR, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_WARN(filename, function, line, ...) \ + ethanlog(ETHAN_LOG_WARNING, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_MIL(filename, function, line, ...) \ + ethanlog(ETHAN_LOG_MILESTONE, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_INFO(filename, function, line, ...) ethanlog(ETHAN_LOG_INFO, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_DEBUG(filename, function, line, ...) ethanlog(ETHAN_LOG_DEBUG, filename, function, line, __VA_ARGS__) + +#else + +#include + +#define SYSTEM_LOG_FATAL(filename, function, line, ...) GST_CAT_ERROR(kGstRialtoCategory, __VA_ARGS__) +#define SYSTEM_LOG_ERROR(filename, function, line, ...) GST_CAT_ERROR(kGstRialtoCategory, __VA_ARGS__) +#define SYSTEM_LOG_WARN(filename, function, line, ...) GST_CAT_WARNING(kGstRialtoCategory, __VA_ARGS__) +#define SYSTEM_LOG_MIL(filename, function, line, ...) GST_CAT_INFO(kGstRialtoCategory, __VA_ARGS__) +#define SYSTEM_LOG_INFO(filename, function, line, ...) GST_CAT_INFO(kGstRialtoCategory, __VA_ARGS__) +#define SYSTEM_LOG_DEBUG(filename, function, line, ...) GST_CAT_DEBUG(kGstRialtoCategory, __VA_ARGS__) + +namespace +{ +GST_DEBUG_CATEGORY_STATIC(kGstRialtoCategory); +const char *kCategory = "rialto"; +}; // namespace + +#endif + +using namespace firebolt::rialto; + +LogToGstHandler::LogToGstHandler() +{ +#ifndef USE_ETHANLOG + GST_DEBUG_CATEGORY_INIT(kGstRialtoCategory, kCategory, 0, "Messages from rialto client library"); +#endif +} + +LogToGstHandler::~LogToGstHandler() {} + +void LogToGstHandler::log(Level level, const std::string &file, int line, const std::string &function, + const std::string &message) +{ + std::string toReport; + toReport += "M:" + file; + toReport += " F:" + function; + toReport += " L:" + std::to_string(line); + toReport += " > " + message; + + switch (level) + { + case Level::Fatal: + SYSTEM_LOG_FATAL(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); + break; + + case Level::Error: + SYSTEM_LOG_ERROR(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); + break; + + case Level::Warning: + SYSTEM_LOG_WARN(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); + break; + + case Level::Milestone: + SYSTEM_LOG_MIL(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); + break; + + case Level::Info: + SYSTEM_LOG_INFO(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); + break; + + case Level::Debug: + SYSTEM_LOG_DEBUG(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); + break; + + case Level::External: + default: + SYSTEM_LOG_INFO(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); + break; + } +} diff --git a/middleware/rialto-gstreamer/source/LogToGstHandler.h b/middleware/rialto-gstreamer/source/LogToGstHandler.h new file mode 100644 index 000000000..f73d541f6 --- /dev/null +++ b/middleware/rialto-gstreamer/source/LogToGstHandler.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2024 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef FIREBOLT_RIALTO_LOG_HANDLER_H_ +#define FIREBOLT_RIALTO_LOG_HANDLER_H_ + +#include "IClientLogHandler.h" + +namespace firebolt::rialto +{ +class LogToGstHandler : public IClientLogHandler +{ +public: + LogToGstHandler(); + ~LogToGstHandler(); + + void log(Level level, const std::string &file, int line, const std::string &function, const std::string &message); +}; +} // namespace firebolt::rialto +#endif // FIREBOLT_RIALTO_RIALTO_LOG_HANDLER_H_ diff --git a/middleware/rialto-gstreamer/source/MediaPlayerClientBackend.h b/middleware/rialto-gstreamer/source/MediaPlayerClientBackend.h new file mode 100644 index 000000000..8f9164c09 --- /dev/null +++ b/middleware/rialto-gstreamer/source/MediaPlayerClientBackend.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "MediaPlayerClientBackendInterface.h" +#include +#include +#include + +namespace firebolt::rialto::client +{ +class MediaPlayerClientBackend final : public MediaPlayerClientBackendInterface +{ +public: + MediaPlayerClientBackend() : m_mediaPlayerBackend(nullptr) {} + ~MediaPlayerClientBackend() final { m_mediaPlayerBackend.reset(); } + + void createMediaPlayerBackend(std::weak_ptr client, uint32_t maxWidth, uint32_t maxHeight) override + { + firebolt::rialto::VideoRequirements videoRequirements; + videoRequirements.maxWidth = maxWidth; + videoRequirements.maxHeight = maxHeight; + + m_mediaPlayerBackend = + firebolt::rialto::IMediaPipelineFactory::createFactory()->createMediaPipeline(client, videoRequirements); + + if (!m_mediaPlayerBackend) + { + GST_ERROR("Could not create media player backend"); + return; + } + } + + bool isMediaPlayerBackendCreated() const override { return static_cast(m_mediaPlayerBackend); } + + bool attachSource(std::unique_ptr &source) override + { + return m_mediaPlayerBackend->attachSource(source); + } + + bool removeSource(int32_t id) override { return m_mediaPlayerBackend->removeSource(id); } + + bool allSourcesAttached() override { return m_mediaPlayerBackend->allSourcesAttached(); } + + bool load(firebolt::rialto::MediaType type, const std::string &mimeType, const std::string &url) override + { + return m_mediaPlayerBackend->load(type, mimeType, url); + } + + bool play() override { return m_mediaPlayerBackend->play(); } + bool pause() override { return m_mediaPlayerBackend->pause(); } + bool stop() override { return m_mediaPlayerBackend->stop(); } + bool haveData(firebolt::rialto::MediaSourceStatus status, unsigned int needDataRequestId) override + { + return m_mediaPlayerBackend->haveData(status, needDataRequestId); + } + bool setPlaybackRate(double rate) override { return m_mediaPlayerBackend->setPlaybackRate(rate); } + bool setVideoWindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height) override + { + return m_mediaPlayerBackend->setVideoWindow(x, y, width, height); + } + + firebolt::rialto::AddSegmentStatus + addSegment(unsigned int needDataRequestId, + const std::unique_ptr &mediaSegment) override + { + return m_mediaPlayerBackend->addSegment(needDataRequestId, mediaSegment); + } + + bool getPosition(int64_t &position) override { return m_mediaPlayerBackend->getPosition(position); } + + bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override + { + return m_mediaPlayerBackend->setImmediateOutput(sourceId, immediateOutput); + } + + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override + { + return m_mediaPlayerBackend->getImmediateOutput(sourceId, immediateOutput); + } + + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override + { + return m_mediaPlayerBackend->getStats(sourceId, renderedFrames, droppedFrames); + } + + bool renderFrame() override { return m_mediaPlayerBackend->renderFrame(); } + + bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override + { + return m_mediaPlayerBackend->setVolume(targetVolume, volumeDuration, easeType); + } + + bool getVolume(double ¤tVolume) override { return m_mediaPlayerBackend->getVolume(currentVolume); } + + bool setMute(bool mute, int sourceId) override { return m_mediaPlayerBackend->setMute(sourceId, mute); } + + bool getMute(bool &mute, int sourceId) override { return m_mediaPlayerBackend->getMute(sourceId, mute); } + + bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override + { + return m_mediaPlayerBackend->setTextTrackIdentifier(textTrackIdentifier); + } + + bool getTextTrackIdentifier(std::string &textTrackIdentifier) override + { + return m_mediaPlayerBackend->getTextTrackIdentifier(textTrackIdentifier); + } + + bool setLowLatency(bool lowLatency) override { return m_mediaPlayerBackend->setLowLatency(lowLatency); } + + bool setSync(bool sync) override { return m_mediaPlayerBackend->setSync(sync); } + + bool getSync(bool &sync) override { return m_mediaPlayerBackend->getSync(sync); } + + bool setSyncOff(bool syncOff) override { return m_mediaPlayerBackend->setSyncOff(syncOff); } + + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override + { + return m_mediaPlayerBackend->setStreamSyncMode(sourceId, streamSyncMode); + } + + bool getStreamSyncMode(int32_t &streamSyncMode) override + { + return m_mediaPlayerBackend->getStreamSyncMode(streamSyncMode); + } + + bool flush(int32_t sourceId, bool resetTime, bool &async) override + { + return m_mediaPlayerBackend->flush(sourceId, resetTime, async); + } + + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate = 1.0, + uint64_t stopPosition = GST_CLOCK_TIME_NONE) override + { + return m_mediaPlayerBackend->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition); + } + + bool setSubtitleOffset(int32_t sourceId, int64_t position) override + { + return m_mediaPlayerBackend->setSubtitleOffset(sourceId, position); + } + + + bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override + { + return m_mediaPlayerBackend->processAudioGap(position, duration, discontinuityGap, audioAac); + } + + bool setBufferingLimit(uint32_t limitBufferingMs) override + { + return m_mediaPlayerBackend->setBufferingLimit(limitBufferingMs); + } + + bool getBufferingLimit(uint32_t &limitBufferingMs) override + { + return m_mediaPlayerBackend->getBufferingLimit(limitBufferingMs); + } + + bool setUseBuffering(bool useBuffering) override { return m_mediaPlayerBackend->setUseBuffering(useBuffering); } + + bool getUseBuffering(bool &useBuffering) override { return m_mediaPlayerBackend->getUseBuffering(useBuffering); } + + bool switchSource(const std::unique_ptr &source) override + { + return m_mediaPlayerBackend->switchSource(source); + } + +private: + std::unique_ptr m_mediaPlayerBackend; +}; +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/MediaPlayerClientBackendInterface.h b/middleware/rialto-gstreamer/source/MediaPlayerClientBackendInterface.h new file mode 100644 index 000000000..4206581e9 --- /dev/null +++ b/middleware/rialto-gstreamer/source/MediaPlayerClientBackendInterface.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include +#include + +#include + +namespace firebolt::rialto::client +{ +class MediaPlayerClientBackendInterface +{ +public: + virtual ~MediaPlayerClientBackendInterface() = default; + virtual void createMediaPlayerBackend(std::weak_ptr client, uint32_t maxWidth, + uint32_t maxHeight) = 0; + virtual bool isMediaPlayerBackendCreated() const = 0; + virtual bool attachSource(std::unique_ptr &source) = 0; + virtual bool removeSource(int32_t id) = 0; + virtual bool allSourcesAttached() = 0; + virtual bool load(firebolt::rialto::MediaType type, const std::string &mimeType, const std::string &url) = 0; + virtual bool play() = 0; + virtual bool pause() = 0; + virtual bool stop() = 0; + virtual bool haveData(firebolt::rialto::MediaSourceStatus status, unsigned int needDataRequestId) = 0; + virtual bool setPlaybackRate(double rate) = 0; + virtual bool setVideoWindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height) = 0; + virtual firebolt::rialto::AddSegmentStatus + addSegment(unsigned int needDataRequestId, + const std::unique_ptr &mediaSegment) = 0; + virtual bool getPosition(int64_t &position) = 0; + virtual bool setImmediateOutput(int32_t sourceId, bool immediateOutput) = 0; + virtual bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) = 0; + virtual bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; + virtual bool renderFrame() = 0; + virtual bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) = 0; + virtual bool getVolume(double ¤tVolume) = 0; + virtual bool setMute(bool mute, int sourceId) = 0; + virtual bool getMute(bool &mute, int sourceId) = 0; + virtual bool setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; + virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; + virtual bool setLowLatency(bool lowLatency) = 0; + virtual bool setSync(bool sync) = 0; + virtual bool getSync(bool &sync) = 0; + virtual bool setSyncOff(bool syncOff) = 0; + virtual bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) = 0; + virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; + virtual bool flush(int32_t sourceId, bool resetTime, bool &async) = 0; + virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate = 1.0, + uint64_t stopPosition = GST_CLOCK_TIME_NONE) = 0; + virtual bool setSubtitleOffset(int32_t sourceId, int64_t position) = 0; + virtual bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; + virtual bool setBufferingLimit(uint32_t limitBufferingMs) = 0; + virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; + virtual bool setUseBuffering(bool useBuffering) = 0; + virtual bool getUseBuffering(bool &useBuffering) = 0; + virtual bool switchSource(const std::unique_ptr &source) = 0; +}; +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/MediaPlayerManager.cpp b/middleware/rialto-gstreamer/source/MediaPlayerManager.cpp new file mode 100644 index 000000000..2c7d8c63f --- /dev/null +++ b/middleware/rialto-gstreamer/source/MediaPlayerManager.cpp @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "MediaPlayerManager.h" +#include "GstreamerCatLog.h" +#include "IMessageQueue.h" +#include "MediaPlayerClientBackend.h" + +std::mutex MediaPlayerManager::m_mediaPlayerClientsMutex; +std::map MediaPlayerManager::m_mediaPlayerClientsInfo; +#define GST_CAT_DEFAULT rialtoGStreamerCat +MediaPlayerManager::MediaPlayerManager() : m_currentGstBinParent(nullptr) {} + +MediaPlayerManager::~MediaPlayerManager() +{ + releaseMediaPlayerClient(); +} + +bool MediaPlayerManager::attachMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth, + const uint32_t maxVideoHeight) +{ + if (!m_client.lock()) + { + createMediaPlayerClient(gstBinParent, maxVideoWidth, maxVideoHeight); + } + else if (gstBinParent != m_currentGstBinParent) + { + // New parent gst bin, release old client and create new + releaseMediaPlayerClient(); + createMediaPlayerClient(gstBinParent, maxVideoWidth, maxVideoHeight); + } + + if (!m_client.lock()) + { + GST_ERROR("Failed to attach the media player client"); + return false; + } + else + { + return true; + } +} + +std::shared_ptr MediaPlayerManager::getMediaPlayerClient() const +{ + return m_client.lock(); +} + +bool MediaPlayerManager::hasControl() +{ + if (m_client.lock()) + { + std::lock_guard guard(m_mediaPlayerClientsMutex); + + auto it = m_mediaPlayerClientsInfo.find(m_currentGstBinParent); + if (it != m_mediaPlayerClientsInfo.end()) + { + if (it->second.controller == this) + { + return true; + } + else + { // in case there's no controller anymore + return acquireControl(it->second); + } + } + else + { + GST_WARNING("Could not find the attached media player client"); + } + } + else + { + GST_WARNING("No media player client attached"); + } + + return false; +} + +void MediaPlayerManager::releaseMediaPlayerClient() +{ + if (m_client.lock()) + { + std::lock_guard guard(m_mediaPlayerClientsMutex); + + auto it = m_mediaPlayerClientsInfo.find(m_currentGstBinParent); + if (it != m_mediaPlayerClientsInfo.end()) + { + it->second.refCount--; + if (it->second.refCount == 0) + { + it->second.client->stop(); + it->second.client->stopStreaming(); + it->second.client->destroyClientBackend(); + m_mediaPlayerClientsInfo.erase(it); + } + else + { + if (it->second.controller == this) + it->second.controller = nullptr; + } + m_client.reset(); + m_currentGstBinParent = nullptr; + } + else + { + GST_ERROR("Could not find the attached media player client"); + } + } +} + +bool MediaPlayerManager::acquireControl(MediaPlayerClientInfo &mediaPlayerClientInfo) +{ + if (mediaPlayerClientInfo.controller == nullptr) + { + mediaPlayerClientInfo.controller = this; + return true; + } + + return false; +} + +void MediaPlayerManager::createMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth, + const uint32_t maxVideoHeight) +{ + std::lock_guard guard(m_mediaPlayerClientsMutex); + + auto it = m_mediaPlayerClientsInfo.find(gstBinParent); + if (it != m_mediaPlayerClientsInfo.end()) + { + it->second.refCount++; + m_client = it->second.client; + m_currentGstBinParent = gstBinParent; + } + else + { + std::shared_ptr clientBackend = + std::make_shared(); + std::shared_ptr client = + std::make_shared(IMessageQueueFactory::createFactory(), clientBackend, + maxVideoWidth, maxVideoHeight); + + if (client->createBackend()) + { + // Store the new client in global map + MediaPlayerClientInfo newClientInfo; + newClientInfo.client = client; + newClientInfo.controller = this; + newClientInfo.refCount = 1; + m_mediaPlayerClientsInfo.insert( + std::pair(gstBinParent, newClientInfo)); + + // Store client info in object + m_client = client; + m_currentGstBinParent = gstBinParent; + } + else + { + GST_ERROR("Failed to create the media player client backend"); + return; + } + } +} diff --git a/middleware/rialto-gstreamer/source/MediaPlayerManager.h b/middleware/rialto-gstreamer/source/MediaPlayerManager.h new file mode 100644 index 000000000..a2272f6ec --- /dev/null +++ b/middleware/rialto-gstreamer/source/MediaPlayerManager.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MEDIAPLAYERMANAGER_H +#define MEDIAPLAYERMANAGER_H + +#include "GStreamerMSEMediaPlayerClient.h" +#include + +class MediaPlayerManager +{ +public: + MediaPlayerManager(); + ~MediaPlayerManager(); + + std::shared_ptr getMediaPlayerClient() const; + bool attachMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth = 0, + const uint32_t maxVideoHeight = 0); + void releaseMediaPlayerClient(); + bool hasControl(); + +private: + struct MediaPlayerClientInfo + { + std::shared_ptr client; + void *controller; + uint32_t refCount; + }; + + void createMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth, + const uint32_t maxVideoHeight); + bool acquireControl(MediaPlayerClientInfo &mediaPlayerClientInfo); + + std::weak_ptr m_client; + const GstObject *m_currentGstBinParent; + + static std::mutex m_mediaPlayerClientsMutex; + static std::map m_mediaPlayerClientsInfo; +}; + +#endif // MEDIAPLAYERMANAGER_H \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/MessageQueue.cpp b/middleware/rialto-gstreamer/source/MessageQueue.cpp new file mode 100644 index 000000000..40ab2b87b --- /dev/null +++ b/middleware/rialto-gstreamer/source/MessageQueue.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "MessageQueue.h" +#include "GstreamerCatLog.h" +#define GST_CAT_DEFAULT rialtoGStreamerCat +CallInEventLoopMessage::CallInEventLoopMessage(const std::function &func) : m_func(func), m_done{false} {} + +void CallInEventLoopMessage::handle() +{ + std::unique_lock lock(m_callInEventLoopMutex); + m_func(); + m_done = true; + m_callInEventLoopCondVar.notify_all(); +} + +void CallInEventLoopMessage::skip() +{ + std::unique_lock lock(m_callInEventLoopMutex); + m_done = true; + m_callInEventLoopCondVar.notify_all(); +} + +void CallInEventLoopMessage::wait() +{ + std::unique_lock lock(m_callInEventLoopMutex); + m_callInEventLoopCondVar.wait(lock, [this]() { return m_done; }); +} + +ScheduleInEventLoopMessage::ScheduleInEventLoopMessage(const std::function &func) : m_func(func) {} + +void ScheduleInEventLoopMessage::handle() +{ + m_func(); +} + +std::shared_ptr IMessageQueueFactory::createFactory() +{ + return std::make_shared(); +} + +std::unique_ptr MessageQueueFactory::createMessageQueue() const +{ + return std::make_unique(); +} + +namespace rialto +{ +MessageQueue::MessageQueue() : m_running(false) {} + +MessageQueue::~MessageQueue() +{ + doStop(); +} + +void MessageQueue::start() +{ + if (m_running) + { + // queue is running + return; + } + m_running = true; + std::thread startThread(&MessageQueue::processMessages, this); + m_workerThread.swap(startThread); +} + +void MessageQueue::stop() +{ + doStop(); +} + +void MessageQueue::clear() +{ + doClear(); +} + +std::shared_ptr MessageQueue::waitForMessage() +{ + std::unique_lock lock(m_mutex); + while (m_queue.empty()) + { + m_condVar.wait(lock); + } + std::shared_ptr message = m_queue.front(); + m_queue.pop_front(); + return message; +} + +bool MessageQueue::postMessage(const std::shared_ptr &msg) +{ + const std::lock_guard lock(m_mutex); + if (!m_running) + { + GST_ERROR("Message queue is not running"); + return false; + } + m_queue.push_back(msg); + m_condVar.notify_all(); + + return true; +} + +void MessageQueue::processMessages() +{ + do + { + std::shared_ptr message = waitForMessage(); + message->handle(); + } while (m_running); +} + +bool MessageQueue::scheduleInEventLoop(const std::function &func) +{ + auto message = std::make_shared(func); + if (!postMessage(message)) + { + return false; + } + + return true; +} + +bool MessageQueue::callInEventLoop(const std::function &func) +{ + return callInEventLoopInternal(func); +} + +bool MessageQueue::callInEventLoopInternal(const std::function &func) +{ + if (std::this_thread::get_id() != m_workerThread.get_id()) + { + auto message = std::make_shared(func); + if (!postMessage(message)) + { + return false; + } + message->wait(); + } + else + { + func(); + } + + return true; +} + +void MessageQueue::doStop() +{ + if (!m_running) + { + // queue is not running + return; + } + callInEventLoopInternal([this]() { m_running = false; }); + + if (m_workerThread.joinable()) + m_workerThread.join(); + + doClear(); +} + +void MessageQueue::doClear() +{ + std::unique_lock lock(m_mutex); + while (!m_queue.empty()) + { + m_queue.front()->skip(); + m_queue.pop_front(); + } +} +} // namespace rialto diff --git a/middleware/rialto-gstreamer/source/MessageQueue.h b/middleware/rialto-gstreamer/source/MessageQueue.h new file mode 100644 index 000000000..f6d22538a --- /dev/null +++ b/middleware/rialto-gstreamer/source/MessageQueue.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "IMessageQueue.h" +#include +#include +#include +#include +#include +#include +#include + +class CallInEventLoopMessage : public Message +{ +public: + explicit CallInEventLoopMessage(const std::function &func); + void handle() override; + void skip() override; + void wait(); + +private: + const std::function m_func; + std::mutex m_callInEventLoopMutex; + std::condition_variable m_callInEventLoopCondVar; + bool m_done; +}; + +class ScheduleInEventLoopMessage : public Message +{ +public: + explicit ScheduleInEventLoopMessage(const std::function &func); + void handle() override; + +private: + const std::function m_func; +}; + +class MessageQueueFactory : public IMessageQueueFactory +{ +public: + std::unique_ptr createMessageQueue() const override; +}; +namespace rialto +{ +class MessageQueue : public IMessageQueue +{ +public: + MessageQueue(); + ~MessageQueue(); + + void start() override; + void stop() override; + void clear() override; + // Wait for a message to appear on the queue. + std::shared_ptr waitForMessage() override; + // Posts a message to the queue. + bool postMessage(const std::shared_ptr &msg) override; + void processMessages() override; + bool scheduleInEventLoop(const std::function &func) override; + bool callInEventLoop(const std::function &func) override; + +protected: + void doStop(); + void doClear(); + // We need to have a non-virtual method, which can be called in class destructor + bool callInEventLoopInternal(const std::function &func); + +protected: + std::condition_variable m_condVar; + std::mutex m_mutex; + std::deque> m_queue; + std::thread m_workerThread; + bool m_running; +}; +} // namespace rialto diff --git a/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.cpp new file mode 100644 index 000000000..eee0f8693 --- /dev/null +++ b/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.cpp @@ -0,0 +1,715 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "PullModeAudioPlaybackDelegate.h" +#include "GStreamerMSEUtils.h" +#include "GstreamerCatLog.h" +#include +#include +#include + +#define GST_CAT_DEFAULT rialtoGStreamerCat + +namespace +{ +firebolt::rialto::EaseType convertCharToEaseType(char easeTypeChar) +{ + switch (easeTypeChar) + { + case 'L': + return firebolt::rialto::EaseType::EASE_LINEAR; + case 'I': + return firebolt::rialto::EaseType::EASE_IN_CUBIC; + case 'O': + return firebolt::rialto::EaseType::EASE_OUT_CUBIC; + default: + return firebolt::rialto::EaseType::EASE_LINEAR; + } +} +} // namespace + +PullModeAudioPlaybackDelegate::PullModeAudioPlaybackDelegate(GstElement *sink) : PullModePlaybackDelegate(sink) +{ + m_mediaSourceType = firebolt::rialto::MediaSourceType::AUDIO; +} + +GstStateChangeReturn PullModeAudioPlaybackDelegate::changeState(GstStateChange transition) +{ + switch (transition) + { + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + if (!attachToMediaClientAndSetStreamsNumber()) + { + return GST_STATE_CHANGE_FAILURE; + } + + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + GST_ERROR_OBJECT(m_sink, "MediaPlayerClient is nullptr"); + return GST_STATE_CHANGE_FAILURE; + } + if (m_isVolumeQueued) + { + client->setVolume(m_targetVolume, kDefaultVolumeDuration, kDefaultEaseType); + m_isVolumeQueued = false; + } + if (m_isAudioFadeQueued) + { + AudioFadeConfig audioFadeConfig; + { + std::lock_guard lock(m_audioFadeConfigMutex); + audioFadeConfig = m_audioFadeConfig; + } + client->setVolume(audioFadeConfig.volume, audioFadeConfig.duration, audioFadeConfig.easeType); + m_isAudioFadeQueued = false; + } + break; + } + default: + break; + } + return PullModePlaybackDelegate::changeState(transition); +} + +gboolean PullModeAudioPlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) +{ + switch (GST_EVENT_TYPE(event)) + { + case GST_EVENT_CAPS: + { + GstCaps *caps{nullptr}; + gst_event_parse_caps(event, &caps); + if (m_sourceAttached) + { + GST_INFO_OBJECT(m_sink, "Source already attached. Skip calling attachSource"); + break; + } + + GST_INFO_OBJECT(m_sink, "Attaching AUDIO source with caps %" GST_PTR_FORMAT, caps); + + std::unique_ptr asource = createMediaSource(caps); + if (asource) + { + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if ((!client) || (!client->attachSource(asource, RIALTO_MSE_BASE_SINK(m_sink), shared_from_this()))) + { + GST_ERROR_OBJECT(m_sink, "Failed to attach AUDIO source"); + } + else + { + m_sourceAttached = true; + + if (m_isMuteQueued) + { + client->setMute(m_mute, m_sourceId); + m_isMuteQueued = false; + } + if (m_isLowLatencyQueued) + { + if (!client->setLowLatency(m_lowLatency)) + { + GST_ERROR_OBJECT(m_sink, "Could not set queued low-latency"); + } + m_isLowLatencyQueued = false; + } + if (m_isSyncQueued) + { + if (!client->setSync(m_sync)) + { + GST_ERROR_OBJECT(m_sink, "Could not set queued sync"); + } + m_isSyncQueued = false; + } + if (m_isSyncOffQueued) + { + if (!client->setSyncOff(m_syncOff)) + { + GST_ERROR_OBJECT(m_sink, "Could not set queued sync-off"); + } + m_isSyncOffQueued = false; + } + if (m_isStreamSyncModeQueued) + { + if (!client->setStreamSyncMode(m_sourceId, m_streamSyncMode)) + { + GST_ERROR_OBJECT(m_sink, "Could not set queued stream-sync-mode"); + } + m_isStreamSyncModeQueued = false; + } + if (m_isBufferingLimitQueued) + { + client->setBufferingLimit(m_bufferingLimit); + m_isBufferingLimitQueued = false; + } + if (m_isUseBufferingQueued) + { + client->setUseBuffering(m_useBuffering); + m_isUseBufferingQueued = false; + } + // check if READY -> PAUSED was requested before source was attached + if (GST_STATE_NEXT(m_sink) == GST_STATE_PAUSED) + { + client->pause(m_sourceId); + } + } + } + else + { + GST_ERROR_OBJECT(m_sink, "Failed to create AUDIO source"); + } + break; + } + case GST_EVENT_CUSTOM_DOWNSTREAM: + case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: + { + if (gst_event_has_name(event, "switch-source")) + { + GST_DEBUG_OBJECT(m_sink, "Switch source event received"); + const GstStructure *structure{gst_event_get_structure(event)}; + const GValue *value = gst_structure_get_value(structure, "caps"); + if (!value) + { + GST_ERROR_OBJECT(m_sink, "Caps not available in switch-source event"); + break; + } + const GstCaps *caps = gst_value_get_caps(value); + GstCaps *mutableCaps = gst_caps_copy(caps); + std::unique_ptr asource = createMediaSource(mutableCaps); + gst_caps_unref(mutableCaps); + if (!asource) + { + GST_ERROR_OBJECT(m_sink, "Not able to parse caps"); + break; + } + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if ((!client) || (!client->switchSource(asource))) + { + GST_ERROR_OBJECT(m_sink, "Failed to switch AUDIO source"); + } + } + break; + } + default: + break; + } + return PullModePlaybackDelegate::handleEvent(pad, parent, event); +} + +void PullModeAudioPlaybackDelegate::getProperty(const Property &type, GValue *value) +{ + std::shared_ptr client{m_mediaPlayerManager.getMediaPlayerClient()}; + + switch (type) + { + case IPlaybackDelegate::Property::Volume: + { + double volume; + if (client) + { + if (client->getVolume(volume)) + m_targetVolume = volume; + else + volume = m_targetVolume; // Use last known volume + } + else + { + volume = m_targetVolume; + } + g_value_set_double(value, volume); + break; + } + case IPlaybackDelegate::Property::Mute: + { + if (!client) + { + g_value_set_boolean(value, m_mute); + return; + } + g_value_set_boolean(value, client->getMute(m_sourceId)); + break; + } + case IPlaybackDelegate::Property::Sync: + { + if (!client) + { + g_value_set_boolean(value, m_sync); + return; + } + + bool sync{kDefaultSync}; + if (!client->getSync(sync)) + { + GST_ERROR_OBJECT(m_sink, "Could not get sync"); + } + g_value_set_boolean(value, sync); + break; + } + case IPlaybackDelegate::Property::StreamSyncMode: + { + if (!client) + { + g_value_set_int(value, m_streamSyncMode); + return; + } + + int32_t streamSyncMode{kDefaultStreamSyncMode}; + if (!client->getStreamSyncMode(streamSyncMode)) + { + GST_ERROR_OBJECT(m_sink, "Could not get stream-sync-mode"); + } + g_value_set_int(value, streamSyncMode); + break; + } + case IPlaybackDelegate::Property::FadeVolume: + { + double volume{}; + if (!client || !client->getVolume(volume)) + { + g_value_set_uint(value, kDefaultFadeVolume); + return; + } + g_value_set_uint(value, static_cast(volume * 100.0)); + break; + } + case IPlaybackDelegate::Property::LimitBufferingMs: + { + if (!client) + { + g_value_set_uint(value, m_bufferingLimit); + return; + } + g_value_set_uint(value, client->getBufferingLimit()); + break; + } + case IPlaybackDelegate::Property::UseBuffering: + { + if (!client) + { + g_value_set_boolean(value, m_useBuffering); + return; + } + g_value_set_boolean(value, client->getUseBuffering()); + break; + } + case IPlaybackDelegate::Property::Async: + { + // Rialto MSE Audio sink is always async + g_value_set_boolean(value, TRUE); + break; + } + default: + { + PullModePlaybackDelegate::getProperty(type, value); + break; + } + } +} + +void PullModeAudioPlaybackDelegate::setProperty(const Property &type, const GValue *value) +{ + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + + switch (type) + { + case IPlaybackDelegate::Property::Volume: + { + m_targetVolume = g_value_get_double(value); + if (!client || !m_sourceAttached) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue volume setting"); + m_isVolumeQueued = true; + return; + } + client->setVolume(m_targetVolume, kDefaultVolumeDuration, kDefaultEaseType); + break; + } + case IPlaybackDelegate::Property::Mute: + { + m_mute = g_value_get_boolean(value); + if (!client || !m_sourceAttached) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue mute setting"); + m_isMuteQueued = true; + return; + } + client->setMute(m_mute, m_sourceId); + break; + } + case IPlaybackDelegate::Property::Gap: + { + gint64 position{0}, discontinuityGap{0}; + guint duration{0}; + gboolean audioAac{FALSE}; + + GstStructure *gapData = GST_STRUCTURE_CAST(g_value_get_boxed(value)); + if (!gst_structure_get_int64(gapData, "position", &position)) + { + GST_WARNING_OBJECT(m_sink, "Set gap: position is missing!"); + } + if (!gst_structure_get_uint(gapData, "duration", &duration)) + { + GST_WARNING_OBJECT(m_sink, "Set gap: duration is missing!"); + } + if (!gst_structure_get_int64(gapData, "discontinuity-gap", &discontinuityGap)) + { + GST_WARNING_OBJECT(m_sink, "Set gap: discontinuity gap is missing!"); + } + if (!gst_structure_get_boolean(gapData, "audio-aac", &audioAac)) + { + GST_WARNING_OBJECT(m_sink, "Set gap: audio aac is missing!"); + } + + GST_DEBUG_OBJECT(m_sink, "Processing audio gap."); + client->processAudioGap(position, duration, discontinuityGap, audioAac); + break; + } + case IPlaybackDelegate::Property::LowLatency: + { + m_lowLatency = g_value_get_boolean(value); + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue low latency setting"); + m_isLowLatencyQueued = true; + return; + } + + if (!client->setLowLatency(m_lowLatency)) + { + GST_ERROR_OBJECT(m_sink, "Could not set low-latency"); + } + break; + } + case IPlaybackDelegate::Property::Sync: + { + m_sync = g_value_get_boolean(value); + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue sync setting"); + m_isSyncQueued = true; + return; + } + + if (!client->setSync(m_sync)) + { + GST_ERROR_OBJECT(m_sink, "Could not set sync"); + } + break; + } + case IPlaybackDelegate::Property::SyncOff: + { + m_syncOff = g_value_get_boolean(value); + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue sync off setting"); + m_isSyncOffQueued = true; + return; + } + + if (!client->setSyncOff(m_syncOff)) + { + GST_ERROR_OBJECT(m_sink, "Could not set sync-off"); + } + break; + } + case IPlaybackDelegate::Property::StreamSyncMode: + { + m_streamSyncMode = g_value_get_int(value); + if (!client || !m_sourceAttached) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue stream sync mode setting"); + m_isStreamSyncModeQueued = true; + return; + } + + if (!client->setStreamSyncMode(m_sourceId, m_streamSyncMode)) + { + GST_ERROR_OBJECT(m_sink, "Could not set stream-sync-mode"); + } + break; + } + case IPlaybackDelegate::Property::AudioFade: + { + const gchar *audioFadeStr = g_value_get_string(value); + + uint32_t fadeVolume = static_cast(kDefaultVolume * 100); + uint32_t duration = kDefaultVolumeDuration; + char easeTypeChar = 'L'; + + int parsedItems = sscanf(audioFadeStr, "%u,%u,%c", &fadeVolume, &duration, &easeTypeChar); + + if (parsedItems == 0) + { + GST_ERROR_OBJECT(m_sink, "Failed to parse any values from audio fade string: %s.", audioFadeStr); + return; + } + else if (parsedItems == 1 || parsedItems == 2) + { + GST_WARNING_OBJECT(m_sink, "Partially parsed audio fade string: %s. Continuing with values: fadeVolume=%u, duration=%u, easeTypeChar=%c", + audioFadeStr, fadeVolume, duration, easeTypeChar); + } + + if (fadeVolume > 100) + { + GST_WARNING_OBJECT(m_sink, "Fade volume is greater than 100. Setting it to 100."); + fadeVolume = 100; + } + double volume = fadeVolume / 100.0; + + firebolt::rialto::EaseType easeType = convertCharToEaseType(easeTypeChar); + + { + std::lock_guard lock(m_audioFadeConfigMutex); + m_audioFadeConfig.volume = volume; + m_audioFadeConfig.duration = duration; + m_audioFadeConfig.easeType = easeType; + } + + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue audio fade setting"); + m_isAudioFadeQueued = true; + return; + } + + client->setVolume(volume, duration, easeType); + break; + } + case IPlaybackDelegate::Property::LimitBufferingMs: + { + m_bufferingLimit = g_value_get_uint(value); + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue buffering limit setting"); + m_isBufferingLimitQueued = true; + return; + } + + client->setBufferingLimit(m_bufferingLimit); + break; + } + case IPlaybackDelegate::Property::UseBuffering: + { + m_useBuffering = g_value_get_boolean(value); + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue use buffering setting"); + m_isUseBufferingQueued = true; + return; + } + + client->setUseBuffering(m_useBuffering); + break; + } + case IPlaybackDelegate::Property::Async: + { + if (FALSE == g_value_get_boolean(value)) + { + GST_WARNING_OBJECT(m_sink, "Cannot set ASYNC to false - not supported"); + } + break; + } + default: + { + PullModePlaybackDelegate::setProperty(type, value); + break; + } + } +} + +void PullModeAudioPlaybackDelegate::handleQos(uint64_t processed, uint64_t dropped) const +{ + GstBus *bus = gst_element_get_bus(m_sink); + /* Hardcode isLive to FALSE and set invalid timestamps */ + GstMessage *message = gst_message_new_qos(GST_OBJECT(m_sink), FALSE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, + GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); + gst_message_set_qos_stats(message, GST_FORMAT_DEFAULT, processed, dropped); + gst_bus_post(bus, message); + gst_object_unref(bus); +} + +std::unique_ptr +PullModeAudioPlaybackDelegate::createMediaSource(GstCaps *caps) const +{ + GstStructure *structure = gst_caps_get_structure(caps, 0); + const gchar *structName = gst_structure_get_name(structure); + + firebolt::rialto::AudioConfig audioConfig{}; + firebolt::rialto::SegmentAlignment alignment{get_segment_alignment(structure)}; + std::shared_ptr codecData{get_codec_data(structure)}; + firebolt::rialto::StreamFormat format{get_stream_format(structure)}; + + if (structName) + { + std::string mimeType{}; + if (g_str_has_prefix(structName, "audio/mpeg") || g_str_has_prefix(structName, "audio/x-eac3") || + g_str_has_prefix(structName, "audio/x-ac3")) + { + gint sample_rate{0}; + gint number_of_channels{0}; + gst_structure_get_int(structure, "rate", &sample_rate); + gst_structure_get_int(structure, "channels", &number_of_channels); + + audioConfig = firebolt::rialto::AudioConfig{static_cast(number_of_channels), + static_cast(sample_rate), + {}}; + + if (g_str_has_prefix(structName, "audio/mpeg")) + { + gint mpegversion{0}; + gint layer{0}; + gst_structure_get_int(structure, "mpegversion", &mpegversion); + gst_structure_get_int(structure, "layer", &layer); + if (1 == mpegversion && 3 == layer) + { + mimeType = "audio/mp3"; + } + else + { + mimeType = "audio/mp4"; + } + } + else + { + mimeType = "audio/x-eac3"; + } + } + else if (g_str_has_prefix(structName, "audio/x-opus")) + { + mimeType = "audio/x-opus"; + guint32 sampleRate{48000}; + guint8 numberOfChannels{}, streams{}, stereoStreams{}, channelMappingFamily{}; + guint8 channelMapping[256]{}; + guint16 preSkip{0}; + gint16 gain{0}; + if (gst_codec_utils_opus_parse_caps(caps, &sampleRate, &numberOfChannels, &channelMappingFamily, &streams, + &stereoStreams, channelMapping)) + { + GstBuffer *idHeader{}; + idHeader = gst_codec_utils_opus_create_header(sampleRate, numberOfChannels, channelMappingFamily, + streams, stereoStreams, channelMapping, preSkip, gain); + std::vector codecSpecificConfig{}; + GstMapInfo lsMap{}; + if (gst_buffer_map(idHeader, &lsMap, GST_MAP_READ)) + { + codecSpecificConfig.assign(lsMap.data, lsMap.data + lsMap.size); + gst_buffer_unmap(idHeader, &lsMap); + } + else + { + GST_ERROR_OBJECT(m_sink, "Failed to read opus header details from a GstBuffer!"); + } + gst_buffer_unref(idHeader); + + audioConfig = firebolt::rialto::AudioConfig{numberOfChannels, sampleRate, codecSpecificConfig}; + } + else + { + GST_ERROR("Failed to parse opus caps!"); + return nullptr; + } + } + else if (g_str_has_prefix(structName, "audio/b-wav") || g_str_has_prefix(structName, "audio/x-raw")) + { + gint sampleRate{0}; + gint numberOfChannels{0}; + std::optional channelMask; + gst_structure_get_int(structure, "rate", &sampleRate); + gst_structure_get_int(structure, "channels", &numberOfChannels); + std::optional layout = + rialto_mse_sink_convert_layout(gst_structure_get_string(structure, "layout")); + std::optional rialtoFormat = + rialto_mse_sink_convert_format(gst_structure_get_string(structure, "format")); + const GValue *channelMaskValue = gst_structure_get_value(structure, "channel-mask"); + if (channelMaskValue) + { + channelMask = gst_value_get_bitmask(channelMaskValue); + } + + if (g_str_has_prefix(structName, "audio/b-wav")) + { + mimeType = "audio/b-wav"; + } + else + { + mimeType = "audio/x-raw"; + } + + audioConfig = firebolt::rialto::AudioConfig{static_cast(numberOfChannels), + static_cast(sampleRate), + {}, + rialtoFormat, + layout, + channelMask}; + } + else if (g_str_has_prefix(structName, "audio/x-flac")) + { + mimeType = "audio/x-flac"; + gint sampleRate{0}; + gint numberOfChannels{0}; + gst_structure_get_int(structure, "rate", &sampleRate); + gst_structure_get_int(structure, "channels", &numberOfChannels); + std::vector> streamHeaderVec; + const GValue *streamheader = gst_structure_get_value(structure, "streamheader"); + if (streamheader) + { + for (guint i = 0; i < gst_value_array_get_size(streamheader); ++i) + { + const GValue *headerValue = gst_value_array_get_value(streamheader, i); + GstBuffer *headerBuffer = gst_value_get_buffer(headerValue); + if (headerBuffer) + { + GstMappedBuffer mappedBuf(headerBuffer, GST_MAP_READ); + if (mappedBuf) + { + streamHeaderVec.push_back( + std::vector(mappedBuf.data(), mappedBuf.data() + mappedBuf.size())); + } + } + } + } + std::optional framed; + gboolean framedValue{FALSE}; + if (gst_structure_get_boolean(structure, "framed", &framedValue)) + { + framed = framedValue; + } + + audioConfig = firebolt::rialto::AudioConfig{static_cast(numberOfChannels), + static_cast(sampleRate), + {}, + std::nullopt, + std::nullopt, + std::nullopt, + streamHeaderVec, + framed}; + } + else + { + GST_INFO_OBJECT(m_sink, "%s audio media source created", structName); + mimeType = structName; + } + + return std::make_unique(mimeType, m_hasDrm, audioConfig, + alignment, format, codecData); + } + + GST_ERROR_OBJECT(m_sink, "Empty caps' structure name! Failed to set mime type for audio media source."); + return nullptr; +} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.h b/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.h new file mode 100644 index 000000000..7e4c2be6e --- /dev/null +++ b/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "PullModePlaybackDelegate.h" + +struct AudioFadeConfig +{ + double volume; + uint32_t duration; + firebolt::rialto::EaseType easeType; +}; + +class PullModeAudioPlaybackDelegate : public PullModePlaybackDelegate, + public std::enable_shared_from_this +{ +public: + explicit PullModeAudioPlaybackDelegate(GstElement *sink); + ~PullModeAudioPlaybackDelegate() override = default; + + GstStateChangeReturn changeState(GstStateChange transition) override; + gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; + void getProperty(const Property &type, GValue *value) override; + void setProperty(const Property &type, const GValue *value) override; + void handleQos(uint64_t processed, uint64_t dropped) const override; + +private: + std::unique_ptr createMediaSource(GstCaps *caps) const; + +private: + std::atomic m_targetVolume{kDefaultVolume}; + std::atomic_bool m_mute{kDefaultMute}; + std::atomic_bool m_isVolumeQueued{false}; + std::atomic_bool m_isMuteQueued{false}; + std::atomic_bool m_lowLatency{kDefaultLowLatency}; + std::atomic_bool m_isLowLatencyQueued{false}; + std::atomic_bool m_sync{kDefaultSync}; + std::atomic_bool m_isSyncQueued{false}; + std::atomic_bool m_syncOff{kDefaultSyncOff}; + std::atomic_bool m_isSyncOffQueued{false}; + std::atomic m_streamSyncMode{kDefaultStreamSyncMode}; + std::atomic_bool m_isStreamSyncModeQueued{false}; + AudioFadeConfig m_audioFadeConfig{}; + std::mutex m_audioFadeConfigMutex{}; + std::atomic_bool m_isAudioFadeQueued{false}; + std::atomic m_bufferingLimit{kDefaultBufferingLimit}; + std::atomic_bool m_isBufferingLimitQueued{false}; + std::atomic_bool m_useBuffering{kDefaultUseBuffering}; + std::atomic_bool m_isUseBufferingQueued{false}; +}; \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.cpp new file mode 100644 index 000000000..1171ee1db --- /dev/null +++ b/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.cpp @@ -0,0 +1,962 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "PullModePlaybackDelegate.h" +#include "ControlBackend.h" +#include "GstreamerCatLog.h" +#include "RialtoGStreamerMSEBaseSink.h" +#include "RialtoGStreamerMSEBaseSinkPrivate.h" + +#define GST_CAT_DEFAULT rialtoGStreamerCat + +namespace +{ +GstObject *getOldestGstBinParent(GstElement *element) +{ + GstObject *parent = gst_object_get_parent(GST_OBJECT_CAST(element)); + GstObject *result = GST_OBJECT_CAST(element); + if (parent) + { + if (GST_IS_BIN(parent)) + { + result = getOldestGstBinParent(GST_ELEMENT_CAST(parent)); + } + gst_object_unref(parent); + } + + return result; +} + +unsigned getGstPlayFlag(const char *nick) +{ + GFlagsClass *flagsClass = static_cast(g_type_class_ref(g_type_from_name("GstPlayFlags"))); + GFlagsValue *flag = g_flags_get_value_by_nick(flagsClass, nick); + return flag ? flag->value : 0; +} + +bool getNStreamsFromParent(GstObject *parentObject, gint &n_video, gint &n_audio, gint &n_text) +{ + if (g_object_class_find_property(G_OBJECT_GET_CLASS(parentObject), "n-video") && + g_object_class_find_property(G_OBJECT_GET_CLASS(parentObject), "n-audio") && + g_object_class_find_property(G_OBJECT_GET_CLASS(parentObject), "n-text")) + { + g_object_get(parentObject, "n-video", &n_video, "n-audio", &n_audio, "n-text", &n_text, nullptr); + + if (g_object_class_find_property(G_OBJECT_GET_CLASS(parentObject), "flags")) + { + guint flags = 0; + g_object_get(parentObject, "flags", &flags, nullptr); + n_video = (flags & getGstPlayFlag("video")) ? n_video : 0; + n_audio = (flags & getGstPlayFlag("audio")) ? n_audio : 0; + n_text = (flags & getGstPlayFlag("text")) ? n_text : 0; + } + + return true; + } + + return false; +} +} // namespace + +PullModePlaybackDelegate::PullModePlaybackDelegate(GstElement *sink) : m_sink{sink} +{ + RialtoMSEBaseSink *baseSink = RIALTO_MSE_BASE_SINK(sink); + m_sinkPad = baseSink->priv->m_sinkPad; + m_rialtoControlClient = std::make_unique(); + gst_segment_init(&m_lastSegment, GST_FORMAT_TIME); +} + +PullModePlaybackDelegate::~PullModePlaybackDelegate() +{ + if (m_caps) + gst_caps_unref(m_caps); + clearBuffersUnlocked(); +} + +void PullModePlaybackDelegate::clearBuffersUnlocked() +{ + m_isFlushOngoing = true; + m_needDataCondVariable.notify_all(); + while (!m_samples.empty()) + { + GstSample *sample = m_samples.front(); + m_samples.pop(); + gst_sample_unref(sample); + } +} + +void PullModePlaybackDelegate::setSourceId(int32_t sourceId) +{ + std::unique_lock lock{m_sinkMutex}; + m_sourceId = sourceId; +} + +void PullModePlaybackDelegate::handleEos() +{ + GstState currentState = GST_STATE(m_sink); + if ((currentState != GST_STATE_PAUSED) && (currentState != GST_STATE_PLAYING)) + { + GST_ERROR_OBJECT(m_sink, "Sink cannot post a EOS message in state '%s', posting an error instead", + gst_element_state_get_name(currentState)); + + const char *errMessage = "Rialto sinks received EOS in non-playing state"; + GError *gError{g_error_new_literal(GST_STREAM_ERROR, 0, errMessage)}; + gst_element_post_message(m_sink, gst_message_new_error(GST_OBJECT_CAST(m_sink), gError, errMessage)); + g_error_free(gError); + } + else if (!m_isFlushOngoing) + { + gst_element_post_message(m_sink, gst_message_new_eos(GST_OBJECT_CAST(m_sink))); + } + else + { + GST_WARNING_OBJECT(m_sink, "Skip sending eos message - flush is ongoing..."); + } +} + +void PullModePlaybackDelegate::handleFlushCompleted() +{ + GST_INFO_OBJECT(m_sink, "Flush completed"); + std::unique_lock lock(m_flushMutex); + m_flushCondVariable.notify_all(); +} + +void PullModePlaybackDelegate::handleStateChanged(firebolt::rialto::PlaybackState state) +{ + GstState current = GST_STATE(m_sink); + GstState next = GST_STATE_NEXT(m_sink); + GstState pending = GST_STATE_PENDING(m_sink); + GstState postNext = next == pending ? GST_STATE_VOID_PENDING : pending; + + GST_DEBUG_OBJECT(m_sink, + "Received server's state change to %u. Sink's states are: current state: %s next state: %s " + "pending state: %s, last return state %s", + static_cast(state), gst_element_state_get_name(current), + gst_element_state_get_name(next), gst_element_state_get_name(pending), + gst_element_state_change_return_get_name(GST_STATE_RETURN(m_sink))); + + if (m_isStateCommitNeeded) + { + if ((state == firebolt::rialto::PlaybackState::PAUSED && next == GST_STATE_PAUSED) || + (state == firebolt::rialto::PlaybackState::PLAYING && next == GST_STATE_PLAYING)) + { + GST_STATE(m_sink) = next; + GST_STATE_NEXT(m_sink) = postNext; + GST_STATE_PENDING(m_sink) = GST_STATE_VOID_PENDING; + GST_STATE_RETURN(m_sink) = GST_STATE_CHANGE_SUCCESS; + + GST_INFO_OBJECT(m_sink, "Async state transition to state %s done", gst_element_state_get_name(next)); + + gst_element_post_message(m_sink, + gst_message_new_state_changed(GST_OBJECT_CAST(m_sink), current, next, pending)); + postAsyncDone(); + } + /* Immediately transition to PLAYING when prerolled and PLAY is requested */ + else if (state == firebolt::rialto::PlaybackState::PAUSED && current == GST_STATE_PAUSED && + next == GST_STATE_PLAYING) + { + GST_INFO_OBJECT(m_sink, "Async state transition to PAUSED done. Transitioning to PLAYING"); + changeState(GST_STATE_CHANGE_PAUSED_TO_PLAYING); + } + } +} + +GstStateChangeReturn PullModePlaybackDelegate::changeState(GstStateChange transition) +{ + GstState current_state = GST_STATE_TRANSITION_CURRENT(transition); + GstState next_state = GST_STATE_TRANSITION_NEXT(transition); + GST_INFO_OBJECT(m_sink, "State change: (%s) -> (%s)", gst_element_state_get_name(current_state), + gst_element_state_get_name(next_state)); + + GstStateChangeReturn status = GST_STATE_CHANGE_SUCCESS; + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + + switch (transition) + { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!m_sinkPad) + { + GST_ERROR_OBJECT(m_sink, "Cannot start, because there's no sink pad"); + return GST_STATE_CHANGE_FAILURE; + } + if (!m_rialtoControlClient->waitForRunning()) + { + GST_ERROR_OBJECT(m_sink, "Control: Rialto client cannot reach running state"); + return GST_STATE_CHANGE_FAILURE; + } + GST_INFO_OBJECT(m_sink, "Control: Rialto client reached running state"); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + if (!client) + { + GST_ERROR_OBJECT(m_sink, "Cannot get the media player client object"); + return GST_STATE_CHANGE_FAILURE; + } + + m_isFlushOngoing = false; + + StateChangeResult result = client->pause(m_sourceId); + if (result == StateChangeResult::SUCCESS_ASYNC || result == StateChangeResult::NOT_ATTACHED) + { + // NOT_ATTACHED is not a problem here, because source will be attached later when GST_EVENT_CAPS is received + if (result == StateChangeResult::NOT_ATTACHED) + { + postAsyncStart(); + } + status = GST_STATE_CHANGE_ASYNC; + } + + break; + } + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + if (!client) + { + GST_ERROR_OBJECT(m_sink, "Cannot get the media player client object"); + return GST_STATE_CHANGE_FAILURE; + } + + StateChangeResult result = client->play(m_sourceId); + if (result == StateChangeResult::SUCCESS_ASYNC) + { + status = GST_STATE_CHANGE_ASYNC; + } + else if (result == StateChangeResult::NOT_ATTACHED) + { + GST_ERROR_OBJECT(m_sink, "Failed to change state to playing"); + return GST_STATE_CHANGE_FAILURE; + } + + break; + } + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + { + if (!client) + { + GST_ERROR_OBJECT(m_sink, "Cannot get the media player client object"); + return GST_STATE_CHANGE_FAILURE; + } + + StateChangeResult result = client->pause(m_sourceId); + if (result == StateChangeResult::SUCCESS_ASYNC) + { + status = GST_STATE_CHANGE_ASYNC; + } + else if (result == StateChangeResult::NOT_ATTACHED) + { + GST_ERROR_OBJECT(m_sink, "Failed to change state to paused"); + return GST_STATE_CHANGE_FAILURE; + } + + break; + } + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (!client) + { + GST_ERROR_OBJECT(m_sink, "Cannot get the media player client object"); + return GST_STATE_CHANGE_FAILURE; + } + + if (m_isStateCommitNeeded) + { + GST_DEBUG_OBJECT(m_sink, "Sending async_done in PAUSED->READY transition"); + postAsyncDone(); + } + + client->removeSource(m_sourceId); + { + std::lock_guard lock(m_sinkMutex); + clearBuffersUnlocked(); + m_sourceAttached = false; + } + break; + case GST_STATE_CHANGE_READY_TO_NULL: + // Playback will be stopped once all sources are finished and ref count + // of the media pipeline object reaches 0 + m_mediaPlayerManager.releaseMediaPlayerClient(); + m_rialtoControlClient->removeControlBackend(); + break; + default: + break; + } + + return status; +} + +void PullModePlaybackDelegate::handleError(const std::string &message, gint code) +{ + GError *gError{g_error_new_literal(GST_STREAM_ERROR, code, message.c_str())}; + gst_element_post_message(GST_ELEMENT_CAST(m_sink), + gst_message_new_error(GST_OBJECT_CAST(m_sink), gError, message.c_str())); + g_error_free(gError); +} + +void PullModePlaybackDelegate::postAsyncStart() +{ + m_isStateCommitNeeded = true; + gst_element_post_message(GST_ELEMENT_CAST(m_sink), gst_message_new_async_start(GST_OBJECT(m_sink))); +} + +void PullModePlaybackDelegate::postAsyncDone() +{ + m_isStateCommitNeeded = false; + gst_element_post_message(m_sink, gst_message_new_async_done(GST_OBJECT_CAST(m_sink), GST_CLOCK_TIME_NONE)); +} + +void PullModePlaybackDelegate::setProperty(const Property &type, const GValue *value) +{ + switch (type) + { + case Property::IsSinglePathStream: + { + std::lock_guard lock(m_sinkMutex); + m_isSinglePathStream = g_value_get_boolean(value) != FALSE; + break; + } + case Property::NumberOfStreams: + { + std::lock_guard lock(m_sinkMutex); + m_numOfStreams = g_value_get_int(value); + break; + } + case Property::HasDrm: + { + std::lock_guard lock(m_sinkMutex); + m_hasDrm = g_value_get_boolean(value) != FALSE; + break; + } + default: + { + break; + } + } +} + +void PullModePlaybackDelegate::getProperty(const Property &type, GValue *value) +{ + switch (type) + { + case Property::IsSinglePathStream: + { + std::lock_guard lock(m_sinkMutex); + g_value_set_boolean(value, m_isSinglePathStream ? TRUE : FALSE); + break; + } + case Property::NumberOfStreams: + { + std::lock_guard lock(m_sinkMutex); + g_value_set_int(value, m_numOfStreams); + break; + } + case Property::HasDrm: + { + std::lock_guard lock(m_sinkMutex); + g_value_set_boolean(value, m_hasDrm ? TRUE : FALSE); + break; + } + case Property::Stats: + { + std::lock_guard lock(m_sinkMutex); + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + GST_ERROR_OBJECT(m_sink, "Could not get the media player client"); + break; + } + + guint64 totalVideoFrames{0}; + guint64 droppedVideoFrames{0}; + if (client->getStats(m_sourceId, totalVideoFrames, droppedVideoFrames)) + { + GstStructure *stats{gst_structure_new("stats", "rendered", G_TYPE_UINT64, totalVideoFrames, "dropped", + G_TYPE_UINT64, droppedVideoFrames, nullptr)}; + g_value_set_pointer(value, stats); + } + else + { + GST_ERROR_OBJECT(m_sink, "No stats returned from client"); + } + } + default: + { + break; + } + } +} + +std::optional PullModePlaybackDelegate::handleQuery(GstQuery *query) const +{ + GST_DEBUG_OBJECT(m_sink, "handling query '%s'", GST_QUERY_TYPE_NAME(query)); + switch (GST_QUERY_TYPE(query)) + { + case GST_QUERY_SEEKING: + { + GstFormat fmt; + gst_query_parse_seeking(query, &fmt, NULL, NULL, NULL); + gst_query_set_seeking(query, fmt, FALSE, 0, -1); + return TRUE; + } + case GST_QUERY_POSITION: + { + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + return FALSE; + } + + GstFormat fmt; + gst_query_parse_position(query, &fmt, NULL); + switch (fmt) + { + case GST_FORMAT_TIME: + { + gint64 position = client->getPosition(m_sourceId); + GST_DEBUG_OBJECT(m_sink, "Queried position is %" GST_TIME_FORMAT, GST_TIME_ARGS(position)); + if (position < 0) + { + return FALSE; + } + + gst_query_set_position(query, fmt, position); + break; + } + default: + break; + } + return TRUE; + } + case GST_QUERY_SEGMENT: + { + std::lock_guard lock(m_sinkMutex); + GstFormat format{m_lastSegment.format}; + gint64 start{static_cast(gst_segment_to_stream_time(&m_lastSegment, format, m_lastSegment.start))}; + gint64 stop{0}; + if (m_lastSegment.stop == GST_CLOCK_TIME_NONE) + { + stop = m_lastSegment.duration; + } + else + { + stop = gst_segment_to_stream_time(&m_lastSegment, format, m_lastSegment.stop); + } + gst_query_set_segment(query, m_lastSegment.rate, format, start, stop); + return TRUE; + } + default: + break; + } + return std::nullopt; +} + +gboolean PullModePlaybackDelegate::handleSendEvent(GstEvent *event) +{ + GST_DEBUG_OBJECT(m_sink, "handling event '%s'", GST_EVENT_TYPE_NAME(event)); + bool shouldForwardUpstream = GST_EVENT_IS_UPSTREAM(event); + + switch (GST_EVENT_TYPE(event)) + { + case GST_EVENT_SEEK: + { + gdouble rate{1.0}; + GstFormat seekFormat{GST_FORMAT_UNDEFINED}; + GstSeekFlags flags{GST_SEEK_FLAG_NONE}; + GstSeekType startType{GST_SEEK_TYPE_NONE}, stopType{GST_SEEK_TYPE_NONE}; + gint64 start{0}, stop{0}; + if (event) + { + gst_event_parse_seek(event, &rate, &seekFormat, &flags, &startType, &start, &stopType, &stop); + + if (flags & GST_SEEK_FLAG_FLUSH) + { + if (seekFormat == GST_FORMAT_TIME && startType == GST_SEEK_TYPE_END) + { + GST_ERROR_OBJECT(m_sink, "GST_SEEK_TYPE_END seek is not supported"); + gst_event_unref(event); + return FALSE; + } + // Update last segment + if (seekFormat == GST_FORMAT_TIME) + { + gboolean update{FALSE}; + std::lock_guard lock(m_sinkMutex); + gst_segment_do_seek(&m_lastSegment, rate, seekFormat, flags, startType, start, stopType, stop, + &update); + } + } +#if GST_CHECK_VERSION(1, 18, 0) + else if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) + { + gdouble rateMultiplier = rate / m_lastSegment.rate; + GstEvent *rateChangeEvent = gst_event_new_instant_rate_change(rateMultiplier, (GstSegmentFlags)flags); + gst_event_set_seqnum(rateChangeEvent, gst_event_get_seqnum(event)); + gst_event_unref(event); + if (gst_pad_send_event(m_sinkPad, rateChangeEvent) != TRUE) + { + GST_ERROR_OBJECT(m_sink, "Sending instant rate change failed."); + return FALSE; + } + return TRUE; + } +#endif + else + { + GST_WARNING_OBJECT(m_sink, "Seek with flags 0x%X is not supported", flags); + gst_event_unref(event); + return FALSE; + } + } + break; + } +#if GST_CHECK_VERSION(1, 18, 0) + case GST_EVENT_INSTANT_RATE_SYNC_TIME: + { + double rate{0.0}; + GstClockTime runningTime{GST_CLOCK_TIME_NONE}, upstreamRunningTime{GST_CLOCK_TIME_NONE}; + guint32 seqnum = gst_event_get_seqnum(event); + gst_event_parse_instant_rate_sync_time(event, &rate, &runningTime, &upstreamRunningTime); + + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if ((client) && (m_mediaPlayerManager.hasControl())) + { + GST_DEBUG_OBJECT(m_sink, "Instant playback rate change: %.2f", rate); + m_currentInstantRateChangeSeqnum = seqnum; + client->setPlaybackRate(rate); + } + break; + } +#endif + default: + break; + } + + if (shouldForwardUpstream) + { + bool result = gst_pad_push_event(m_sinkPad, event); + if (!result) + { + GST_DEBUG_OBJECT(m_sink, "forwarding upstream event '%s' failed", GST_EVENT_TYPE_NAME(event)); + } + + return result; + } + + gst_event_unref(event); + return TRUE; +} + +gboolean PullModePlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) +{ + GST_DEBUG_OBJECT(m_sink, "handling event %" GST_PTR_FORMAT, event); + switch (GST_EVENT_TYPE(event)) + { + case GST_EVENT_SEGMENT: + { + copySegment(event); + setSegment(); + break; + } + case GST_EVENT_EOS: + { + std::lock_guard lock(m_sinkMutex); + m_isEos = true; + break; + } + case GST_EVENT_CAPS: + { + GstCaps *caps; + gst_event_parse_caps(event, &caps); + { + std::lock_guard lock(m_sinkMutex); + if (m_caps) + { + if (!gst_caps_is_equal(caps, m_caps)) + { + gst_caps_unref(m_caps); + m_caps = gst_caps_copy(caps); + } + } + else + { + m_caps = gst_caps_copy(caps); + } + } + break; + } + case GST_EVENT_SINK_MESSAGE: + { + GstMessage *message = nullptr; + gst_event_parse_sink_message(event, &message); + + if (message) + { + gst_element_post_message(m_sink, message); + } + + break; + } + case GST_EVENT_CUSTOM_DOWNSTREAM: + case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: + { + if (gst_event_has_name(event, "custom-instant-rate-change")) + { + GST_DEBUG_OBJECT(m_sink, "Change rate event received"); + changePlaybackRate(event); + } + break; + } + case GST_EVENT_FLUSH_START: + { + startFlushing(); + break; + } + case GST_EVENT_FLUSH_STOP: + { + gboolean resetTime{FALSE}; + gst_event_parse_flush_stop(event, &resetTime); + + stopFlushing(resetTime); + break; + } + case GST_EVENT_STREAM_COLLECTION: + { + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + gst_event_unref(event); + return FALSE; + } + int32_t videoStreams{0}, audioStreams{0}, textStreams{0}; + GstStreamCollection *streamCollection{nullptr}; + gst_event_parse_stream_collection(event, &streamCollection); + guint streamsSize = gst_stream_collection_get_size(streamCollection); + for (guint i = 0; i < streamsSize; ++i) + { + auto *stream = gst_stream_collection_get_stream(streamCollection, i); + auto type = gst_stream_get_stream_type(stream); + if (type & GST_STREAM_TYPE_AUDIO) + { + ++audioStreams; + } + else if (type & GST_STREAM_TYPE_VIDEO) + { + ++videoStreams; + } + else if (type & GST_STREAM_TYPE_TEXT) + { + ++textStreams; + } + } + gst_object_unref(streamCollection); + client->handleStreamCollection(audioStreams, videoStreams, textStreams); + client->sendAllSourcesAttachedIfPossible(); + break; + } +#if GST_CHECK_VERSION(1, 18, 0) + case GST_EVENT_INSTANT_RATE_CHANGE: + { + guint32 seqnum = gst_event_get_seqnum(event); + if (m_lastInstantRateChangeSeqnum == seqnum || m_currentInstantRateChangeSeqnum.load() == seqnum) + { + /* Ignore if we already received the instant-rate-sync-time event from the pipeline */ + GST_DEBUG_OBJECT(m_sink, "Instant rate change event with seqnum %u already handled. Ignoring...", seqnum); + break; + } + + m_lastInstantRateChangeSeqnum = seqnum; + gdouble rate{0.0}; + GstSegmentFlags flags{GST_SEGMENT_FLAG_NONE}; + gst_event_parse_instant_rate_change(event, &rate, &flags); + GstMessage *msg = gst_message_new_instant_rate_request(GST_OBJECT_CAST(m_sink), rate); + gst_message_set_seqnum(msg, seqnum); + gst_element_post_message(m_sink, msg); + break; + } +#endif + default: + break; + } + + gst_event_unref(event); + + return TRUE; +} + +void PullModePlaybackDelegate::copySegment(GstEvent *event) +{ + std::lock_guard lock(m_sinkMutex); + gst_event_copy_segment(event, &m_lastSegment); +} + +void PullModePlaybackDelegate::setSegment() +{ + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + GST_ERROR_OBJECT(m_sink, "Could not get the media player client"); + return; + } + const bool kResetTime{m_lastSegment.flags == GST_SEGMENT_FLAG_RESET}; + int64_t position = static_cast(m_lastSegment.start); + client->setSourcePosition(m_sourceId, position, kResetTime, m_lastSegment.applied_rate, m_lastSegment.stop); + m_segmentSet = true; +} + +void PullModePlaybackDelegate::changePlaybackRate(GstEvent *event) +{ + const GstStructure *structure{gst_event_get_structure(event)}; + gdouble playbackRate{1.0}; + if (gst_structure_get_double(structure, "rate", &playbackRate) == TRUE) + { + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (client && m_mediaPlayerManager.hasControl()) + { + GST_DEBUG_OBJECT(m_sink, "Instant playback rate change: %.2f", playbackRate); + client->setPlaybackRate(playbackRate); + } + } +} + +void PullModePlaybackDelegate::startFlushing() +{ + std::lock_guard lock(m_sinkMutex); + if (!m_isFlushOngoing) + { + GST_INFO_OBJECT(m_sink, "Starting flushing"); + if (m_isEos) + { + GST_DEBUG_OBJECT(m_sink, "Flush will clear EOS state."); + m_isEos = false; + } + m_isFlushOngoing = true; + m_segmentSet = false; + clearBuffersUnlocked(); + } +} + +void PullModePlaybackDelegate::stopFlushing(bool resetTime) +{ + GST_INFO_OBJECT(m_sink, "Stopping flushing"); + flushServer(resetTime); + std::lock_guard lock(m_sinkMutex); + m_isFlushOngoing = false; + + if (resetTime) + { + GST_DEBUG_OBJECT(m_sink, "sending reset_time message"); + gst_element_post_message(m_sink, gst_message_new_reset_time(GST_OBJECT_CAST(m_sink), 0)); + } +} + +void PullModePlaybackDelegate::flushServer(bool resetTime) +{ + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + GST_ERROR_OBJECT(m_sink, "Could not get the media player client"); + return; + } + + std::unique_lock lock(m_flushMutex); + GST_INFO_OBJECT(m_sink, "Flushing sink with sourceId %d", m_sourceId.load()); + client->flush(m_sourceId, resetTime); + if (m_sourceAttached) + { + m_flushCondVariable.wait(lock); + } + else + { + GST_DEBUG_OBJECT(m_sink, "Skip waiting for flush finish - source not attached yet."); + } +} + +GstFlowReturn PullModePlaybackDelegate::handleBuffer(GstBuffer *buffer) +{ + constexpr size_t kMaxInternalBuffersQueueSize = 24; + GST_LOG_OBJECT(m_sink, "Handling buffer %p with PTS %" GST_TIME_FORMAT, buffer, + GST_TIME_ARGS(GST_BUFFER_PTS(buffer))); + + std::unique_lock lock(m_sinkMutex); + + if (m_samples.size() >= kMaxInternalBuffersQueueSize) + { + GST_DEBUG_OBJECT(m_sink, "Waiting for more space in buffers queue\n"); + m_needDataCondVariable.wait(lock); + } + + if (m_isFlushOngoing) + { + GST_DEBUG_OBJECT(m_sink, "Discarding buffer which was received during flushing"); + gst_buffer_unref(buffer); + return GST_FLOW_FLUSHING; + } + + GstSample *sample = gst_sample_new(buffer, m_caps, &m_lastSegment, nullptr); + if (sample) + m_samples.push(sample); + else + GST_ERROR_OBJECT(m_sink, "Failed to create a sample"); + + gst_buffer_unref(buffer); + + return GST_FLOW_OK; +} + +GstRefSample PullModePlaybackDelegate::getFrontSample() const +{ + std::lock_guard lock(m_sinkMutex); + if (!m_samples.empty()) + { + GstSample *sample = m_samples.front(); + GstBuffer *buffer = gst_sample_get_buffer(sample); + GST_LOG_OBJECT(m_sink, "Pulling buffer %p with PTS %" GST_TIME_FORMAT, buffer, + GST_TIME_ARGS(GST_BUFFER_PTS(buffer))); + + return GstRefSample{sample}; + } + + return GstRefSample{}; +} + +void PullModePlaybackDelegate::popSample() +{ + std::lock_guard lock(m_sinkMutex); + if (!m_samples.empty()) + { + gst_sample_unref(m_samples.front()); + m_samples.pop(); + } + m_needDataCondVariable.notify_all(); +} + +bool PullModePlaybackDelegate::isEos() const +{ + std::lock_guard lock(m_sinkMutex); + return m_samples.empty() && m_isEos; +} + +bool PullModePlaybackDelegate::isReadyToSendData() const +{ + std::lock_guard lock(m_sinkMutex); + return m_isEos || m_segmentSet; +} + +void PullModePlaybackDelegate::lostState() +{ + m_isStateCommitNeeded = true; + gst_element_lost_state(m_sink); +} + +bool PullModePlaybackDelegate::attachToMediaClientAndSetStreamsNumber(const uint32_t maxVideoWidth, + const uint32_t maxVideoHeight) +{ + GstObject *parentObject = getOldestGstBinParent(m_sink); + if (!m_mediaPlayerManager.attachMediaPlayerClient(parentObject, maxVideoWidth, maxVideoHeight)) + { + GST_ERROR_OBJECT(m_sink, "Cannot attach the MediaPlayerClient"); + return false; + } + + gchar *parentObjectName = gst_object_get_name(parentObject); + GST_INFO_OBJECT(m_sink, "Attached media player client with parent %s(%p)", parentObjectName, parentObject); + g_free(parentObjectName); + + return setStreamsNumber(parentObject); +} + +bool PullModePlaybackDelegate::setStreamsNumber(GstObject *parentObject) +{ + int32_t videoStreams{-1}, audioStreams{-1}, subtitleStreams{-1}; + + GstContext *context = gst_element_get_context(m_sink, "streams-info"); + if (context) + { + GST_DEBUG_OBJECT(m_sink, "Getting number of streams from \"streams-info\" context"); + + guint n_video{0}, n_audio{0}, n_text{0}; + + const GstStructure *streamsInfoStructure = gst_context_get_structure(context); + gst_structure_get_uint(streamsInfoStructure, "video-streams", &n_video); + gst_structure_get_uint(streamsInfoStructure, "audio-streams", &n_audio); + gst_structure_get_uint(streamsInfoStructure, "text-streams", &n_text); + + if (n_video > std::numeric_limits::max() || n_audio > std::numeric_limits::max() || + n_text > std::numeric_limits::max()) + { + GST_ERROR_OBJECT(m_sink, "Number of streams is too big, video=%u, audio=%u, text=%u", n_video, n_audio, + n_text); + gst_context_unref(context); + return false; + } + + videoStreams = n_video; + audioStreams = n_audio; + subtitleStreams = n_text; + + gst_context_unref(context); + } + else if (getNStreamsFromParent(parentObject, videoStreams, audioStreams, subtitleStreams)) + { + GST_DEBUG_OBJECT(m_sink, "Got number of streams from playbin2 properties"); + } + else + { + // The default value of streams is V:1, A:1, S:0 + // Changing the default setting via properties is considered as DEPRECATED + subtitleStreams = 0; + std::lock_guard lock{m_sinkMutex}; + if (m_mediaSourceType == firebolt::rialto::MediaSourceType::VIDEO) + { + videoStreams = m_numOfStreams; + if (m_isSinglePathStream) + { + audioStreams = 0; + subtitleStreams = 0; + } + } + else if (m_mediaSourceType == firebolt::rialto::MediaSourceType::AUDIO) + { + audioStreams = m_numOfStreams; + if (m_isSinglePathStream) + { + videoStreams = 0; + subtitleStreams = 0; + } + } + else if (m_mediaSourceType == firebolt::rialto::MediaSourceType::SUBTITLE) + { + subtitleStreams = m_numOfStreams; + if (m_isSinglePathStream) + { + videoStreams = 0; + audioStreams = 0; + } + } + } + + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + GST_ERROR_OBJECT(m_sink, "MediaPlayerClient is nullptr"); + return false; + } + + client->handleStreamCollection(audioStreams, videoStreams, subtitleStreams); + + return true; +} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.h b/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.h new file mode 100644 index 000000000..5b3fc86d1 --- /dev/null +++ b/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.h @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "IPullModePlaybackDelegate.h" +#include + +#include + +#include "ControlBackendInterface.h" +#include "MediaPlayerManager.h" +#include +#include +#include +#include +#include + +class PullModePlaybackDelegate : public IPullModePlaybackDelegate +{ +protected: + explicit PullModePlaybackDelegate(GstElement *sink); + ~PullModePlaybackDelegate() override; + +public: + void setSourceId(int32_t sourceId) override; + + void handleEos() override; + void handleFlushCompleted() override; + void handleStateChanged(firebolt::rialto::PlaybackState state) override; + void handleError(const std::string &message, gint code = 0) override; + GstStateChangeReturn changeState(GstStateChange transition) override; + void postAsyncStart() override; + void setProperty(const Property &type, const GValue *value) override; + void getProperty(const Property &type, GValue *value) override; + std::optional handleQuery(GstQuery *query) const override; + gboolean handleSendEvent(GstEvent *event) override; + gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; + GstFlowReturn handleBuffer(GstBuffer *buffer) override; + GstRefSample getFrontSample() const override; + void popSample() override; + bool isEos() const override; + void lostState() override; + bool isReadyToSendData() const override; + +protected: + bool attachToMediaClientAndSetStreamsNumber(const uint32_t maxVideoWidth = 0, const uint32_t maxVideoHeight = 0); + +private: + void clearBuffersUnlocked(); + void postAsyncDone(); + void copySegment(GstEvent *event); + void setSegment(); + void changePlaybackRate(GstEvent *event); + void startFlushing(); + void stopFlushing(bool resetTime); + void flushServer(bool resetTime); + bool setStreamsNumber(GstObject *parentObject); + +protected: + GstElement *m_sink{nullptr}; + GstPad *m_sinkPad{nullptr}; + GstSegment m_lastSegment{}; + GstCaps *m_caps{nullptr}; + + std::atomic m_sourceId{-1}; + std::queue m_samples{}; + bool m_isEos{false}; + std::atomic m_segmentSet{false}; + std::atomic m_isFlushOngoing{false}; + std::atomic m_isStateCommitNeeded{false}; + mutable std::mutex m_sinkMutex{}; + + std::condition_variable m_needDataCondVariable{}; + std::condition_variable m_flushCondVariable{}; + std::mutex m_flushMutex{}; + + MediaPlayerManager m_mediaPlayerManager{}; + std::unique_ptr m_rialtoControlClient{}; + std::atomic m_sourceAttached{false}; + bool m_isSinglePathStream{false}; + int32_t m_numOfStreams{1}; + std::atomic m_hasDrm{true}; + std::atomic m_isAsync{false}; + firebolt::rialto::PlaybackState m_serverPlaybackState{firebolt::rialto::PlaybackState::UNKNOWN}; + firebolt::rialto::MediaSourceType m_mediaSourceType{firebolt::rialto::MediaSourceType::UNKNOWN}; + guint32 m_lastInstantRateChangeSeqnum{GST_SEQNUM_INVALID}; + std::atomic m_currentInstantRateChangeSeqnum{GST_SEQNUM_INVALID}; +}; \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.cpp new file mode 100644 index 000000000..f32b816e4 --- /dev/null +++ b/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "PullModeSubtitlePlaybackDelegate.h" +#include "GstreamerCatLog.h" + +#define GST_CAT_DEFAULT rialtoGStreamerCat + +PullModeSubtitlePlaybackDelegate::PullModeSubtitlePlaybackDelegate(GstElement *sink) : PullModePlaybackDelegate(sink) +{ + m_mediaSourceType = firebolt::rialto::MediaSourceType::SUBTITLE; + m_isAsync = false; +} + +GstStateChangeReturn PullModeSubtitlePlaybackDelegate::changeState(GstStateChange transition) +{ + switch (transition) + { + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + if (!attachToMediaClientAndSetStreamsNumber()) + { + return GST_STATE_CHANGE_FAILURE; + } + } + default: + break; + } + return PullModePlaybackDelegate::changeState(transition); +} + +gboolean PullModeSubtitlePlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) +{ + switch (GST_EVENT_TYPE(event)) + { + case GST_EVENT_CAPS: + { + GstCaps *caps; + gst_event_parse_caps(event, &caps); + if (m_sourceAttached) + { + GST_INFO_OBJECT(m_sink, "Source already attached. Skip calling attachSource"); + break; + } + + GST_INFO_OBJECT(m_sink, "Attaching SUBTITLE source with caps %" GST_PTR_FORMAT, caps); + + std::unique_ptr subtitleSource{createMediaSource(caps)}; + if (subtitleSource) + { + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if ((!client) || (!client->attachSource(subtitleSource, RIALTO_MSE_BASE_SINK(m_sink), shared_from_this()))) + { + GST_ERROR_OBJECT(m_sink, "Failed to attach SUBTITLE source"); + } + else + { + m_sourceAttached = true; + if (m_isMuteQueued) + { + client->setMute(m_isMuted, m_sourceId); + m_isMuteQueued = false; + } + + { + std::unique_lock lock{m_mutex}; + if (m_isTextTrackIdentifierQueued) + { + client->setTextTrackIdentifier(m_textTrackIdentifier); + m_isTextTrackIdentifierQueued = false; + } + + if (m_queuedOffset) + { + GST_DEBUG_OBJECT(m_sink, "Setting subtitle offset to: %" GST_TIME_FORMAT, + GST_TIME_ARGS(m_queuedOffset.value())); + client->setSubtitleOffset(m_sourceId, m_queuedOffset.value()); + m_queuedOffset.reset(); + } + } + + // check if READY -> PAUSED was requested before source was attached + if (GST_STATE_NEXT(m_sink) == GST_STATE_PAUSED) + { + client->pause(m_sourceId); + } + } + } + else + { + GST_ERROR_OBJECT(m_sink, "Failed to create SUBTITLE source"); + } + + break; + } + case GST_EVENT_CUSTOM_DOWNSTREAM: + case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: + { + if (gst_event_has_name(event, "set-pts-offset")) + { + GST_DEBUG_OBJECT(m_sink, "Set pts offset event received"); + const GstStructure *structure{gst_event_get_structure(event)}; + guint64 ptsOffset{GST_CLOCK_TIME_NONE}; + if (gst_structure_get_uint64(structure, "pts-offset", &ptsOffset) == TRUE) + { + std::unique_lock lock{m_sinkMutex}; + + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client || !m_sourceAttached) + { + GST_DEBUG_OBJECT(m_sink, "offset setting enqueued"); + m_queuedOffset = static_cast(ptsOffset); + } + else + { + GST_DEBUG_OBJECT(m_sink, "Setting subtitle offset to: %" GST_TIME_FORMAT, GST_TIME_ARGS(ptsOffset)); + client->setSubtitleOffset(m_sourceId, ptsOffset); + } + } + else + { + GST_WARNING_OBJECT(m_sink, "Unable to set pts offset. Value not present"); + } + } + break; + } + default: + break; + } + return PullModePlaybackDelegate::handleEvent(pad, parent, event); +} + +void PullModeSubtitlePlaybackDelegate::getProperty(const Property &type, GValue *value) +{ + std::shared_ptr client{m_mediaPlayerManager.getMediaPlayerClient()}; + + switch (type) + { + case Property::Mute: + { + if (!client) + { + g_value_set_boolean(value, m_isMuted); + return; + } + g_value_set_boolean(value, client->getMute(m_sourceId)); + break; + } + case Property::TextTrackIdentifier: + { + { + std::unique_lock lock{m_mutex}; + if (!client) + { + g_value_set_string(value, m_textTrackIdentifier.c_str()); + return; + } + } + g_value_set_string(value, client->getTextTrackIdentifier().c_str()); + + break; + } + case Property::WindowId: + { + g_value_set_uint(value, m_videoId); + break; + } + case Property::Async: + { + g_value_set_boolean(value, m_isAsync); + break; + } + default: + { + PullModePlaybackDelegate::getProperty(type, value); + break; + } + } +} + +void PullModeSubtitlePlaybackDelegate::setProperty(const Property &type, const GValue *value) +{ + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + + switch (type) + { + case Property::Mute: + m_isMuted = g_value_get_boolean(value); + if (!client || !m_sourceAttached) + { + m_isMuteQueued = true; + return; + } + + client->setMute(m_isMuted, m_sourceId); + + break; + case Property::TextTrackIdentifier: + { + const gchar *textTrackIdentifier = g_value_get_string(value); + if (!textTrackIdentifier) + { + GST_WARNING_OBJECT(m_sink, "TextTrackIdentifier string not valid"); + break; + } + + std::unique_lock lock{m_mutex}; + m_textTrackIdentifier = std::string(textTrackIdentifier); + if (!client || !m_sourceAttached) + { + GST_DEBUG_OBJECT(m_sink, "Text track identifier setting enqueued"); + m_isTextTrackIdentifierQueued = true; + } + else + { + client->setTextTrackIdentifier(m_textTrackIdentifier); + } + + break; + } + case Property::WindowId: + { + m_videoId = g_value_get_uint(value); + break; + } + case Property::Async: + { + m_isAsync = g_value_get_boolean(value); + break; + } + default: + { + PullModePlaybackDelegate::setProperty(type, value); + break; + } + } +} + +void PullModeSubtitlePlaybackDelegate::handleQos(uint64_t processed, uint64_t dropped) const +{ + GstBus *bus = gst_element_get_bus(m_sink); + /* Hardcode isLive to FALSE and set invalid timestamps */ + GstMessage *message = gst_message_new_qos(GST_OBJECT(m_sink), FALSE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, + GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); + + gst_message_set_qos_stats(message, GST_FORMAT_BUFFERS, processed, dropped); + gst_bus_post(bus, message); + gst_object_unref(bus); +} + +std::unique_ptr +PullModeSubtitlePlaybackDelegate::createMediaSource(GstCaps *caps) const +{ + GstStructure *structure = gst_caps_get_structure(caps, 0); + const gchar *mimeName = gst_structure_get_name(structure); + if (mimeName) + { + std::string mimeType{}; + if (g_str_has_prefix(mimeName, "text/vtt") || g_str_has_prefix(mimeName, "application/x-subtitle-vtt")) + { + mimeType = "text/vtt"; + } + else if (g_str_has_prefix(mimeName, "application/ttml+xml")) + { + mimeType = "text/ttml"; + } + else if (g_str_has_prefix(mimeName, "closedcaption/x-cea-608") || + g_str_has_prefix(mimeName, "closedcaption/x-cea-708") || + g_str_has_prefix(mimeName, "application/x-cea-608") || + g_str_has_prefix(mimeName, "application/x-cea-708") || + g_str_has_prefix(mimeName, "application/x-subtitle-cc")) + { + mimeType = "text/cc"; + } + else + { + mimeType = mimeName; + } + + GST_INFO_OBJECT(m_sink, "%s subtitle media source created", mimeType.c_str()); + return std::make_unique(mimeType, m_textTrackIdentifier); + } + else + { + GST_ERROR_OBJECT(m_sink, + "Empty caps' structure name! Failed to set mime type when constructing subtitle media source"); + } + + return nullptr; +} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.h b/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.h new file mode 100644 index 000000000..e5b810637 --- /dev/null +++ b/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "PullModePlaybackDelegate.h" +#include +#include +#include + +class PullModeSubtitlePlaybackDelegate : public PullModePlaybackDelegate, + public std::enable_shared_from_this +{ +public: + explicit PullModeSubtitlePlaybackDelegate(GstElement *sink); + ~PullModeSubtitlePlaybackDelegate() override = default; + + GstStateChangeReturn changeState(GstStateChange transition) override; + gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; + void getProperty(const Property &type, GValue *value) override; + void setProperty(const Property &type, const GValue *value) override; + void handleQos(uint64_t processed, uint64_t dropped) const override; + +private: + std::unique_ptr createMediaSource(GstCaps *caps) const; + +private: + std::mutex m_mutex; + std::string m_textTrackIdentifier{}; + bool m_isTextTrackIdentifierQueued{false}; + std::atomic m_isMuted{false}; + bool m_isMuteQueued{false}; + uint32_t m_videoId{0}; + std::optional m_queuedOffset{}; +}; diff --git a/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.cpp new file mode 100644 index 000000000..8bc36a0da --- /dev/null +++ b/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.cpp @@ -0,0 +1,386 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "PullModeVideoPlaybackDelegate.h" +#include "GStreamerEMEUtils.h" +#include "GStreamerMSEUtils.h" +#include "GstreamerCatLog.h" + +#define GST_CAT_DEFAULT rialtoGStreamerCat + +PullModeVideoPlaybackDelegate::PullModeVideoPlaybackDelegate(GstElement *sink) : PullModePlaybackDelegate(sink) +{ + m_mediaSourceType = firebolt::rialto::MediaSourceType::VIDEO; + m_isAsync = true; +} + +GstStateChangeReturn PullModeVideoPlaybackDelegate::changeState(GstStateChange transition) +{ + switch (transition) + { + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + if (!attachToMediaClientAndSetStreamsNumber(m_maxWidth, m_maxHeight)) + { + return GST_STATE_CHANGE_FAILURE; + } + + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + GST_ERROR_OBJECT(m_sink, "MediaPlayerClient is nullptr"); + return GST_STATE_CHANGE_FAILURE; + } + + std::unique_lock lock{m_propertyMutex}; + if (m_rectangleSettingQueued) + { + GST_DEBUG_OBJECT(m_sink, "Set queued video rectangle"); + m_rectangleSettingQueued = false; + client->setVideoRectangle(m_videoRectangle); + } + break; + } + default: + break; + } + return PullModePlaybackDelegate::changeState(transition); +} + +gboolean PullModeVideoPlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) +{ + switch (GST_EVENT_TYPE(event)) + { + case GST_EVENT_CAPS: + { + GstCaps *caps{nullptr}; + gst_event_parse_caps(event, &caps); + if (m_sourceAttached) + { + GST_INFO_OBJECT(m_sink, "Source already attached. Skip calling attachSource"); + break; + } + + GST_INFO_OBJECT(m_sink, "Attaching VIDEO source with caps %" GST_PTR_FORMAT, caps); + + std::unique_ptr vsource = createMediaSource(caps); + if (vsource) + { + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + if ((!client) || (!client->attachSource(vsource, RIALTO_MSE_BASE_SINK(m_sink), shared_from_this()))) + { + GST_ERROR_OBJECT(m_sink, "Failed to attach VIDEO source"); + } + else + { + m_sourceAttached = true; + + // check if READY -> PAUSED was requested before source was attached + if (GST_STATE_NEXT(m_sink) == GST_STATE_PAUSED) + { + client->pause(m_sourceId); + } + std::unique_lock lock{m_propertyMutex}; + if (m_immediateOutputQueued) + { + GST_DEBUG_OBJECT(m_sink, "Set queued immediate-output"); + m_immediateOutputQueued = false; + if (!client->setImmediateOutput(m_sourceId, m_immediateOutput)) + { + GST_ERROR_OBJECT(m_sink, "Could not set immediate-output"); + } + } + if (m_syncmodeStreamingQueued) + { + GST_DEBUG_OBJECT(m_sink, "Set queued syncmode-streaming"); + m_syncmodeStreamingQueued = false; + if (!client->setStreamSyncMode(m_sourceId, m_syncmodeStreaming)) + { + GST_ERROR_OBJECT(m_sink, "Could not set syncmode-streaming"); + } + } + if (m_videoMuteQueued) + { + GST_DEBUG_OBJECT(m_sink, "Set queued show-video-window"); + m_videoMuteQueued = false; + client->setMute(m_videoMute, m_sourceId); + } + } + } + else + { + GST_ERROR_OBJECT(m_sink, "Failed to create VIDEO source"); + } + + break; + } + default: + break; + } + return PullModePlaybackDelegate::handleEvent(pad, parent, event); +} + +void PullModeVideoPlaybackDelegate::getProperty(const Property &type, GValue *value) +{ + switch (type) + { + case Property::WindowSet: + { + std::unique_lock lock{m_propertyMutex}; + auto client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + // Return the default value and + // queue a setting event (for the default value) so that it will become true when + // the client connects... + GST_DEBUG_OBJECT(m_sink, "Return default rectangle setting, and queue an event to set the default upon " + "client connect"); + m_rectangleSettingQueued = true; + g_value_set_string(value, m_videoRectangle.c_str()); + } + else + { + lock.unlock(); + g_value_set_string(value, client->getVideoRectangle().c_str()); + } + break; + } + case Property::MaxVideoWidth: + { + g_value_set_uint(value, m_maxWidth); + break; + } + case Property::MaxVideoHeight: + { + g_value_set_uint(value, m_maxHeight); + break; + } + case Property::FrameStepOnPreroll: + { + g_value_set_boolean(value, m_stepOnPrerollEnabled); + break; + } + case Property::ImmediateOutput: + { + std::unique_lock lock{m_propertyMutex}; + auto client = m_mediaPlayerManager.getMediaPlayerClient(); + if (!client) + { + // Return the default value and + // queue a setting event (for the default value) so that it will become true when + // the client connects... + GST_DEBUG_OBJECT(m_sink, "Return default immediate-output setting, and queue an event to set the default " + "upon client connect"); + m_immediateOutputQueued = true; + g_value_set_boolean(value, m_immediateOutput); + } + else + { + bool immediateOutput{m_immediateOutput}; + lock.unlock(); + if (!client->getImmediateOutput(m_sourceId, immediateOutput)) + { + GST_ERROR_OBJECT(m_sink, "Could not get immediate-output"); + } + g_value_set_boolean(value, immediateOutput); + } + break; + } + default: + { + PullModePlaybackDelegate::getProperty(type, value); + break; + } + } +} + +void PullModeVideoPlaybackDelegate::setProperty(const Property &type, const GValue *value) +{ + std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); + switch (type) + { + case Property::WindowSet: + { + const gchar *rectangle = g_value_get_string(value); + if (!rectangle) + { + GST_WARNING_OBJECT(m_sink, "Rectangle string not valid"); + break; + } + std::string videoRectangle{rectangle}; + std::unique_lock lock{m_propertyMutex}; + m_videoRectangle = videoRectangle; + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Rectangle setting enqueued"); + m_rectangleSettingQueued = true; + } + else + { + lock.unlock(); + client->setVideoRectangle(videoRectangle); + } + break; + } + case Property::MaxVideoWidth: + m_maxWidth = g_value_get_uint(value); + break; + case Property::MaxVideoHeight: + m_maxHeight = g_value_get_uint(value); + break; + case Property::FrameStepOnPreroll: + { + bool stepOnPrerollEnabled = g_value_get_boolean(value); + if (client && stepOnPrerollEnabled && !m_stepOnPrerollEnabled) + { + GST_INFO_OBJECT(m_sink, "Frame stepping on preroll"); + client->renderFrame(m_sourceId); + } + m_stepOnPrerollEnabled = stepOnPrerollEnabled; + break; + } + case Property::ImmediateOutput: + { + bool immediateOutput = (g_value_get_boolean(value) != FALSE); + std::unique_lock lock{m_propertyMutex}; + m_immediateOutput = immediateOutput; + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Immediate output setting enqueued"); + m_immediateOutputQueued = true; + } + else + { + lock.unlock(); + if (!client->setImmediateOutput(m_sourceId, immediateOutput)) + { + GST_ERROR_OBJECT(m_sink, "Could not set immediate-output"); + } + } + break; + } + case Property::SyncmodeStreaming: + { + bool syncmodeStreaming = (g_value_get_boolean(value) != FALSE); + std::unique_lock lock{m_propertyMutex}; + m_syncmodeStreaming = syncmodeStreaming; + if (!client) + { + GST_DEBUG_OBJECT(m_sink, "Syncmode streaming setting enqueued"); + m_syncmodeStreamingQueued = true; + } + else + { + lock.unlock(); + if (!client->setStreamSyncMode(m_sourceId, syncmodeStreaming)) + { + GST_ERROR_OBJECT(m_sink, "Could not set syncmode-streaming"); + } + } + break; + } + case Property::ShowVideoWindow: + { + bool videoMute = (g_value_get_boolean(value) == FALSE); + std::unique_lock lock{m_propertyMutex}; + m_videoMute = videoMute; + if (!client || !m_sourceAttached) + { + GST_DEBUG_OBJECT(m_sink, "Show video window setting enqueued"); + m_videoMuteQueued = true; + } + else + { + lock.unlock(); + client->setMute(videoMute, m_sourceId); + } + break; + } + default: + { + PullModePlaybackDelegate::setProperty(type, value); + break; + } + } +} + +void PullModeVideoPlaybackDelegate::handleQos(uint64_t processed, uint64_t dropped) const +{ + GstBus *bus = gst_element_get_bus(m_sink); + /* Hardcode isLive to FALSE and set invalid timestamps */ + GstMessage *message = gst_message_new_qos(GST_OBJECT(m_sink), FALSE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, + GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); + + gst_message_set_qos_stats(message, GST_FORMAT_BUFFERS, processed, dropped); + gst_bus_post(bus, message); + gst_object_unref(bus); +} + +std::unique_ptr +PullModeVideoPlaybackDelegate::createMediaSource(GstCaps *caps) const +{ + GstStructure *structure = gst_caps_get_structure(caps, 0); + const gchar *strct_name = gst_structure_get_name(structure); + + firebolt::rialto::SegmentAlignment alignment = get_segment_alignment(structure); + std::shared_ptr codecData = get_codec_data(structure); + firebolt::rialto::StreamFormat format = get_stream_format(structure); + + gint width{0}; + gint height{0}; + gst_structure_get_int(structure, "width", &width); + gst_structure_get_int(structure, "height", &height); + + if (strct_name) + { + std::string mimeType{}; + if (g_str_has_prefix(strct_name, "video/x-h264")) + { + mimeType = "video/h264"; + } + else if (g_str_has_prefix(strct_name, "video/x-h265")) + { + mimeType = "video/h265"; + + uint32_t dolbyVisionProfile{0}; + if (get_dv_profile(structure, dolbyVisionProfile)) + { + return std::make_unique(mimeType, + dolbyVisionProfile, + m_hasDrm, width, + height, alignment, + format, codecData); + } + } + else + { + mimeType = strct_name; + } + + GST_INFO_OBJECT(m_sink, "%s video media source created", mimeType.c_str()); + return std::make_unique(mimeType, m_hasDrm, width, height, + alignment, format, codecData); + } + else + { + GST_ERROR_OBJECT(m_sink, + "Empty caps' structure name! Failed to set mime type when constructing video media source"); + } + + return nullptr; +} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.h b/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.h new file mode 100644 index 000000000..a9bb5b652 --- /dev/null +++ b/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "PullModePlaybackDelegate.h" + +class PullModeVideoPlaybackDelegate : public PullModePlaybackDelegate, + public std::enable_shared_from_this +{ +public: + explicit PullModeVideoPlaybackDelegate(GstElement *sink); + ~PullModeVideoPlaybackDelegate() override = default; + + GstStateChangeReturn changeState(GstStateChange transition) override; + gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; + void getProperty(const Property &type, GValue *value) override; + void setProperty(const Property &type, const GValue *value) override; + void handleQos(uint64_t processed, uint64_t dropped) const override; + +private: + std::unique_ptr createMediaSource(GstCaps *caps) const; + +private: + uint32_t m_maxWidth{0}; + uint32_t m_maxHeight{0}; + bool m_stepOnPrerollEnabled{false}; + + std::mutex m_propertyMutex{}; + // START of variables locked by propertyMutex + // rectangle properties + std::string m_videoRectangle{"0,0,1920,1080"}; + bool m_rectangleSettingQueued{false}; + // immediate output properties + bool m_immediateOutput{false}; + bool m_immediateOutputQueued{false}; + bool m_syncmodeStreaming{false}; + bool m_syncmodeStreamingQueued{false}; + bool m_videoMute{false}; + bool m_videoMuteQueued{false}; + // END of variables locked by propertyMutex +}; \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.cpp new file mode 100644 index 000000000..57eafbf8c --- /dev/null +++ b/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.cpp @@ -0,0 +1,365 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "PushModeAudioPlaybackDelegate.h" +#include "ControlBackend.h" +#include "GStreamerWebAudioPlayerClient.h" +#include "GstreamerCatLog.h" +#include "MessageQueue.h" +#include "WebAudioClientBackend.h" + +#define GST_CAT_DEFAULT rialtoGStreamerCat + +PushModeAudioPlaybackDelegate::PushModeAudioPlaybackDelegate(GstElement *sink) + : m_sink{sink}, m_rialtoControlClient{std::make_unique()}, + m_webAudioClient{ + std::make_shared(std::make_unique(), + std::make_unique(), *this, + ITimerFactory::getFactory())} +{ +} + +PushModeAudioPlaybackDelegate::~PushModeAudioPlaybackDelegate() +{ + m_webAudioClient.reset(); +} + +void PushModeAudioPlaybackDelegate::handleEos() +{ + GstState currentState = GST_STATE(m_sink); + if ((currentState != GST_STATE_PAUSED) && (currentState != GST_STATE_PLAYING)) + { + GST_ERROR_OBJECT(m_sink, "Sink cannot post a EOS message in state '%s', posting an error instead", + gst_element_state_get_name(currentState)); + + const char *errMessage = "Web audio sink received EOS in non-playing state"; + GError *gError{g_error_new_literal(GST_STREAM_ERROR, 0, errMessage)}; + gst_element_post_message(GST_ELEMENT_CAST(m_sink), + gst_message_new_error(GST_OBJECT_CAST(m_sink), gError, errMessage)); + g_error_free(gError); + } + else + { + gst_element_post_message(GST_ELEMENT_CAST(m_sink), gst_message_new_eos(GST_OBJECT_CAST(m_sink))); + } +} + +void PushModeAudioPlaybackDelegate::handleStateChanged(firebolt::rialto::PlaybackState state) +{ + GstState current = GST_STATE(m_sink); + GstState next = GST_STATE_NEXT(m_sink); + GstState pending = GST_STATE_PENDING(m_sink); + + GST_DEBUG_OBJECT(m_sink, + "Received server's state change to %u. Sink's states are: current state: %s next state: %s " + "pending state: %s, last return state %s", + static_cast(state), gst_element_state_get_name(current), + gst_element_state_get_name(next), gst_element_state_get_name(pending), + gst_element_state_change_return_get_name(GST_STATE_RETURN(m_sink))); + + if (m_isStateCommitNeeded && ((state == firebolt::rialto::PlaybackState::PAUSED && next == GST_STATE_PAUSED) || + (state == firebolt::rialto::PlaybackState::PLAYING && next == GST_STATE_PLAYING))) + { + GstState postNext = next == pending ? GST_STATE_VOID_PENDING : pending; + GST_STATE(m_sink) = next; + GST_STATE_NEXT(m_sink) = postNext; + GST_STATE_PENDING(m_sink) = GST_STATE_VOID_PENDING; + GST_STATE_RETURN(m_sink) = GST_STATE_CHANGE_SUCCESS; + + GST_INFO_OBJECT(m_sink, "Async state transition to state %s done", gst_element_state_get_name(next)); + + gst_element_post_message(GST_ELEMENT_CAST(m_sink), + gst_message_new_state_changed(GST_OBJECT_CAST(m_sink), current, next, pending)); + postAsyncDone(); + } +} + +void PushModeAudioPlaybackDelegate::handleError(const std::string &message, gint code) +{ + GError *gError{g_error_new_literal(GST_STREAM_ERROR, code, message.c_str())}; + gst_element_post_message(GST_ELEMENT_CAST(m_sink), + gst_message_new_error(GST_OBJECT_CAST(m_sink), gError, message.c_str())); + g_error_free(gError); +} + +void PushModeAudioPlaybackDelegate::handleQos(uint64_t processed, uint64_t dropped) const {} + +GstStateChangeReturn PushModeAudioPlaybackDelegate::changeState(GstStateChange transition) +{ + GstPad *sinkPad = gst_element_get_static_pad(GST_ELEMENT_CAST(m_sink), "sink"); + + GstState current_state = GST_STATE_TRANSITION_CURRENT(transition); + GstState next_state = GST_STATE_TRANSITION_NEXT(transition); + GST_INFO_OBJECT(m_sink, "State change: (%s) -> (%s)", gst_element_state_get_name(current_state), + gst_element_state_get_name(next_state)); + + GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; + switch (transition) + { + case GST_STATE_CHANGE_NULL_TO_READY: + { + GST_DEBUG_OBJECT(m_sink, "GST_STATE_CHANGE_NULL_TO_READY"); + + if (!m_rialtoControlClient->waitForRunning()) + { + GST_ERROR_OBJECT(m_sink, "Rialto client cannot reach running state"); + result = GST_STATE_CHANGE_FAILURE; + } + break; + } + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + GST_DEBUG("GST_STATE_CHANGE_READY_TO_PAUSED"); + break; + } + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + GST_DEBUG_OBJECT(m_sink, "GST_STATE_CHANGE_PAUSED_TO_PLAYING"); + if (!m_webAudioClient->isOpen()) + { + GST_INFO_OBJECT(m_sink, "Delay playing until the caps are recieved and the player is opened"); + m_isPlayingDelayed = true; + result = GST_STATE_CHANGE_ASYNC; + postAsyncStart(); + } + else + { + if (!m_webAudioClient->play()) + { + GST_ERROR_OBJECT(m_sink, "Failed to play web audio"); + result = GST_STATE_CHANGE_FAILURE; + } + else + { + result = GST_STATE_CHANGE_ASYNC; + postAsyncStart(); + } + } + break; + } + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + { + GST_DEBUG_OBJECT(m_sink, "GST_STATE_CHANGE_PLAYING_TO_PAUSED"); + if (!m_webAudioClient->pause()) + { + GST_ERROR_OBJECT(m_sink, "Failed to pause web audio"); + result = GST_STATE_CHANGE_FAILURE; + } + else + { + result = GST_STATE_CHANGE_ASYNC; + postAsyncStart(); + } + break; + } + case GST_STATE_CHANGE_PAUSED_TO_READY: + { + GST_DEBUG_OBJECT(m_sink, "GST_STATE_CHANGE_PAUSED_TO_READY"); + if (!m_webAudioClient->close()) + { + GST_ERROR_OBJECT(m_sink, "Failed to close web audio"); + result = GST_STATE_CHANGE_FAILURE; + } + break; + } + case GST_STATE_CHANGE_READY_TO_NULL: + { + GST_DEBUG("GST_STATE_CHANGE_READY_TO_NULL"); + + m_rialtoControlClient->removeControlBackend(); + } + default: + break; + } + + gst_object_unref(sinkPad); + + return result; +} + +void PushModeAudioPlaybackDelegate::postAsyncStart() +{ + m_isStateCommitNeeded = true; + gst_element_post_message(GST_ELEMENT_CAST(m_sink), gst_message_new_async_start(GST_OBJECT(m_sink))); +} + +void PushModeAudioPlaybackDelegate::setProperty(const Property &type, const GValue *value) +{ + switch (type) + { + case Property::TsOffset: + { + GST_INFO_OBJECT(m_sink, "ts-offset property not supported, RialtoWebAudioSink does not require the " + "synchronisation of sources"); + break; + } + case Property::Volume: + { + m_volume = g_value_get_double(value); + if (!m_webAudioClient || !m_webAudioClient->isOpen()) + { + GST_DEBUG_OBJECT(m_sink, "Enqueue volume setting"); + m_isVolumeQueued = true; + return; + } + if (!m_webAudioClient->setVolume(m_volume)) + { + GST_ERROR_OBJECT(m_sink, "Failed to set volume"); + } + break; + } + default: + { + break; + } + } +} + +void PushModeAudioPlaybackDelegate::getProperty(const Property &type, GValue *value) +{ + switch (type) + { + case Property::TsOffset: + { + GST_INFO_OBJECT(m_sink, "ts-offset property not supported, RialtoWebAudioSink does not require the " + "synchronisation of sources"); + break; + } + case Property::Volume: + { + double volume{0.0}; + if (m_webAudioClient && m_webAudioClient->isOpen()) + { + if (m_webAudioClient->getVolume(volume)) + m_volume = volume; + else + volume = m_volume; // Use last known volume + } + else + { + volume = m_volume; + } + g_value_set_double(value, volume); + break; + } + default: + { + break; + } + } +} + +std::optional PushModeAudioPlaybackDelegate::handleQuery(GstQuery *query) const +{ + return std::nullopt; +} + +gboolean PushModeAudioPlaybackDelegate::handleSendEvent(GstEvent *event) +{ + switch (GST_EVENT_TYPE(event)) + { + case GST_EVENT_CAPS: + { + GstCaps *caps; + gst_event_parse_caps(event, &caps); + GST_INFO_OBJECT(m_sink, "Attaching AUDIO source with caps %" GST_PTR_FORMAT, caps); + } + default: + break; + } + gst_event_unref(event); + return TRUE; +} + +gboolean PushModeAudioPlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) +{ + gboolean result = FALSE; + switch (GST_EVENT_TYPE(event)) + { + case GST_EVENT_EOS: + { + GST_DEBUG_OBJECT(m_sink, "GST_EVENT_EOS"); + result = m_webAudioClient->setEos(); + break; + } + case GST_EVENT_CAPS: + { + GstCaps *caps; + gst_event_parse_caps(event, &caps); + GST_INFO_OBJECT(m_sink, "Opening WebAudio with caps %" GST_PTR_FORMAT, caps); + + if (!m_webAudioClient->open(caps)) + { + GST_ERROR_OBJECT(m_sink, "Failed to open web audio"); + } + else + { + result = TRUE; + if (m_isVolumeQueued) + { + if (!m_webAudioClient->setVolume(m_volume)) + { + GST_ERROR_OBJECT(m_sink, "Failed to set volume"); + result = FALSE; + } + else + { + m_isVolumeQueued = false; + } + } + if (m_isPlayingDelayed) + { + if (!m_webAudioClient->play()) + { + GST_ERROR_OBJECT(m_sink, "Failed to play web audio"); + result = FALSE; + } + else + { + m_isPlayingDelayed = false; + } + } + } + break; + } + default: + return gst_pad_event_default(pad, parent, event); + } + gst_event_unref(event); + return result; +} + +GstFlowReturn PushModeAudioPlaybackDelegate::handleBuffer(GstBuffer *buffer) +{ + if (m_webAudioClient->notifyNewSample(buffer)) + { + return GST_FLOW_OK; + } + else + { + GST_ERROR_OBJECT(m_sink, "Failed to push sample"); + return GST_FLOW_ERROR; + } +} + +void PushModeAudioPlaybackDelegate::postAsyncDone() +{ + m_isStateCommitNeeded = false; + gst_element_post_message(GST_ELEMENT_CAST(m_sink), + gst_message_new_async_done(GST_OBJECT_CAST(m_sink), GST_CLOCK_TIME_NONE)); +} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.h b/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.h new file mode 100644 index 000000000..a1b1359e0 --- /dev/null +++ b/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2025 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "Constants.h" +#include "ControlBackendInterface.h" +#include "GStreamerWebAudioPlayerClient.h" +#include "IPlaybackDelegate.h" +#include +#include +#include + +class PushModeAudioPlaybackDelegate : public IPlaybackDelegate +{ +public: + explicit PushModeAudioPlaybackDelegate(GstElement *sink); + ~PushModeAudioPlaybackDelegate() override; + + void handleEos() override; + void handleStateChanged(firebolt::rialto::PlaybackState state) override; + void handleError(const std::string &message, gint code = 0) override; + void handleQos(uint64_t processed, uint64_t dropped) const override; + GstStateChangeReturn changeState(GstStateChange transition) override; + void postAsyncStart() override; + void setProperty(const Property &type, const GValue *value) override; + void getProperty(const Property &type, GValue *value) override; + std::optional handleQuery(GstQuery *query) const override; + gboolean handleSendEvent(GstEvent *event) override; + gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; + GstFlowReturn handleBuffer(GstBuffer *buffer) override; + +private: + void postAsyncDone(); + +private: + GstElement *m_sink; + std::unique_ptr m_rialtoControlClient; + std::shared_ptr m_webAudioClient; + bool m_isPlayingDelayed{false}; + std::atomic m_isStateCommitNeeded{false}; + std::atomic m_volume{kDefaultVolume}; + std::atomic m_isVolumeQueued{false}; +}; \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/RialtoGSteamerPlugin.cpp b/middleware/rialto-gstreamer/source/RialtoGSteamerPlugin.cpp new file mode 100644 index 000000000..ef0978595 --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGSteamerPlugin.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "GstreamerCatLog.h" +#include "RialtoGStreamerMSEAudioSink.h" +#include "RialtoGStreamerMSESubtitleSink.h" +#include "RialtoGStreamerMSEVideoSink.h" +#include "RialtoGStreamerWebAudioSink.h" +#include +#include + +#ifndef PACKAGE +#define PACKAGE "rialto-gstreamer" +#endif + +static gboolean rialto_mse_sinks_init(GstPlugin *plugin) +{ + init_gst_debug_category(); + + const char kSrcRev[] = "N"; + const char kTags[] = "N"; + + if (std::strlen(kSrcRev) > 0) + { + if (std::strlen(kTags) > 0) + { + GST_INFO("Release Tag(s): %s (Commit ID: %s)", kTags, kSrcRev); + } + else + { + GST_INFO("Release Tag(s): No Release Tags! (Commit ID: %s)", kSrcRev); + } + } + else + { + GST_WARNING("Failed to get git commit ID!"); + } + + const char *socketPathStr = getenv("RIALTO_SOCKET_PATH"); + guint sinkRank = socketPathStr ? std::numeric_limits::max() : 0; + + const char *sinkRankStr = getenv("RIALTO_SINKS_RANK"); + if (sinkRankStr) + { + char *end; + unsigned long val = strtoul(sinkRankStr, &end, 10); + if (*end != '\0' || errno == ERANGE) + GST_WARNING("Failed to parse 'RIALTO_SINKS_RANK' env variable - '%s'", sinkRankStr); + else + sinkRank = val; + } + + if (sinkRank == 0) + { + GST_INFO("sinkRank has a value of 0"); + return true; + } + + GST_INFO("Registering plugins with rank %u", sinkRank); + + return gst_element_register(plugin, "rialtomsevideosink", sinkRank, RIALTO_TYPE_MSE_VIDEO_SINK) && + gst_element_register(plugin, "rialtomseaudiosink", sinkRank, RIALTO_TYPE_MSE_AUDIO_SINK) && + gst_element_register(plugin, "rialtomsesubtitlesink", sinkRank, RIALTO_TYPE_MSE_SUBTITLE_SINK) && + gst_element_register(plugin, "rialtowebaudiosink", sinkRank, RIALTO_TYPE_WEB_AUDIO_SINK); +} + +GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, rialtosinks, "Sinks which communicate with RialtoServer", + rialto_mse_sinks_init, "1.0", "LGPL", PACKAGE, "https://gstreamer.net") diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.cpp new file mode 100644 index 000000000..105d002c7 --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.cpp @@ -0,0 +1,374 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include +#include + +#include "GStreamerMSEUtils.h" +#include "IMediaPipelineCapabilities.h" +#include "PullModeAudioPlaybackDelegate.h" +#include "PushModeAudioPlaybackDelegate.h" +#include "RialtoGStreamerMSEAudioSink.h" +#include "RialtoGStreamerMSEBaseSinkPrivate.h" + +using namespace firebolt::rialto::client; + +GST_DEBUG_CATEGORY_STATIC(RialtoMSEAudioSinkDebug); +#define GST_CAT_DEFAULT RialtoMSEAudioSinkDebug + +#define rialto_mse_audio_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE(RialtoMSEAudioSink, rialto_mse_audio_sink, RIALTO_TYPE_MSE_BASE_SINK, + G_IMPLEMENT_INTERFACE(GST_TYPE_STREAM_VOLUME, NULL) + GST_DEBUG_CATEGORY_INIT(RialtoMSEAudioSinkDebug, "rialtomseaudiosink", 0, + "rialto mse audio sink")); + +enum +{ + PROP_0, + PROP_VOLUME, + PROP_MUTE, + PROP_GAP, + PROP_LOW_LATENCY, + PROP_SYNC, + PROP_SYNC_OFF, + PROP_STREAM_SYNC_MODE, + PROP_AUDIO_FADE, + PROP_FADE_VOLUME, + PROP_LIMIT_BUFFERING_MS, + PROP_USE_BUFFERING, + PROP_ASYNC, + PROP_WEBAUDIO, + PROP_LAST +}; + +static GstStateChangeReturn rialto_mse_audio_sink_change_state(GstElement *element, GstStateChange transition) +{ + RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(element); + if (GST_STATE_CHANGE_NULL_TO_READY == transition) + { + if (PlaybackMode::Pull == sink->priv->m_playbackMode) + { + GST_INFO_OBJECT(sink, "RialtoMSEAudioSink state change to READY. Initializing Pull Mode delegate"); + rialto_mse_base_sink_initialise_delegate(sink, std::make_shared(element)); + } + else // Push playback mode + { + GST_INFO_OBJECT(sink, "RialtoMSEAudioSink state change to READY. Initializing Push Mode delegate"); + rialto_mse_base_sink_initialise_delegate(sink, std::make_shared(element)); + } + } + + GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) + { + GST_WARNING_OBJECT(sink, "State change failed"); + return result; + } + + return result; +} + +static void rialto_mse_audio_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) +{ + RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(object); + switch (propId) + { + case PROP_VOLUME: + { + g_value_set_double(value, kDefaultVolume); + rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::Volume, value); + break; + } + case PROP_MUTE: + { + g_value_set_boolean(value, kDefaultMute); + rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::Mute, value); + break; + } + case PROP_SYNC: + { + g_value_set_boolean(value, kDefaultSync); + rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::Sync, value); + break; + } + case PROP_STREAM_SYNC_MODE: + { + g_value_set_int(value, kDefaultStreamSyncMode); + rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::StreamSyncMode, value); + break; + } + case PROP_FADE_VOLUME: + { + g_value_set_uint(value, kDefaultFadeVolume); + rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::FadeVolume, value); + break; + } + case PROP_LIMIT_BUFFERING_MS: + { + g_value_set_uint(value, kDefaultBufferingLimit); + rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::LimitBufferingMs, value); + break; + } + case PROP_USE_BUFFERING: + { + g_value_set_boolean(value, kDefaultUseBuffering); + rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::UseBuffering, value); + break; + } + case PROP_ASYNC: + { + g_value_set_boolean(value, TRUE); + rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::Async, value); + break; + } + case PROP_WEBAUDIO: + { + g_value_set_boolean(value, (sink->priv->m_playbackMode == PlaybackMode::Push)); + break; + } + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } + } +} + +static void rialto_mse_audio_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) +{ + RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(object); + switch (propId) + { + case PROP_VOLUME: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Volume, value); + break; + } + case PROP_MUTE: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Mute, value); + break; + } + case PROP_GAP: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Gap, value); + break; + } + case PROP_LOW_LATENCY: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::LowLatency, value); + break; + } + case PROP_SYNC: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Sync, value); + break; + } + case PROP_SYNC_OFF: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::SyncOff, value); + break; + } + case PROP_STREAM_SYNC_MODE: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::StreamSyncMode, value); + break; + } + case PROP_AUDIO_FADE: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::AudioFade, value); + break; + } + case PROP_LIMIT_BUFFERING_MS: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::LimitBufferingMs, value); + break; + } + case PROP_USE_BUFFERING: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::UseBuffering, value); + break; + } + case PROP_ASYNC: + { + rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Async, value); + break; + } + case PROP_WEBAUDIO: + { + if (GST_STATE(sink) > GST_STATE_NULL) + { + GST_ERROR_OBJECT(object, "Playback mode set too late - sink is not in NULL state"); + break; + } + if (TRUE == g_value_get_boolean(value)) + { + sink->priv->m_playbackMode = PlaybackMode::Push; + } + else + { + sink->priv->m_playbackMode = PlaybackMode::Pull; + } + break; + } + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } + } +} + +static void rialto_mse_audio_sink_init(RialtoMSEAudioSink *sink) +{ + RialtoMSEBaseSinkPrivate *priv = sink->parent.priv; + + if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink))) + { + GST_ERROR_OBJECT(sink, "Failed to initialise AUDIO sink. Sink pad initialisation failed."); + return; + } + + gst_pad_set_chain_function(priv->m_sinkPad, rialto_mse_base_sink_chain); + gst_pad_set_event_function(priv->m_sinkPad, rialto_mse_base_sink_event); +} + +static void rialto_mse_audio_sink_class_init(RialtoMSEAudioSinkClass *klass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); + GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); + gobjectClass->get_property = rialto_mse_audio_sink_get_property; + gobjectClass->set_property = rialto_mse_audio_sink_set_property; + elementClass->change_state = rialto_mse_audio_sink_change_state; + + g_object_class_install_property(gobjectClass, PROP_VOLUME, + g_param_spec_double("volume", "Volume", "Volume of this stream", 0, 1.0, + kDefaultVolume, + GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(gobjectClass, PROP_MUTE, + g_param_spec_boolean("mute", "Mute", "Mute status of this stream", kDefaultMute, + GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(gobjectClass, PROP_GAP, + g_param_spec_boxed("gap", "Gap", "Audio Gap", GST_TYPE_STRUCTURE, + (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(gobjectClass, PROP_USE_BUFFERING, + g_param_spec_boolean("use-buffering", + "Use buffering", "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds", + kDefaultUseBuffering, G_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, PROP_ASYNC, + g_param_spec_boolean("async", "Async", "Asynchronous mode", FALSE, G_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, PROP_WEBAUDIO, + g_param_spec_boolean("web-audio", + "Webaudio mode", "Enable webaudio mode. Property should be set before NULL->READY transition", + FALSE, G_PARAM_READWRITE)); + + std::unique_ptr mediaPlayerCapabilities = + firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities(); + if (mediaPlayerCapabilities) + { + std::vector supportedMimeTypes = + mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::AUDIO); + + rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes); + + const std::string kLowLatencyPropertyName{"low-latency"}; + const std::string kSyncPropertyName{"sync"}; + const std::string kSyncOffPropertyName{"sync-off"}; + const std::string kStreamSyncModePropertyName{"stream-sync-mode"}; + const std::string kAudioFadePropertyName{"audio-fade"}; + const std::string kFadeVolumePropertyName{"fade-volume"}; + const std::string kBufferingLimitPropertyName{"limit-buffering-ms"}; + const std::vector kPropertyNamesToSearch{kLowLatencyPropertyName, kSyncPropertyName, + kSyncOffPropertyName, kStreamSyncModePropertyName, + kBufferingLimitPropertyName, kAudioFadePropertyName, + kFadeVolumePropertyName}; + std::vector supportedProperties{ + mediaPlayerCapabilities->getSupportedProperties(firebolt::rialto::MediaSourceType::AUDIO, + kPropertyNamesToSearch)}; + + for (auto it = supportedProperties.begin(); it != supportedProperties.end(); ++it) + { + if (kLowLatencyPropertyName == *it) + { + g_object_class_install_property(gobjectClass, PROP_LOW_LATENCY, + g_param_spec_boolean(kLowLatencyPropertyName.c_str(), + "low latency", "Turn on low latency mode, for use with gaming (no audio decoding, no a/v sync)", + kDefaultLowLatency, GParamFlags(G_PARAM_WRITABLE))); + } + else if (kSyncPropertyName == *it) + { + g_object_class_install_property(gobjectClass, PROP_SYNC, + g_param_spec_boolean(kSyncPropertyName.c_str(), "sync", "Clock sync", + kDefaultSync, GParamFlags(G_PARAM_READWRITE))); + } + else if (kSyncOffPropertyName == *it) + { + g_object_class_install_property(gobjectClass, PROP_SYNC_OFF, + g_param_spec_boolean(kSyncOffPropertyName.c_str(), + "sync off", "Turn on free running audio. Must be set before pipeline is PLAYING state.", + kDefaultSyncOff, GParamFlags(G_PARAM_WRITABLE))); + } + else if (kStreamSyncModePropertyName == *it) + { + g_object_class_install_property(gobjectClass, PROP_STREAM_SYNC_MODE, + g_param_spec_int(kStreamSyncModePropertyName.c_str(), + "stream sync mode", "1 - Frame to decode frame will immediately proceed next frame sync, 0 - Frame decoded with no frame sync", + 0, G_MAXINT, kDefaultStreamSyncMode, + GParamFlags(G_PARAM_READWRITE))); + } + else if (kAudioFadePropertyName == *it) + { + g_object_class_install_property(gobjectClass, PROP_AUDIO_FADE, + g_param_spec_string(kAudioFadePropertyName.c_str(), + "audio fade", "Start audio fade (vol[0-100],duration ms,easetype[(L)inear,Cubic(I)n,Cubic(O)ut])", + kDefaultAudioFade, GParamFlags(G_PARAM_WRITABLE))); + } + else if (kFadeVolumePropertyName == *it) + { + g_object_class_install_property(gobjectClass, PROP_FADE_VOLUME, + g_param_spec_uint(kFadeVolumePropertyName.c_str(), "fade volume", + "Get current fade volume", 0, 100, kDefaultFadeVolume, + G_PARAM_READABLE)); + } + else if (kBufferingLimitPropertyName == *it) + { + constexpr uint32_t kMaxValue{20000}; + g_object_class_install_property(gobjectClass, PROP_LIMIT_BUFFERING_MS, + g_param_spec_uint("limit-buffering-ms", + "limit buffering ms", "Set millisecond threshold used if limit_buffering is set. Changing this value does not enable/disable limit_buffering", + 0, kMaxValue, kDefaultBufferingLimit, + G_PARAM_READWRITE)); + } + else + { + GST_ERROR("Unexpected property %s returned from rialto", it->c_str()); + } + } + } + else + { + GST_ERROR("Failed to get supported mime types for AUDIO"); + } + + gst_element_class_set_details_simple(elementClass, "Rialto Audio Sink", "Decoder/Audio/Sink/Audio", + "Communicates with Rialto Server", " "); +} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.h new file mode 100644 index 000000000..9e7b3e800 --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "GStreamerMSEMediaPlayerClient.h" +#include "RialtoGStreamerMSEBaseSink.h" +#include +#include + +G_BEGIN_DECLS + +#define RIALTO_TYPE_MSE_AUDIO_SINK (rialto_mse_audio_sink_get_type()) +#define RIALTO_MSE_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_MSE_AUDIO_SINK, RialtoMSEAudioSink)) +#define RIALTO_MSE_AUDIO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_MSE_AUDIO_SINK, RialtoMSEAudioSinkClass)) +#define RIALTO_IS_MSE_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_MSE_AUDIO_SINK)) +#define RIALTO_IS_MSE_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_MSE_AUDIO_SINK)) + +typedef struct _RialtoMSEAudioSink RialtoMSEAudioSink; +typedef struct _RialtoMSEAudioSinkClass RialtoMSEAudioSinkClass; + +struct _RialtoMSEAudioSink +{ + RialtoMSEBaseSink parent; +}; + +struct _RialtoMSEAudioSinkClass +{ + RialtoMSEBaseSinkClass parent_class; +}; + +GType rialto_mse_audio_sink_get_type(void); + +void rialto_mse_audio_sink_set_client_backend(GstElement *sink, + const std::shared_ptr &mediaPlayerClient); +G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.cpp new file mode 100644 index 000000000..31f1e2dc8 --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.cpp @@ -0,0 +1,331 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define USE_GLIB 1 + +#include +#include + +#include + +#include "ControlBackend.h" +#include "GStreamerUtils.h" +#include "IClientLogControl.h" +#include "IMediaPipeline.h" +#include "LogToGstHandler.h" +#include "RialtoGStreamerMSEBaseSink.h" +#include "RialtoGStreamerMSEBaseSinkPrivate.h" + +GST_DEBUG_CATEGORY_STATIC(RialtoMSEBaseSinkDebug); +#define GST_CAT_DEFAULT RialtoMSEBaseSinkDebug + +#define rialto_mse_base_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE(RialtoMSEBaseSink, rialto_mse_base_sink, GST_TYPE_ELEMENT, + G_ADD_PRIVATE(RialtoMSEBaseSink) + GST_DEBUG_CATEGORY_INIT(RialtoMSEBaseSinkDebug, "rialtomsebasesink", 0, + "rialto mse base sink")); + +enum +{ + PROP_0, + PROP_IS_SINGLE_PATH_STREAM, + PROP_N_STREAMS, + PROP_HAS_DRM, + PROP_STATS, + PROP_LAST +}; + +enum +{ + SIGNAL_UNDERFLOW, + SIGNAL_LAST +}; + +static guint g_signals[SIGNAL_LAST] = {0}; + +void rialto_mse_base_sink_initialise_delegate(RialtoMSEBaseSink *sink, const std::shared_ptr &delegate) +{ + std::unique_lock lock{sink->priv->m_sinkMutex}; + sink->priv->m_delegate = delegate; + + for (auto &[type, value] : sink->priv->m_queuedProperties) + { + delegate->setProperty(type, &value); + g_value_unset(&value); + } + sink->priv->m_queuedProperties.clear(); +} + +static std::shared_ptr rialto_mse_base_sink_get_delegate(RialtoMSEBaseSink *sink) +{ + std::unique_lock lock{sink->priv->m_sinkMutex}; + if (!sink->priv->m_delegate) + { + GST_ERROR_OBJECT(sink, "Sink delegate not initialized"); + } + return sink->priv->m_delegate; +} + +static gboolean rialto_mse_base_sink_send_event(GstElement *element, GstEvent *event) +{ + if (auto delegate = rialto_mse_base_sink_get_delegate(RIALTO_MSE_BASE_SINK(element))) + { + return delegate->handleSendEvent(event); + } + return FALSE; +} + +gboolean rialto_mse_base_sink_event(GstPad *pad, GstObject *parent, GstEvent *event) +{ + if (auto delegate = rialto_mse_base_sink_get_delegate(RIALTO_MSE_BASE_SINK(parent))) + { + return delegate->handleEvent(pad, parent, event); + } + return FALSE; +} + +GstFlowReturn rialto_mse_base_sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buf) +{ + if (auto delegate = rialto_mse_base_sink_get_delegate(RIALTO_MSE_BASE_SINK(parent))) + { + return delegate->handleBuffer(buf); + } + return GST_FLOW_ERROR; +} + +static gboolean rialto_mse_base_sink_query(GstElement *element, GstQuery *query) +{ + RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(element); + if (auto delegate = rialto_mse_base_sink_get_delegate(sink)) + { + std::optional result{delegate->handleQuery(query)}; + if (result.has_value()) + { + return result.value(); + } + GstElement *parent = GST_ELEMENT(&sink->parent); + return GST_ELEMENT_CLASS(parent_class)->query(parent, query); + } + return FALSE; +} + +static GstStateChangeReturn rialto_mse_base_sink_change_state(GstElement *element, GstStateChange transition) +{ + RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(element); + if (auto delegate = rialto_mse_base_sink_get_delegate(sink)) + { + GstStateChangeReturn status = delegate->changeState(transition); + if (GST_STATE_CHANGE_FAILURE != status) + { + if (GST_STATE_CHANGE_READY_TO_NULL == transition) + { + sink->priv->m_delegate.reset(); + } + GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) + { + GST_WARNING_OBJECT(sink, "State change failed"); + return result; + } + else if (result == GST_STATE_CHANGE_ASYNC) + { + return GST_STATE_CHANGE_ASYNC; + } + } + return status; + } + return GST_STATE_CHANGE_FAILURE; +} + +void rialto_mse_base_sink_handle_get_property(RialtoMSEBaseSink *sink, const IPlaybackDelegate::Property &property, + GValue *value) +{ + if (auto delegate = rialto_mse_base_sink_get_delegate(sink)) + { + delegate->getProperty(property, value); + } + else // Copy queued value if present + { + std::unique_lock lock{sink->priv->m_sinkMutex}; + if (sink->priv->m_queuedProperties.find(property) != sink->priv->m_queuedProperties.end()) + { + g_value_copy(&sink->priv->m_queuedProperties[property], value); + } + } +} + +void rialto_mse_base_sink_handle_set_property(RialtoMSEBaseSink *sink, const IPlaybackDelegate::Property &property, + const GValue *value) +{ + if (auto delegate = rialto_mse_base_sink_get_delegate(sink)) + { + delegate->setProperty(property, value); + } + else + { + std::unique_lock lock{sink->priv->m_sinkMutex}; + sink->priv->m_queuedProperties[property] = G_VALUE_INIT; + g_value_init(&(sink->priv->m_queuedProperties[property]), G_VALUE_TYPE(value)); + g_value_copy(value, &(sink->priv->m_queuedProperties[property])); + } +} + +static void rialto_mse_base_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) +{ + switch (propId) + { + case PROP_IS_SINGLE_PATH_STREAM: + // Set default value if it can't be acquired + g_value_set_boolean(value, FALSE); + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::IsSinglePathStream, value); + break; + case PROP_N_STREAMS: + // Set default value if it can't be acquired + g_value_set_int(value, 1); + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::NumberOfStreams, value); + break; + case PROP_HAS_DRM: + // Set default value if it can't be acquired + g_value_set_boolean(value, TRUE); + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::HasDrm, + value); + break; + case PROP_STATS: + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Stats, value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } +} + +static void rialto_mse_base_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) +{ + switch (propId) + { + case PROP_IS_SINGLE_PATH_STREAM: + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::IsSinglePathStream, value); + break; + case PROP_N_STREAMS: + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::NumberOfStreams, value); + break; + case PROP_HAS_DRM: + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::HasDrm, + value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } +} + +void rialto_mse_base_handle_rialto_server_sent_buffer_underflow(RialtoMSEBaseSink *sink) +{ + GST_WARNING_OBJECT(sink, "Sending underflow signal"); + // send 2 last parameters just to be compatible with RDK's buffer-underflow-callback signal signature + g_signal_emit(G_OBJECT(sink), g_signals[SIGNAL_UNDERFLOW], 0, 0, nullptr); +} + +bool rialto_mse_base_sink_initialise_sinkpad(RialtoMSEBaseSink *sink) +{ + GstPadTemplate *pad_template = + gst_element_class_get_pad_template(GST_ELEMENT_CLASS(G_OBJECT_GET_CLASS(sink)), "sink"); + if (!pad_template) + { + GST_ERROR_OBJECT(sink, "Could not find sink pad template"); + return false; + } + + GstPad *sinkPad = gst_pad_new_from_template(pad_template, "sink"); + if (!sinkPad) + { + GST_ERROR_OBJECT(sink, "Could not create sinkpad"); + return false; + } + + gst_element_add_pad(GST_ELEMENT_CAST(sink), sinkPad); + sink->priv->m_sinkPad = sinkPad; + + return true; +} + +static void rialto_mse_base_sink_init(RialtoMSEBaseSink *sink) +{ + GST_INFO_OBJECT(sink, "Init: %" GST_PTR_FORMAT, sink); + sink->priv = static_cast(rialto_mse_base_sink_get_instance_private(sink)); + new (sink->priv) RialtoMSEBaseSinkPrivate(); + + GST_OBJECT_FLAG_SET(sink, GST_ELEMENT_FLAG_SINK); +} + +static void rialto_mse_base_sink_finalize(GObject *object) +{ + RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(object); + RialtoMSEBaseSinkPrivate *priv = sink->priv; + GST_INFO_OBJECT(sink, "Finalize: %" GST_PTR_FORMAT " %" GST_PTR_FORMAT, sink, priv); + + priv->~RialtoMSEBaseSinkPrivate(); + GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); +} + +static void rialto_mse_base_sink_class_init(RialtoMSEBaseSinkClass *klass) +{ + std::shared_ptr logToGstHandler = + std::make_shared(); + if (!firebolt::rialto::IClientLogControlFactory::createFactory()->createClientLogControl().registerLogHandler(logToGstHandler, + true)) + { + GST_ERROR("Unable to preRegister log handler"); + } + + GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); + GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); + + gst_element_class_set_metadata(elementClass, "Rialto MSE base sink", "Generic", "A sink for Rialto", " "); + + gobjectClass->finalize = rialto_mse_base_sink_finalize; + gobjectClass->get_property = rialto_mse_base_sink_get_property; + gobjectClass->set_property = rialto_mse_base_sink_set_property; + elementClass->query = rialto_mse_base_sink_query; + elementClass->send_event = rialto_mse_base_sink_send_event; + elementClass->change_state = rialto_mse_base_sink_change_state; + + g_signals[SIGNAL_UNDERFLOW] = g_signal_new("buffer-underflow-callback", G_TYPE_FROM_CLASS(klass), + (GSignalFlags)(G_SIGNAL_RUN_LAST), 0, nullptr, nullptr, + g_cclosure_marshal_VOID__UINT_POINTER, G_TYPE_NONE, 2, G_TYPE_UINT, + G_TYPE_POINTER); + + g_object_class_install_property(gobjectClass, PROP_IS_SINGLE_PATH_STREAM, + g_param_spec_boolean("single-path-stream", "single path stream", + "is single path stream", FALSE, GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_N_STREAMS, + g_param_spec_int("streams-number", "streams number", "streams number", 1, G_MAXINT, + 1, GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_HAS_DRM, + g_param_spec_boolean("has-drm", "has drm", "has drm", TRUE, + GParamFlags(G_PARAM_READWRITE))); + g_object_class_install_property(gobjectClass, PROP_STATS, + g_param_spec_pointer("stats", NULL, "pointer to a gst_structure", + GParamFlags(G_PARAM_READABLE))); +} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.h new file mode 100644 index 000000000..714fb57c2 --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "GStreamerUtils.h" +#include "IPlaybackDelegate.h" +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define RIALTO_TYPE_MSE_BASE_SINK (rialto_mse_base_sink_get_type()) +#define RIALTO_MSE_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_MSE_BASE_SINK, RialtoMSEBaseSink)) +#define RIALTO_MSE_BASE_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_MSE_BASE_SINK, RialtoMSEBaseSinkClass)) +#define RIALTO_IS_MSE_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_MSE_BASE_SINK)) +#define RIALTO_IS_MSE_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_MSE_BASE_SINK)) + +typedef struct _RialtoMSEBaseSink RialtoMSEBaseSink; +typedef struct _RialtoMSEBaseSinkClass RialtoMSEBaseSinkClass; +typedef struct _RialtoMSEBaseSinkPrivate RialtoMSEBaseSinkPrivate; + +struct _RialtoMSEBaseSink +{ + GstElement parent; + RialtoMSEBaseSinkPrivate *priv; +}; + +struct _RialtoMSEBaseSinkClass +{ + GstElementClass parent_class; +}; + +namespace firebolt::rialto::client +{ +class MediaPlayerBackend; +} + +GType rialto_mse_base_sink_get_type(void); + +void rialto_mse_base_sink_initialise_delegate(RialtoMSEBaseSink *sink, + const std::shared_ptr &delegate); +void rialto_mse_base_sink_handle_get_property(RialtoMSEBaseSink *sink, const IPlaybackDelegate::Property &property, + GValue *value); +void rialto_mse_base_sink_handle_set_property(RialtoMSEBaseSink *sink, const IPlaybackDelegate::Property &property, + const GValue *value); + +GstFlowReturn rialto_mse_base_sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buf); +gboolean rialto_mse_base_sink_event(GstPad *pad, GstObject *parent, GstEvent *event); +bool rialto_mse_base_sink_initialise_sinkpad(RialtoMSEBaseSink *sink); + +void rialto_mse_base_handle_rialto_server_sent_buffer_underflow(RialtoMSEBaseSink *sink); + +G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSinkPrivate.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSinkPrivate.h new file mode 100644 index 000000000..2b0d6eb26 --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSinkPrivate.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include + +#include + +#include "ControlBackendInterface.h" +#include "IPlaybackDelegate.h" +#include "MediaPlayerManager.h" +#include +#include +#include +#include +#include +#include + +enum class PlaybackMode +{ + Pull, + Push +}; + +G_BEGIN_DECLS + +struct _RialtoMSEBaseSinkPrivate +{ + _RialtoMSEBaseSinkPrivate() = default; + ~_RialtoMSEBaseSinkPrivate() = default; + + GstPad *m_sinkPad{nullptr}; + std::mutex m_sinkMutex; + std::shared_ptr m_delegate{nullptr}; + std::map m_queuedProperties{}; + std::atomic m_playbackMode{PlaybackMode::Pull}; +}; +G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.cpp new file mode 100644 index 000000000..646258e06 --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2024 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "GStreamerEMEUtils.h" +#include "GStreamerMSEUtils.h" +#include "IMediaPipelineCapabilities.h" +#include "PullModeSubtitlePlaybackDelegate.h" +#include "RialtoGStreamerMSEBaseSinkPrivate.h" +#include "RialtoGStreamerMSESubtitleSink.h" + +using namespace firebolt::rialto::client; + +GST_DEBUG_CATEGORY_STATIC(RialtoMSESubtitleSinkDebug); +#define GST_CAT_DEFAULT RialtoMSESubtitleSinkDebug + +#define rialto_mse_subtitle_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE(RialtoMSESubtitleSink, rialto_mse_subtitle_sink, RIALTO_TYPE_MSE_BASE_SINK, + GST_DEBUG_CATEGORY_INIT(RialtoMSESubtitleSinkDebug, "rialtomsesubtitlesink", 0, + "rialto mse subtitle sink")); + +enum +{ + PROP_0, + PROP_MUTE, + PROP_TEXT_TRACK_IDENTIFIER, + PROP_WINDOW_ID, + PROP_ASYNC, + PROP_LAST +}; + +static GstStateChangeReturn rialto_mse_subtitle_sink_change_state(GstElement *element, GstStateChange transition) +{ + RialtoMSESubtitleSink *sink = RIALTO_MSE_SUBTITLE_SINK(element); + + if (GST_STATE_CHANGE_NULL_TO_READY == transition) + { + GST_INFO_OBJECT(sink, "RialtoMSESubtitleSink state change to READY. Initializing delegate"); + rialto_mse_base_sink_initialise_delegate(RIALTO_MSE_BASE_SINK(sink), + std::make_shared(element)); + } + + GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) + { + GST_WARNING_OBJECT(sink, "State change failed"); + return result; + } + + return result; +} + +static void rialto_mse_subtitle_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) +{ + switch (propId) + { + case PROP_MUTE: + { + g_value_set_boolean(value, FALSE); // Set default value first + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Mute, value); + break; + } + case PROP_TEXT_TRACK_IDENTIFIER: + { + g_value_set_string(value, ""); // Set default value first + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::TextTrackIdentifier, value); + break; + } + case PROP_WINDOW_ID: + { + g_value_set_uint(value, 0); // Set default value first + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowId, + value); + break; + } + case PROP_ASYNC: + { + g_value_set_boolean(value, FALSE); // Set default value first + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Async, value); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } +} + +static void rialto_mse_subtitle_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) +{ + switch (propId) + { + case PROP_MUTE: + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Mute, value); + break; + case PROP_TEXT_TRACK_IDENTIFIER: + { + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::TextTrackIdentifier, value); + break; + } + case PROP_WINDOW_ID: + { + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowId, + value); + break; + } + case PROP_ASYNC: + { + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Async, value); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } +} + +static void rialto_mse_subtitle_sink_init(RialtoMSESubtitleSink *sink) +{ + RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv; + + if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink))) + { + GST_ERROR_OBJECT(sink, "Failed to initialise SUBTITLE sink. Sink pad initialisation failed."); + return; + } + + gst_pad_set_chain_function(basePriv->m_sinkPad, rialto_mse_base_sink_chain); + gst_pad_set_event_function(basePriv->m_sinkPad, rialto_mse_base_sink_event); +} + +static void rialto_mse_subtitle_sink_class_init(RialtoMSESubtitleSinkClass *klass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); + GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); + gobjectClass->get_property = rialto_mse_subtitle_sink_get_property; + gobjectClass->set_property = rialto_mse_subtitle_sink_set_property; + elementClass->change_state = rialto_mse_subtitle_sink_change_state; + + g_object_class_install_property(gobjectClass, PROP_MUTE, + g_param_spec_boolean("mute", "Mute", "Mute subtitles", FALSE, G_PARAM_READWRITE)); + + g_object_class_install_property(gobjectClass, PROP_TEXT_TRACK_IDENTIFIER, + g_param_spec_string("text-track-identifier", "Text Track Identifier", + "Identifier of text track. Valid input for service is " + "\"CC[1-4]\", \"TEXT[1-4]\", \"SERVICE[1-64]\"", + nullptr, GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_WINDOW_ID, + g_param_spec_uint("window-id", "Window ID", "Id of window (placeholder)", 0, 256, 0, + GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_ASYNC, + g_param_spec_boolean("async", "Async", "Asynchronous mode", FALSE, G_PARAM_READWRITE)); + + std::unique_ptr mediaPlayerCapabilities = + firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities(); + if (mediaPlayerCapabilities) + { + std::vector supportedMimeTypes = + mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::SUBTITLE); + + rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes); + } + else + { + GST_ERROR("Failed to get supported mime types for Subtitle"); + } + + gst_element_class_set_details_simple(elementClass, "Rialto Subtitle Sink", "Parser/Subtitle/Sink/Subtitle", + "Communicates with Rialto Server", " "); +} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.h new file mode 100644 index 000000000..3e6e5813d --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2024 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "GStreamerMSEMediaPlayerClient.h" +#include "RialtoGStreamerMSEBaseSink.h" +#include +#include + +G_BEGIN_DECLS + +#define RIALTO_TYPE_MSE_SUBTITLE_SINK (rialto_mse_subtitle_sink_get_type()) +#define RIALTO_MSE_SUBTITLE_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_MSE_SUBTITLE_SINK, RialtoMSESubtitleSink)) +#define RIALTO_MSE_SUBTITLE_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_MSE_SUBTITLE_SINK, RialtoMSESubtitleSinkClass)) +#define RIALTO_IS_MSE_SUBTITLE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_MSE_SUBTITLE_SINK)) +#define RIALTO_IS_MSE_SUBTITLE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_MSE_SUBTITLE_SINK)) + +typedef struct _RialtoMSESubtitleSink RialtoMSESubtitleSink; +typedef struct _RialtoMSESubtitleSinkClass RialtoMSESubtitleSinkClass; + +struct _RialtoMSESubtitleSink +{ + RialtoMSEBaseSink parent; +}; + +struct _RialtoMSESubtitleSinkClass +{ + RialtoMSEBaseSinkClass parent_class; +}; + +GType rialto_mse_subtitle_sink_get_type(void); + +void rialto_mse_subtitle_sink_set_client_backend(GstElement *sink, + const std::shared_ptr &mediaPlayerClient); +G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.cpp new file mode 100644 index 000000000..2bf231d6d --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.cpp @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "GStreamerEMEUtils.h" +#include "GStreamerMSEUtils.h" +#include "IMediaPipelineCapabilities.h" +#include "PullModeVideoPlaybackDelegate.h" +#include "RialtoGStreamerMSEBaseSinkPrivate.h" +#include "RialtoGStreamerMSEVideoSink.h" + +using namespace firebolt::rialto::client; + +GST_DEBUG_CATEGORY_STATIC(RialtoMSEVideoSinkDebug); +#define GST_CAT_DEFAULT RialtoMSEVideoSinkDebug + +#define rialto_mse_video_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE(RialtoMSEVideoSink, rialto_mse_video_sink, RIALTO_TYPE_MSE_BASE_SINK, + GST_DEBUG_CATEGORY_INIT(RialtoMSEVideoSinkDebug, "rialtomsevideosink", 0, + "rialto mse video sink")); + +enum +{ + PROP_0, + PROP_WINDOW_SET, + PROP_MAX_VIDEO_WIDTH, + PROP_MAX_VIDEO_HEIGHT, + PROP_MAX_VIDEO_WIDTH_DEPRECATED, + PROP_MAX_VIDEO_HEIGHT_DEPRECATED, + PROP_FRAME_STEP_ON_PREROLL, + PROP_IMMEDIATE_OUTPUT, + PROP_SYNCMODE_STREAMING, + PROP_SHOW_VIDEO_WINDOW, + PROP_IS_MASTER, + PROP_LAST +}; + +static GstStateChangeReturn rialto_mse_video_sink_change_state(GstElement *element, GstStateChange transition) +{ + RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(element); + if (GST_STATE_CHANGE_NULL_TO_READY == transition) + { + GST_INFO_OBJECT(sink, "RialtoMSEVideoSink state change to READY. Initializing delegate"); + rialto_mse_base_sink_initialise_delegate(RIALTO_MSE_BASE_SINK(sink), + std::make_shared(element)); + } + GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) + { + GST_WARNING_OBJECT(sink, "State change failed"); + return result; + } + + return result; +} + +static void rialto_mse_video_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) +{ + switch (propId) + { + case PROP_WINDOW_SET: + { + g_value_set_string(value, "0,0,1920,1080"); // Set default value + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowSet, + value); + break; + } + case PROP_MAX_VIDEO_WIDTH_DEPRECATED: + GST_WARNING_OBJECT(object, "MaxVideoWidth property is deprecated. Use 'max-video-width' instead"); + case PROP_MAX_VIDEO_WIDTH: + { + g_value_set_uint(value, 0); // Set default value + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::MaxVideoWidth, value); + break; + } + case PROP_MAX_VIDEO_HEIGHT_DEPRECATED: + GST_WARNING_OBJECT(object, "MaxVideoHeight property is deprecated. Use 'max-video-height' instead"); + case PROP_MAX_VIDEO_HEIGHT: + { + g_value_set_uint(value, 0); // Set default value + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::MaxVideoHeight, value); + break; + } + case PROP_FRAME_STEP_ON_PREROLL: + { + g_value_set_boolean(value, FALSE); // Set default value + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::FrameStepOnPreroll, value); + break; + } + case PROP_IMMEDIATE_OUTPUT: + { + g_value_set_boolean(value, FALSE); // Set default value + rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::ImmediateOutput, value); + break; + } + case PROP_IS_MASTER: + { + g_value_set_boolean(value, TRUE); // Set default value + std::unique_ptr mediaPlayerCapabilities = + firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities(); + bool isMaster{false}; + if (mediaPlayerCapabilities && mediaPlayerCapabilities->isVideoMaster(isMaster)) + { + g_value_set_boolean(value, isMaster); + } + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } +} + +static void rialto_mse_video_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) +{ + switch (propId) + { + case PROP_WINDOW_SET: + { + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowSet, + value); + break; + } + case PROP_MAX_VIDEO_WIDTH: + case PROP_MAX_VIDEO_WIDTH_DEPRECATED: + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::MaxVideoWidth, value); + break; + case PROP_MAX_VIDEO_HEIGHT: + case PROP_MAX_VIDEO_HEIGHT_DEPRECATED: + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::MaxVideoHeight, value); + break; + case PROP_FRAME_STEP_ON_PREROLL: + { + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::FrameStepOnPreroll, value); + break; + } + case PROP_IMMEDIATE_OUTPUT: + { + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::ImmediateOutput, value); + break; + } + case PROP_SYNCMODE_STREAMING: + { + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::SyncmodeStreaming, value); + break; + } + case PROP_SHOW_VIDEO_WINDOW: + { + rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), + IPlaybackDelegate::Property::ShowVideoWindow, value); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } +} + +static void rialto_mse_video_sink_init(RialtoMSEVideoSink *sink) +{ + RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv; + + if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink))) + { + GST_ERROR_OBJECT(sink, "Failed to initialise VIDEO sink. Sink pad initialisation failed."); + return; + } + + gst_pad_set_chain_function(basePriv->m_sinkPad, rialto_mse_base_sink_chain); + gst_pad_set_event_function(basePriv->m_sinkPad, rialto_mse_base_sink_event); +} + +static void rialto_mse_video_sink_class_init(RialtoMSEVideoSinkClass *klass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); + GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); + gobjectClass->get_property = rialto_mse_video_sink_get_property; + gobjectClass->set_property = rialto_mse_video_sink_set_property; + elementClass->change_state = rialto_mse_video_sink_change_state; + + g_object_class_install_property(gobjectClass, PROP_WINDOW_SET, + g_param_spec_string("rectangle", "rectangle", "Window Set Format: x,y,width,height", + nullptr, GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_WIDTH, + g_param_spec_uint("max-video-width", + "max video width", "Maximum width of video frames to be decoded. Should only be set for video only streams.", + 0, 3840, DEFAULT_MAX_VIDEO_WIDTH, GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_HEIGHT, + g_param_spec_uint("max-video-height", + "max video height", "Maximum height of video frames to be decoded. should only be set for video only streams.", + 0, 2160, DEFAULT_MAX_VIDEO_HEIGHT, GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_WIDTH_DEPRECATED, + g_param_spec_uint("maxVideoWidth", "maxVideoWidth", "[DEPRECATED] Use max-video-width", + 0, 3840, DEFAULT_MAX_VIDEO_WIDTH, GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_HEIGHT_DEPRECATED, + g_param_spec_uint("maxVideoHeight", "maxVideoHeight", "[DEPRECATED] max-video-height", + 0, 2160, DEFAULT_MAX_VIDEO_HEIGHT, GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_FRAME_STEP_ON_PREROLL, + g_param_spec_boolean("frame-step-on-preroll", "frame step on preroll", + "allow frame stepping on preroll into pause", FALSE, + G_PARAM_READWRITE)); + g_object_class_install_property(gobjectClass, PROP_IS_MASTER, + g_param_spec_boolean("is-master", "is master", + "Checks if the platform is video master", TRUE, + G_PARAM_READABLE)); + + std::unique_ptr mediaPlayerCapabilities = + firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities(); + if (mediaPlayerCapabilities) + { + std::vector supportedMimeTypes = + mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::VIDEO); + + rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes); + + const std::string kImmediateOutputPropertyName{"immediate-output"}; + const std::string kSyncmodeStreamingPropertyName{"syncmode-streaming"}; + const std::string kShowVideoWindowPropertyName{"show-video-window"}; + const std::vector kPropertyNamesToSearch{kImmediateOutputPropertyName, + kSyncmodeStreamingPropertyName, + kShowVideoWindowPropertyName}; + std::vector supportedProperties{ + mediaPlayerCapabilities->getSupportedProperties(firebolt::rialto::MediaSourceType::VIDEO, + kPropertyNamesToSearch)}; + + for (const auto &propertyName : supportedProperties) + { + if (kImmediateOutputPropertyName == propertyName) + { + g_object_class_install_property(gobjectClass, PROP_IMMEDIATE_OUTPUT, + g_param_spec_boolean(kImmediateOutputPropertyName.c_str(), + "immediate output", "immediate output", TRUE, + GParamFlags(G_PARAM_READWRITE))); + } + else if (kSyncmodeStreamingPropertyName == propertyName) + { + g_object_class_install_property(gobjectClass, PROP_SYNCMODE_STREAMING, + g_param_spec_boolean("syncmode-streaming", "Streaming Sync Mode", + "Enable/disable OTT streaming sync mode", FALSE, + G_PARAM_WRITABLE)); + } + else if (kShowVideoWindowPropertyName == propertyName) + { + g_object_class_install_property(gobjectClass, PROP_SHOW_VIDEO_WINDOW, + g_param_spec_boolean(kShowVideoWindowPropertyName.c_str(), + "make video window visible", + "true: visible, false: hidden", TRUE, + G_PARAM_WRITABLE)); + } + } + } + else + { + GST_ERROR("Failed to get supported mime types for VIDEO"); + } + + gst_element_class_set_details_simple(elementClass, "Rialto Video Sink", "Decoder/Video/Sink/Video", + "Communicates with Rialto Server", " "); +} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.h new file mode 100644 index 000000000..989981ffc --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "GStreamerMSEMediaPlayerClient.h" +#include "RialtoGStreamerMSEBaseSink.h" +#include +#include + +G_BEGIN_DECLS + +#define RIALTO_TYPE_MSE_VIDEO_SINK (rialto_mse_video_sink_get_type()) +#define RIALTO_MSE_VIDEO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_MSE_VIDEO_SINK, RialtoMSEVideoSink)) +#define RIALTO_MSE_VIDEO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_MSE_VIDEO_SINK, RialtoMSEVideoSinkClass)) +#define RIALTO_IS_MSE_VIDEO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_MSE_VIDEO_SINK)) +#define RIALTO_IS_MSE_VIDEO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_MSE_VIDEO_SINK)) + +typedef struct _RialtoMSEVideoSink RialtoMSEVideoSink; +typedef struct _RialtoMSEVideoSinkClass RialtoMSEVideoSinkClass; + +struct _RialtoMSEVideoSink +{ + RialtoMSEBaseSink parent; +}; + +struct _RialtoMSEVideoSinkClass +{ + RialtoMSEBaseSinkClass parent_class; +}; + +GType rialto_mse_video_sink_get_type(void); + +void rialto_mse_video_sink_set_client_backend(GstElement *sink, + const std::shared_ptr &mediaPlayerClient); +G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.cpp new file mode 100644 index 000000000..98dbad2fe --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.cpp @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "Constants.h" +#include "PushModeAudioPlaybackDelegate.h" +#include "RialtoGStreamerWebAudioSink.h" + +using namespace firebolt::rialto::client; + +GST_DEBUG_CATEGORY_STATIC(RialtoWebAudioSinkDebug); +#define GST_CAT_DEFAULT RialtoWebAudioSinkDebug + +#define rialto_web_audio_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE(RialtoWebAudioSink, rialto_web_audio_sink, GST_TYPE_ELEMENT, + G_ADD_PRIVATE(RialtoWebAudioSink) + GST_DEBUG_CATEGORY_INIT(RialtoWebAudioSinkDebug, "rialtowebaudiosink", 0, + "rialto web audio sink")); +enum +{ + PROP_0, + PROP_TS_OFFSET, + PROP_VOLUME, + PROP_LAST +}; + +void rialto_web_audio_sink_initialise_delegate(RialtoWebAudioSink *sink, + const std::shared_ptr &delegate) +{ + std::unique_lock lock{sink->priv->m_sinkMutex}; + sink->priv->m_delegate = delegate; + + for (auto &[type, value] : sink->priv->m_queuedProperties) + { + delegate->setProperty(type, &value); + g_value_unset(&value); + } + sink->priv->m_queuedProperties.clear(); +} + +static std::shared_ptr rialto_web_audio_sink_get_delegate(RialtoWebAudioSink *sink) +{ + std::unique_lock lock{sink->priv->m_sinkMutex}; + if (!sink->priv->m_delegate) + { + GST_ERROR_OBJECT(sink, "Sink delegate not initialized"); + } + return sink->priv->m_delegate; +} + +static void rialto_web_audio_sink_handle_get_property(RialtoWebAudioSink *sink, + const IPlaybackDelegate::Property &property, GValue *value) +{ + if (auto delegate = rialto_web_audio_sink_get_delegate(sink)) + { + delegate->getProperty(property, value); + } + else // Copy queued value if present + { + std::unique_lock lock{sink->priv->m_sinkMutex}; + if (sink->priv->m_queuedProperties.find(property) != sink->priv->m_queuedProperties.end()) + { + g_value_copy(&sink->priv->m_queuedProperties[property], value); + } + } +} + +static void rialto_web_audio_sink_handle_set_property(RialtoWebAudioSink *sink, + const IPlaybackDelegate::Property &property, const GValue *value) +{ + if (auto delegate = rialto_web_audio_sink_get_delegate(sink)) + { + delegate->setProperty(property, value); + } + else + { + std::unique_lock lock{sink->priv->m_sinkMutex}; + sink->priv->m_queuedProperties[property] = G_VALUE_INIT; + g_value_init(&(sink->priv->m_queuedProperties[property]), G_VALUE_TYPE(value)); + g_value_copy(value, &(sink->priv->m_queuedProperties[property])); + } +} + +static gboolean rialto_web_audio_sink_send_event(GstElement *element, GstEvent *event) +{ + RialtoWebAudioSink *sink = RIALTO_WEB_AUDIO_SINK(element); + if (auto delegate = rialto_web_audio_sink_get_delegate(sink)) + { + return delegate->handleSendEvent(event); + } + return FALSE; +} + +static GstStateChangeReturn rialto_web_audio_sink_change_state(GstElement *element, GstStateChange transition) +{ + RialtoWebAudioSink *sink = RIALTO_WEB_AUDIO_SINK(element); + if (GST_STATE_CHANGE_NULL_TO_READY == transition) + { + GST_INFO_OBJECT(sink, "RialtoWebAudioSink state change to READY. Initializing delegate"); + rialto_web_audio_sink_initialise_delegate(sink, std::make_shared(element)); + } + if (auto delegate = rialto_web_audio_sink_get_delegate(sink)) + { + GstStateChangeReturn status = delegate->changeState(transition); + if (GST_STATE_CHANGE_FAILURE != status) + { + GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) + { + GST_WARNING_OBJECT(sink, "State change failed"); + return result; + } + else if (result == GST_STATE_CHANGE_ASYNC) + { + return GST_STATE_CHANGE_ASYNC; + } + } + return status; + } + return GST_STATE_CHANGE_FAILURE; +} + +static gboolean rialto_web_audio_sink_event(GstPad *pad, GstObject *parent, GstEvent *event) +{ + if (auto delegate = rialto_web_audio_sink_get_delegate(RIALTO_WEB_AUDIO_SINK(parent))) + { + return delegate->handleEvent(pad, parent, event); + } + return FALSE; +} + +static void rialto_web_audio_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) +{ + switch (propId) + { + case PROP_TS_OFFSET: + { + rialto_web_audio_sink_handle_get_property(RIALTO_WEB_AUDIO_SINK(object), IPlaybackDelegate::Property::TsOffset, + value); + } + + case PROP_VOLUME: + { + g_value_set_double(value, kDefaultVolume); + rialto_web_audio_sink_handle_get_property(RIALTO_WEB_AUDIO_SINK(object), IPlaybackDelegate::Property::Volume, + value); + break; + } + + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } + } +} + +static void rialto_web_audio_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) +{ + switch (propId) + { + case PROP_TS_OFFSET: + { + rialto_web_audio_sink_handle_set_property(RIALTO_WEB_AUDIO_SINK(object), IPlaybackDelegate::Property::TsOffset, + value); + break; + } + + case PROP_VOLUME: + { + rialto_web_audio_sink_handle_set_property(RIALTO_WEB_AUDIO_SINK(object), IPlaybackDelegate::Property::Volume, + value); + break; + } + + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } + } +} + +static GstFlowReturn rialto_web_audio_sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buf) +{ + if (auto delegate = rialto_web_audio_sink_get_delegate(RIALTO_WEB_AUDIO_SINK(parent))) + { + return delegate->handleBuffer(buf); + } + return GST_FLOW_ERROR; +} + +static void rialto_web_audio_sink_setup_supported_caps(GstElementClass *elementClass) +{ + GstCaps *caps = gst_caps_from_string("audio/x-raw"); + GstPadTemplate *sinktempl = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps); + gst_element_class_add_pad_template(elementClass, sinktempl); + gst_caps_unref(caps); +} + +static bool rialto_web_audio_sink_initialise_sinkpad(RialtoWebAudioSink *sink) +{ + GstPadTemplate *pad_template = + gst_element_class_get_pad_template(GST_ELEMENT_CLASS(G_OBJECT_GET_CLASS(sink)), "sink"); + if (!pad_template) + { + GST_ERROR_OBJECT(sink, "Could not find sink pad template"); + return false; + } + + GstPad *sinkPad = gst_pad_new_from_template(pad_template, "sink"); + if (!sinkPad) + { + GST_ERROR_OBJECT(sink, "Could not create sinkpad"); + return false; + } + + gst_element_add_pad(GST_ELEMENT_CAST(sink), sinkPad); + + gst_pad_set_event_function(sinkPad, rialto_web_audio_sink_event); + gst_pad_set_chain_function(sinkPad, rialto_web_audio_sink_chain); + + return true; +} + +static void rialto_web_audio_sink_init(RialtoWebAudioSink *sink) +{ + GST_INFO_OBJECT(sink, "Init: %" GST_PTR_FORMAT, sink); + sink->priv = static_cast(rialto_web_audio_sink_get_instance_private(sink)); + new (sink->priv) RialtoWebAudioSinkPrivate(); + + GST_OBJECT_FLAG_SET(sink, GST_ELEMENT_FLAG_SINK); + if (!rialto_web_audio_sink_initialise_sinkpad(sink)) + { + GST_ERROR_OBJECT(sink, "Failed to initialise AUDIO sink. Sink pad initialisation failed."); + return; + } +} + +static void rialto_web_audio_sink_finalize(GObject *object) +{ + RialtoWebAudioSink *sink = RIALTO_WEB_AUDIO_SINK(object); + RialtoWebAudioSinkPrivate *priv = sink->priv; + GST_INFO_OBJECT(sink, "Finalize: %" GST_PTR_FORMAT " %" GST_PTR_FORMAT, sink, priv); + + priv->~RialtoWebAudioSinkPrivate(); + + GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); +} + +static void rialto_web_audio_sink_class_init(RialtoWebAudioSinkClass *klass) +{ + GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); + GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); + + gst_element_class_set_metadata(elementClass, "Rialto Web Audio sink", "Generic", "A sink for Rialto Web Audio", + " "); + + gobjectClass->finalize = rialto_web_audio_sink_finalize; + gobjectClass->get_property = rialto_web_audio_sink_get_property; + gobjectClass->set_property = rialto_web_audio_sink_set_property; + + elementClass->change_state = rialto_web_audio_sink_change_state; + elementClass->send_event = rialto_web_audio_sink_send_event; + + g_object_class_install_property(gobjectClass, PROP_TS_OFFSET, + g_param_spec_int64("ts-offset", + "ts-offset", "Not supported, RialtoWebAudioSink does not require the synchronisation of sources", + G_MININT64, G_MAXINT64, 0, + GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + g_object_class_install_property(gobjectClass, PROP_VOLUME, + g_param_spec_double("volume", "Volume", "Volume of this stream", 0, 1.0, + kDefaultVolume, + GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + + rialto_web_audio_sink_setup_supported_caps(elementClass); + + gst_element_class_set_details_simple(elementClass, "Rialto Web Audio Sink", "Decoder/Audio/Sink/Audio", + "Communicates with Rialto Server", " "); +} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.h new file mode 100644 index 000000000..8a7bc12a3 --- /dev/null +++ b/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "IPlaybackDelegate.h" +#include +#include +#include + +G_BEGIN_DECLS + +#define RIALTO_TYPE_WEB_AUDIO_SINK (rialto_web_audio_sink_get_type()) +#define RIALTO_WEB_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_WEB_AUDIO_SINK, RialtoWebAudioSink)) +#define RIALTO_WEB_AUDIO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_WEB_AUDIO_SINK, RialtoWebAudioSinkClass)) +#define RIALTO_IS_WEB_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_WEB_AUDIO_SINK)) +#define RIALTO_IS_WEB_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_WEB_AUDIO_SINK)) + +typedef struct _RialtoWebAudioSink RialtoWebAudioSink; +typedef struct _RialtoWebAudioSinkClass RialtoWebAudioSinkClass; +typedef struct _RialtoWebAudioSinkPrivate RialtoWebAudioSinkPrivate; + +struct _RialtoWebAudioSinkPrivate +{ + std::mutex m_sinkMutex; + std::shared_ptr m_delegate{nullptr}; + std::map m_queuedProperties{}; +}; + +struct _RialtoWebAudioSink +{ + GstElement parent; + RialtoWebAudioSinkPrivate *priv; +}; + +struct _RialtoWebAudioSinkClass +{ + GstElementClass parent_class; +}; + +GType rialto_web_audio_sink_get_type(void); + +G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/Timer.cpp b/middleware/rialto-gstreamer/source/Timer.cpp new file mode 100644 index 000000000..7ec54d7ee --- /dev/null +++ b/middleware/rialto-gstreamer/source/Timer.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Timer.h" +#include + +std::weak_ptr TimerFactory::m_factory; + +std::shared_ptr ITimerFactory::getFactory() +{ + std::shared_ptr factory = TimerFactory::m_factory.lock(); + + if (!factory) + { + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + GST_ERROR("Failed to create the timer factory, reason: %s", e.what()); + } + + TimerFactory::m_factory = factory; + } + + return factory; +} + +std::unique_ptr TimerFactory::createTimer(const std::chrono::milliseconds &timeout, + const std::function &callback, TimerType timerType) const +{ + return std::make_unique(timeout, callback, timerType); +} + +Timer::Timer(const std::chrono::milliseconds &timeout, const std::function &callback, TimerType timerType) + : m_active{true}, m_timeout{timeout}, m_callback{callback} +{ + m_thread = std::thread( + [this, timerType]() + { + do + { + std::unique_lock lock{m_mutex}; + if (!m_cv.wait_for(lock, m_timeout, [this]() { return !m_active; })) + { + if (m_active && m_callback) + { + lock.unlock(); + m_callback(); + } + } + } while (timerType == TimerType::PERIODIC && m_active); + m_active = false; + }); +} + +Timer::~Timer() +{ + doCancel(); +} + +void Timer::cancel() +{ + doCancel(); +} + +bool Timer::isActive() const +{ + return m_active; +} + +void Timer::doCancel() +{ + m_active = false; + + if (std::this_thread::get_id() != m_thread.get_id() && m_thread.joinable()) + { + m_cv.notify_one(); + m_thread.join(); + } +} diff --git a/middleware/rialto-gstreamer/source/Timer.h b/middleware/rialto-gstreamer/source/Timer.h new file mode 100644 index 000000000..3f6d767d4 --- /dev/null +++ b/middleware/rialto-gstreamer/source/Timer.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TIMER_H_ +#define TIMER_H_ + +#include "ITimer.h" + +#include +#include +#include +#include +#include + +/** + * @brief ITimerFactory factory class definition. + */ +class TimerFactory : public ITimerFactory +{ +public: + /** + * @brief Weak pointer to the singleton factory object. + */ + static std::weak_ptr m_factory; + + std::unique_ptr createTimer(const std::chrono::milliseconds &timeout, const std::function &callback, + TimerType timerType = TimerType::ONE_SHOT) const override; +}; + +class Timer : public ITimer +{ +public: + Timer(const std::chrono::milliseconds &timeout, const std::function &callback, + TimerType timerType = TimerType::ONE_SHOT); + ~Timer(); + Timer(const Timer &) = delete; + Timer(Timer &&) = delete; + Timer &operator=(const Timer &) = delete; + Timer &operator=(Timer &&) = delete; + + void cancel() override; + bool isActive() const override; + +private: + void doCancel(); + + std::atomic m_active; + std::chrono::milliseconds m_timeout; + std::function m_callback; + mutable std::mutex m_mutex; + std::thread m_thread; + std::condition_variable m_cv; +}; + +#endif // TIMER_H_ diff --git a/middleware/rialto-gstreamer/source/WebAudioClientBackend.h b/middleware/rialto-gstreamer/source/WebAudioClientBackend.h new file mode 100644 index 000000000..1f22a0a6b --- /dev/null +++ b/middleware/rialto-gstreamer/source/WebAudioClientBackend.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#pragma once + +#include "WebAudioClientBackendInterface.h" +#include +#include +#include +#include + +namespace firebolt::rialto::client +{ +class WebAudioClientBackend final : public WebAudioClientBackendInterface +{ +public: + WebAudioClientBackend() : m_webAudioPlayerBackend(nullptr) {} + ~WebAudioClientBackend() final { m_webAudioPlayerBackend.reset(); } + + bool createWebAudioBackend(std::weak_ptr client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config) override + { + m_webAudioPlayerBackend = + firebolt::rialto::IWebAudioPlayerFactory::createFactory()->createWebAudioPlayer(client, audioMimeType, + priority, config); + + if (!m_webAudioPlayerBackend) + { + GST_ERROR("Could not create web audio backend"); + return false; + } + return true; + } + void destroyWebAudioBackend() override { m_webAudioPlayerBackend.reset(); } + + bool play() override { return m_webAudioPlayerBackend->play(); } + bool pause() override { return m_webAudioPlayerBackend->pause(); } + bool setEos() override { return m_webAudioPlayerBackend->setEos(); } + bool getBufferAvailable(uint32_t &availableFrames) override + { + std::shared_ptr webAudioShmInfo; + return m_webAudioPlayerBackend->getBufferAvailable(availableFrames, webAudioShmInfo); + } + bool getBufferDelay(uint32_t &delayFrames) override { return m_webAudioPlayerBackend->getBufferDelay(delayFrames); } + bool writeBuffer(const uint32_t numberOfFrames, void *data) override + { + return m_webAudioPlayerBackend->writeBuffer(numberOfFrames, data); + } + bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override + { + return m_webAudioPlayerBackend->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay); + } + bool setVolume(double volume) override { return m_webAudioPlayerBackend->setVolume(volume); } + bool getVolume(double &volume) override { return m_webAudioPlayerBackend->getVolume(volume); } + +private: + std::unique_ptr m_webAudioPlayerBackend; +}; +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/WebAudioClientBackendInterface.h b/middleware/rialto-gstreamer/source/WebAudioClientBackendInterface.h new file mode 100644 index 000000000..8cbac732f --- /dev/null +++ b/middleware/rialto-gstreamer/source/WebAudioClientBackendInterface.h @@ -0,0 +1,43 @@ +/* + + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once +#include +#include + +namespace firebolt::rialto::client +{ +class WebAudioClientBackendInterface +{ +public: + virtual ~WebAudioClientBackendInterface() = default; + virtual bool createWebAudioBackend(std::weak_ptr client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config) = 0; + virtual void destroyWebAudioBackend() = 0; + + virtual bool play() = 0; + virtual bool pause() = 0; + virtual bool setEos() = 0; + virtual bool getBufferAvailable(uint32_t &availableFrames) = 0; + virtual bool getBufferDelay(uint32_t &delayFrames) = 0; + virtual bool writeBuffer(const uint32_t numberOfFrames, void *data) = 0; + virtual bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) = 0; + virtual bool setVolume(double volume) = 0; + virtual bool getVolume(double &volume) = 0; +}; +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-ocdm/include/ActiveSessions.h b/middleware/rialto-ocdm/include/ActiveSessions.h new file mode 100644 index 000000000..cf7918bc5 --- /dev/null +++ b/middleware/rialto-ocdm/include/ActiveSessions.h @@ -0,0 +1,55 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ACTIVE_SESSIONS_H_ +#define ACTIVE_SESSIONS_H_ + +#include "ICdmBackend.h" +#include "IMessageDispatcher.h" +#include "OpenCDMSession.h" +#include +#include +#include +#include +#include +#include +#include + +class ActiveSessions +{ +public: + static ActiveSessions &instance(); + + OpenCDMSession *create(const std::shared_ptr &cdm, + const std::shared_ptr &messageDispatcher, const LicenseType &sessionType, + OpenCDMSessionCallbacks *callbacks, void *context, const std::string &initDataType, + const std::vector &initData); + OpenCDMSession *get(const std::vector &keyId); + void remove(OpenCDMSession *session); + +private: + ActiveSessions() = default; + ~ActiveSessions() = default; + +private: + std::mutex m_mutex; + std::map m_activeSessions; +}; + +#endif // ACTIVE_SESSIONS_H_ diff --git a/middleware/rialto-ocdm/include/CdmBackend.h b/middleware/rialto-ocdm/include/CdmBackend.h new file mode 100644 index 000000000..c56504782 --- /dev/null +++ b/middleware/rialto-ocdm/include/CdmBackend.h @@ -0,0 +1,80 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CDM_BACKEND_H_ +#define CDM_BACKEND_H_ + +#include "ICdmBackend.h" +#include "Logger.h" +#include "MessageDispatcher.h" +#include +#include +#include +#include +#include +#include +#include + +class CdmBackend : public ICdmBackend, public firebolt::rialto::IControlClient +{ +public: + CdmBackend(const std::string &keySystem, const std::shared_ptr &mediaKeysClient, + const std::shared_ptr &mediaKeysFactory); + ~CdmBackend() override = default; + + void notifyApplicationState(firebolt::rialto::ApplicationState state) override; + + bool initialize(const firebolt::rialto::ApplicationState &initialState) override; + + bool selectKeyId(int32_t keySessionId, const std::vector &keyId) override; + bool containsKey(int32_t keySessionId, const std::vector &keyId) override; + bool createKeySession(firebolt::rialto::KeySessionType sessionType, bool isLDL, int32_t &keySessionId) override; + bool generateRequest(int32_t keySessionId, firebolt::rialto::InitDataType initDataType, + const std::vector &initData) override; + bool loadSession(int32_t keySessionId) override; + bool updateSession(int32_t keySessionId, const std::vector &responseData) override; + bool setDrmHeader(int32_t keySessionId, const std::vector &requestData) override; + bool closeKeySession(int32_t keySessionId) override; + bool removeKeySession(int32_t keySessionId) override; + bool deleteDrmStore() override; + bool deleteKeyStore() override; + bool getDrmStoreHash(std::vector &drmStoreHash) override; + bool getKeyStoreHash(std::vector &keyStoreHash) override; + bool getLdlSessionsLimit(uint32_t &ldlLimit) override; + bool getLastDrmError(int32_t keySessionId, uint32_t &errorCode) override; + bool getDrmTime(uint64_t &drmTime) override; + bool getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) override; + bool releaseKeySession(int32_t keySessionId) override; + bool getMetricSystemData(std::vector &buffer) override; + +private: + bool createMediaKeys(); + +private: + Logger m_log; + std::mutex m_mutex; + std::condition_variable m_cv; + firebolt::rialto::ApplicationState m_appState; + const std::string m_keySystem; + std::shared_ptr m_mediaKeysClient; + std::shared_ptr m_mediaKeysFactory; + std::unique_ptr m_mediaKeys; +}; + +#endif // CDM_BACKEND_H_ diff --git a/middleware/rialto-ocdm/include/ICdmBackend.h b/middleware/rialto-ocdm/include/ICdmBackend.h new file mode 100644 index 000000000..d78d09c09 --- /dev/null +++ b/middleware/rialto-ocdm/include/ICdmBackend.h @@ -0,0 +1,59 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef I_CDM_BACKEND_H_ +#define I_CDM_BACKEND_H_ + +#include +#include +#include +#include +#include +#include +#include + +class ICdmBackend +{ +public: + virtual ~ICdmBackend() = default; + + virtual bool initialize(const firebolt::rialto::ApplicationState &initialState) = 0; + virtual bool selectKeyId(int32_t keySessionId, const std::vector &keyId) = 0; + virtual bool containsKey(int32_t keySessionId, const std::vector &keyId) = 0; + virtual bool createKeySession(firebolt::rialto::KeySessionType sessionType, bool isLDL, int32_t &keySessionId) = 0; + virtual bool generateRequest(int32_t keySessionId, firebolt::rialto::InitDataType initDataType, + const std::vector &initData) = 0; + virtual bool loadSession(int32_t keySessionId) = 0; + virtual bool updateSession(int32_t keySessionId, const std::vector &responseData) = 0; + virtual bool setDrmHeader(int32_t keySessionId, const std::vector &requestData) = 0; + virtual bool closeKeySession(int32_t keySessionId) = 0; + virtual bool removeKeySession(int32_t keySessionId) = 0; + virtual bool deleteDrmStore() = 0; + virtual bool deleteKeyStore() = 0; + virtual bool getDrmStoreHash(std::vector &drmStoreHash) = 0; + virtual bool getKeyStoreHash(std::vector &keyStoreHash) = 0; + virtual bool getLdlSessionsLimit(uint32_t &ldlLimit) = 0; + virtual bool getLastDrmError(int32_t keySessionId, uint32_t &errorCode) = 0; + virtual bool getDrmTime(uint64_t &drmTime) = 0; + virtual bool getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) = 0; + virtual bool releaseKeySession(int32_t keySessionId) = 0; + virtual bool getMetricSystemData(std::vector &buffer) = 0; +}; + +#endif // I_CDM_BACKEND_H_ diff --git a/middleware/rialto-ocdm/include/IMessageDispatcher.h b/middleware/rialto-ocdm/include/IMessageDispatcher.h new file mode 100644 index 000000000..6a8e36aa8 --- /dev/null +++ b/middleware/rialto-ocdm/include/IMessageDispatcher.h @@ -0,0 +1,39 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef I_MESSAGE_DISPATCHER_H_ +#define I_MESSAGE_DISPATCHER_H_ + +#include +#include + +class IMessageDispatcherClient +{ +public: + virtual ~IMessageDispatcherClient() = default; +}; + +class IMessageDispatcher +{ +public: + virtual ~IMessageDispatcher() = default; + virtual std::unique_ptr createClient(firebolt::rialto::IMediaKeysClient *client) = 0; +}; + +#endif // I_MESSAGE_DISPATCHER_H_ diff --git a/middleware/rialto-ocdm/include/Logger.h b/middleware/rialto-ocdm/include/Logger.h new file mode 100644 index 000000000..cd2e2945f --- /dev/null +++ b/middleware/rialto-ocdm/include/Logger.h @@ -0,0 +1,87 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include +#include +#include +#include + +enum Severity +{ + fatal = 0, + error = 1, + warn = 2, + mil = 3, + info = 4, + debug = 5 +}; + +class LogFile +{ +public: + static LogFile &instance(); + bool write(const std::string &line); + bool isEnabled() const; + void reset(); + +private: + LogFile(); + ~LogFile(); + + void tryOpenFile(); + void tryCloseFile(); + +private: + std::fstream m_file; + std::mutex m_mutex; +}; + +class Logger; +class Flusher +{ +public: + Flusher(std::stringstream &stream, const std::string &componentName, const Severity &severity); + ~Flusher(); + + template Flusher &operator<<(const T &text) + { + m_stream << text; + return *this; + } + +private: + std::stringstream &m_stream; + Severity m_severity; +}; + +class Logger +{ +public: + explicit Logger(const std::string &componentName); + Flusher operator<<(const Severity &) const; + +private: + const std::string m_componentName; + mutable std::stringstream m_stream; +}; + +#endif // LOGGER_H_ diff --git a/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h b/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h new file mode 100644 index 000000000..baf3706fd --- /dev/null +++ b/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEDIA_KEYS_CAPABILITIES_BACKEND_H_ +#define MEDIA_KEYS_CAPABILITIES_BACKEND_H_ + +#include +#include +#include +#include +#include + +class MediaKeysCapabilitiesBackend +{ +public: + static MediaKeysCapabilitiesBackend &instance(); + + std::vector getSupportedKeySystems(); + OpenCDMError supportsKeySystem(const std::string &keySystem); + bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version); + bool isServerCertificateSupported(const std::string &keySystem); + +private: + MediaKeysCapabilitiesBackend(); + ~MediaKeysCapabilitiesBackend(); + +private: + std::shared_ptr m_mediaKeysCapabilities; +}; + +#endif // MEDIA_KEYS_CAPABILITIES_BACKEND_H_ diff --git a/middleware/rialto-ocdm/include/MessageDispatcher.h b/middleware/rialto-ocdm/include/MessageDispatcher.h new file mode 100644 index 000000000..4802ecd14 --- /dev/null +++ b/middleware/rialto-ocdm/include/MessageDispatcher.h @@ -0,0 +1,63 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MESSAGE_DISPATCHER_H_ +#define MESSAGE_DISPATCHER_H_ + +#include "IMessageDispatcher.h" +#include +#include +#include +#include +#include + +class MessageDispatcher : public IMessageDispatcher, public firebolt::rialto::IMediaKeysClient +{ + class MessageDispatcherClient : public IMessageDispatcherClient + { + public: + MessageDispatcherClient(MessageDispatcher &dispatcher, firebolt::rialto::IMediaKeysClient *client); + ~MessageDispatcherClient() override; + + private: + MessageDispatcher &m_dispatcher; + firebolt::rialto::IMediaKeysClient *m_client; + }; + +public: + MessageDispatcher() = default; + ~MessageDispatcher() override = default; + + std::unique_ptr createClient(firebolt::rialto::IMediaKeysClient *client) override; + + void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, + const std::string &url) override; + void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) override; + void onKeyStatusesChanged(int32_t keySessionId, const firebolt::rialto::KeyStatusVector &keyStatuses) override; + +private: + void addClient(firebolt::rialto::IMediaKeysClient *client); + void removeClient(firebolt::rialto::IMediaKeysClient *client); + +private: + std::mutex m_mutex; + std::set m_clients; +}; + +#endif // MESSAGE_DISPATCHER_H_ diff --git a/middleware/rialto-ocdm/include/OpenCDMSession.h b/middleware/rialto-ocdm/include/OpenCDMSession.h new file mode 100644 index 000000000..dba49ab48 --- /dev/null +++ b/middleware/rialto-ocdm/include/OpenCDMSession.h @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OPENCDM_SESSION_H_ +#define OPENCDM_SESSION_H_ + +#include +#include +#include +#include +#include +#include +#include + +struct _GstCaps; +struct _GstBuffer; +typedef struct _GstCaps GstCaps; +typedef struct _GstBuffer GstBuffer; + +class OpenCDMSession +{ +public: + typedef std::function &license_renewal_message, uint64_t session_id)> LicenseRenewalCallback; + typedef std::function, firebolt::rialto::KeyStatus>> &key_statuses, + uint64_t session_id)> + KeyStatusesChangedCallback; + + OpenCDMSession() = default; + virtual ~OpenCDMSession() = default; + + virtual bool initialize() = 0; + virtual bool initialize(bool) = 0; + virtual bool generateRequest(const std::string &initDataType, const std::vector &initData, + const std::vector &cdmData) = 0; + virtual bool loadSession() = 0; + virtual bool updateSession(const std::vector &license) = 0; + virtual bool getChallengeData(std::vector &challengeData) = 0; + virtual bool containsKey(const std::vector &keyId) = 0; + virtual bool setDrmHeader(const std::vector &drmHeader) = 0; + virtual bool selectKeyId(const std::vector &keyId) = 0; + virtual void addProtectionMeta(GstBuffer *buffer, GstBuffer *subSample, const uint32_t subSampleCount, + GstBuffer *IV, GstBuffer *keyID, uint32_t initWithLast15) = 0; + virtual bool addProtectionMeta(GstBuffer *buffer) = 0; + virtual bool closeSession() = 0; + virtual bool removeSession() = 0; + virtual KeyStatus status(const std::vector &key) const = 0; + + virtual const std::string &getSessionId() const = 0; + virtual uint32_t getLastDrmError() const = 0; +}; + +#endif // OPENCDM_SESSION_H_ diff --git a/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h b/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h new file mode 100644 index 000000000..c0f699df1 --- /dev/null +++ b/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h @@ -0,0 +1,104 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OPENCDM_SESSION_PRIVATE_H_ +#define OPENCDM_SESSION_PRIVATE_H_ + +#include "IMediaKeysClient.h" +#include "Logger.h" +#include "OpenCDMSession.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct _GstCaps; +struct _GstBuffer; +typedef struct _GstCaps GstCaps; +typedef struct _GstBuffer GstBuffer; + +class OpenCDMSessionPrivate : public OpenCDMSession, public firebolt::rialto::IMediaKeysClient +{ +public: + OpenCDMSessionPrivate(const std::shared_ptr &cdm, + const std::shared_ptr &messageDispatcher, const LicenseType &sessionType, + OpenCDMSessionCallbacks *callbacks, void *context, const std::string &initDataType, + const std::vector &initData); + ~OpenCDMSessionPrivate(); + + void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, + const std::string &url) override; + void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) override; + void onKeyStatusesChanged(int32_t keySessionId, const firebolt::rialto::KeyStatusVector &keyStatuses) override; + + bool initialize() override; + bool initialize(bool) override; + bool generateRequest(const std::string &initDataType, const std::vector &initData, + const std::vector &cdmData) override; + bool loadSession() override; + bool updateSession(const std::vector &license) override; + bool getChallengeData(std::vector &challengeData) override; + bool containsKey(const std::vector &keyId) override; + bool setDrmHeader(const std::vector &drmHeader) override; + bool selectKeyId(const std::vector &keyId) override; + void addProtectionMeta(GstBuffer *buffer, GstBuffer *subSample, const uint32_t subSampleCount, GstBuffer *IV, + GstBuffer *keyID, uint32_t initWithLast15) override; + bool addProtectionMeta(GstBuffer *buffer) override; + bool closeSession() override; + bool removeSession() override; + KeyStatus status(const std::vector &key) const override; + + const std::string &getSessionId() const override; + uint32_t getLastDrmError() const override; + +private: + void initializeCdmKeySessionId(); + void updateChallenge(const std::vector &challenge); + void releaseSession(); + +private: + Logger m_log; + std::mutex m_mutex; + std::condition_variable m_challengeCv; + void *m_context; + std::shared_ptr m_cdmBackend; + std::shared_ptr m_messageDispatcher; + std::unique_ptr m_messageDispatcherClient; + int32_t m_rialtoSessionId; + std::string m_cdmKeySessionId; + OpenCDMSessionCallbacks *m_callbacks; + firebolt::rialto::KeySessionType m_sessionType; + firebolt::rialto::InitDataType m_initDataType; + std::vector m_initData; + bool m_isInitialized; + std::vector m_challengeData; + std::vector m_playreadyKeyId; + std::map, firebolt::rialto::KeyStatus> m_keyStatuses; + + firebolt::rialto::KeySessionType getRialtoSessionType(const LicenseType licenseType); + firebolt::rialto::InitDataType getRialtoInitDataType(const std::string &type); +}; + +#endif // OPENCDM_SESSION_PRIVATE_H_ diff --git a/middleware/rialto-ocdm/include/OpenCDMSystem.h b/middleware/rialto-ocdm/include/OpenCDMSystem.h new file mode 100644 index 000000000..9efc00a05 --- /dev/null +++ b/middleware/rialto-ocdm/include/OpenCDMSystem.h @@ -0,0 +1,52 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OPENCDM_SYSTEM_H_ +#define OPENCDM_SYSTEM_H_ + +#include "OpenCDMSession.h" +#include +#include +#include +#include + +struct OpenCDMSystem +{ + OpenCDMSystem() = default; + virtual ~OpenCDMSystem() = default; + OpenCDMSystem(const OpenCDMSystem &) = default; + OpenCDMSystem(OpenCDMSystem &&) = default; + OpenCDMSystem &operator=(OpenCDMSystem &&) = default; + OpenCDMSystem &operator=(const OpenCDMSystem &) = default; + + virtual const std::string &keySystem() const = 0; + virtual const std::string &metadata() const = 0; + virtual OpenCDMSession *createSession(const LicenseType licenseType, OpenCDMSessionCallbacks *callbacks, + void *userData, const std::string &initDataType, + const std::vector &initData) const = 0; + virtual bool getDrmTime(uint64_t &drmTime) const = 0; + virtual bool getLdlSessionsLimit(uint32_t &ldlLimit) const = 0; + virtual bool getKeyStoreHash(std::vector &keyStoreHash) const = 0; + virtual bool getDrmStoreHash(std::vector &drmStoreHash) const = 0; + virtual bool deleteKeyStore() const = 0; + virtual bool deleteDrmStore() const = 0; + virtual bool getMetricSystemData(std::vector &buffer) const = 0; +}; + +#endif // OPENCDM_SYSTEM_H_ diff --git a/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h b/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h new file mode 100644 index 000000000..63d1cc88a --- /dev/null +++ b/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h @@ -0,0 +1,66 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OPENCDM_SYSTEM_PRIVATE_H_ +#define OPENCDM_SYSTEM_PRIVATE_H_ + +#include "CdmBackend.h" +#include "Logger.h" +#include "MessageDispatcher.h" +#include "OpenCDMSystem.h" +#include +#include +#include +#include + +OpenCDMSystem *createSystem(const char system[], const std::string &metadata); + +class OpenCDMSystemPrivate : public OpenCDMSystem +{ +public: + OpenCDMSystemPrivate(const std::string &system, const std::string &metadata, + const std::shared_ptr &messageDispatcher, + const std::shared_ptr &cdmBackend); + ~OpenCDMSystemPrivate(); + OpenCDMSystemPrivate(const OpenCDMSystemPrivate &) = default; + OpenCDMSystemPrivate(OpenCDMSystemPrivate &&) = default; + OpenCDMSystemPrivate &operator=(OpenCDMSystemPrivate &&) = default; + OpenCDMSystemPrivate &operator=(const OpenCDMSystemPrivate &) = default; + const std::string &keySystem() const; + const std::string &metadata() const; + OpenCDMSession *createSession(const LicenseType licenseType, OpenCDMSessionCallbacks *callbacks, void *userData, + const std::string &initDataType, const std::vector &initData) const; + bool getDrmTime(uint64_t &drmTime) const; + bool getLdlSessionsLimit(uint32_t &ldlLimit) const; + bool getKeyStoreHash(std::vector &keyStoreHash) const; + bool getDrmStoreHash(std::vector &drmStoreHash) const; + bool deleteKeyStore() const; + bool deleteDrmStore() const; + bool getMetricSystemData(std::vector &buffer) const; + +private: + Logger m_log; + std::string m_keySystem; + std::string m_metadata; + std::shared_ptr m_control; + std::shared_ptr m_messageDispatcher; + std::shared_ptr m_cdmBackend; +}; + +#endif // OPENCDM_SYSTEM_PRIVATE_H_ diff --git a/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h b/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h new file mode 100644 index 000000000..73126a95f --- /dev/null +++ b/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RIALTOG_STREAMEREME_PROTECTION_METADATA_H_ +#define RIALTOG_STREAMEREME_PROTECTION_METADATA_H_ + +#include + +G_BEGIN_DECLS + +#define GST_RIALTO_PROTECTION_METADATA_GET_TYPE (rialto_eme_protection_metadata_get_type()) +#define GST_RIALTO_PROTECTION_METADATA_INFO (rialto_mse_protection_metadata_get_info()) + +struct _GstRialtoProtectionMetadata +{ + GstMeta parent; + GstStructure *info; +}; + +typedef struct _GstRialtoProtectionMetadata GstRialtoProtectionMetadata; + +// NOLINTNEXTLINE(build/function_format) +GType rialto_eme_protection_metadata_get_type(); +// NOLINTNEXTLINE(build/function_format) +const GstMetaInfo *rialto_mse_protection_metadata_get_info(); +// NOLINTNEXTLINE(build/function_format) +GstRialtoProtectionMetadata *rialto_mse_add_protection_metadata(GstBuffer *gstBuffer, GstStructure *info); + +G_END_DECLS + +#endif // RIALTOG_STREAMEREME_PROTECTION_METADATA_H_ diff --git a/middleware/rialto-ocdm/source/ActiveSessions.cpp b/middleware/rialto-ocdm/source/ActiveSessions.cpp new file mode 100644 index 000000000..c1df51192 --- /dev/null +++ b/middleware/rialto-ocdm/source/ActiveSessions.cpp @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ActiveSessions.h" +#include "OpenCDMSessionPrivate.h" +#include + +ActiveSessions &ActiveSessions::instance() +{ + static ActiveSessions activeSessions; + return activeSessions; +} + +OpenCDMSession *ActiveSessions::create(const std::shared_ptr &cdm, + const std::shared_ptr &messageDispatcher, + const LicenseType &sessionType, OpenCDMSessionCallbacks *callbacks, void *context, + const std::string &initDataType, const std::vector &initData) +{ + std::unique_lock lock{m_mutex}; + OpenCDMSession *newSession = + new OpenCDMSessionPrivate(cdm, messageDispatcher, sessionType, callbacks, context, initDataType, initData); + m_activeSessions.insert(std::make_pair(newSession, 1)); + return newSession; +} + +OpenCDMSession *ActiveSessions::get(const std::vector &keyId) +{ + std::unique_lock lock{m_mutex}; + auto sessionIter{std::find_if(m_activeSessions.begin(), m_activeSessions.end(), [&](const auto &iter) + { return iter.first->status(keyId) != KeyStatus::InternalError; })}; + if (sessionIter != m_activeSessions.end()) + { + ++sessionIter->second; + return sessionIter->first; + } + return nullptr; +} + +void ActiveSessions::remove(OpenCDMSession *session) +{ + std::unique_lock lock{m_mutex}; + auto sessionIter{m_activeSessions.find(session)}; + if (sessionIter != m_activeSessions.end()) + { + --sessionIter->second; + if (0 == sessionIter->second) + { + delete sessionIter->first; + m_activeSessions.erase(sessionIter); + } + } +} diff --git a/middleware/rialto-ocdm/source/CPPLINT.cfg b/middleware/rialto-ocdm/source/CPPLINT.cfg new file mode 100644 index 000000000..8e1289432 --- /dev/null +++ b/middleware/rialto-ocdm/source/CPPLINT.cfg @@ -0,0 +1,21 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2023 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Exclude files with opencdm functions +exclude_files=open_* diff --git a/middleware/rialto-ocdm/source/CdmBackend.cpp b/middleware/rialto-ocdm/source/CdmBackend.cpp new file mode 100644 index 000000000..d230f1722 --- /dev/null +++ b/middleware/rialto-ocdm/source/CdmBackend.cpp @@ -0,0 +1,286 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CdmBackend.h" + +CdmBackend::CdmBackend(const std::string &keySystem, + const std::shared_ptr &mediaKeysClient, + const std::shared_ptr &mediaKeysFactory) + : m_log{"CdmBackend"}, m_appState{firebolt::rialto::ApplicationState::UNKNOWN}, m_keySystem{keySystem}, + m_mediaKeysClient{mediaKeysClient}, m_mediaKeysFactory{mediaKeysFactory} +{ +} + +void CdmBackend::notifyApplicationState(firebolt::rialto::ApplicationState state) +{ + std::unique_lock lock{m_mutex}; + if (state == m_appState) + { + return; + } + if (firebolt::rialto::ApplicationState::RUNNING == state) + { + m_log << info << "Rialto state changed to: RUNNING"; + if (createMediaKeys()) + { + m_appState = state; + m_cv.notify_one(); + } + } + else + { + m_log << info << "Rialto state changed to: INACTIVE"; + m_mediaKeys.reset(); + m_appState = state; + } +} + +bool CdmBackend::initialize(const firebolt::rialto::ApplicationState &initialState) +{ + std::unique_lock lock{m_mutex}; + if (firebolt::rialto::ApplicationState::UNKNOWN != m_appState) + { + // CdmBackend initialized by Rialto Client thread in notifyApplicationState() + return true; + } + if (firebolt::rialto::ApplicationState::RUNNING == initialState) + { + if (!createMediaKeys()) + { + return false; + } + } + m_log << info << "CdmBackend initialized in " + << (firebolt::rialto::ApplicationState::RUNNING == initialState ? "RUNNING" : "INACTIVE") << " state"; + m_appState = initialState; + return true; +} + +bool CdmBackend::selectKeyId(int32_t keySessionId, const std::vector &keyId) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->selectKeyId(keySessionId, keyId); +} + +bool CdmBackend::containsKey(int32_t keySessionId, const std::vector &keyId) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return m_mediaKeys->containsKey(keySessionId, keyId); +} + +bool CdmBackend::createKeySession(firebolt::rialto::KeySessionType sessionType, bool isLDL, int32_t &keySessionId) +{ + std::unique_lock lock{m_mutex}; + // Sometimes app tries to create session before reaching RUNNING state. We have to wait for it. + m_cv.wait_for(lock, std::chrono::seconds(1), + [this]() { return firebolt::rialto::ApplicationState::RUNNING == m_appState; }); + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == + m_mediaKeys->createKeySession(sessionType, m_mediaKeysClient, isLDL, keySessionId); +} + +bool CdmBackend::generateRequest(int32_t keySessionId, firebolt::rialto::InitDataType initDataType, + const std::vector &initData) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == + m_mediaKeys->generateRequest(keySessionId, initDataType, initData); +} + +bool CdmBackend::loadSession(int32_t keySessionId) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->loadSession(keySessionId); +} + +bool CdmBackend::updateSession(int32_t keySessionId, const std::vector &responseData) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->updateSession(keySessionId, responseData); +} + +bool CdmBackend::setDrmHeader(int32_t keySessionId, const std::vector &requestData) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->setDrmHeader(keySessionId, requestData); +} + +bool CdmBackend::closeKeySession(int32_t keySessionId) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->closeKeySession(keySessionId); +} + +bool CdmBackend::removeKeySession(int32_t keySessionId) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->removeKeySession(keySessionId); +} + +bool CdmBackend::deleteDrmStore() +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->deleteDrmStore(); +} + +bool CdmBackend::deleteKeyStore() +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->deleteKeyStore(); +} + +bool CdmBackend::getDrmStoreHash(std::vector &drmStoreHash) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getDrmStoreHash(drmStoreHash); +} + +bool CdmBackend::getKeyStoreHash(std::vector &keyStoreHash) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getKeyStoreHash(keyStoreHash); +} + +bool CdmBackend::getLdlSessionsLimit(uint32_t &ldlLimit) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getLdlSessionsLimit(ldlLimit); +} + +bool CdmBackend::getLastDrmError(int32_t keySessionId, uint32_t &errorCode) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getLastDrmError(keySessionId, errorCode); +} + +bool CdmBackend::getDrmTime(uint64_t &drmTime) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getDrmTime(drmTime); +} + +bool CdmBackend::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getCdmKeySessionId(keySessionId, cdmKeySessionId); +} + +bool CdmBackend::releaseKeySession(int32_t keySessionId) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->releaseKeySession(keySessionId); +} + +bool CdmBackend::createMediaKeys() +{ + if (!m_mediaKeysFactory) + { + m_log << error << "Failed to initialize media keys - not possible to create factory"; + return false; + } + + m_mediaKeys = m_mediaKeysFactory->createMediaKeys(m_keySystem); + if (!m_mediaKeys) + { + m_log << error << "Failed to initialize media keys - not possible to create media keys"; + return false; + } + return true; +} + +bool CdmBackend::getMetricSystemData(std::vector &buffer) +{ + std::unique_lock lock{m_mutex}; + if (!m_mediaKeys) + { + return false; + } + return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getMetricSystemData(buffer); +} diff --git a/middleware/rialto-ocdm/source/Logger.cpp b/middleware/rialto-ocdm/source/Logger.cpp new file mode 100644 index 000000000..6d46b1e5b --- /dev/null +++ b/middleware/rialto-ocdm/source/Logger.cpp @@ -0,0 +1,227 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Logger.h" +#include +#include +#include +#include +#include + +#ifdef USE_ETHANLOG + +#include + +#define SYSTEM_LOG_FATAL(filename, function, line, ...) ethanlog(ETHAN_LOG_FATAL, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_ERROR(filename, function, line, ...) ethanlog(ETHAN_LOG_ERROR, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_WARN(filename, function, line, ...) \ + ethanlog(ETHAN_LOG_WARNING, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_MIL(filename, function, line, ...) \ + ethanlog(ETHAN_LOG_MILESTONE, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_INFO(filename, function, line, ...) ethanlog(ETHAN_LOG_INFO, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_DEBUG(filename, function, line, ...) ethanlog(ETHAN_LOG_DEBUG, filename, function, line, __VA_ARGS__) + +#else + +#include + +#define SYSTEM_LOG_FATAL(filename, function, line, ...) syslog(LOG_CRIT, __VA_ARGS__) +#define SYSTEM_LOG_ERROR(filename, function, line, ...) syslog(LOG_ERR, __VA_ARGS__) +#define SYSTEM_LOG_WARN(filename, function, line, ...) syslog(LOG_WARNING, __VA_ARGS__) +#define SYSTEM_LOG_MIL(filename, function, line, ...) syslog(LOG_NOTICE, __VA_ARGS__) +#define SYSTEM_LOG_INFO(filename, function, line, ...) syslog(LOG_INFO, __VA_ARGS__) +#define SYSTEM_LOG_DEBUG(filename, function, line, ...) syslog(LOG_DEBUG, __VA_ARGS__) + +#endif + +namespace +{ +Severity getLogLevel() +{ + const char *debugVar = getenv("RIALTO_DEBUG"); + if (debugVar) + { + std::string varStr{debugVar}; + if ("0" == varStr) + return Severity::fatal; + if ("1" == varStr) + return Severity::error; + if ("2" == varStr) + return Severity::warn; + if ("3" == varStr) + return Severity::mil; + if ("4" == varStr) + return Severity::info; + if ("5" == varStr) + return Severity::debug; + } + return Severity::warn; +} + +bool isConsoleLogEnabled() +{ + const char *debugVar = getenv("RIALTO_CONSOLE_LOG"); + if (debugVar) + { + return std::string(debugVar) == "1"; + } + return false; +} + +std::string getRialtoLogPath() +{ + const char *logPathEnvVar = getenv("RIALTO_LOG_PATH"); + if (logPathEnvVar) + { + return std::string(logPathEnvVar); + } + return ""; +} + +std::string toString(const Severity &severity) +{ + if (Severity::fatal == severity) + return "ftl"; + if (Severity::error == severity) + return "err"; + if (Severity::warn == severity) + return "wrn"; + if (Severity::mil == severity) + return "mil"; + if (Severity::info == severity) + return "inf"; + if (Severity::debug == severity) + return "dbg"; + return "???"; +} + +} // namespace + +LogFile &LogFile::instance() +{ + static LogFile logFile; + return logFile; +} + +bool LogFile::write(const std::string &line) +{ + std::unique_lock lock{m_mutex}; + m_file << line << std::endl; + return true; +} + +bool LogFile::isEnabled() const +{ + return m_file.is_open(); +} + +void LogFile::reset() +{ + tryCloseFile(); + tryOpenFile(); +} + +LogFile::LogFile() +{ + tryOpenFile(); +} + +LogFile::~LogFile() +{ + tryCloseFile(); +} + +void LogFile::tryOpenFile() +{ + std::string logPath{getRialtoLogPath()}; + if (!logPath.empty()) + { + // Add suffix to have rialto client and rialto ocdm logs in separate files + logPath += ".ocdm"; + m_file = std::fstream(logPath, std::fstream::out); + } +} + +void LogFile::tryCloseFile() +{ + if (m_file.is_open()) + { + m_file.close(); + } +} + +Flusher::Flusher(std::stringstream &stream, const std::string &componentName, const Severity &severity) + : m_stream{stream}, m_severity{severity} +{ + if (LogFile::instance().isEnabled() || isConsoleLogEnabled()) + { + const std::chrono::time_point now = std::chrono::system_clock::now(); + const std::time_t t_c = std::chrono::system_clock::to_time_t(now); + m_stream << std::put_time(std::localtime(&t_c), "[%F %T]"); + } + m_stream << "[" << componentName << "][" << toString(severity) << "]: "; +} + +Flusher::~Flusher() +{ + if (getLogLevel() >= m_severity) + { + if (LogFile::instance().isEnabled()) + { + LogFile::instance().write(m_stream.str()); + } + else if (isConsoleLogEnabled()) + { + std::cout << m_stream.str() << std::endl; + } + else + { + switch (m_severity) + { + case Severity::fatal: + SYSTEM_LOG_FATAL(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); + break; + case Severity::error: + SYSTEM_LOG_ERROR(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); + break; + case Severity::warn: + SYSTEM_LOG_WARN(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); + break; + case Severity::mil: + SYSTEM_LOG_MIL(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); + break; + case Severity::info: + SYSTEM_LOG_INFO(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); + break; + case Severity::debug: + default: + SYSTEM_LOG_DEBUG(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); + break; + } + } + } + m_stream.str(""); +} + +Logger::Logger(const std::string &componentName) : m_componentName{componentName} {} + +Flusher Logger::operator<<(const Severity &severity) const +{ + return Flusher(m_stream, m_componentName, severity); +} diff --git a/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp b/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp new file mode 100644 index 000000000..f0dd064d3 --- /dev/null +++ b/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp @@ -0,0 +1,85 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaKeysCapabilitiesBackend.h" + +MediaKeysCapabilitiesBackend &MediaKeysCapabilitiesBackend::instance() +{ + static MediaKeysCapabilitiesBackend mkcBackend; + return mkcBackend; +} + +std::vector MediaKeysCapabilitiesBackend::getSupportedKeySystems() +{ + std::vector result{}; + if (m_mediaKeysCapabilities) + { + result = m_mediaKeysCapabilities->getSupportedKeySystems(); + } + return result; +} + +OpenCDMError MediaKeysCapabilitiesBackend::supportsKeySystem(const std::string &keySystem) +{ + OpenCDMError result{ERROR_FAIL}; + if (m_mediaKeysCapabilities) + { + result = ERROR_KEYSYSTEM_NOT_SUPPORTED; + if (m_mediaKeysCapabilities->supportsKeySystem(keySystem)) + { + result = ERROR_NONE; + } + } + return result; +} + +bool MediaKeysCapabilitiesBackend::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) +{ + bool result{false}; + if (m_mediaKeysCapabilities) + { + result = m_mediaKeysCapabilities->getSupportedKeySystemVersion(keySystem, version); + } + return result; +} + +bool MediaKeysCapabilitiesBackend::isServerCertificateSupported(const std::string &keySystem) +{ + bool result{false}; + if (m_mediaKeysCapabilities) + { + result = m_mediaKeysCapabilities->isServerCertificateSupported(keySystem); + } + return result; +} + +MediaKeysCapabilitiesBackend::MediaKeysCapabilitiesBackend() +{ + std::shared_ptr factory = + firebolt::rialto::IMediaKeysCapabilitiesFactory::createFactory(); + if (factory) + { + m_mediaKeysCapabilities = factory->getMediaKeysCapabilities(); + } +} + +MediaKeysCapabilitiesBackend::~MediaKeysCapabilitiesBackend() +{ + m_mediaKeysCapabilities.reset(); +} diff --git a/middleware/rialto-ocdm/source/MessageDispatcher.cpp b/middleware/rialto-ocdm/source/MessageDispatcher.cpp new file mode 100644 index 000000000..ef78fcb4b --- /dev/null +++ b/middleware/rialto-ocdm/source/MessageDispatcher.cpp @@ -0,0 +1,77 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MessageDispatcher.h" + +MessageDispatcher::MessageDispatcherClient::MessageDispatcherClient(MessageDispatcher &dispatcher, + firebolt::rialto::IMediaKeysClient *client) + : m_dispatcher{dispatcher}, m_client{client} +{ + m_dispatcher.addClient(m_client); +} + +MessageDispatcher::MessageDispatcherClient::~MessageDispatcherClient() +{ + m_dispatcher.removeClient(m_client); +} + +std::unique_ptr MessageDispatcher::createClient(firebolt::rialto::IMediaKeysClient *client) +{ + return std::make_unique(*this, client); +} + +void MessageDispatcher::addClient(firebolt::rialto::IMediaKeysClient *client) +{ + std::unique_lock lock{m_mutex}; + m_clients.emplace(client); +} + +void MessageDispatcher::removeClient(firebolt::rialto::IMediaKeysClient *client) +{ + std::unique_lock lock{m_mutex}; + m_clients.erase(client); +} + +void MessageDispatcher::onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, + const std::string &url) +{ + std::unique_lock lock{m_mutex}; + for (auto *client : m_clients) + { + client->onLicenseRequest(keySessionId, licenseRequestMessage, url); + } +} + +void MessageDispatcher::onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) +{ + std::unique_lock lock{m_mutex}; + for (auto *client : m_clients) + { + client->onLicenseRenewal(keySessionId, licenseRenewalMessage); + } +} + +void MessageDispatcher::onKeyStatusesChanged(int32_t keySessionId, const firebolt::rialto::KeyStatusVector &keyStatuses) +{ + std::unique_lock lock{m_mutex}; + for (auto *client : m_clients) + { + client->onKeyStatusesChanged(keySessionId, keyStatuses); + } +} diff --git a/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp b/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp new file mode 100644 index 000000000..b25af717f --- /dev/null +++ b/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp @@ -0,0 +1,554 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OpenCDMSessionPrivate.h" +#include "RialtoGStreamerEMEProtectionMetadata.h" +#include +#include +#include + +namespace +{ +const KeyStatus convertKeyStatus(const firebolt::rialto::KeyStatus &keyStatus) +{ + switch (keyStatus) + { + case firebolt::rialto::KeyStatus::USABLE: + { + return Usable; + } + case firebolt::rialto::KeyStatus::EXPIRED: + { + return Expired; + } + case firebolt::rialto::KeyStatus::RELEASED: + { + return Released; + } + case firebolt::rialto::KeyStatus::OUTPUT_RESTRICTED: + { + return OutputRestricted; + } + case firebolt::rialto::KeyStatus::PENDING: + { + return StatusPending; + } + case firebolt::rialto::KeyStatus::INTERNAL_ERROR: + default: + { + return InternalError; + } + } +} + +const std::string kDefaultSessionId{"0"}; +} // namespace + +OpenCDMSessionPrivate::OpenCDMSessionPrivate(const std::shared_ptr &cdm, + const std::shared_ptr &messageDispatcher, + const LicenseType &sessionType, OpenCDMSessionCallbacks *callbacks, + void *context, const std::string &initDataType, + const std::vector &initData) + : m_log{"OpenCDMSessionPrivate"}, m_context(context), m_cdmBackend(cdm), m_messageDispatcher(messageDispatcher), + m_rialtoSessionId(firebolt::rialto::kInvalidSessionId), m_callbacks(callbacks), + m_sessionType(getRialtoSessionType(sessionType)), m_initDataType(getRialtoInitDataType(initDataType)), + m_initData(initData), m_isInitialized{false} +{ + m_log << debug << "constructed: " << static_cast(this); +} + +OpenCDMSessionPrivate::~OpenCDMSessionPrivate() +{ + m_log << debug << "destructed: " << static_cast(this); + if (m_isInitialized) + { + releaseSession(); + } +} + +bool OpenCDMSessionPrivate::initialize() +{ + return initialize(false); +} + +bool OpenCDMSessionPrivate::initialize(bool isLDL) +{ + if (!m_cdmBackend || !m_messageDispatcher) + { + m_log << error << "Cdm/message dispatcher is NULL or not initialized"; + return false; + } + if (!m_isInitialized) + { + if (!m_cdmBackend->createKeySession(m_sessionType, isLDL, m_rialtoSessionId)) + { + m_log << error << "Failed to create a session. Got drm error %u", getLastDrmError(); + return false; + } + m_messageDispatcherClient = m_messageDispatcher->createClient(this); + m_isInitialized = true; + m_log << info << "Successfully created a session"; + } + return true; +} + +bool OpenCDMSessionPrivate::generateRequest(const std::string &initDataType, const std::vector &initData, + const std::vector &cdmData) +{ + firebolt::rialto::InitDataType dataType = getRialtoInitDataType(initDataType); + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return false; + } + + if ((dataType != firebolt::rialto::InitDataType::UNKNOWN) && (-1 != m_rialtoSessionId)) + { + if (m_cdmBackend->generateRequest(m_rialtoSessionId, dataType, initData)) + { + m_log << info << "Successfully generated the request for the session"; + initializeCdmKeySessionId(); + return true; + } + else + { + m_log << error << "Failed to request for the session. Got drm error " << getLastDrmError(); + } + } + + return false; +} + +bool OpenCDMSessionPrivate::loadSession() +{ + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return false; + } + + if (-1 != m_rialtoSessionId) + { + if (m_cdmBackend->loadSession(m_rialtoSessionId)) + { + m_log << info << "Successfully loaded the session"; + return true; + } + else + { + m_log << error << "Failed to load the session. Got drm error " << getLastDrmError(); + } + } + return false; +} + +bool OpenCDMSessionPrivate::updateSession(const std::vector &license) +{ + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return false; + } + + if (-1 != m_rialtoSessionId) + { + if (m_cdmBackend->updateSession(m_rialtoSessionId, license)) + { + m_log << info << "Successfully updated the session"; + return true; + } + else + { + m_log << error << "Failed to update the session. Got drm error " << getLastDrmError(); + } + } + + return false; +} + +bool OpenCDMSessionPrivate::getChallengeData(std::vector &challengeData) +{ + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return false; + } + if ((m_initDataType != firebolt::rialto::InitDataType::UNKNOWN) && (-1 != m_rialtoSessionId)) + { + if (m_cdmBackend->generateRequest(m_rialtoSessionId, m_initDataType, m_initData)) + { + m_log << info << "Successfully generated the request for the session"; + initializeCdmKeySessionId(); + } + else + { + m_log << error << "Failed to request for the session. Got drm error " << getLastDrmError(); + return false; + } + } + else + { + return false; + } + std::unique_lock lock{m_mutex}; + m_challengeCv.wait_for(lock, std::chrono::seconds{1}, [this]() { return !m_challengeData.empty(); }); + challengeData = m_challengeData; + return !challengeData.empty(); +} + +void OpenCDMSessionPrivate::addProtectionMeta(GstBuffer *buffer, GstBuffer *subSample, const uint32_t subSampleCount, + GstBuffer *IV, GstBuffer *keyID, uint32_t initWithLast15) +{ + // Set key for Playready + GstBuffer *keyToApply = keyID; + bool shouldReleaseKey{false}; + if (keyID && 0 == gst_buffer_get_size(keyID) && !m_playreadyKeyId.empty()) + { + keyToApply = gst_buffer_new_allocate(nullptr, m_playreadyKeyId.size(), nullptr); + gst_buffer_fill(keyToApply, 0, m_playreadyKeyId.data(), m_playreadyKeyId.size()); + shouldReleaseKey = true; + } + + GstStructure *info = gst_structure_new("application/x-cenc", "encrypted", G_TYPE_BOOLEAN, TRUE, "mks_id", + G_TYPE_INT, m_rialtoSessionId, "kid", GST_TYPE_BUFFER, keyToApply, "iv_size", + G_TYPE_UINT, gst_buffer_get_size(IV), "iv", GST_TYPE_BUFFER, IV, + "subsample_count", G_TYPE_UINT, subSampleCount, "subsamples", GST_TYPE_BUFFER, + subSample, "encryption_scheme", G_TYPE_UINT, 0, // AES Counter + "init_with_last_15", G_TYPE_UINT, initWithLast15, NULL); + + GstProtectionMeta *protectionMeta = reinterpret_cast(gst_buffer_get_protection_meta(buffer)); + if (protectionMeta && protectionMeta->info) + { + const char *cipherModeBuf = gst_structure_get_string(protectionMeta->info, "cipher-mode"); + if (cipherModeBuf) + { + GST_INFO("Copy cipher mode [%s] and crypt/skipt byte blocks to protection metadata.", cipherModeBuf); + gst_structure_set(info, "cipher-mode", G_TYPE_STRING, cipherModeBuf, NULL); + + uint32_t patternCryptoBlocks = 0; + uint32_t patternClearBlocks = 0; + + if (gst_structure_get_uint(protectionMeta->info, "crypt_byte_block", &patternCryptoBlocks)) + { + gst_structure_set(info, "crypt_byte_block", G_TYPE_UINT, patternCryptoBlocks, NULL); + } + + if (gst_structure_get_uint(protectionMeta->info, "skip_byte_block", &patternClearBlocks)) + { + gst_structure_set(info, "skip_byte_block", G_TYPE_UINT, patternClearBlocks, NULL); + } + } + } + + rialto_mse_add_protection_metadata(buffer, info); + + if (shouldReleaseKey) + { + gst_buffer_unref(keyToApply); + } +} + +bool OpenCDMSessionPrivate::addProtectionMeta(GstBuffer *buffer) +{ + GstProtectionMeta *protectionMeta = reinterpret_cast(gst_buffer_get_protection_meta(buffer)); + if (!protectionMeta) + { + m_log << debug << "No protection meta added to the buffer"; + return false; + } + + GstStructure *info = gst_structure_copy(protectionMeta->info); + gst_structure_set(info, "mks_id", G_TYPE_INT, m_rialtoSessionId, NULL); + + if (!gst_structure_has_field_typed(info, "encrypted", G_TYPE_BOOLEAN)) + { + // Set encrypted + gst_structure_set(info, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL); + } + + if (gst_structure_has_field_typed(info, "iv", GST_TYPE_BUFFER) && + !gst_structure_has_field_typed(info, "iv_size", G_TYPE_UINT)) + { + const GValue *value = gst_structure_get_value(info, "iv"); + if (value) + { + GstBuffer *ivBuffer = gst_value_get_buffer(value); + // Set iv size + gst_structure_set(info, "iv_size", G_TYPE_UINT, gst_buffer_get_size(ivBuffer), NULL); + } + } + + if (!gst_structure_has_field_typed(info, "encryption_scheme", G_TYPE_UINT)) + { + // Not used but required + gst_structure_set(info, "encryption_scheme", G_TYPE_UINT, 0, NULL); + } + + // Set key for Playready + if (!m_playreadyKeyId.empty()) + { + GstBuffer *keyID = gst_buffer_new_allocate(nullptr, m_playreadyKeyId.size(), nullptr); + gst_buffer_fill(keyID, 0, m_playreadyKeyId.data(), m_playreadyKeyId.size()); + gst_structure_set(info, "kid", GST_TYPE_BUFFER, keyID, NULL); + gst_buffer_unref(keyID); + } + + rialto_mse_add_protection_metadata(buffer, info); + + return true; +} + +bool OpenCDMSessionPrivate::closeSession() +{ + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return false; + } + + if (-1 != m_rialtoSessionId) + { + if (m_cdmBackend->closeKeySession(m_rialtoSessionId)) + { + m_log << info << "Successfully closed the session"; + m_messageDispatcherClient.reset(); + m_challengeData.clear(); + m_keyStatuses.clear(); + return true; + } + else + { + m_log << warn << "Failed to close the session."; + } + } + + return false; +} + +bool OpenCDMSessionPrivate::removeSession() +{ + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return false; + } + + if (-1 != m_rialtoSessionId) + { + if (m_cdmBackend->removeKeySession(m_rialtoSessionId)) + { + m_log << info << "Successfully removed the session"; + return true; + } + else + { + m_log << warn << "Failed to remove the session."; + } + } + + return false; +} + +void OpenCDMSessionPrivate::releaseSession() +{ + if (-1 != m_rialtoSessionId) + { + if (m_cdmBackend->releaseKeySession(m_rialtoSessionId)) + { + m_log << info << "Successfully released the session"; + } + else + { + m_log << warn << "Failed to release the session."; + } + } +} + +bool OpenCDMSessionPrivate::containsKey(const std::vector &keyId) +{ + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return false; + } + + if (-1 != m_rialtoSessionId) + { + return m_cdmBackend->containsKey(m_rialtoSessionId, keyId); + } + return false; +} + +bool OpenCDMSessionPrivate::setDrmHeader(const std::vector &drmHeader) +{ + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return false; + } + + if (-1 != m_rialtoSessionId) + { + return m_cdmBackend->setDrmHeader(m_rialtoSessionId, drmHeader); + } + return false; +} + +bool OpenCDMSessionPrivate::selectKeyId(const std::vector &keyId) +{ + m_log << debug << "Playready key selected."; + m_playreadyKeyId = keyId; + return true; +} + +void OpenCDMSessionPrivate::onLicenseRequest(int32_t keySessionId, + const std::vector &licenseRequestMessage, + const std::string &url) +{ + if (keySessionId == m_rialtoSessionId) + { + updateChallenge(licenseRequestMessage); + + if ((m_callbacks) && (m_callbacks->process_challenge_callback)) + { + m_callbacks->process_challenge_callback(this, m_context, url.c_str(), licenseRequestMessage.data(), + licenseRequestMessage.size()); + } + } +} + +void OpenCDMSessionPrivate::onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) +{ + if (keySessionId == m_rialtoSessionId) + { + updateChallenge(licenseRenewalMessage); + + if ((m_callbacks) && (m_callbacks->process_challenge_callback)) + { + m_callbacks->process_challenge_callback(this, m_context, "" /*URL*/, licenseRenewalMessage.data(), + licenseRenewalMessage.size()); + } + } +} + +void OpenCDMSessionPrivate::updateChallenge(const std::vector &challenge) +{ + std::unique_lock lock{m_mutex}; + m_challengeData = challenge; + m_challengeCv.notify_one(); +} + +void OpenCDMSessionPrivate::onKeyStatusesChanged(int32_t keySessionId, + const firebolt::rialto::KeyStatusVector &keyStatuses) +{ + if ((keySessionId == m_rialtoSessionId) && (m_callbacks) && (m_callbacks->key_update_callback)) + { + for (const std::pair, firebolt::rialto::KeyStatus> &keyStatus : keyStatuses) + { + // Update internal key statuses + m_keyStatuses[keyStatus.first] = keyStatus.second; + + const std::vector &key = keyStatus.first; + m_callbacks->key_update_callback(this, m_context, key.data(), key.size()); + } + + if (m_callbacks->keys_updated_callback) + { + m_callbacks->keys_updated_callback(this, m_context); + } + } +} + +KeyStatus OpenCDMSessionPrivate::status(const std::vector &key) const +{ + auto it = m_keyStatuses.find(key); + if (it != m_keyStatuses.end()) + { + return convertKeyStatus(it->second); + } + return KeyStatus::InternalError; +} + +const std::string &OpenCDMSessionPrivate::getSessionId() const +{ + return m_cdmKeySessionId; +} + +void OpenCDMSessionPrivate::initializeCdmKeySessionId() +{ + bool result{false}; + + if (-1 != m_rialtoSessionId) + { + result = m_cdmBackend->getCdmKeySessionId(m_rialtoSessionId, m_cdmKeySessionId); + } + if (!result) + { + m_cdmKeySessionId = kDefaultSessionId; + } +} + +uint32_t OpenCDMSessionPrivate::getLastDrmError() const +{ + uint32_t err = 0; + if (!m_cdmBackend) + { + m_log << error << "Cdm is NULL or not initialized"; + return -1; + } + + (void)m_cdmBackend->getLastDrmError(m_rialtoSessionId, err); + + return err; +} + +firebolt::rialto::KeySessionType OpenCDMSessionPrivate::getRialtoSessionType(const LicenseType licenseType) +{ + switch (licenseType) + { + case Temporary: + return firebolt::rialto::KeySessionType::TEMPORARY; + case PersistentUsageRecord: /// TODO: Rialto's equivalent?? + return firebolt::rialto::KeySessionType::UNKNOWN; + case PersistentLicense: + return firebolt::rialto::KeySessionType::PERSISTENT_LICENCE; + default: + return firebolt::rialto::KeySessionType::UNKNOWN; + } +} + +firebolt::rialto::InitDataType OpenCDMSessionPrivate::getRialtoInitDataType(const std::string &type) +{ + firebolt::rialto::InitDataType initDataType = firebolt::rialto::InitDataType::UNKNOWN; + + if (type == "cenc") + { + initDataType = firebolt::rialto::InitDataType::CENC; + } + else if (type == "webm") + { + initDataType = firebolt::rialto::InitDataType::WEBM; + } + else if (type == "drmheader") + { + initDataType = firebolt::rialto::InitDataType::DRMHEADER; + } + + return initDataType; +} diff --git a/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp b/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp new file mode 100644 index 000000000..ef447490d --- /dev/null +++ b/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp @@ -0,0 +1,136 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "OpenCDMSystemPrivate.h" +#include "ActiveSessions.h" +#include "IMediaKeys.h" +#include + +OpenCDMSystem *createSystem(const char system[], const std::string &metadata) +{ + const std::string kKeySystem{system}; + auto messageDispatcher{std::make_shared()}; + auto cdmBackend{std::make_shared(kKeySystem, messageDispatcher, + firebolt::rialto::IMediaKeysFactory::createFactory())}; + return new OpenCDMSystemPrivate(kKeySystem, metadata, messageDispatcher, cdmBackend); +} + +OpenCDMSystemPrivate::OpenCDMSystemPrivate(const std::string &system, const std::string &metadata, + const std::shared_ptr &messageDispatcher, + const std::shared_ptr &cdmBackend) + : m_log{"OpenCDMSystemPrivate"}, m_keySystem(system), m_metadata(metadata), + m_control{firebolt::rialto::IControlFactory::createFactory()->createControl()}, + m_messageDispatcher{messageDispatcher}, m_cdmBackend{cdmBackend} +{ + m_log << debug << "constructed: " << static_cast(this); + if (!m_control || !m_cdmBackend) + { + return; + } + firebolt::rialto::ApplicationState initialState{firebolt::rialto::ApplicationState::UNKNOWN}; + m_control->registerClient(m_cdmBackend, initialState); + m_cdmBackend->initialize(initialState); +} + +OpenCDMSystemPrivate::~OpenCDMSystemPrivate() +{ + m_log << debug << "destructed: " << static_cast(this); +} + +const std::string &OpenCDMSystemPrivate::keySystem() const +{ + return m_keySystem; +} + +const std::string &OpenCDMSystemPrivate::metadata() const +{ + return m_metadata; +} + +OpenCDMSession *OpenCDMSystemPrivate::createSession(const LicenseType licenseType, OpenCDMSessionCallbacks *callbacks, + void *userData, const std::string &initDataType, + const std::vector &initData) const +{ + return ActiveSessions::instance().create(m_cdmBackend, m_messageDispatcher, licenseType, callbacks, userData, + initDataType, initData); +} + +bool OpenCDMSystemPrivate::getDrmTime(uint64_t &drmTime) const +{ + if (!m_cdmBackend) + { + return false; + } + return m_cdmBackend->getDrmTime(drmTime); +} + +bool OpenCDMSystemPrivate::getLdlSessionsLimit(uint32_t &ldlLimit) const +{ + if (!m_cdmBackend) + { + return false; + } + return m_cdmBackend->getLdlSessionsLimit(ldlLimit); +} + +bool OpenCDMSystemPrivate::getKeyStoreHash(std::vector &keyStoreHash) const +{ + if (!m_cdmBackend) + { + return false; + } + return m_cdmBackend->getKeyStoreHash(keyStoreHash); +} + +bool OpenCDMSystemPrivate::getDrmStoreHash(std::vector &drmStoreHash) const +{ + if (!m_cdmBackend) + { + return false; + } + return m_cdmBackend->getDrmStoreHash(drmStoreHash); +} + +bool OpenCDMSystemPrivate::deleteKeyStore() const +{ + if (!m_cdmBackend) + { + return false; + } + return m_cdmBackend->deleteKeyStore(); +} + +bool OpenCDMSystemPrivate::deleteDrmStore() const +{ + if (!m_cdmBackend) + { + return false; + } + return m_cdmBackend->deleteDrmStore(); +} + +bool OpenCDMSystemPrivate::getMetricSystemData(std::vector &buffer) const +{ + if (!m_cdmBackend) + { + return false; + } + + return m_cdmBackend->getMetricSystemData(buffer); +} diff --git a/middleware/rialto-ocdm/source/RialtoFactoryStubs.cpp b/middleware/rialto-ocdm/source/RialtoFactoryStubs.cpp new file mode 100644 index 000000000..3c0a1804e --- /dev/null +++ b/middleware/rialto-ocdm/source/RialtoFactoryStubs.cpp @@ -0,0 +1,72 @@ + +#include "IControl.h" +#include "IMediaKeys.h" +#include +#include +#include + +namespace firebolt::rialto +{ +// ---- IControl stub ---- + +class ControlFactoryStub : public IControlFactory +{ +public: + std::shared_ptr createControl() const override + { + struct ControlStub : public IControl + { + bool registerClient(std::weak_ptr /*client*/, ApplicationState &appState) override + { + // Leave application state UNKNOWN for stub + appState = ApplicationState::UNKNOWN; + return true; // pretend success + } + }; + return std::make_shared(); + } +}; + +std::shared_ptr IControlFactory::createFactory() +{ + return std::make_shared(); +} + +// ---- IMediaKeys stub ---- +class MediaKeysFactoryStub : public IMediaKeysFactory +{ +public: + std::unique_ptr createMediaKeys(const std::string & /*keySystem*/) const override + { + struct MediaKeysStub : public IMediaKeys + { + MediaKeyErrorStatus selectKeyId(int32_t /*keySessionId*/, const std::vector &/*keyId*/) override { return MediaKeyErrorStatus::FAIL; } + bool containsKey(int32_t /*keySessionId*/, const std::vector &/*keyId*/) override { return false; } + MediaKeyErrorStatus createKeySession(KeySessionType /*sessionType*/, std::weak_ptr /*client*/, bool /*isLDL*/, int32_t &keySessionId) override { keySessionId = -1; return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus generateRequest(int32_t /*keySessionId*/, InitDataType /*initDataType*/, const std::vector &/*initData*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus loadSession(int32_t /*keySessionId*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus updateSession(int32_t /*keySessionId*/, const std::vector &/*responseData*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus setDrmHeader(int32_t /*keySessionId*/, const std::vector &/*requestData*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus closeKeySession(int32_t /*keySessionId*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus removeKeySession(int32_t /*keySessionId*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus deleteDrmStore() override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus deleteKeyStore() override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus getDrmStoreHash(std::vector &/*drmStoreHash*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus getKeyStoreHash(std::vector &/*keyStoreHash*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) override { ldlLimit = 0; return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus getLastDrmError(int32_t /*keySessionId*/, uint32_t &errorCode) override { errorCode = 0; return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) override { drmTime = 0; return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus getCdmKeySessionId(int32_t /*keySessionId*/, std::string &cdmKeySessionId) override { cdmKeySessionId.clear(); return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus releaseKeySession(int32_t /*keySessionId*/) override { return MediaKeyErrorStatus::FAIL; } + MediaKeyErrorStatus getMetricSystemData(std::vector &/*buffer*/) override { return MediaKeyErrorStatus::FAIL; } + }; + return std::make_unique(); + } +}; + +std::shared_ptr IMediaKeysFactory::createFactory() +{ + return std::make_shared(); +} + +} // namespace firebolt::rialto diff --git a/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp b/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp new file mode 100644 index 000000000..c657d49ec --- /dev/null +++ b/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp @@ -0,0 +1,87 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "RialtoGStreamerEMEProtectionMetadata.h" +#include + +// NOLINTNEXTLINE(build/function_format) +static gboolean rialto_eme_protection_metadata_init(GstMeta *meta, gpointer params, GstBuffer *buffer) +{ + // NOLINTNEXTLINE(readability/casting) + GstRialtoProtectionMetadata *emeta = reinterpret_cast(meta); + + emeta->info = NULL; + + return TRUE; +} + +// NOLINTNEXTLINE(build/function_format) +static gboolean rialto_eme_protection_metadata_free(GstMeta *meta, GstBuffer *buffer) +{ + // NOLINTNEXTLINE(readability/casting) + GstRialtoProtectionMetadata *emeta = reinterpret_cast(meta); + + if (emeta->info) + { + gst_structure_free(emeta->info); + emeta->info = nullptr; + } + + return TRUE; +} + +// NOLINTNEXTLINE(build/function_format) +GST_EXPORT GType rialto_eme_protection_metadata_get_type() +{ + static GType g_type{0}; + static const gchar *api_tags[] = {"rialto", "protection", NULL}; + + if (g_once_init_enter(&g_type)) + { + GType _type = gst_meta_api_type_register("GstRialtoProtectionMetadataAPI", api_tags); + g_once_init_leave(&g_type, _type); + } + return g_type; +} + +// NOLINTNEXTLINE(build/function_format) +const GstMetaInfo *rialto_mse_protection_metadata_get_info() +{ + static const GstMetaInfo *metainfo = NULL; + if (g_once_init_enter(&metainfo)) + { + const GstMetaInfo *gstMeta = + gst_meta_register(GST_RIALTO_PROTECTION_METADATA_GET_TYPE, "GstRialtoProtectionMetadata", + sizeof(GstRialtoProtectionMetadata), + (GstMetaInitFunction)rialto_eme_protection_metadata_init, + (GstMetaFreeFunction)rialto_eme_protection_metadata_free, (GstMetaTransformFunction)NULL); + + g_once_init_leave(&metainfo, gstMeta); + } + return metainfo; +} + +// NOLINTNEXTLINE(build/function_format) +GstRialtoProtectionMetadata *rialto_mse_add_protection_metadata(GstBuffer *gstBuffer, GstStructure *info) +{ + GstRialtoProtectionMetadata *metadata = reinterpret_cast( + gst_buffer_add_meta(gstBuffer, GST_RIALTO_PROTECTION_METADATA_INFO, NULL)); + metadata->info = info; + return metadata; +} diff --git a/middleware/rialto-ocdm/source/open_cdm.cpp b/middleware/rialto-ocdm/source/open_cdm.cpp new file mode 100644 index 000000000..ed7566798 --- /dev/null +++ b/middleware/rialto-ocdm/source/open_cdm.cpp @@ -0,0 +1,453 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ActiveSessions.h" +#include "Logger.h" +#include "MediaKeysCapabilitiesBackend.h" +#include "OpenCDMSession.h" +#include "OpenCDMSystemPrivate.h" +#include +#include + +namespace +{ +const Logger kLog{"open_cdm"}; + +bool isNetflixPlayreadyKeysystem(const std::string &keySystem) +{ + return keySystem.find("netflix") != std::string::npos; +} +} // namespace + +OpenCDMSystem *opencdm_create_system(const char keySystem[]) +{ + kLog << debug << __func__; + + const char kSrcRev[] = "NULL"; + const char kTags[] = "NULL"; + + if (std::strlen(kSrcRev) > 0) + { + if (std::strlen(kTags) > 0) + { + kLog << mil << "Release Tag(s): " << kTags << " (Commit ID: " << kSrcRev << ")"; + } + else + { + kLog << mil << "Release Tag(s): No Release Tags!" << " (Commit ID: " << kSrcRev << ")"; + } + } + else + { + kLog << warn << "Failed to get git commit ID!"; + } + + OpenCDMSystem *result = nullptr; + opencdm_create_system_extended(keySystem, &result); + + return result; +} + +OpenCDMError opencdm_create_system_extended(const char keySystem[], struct OpenCDMSystem **system) +{ + kLog << debug << __func__; + assert(system != nullptr); + + *system = createSystem(keySystem, ""); + + return ERROR_NONE; +} + +OpenCDMError opencdm_destruct_system(struct OpenCDMSystem *system) +{ + kLog << debug << __func__; + if (system) + { + delete system; + } + + return ERROR_NONE; +} + +OpenCDMError opencdm_is_type_supported(const char keySystem[], const char mimeType[]) +{ + kLog << debug << __func__; + return MediaKeysCapabilitiesBackend::instance().supportsKeySystem(std::string(keySystem)); +} + +OpenCDMError opencdm_system_get_metadata(struct OpenCDMSystem *system, char metadata[], uint16_t *metadataSize) +{ + kLog << debug << __func__; + if (!system || !metadataSize) + { + kLog << error << __func__ << ": System or metadataSize is NULL"; + return ERROR_FAIL; + } + *metadataSize = 0; + return ERROR_NONE; +} + +OpenCDMError opencdm_system_get_version(struct OpenCDMSystem *system, char versionStr[]) +{ + kLog << debug << __func__; + if (!system || !versionStr) + { + kLog << error << __func__ << ": System or versionStr is NULL"; + return ERROR_FAIL; + } + std::string version; + if (!MediaKeysCapabilitiesBackend::instance().getSupportedKeySystemVersion(system->keySystem(), version)) + { + return ERROR_FAIL; + } + + const size_t MAX_LEN = 64; + snprintf(versionStr, MAX_LEN, "%s", version.c_str()); + + return ERROR_NONE; +} + +OpenCDMError opencdm_system_get_drm_time(struct OpenCDMSystem *system, uint64_t *time) +{ + kLog << debug << __func__; + if (!time || !system) + { + kLog << error << "Ptr is null"; + return ERROR_FAIL; + } + if (!system->getDrmTime(*time)) + { + kLog << error << "Failed to get DRM Time"; + return ERROR_FAIL; + } + return ERROR_NONE; +} + +struct OpenCDMSession *opencdm_get_system_session(struct OpenCDMSystem *system, const uint8_t keyId[], + const uint8_t length, const uint32_t waitTime) +{ + kLog << debug << __func__; + return ActiveSessions::instance().get(std::vector(keyId, keyId + length)); +} + +OpenCDMError opencdm_system_set_server_certificate(struct OpenCDMSystem *system, const uint8_t serverCertificate[], + const uint16_t serverCertificateLength) +{ + kLog << debug << __func__; + return ERROR_NONE; +} + +struct OpenCDMSession *opencdm_get_session(const uint8_t keyId[], const uint8_t length, const uint32_t waitTime) +{ + kLog << debug << __func__; + return opencdm_get_system_session(nullptr, keyId, length, waitTime); +} + +OpenCDMError opencdm_construct_session(struct OpenCDMSystem *system, const LicenseType licenseType, + const char initDataType[], const uint8_t initData[], + const uint16_t initDataLength, const uint8_t CDMData[], + const uint16_t CDMDataLength, OpenCDMSessionCallbacks *callbacks, void *userData, + struct OpenCDMSession **session) +{ + kLog << debug << __func__; + if (!system) + { + kLog << error << "System is NULL or not initialized"; + return ERROR_FAIL; + } + std::string initializationDataType(initDataType); + std::vector initDataVec(reinterpret_cast(initData), + reinterpret_cast(initData) + initDataLength); + + OpenCDMSession *newSession = + system->createSession(licenseType, callbacks, userData, initializationDataType, initDataVec); + + if (!newSession) + { + return ERROR_INVALID_SESSION; + } + + if (!isNetflixPlayreadyKeysystem(system->keySystem())) + { + if (!newSession->initialize()) + { + kLog << error << "Failed to create session"; + ActiveSessions::instance().remove(newSession); + return ERROR_FAIL; + } + std::vector cdmDataVec(reinterpret_cast(CDMData), + reinterpret_cast(CDMData) + CDMDataLength); + + if (!newSession->generateRequest(initializationDataType, initDataVec, cdmDataVec /*not used yet*/)) + { + kLog << error << "Failed to generate request"; + + opencdm_session_close(newSession); + opencdm_destruct_session(newSession); + return ERROR_FAIL; + } + } + + *session = newSession; + + return ERROR_NONE; +} + +OpenCDMError opencdm_destruct_session(struct OpenCDMSession *session) +{ + kLog << debug << __func__; + if (session) + { + ActiveSessions::instance().remove(session); + return ERROR_NONE; + } + return ERROR_INVALID_SESSION; +} + +OpenCDMError opencdm_session_load(struct OpenCDMSession *session) +{ + kLog << debug << __func__; + OpenCDMError result = ERROR_INVALID_SESSION; + if (session) + { + if (session->loadSession()) + { + result = ERROR_NONE; + } + else + { + kLog << error << "Failed to load the session"; + result = ERROR_FAIL; + } + } + + return result; +} + +OpenCDMError opencdm_session_metadata(const struct OpenCDMSession *session, char metadata[], uint16_t *metadataSize) +{ + kLog << debug << __func__; + if (!session || !metadataSize) + { + kLog << error << __func__ << ": session or metadata size is null"; + return ERROR_FAIL; + } + *metadataSize = 0; + return ERROR_NONE; +} + +const char *opencdm_session_id(const struct OpenCDMSession *session) +{ + kLog << debug << __func__; + if (!session) + { + return nullptr; + } + return session->getSessionId().c_str(); +} + +const char *opencdm_session_buffer_id(const struct OpenCDMSession *session) +{ + kLog << debug << __func__; + return nullptr; +} + +uint32_t opencdm_session_has_key_id(struct OpenCDMSession *session, const uint8_t length, const uint8_t keyId[]) +{ + kLog << debug << __func__; + if (!session) + { + kLog << error << "Failed to check key id"; + return 0; + } + std::vector key(keyId, keyId + length); + return static_cast(session->containsKey(key)); +} + +KeyStatus opencdm_session_status(const struct OpenCDMSession *session, const uint8_t keyId[], uint8_t length) +{ + kLog << debug << __func__; + if (session && keyId && 0 != length) + { + std::vector key(keyId, keyId + length); + return session->status(key); + } + + return InternalError; +} + +uint32_t opencdm_session_error(const struct OpenCDMSession *session, const uint8_t keyId[], uint8_t length) +{ + kLog << warn << __func__ << " NOT IMPLEMENTED YET"; + return 0; +} + +OpenCDMError opencdm_session_system_error(const struct OpenCDMSession *session) +{ + kLog << debug << __func__; + if (!session) + { + kLog << error << __func__ << ": Failed to get session system error - session is null"; + return ERROR_FAIL; + } + uint32_t err = session->getLastDrmError(); + // Rialto doesn't implement it yet + switch (err) + { + default: + return ERROR_NONE; + } +} + +OpenCDMError opencdm_session_update(struct OpenCDMSession *session, const uint8_t keyMessage[], uint16_t keyLength) +{ + kLog << debug << __func__; + if (!session) + { + kLog << error << __func__ << ": Session is NULL"; + return ERROR_INVALID_SESSION; + } + if (!keyMessage || keyLength == 0) + { + kLog << error << __func__ << ": keyMessage is empty"; + return ERROR_FAIL; + } + std::vector license(keyMessage, keyMessage + keyLength); + if (!session->updateSession(license)) + { + kLog << error << "Failed to update the session"; + return ERROR_FAIL; + } + + return ERROR_NONE; +} + +OpenCDMError opencdm_session_remove(struct OpenCDMSession *session) +{ + kLog << debug << __func__; + OpenCDMError result = ERROR_INVALID_SESSION; + if (session) + { + if (session->removeSession()) + { + result = ERROR_NONE; + } + else + { + kLog << error << "Failed to remove the key session"; + result = ERROR_FAIL; + } + } + + return result; +} + +OpenCDMError opencdm_session_resetoutputprotection(struct OpenCDMSession *session) +{ + kLog << warn << __func__ << " NOT IMPLEMENTED YET"; + return ERROR_NONE; +} + +OpenCDMError opencdm_session_set_parameter(struct OpenCDMSession *session, const std::string &name, + const std::string &value) +{ + kLog << warn << __func__ << " NOT IMPLEMENTED YET"; + return ERROR_NONE; +} + +OpenCDMError opencdm_session_close(struct OpenCDMSession *session) +{ + kLog << debug << __func__; + OpenCDMError result = ERROR_INVALID_SESSION; + if (session) + { + if (session->closeSession()) + { + result = ERROR_NONE; + } + else + { + kLog << error << "Failed to close the key session"; + result = ERROR_FAIL; + } + } + + return result; +} + +OpenCDMBool opencdm_system_supports_server_certificate(struct OpenCDMSystem *system) +{ + kLog << debug << __func__; + if (MediaKeysCapabilitiesBackend::instance().isServerCertificateSupported(system->keySystem())) + { + return OpenCDMBool::OPENCDM_BOOL_TRUE; + } + return OpenCDMBool::OPENCDM_BOOL_FALSE; +} + +OpenCDMError opencdm_session_decrypt(struct OpenCDMSession *session, uint8_t encrypted[], + const uint32_t encryptedLength, const EncryptionScheme encScheme, + const EncryptionPattern pattern, const uint8_t *IV, uint16_t IVLength, + const uint8_t *keyId, const uint16_t keyIdLength, uint32_t initWithLast15) +{ + kLog << warn << __func__ << " not implemented"; + return ERROR_FAIL; +} + +OpenCDMError opencdm_get_metric_system_data(struct OpenCDMSystem *system, uint32_t *bufferLength, uint8_t *buffer) +{ + kLog << debug << __func__; + if (!system) + { + kLog << error << "System ptr is null"; + return ERROR_FAIL; + } + + if (!bufferLength) + { + kLog << error << "Buffer length ptr is null"; + return ERROR_FAIL; + } + + if (!buffer) + { + kLog << error << "Buffer ptr is null"; + return ERROR_FAIL; + } + + std::vector bufferVec; + if (!system->getMetricSystemData(bufferVec)) + { + kLog << error << "Failed to get metric system data"; + return ERROR_FAIL; + } + + if (*bufferLength < bufferVec.size()) + { + kLog << error << "Buffer is too small - return size " << bufferVec.size() << " does not fit in buffer of size " + << *bufferLength; + return ERROR_BUFFER_TOO_SMALL; + } + + std::memcpy(buffer, bufferVec.data(), bufferVec.size()); + *bufferLength = bufferVec.size(); + return ERROR_NONE; +} diff --git a/middleware/rialto-ocdm/source/open_cdm_adapter.cpp b/middleware/rialto-ocdm/source/open_cdm_adapter.cpp new file mode 100644 index 000000000..0b694b2fe --- /dev/null +++ b/middleware/rialto-ocdm/source/open_cdm_adapter.cpp @@ -0,0 +1,70 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Logger.h" +#include "OpenCDMSession.h" +#include + +namespace +{ +const Logger kLog{"open_cdm_adapter"}; +} // namespace + +OpenCDMError opencdm_gstreamer_session_decrypt_ex(struct OpenCDMSession *session, GstBuffer *buffer, + GstBuffer *subSample, const uint32_t subSampleCount, GstBuffer *IV, + GstBuffer *keyID, uint32_t initWithLast15, GstCaps *caps) +{ + if (nullptr == session) + { + kLog << error << "Failed to decrypt - session is NULL"; + return ERROR_FAIL; + } + session->addProtectionMeta(buffer, subSample, subSampleCount, IV, keyID, initWithLast15); + return ERROR_NONE; +} + +OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession *session, GstBuffer *buffer, GstBuffer *subSample, + const uint32_t subSampleCount, GstBuffer *IV, GstBuffer *keyID, + uint32_t initWithLast15) +{ + return opencdm_gstreamer_session_decrypt_ex(session, buffer, subSample, subSampleCount, IV, keyID, initWithLast15, + nullptr); +} + +OpenCDMError opencdm_gstreamer_session_decrypt_buffer(struct OpenCDMSession *session, GstBuffer *buffer, GstCaps *caps) +{ + if (nullptr == session) + { + kLog << error << "Failed to decrypt - session is NULL"; + return ERROR_FAIL; + } + + if (!session->addProtectionMeta(buffer)) + { + kLog << error << "Failed to decrypt - could not append protection meta"; + return ERROR_FAIL; + } + + return ERROR_NONE; +} + +OpenCDMError opencdm_gstreamer_transform_caps(GstCaps **caps) +{ + return ERROR_NONE; +} diff --git a/middleware/rialto-ocdm/source/open_cdm_ext.cpp b/middleware/rialto-ocdm/source/open_cdm_ext.cpp new file mode 100644 index 000000000..7539a43e3 --- /dev/null +++ b/middleware/rialto-ocdm/source/open_cdm_ext.cpp @@ -0,0 +1,285 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Logger.h" +#include "OpenCDMSession.h" +#include "OpenCDMSystem.h" +#include + +namespace +{ +const Logger kLog{"open_cdm_ext"}; +} // namespace + +OpenCDMError opencdm_system_ext_get_ldl_session_limit(struct OpenCDMSystem *system, uint32_t *ldlLimit) +{ + kLog << debug << __func__; + if (!system || !ldlLimit) + { + kLog << error << "Failed to get ldl session limit - System is NULL"; + return ERROR_FAIL; + } + + if (!system->getLdlSessionsLimit(*ldlLimit)) + { + kLog << error << "Failed to get LDL Session limit"; + return ERROR_FAIL; + } + return ERROR_NONE; +} + +uint32_t opencdm_system_ext_is_secure_stop_enabled(struct OpenCDMSystem *system) +{ + kLog << warn << "Secure stop not supported"; + return 0; +} + +OpenCDMError opencdm_system_ext_enable_secure_stop(struct OpenCDMSystem *system, uint32_t use) +{ + kLog << warn << "Secure stop not supported"; + return ERROR_FAIL; +} + +uint32_t opencdm_system_ext_reset_secure_stop(struct OpenCDMSystem *system) +{ + kLog << warn << "Reset secure stop not supported"; + return 0; +} + +OpenCDMError opencdm_system_ext_get_secure_stop_ids(struct OpenCDMSystem *system, uint8_t Ids[], uint16_t idsLength, + uint32_t *count) +{ + kLog << warn << "Failed to get secure stop ids - not supported"; + return ERROR_FAIL; +} + +OpenCDMError opencdm_system_ext_get_secure_stop(struct OpenCDMSystem *system, const uint8_t sessionID[], + uint32_t sessionIDLength, uint8_t rawData[], uint16_t *rawSize) +{ + kLog << warn << "Failed to get secure stop - not supported"; + return ERROR_FAIL; +} + +OpenCDMError opencdm_system_ext_commit_secure_stop(struct OpenCDMSystem *system, const uint8_t sessionID[], + uint32_t sessionIDLength, const uint8_t serverResponse[], + uint32_t serverResponseLength) +{ + kLog << warn << "Failed to commit secure stop - not supported"; + return ERROR_FAIL; +} + +OpenCDMError opencdm_get_key_store_hash_ext(struct OpenCDMSystem *system, uint8_t keyStoreHash[], + uint32_t keyStoreHashLength) +{ + kLog << debug << __func__; + if (!system || 0 == keyStoreHashLength) + { + kLog << error << "Failed to get key store hash - arguments are not valid"; + return ERROR_FAIL; + } + std::vector keyStoreHashVec; + if (!system->getKeyStoreHash(keyStoreHashVec)) + { + kLog << error << "Failed to get key store hash - operation failed"; + return ERROR_FAIL; + } + if (keyStoreHashVec.size() > keyStoreHashLength) + { + kLog << error << "Failed to get key store hash - return of size " << keyStoreHashVec.size() + << " does not fit in buffer of size " << keyStoreHashLength; + return ERROR_FAIL; + } + memcpy(keyStoreHash, keyStoreHashVec.data(), keyStoreHashVec.size()); + return ERROR_NONE; +} + +OpenCDMError opencdm_get_secure_store_hash_ext(struct OpenCDMSystem *system, uint8_t secureStoreHash[], + uint32_t secureStoreHashLength) +{ + kLog << debug << __func__; + if (!system || 0 == secureStoreHashLength) + { + kLog << error << "Failed to get secure store hash - arguments are not valid"; + return ERROR_FAIL; + } + std::vector secureStoreHashVec; + if (!system->getDrmStoreHash(secureStoreHashVec)) + { + kLog << error << "Failed to get secure store hash - operation failed"; + return ERROR_FAIL; + } + if (secureStoreHashVec.size() > secureStoreHashLength) + { + kLog << error << "Failed to get key store hash - return size " << secureStoreHashVec.size() + << " does not fit in buffer of size " << secureStoreHashLength; + return ERROR_FAIL; + } + memcpy(secureStoreHash, secureStoreHashVec.data(), secureStoreHashVec.size()); + return ERROR_NONE; +} + +OpenCDMError opencdm_delete_key_store(struct OpenCDMSystem *system) +{ + kLog << debug << __func__; + if (!system) + { + kLog << error << "Failed to delete key store - arguments are not valid"; + return ERROR_FAIL; + } + if (!system->deleteKeyStore()) + { + kLog << error << "Failed to delete key store - operation failed"; + return ERROR_FAIL; + } + return ERROR_NONE; +} + +OpenCDMError opencdm_delete_secure_store(struct OpenCDMSystem *system) +{ + kLog << debug << __func__; + if (!system) + { + kLog << error << "Failed to delete secure store - arguments are not valid"; + return ERROR_FAIL; + } + if (!system->deleteDrmStore()) + { + kLog << error << "Failed to delete secure store - operation failed"; + return ERROR_FAIL; + } + return ERROR_NONE; +} + +OpenCDMError opencdm_session_set_drm_header(struct OpenCDMSession *opencdmSession, const uint8_t drmHeader[], + uint32_t drmHeaderSize) +{ + kLog << debug << __func__; + if (nullptr == opencdmSession) + { + kLog << error << "Failed to set Drm Header - session is NULL"; + return ERROR_FAIL; + } + std::vector drmHeaderVec(drmHeader, drmHeader + drmHeaderSize); + if (!opencdmSession->setDrmHeader(drmHeaderVec)) + { + kLog << error << "Failed to set Drm Header - operation returned NOK status"; + return ERROR_FAIL; + } + return ERROR_NONE; +} + +OpenCDMError opencdm_session_get_challenge_data(struct OpenCDMSession *mOpenCDMSession, uint8_t *challenge, + uint32_t *challengeSize, uint32_t isLDL) +{ + kLog << debug << __func__; + if (nullptr == mOpenCDMSession || nullptr == challengeSize) + { + kLog << error << "Failed to get challenge data - arguments are not valid"; + return ERROR_FAIL; + } + if (!mOpenCDMSession->initialize(isLDL)) + { + kLog << error << "Failed to create session"; + return ERROR_FAIL; + } + std::vector challengeVec; + if (!mOpenCDMSession->getChallengeData(challengeVec)) + { + kLog << error << "Failed to get challenge data - operation returned NOK status"; + return ERROR_FAIL; + } + *challengeSize = challengeVec.size(); + if (nullptr != challenge) + { + memcpy(challenge, challengeVec.data(), challengeVec.size()); + } + return ERROR_NONE; +} + +OpenCDMError opencdm_session_cancel_challenge_data(struct OpenCDMSession *mOpenCDMSession) +{ + kLog << debug << __func__; + // MKS is destructed in opencdm_session_clean_decrypt_context + return ERROR_NONE; +} + +OpenCDMError opencdm_session_store_license_data(struct OpenCDMSession *openCDMSession, const uint8_t licenseData[], + uint32_t licenseDataSize, uint8_t *secureStopId) +{ + kLog << debug << __func__; + if (!openCDMSession) + { + kLog << error << "Failed to store license data - session is NULL"; + return ERROR_INVALID_SESSION; + } + if (!licenseData || 0 == licenseDataSize) + { + kLog << error << "Failed to store license data - data is null or empty"; + return ERROR_FAIL; + } + std::vector license(licenseData, licenseData + licenseDataSize); + + if (!openCDMSession->updateSession(license)) + { + kLog << error << "Failed to store license data - op failed"; + return ERROR_FAIL; + } + + return ERROR_NONE; +} + +OpenCDMError opencdm_session_select_key_id(struct OpenCDMSession *mOpenCDMSession, uint8_t keyLength, + const uint8_t keyId[]) +{ + kLog << debug << __func__; + if (!mOpenCDMSession || !keyId || 0 == keyLength) + { + kLog << error << "Failed to select key id - session or key is NULL"; + return ERROR_FAIL; + } + std::vector keyIdVec(keyId, keyId + keyLength); + if (!mOpenCDMSession->selectKeyId(keyIdVec)) + { + kLog << error << "Failed to select key id - operation returned NOK status"; + return ERROR_FAIL; + } + return ERROR_NONE; +} + +OpenCDMError opencdm_system_teardown(struct OpenCDMSystem *system) +{ + kLog << debug << __func__; + return ERROR_NONE; +} + +OpenCDMError opencdm_session_clean_decrypt_context(struct OpenCDMSession *mOpenCDMSession) +{ + kLog << debug << __func__; + if (!mOpenCDMSession) + { + kLog << error << "Failed to clean decrypt context - arguments are not valid"; + return ERROR_FAIL; + } + if (!mOpenCDMSession->closeSession()) + { + kLog << error << "Failed to close the session"; + return ERROR_FAIL; + } + return ERROR_NONE; +} diff --git a/rialto-master/media/public/include/IMediaPipeline.h b/rialto-master/media/public/include/IMediaPipeline.h index 0e7ce629f..47f2e3cb9 100644 --- a/rialto-master/media/public/include/IMediaPipeline.h +++ b/rialto-master/media/public/include/IMediaPipeline.h @@ -1449,6 +1449,8 @@ class IMediaPipeline */ virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, uint64_t stopPosition = kUndefinedPosition) = 0; + + virtual bool setSubtitleOffset(int32_t sourceId, int64_t position) = 0; /** * @brief Process audio gap diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index b7a2cb278..803134059 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -5,9 +5,15 @@ // Created by Stroffolino, Philip on 9/19/25. // #include +#include +#include +#include #include "mp4demux.hpp" #include "rialto-gst-pipeline.h" +// Using Rialto pipeline only: define nanosecond conversion locally instead of relying on GST headers. +static const int64_t NS_SECOND = 1000000000LL; + static Mp4Demux trackAudio; static Mp4Demux trackVideo; static GstMediaPipeline *gstMediaPipeline; @@ -74,14 +80,17 @@ void ConfigureAudio( void ) assert(0); break; } - std::unique_ptr sourceAudio = std::make_unique( + std::unique_ptr sourceAudio = std::make_unique( mimeType, hasDrm, audioConfig, SegmentAlignment::UNDEFINED, streamFormat, nullptr /* codecData*/ ); - gstMediaPipeline->attachSource( std::move(sourceAudio), sourceIdAudio ); + // Attach; then read assigned id from source + bool okA = gstMediaPipeline->attachSource( sourceAudio ); + assert(okA); + sourceIdAudio = sourceAudio->getId(); } void ConfigureVideo( void ) @@ -112,7 +121,8 @@ void ConfigureVideo( void ) CodecData codecData; const char *codec_ptr = trackVideo.codec_data.c_str(); codecData.data = std::vector( codec_ptr, &codec_ptr[trackVideo.codec_data.size()] ); - std::unique_ptr sourceVideo = + // Store derived video source in unique_ptr so it matches attachSource(const unique_ptr&) + std::unique_ptr sourceVideo = std::make_unique( mimeType, hasDrm, @@ -121,7 +131,9 @@ void ConfigureVideo( void ) alignment, streamFormat, std::make_shared(codecData) ); - gstMediaPipeline->attachSource( std::move(sourceVideo), sourceIdVideo ); + bool okV = gstMediaPipeline->attachSource( sourceVideo ); + assert(okV); + sourceIdVideo = sourceVideo->getId(); } void ConfigurenComplete() @@ -140,11 +152,11 @@ void InjectAudio( void ) double dur = trackAudio.getDuration(i); std::unique_ptr audioSegment = std::make_unique( - sourceIdAudio, - (int64_t)(pts*GST_SECOND), // timestamp - (int64_t)(dur*GST_SECOND), - trackAudio.audio.samplerate, - trackAudio.audio.channel_count ); + sourceIdAudio, + (int64_t)(pts*NS_SECOND), // timestamp + (int64_t)(dur*NS_SECOND), + trackAudio.audio.samplerate, + trackAudio.audio.channel_count ); size_t len = trackAudio.getLen(i); uint8_t *data = new uint8_t[len]; std::memcpy(data, trackAudio.getPtr(i),len); @@ -166,11 +178,11 @@ void InjectVideo( void ) double dur = trackVideo.getDuration(i); std::unique_ptr videoSegment = std::make_unique( - sourceIdVideo, - (int64_t)(pts*GST_SECOND), - (int64_t)(dur*GST_SECOND), - trackVideo.video.width, - trackVideo.video.height ); + sourceIdVideo, + (int64_t)(pts*NS_SECOND), + (int64_t)(dur*NS_SECOND), + trackVideo.video.width, + trackVideo.video.height ); size_t len = trackVideo.getLen(i); uint8_t *data = new uint8_t[len]; std::memcpy(data, trackVideo.getPtr(i),len); @@ -192,8 +204,6 @@ int my_main(int argc, char **argv) // assert( delim ); gUserPathLen = (int)(delim - gUserPathPtr); - gst_init(&argc, &argv); - gstMediaPipeline = new GstMediaPipeline(); gstMediaPipeline->play(); ConfigureAudio(); @@ -202,9 +212,8 @@ int my_main(int argc, char **argv) InjectAudio(); InjectVideo(); - GMainLoop *main_loop = g_main_loop_new(nullptr, FALSE); - g_main_loop_run(main_loop); - g_main_loop_unref(main_loop); + // Minimal sleep to allow any async Rialto operations; replace with real event loop if needed. + std::this_thread::sleep_for(std::chrono::seconds(2)); return 0; } diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index 09e06c331..88f108b78 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -1,168 +1,104 @@ + #include "rialto-gst-pipeline.h" -#include #include #include -static const int32_t TRACK_VIDEO = 0; -static const int32_t TRACK_AUDIO = 1; - -static void found_video_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ) +GstMediaPipeline::GstMediaPipeline() { - printf( "found_video_source_cb\n" ); - gstMediaPipeline->found_source(orig,pspec,TRACK_VIDEO); + printf("constructing GstMediaPipeline (Rialto-backed)\n"); + if (!gst_is_initialized()) + { + int argc = 0; char **argv = nullptr; gst_init(&argc, &argv); + } + m_messageQueueFactory = IMessageQueueFactory::createFactory(); + m_clientBackend = std::make_shared(); + const uint32_t maxW = DEFAULT_MAX_VIDEO_WIDTH; + const uint32_t maxH = DEFAULT_MAX_VIDEO_HEIGHT; + m_mseClient = std::make_shared(m_messageQueueFactory, m_clientBackend, maxW, maxH); + if (!m_mseClient->createBackend()) + { + fprintf(stderr, "Failed to create Rialto media pipeline backend\n"); + } } -static void found_audio_source_cb( GObject * object, GObject * orig, GParamSpec * pspec, class GstMediaPipeline *gstMediaPipeline ) +GstMediaPipeline::~GstMediaPipeline() { - printf( "found_audio_source_cb\n" ); - gstMediaPipeline->found_source(orig,pspec,TRACK_AUDIO); + printf("destructing GstMediaPipeline (Rialto-backed)\n"); + if (m_clientBackend) + { + m_clientBackend->stop(); + } + m_mseClient.reset(); + m_clientBackend.reset(); + m_messageQueueFactory.reset(); } -void GstMediaPipeline::found_source( GObject *orig, GParamSpec *pspec, int sourceId ) +bool GstMediaPipeline::play() { - g_object_get( orig, pspec->name, &track[sourceId].appsrc, NULL ); + printf("play (Rialto backend)\n"); + if (!m_clientBackend) + { + fprintf(stderr, "play(): backend not created\n"); + return false; + } + return m_clientBackend->play(); } -bool GstMediaPipeline::attachSource(const std::unique_ptr &source, int32_t &sourceId ){ - MediaSourceType sourceType = source->getType(); - GstCaps * caps = gst_caps_new_empty_simple( source->getMimeType().c_str() ); - - if( sourceType == MediaSourceType::VIDEO || sourceType == MediaSourceType::AUDIO ) - { - const IMediaPipeline::MediaSourceAV *mediaSourceAV = dynamic_cast(source.get()); - if( mediaSourceAV ) - { - const char *streamFormat = nullptr; - switch( mediaSourceAV->getStreamFormat() ) - { - case StreamFormat::HVC1: - streamFormat = "hvc1"; - break; - case StreamFormat::AVC: - streamFormat = "avc"; - break; - case StreamFormat::RAW: - streamFormat = "raw"; - break; - default: - break; - } - if( streamFormat ) - { - gst_caps_set_simple( caps, "stream-format", G_TYPE_STRING, streamFormat, nullptr ); - } - const std::shared_ptr codecData = mediaSourceAV->getCodecData(); - GstBuffer *buf = nullptr; - if( codecData ) - { - buf = gst_buffer_new_and_alloc(codecData->data.size()); - gst_buffer_fill(buf, 0, codecData->data.data(), codecData->data.size() ); - gst_caps_set_simple( caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr ); - } - - if( sourceType == MediaSourceType::VIDEO ) - { - sourceId = TRACK_VIDEO; - const IMediaPipeline::MediaSourceVideo *mediaSourceVideo = dynamic_cast(source.get()); - if( mediaSourceVideo ) - { - gst_caps_set_simple( caps, - "alignment", G_TYPE_STRING, "au", - "width", G_TYPE_INT, mediaSourceVideo->getWidth(), - "height", G_TYPE_INT, mediaSourceVideo->getHeight(), - "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, - nullptr); - } - } - else if( sourceType == MediaSourceType::AUDIO ) - { - sourceId = TRACK_AUDIO; - const IMediaPipeline::MediaSourceAudio *mediaSourceAudio = dynamic_cast(source.get()); - if( mediaSourceAudio ) - { - const auto &audioConfig = mediaSourceAudio->getAudioConfig(); - gst_caps_set_simple( caps, - "framed", G_TYPE_BOOLEAN, TRUE, - "rate", G_TYPE_INT, audioConfig.sampleRate, - "channels", G_TYPE_INT, audioConfig.numberOfChannels, - nullptr ); - } - } - else - { - assert(0); - } - - gchar *caps_string = gst_caps_to_string(caps); - g_print("Negotiated caps: %s\n", caps_string); - g_free(caps_string); - - gst_app_src_set_caps(GST_APP_SRC(track[sourceId].appsrc), caps); - gst_caps_unref(caps); - if( buf ) - { - gst_buffer_unref(buf); - } - } - printf( "attachSource() -> sourceId=%" PRId32 "\n", sourceId ); - } - return true; -}; - -bool GstMediaPipeline::removeSource(int32_t id){ - printf( "removeSource(sourceId=%" PRId32 ")\n", id ); - return false; -}; - -bool GstMediaPipeline::allSourcesAttached(){ - return true; -}; - -bool GstMediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url){ return true; } - -bool GstMediaPipeline::play(){ - printf( "play\n" ); - gst_element_set_state( pipeline, GST_STATE_PLAYING ); - return true; -}; +bool GstMediaPipeline::removeSource(int32_t id) +{ + if (!m_clientBackend) return false; + return m_clientBackend->removeSource(id); +} -AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) +bool GstMediaPipeline::allSourcesAttached() { - GstBuffer *gstBuffer = gst_buffer_new_wrapped( - (gpointer)mediaSegment->getData(), - (gsize)mediaSegment->getDataLength() ); - GST_BUFFER_PTS(gstBuffer) = (GstClockTime)(mediaSegment->getTimeStamp()); - GST_BUFFER_DURATION(gstBuffer) = (GstClockTime)(mediaSegment->getDuration()); - gst_app_src_push_buffer(GST_APP_SRC(track[mediaSegment->getId()].appsrc), gstBuffer ); - return AddSegmentStatus::OK; + if (!m_clientBackend) return false; + return m_clientBackend->allSourcesAttached(); } -GstMediaPipeline::GstMediaPipeline() +bool GstMediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url) +{ + if (!m_clientBackend) return false; + return m_clientBackend->load(type, mimeType, url); +} + +AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) { - printf( "constructing GstMediaPipeline\n" ); - pipeline = gst_pipeline_new( "rialtoTest" ); - for( int i=0; i<2; i++ ) - { - printf( "creating playbin for track#%d\n", i ); - GstElement *playbin = gst_element_factory_make("playbin", nullptr); - track[i].playbin = playbin; - track[i].appsrc = nullptr; - gboolean rc = gst_bin_add(GST_BIN(pipeline), playbin ); - assert( rc ); - g_object_set( playbin, "uri", "appsrc://", nullptr ); - switch( i ) - { - case TRACK_VIDEO: - g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_video_source_cb), this ); - break; - case TRACK_AUDIO: - g_signal_connect( playbin, "deep-notify::source", G_CALLBACK(found_audio_source_cb), this ); - break; - } - } + if (!m_clientBackend) + { + return AddSegmentStatus::ERROR; + } + return m_clientBackend->addSegment(needDataRequestId, mediaSegment); } -GstMediaPipeline::~GstMediaPipeline() +bool GstMediaPipeline::attachSource(const std::unique_ptr &source) { - printf( "destructing GstMediaPipeline\n" ); + if (!m_clientBackend) + { + fprintf(stderr, "attachSource(): backend not ready\n"); + return false; + } + if (!source) + { + fprintf(stderr, "attachSource(): null source\n"); + return false; + } + // Create a copy we can hand to backend (it may mutate id inside copy) + std::unique_ptr temp = source->copy(); + if (!temp) + { + fprintf(stderr, "attachSource(): copy failed\n"); + return false; + } + bool ok = m_clientBackend->attachSource(temp); + if (!ok) + { + fprintf(stderr, "attachSource(): backend attach failed\n"); + return false; + } + // Propagate assigned id back to original + const int32_t assignedId = temp->getId(); + const_cast(source.get())->setId(assignedId); + printf("attachSource() -> sourceId=%d (Rialto backend)\n", assignedId); + return true; } diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h index 30a498351..8bfa9705e 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.h +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -2,6 +2,10 @@ #define GST_MEDIA_PIPELINE_H #include "IMediaPipeline.h" +// Rialto gstreamer client side helpers +#include "GStreamerMSEMediaPlayerClient.h" +#include "MediaPlayerClientBackend.h" +#include "IMessageQueue.h" #include using namespace firebolt::rialto; @@ -9,22 +13,20 @@ using namespace firebolt::rialto; class GstMediaPipeline:IMediaPipeline { private: - GstElement *pipeline; - - struct - { - GstElement *playbin; - GstElement *appsrc; - } track[2]; + // New Rialto-backed objects replacing manual playbin/appsrc construction + std::shared_ptr m_messageQueueFactory; // creates async queues used by client + std::shared_ptr m_clientBackend; // thin wrapper over IMediaPipeline + std::shared_ptr m_mseClient; // implements IMediaPipelineClient callbacks protected: - std::weak_ptr client; - std::weak_ptr getClient(){ return client; } - + std::weak_ptr client; // legacy handle if external code sets it + std::weak_ptr getClient(){ return client; } + public: - void found_source( GObject *orig, GParamSpec *pspec, int sourceId ); - GstMediaPipeline(); - ~GstMediaPipeline(); + // Legacy helper retained for compatibility (now unused) + void found_source( GObject *orig, GParamSpec *pspec, int sourceId ){}; + GstMediaPipeline(); + ~GstMediaPipeline(); bool pause(){ return false; }; bool stop(){ return false; }; @@ -36,7 +38,6 @@ class GstMediaPipeline:IMediaPipeline bool getImmediateOutput(int32_t sourceId, bool &immediateOutput){ return false; }; bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height){ return false; }; bool haveData(MediaSourceStatus status, uint32_t needDataRequestId){ return false; }; - bool attachSource(const std::unique_ptr &source){ return true; } bool renderFrame(){ return false; }; bool setVolume(double targetVolume, uint32_t volumeDuration = 0, EaseType easeType = EaseType::EASE_LINEAR){ return false; }; bool getTextTrackIdentifier(std::string &textTrackIdentifier){ return false; }; @@ -48,6 +49,7 @@ class GstMediaPipeline:IMediaPipeline bool getStreamSyncMode(int32_t &streamSyncMode){ return false; }; bool flush(int32_t sourceId, bool resetTime, bool &async){ return false; }; bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, uint64_t stopPosition = kUndefinedPosition){ return false; }; + bool setSubtitleOffset(int32_t sourceId, int64_t position){ return false; }; bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac){ return false; }; bool setBufferingLimit(uint32_t limitBufferingMs){ return false; }; bool getBufferingLimit(uint32_t &limitBufferingMs){ return false; }; @@ -59,7 +61,8 @@ class GstMediaPipeline:IMediaPipeline bool getMute(int32_t sourceId, bool &mute){ return false; } bool setTextTrackIdentifier(const std::string &textTrackIdentifier){ return false; } - bool attachSource(const std::unique_ptr &source, int32_t &sourceId ); + // Rialto native pattern: attach source; after true, caller reads source->getId() + bool attachSource(const std::unique_ptr &source); bool removeSource(int32_t id); bool allSourcesAttached(); bool load(MediaType type, const std::string &mimeType, const std::string &url); From 2bf4e90697d373b7760589949c73342c6d3f71ca Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Tue, 11 Nov 2025 16:40:33 -0500 Subject: [PATCH 08/21] TEST - DO NOT MERGE Signed-off-by: ryadav698 --- CMakeLists.txt | 32 +- .../rialto-client/common/CMakeLists.txt | 58 + .../common/include/EventThread.h | 68 + .../rialto-client/common/include/Timer.h | 72 + .../common/interface/IEventThread.h | 104 + .../rialto-client/common/interface/ITimer.h | 93 + .../common/interface/LinuxUtils.h | 31 + .../common/interface/RialtoCommonLogging.h | 44 + .../common/public/CMakeLists.txt | 51 + .../public/include/SessionServerCommon.in | 112 + .../common/source/EventThread.cpp | 122 + .../common/source/LinuxUtils.cpp | 107 + .../rialto-client/common/source/Timer.cpp | 96 + middleware/rialto-client/ipc/CMakeLists.txt | 54 + middleware/rialto-client/ipc/README.md | 52 + .../rialto-client/ipc/client/CMakeLists.txt | 56 + .../ipc/client/include/IBlockingClosure.h | 82 + .../ipc/client/include/IIpcChannel.h | 170 ++ .../client/include/IIpcControllerFactory.h | 52 + .../ipc/client/source/BlockingClosure.cpp | 113 + .../ipc/client/source/BlockingClosure.h | 68 + .../ipc/client/source/IpcChannelImpl.cpp | 1207 +++++++++ .../ipc/client/source/IpcChannelImpl.h | 147 ++ .../client/source/IpcClientControllerImpl.cpp | 146 ++ .../client/source/IpcClientControllerImpl.h | 130 + .../ipc/client/source/IpcControllerFactory.h | 41 + .../rialto-client/ipc/common/CMakeLists.txt | 59 + .../ipc/common/include/INamedSocket.h | 52 + .../common/proto/rialtoipc-transport.proto | 1 + .../ipc/common/proto/rialtoipc.proto | 1 + .../ipc/common/source/FileDescriptor.cpp | 126 + .../ipc/common/source/FileDescriptor.h | 66 + .../ipc/common/source/IpcLogging.h | 44 + .../ipc/common/source/NamedSocket.cpp | 313 +++ .../ipc/common/source/NamedSocket.h | 63 + .../ipc/common/source/SimpleBufferPool.cpp | 106 + .../ipc/common/source/SimpleBufferPool.h | 66 + .../rialto-client/ipc/examples/CMakeLists.txt | 113 + .../ipc/examples/ExampleClient.cpp | 194 ++ .../ipc/examples/ExampleServer.cpp | 124 + .../ipc/examples/ExampleSocketPair.cpp | 198 ++ .../rialto-client/ipc/examples/example.proto | 74 + .../rialto-client/ipc/server/CMakeLists.txt | 59 + .../ipc/server/include/IIpcController.h | 132 + .../ipc/server/include/IIpcServer.h | 231 ++ .../ipc/server/include/IIpcServerFactory.h | 52 + .../ipc/server/source/IpcClientImpl.cpp | 79 + .../ipc/server/source/IpcClientImpl.h | 68 + .../server/source/IpcServerControllerImpl.cpp | 56 + .../server/source/IpcServerControllerImpl.h | 84 + .../ipc/server/source/IpcServerImpl.cpp | 1417 ++++++++++ .../ipc/server/source/IpcServerImpl.h | 159 ++ .../rialto-client/logging/CMakeLists.txt | 53 + .../logging/include/RialtoLogging.h | 235 ++ .../logging/source/EnvVariableParser.cpp | 223 ++ .../logging/source/EnvVariableParser.h | 57 + .../logging/source/LogFileHandle.cpp | 60 + .../logging/source/LogFileHandle.h | 46 + .../logging/source/RialtoLogging.cpp | 413 +++ middleware/rialto-client/media/CMakeLists.txt | 31 + .../rialto-client/media/client/CMakeLists.txt | 22 + .../media/client/common/CMakeLists.txt | 35 + .../common/include/RialtoClientLogging.h | 44 + .../media/client/ipc/CMakeLists.txt | 70 + .../media/client/ipc/include/ControlIpc.h | 118 + .../client/ipc/include/IConnectionObserver.h | 35 + .../media/client/ipc/include/IIpcClient.h | 120 + .../media/client/ipc/include/IpcClient.h | 117 + .../media/client/ipc/include/IpcModule.h | 125 + .../ipc/include/MediaKeysCapabilitiesIpc.h | 96 + .../media/client/ipc/include/MediaKeysIpc.h | 183 ++ .../include/MediaPipelineCapabilitiesIpc.h | 117 + .../client/ipc/include/MediaPipelineIpc.h | 300 +++ .../client/ipc/include/RialtoCommonIpc.h | 31 + .../client/ipc/include/WebAudioPlayerIpc.h | 119 + .../media/client/ipc/interface/IControlIpc.h | 93 + .../IMediaKeysCapabilitiesIpcFactory.h | 62 + .../ipc/interface/IMediaKeysIpcFactory.h | 68 + .../IMediaPipelineCapabilitiesIpcFactory.h | 62 + .../client/ipc/interface/IMediaPipelineIpc.h | 458 ++++ .../ipc/interface/IMediaPipelineIpcClient.h | 121 + .../client/ipc/interface/IWebAudioPlayerIpc.h | 170 ++ .../ipc/interface/IWebAudioPlayerIpcClient.h | 58 + .../client/ipc/proto/controlmodule.proto | 1 + .../proto/mediakeyscapabilitiesmodule.proto | 1 + .../client/ipc/proto/mediakeysmodule.proto | 1 + .../mediapipelinecapabilitiesmodule.proto | 1 + .../ipc/proto/mediapipelinemodule.proto | 1 + .../media/client/ipc/proto/rialtocommon.proto | 1 + .../ipc/proto/webaudioplayermodule.proto | 1 + .../media/client/ipc/source/ControlIpc.cpp | 265 ++ .../media/client/ipc/source/IpcClient.cpp | 219 ++ .../media/client/ipc/source/IpcModule.cpp | 136 + .../ipc/source/MediaKeysCapabilitiesIpc.cpp | 216 ++ .../media/client/ipc/source/MediaKeysIpc.cpp | 936 +++++++ .../source/MediaPipelineCapabilitiesIpc.cpp | 208 ++ .../client/ipc/source/MediaPipelineIpc.cpp | 1910 ++++++++++++++ .../client/ipc/source/RialtoCommonIpc.cpp | 44 + .../client/ipc/source/WebAudioPlayerIpc.cpp | 513 ++++ .../media/client/main/CMakeLists.txt | 95 + .../client/main/include/AttachedSources.h | 58 + .../client/main/include/ClientController.h | 116 + .../client/main/include/ClientLogControl.h | 87 + .../media/client/main/include/Control.h | 86 + .../client/main/include/IClientController.h | 110 + .../client/main/include/ISharedMemoryHandle.h | 41 + .../media/client/main/include/KeyIdMap.h | 53 + .../media/client/main/include/MediaKeys.h | 132 + .../main/include/MediaKeysCapabilities.h | 93 + .../media/client/main/include/MediaPipeline.h | 336 +++ .../main/include/MediaPipelineCapabilities.h | 116 + .../client/main/include/MediaPipelineProxy.h | 186 ++ .../client/main/include/SharedMemoryHandle.h | 53 + .../client/main/include/WebAudioPlayer.h | 165 ++ .../client/main/include/WebAudioPlayerProxy.h | 75 + .../client/main/source/AttachedSources.cpp | 68 + .../client/main/source/ClientController.cpp | 281 ++ .../client/main/source/ClientLogControl.cpp | 143 ++ .../media/client/main/source/Control.cpp | 86 + .../media/client/main/source/KeyIdMap.cpp | 64 + .../media/client/main/source/MediaKeys.cpp | 244 ++ .../main/source/MediaKeysCapabilities.cpp | 123 + .../client/main/source/MediaPipeline.cpp | 901 +++++++ .../main/source/MediaPipelineCapabilities.cpp | 111 + .../client/main/source/SharedMemoryHandle.cpp | 76 + .../client/main/source/WebAudioPlayer.cpp | 280 ++ .../rialto-client/media/common/CMakeLists.txt | 77 + .../media/common/include/ByteWriter.h | 102 + .../common/include/MediaFrameWriterFactory.h | 44 + .../media/common/include/MediaFrameWriterV1.h | 147 ++ .../media/common/include/MediaFrameWriterV2.h | 111 + .../common/interface/IMediaFrameWriter.h | 99 + .../media/common/interface/SchemaVersion.h | 51 + .../media/common/interface/ShmCommon.h | 43 + .../media/common/interface/TypeConverters.h | 32 + .../media/common/proto/metadata.proto | 1 + .../media/common/source/ByteWriter.cpp | 76 + .../common/source/MediaFrameWriterFactory.cpp | 83 + .../common/source/MediaFrameWriterV1.cpp | 157 ++ .../common/source/MediaFrameWriterV2.cpp | 215 ++ .../media/common/source/SchemaVersion.cpp | 71 + .../media/common/source/TypeConverters.cpp | 91 + .../rialto-client/media/public/CMakeLists.txt | 58 + .../media/public/include/ControlCommon.h | 46 + .../media/public/include/IClientLogControl.h | 103 + .../media/public/include/IClientLogHandler.h | 84 + .../media/public/include/IControl.h | 99 + .../media/public/include/IControlClient.h | 61 + .../media/public/include/IMediaKeys.h | 306 +++ .../public/include/IMediaKeysCapabilities.h | 122 + .../media/public/include/IMediaKeysClient.h | 83 + .../media/public/include/IMediaPipeline.h | 1542 +++++++++++ .../include/IMediaPipelineCapabilities.h | 123 + .../public/include/IMediaPipelineClient.h | 222 ++ .../media/public/include/IWebAudioPlayer.h | 216 ++ .../public/include/IWebAudioPlayerClient.h | 68 + .../media/public/include/MediaCommon.h | 470 ++++ .../rialto-client/media/server/CMakeLists.txt | 77 + .../media/server/common/CMakeLists.txt | 35 + .../common/include/RialtoServerLogging.h | 44 + .../media/server/gstplayer/CMakeLists.txt | 147 ++ .../server/gstplayer/include/CapsBuilder.h | 99 + .../server/gstplayer/include/FlushWatcher.h | 45 + .../gstplayer/include/GenericPlayerContext.h | 271 ++ .../gstplayer/include/GstCapabilities.h | 167 ++ .../include/GstDecryptorElementFactory.h | 44 + .../gstplayer/include/GstDecryptorPrivate.h | 107 + .../gstplayer/include/GstDispatcherThread.h | 78 + .../gstplayer/include/GstGenericPlayer.h | 425 +++ .../server/gstplayer/include/GstInitialiser.h | 50 + .../gstplayer/include/GstLogForwarding.h | 28 + .../server/gstplayer/include/GstMimeMapping.h | 123 + .../gstplayer/include/GstProtectionMetadata.h | 58 + .../include/GstProtectionMetadataHelper.h | 49 + .../GstProtectionMetadataHelperFactory.h | 43 + .../include/GstRialtoTextTrackSinkPrivate.h | 47 + .../media/server/gstplayer/include/GstSrc.h | 162 ++ .../include/GstTextTrackSinkFactory.h | 42 + .../gstplayer/include/GstWebAudioPlayer.h | 190 ++ .../server/gstplayer/include/IFlushWatcher.h | 38 + .../include/IGstDecryptorElementFactory.h | 61 + .../gstplayer/include/IGstDispatcherThread.h | 55 + .../include/IGstDispatcherThreadClient.h | 47 + .../include/IGstGenericPlayerPrivate.h | 323 +++ .../include/IGstProtectionMetadataHelper.h | 38 + .../IGstProtectionMetadataHelperFactory.h | 58 + .../media/server/gstplayer/include/IGstSrc.h | 123 + .../include/IGstTextTrackSinkFactory.h | 56 + .../include/IGstWebAudioPlayerPrivate.h | 54 + .../server/gstplayer/include/IWorkerThread.h | 66 + .../gstplayer/include/NeedDataMapping.h | 48 + .../media/server/gstplayer/include/Utils.h | 48 + .../gstplayer/include/WebAudioPlayerContext.h | 81 + .../server/gstplayer/include/WorkerThread.h | 91 + .../include/tasks/IGenericPlayerTaskFactory.h | 550 ++++ .../gstplayer/include/tasks/IPlayerTask.h | 39 + .../tasks/IWebAudioPlayerTaskFactory.h | 148 ++ .../include/tasks/generic/AttachSamples.h | 72 + .../include/tasks/generic/AttachSource.h | 61 + .../tasks/generic/CheckAudioUnderflow.h | 48 + .../include/tasks/generic/DeepElementAdded.h | 56 + .../include/tasks/generic/EnoughData.h | 46 + .../gstplayer/include/tasks/generic/Eos.h | 49 + .../include/tasks/generic/FinishSetupSource.h | 44 + .../gstplayer/include/tasks/generic/Flush.h | 51 + .../tasks/generic/GenericPlayerTaskFactory.h | 145 ++ .../include/tasks/generic/HandleBusMessage.h | 60 + .../include/tasks/generic/NeedData.h | 47 + .../gstplayer/include/tasks/generic/Pause.h | 42 + .../gstplayer/include/tasks/generic/Ping.h | 41 + .../gstplayer/include/tasks/generic/Play.h | 40 + .../include/tasks/generic/ProcessAudioGap.h | 56 + .../generic/ReadShmDataAndAttachSamples.h | 50 + .../include/tasks/generic/RemoveSource.h | 49 + .../include/tasks/generic/RenderFrame.h | 42 + .../include/tasks/generic/ReportPosition.h | 49 + .../include/tasks/generic/SetBufferingLimit.h | 45 + .../tasks/generic/SetImmediateOutput.h | 49 + .../include/tasks/generic/SetLowLatency.h | 43 + .../gstplayer/include/tasks/generic/SetMute.h | 52 + .../include/tasks/generic/SetPlaybackRate.h | 47 + .../include/tasks/generic/SetPosition.h | 50 + .../include/tasks/generic/SetSourcePosition.h | 58 + .../include/tasks/generic/SetStreamSyncMode.h | 45 + .../include/tasks/generic/SetSubtitleOffset.h | 47 + .../gstplayer/include/tasks/generic/SetSync.h | 45 + .../include/tasks/generic/SetSyncOff.h | 43 + .../tasks/generic/SetTextTrackIdentifier.h | 48 + .../include/tasks/generic/SetUseBuffering.h | 44 + .../include/tasks/generic/SetVideoGeometry.h | 43 + .../include/tasks/generic/SetVolume.h | 55 + .../include/tasks/generic/SetupElement.h | 51 + .../include/tasks/generic/SetupSource.h | 44 + .../include/tasks/generic/Shutdown.h | 45 + .../gstplayer/include/tasks/generic/Stop.h | 42 + .../include/tasks/generic/SwitchSource.h | 49 + .../tasks/generic/SynchroniseSubtitleClock.h | 50 + .../include/tasks/generic/Underflow.h | 48 + .../tasks/generic/UpdatePlaybackGroup.h | 53 + .../gstplayer/include/tasks/webAudio/Eos.h | 45 + .../include/tasks/webAudio/HandleBusMessage.h | 53 + .../gstplayer/include/tasks/webAudio/Pause.h | 42 + .../gstplayer/include/tasks/webAudio/Ping.h | 41 + .../gstplayer/include/tasks/webAudio/Play.h | 42 + .../include/tasks/webAudio/SetCaps.h | 53 + .../include/tasks/webAudio/SetVolume.h | 45 + .../include/tasks/webAudio/Shutdown.h | 45 + .../gstplayer/include/tasks/webAudio/Stop.h | 40 + .../webAudio/WebAudioPlayerTaskFactory.h | 61 + .../include/tasks/webAudio/WriteBuffer.h | 50 + .../gstplayer/interface/IGstCapabilities.h | 105 + .../gstplayer/interface/IGstGenericPlayer.h | 460 ++++ .../interface/IGstGenericPlayerClient.h | 175 ++ .../gstplayer/interface/IGstInitialiser.h | 42 + .../gstplayer/interface/IGstWebAudioPlayer.h | 154 ++ .../interface/IGstWebAudioPlayerClient.h | 70 + .../server/gstplayer/source/CapsBuilder.cpp | 262 ++ .../server/gstplayer/source/FlushWatcher.cpp | 52 + .../gstplayer/source/GstCapabilities.cpp | 464 ++++ .../server/gstplayer/source/GstDecryptor.cpp | 372 +++ .../gstplayer/source/GstDispatcherThread.cpp | 124 + .../gstplayer/source/GstGenericPlayer.cpp | 2270 +++++++++++++++++ .../gstplayer/source/GstInitialiser.cpp | 93 + .../gstplayer/source/GstLogForwarding.cpp | 117 + .../source/GstProtectionMetadata.cpp | 92 + .../source/GstProtectionMetadataHelper.cpp | 77 + .../media/server/gstplayer/source/GstSrc.cpp | 531 ++++ .../gstplayer/source/GstTextTrackSink.cpp | 585 +++++ .../gstplayer/source/GstWebAudioPlayer.cpp | 473 ++++ .../gstplayer/source/NeedDataMapping.cpp | 41 + .../media/server/gstplayer/source/Utils.cpp | 183 ++ .../server/gstplayer/source/WorkerThread.cpp | 125 + .../source/tasks/generic/AttachSamples.cpp | 135 + .../source/tasks/generic/AttachSource.cpp | 131 + .../tasks/generic/CheckAudioUnderflow.cpp | 65 + .../source/tasks/generic/DeepElementAdded.cpp | 112 + .../source/tasks/generic/EnoughData.cpp | 51 + .../gstplayer/source/tasks/generic/Eos.cpp | 77 + .../tasks/generic/FinishSetupSource.cpp | 127 + .../gstplayer/source/tasks/generic/Flush.cpp | 110 + .../generic/GenericPlayerTaskFactory.cpp | 363 +++ .../source/tasks/generic/HandleBusMessage.cpp | 295 +++ .../source/tasks/generic/NeedData.cpp | 73 + .../gstplayer/source/tasks/generic/Pause.cpp | 44 + .../gstplayer/source/tasks/generic/Ping.cpp | 40 + .../gstplayer/source/tasks/generic/Play.cpp | 42 + .../source/tasks/generic/ProcessAudioGap.cpp | 53 + .../generic/ReadShmDataAndAttachSamples.cpp | 125 + .../source/tasks/generic/RemoveSource.cpp | 82 + .../source/tasks/generic/RenderFrame.cpp | 46 + .../source/tasks/generic/ReportPosition.cpp | 50 + .../tasks/generic/SetBufferingLimit.cpp | 47 + .../tasks/generic/SetImmediateOutput.cpp | 56 + .../source/tasks/generic/SetLowLatency.cpp | 46 + .../source/tasks/generic/SetMute.cpp | 77 + .../source/tasks/generic/SetPlaybackRate.cpp | 105 + .../source/tasks/generic/SetPosition.cpp | 106 + .../tasks/generic/SetSourcePosition.cpp | 104 + .../tasks/generic/SetStreamSyncMode.cpp | 47 + .../tasks/generic/SetSubtitleOffset.cpp | 53 + .../source/tasks/generic/SetSync.cpp | 44 + .../source/tasks/generic/SetSyncOff.cpp | 46 + .../tasks/generic/SetTextTrackIdentifier.cpp | 51 + .../source/tasks/generic/SetUseBuffering.cpp | 47 + .../source/tasks/generic/SetVideoGeometry.cpp | 47 + .../source/tasks/generic/SetVolume.cpp | 122 + .../source/tasks/generic/SetupElement.cpp | 325 +++ .../source/tasks/generic/SetupSource.cpp | 49 + .../source/tasks/generic/Shutdown.cpp | 41 + .../gstplayer/source/tasks/generic/Stop.cpp | 48 + .../source/tasks/generic/SwitchSource.cpp | 48 + .../generic/SynchroniseSubtitleClock.cpp | 91 + .../source/tasks/generic/Underflow.cpp | 65 + .../tasks/generic/UpdatePlaybackGroup.cpp | 79 + .../gstplayer/source/tasks/webAudio/Eos.cpp | 47 + .../tasks/webAudio/HandleBusMessage.cpp | 139 + .../gstplayer/source/tasks/webAudio/Pause.cpp | 46 + .../gstplayer/source/tasks/webAudio/Ping.cpp | 40 + .../gstplayer/source/tasks/webAudio/Play.cpp | 46 + .../source/tasks/webAudio/SetCaps.cpp | 190 ++ .../source/tasks/webAudio/SetVolume.cpp | 44 + .../source/tasks/webAudio/Shutdown.cpp | 41 + .../gstplayer/source/tasks/webAudio/Stop.cpp | 43 + .../webAudio/WebAudioPlayerTaskFactory.cpp | 97 + .../source/tasks/webAudio/WriteBuffer.cpp | 108 + .../media/server/ipc/CMakeLists.txt | 82 + .../media/server/ipc/include/AckSender.h | 42 + .../ipc/include/ApplicationManagementServer.h | 62 + .../ipc/include/ControlClientServerInternal.h | 45 + .../server/ipc/include/ControlModuleService.h | 69 + .../ipc/include/IControlModuleService.h | 90 + .../IMediaKeysCapabilitiesModuleService.h | 91 + .../ipc/include/IMediaKeysModuleService.h | 90 + .../IMediaPipelineCapabilitiesModuleService.h | 91 + .../ipc/include/IMediaPipelineModuleService.h | 89 + .../IServerManagerModuleServiceFactory.h | 56 + .../include/IWebAudioPlayerModuleService.h | 89 + .../MediaKeysCapabilitiesModuleService.h | 71 + .../server/ipc/include/MediaKeysClient.h | 48 + .../ipc/include/MediaKeysModuleService.h | 126 + .../MediaPipelineCapabilitiesModuleService.h | 71 + .../server/ipc/include/MediaPipelineClient.h | 62 + .../ipc/include/MediaPipelineModuleService.h | 169 ++ .../server/ipc/include/RialtoCommonModule.h | 31 + .../ipc/include/ServerManagerModuleService.h | 60 + .../ipc/include/SessionManagementServer.h | 89 + .../server/ipc/include/SetLogLevelsService.h | 53 + .../server/ipc/include/WebAudioPlayerClient.h | 43 + .../ipc/include/WebAudioPlayerModuleService.h | 94 + .../interface/IApplicationManagementServer.h | 46 + .../media/server/ipc/interface/IIpcFactory.h | 47 + .../ipc/interface/ISessionManagementServer.h | 50 + .../media/server/ipc/interface/IpcFactory.h | 46 + .../server/ipc/proto/controlmodule.proto | 1 + .../proto/mediakeyscapabilitiesmodule.proto | 1 + .../server/ipc/proto/mediakeysmodule.proto | 1 + .../mediapipelinecapabilitiesmodule.proto | 1 + .../ipc/proto/mediapipelinemodule.proto | 1 + .../media/server/ipc/proto/rialtocommon.proto | 1 + .../ipc/proto/servermanagermodule.proto | 1 + .../ipc/proto/webaudioplayermodule.proto | 1 + .../media/server/ipc/source/AckSender.cpp | 38 + .../source/ApplicationManagementServer.cpp | 122 + .../source/ControlClientServerInternal.cpp | 73 + .../ipc/source/ControlModuleService.cpp | 192 ++ .../media/server/ipc/source/IpcFactory.cpp | 57 + .../MediaKeysCapabilitiesModuleService.cpp | 171 ++ .../server/ipc/source/MediaKeysClient.cpp | 120 + .../ipc/source/MediaKeysModuleService.cpp | 498 ++++ ...MediaPipelineCapabilitiesModuleService.cpp | 183 ++ .../server/ipc/source/MediaPipelineClient.cpp | 265 ++ .../ipc/source/MediaPipelineModuleService.cpp | 1082 ++++++++ .../server/ipc/source/RialtoCommonModule.cpp | 48 + .../ipc/source/ServerManagerModuleService.cpp | 171 ++ .../ipc/source/SessionManagementServer.cpp | 187 ++ .../server/ipc/source/SetLogLevelsService.cpp | 52 + .../ipc/source/WebAudioPlayerClient.cpp | 82 + .../source/WebAudioPlayerModuleService.cpp | 346 +++ .../media/server/main/CMakeLists.txt | 97 + .../server/main/include/ActiveRequests.h | 85 + .../main/include/ControlServerInternal.h | 63 + .../server/main/include/DataReaderFactory.h | 38 + .../media/server/main/include/DataReaderV1.h | 88 + .../media/server/main/include/DataReaderV2.h | 46 + .../server/main/include/HeartbeatProcedure.h | 70 + .../server/main/include/IActiveRequests.h | 52 + .../server/main/include/IDataReaderFactory.h | 45 + .../server/main/include/IMediaKeySession.h | 192 ++ .../main/include/INeedMediaDataThread.h | 41 + .../server/main/include/ITextTrackAccessor.h | 70 + .../media/server/main/include/MainThread.h | 141 + .../server/main/include/MediaKeySession.h | 218 ++ .../main/include/MediaKeysCapabilities.h | 90 + .../server/main/include/MediaKeysCommon.h | 49 + .../main/include/MediaKeysServerInternal.h | 312 +++ .../main/include/MediaPipelineCapabilities.h | 85 + .../include/MediaPipelineServerInternal.h | 720 ++++++ .../media/server/main/include/NeedMediaData.h | 54 + .../server/main/include/SharedMemoryBuffer.h | 87 + .../media/server/main/include/ShmUtils.h | 42 + .../server/main/include/TextTrackAccessor.h | 70 + .../server/main/include/TextTrackSession.h | 62 + .../include/WebAudioPlayerServerInternal.h | 257 ++ .../media/server/main/interface/IAckSender.h | 33 + .../interface/IControlClientServerInternal.h | 64 + .../main/interface/IControlServerInternal.h | 95 + .../media/server/main/interface/IDataReader.h | 35 + .../main/interface/IDecryptionService.h | 42 + .../server/main/interface/IHeartbeatHandler.h | 51 + .../main/interface/IHeartbeatProcedure.h | 57 + .../media/server/main/interface/IMainThread.h | 117 + .../main/interface/IMediaKeysServerInternal.h | 136 + .../interface/IMediaPipelineServerInternal.h | 112 + .../main/interface/ISharedMemoryBuffer.h | 152 ++ .../server/main/interface/ITextTrackSession.h | 57 + .../interface/IWebAudioPlayerServerInternal.h | 104 + .../media/server/main/proto/metadata.proto | 1 + .../server/main/source/ActiveRequests.cpp | 126 + .../main/source/ControlServerInternal.cpp | 163 ++ .../server/main/source/DataReaderFactory.cpp | 56 + .../media/server/main/source/DataReaderV1.cpp | 68 + .../media/server/main/source/DataReaderV2.cpp | 240 ++ .../server/main/source/HeartbeatProcedure.cpp | 78 + .../media/server/main/source/MainThread.cpp | 190 ++ .../server/main/source/MediaKeySession.cpp | 489 ++++ .../main/source/MediaKeysCapabilities.cpp | 175 ++ .../main/source/MediaKeysServerInternal.cpp | 759 ++++++ .../main/source/MediaPipelineCapabilities.cpp | 102 + .../source/MediaPipelineServerInternal.cpp | 1620 ++++++++++++ .../server/main/source/NeedMediaData.cpp | 81 + .../server/main/source/SharedMemoryBuffer.cpp | 453 ++++ .../server/main/source/TextTrackAccessor.cpp | 310 +++ .../server/main/source/TextTrackSession.cpp | 165 ++ .../source/WebAudioPlayerServerInternal.cpp | 577 +++++ .../media/server/service/CMakeLists.txt | 59 + .../include/IApplicationSessionServer.h | 45 + .../server/service/include/ICdmService.h | 84 + .../server/service/include/IControlService.h | 50 + .../service/include/IMediaPipelineService.h | 97 + .../server/service/include/IPlaybackService.h | 63 + .../service/include/ISessionServerManager.h | 58 + .../service/include/IWebAudioPlayerService.h | 63 + .../source/ApplicationSessionServer.cpp | 43 + .../service/source/ApplicationSessionServer.h | 77 + .../server/service/source/CdmService.cpp | 561 ++++ .../media/server/service/source/CdmService.h | 95 + .../server/service/source/ControlService.cpp | 81 + .../server/service/source/ControlService.h | 51 + .../service/source/MediaPipelineService.cpp | 671 +++++ .../service/source/MediaPipelineService.h | 118 + .../server/service/source/PlaybackService.cpp | 155 ++ .../server/service/source/PlaybackService.h | 86 + .../service/source/SessionServerManager.cpp | 282 ++ .../service/source/SessionServerManager.h | 84 + .../service/source/WebAudioPlayerService.cpp | 254 ++ .../service/source/WebAudioPlayerService.h | 76 + .../media/server/service/source/main.cpp | 67 + .../rialto-ocdm/include/ActiveSessions.h | 2 +- middleware/rialto-ocdm/include/CdmBackend.h | 2 +- middleware/rialto-ocdm/include/ICdmBackend.h | 2 +- .../rialto-ocdm/include/IMessageDispatcher.h | 2 +- middleware/rialto-ocdm/include/Logger.h | 2 +- .../include/MediaKeysCapabilitiesBackend.h | 2 +- .../rialto-ocdm/include/MessageDispatcher.h | 2 +- .../rialto-ocdm/include/OpenCDMSession.h | 4 +- .../include/OpenCDMSessionPrivate.h | 2 +- .../rialto-ocdm/include/OpenCDMSystem.h | 2 +- .../include/OpenCDMSystemPrivate.h | 2 +- .../RialtoGStreamerEMEProtectionMetadata.h | 2 +- .../rialto-ocdm/source/ActiveSessions.cpp | 2 +- middleware/rialto-ocdm/source/CPPLINT.cfg | 2 +- middleware/rialto-ocdm/source/CdmBackend.cpp | 2 +- middleware/rialto-ocdm/source/Logger.cpp | 2 +- .../source/MediaKeysCapabilitiesBackend.cpp | 2 +- .../rialto-ocdm/source/MessageDispatcher.cpp | 2 +- .../source/OpenCDMSessionPrivate.cpp | 2 +- .../source/OpenCDMSystemPrivate.cpp | 2 +- .../RialtoGStreamerEMEProtectionMetadata.cpp | 2 +- middleware/rialto-ocdm/source/open_cdm.cpp | 2 +- .../rialto-ocdm/source/open_cdm_adapter.cpp | 2 +- .../rialto-ocdm/source/open_cdm_ext.cpp | 2 +- 481 files changed, 61734 insertions(+), 27 deletions(-) create mode 100644 middleware/rialto-client/common/CMakeLists.txt create mode 100644 middleware/rialto-client/common/include/EventThread.h create mode 100644 middleware/rialto-client/common/include/Timer.h create mode 100644 middleware/rialto-client/common/interface/IEventThread.h create mode 100644 middleware/rialto-client/common/interface/ITimer.h create mode 100644 middleware/rialto-client/common/interface/LinuxUtils.h create mode 100644 middleware/rialto-client/common/interface/RialtoCommonLogging.h create mode 100644 middleware/rialto-client/common/public/CMakeLists.txt create mode 100644 middleware/rialto-client/common/public/include/SessionServerCommon.in create mode 100644 middleware/rialto-client/common/source/EventThread.cpp create mode 100644 middleware/rialto-client/common/source/LinuxUtils.cpp create mode 100644 middleware/rialto-client/common/source/Timer.cpp create mode 100644 middleware/rialto-client/ipc/CMakeLists.txt create mode 100644 middleware/rialto-client/ipc/README.md create mode 100644 middleware/rialto-client/ipc/client/CMakeLists.txt create mode 100644 middleware/rialto-client/ipc/client/include/IBlockingClosure.h create mode 100644 middleware/rialto-client/ipc/client/include/IIpcChannel.h create mode 100644 middleware/rialto-client/ipc/client/include/IIpcControllerFactory.h create mode 100644 middleware/rialto-client/ipc/client/source/BlockingClosure.cpp create mode 100644 middleware/rialto-client/ipc/client/source/BlockingClosure.h create mode 100644 middleware/rialto-client/ipc/client/source/IpcChannelImpl.cpp create mode 100644 middleware/rialto-client/ipc/client/source/IpcChannelImpl.h create mode 100644 middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.cpp create mode 100644 middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.h create mode 100644 middleware/rialto-client/ipc/client/source/IpcControllerFactory.h create mode 100644 middleware/rialto-client/ipc/common/CMakeLists.txt create mode 100644 middleware/rialto-client/ipc/common/include/INamedSocket.h create mode 120000 middleware/rialto-client/ipc/common/proto/rialtoipc-transport.proto create mode 120000 middleware/rialto-client/ipc/common/proto/rialtoipc.proto create mode 100644 middleware/rialto-client/ipc/common/source/FileDescriptor.cpp create mode 100644 middleware/rialto-client/ipc/common/source/FileDescriptor.h create mode 100644 middleware/rialto-client/ipc/common/source/IpcLogging.h create mode 100644 middleware/rialto-client/ipc/common/source/NamedSocket.cpp create mode 100644 middleware/rialto-client/ipc/common/source/NamedSocket.h create mode 100644 middleware/rialto-client/ipc/common/source/SimpleBufferPool.cpp create mode 100644 middleware/rialto-client/ipc/common/source/SimpleBufferPool.h create mode 100644 middleware/rialto-client/ipc/examples/CMakeLists.txt create mode 100644 middleware/rialto-client/ipc/examples/ExampleClient.cpp create mode 100644 middleware/rialto-client/ipc/examples/ExampleServer.cpp create mode 100644 middleware/rialto-client/ipc/examples/ExampleSocketPair.cpp create mode 100644 middleware/rialto-client/ipc/examples/example.proto create mode 100644 middleware/rialto-client/ipc/server/CMakeLists.txt create mode 100644 middleware/rialto-client/ipc/server/include/IIpcController.h create mode 100644 middleware/rialto-client/ipc/server/include/IIpcServer.h create mode 100644 middleware/rialto-client/ipc/server/include/IIpcServerFactory.h create mode 100644 middleware/rialto-client/ipc/server/source/IpcClientImpl.cpp create mode 100644 middleware/rialto-client/ipc/server/source/IpcClientImpl.h create mode 100644 middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.cpp create mode 100644 middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.h create mode 100644 middleware/rialto-client/ipc/server/source/IpcServerImpl.cpp create mode 100644 middleware/rialto-client/ipc/server/source/IpcServerImpl.h create mode 100644 middleware/rialto-client/logging/CMakeLists.txt create mode 100644 middleware/rialto-client/logging/include/RialtoLogging.h create mode 100644 middleware/rialto-client/logging/source/EnvVariableParser.cpp create mode 100644 middleware/rialto-client/logging/source/EnvVariableParser.h create mode 100644 middleware/rialto-client/logging/source/LogFileHandle.cpp create mode 100644 middleware/rialto-client/logging/source/LogFileHandle.h create mode 100644 middleware/rialto-client/logging/source/RialtoLogging.cpp create mode 100644 middleware/rialto-client/media/CMakeLists.txt create mode 100644 middleware/rialto-client/media/client/CMakeLists.txt create mode 100644 middleware/rialto-client/media/client/common/CMakeLists.txt create mode 100644 middleware/rialto-client/media/client/common/include/RialtoClientLogging.h create mode 100644 middleware/rialto-client/media/client/ipc/CMakeLists.txt create mode 100644 middleware/rialto-client/media/client/ipc/include/ControlIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/include/IConnectionObserver.h create mode 100644 middleware/rialto-client/media/client/ipc/include/IIpcClient.h create mode 100644 middleware/rialto-client/media/client/ipc/include/IpcClient.h create mode 100644 middleware/rialto-client/media/client/ipc/include/IpcModule.h create mode 100644 middleware/rialto-client/media/client/ipc/include/MediaKeysCapabilitiesIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/include/MediaKeysIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/include/MediaPipelineIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/include/RialtoCommonIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/include/WebAudioPlayerIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/interface/IControlIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaKeysCapabilitiesIpcFactory.h create mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaKeysIpcFactory.h create mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaPipelineCapabilitiesIpcFactory.h create mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpcClient.h create mode 100644 middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpc.h create mode 100644 middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpcClient.h create mode 120000 middleware/rialto-client/media/client/ipc/proto/controlmodule.proto create mode 120000 middleware/rialto-client/media/client/ipc/proto/mediakeyscapabilitiesmodule.proto create mode 120000 middleware/rialto-client/media/client/ipc/proto/mediakeysmodule.proto create mode 120000 middleware/rialto-client/media/client/ipc/proto/mediapipelinecapabilitiesmodule.proto create mode 120000 middleware/rialto-client/media/client/ipc/proto/mediapipelinemodule.proto create mode 120000 middleware/rialto-client/media/client/ipc/proto/rialtocommon.proto create mode 120000 middleware/rialto-client/media/client/ipc/proto/webaudioplayermodule.proto create mode 100644 middleware/rialto-client/media/client/ipc/source/ControlIpc.cpp create mode 100644 middleware/rialto-client/media/client/ipc/source/IpcClient.cpp create mode 100644 middleware/rialto-client/media/client/ipc/source/IpcModule.cpp create mode 100644 middleware/rialto-client/media/client/ipc/source/MediaKeysCapabilitiesIpc.cpp create mode 100644 middleware/rialto-client/media/client/ipc/source/MediaKeysIpc.cpp create mode 100644 middleware/rialto-client/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp create mode 100644 middleware/rialto-client/media/client/ipc/source/MediaPipelineIpc.cpp create mode 100644 middleware/rialto-client/media/client/ipc/source/RialtoCommonIpc.cpp create mode 100644 middleware/rialto-client/media/client/ipc/source/WebAudioPlayerIpc.cpp create mode 100644 middleware/rialto-client/media/client/main/CMakeLists.txt create mode 100644 middleware/rialto-client/media/client/main/include/AttachedSources.h create mode 100644 middleware/rialto-client/media/client/main/include/ClientController.h create mode 100644 middleware/rialto-client/media/client/main/include/ClientLogControl.h create mode 100644 middleware/rialto-client/media/client/main/include/Control.h create mode 100644 middleware/rialto-client/media/client/main/include/IClientController.h create mode 100644 middleware/rialto-client/media/client/main/include/ISharedMemoryHandle.h create mode 100644 middleware/rialto-client/media/client/main/include/KeyIdMap.h create mode 100644 middleware/rialto-client/media/client/main/include/MediaKeys.h create mode 100644 middleware/rialto-client/media/client/main/include/MediaKeysCapabilities.h create mode 100644 middleware/rialto-client/media/client/main/include/MediaPipeline.h create mode 100644 middleware/rialto-client/media/client/main/include/MediaPipelineCapabilities.h create mode 100644 middleware/rialto-client/media/client/main/include/MediaPipelineProxy.h create mode 100644 middleware/rialto-client/media/client/main/include/SharedMemoryHandle.h create mode 100644 middleware/rialto-client/media/client/main/include/WebAudioPlayer.h create mode 100644 middleware/rialto-client/media/client/main/include/WebAudioPlayerProxy.h create mode 100644 middleware/rialto-client/media/client/main/source/AttachedSources.cpp create mode 100644 middleware/rialto-client/media/client/main/source/ClientController.cpp create mode 100644 middleware/rialto-client/media/client/main/source/ClientLogControl.cpp create mode 100644 middleware/rialto-client/media/client/main/source/Control.cpp create mode 100644 middleware/rialto-client/media/client/main/source/KeyIdMap.cpp create mode 100644 middleware/rialto-client/media/client/main/source/MediaKeys.cpp create mode 100644 middleware/rialto-client/media/client/main/source/MediaKeysCapabilities.cpp create mode 100644 middleware/rialto-client/media/client/main/source/MediaPipeline.cpp create mode 100644 middleware/rialto-client/media/client/main/source/MediaPipelineCapabilities.cpp create mode 100644 middleware/rialto-client/media/client/main/source/SharedMemoryHandle.cpp create mode 100644 middleware/rialto-client/media/client/main/source/WebAudioPlayer.cpp create mode 100644 middleware/rialto-client/media/common/CMakeLists.txt create mode 100644 middleware/rialto-client/media/common/include/ByteWriter.h create mode 100644 middleware/rialto-client/media/common/include/MediaFrameWriterFactory.h create mode 100644 middleware/rialto-client/media/common/include/MediaFrameWriterV1.h create mode 100644 middleware/rialto-client/media/common/include/MediaFrameWriterV2.h create mode 100644 middleware/rialto-client/media/common/interface/IMediaFrameWriter.h create mode 100644 middleware/rialto-client/media/common/interface/SchemaVersion.h create mode 100644 middleware/rialto-client/media/common/interface/ShmCommon.h create mode 100644 middleware/rialto-client/media/common/interface/TypeConverters.h create mode 120000 middleware/rialto-client/media/common/proto/metadata.proto create mode 100644 middleware/rialto-client/media/common/source/ByteWriter.cpp create mode 100644 middleware/rialto-client/media/common/source/MediaFrameWriterFactory.cpp create mode 100644 middleware/rialto-client/media/common/source/MediaFrameWriterV1.cpp create mode 100644 middleware/rialto-client/media/common/source/MediaFrameWriterV2.cpp create mode 100644 middleware/rialto-client/media/common/source/SchemaVersion.cpp create mode 100644 middleware/rialto-client/media/common/source/TypeConverters.cpp create mode 100644 middleware/rialto-client/media/public/CMakeLists.txt create mode 100644 middleware/rialto-client/media/public/include/ControlCommon.h create mode 100644 middleware/rialto-client/media/public/include/IClientLogControl.h create mode 100644 middleware/rialto-client/media/public/include/IClientLogHandler.h create mode 100644 middleware/rialto-client/media/public/include/IControl.h create mode 100644 middleware/rialto-client/media/public/include/IControlClient.h create mode 100644 middleware/rialto-client/media/public/include/IMediaKeys.h create mode 100644 middleware/rialto-client/media/public/include/IMediaKeysCapabilities.h create mode 100644 middleware/rialto-client/media/public/include/IMediaKeysClient.h create mode 100644 middleware/rialto-client/media/public/include/IMediaPipeline.h create mode 100644 middleware/rialto-client/media/public/include/IMediaPipelineCapabilities.h create mode 100644 middleware/rialto-client/media/public/include/IMediaPipelineClient.h create mode 100644 middleware/rialto-client/media/public/include/IWebAudioPlayer.h create mode 100644 middleware/rialto-client/media/public/include/IWebAudioPlayerClient.h create mode 100644 middleware/rialto-client/media/public/include/MediaCommon.h create mode 100644 middleware/rialto-client/media/server/CMakeLists.txt create mode 100644 middleware/rialto-client/media/server/common/CMakeLists.txt create mode 100644 middleware/rialto-client/media/server/common/include/RialtoServerLogging.h create mode 100644 middleware/rialto-client/media/server/gstplayer/CMakeLists.txt create mode 100644 middleware/rialto-client/media/server/gstplayer/include/CapsBuilder.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/FlushWatcher.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GenericPlayerContext.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstCapabilities.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstDecryptorElementFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstDecryptorPrivate.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstDispatcherThread.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstGenericPlayer.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstInitialiser.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstLogForwarding.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstMimeMapping.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadata.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelper.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelperFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstRialtoTextTrackSinkPrivate.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstSrc.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstTextTrackSinkFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstWebAudioPlayer.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IFlushWatcher.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstDecryptorElementFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThread.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThreadClient.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstGenericPlayerPrivate.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelper.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelperFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstSrc.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstTextTrackSinkFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/IWorkerThread.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/NeedDataMapping.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/Utils.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/WebAudioPlayerContext.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/WorkerThread.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/IPlayerTask.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSamples.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSource.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/CheckAudioUnderflow.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/DeepElementAdded.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/EnoughData.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Eos.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/FinishSetupSource.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Flush.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/NeedData.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Pause.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Ping.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Play.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ProcessAudioGap.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReadShmDataAndAttachSamples.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RemoveSource.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RenderFrame.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReportPosition.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetBufferingLimit.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetImmediateOutput.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetLowLatency.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetMute.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPlaybackRate.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPosition.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSourcePosition.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetStreamSyncMode.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSubtitleOffset.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSync.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSyncOff.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetTextTrackIdentifier.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetUseBuffering.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVideoGeometry.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVolume.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupElement.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupSource.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Shutdown.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Stop.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SwitchSource.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SynchroniseSubtitleClock.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Underflow.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/UpdatePlaybackGroup.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Eos.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/HandleBusMessage.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Pause.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Ping.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Play.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetCaps.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetVolume.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Shutdown.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Stop.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h create mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WriteBuffer.h create mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstCapabilities.h create mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayer.h create mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayerClient.h create mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstInitialiser.h create mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayer.h create mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayerClient.h create mode 100644 middleware/rialto-client/media/server/gstplayer/source/CapsBuilder.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/FlushWatcher.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstCapabilities.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstDecryptor.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstDispatcherThread.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstGenericPlayer.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstInitialiser.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstLogForwarding.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadata.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadataHelper.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstSrc.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstTextTrackSink.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstWebAudioPlayer.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/NeedDataMapping.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/Utils.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/WorkerThread.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSamples.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSource.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/EnoughData.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Eos.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Flush.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/NeedData.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Pause.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Ping.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Play.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ProcessAudioGap.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RenderFrame.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReportPosition.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetBufferingLimit.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetImmediateOutput.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetLowLatency.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetMute.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPosition.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSourcePosition.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetStreamSyncMode.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSubtitleOffset.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSync.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSyncOff.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetTextTrackIdentifier.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetUseBuffering.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVideoGeometry.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVolume.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupElement.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupSource.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Shutdown.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Stop.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SynchroniseSubtitleClock.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Underflow.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Eos.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Pause.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Ping.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Play.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetVolume.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Stop.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp create mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WriteBuffer.cpp create mode 100644 middleware/rialto-client/media/server/ipc/CMakeLists.txt create mode 100644 middleware/rialto-client/media/server/ipc/include/AckSender.h create mode 100644 middleware/rialto-client/media/server/ipc/include/ApplicationManagementServer.h create mode 100644 middleware/rialto-client/media/server/ipc/include/ControlClientServerInternal.h create mode 100644 middleware/rialto-client/media/server/ipc/include/ControlModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/IControlModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/IMediaKeysCapabilitiesModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/IMediaKeysModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/IMediaPipelineCapabilitiesModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/IMediaPipelineModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/IServerManagerModuleServiceFactory.h create mode 100644 middleware/rialto-client/media/server/ipc/include/IWebAudioPlayerModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/MediaKeysCapabilitiesModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/MediaKeysClient.h create mode 100644 middleware/rialto-client/media/server/ipc/include/MediaKeysModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/MediaPipelineClient.h create mode 100644 middleware/rialto-client/media/server/ipc/include/MediaPipelineModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/RialtoCommonModule.h create mode 100644 middleware/rialto-client/media/server/ipc/include/ServerManagerModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/SessionManagementServer.h create mode 100644 middleware/rialto-client/media/server/ipc/include/SetLogLevelsService.h create mode 100644 middleware/rialto-client/media/server/ipc/include/WebAudioPlayerClient.h create mode 100644 middleware/rialto-client/media/server/ipc/include/WebAudioPlayerModuleService.h create mode 100644 middleware/rialto-client/media/server/ipc/interface/IApplicationManagementServer.h create mode 100644 middleware/rialto-client/media/server/ipc/interface/IIpcFactory.h create mode 100644 middleware/rialto-client/media/server/ipc/interface/ISessionManagementServer.h create mode 100644 middleware/rialto-client/media/server/ipc/interface/IpcFactory.h create mode 120000 middleware/rialto-client/media/server/ipc/proto/controlmodule.proto create mode 120000 middleware/rialto-client/media/server/ipc/proto/mediakeyscapabilitiesmodule.proto create mode 120000 middleware/rialto-client/media/server/ipc/proto/mediakeysmodule.proto create mode 120000 middleware/rialto-client/media/server/ipc/proto/mediapipelinecapabilitiesmodule.proto create mode 120000 middleware/rialto-client/media/server/ipc/proto/mediapipelinemodule.proto create mode 120000 middleware/rialto-client/media/server/ipc/proto/rialtocommon.proto create mode 120000 middleware/rialto-client/media/server/ipc/proto/servermanagermodule.proto create mode 120000 middleware/rialto-client/media/server/ipc/proto/webaudioplayermodule.proto create mode 100644 middleware/rialto-client/media/server/ipc/source/AckSender.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/ApplicationManagementServer.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/ControlClientServerInternal.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/ControlModuleService.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/IpcFactory.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/MediaKeysCapabilitiesModuleService.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/MediaKeysClient.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/MediaKeysModuleService.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/MediaPipelineClient.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/MediaPipelineModuleService.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/RialtoCommonModule.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/ServerManagerModuleService.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/SessionManagementServer.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/SetLogLevelsService.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/WebAudioPlayerClient.cpp create mode 100644 middleware/rialto-client/media/server/ipc/source/WebAudioPlayerModuleService.cpp create mode 100644 middleware/rialto-client/media/server/main/CMakeLists.txt create mode 100644 middleware/rialto-client/media/server/main/include/ActiveRequests.h create mode 100644 middleware/rialto-client/media/server/main/include/ControlServerInternal.h create mode 100644 middleware/rialto-client/media/server/main/include/DataReaderFactory.h create mode 100644 middleware/rialto-client/media/server/main/include/DataReaderV1.h create mode 100644 middleware/rialto-client/media/server/main/include/DataReaderV2.h create mode 100644 middleware/rialto-client/media/server/main/include/HeartbeatProcedure.h create mode 100644 middleware/rialto-client/media/server/main/include/IActiveRequests.h create mode 100644 middleware/rialto-client/media/server/main/include/IDataReaderFactory.h create mode 100644 middleware/rialto-client/media/server/main/include/IMediaKeySession.h create mode 100644 middleware/rialto-client/media/server/main/include/INeedMediaDataThread.h create mode 100644 middleware/rialto-client/media/server/main/include/ITextTrackAccessor.h create mode 100644 middleware/rialto-client/media/server/main/include/MainThread.h create mode 100644 middleware/rialto-client/media/server/main/include/MediaKeySession.h create mode 100644 middleware/rialto-client/media/server/main/include/MediaKeysCapabilities.h create mode 100644 middleware/rialto-client/media/server/main/include/MediaKeysCommon.h create mode 100644 middleware/rialto-client/media/server/main/include/MediaKeysServerInternal.h create mode 100644 middleware/rialto-client/media/server/main/include/MediaPipelineCapabilities.h create mode 100644 middleware/rialto-client/media/server/main/include/MediaPipelineServerInternal.h create mode 100644 middleware/rialto-client/media/server/main/include/NeedMediaData.h create mode 100644 middleware/rialto-client/media/server/main/include/SharedMemoryBuffer.h create mode 100644 middleware/rialto-client/media/server/main/include/ShmUtils.h create mode 100644 middleware/rialto-client/media/server/main/include/TextTrackAccessor.h create mode 100644 middleware/rialto-client/media/server/main/include/TextTrackSession.h create mode 100644 middleware/rialto-client/media/server/main/include/WebAudioPlayerServerInternal.h create mode 100644 middleware/rialto-client/media/server/main/interface/IAckSender.h create mode 100644 middleware/rialto-client/media/server/main/interface/IControlClientServerInternal.h create mode 100644 middleware/rialto-client/media/server/main/interface/IControlServerInternal.h create mode 100644 middleware/rialto-client/media/server/main/interface/IDataReader.h create mode 100644 middleware/rialto-client/media/server/main/interface/IDecryptionService.h create mode 100644 middleware/rialto-client/media/server/main/interface/IHeartbeatHandler.h create mode 100644 middleware/rialto-client/media/server/main/interface/IHeartbeatProcedure.h create mode 100644 middleware/rialto-client/media/server/main/interface/IMainThread.h create mode 100644 middleware/rialto-client/media/server/main/interface/IMediaKeysServerInternal.h create mode 100644 middleware/rialto-client/media/server/main/interface/IMediaPipelineServerInternal.h create mode 100644 middleware/rialto-client/media/server/main/interface/ISharedMemoryBuffer.h create mode 100644 middleware/rialto-client/media/server/main/interface/ITextTrackSession.h create mode 100644 middleware/rialto-client/media/server/main/interface/IWebAudioPlayerServerInternal.h create mode 120000 middleware/rialto-client/media/server/main/proto/metadata.proto create mode 100644 middleware/rialto-client/media/server/main/source/ActiveRequests.cpp create mode 100644 middleware/rialto-client/media/server/main/source/ControlServerInternal.cpp create mode 100644 middleware/rialto-client/media/server/main/source/DataReaderFactory.cpp create mode 100644 middleware/rialto-client/media/server/main/source/DataReaderV1.cpp create mode 100644 middleware/rialto-client/media/server/main/source/DataReaderV2.cpp create mode 100644 middleware/rialto-client/media/server/main/source/HeartbeatProcedure.cpp create mode 100644 middleware/rialto-client/media/server/main/source/MainThread.cpp create mode 100644 middleware/rialto-client/media/server/main/source/MediaKeySession.cpp create mode 100644 middleware/rialto-client/media/server/main/source/MediaKeysCapabilities.cpp create mode 100644 middleware/rialto-client/media/server/main/source/MediaKeysServerInternal.cpp create mode 100644 middleware/rialto-client/media/server/main/source/MediaPipelineCapabilities.cpp create mode 100644 middleware/rialto-client/media/server/main/source/MediaPipelineServerInternal.cpp create mode 100644 middleware/rialto-client/media/server/main/source/NeedMediaData.cpp create mode 100644 middleware/rialto-client/media/server/main/source/SharedMemoryBuffer.cpp create mode 100644 middleware/rialto-client/media/server/main/source/TextTrackAccessor.cpp create mode 100644 middleware/rialto-client/media/server/main/source/TextTrackSession.cpp create mode 100644 middleware/rialto-client/media/server/main/source/WebAudioPlayerServerInternal.cpp create mode 100644 middleware/rialto-client/media/server/service/CMakeLists.txt create mode 100644 middleware/rialto-client/media/server/service/include/IApplicationSessionServer.h create mode 100644 middleware/rialto-client/media/server/service/include/ICdmService.h create mode 100644 middleware/rialto-client/media/server/service/include/IControlService.h create mode 100644 middleware/rialto-client/media/server/service/include/IMediaPipelineService.h create mode 100644 middleware/rialto-client/media/server/service/include/IPlaybackService.h create mode 100644 middleware/rialto-client/media/server/service/include/ISessionServerManager.h create mode 100644 middleware/rialto-client/media/server/service/include/IWebAudioPlayerService.h create mode 100644 middleware/rialto-client/media/server/service/source/ApplicationSessionServer.cpp create mode 100644 middleware/rialto-client/media/server/service/source/ApplicationSessionServer.h create mode 100644 middleware/rialto-client/media/server/service/source/CdmService.cpp create mode 100644 middleware/rialto-client/media/server/service/source/CdmService.h create mode 100644 middleware/rialto-client/media/server/service/source/ControlService.cpp create mode 100644 middleware/rialto-client/media/server/service/source/ControlService.h create mode 100644 middleware/rialto-client/media/server/service/source/MediaPipelineService.cpp create mode 100644 middleware/rialto-client/media/server/service/source/MediaPipelineService.h create mode 100644 middleware/rialto-client/media/server/service/source/PlaybackService.cpp create mode 100644 middleware/rialto-client/media/server/service/source/PlaybackService.h create mode 100644 middleware/rialto-client/media/server/service/source/SessionServerManager.cpp create mode 100644 middleware/rialto-client/media/server/service/source/SessionServerManager.h create mode 100644 middleware/rialto-client/media/server/service/source/WebAudioPlayerService.cpp create mode 100644 middleware/rialto-client/media/server/service/source/WebAudioPlayerService.h create mode 100644 middleware/rialto-client/media/server/service/source/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e12ebd94..a2d511324 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,9 +129,27 @@ if(CMAKE_PLATFORM_UBUNTU OR CMAKE_SYSTEM_NAME STREQUAL Darwin) endif(CMAKE_SYSTEM_NAME STREQUAL Darwin) endif() -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rialto-master/media/public/include) +# include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rialto-master/media/public/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/public/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/common/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/common/interface) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/logging/interface) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/client/main/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/client/ipc/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/client/ipc/interface) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/client/common/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/common/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/common/interface) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/ipc/client/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/ipc/client/source) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/ipc/common/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/ipc/common/source) + + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-gstreamer/source) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-gstreamer/source) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-ocdm/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/test/utests/ocdm/) include_directories(${GSTREAMER_INCLUDE_DIRS}) include_directories(${CURL_INCLUDE_DIRS}) @@ -468,12 +486,22 @@ set(GSTTESTHARNESS_SOURCES ) file(GLOB RIALTO_GST_CPP_FILES middleware/rialto-gstreamer/source/*.cpp) + +file(GLOB RIALTO_CLIENT_MAIN_CPP_FILES middleware/rialto-client/media/client/main/source/*.cpp) +file(GLOB RIALTO_CLIENT_IPC_CPP_FILES middleware/rialto-client/media/client/ipc/source/*.cpp) +file(GLOB RIALTO_CLIENT_LOGGING_CPP_FILES middleware/rialto-client/logging/source/*.cpp) +file(GLOB RIALTO_CLIENT_LOGGING_CPP_FILES middleware/rialto-client/common/source/*.cpp) +file(GLOB RIALTO_CLIENT_LOGGING_CPP_FILES middleware/rialto-client/ipc/client/source/*.cpp) +file(GLOB RIALTO_CLIENT_LOGGING_CPP_FILES middleware/rialto-client/ipc/common/source/*.cpp) + file(GLOB RIALTO_OCDM_CPP_FILES middleware/rialto-ocdm/source/*.cpp) + file(GLOB RIALTO_GST_H_FILES middleware/rialto-gstreamer/source/*.h) + message("TEST START") message(${RIALTO_GST_CPP_FILES}) message(${RIALTO_GST_H_FILES}) -list(APPEND GSTTESTHARNESS_SOURCES ${RIALTO_GST_CPP_FILES} ${RIALTO_OCDM_CPP_FILES} ${RIALTO_GST_H_FILES}) +list(APPEND GSTTESTHARNESS_SOURCES ${RIALTO_GST_CPP_FILES} ${RIALTO_OCDM_CPP_FILES} ${RIALTO_CLIENT_MAIN_CPP_FILES} ${RIALTO_CLIENT_IPC_CPP_FILES} ${RIALTO_CLIENT_LOGGING_CPP_FILES} ${RIALTO_GST_H_FILES}) add_executable(gstTestHarness ${GSTTESTHARNESS_SOURCES}) target_link_libraries(gstTestHarness ${GSTTESTHARNESS_DEPENDS} "-lreadline") diff --git a/middleware/rialto-client/common/CMakeLists.txt b/middleware/rialto-client/common/CMakeLists.txt new file mode 100644 index 000000000..42d7a115f --- /dev/null +++ b/middleware/rialto-client/common/CMakeLists.txt @@ -0,0 +1,58 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +add_subdirectory(public) + +add_library( + RialtoCommon + STATIC + + source/EventThread.cpp + source/LinuxUtils.cpp + source/Timer.cpp + ) + +set_property ( + TARGET + RialtoCommon + PROPERTY POSITION_INDEPENDENT_CODE ON +) + +target_include_directories( + RialtoCommon + + PUBLIC + interface + $ + + PRIVATE + include + ) + +target_link_libraries ( + RialtoCommon + + PRIVATE + RialtoLogging + ) diff --git a/middleware/rialto-client/common/include/EventThread.h b/middleware/rialto-client/common/include/EventThread.h new file mode 100644 index 000000000..64cc89010 --- /dev/null +++ b/middleware/rialto-client/common/include/EventThread.h @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_EVENT_THREAD_H_ +#define FIREBOLT_RIALTO_COMMON_EVENT_THREAD_H_ + +#include "IEventThread.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::common +{ +class EventThreadFactory : public IEventThreadFactory +{ +public: + std::unique_ptr createEventThread(std::string threadName) const override; +}; + +class EventThread : public IEventThread +{ +public: + explicit EventThread(std::string threadName = std::string()); + ~EventThread(); + + void flush() override; + +private: + void addImpl(std::function &&func) override; + + void threadExecutor(); + +private: + const std::string m_kThreadName; + + std::list> m_funcs; + std::mutex m_lock; + std::condition_variable m_cond; + + std::atomic m_shutdown; + std::thread m_thread; +}; + +}; // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_EVENT_THREAD_H_ diff --git a/middleware/rialto-client/common/include/Timer.h b/middleware/rialto-client/common/include/Timer.h new file mode 100644 index 000000000..7393c9a61 --- /dev/null +++ b/middleware/rialto-client/common/include/Timer.h @@ -0,0 +1,72 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_TIMER_H_ +#define FIREBOLT_RIALTO_COMMON_TIMER_H_ + +#include "ITimer.h" + +#include +#include +#include +#include +#include + +namespace firebolt::rialto::common +{ +/** + * @brief ITimerFactory factory class definition. + */ +class TimerFactory : public ITimerFactory +{ +public: + /** + * @brief Weak pointer to the singleton factory object. + */ + static std::weak_ptr m_factory; + + std::unique_ptr createTimer(const std::chrono::milliseconds &timeout, const std::function &callback, + TimerType timerType = TimerType::ONE_SHOT) const override; +}; + +class Timer : public ITimer +{ +public: + Timer(const std::chrono::milliseconds &timeout, const std::function &callback, + TimerType timerType = TimerType::ONE_SHOT); + ~Timer(); + Timer(const Timer &) = delete; + Timer(Timer &&) = delete; + Timer &operator=(const Timer &) = delete; + Timer &operator=(Timer &&) = delete; + + void cancel() override; + bool isActive() const override; + +private: + std::atomic m_active; + std::chrono::milliseconds m_timeout; + std::function m_callback; + mutable std::mutex m_mutex; + std::thread m_thread; + std::condition_variable m_cv; +}; +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_TIMER_H_ diff --git a/middleware/rialto-client/common/interface/IEventThread.h b/middleware/rialto-client/common/interface/IEventThread.h new file mode 100644 index 000000000..4c9932e8c --- /dev/null +++ b/middleware/rialto-client/common/interface/IEventThread.h @@ -0,0 +1,104 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_I_EVENT_THREAD_H_ +#define FIREBOLT_RIALTO_COMMON_I_EVENT_THREAD_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::common +{ +class IEventThread; + +/** + * @brief IEventThreadFactory factory class, returns a concrete implementation of IEventThread + */ +class IEventThreadFactory +{ +public: + IEventThreadFactory() = default; + virtual ~IEventThreadFactory() = default; + + /** + * @brief Creates a IEventThreadFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates an IEventThread object. + * + * @param[in] threadName : The name of the thread + * + * @retval the new event thread instance or null on error. + */ + virtual std::unique_ptr createEventThread(std::string threadName = std::string()) const = 0; +}; + +class IEventThread +{ +public: + IEventThread() = default; + virtual ~IEventThread() = default; + + IEventThread(const IEventThread &) = delete; + IEventThread &operator=(const IEventThread &) = delete; + IEventThread(IEventThread &&) = delete; + IEventThread &operator=(IEventThread &&) = delete; + + /** + * @brief Flush any waiting events. + */ + virtual void flush() = 0; + + /** + * @brief Add the event handler function. + * + * @param[in] func : Function to call on event. + */ + template inline void add(Function &&func) { this->addImpl(std::forward(func)); } + + /** + * @brief Add the event handler function with arguments. + * + * @param[in] func : Function to call on event. + * @param[in] args : Arguments to pass into the function. + */ + template inline void add(Function &&func, Args &&...args) + { + this->addImpl(std::bind(std::forward(func), std::forward(args)...)); + } + +private: + virtual void addImpl(std::function &&func) = 0; +}; + +}; // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_I_EVENT_THREAD_H_ diff --git a/middleware/rialto-client/common/interface/ITimer.h b/middleware/rialto-client/common/interface/ITimer.h new file mode 100644 index 000000000..710a3ed32 --- /dev/null +++ b/middleware/rialto-client/common/interface/ITimer.h @@ -0,0 +1,93 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_I_TIMER_H_ +#define FIREBOLT_RIALTO_COMMON_I_TIMER_H_ + +#include +#include +#include + +namespace firebolt::rialto::common +{ +class ITimer; + +enum class TimerType +{ + ONE_SHOT, + PERIODIC +}; + +/** + * @brief ITimerFactory factory class, returns a concrete implementation of ITimer + */ +class ITimerFactory +{ +public: + ITimerFactory() = default; + virtual ~ITimerFactory() = default; + + /** + * @brief Gets the ITimerFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Creates an ITimer object. + * + * @param[in] timeout : Timeout after which callback will be called + * @param[in] callback : Function which is called after timeout + * @param[in] timerType : Type of timer + * + * @retval the new timer instance or null on error. + */ + virtual std::unique_ptr createTimer(const std::chrono::milliseconds &timeout, + const std::function &callback, + TimerType timerType = TimerType::ONE_SHOT) const = 0; +}; + +class ITimer +{ +public: + ITimer() = default; + virtual ~ITimer() = default; + + ITimer(const ITimer &) = delete; + ITimer &operator=(const ITimer &) = delete; + ITimer(ITimer &&) = delete; + ITimer &operator=(ITimer &&) = delete; + + /** + * @brief Cancels the timer + */ + virtual void cancel() = 0; + + /** + * @brief Checks if timer is active + * + * @retval true if timer is active, false otherwise + */ + virtual bool isActive() const = 0; +}; + +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_I_TIMER_H_ diff --git a/middleware/rialto-client/common/interface/LinuxUtils.h b/middleware/rialto-client/common/interface/LinuxUtils.h new file mode 100644 index 000000000..b6c22ade8 --- /dev/null +++ b/middleware/rialto-client/common/interface/LinuxUtils.h @@ -0,0 +1,31 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_LINUX_UTILS_H_ +#define FIREBOLT_RIALTO_COMMON_LINUX_UTILS_H_ + +#include + +namespace firebolt::rialto::common +{ +bool setFilePermissions(const std::string &filePath, unsigned int filePermissions); +bool setFileOwnership(const std::string &filePath, const std::string &fileOwner, const std::string &fileGroup); +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_LINUX_UTILS_H_ diff --git a/middleware/rialto-client/common/interface/RialtoCommonLogging.h b/middleware/rialto-client/common/interface/RialtoCommonLogging.h new file mode 100644 index 000000000..76b2a1ce2 --- /dev/null +++ b/middleware/rialto-client/common/interface/RialtoCommonLogging.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RIALTO_COMMON_LOGGING_H_ +#define RIALTO_COMMON_LOGGING_H_ + +#include "RialtoLogging.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RIALTO_COMMON_LOG_FATAL(fmt, args...) RIALTO_LOG_FATAL(RIALTO_COMPONENT_COMMON, fmt, ##args) +#define RIALTO_COMMON_LOG_SYS_FATAL(err, fmt, args...) RIALTO_LOG_SYS_FATAL(RIALTO_COMPONENT_COMMON, err, fmt, ##args) +#define RIALTO_COMMON_LOG_ERROR(fmt, args...) RIALTO_LOG_ERROR(RIALTO_COMPONENT_COMMON, fmt, ##args) +#define RIALTO_COMMON_LOG_SYS_ERROR(err, fmt, args...) RIALTO_LOG_SYS_ERROR(RIALTO_COMPONENT_COMMON, err, fmt, ##args) +#define RIALTO_COMMON_LOG_WARN(fmt, args...) RIALTO_LOG_WARN(RIALTO_COMPONENT_COMMON, fmt, ##args) +#define RIALTO_COMMON_LOG_SYS_WARN(err, fmt, args...) RIALTO_LOG_SYS_WARN(RIALTO_COMPONENT_COMMON, err, fmt, ##args) +#define RIALTO_COMMON_LOG_MIL(fmt, args...) RIALTO_LOG_MIL(RIALTO_COMPONENT_COMMON, fmt, ##args) +#define RIALTO_COMMON_LOG_INFO(fmt, args...) RIALTO_LOG_INFO(RIALTO_COMPONENT_COMMON, fmt, ##args) +#define RIALTO_COMMON_LOG_DEBUG(fmt, args...) RIALTO_LOG_DEBUG(RIALTO_COMPONENT_COMMON, fmt, ##args) + +#ifdef __cplusplus +} +#endif + +#endif // RIALTO_COMMON_LOGGING_H_ diff --git a/middleware/rialto-client/common/public/CMakeLists.txt b/middleware/rialto-client/common/public/CMakeLists.txt new file mode 100644 index 000000000..019ffe843 --- /dev/null +++ b/middleware/rialto-client/common/public/CMakeLists.txt @@ -0,0 +1,51 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2023 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +configure_file( + include/SessionServerCommon.in + include/SessionServerCommon.h + @ONLY ) + +add_library( + RialtoCommonPublic + INTERFACE + ) + +target_include_directories( + RialtoCommonPublic + + INTERFACE + ${CMAKE_BINARY_DIR}/common/public/include + ) + +if( NOT CMAKE_BUILD_TYPE STREQUAL "UnitTests" ) + include( GNUInstallDirs ) + set (LIB_RIALTO_COMMON_PUBLIC_HEADERS + ${CMAKE_BINARY_DIR}/common/public/include/SessionServerCommon.h + ) + install ( + FILES ${LIB_RIALTO_COMMON_PUBLIC_HEADERS} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rialto + ) +endif() diff --git a/middleware/rialto-client/common/public/include/SessionServerCommon.in b/middleware/rialto-client/common/public/include/SessionServerCommon.in new file mode 100644 index 000000000..1658a93bc --- /dev/null +++ b/middleware/rialto-client/common/public/include/SessionServerCommon.in @@ -0,0 +1,112 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_SESSION_SERVER_COMMON_H_ +#define FIREBOLT_RIALTO_COMMON_SESSION_SERVER_COMMON_H_ + +#include +#include +#include +#include + +namespace firebolt::rialto::common +{ +/** + * @brief Represents all possible states of session server. + * + * Session Servers can be in one of four states, Not Running (session server not loaded or running), + * Active (session server loaded, running and able to stream AV, Inactive (session server loaded but unable + * to stream AV) and Uninitialized (session server loaded, waiting for initialization data). Error is used, + * when something went wrong (for example connection failed) + * + */ +enum class SessionServerState +{ + UNINITIALIZED, + INACTIVE, + ACTIVE, + NOT_RUNNING, + ERROR +}; + +/** + * @brief The max resource capabilities of the platform. + */ +struct MaxResourceCapabilitites +{ + int maxPlaybacks; + int maxWebAudioPlayers; +}; + +/** + * @brief Configuration data for an application + */ +struct AppConfig +{ + std::string clientIpcSocketName; /**< Socket name that Rialto client should connect to */ + /* + * @note Socket name can take the following forms: + * - Empty string, in which case Rialto server will automatically allocate the socket name, e.g. "/tmp/rialto-12" + * - Full path, such as "/foo/bar", in which case Rialto will use this name for the socket + * - Socket name, such as "bar", in which case Rialto will create the named socket in the default dir, e.g. + * "/tmp/bar" In all cases the name can be retrieved with getAppConnectionInfo() + */ + std::string clientDisplayName; /**< Socket name that Rialto client should connect to */ +}; + +/** + * @brief Available permissions + */ +constexpr unsigned int kRead{4}; +constexpr unsigned int kWrite{2}; +constexpr unsigned int kExecute{1}; + +/** + * @brief Socket permissions and ownership + */ +struct SocketPermissions +{ + unsigned int ownerPermissions{@SOCKET_PERMISSIONS_OWNER@}; + unsigned int groupPermissions{@SOCKET_PERMISSIONS_GROUP@}; + unsigned int otherPermissions{@SOCKET_PERMISSIONS_OTHER@}; + std::string owner{@SOCKET_OWNER@}; + std::string group{@SOCKET_GROUP@}; +}; + +/** + * @brief Configuration data for server manager + */ +struct ServerManagerConfig +{ + std::list sessionServerEnvVars{@ENVIRONMENT_VARIABLES@}; + /* List of environment variables, that need to be passed to RialtoSessionServer */ + unsigned numOfPreloadedServers{@NUM_OF_PRELOADED_SERVERS@}; /* Number of preloaded servers */ + std::string sessionServerPath{@SESSION_SERVER_PATH@}; /* Location of Rialto Session Server binary */ + std::chrono::milliseconds sessionServerStartupTimeout{@STARTUP_TIMEOUT_MS@}; + /* Custom session server startup timeout. If 0 - timeout disabled. */ + std::chrono::seconds healthcheckInterval{@HEALTHCHECK_INTERVAL_S@}; + /* Defines how often healthcheck messages will be sent */ + SocketPermissions sessionManagementSocketPermissions{}; /* Defines permissions of session management socket */ + unsigned numOfFailedPingsBeforeRecovery{@NUM_OF_PINGS_BEFORE_RECOVERY@}; + /* Defines how many pings have to fail before recovery action will be taken */ +}; + +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_SESSION_SERVER_COMMON_H_ diff --git a/middleware/rialto-client/common/source/EventThread.cpp b/middleware/rialto-client/common/source/EventThread.cpp new file mode 100644 index 000000000..1ad60188b --- /dev/null +++ b/middleware/rialto-client/common/source/EventThread.cpp @@ -0,0 +1,122 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "EventThread.h" +#include "RialtoCommonLogging.h" + +#include +#include +#include + +namespace firebolt::rialto::common +{ +std::shared_ptr IEventThreadFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_COMMON_LOG_ERROR("Failed to create the event thread factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr EventThreadFactory::createEventThread(std::string threadName) const +{ + return std::make_unique(threadName); +} + +EventThread::EventThread(std::string threadName) : m_kThreadName(std::move(threadName)), m_shutdown(false) +{ + m_thread = std::thread(&EventThread::threadExecutor, this); +} + +EventThread::~EventThread() +{ + std::unique_lock locker(m_lock); + + m_shutdown = true; + + m_cond.notify_all(); + + locker.unlock(); + + if (m_thread.joinable()) + m_thread.join(); +} + +void EventThread::threadExecutor() +{ + if (!m_kThreadName.empty()) + { + pthread_setname_np(pthread_self(), m_kThreadName.c_str()); + } + + std::unique_lock locker(m_lock); + + while (true) + { + while (!m_shutdown && m_funcs.empty()) + m_cond.wait(locker); + + if (m_shutdown) + break; + + std::function func = std::move(m_funcs.front()); + m_funcs.pop_front(); + + m_lock.unlock(); + + if (func) + func(); + + m_lock.lock(); + } +} + +void EventThread::flush() +{ + sem_t semaphore; + sem_init(&semaphore, 0, 0); + + // add a simple function to release the semaphore in the context of the event thread + addImpl( + [sem = &semaphore]() + { + if (sem_post(sem) != 0) + RIALTO_COMMON_LOG_SYS_ERROR(errno, "failed to signal semaphore"); + }); + + // wait for the above call to unblock the semaphore + TEMP_FAILURE_RETRY(sem_wait(&semaphore)); +} + +void EventThread::addImpl(std::function &&func) +{ + std::lock_guard locker(m_lock); + m_funcs.emplace_back(std::move(func)); + m_cond.notify_all(); +} + +}; // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/common/source/LinuxUtils.cpp b/middleware/rialto-client/common/source/LinuxUtils.cpp new file mode 100644 index 000000000..b8906830a --- /dev/null +++ b/middleware/rialto-client/common/source/LinuxUtils.cpp @@ -0,0 +1,107 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LinuxUtils.h" +#include "RialtoCommonLogging.h" +#include +#include +#include +#include + +namespace +{ +constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner +constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group + +uid_t getFileOwnerId(const std::string &fileOwner) +{ + uid_t ownerId = kNoOwnerChange; + const size_t kBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (!fileOwner.empty() && kBufferSize > 0) + { + errno = 0; + passwd passwordStruct{}; + passwd *passwordResult = nullptr; + char buffer[kBufferSize]; + int result = getpwnam_r(fileOwner.c_str(), &passwordStruct, buffer, kBufferSize, &passwordResult); + if (result == 0 && passwordResult) + { + ownerId = passwordResult->pw_uid; + } + else + { + RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to determine ownerId for '%s'", fileOwner.c_str()); + } + } + return ownerId; +} + +gid_t getFileGroupId(const std::string &fileGroup) +{ + gid_t groupId = kNoGroupChange; + const size_t kBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (!fileGroup.empty() && kBufferSize > 0) + { + errno = 0; + group groupStruct{}; + group *groupResult = nullptr; + char buffer[kBufferSize]; + int result = getgrnam_r(fileGroup.c_str(), &groupStruct, buffer, kBufferSize, &groupResult); + if (result == 0 && groupResult) + { + groupId = groupResult->gr_gid; + } + else + { + RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to determine groupId for '%s'", fileGroup.c_str()); + } + } + return groupId; +} +} // namespace + +namespace firebolt::rialto::common +{ +bool setFilePermissions(const std::string &filePath, unsigned int filePermissions) +{ + errno = 0; + if (chmod(filePath.c_str(), filePermissions) != 0) + { + RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to change the permissions on %s", filePath.c_str()); + return false; + } + return true; +} + +bool setFileOwnership(const std::string &filePath, const std::string &fileOwner, const std::string &fileGroup) +{ + uid_t ownerId = getFileOwnerId(fileOwner); + gid_t groupId = getFileGroupId(fileGroup); + + if (ownerId != kNoOwnerChange || groupId != kNoGroupChange) + { + errno = 0; + if (chown(filePath.c_str(), ownerId, groupId) != 0) + { + RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to change the owner/group for %s", filePath.c_str()); + } + } + return true; +} +} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/common/source/Timer.cpp b/middleware/rialto-client/common/source/Timer.cpp new file mode 100644 index 000000000..ae109a692 --- /dev/null +++ b/middleware/rialto-client/common/source/Timer.cpp @@ -0,0 +1,96 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Timer.h" +#include "RialtoCommonLogging.h" + +namespace firebolt::rialto::common +{ +std::weak_ptr TimerFactory::m_factory; + +std::shared_ptr ITimerFactory::getFactory() +{ + std::shared_ptr factory = TimerFactory::m_factory.lock(); + + if (!factory) + { + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_COMMON_LOG_ERROR("Failed to create the timer factory, reason: %s", e.what()); + } + + TimerFactory::m_factory = factory; + } + + return factory; +} + +std::unique_ptr TimerFactory::createTimer(const std::chrono::milliseconds &timeout, + const std::function &callback, TimerType timerType) const +{ + return std::make_unique(timeout, callback, timerType); +} + +Timer::Timer(const std::chrono::milliseconds &timeout, const std::function &callback, TimerType timerType) + : m_active{true}, m_timeout{timeout}, m_callback{callback} +{ + m_thread = std::thread( + [this, timerType]() + { + do + { + std::unique_lock lock{m_mutex}; + if (!m_cv.wait_for(lock, m_timeout, [this]() { return !m_active; })) + { + if (m_active && m_callback) + { + lock.unlock(); + m_callback(); + } + } + } while (timerType == TimerType::PERIODIC && m_active); + m_active = false; + }); +} + +Timer::~Timer() +{ + cancel(); +} + +void Timer::cancel() +{ + m_active = false; + + if (std::this_thread::get_id() != m_thread.get_id() && m_thread.joinable()) + { + m_cv.notify_one(); + m_thread.join(); + } +} + +bool Timer::isActive() const +{ + return m_active; +} +} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/ipc/CMakeLists.txt b/middleware/rialto-client/ipc/CMakeLists.txt new file mode 100644 index 000000000..62e168ef8 --- /dev/null +++ b/middleware/rialto-client/ipc/CMakeLists.txt @@ -0,0 +1,54 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +cmake_minimum_required( VERSION 3.10 ) +project( RialtoIpc ) + +# The following is to check if building this component from this CMakeLists.txt file +# or if it is part of a bigger project +get_directory_property( HAS_PARENT PARENT_DIRECTORY ) +if( NOT HAS_PARENT ) + + set( PROTOC_PATH "" CACHE STRING "Optional path to the host protobuf compiler (protoc) tool" ) + if( PROTOC_PATH ) + add_executable( protobuf::protoc IMPORTED ) + set_target_properties( protobuf::protoc PROPERTIES IMPORTED_LOCATION "${PROTOC_PATH}" ) + endif() + + # Requires protobuf libraries + find_package( Protobuf REQUIRED ) + + # Add the logging component (static library) + add_subdirectory( "${CMAKE_CURRENT_LIST_DIR}/../rialtoLogging" "${CMAKE_CURRENT_BINARY_DIR}/rialtoLogging" ) + +endif() + +# We require C++14 +set( CMAKE_CXX_STANDARD 17 ) +set( CMAKE_CXX_STANDARD_REQUIRED ON ) + +# Build all components with -fPIC as ultimates +set( CMAKE_POSITION_INDEPENDENT_CODE ON ) + +# Sub-components +add_subdirectory( common ) +add_subdirectory( client ) +add_subdirectory( server ) +add_subdirectory( examples EXCLUDE_FROM_ALL ) + diff --git a/middleware/rialto-client/ipc/README.md b/middleware/rialto-client/ipc/README.md new file mode 100644 index 000000000..deafe2738 --- /dev/null +++ b/middleware/rialto-client/ipc/README.md @@ -0,0 +1,52 @@ +# RialtoIpc Library + +This library is used to implement a client channel and server for the Google [protobuf][1] [RPC interface][2]. +In addition, it adds extensions to support sending asynchronous events and passing unix file descriptors in RPC +calls and events. + +The 'library' is actually three libraries, a client side and server side library and a 'common' library that +contains shared code between server and client. The reason for this is to allow a process to be both a client +and server without having symbol clash. + +All transfers are over local unix domain sockets. + +### Dependencies +The only dependency is [protobuf][1], minimum version is 3.6. + +### Server-side Library +* A single server instance can create multiple listening unix domain sockets. +* The server allows for registering zero or more services (protobuf defined service) for a client connection. +* The server can receive RPC method calls and response with a reply or error message. +* The server can send single protobuf messages, these are asynchronous events. + +### Client-side Library +* Clients can make RPC calls using stub c++ code generated by protobuf compiler. +* Clients can register to receive events from the server. +* Clients cannot send events to the server. + +### Both Client and Server Libraries +* Neither library contains any internal threads, each must be driven by an external event loop. + + +## Questions + +### What is Protobuf ? +Protobuf is a host compiler tool and library for taking .proto (text) files describing the format of a message or +service and generating code to serialise and deserialise the messages to / from binary data. It is used in this +library to generate c++ stub code for implementing RPC services. + +### Why not use gRPC ? +[gRPC][3] is built on top of protobuf but also provides the client library code to implement transport across various +different protocols (unix sockets, http, websockets, etc), in this sense it provides the same RPC support. However +since it is more generic it lacks some specific things needed by Rialto: +* Client management - the ability to associate a call with a specific client and get the client details (ie. pid or uid). +* File descriptor passing - it has no support for sending or receiving file descriptors. +* Sending asynchronous events - it doesn't have support for sending asynchronous events, although it does have a concept + of a stream of messages which possibly could be adapted. + + + + +[1]: https://developers.google.com/protocol-buffers +[2]: https://developers.google.com/protocol-buffers/docs/proto#services +[3]: https://grpc.io diff --git a/middleware/rialto-client/ipc/client/CMakeLists.txt b/middleware/rialto-client/ipc/client/CMakeLists.txt new file mode 100644 index 000000000..8334f8d91 --- /dev/null +++ b/middleware/rialto-client/ipc/client/CMakeLists.txt @@ -0,0 +1,56 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +add_library( + RialtoIpcClient + STATIC + + source/IpcChannelImpl.cpp + source/IpcClientControllerImpl.cpp + source/BlockingClosure.cpp + + ) + +target_include_directories( + RialtoIpcClient + + PUBLIC + include + $ + + PRIVATE + $ + + ) + +set_property( + TARGET RialtoIpcClient + PROPERTY POSITION_INDEPENDENT_CODE ON + + ) + +target_link_libraries( + RialtoIpcClient + + PRIVATE + RialtoIpcCommon + RialtoLogging + protobuf::libprotobuf + + ) diff --git a/middleware/rialto-client/ipc/client/include/IBlockingClosure.h b/middleware/rialto-client/ipc/client/include/IBlockingClosure.h new file mode 100644 index 000000000..fa66c9f6e --- /dev/null +++ b/middleware/rialto-client/ipc/client/include/IBlockingClosure.h @@ -0,0 +1,82 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_I_BLOCKING_CLOSURE_H_ +#define FIREBOLT_RIALTO_IPC_I_BLOCKING_CLOSURE_H_ + +#include "IIpcChannel.h" +#include + +namespace firebolt::rialto::ipc +{ +class IBlockingClosure; + +class IBlockingClosureFactory +{ +public: + IBlockingClosureFactory() = default; + virtual ~IBlockingClosureFactory() = default; + + /** + * @brief Create a IBlockingClosureFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a polling IBlockingClosure object. + * Pump the event loop from within the wait() method. + * + * @param[in] ipcChannel : The ipc channel to wait on. + * + * @retval the protobuf controller instance or null on error. + */ + virtual std::shared_ptr + createBlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel) = 0; + + /** + * @brief Creates a semaphore IBlockingClosure object. + * Do not pump the event loop from within the wait() method. + * + * @retval the protobuf controller instance or null on error. + */ + virtual std::shared_ptr createBlockingClosureSemaphore() = 0; +}; + +class IBlockingClosure : public google::protobuf::Closure +{ +public: + IBlockingClosure() = default; + virtual ~IBlockingClosure() = default; + + IBlockingClosure(const IBlockingClosure &) = delete; + IBlockingClosure &operator=(const IBlockingClosure &) = delete; + IBlockingClosure(IBlockingClosure &&) = delete; + IBlockingClosure &operator=(IBlockingClosure &&) = delete; + + /** + * @brief Wait for the response. + */ + virtual void wait() = 0; +}; + +}; // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_I_BLOCKING_CLOSURE_H_ diff --git a/middleware/rialto-client/ipc/client/include/IIpcChannel.h b/middleware/rialto-client/ipc/client/include/IIpcChannel.h new file mode 100644 index 000000000..aa79e41c4 --- /dev/null +++ b/middleware/rialto-client/ipc/client/include/IIpcChannel.h @@ -0,0 +1,170 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_I_IPC_CHANNEL_H_ +#define FIREBOLT_RIALTO_IPC_I_IPC_CHANNEL_H_ + +#include + +#include +#include +#include +#include + +namespace firebolt::rialto::ipc +{ +class IChannel; + +/** + * @brief IChannel factory class, returns a new connected IChannel object + */ +class IChannelFactory +{ +public: + IChannelFactory() = default; + virtual ~IChannelFactory() = default; + + /** + * @brief Create a IChannelFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Create a connected IChannel object. + * + * \threadsafe + * + * @param[in] socketPath : The path of the socket to connect. + * + * @retval the connected ipc channel instance or null on error. + */ + virtual std::shared_ptr createChannel(const std::string &socketPath) = 0; + + /** + * @brief Create a connected IChannel object. + * + * \threadsafe + * + * Creates an IPC channel around the supplied socket fd. + * The call takes ownership of the fd and it will close it when the channel is + * destructed. The exception to this is if the call fails, in which case the + * caller should close the socket themselves. + * + * @param[in] sockFd : The fd of the connected socket. + * + * @retval the connected ipc channel instance or null on error. + */ + virtual std::shared_ptr createChannel(int sockFd) = 0; +}; + +class IChannel : public google::protobuf::RpcChannel +{ +public: + IChannel() = default; + virtual ~IChannel() = default; + + IChannel(const IChannel &) = delete; + IChannel &operator=(const IChannel &) = delete; + IChannel(IChannel &&) = delete; + IChannel &operator=(IChannel &&) = delete; + + /** + * @brief Disconnect the IPC channel from the socket. + * + * \threadsafe + */ + virtual void disconnect() = 0; + + /** + * @brief Query whether the IPC channel is connected. + * + * \threadsafe + * + * @retval true if connected, false otherwise. + */ + virtual bool isConnected() const = 0; + + /** + * @brief Get the epoll file descriptor. + * + * \threadsafe + * + * @retval >= 0 on success, -1 otherwise. + */ + virtual int fd() const = 0; + + /** + * @brief Waits for any I/O to occur on the socket or timeout from a method call. + * + * The call will block for a maximum of timeoutMSecs, to make the call wait + * indefinitely pass -1. + * + * @param[in] timeoutMSecs : The time to wait for I/O. + * + * @retval false if there was an error or the channel was disconnected, true otherwise + */ + inline bool wait() { return this->wait(-1); } + virtual bool wait(int timeoutMSecs) = 0; + + /** + * @brief Processes at most one event on the channel, this may be a socket message or + * a method call timeout. + * + * \threadsafe + * + * @retval false if there was an error or the channel was disconnected, true otherwise + */ + virtual bool process() = 0; + + /** + * @brief Subscribe for event message. + * + * @param[in] handler : The handler to be called when the event is triggered. + * + * @retval the tag of the subscribed event, -1 on error. + */ + template inline int subscribe(std::function &message)> handler) + { + if (!handler) + return -1; + + return this->subscribeImpl(Message::default_instance().GetTypeName(), Message::default_instance().GetDescriptor(), + [handler_ = std::move(handler)](const std::shared_ptr &msg) + { handler_(std::dynamic_pointer_cast(msg)); }); + } + + /** + * @brief Unsubscribe event. + * + * @param[in] eventTag : The tag of the event to unsubscribe too. + * + * @retval true on success. + */ + virtual bool unsubscribe(int eventTag) = 0; + +private: + virtual int subscribeImpl(const std::string &eventName, const google::protobuf::Descriptor *descriptor, + std::function &msg)> &&handler) = 0; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_I_IPC_CHANNEL_H_ diff --git a/middleware/rialto-client/ipc/client/include/IIpcControllerFactory.h b/middleware/rialto-client/ipc/client/include/IIpcControllerFactory.h new file mode 100644 index 000000000..4329534b5 --- /dev/null +++ b/middleware/rialto-client/ipc/client/include/IIpcControllerFactory.h @@ -0,0 +1,52 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_FACTORY_H_ +#define FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_FACTORY_H_ + +#include + +#include + +namespace firebolt::rialto::ipc +{ +class IControllerFactory +{ +public: + IControllerFactory() = default; + virtual ~IControllerFactory() = default; + + /** + * @brief Create a IControllerFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a RpcController object. + * + * @retval the protobuf controller instance or null on error. + */ + virtual std::shared_ptr create() = 0; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_FACTORY_H_ diff --git a/middleware/rialto-client/ipc/client/source/BlockingClosure.cpp b/middleware/rialto-client/ipc/client/source/BlockingClosure.cpp new file mode 100644 index 000000000..4663f6892 --- /dev/null +++ b/middleware/rialto-client/ipc/client/source/BlockingClosure.cpp @@ -0,0 +1,113 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BlockingClosure.h" +#include "IpcLogging.h" + +#include +#include +#include + +namespace firebolt::rialto::ipc +{ +std::shared_ptr IBlockingClosureFactory::createFactory() +{ + std::shared_ptr factory; + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Failed to create the blocking closure factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr +BlockingClosureFactory::createBlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel) +{ + std::shared_ptr blockingClosure; + try + { + blockingClosure = std::make_shared(ipcChannel); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Failed to create the blocking closure, reason: %s", e.what()); + } + + return blockingClosure; +} + +std::shared_ptr BlockingClosureFactory::createBlockingClosureSemaphore() +{ + std::shared_ptr blockingClosure; + try + { + blockingClosure = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Failed to create the blocking closure, reason: %s", e.what()); + } + + return blockingClosure; +} + +BlockingClosurePoll::BlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel) + : m_kChannel(std::move(ipcChannel)), m_done(false) +{ +} + +void BlockingClosurePoll::Run() // NOLINT(build/function_format) +{ + m_done = true; +} + +void BlockingClosurePoll::wait() +{ + while (m_kChannel->process() && !m_done) + { + m_kChannel->wait(-1); + } +} + +BlockingClosureSemaphore::BlockingClosureSemaphore() : m_sem{{0}} +{ + sem_init(&m_sem, 0, 0); +} + +BlockingClosureSemaphore::~BlockingClosureSemaphore() +{ + sem_destroy(&m_sem); +} + +void BlockingClosureSemaphore::Run() // NOLINT(build/function_format) +{ + if (sem_post(&m_sem) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to signal semaphore"); +} + +void BlockingClosureSemaphore::wait() +{ + TEMP_FAILURE_RETRY(sem_wait(&m_sem)); +} +}; // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/client/source/BlockingClosure.h b/middleware/rialto-client/ipc/client/source/BlockingClosure.h new file mode 100644 index 000000000..d5c84b782 --- /dev/null +++ b/middleware/rialto-client/ipc/client/source/BlockingClosure.h @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_BLOCKING_CLOSURE_H_ +#define FIREBOLT_RIALTO_IPC_BLOCKING_CLOSURE_H_ + +#include "IBlockingClosure.h" +#include +#include + +namespace firebolt::rialto::ipc +{ +class BlockingClosureFactory : public IBlockingClosureFactory +{ +public: + BlockingClosureFactory() = default; + ~BlockingClosureFactory() override = default; + + std::shared_ptr + createBlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel) override; + std::shared_ptr createBlockingClosureSemaphore() override; +}; + +class BlockingClosurePoll final : public IBlockingClosure +{ +public: + explicit BlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel); + ~BlockingClosurePoll() final = default; + + void Run() final; + void wait() final; + +private: + const std::shared_ptr<::firebolt::rialto::ipc::IChannel> m_kChannel; + bool m_done; +}; + +class BlockingClosureSemaphore final : public IBlockingClosure +{ +public: + BlockingClosureSemaphore(); + ~BlockingClosureSemaphore() final; + + void Run() final; + void wait() final; + +private: + sem_t m_sem; +}; +}; // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_BLOCKING_CLOSURE_H_ diff --git a/middleware/rialto-client/ipc/client/source/IpcChannelImpl.cpp b/middleware/rialto-client/ipc/client/source/IpcChannelImpl.cpp new file mode 100644 index 000000000..85c6fea52 --- /dev/null +++ b/middleware/rialto-client/ipc/client/source/IpcChannelImpl.cpp @@ -0,0 +1,1207 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "IpcChannelImpl.h" +#include "IpcLogging.h" +#include "rialtoipc.pb.h" + +#if !defined(SCM_MAX_FD) +#define SCM_MAX_FD 255 +#endif + +namespace +{ +constexpr size_t kMaxMessageSize{128 * 1024}; +const std::chrono::milliseconds kDefaultIpcTimeout{3000}; + +std::chrono::milliseconds getIpcTimeout() +{ + const char *kCustomTimeout = getenv("RIALTO_CLIENT_IPC_TIMEOUT"); + std::chrono::milliseconds timeout{kDefaultIpcTimeout}; + if (kCustomTimeout) + { + try + { + timeout = std::chrono::milliseconds{std::stoull(kCustomTimeout)}; + RIALTO_IPC_LOG_INFO("Using custom Ipc timeout: %sms", kCustomTimeout); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Custom Ipc timeout invalid, ignoring: %s", kCustomTimeout); + } + } + return timeout; +} +} // namespace + +namespace firebolt::rialto::ipc +{ + +std::shared_ptr IChannelFactory::createFactory() +{ + std::shared_ptr factory; + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Failed to create the ipc channel factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr ChannelFactory::createChannel(int sockFd) +{ + std::shared_ptr channel; + try + { + channel = std::make_shared(sockFd); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Failed to create the ipc channel with socketFd %d, reason: %s", sockFd, e.what()); + } + + return channel; +} + +std::shared_ptr ChannelFactory::createChannel(const std::string &socketPath) +{ + std::shared_ptr channel; + try + { + channel = std::make_shared(socketPath); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Failed to create the ipc channel with socketPath %s, reason: %s", socketPath.c_str(), + e.what()); + } + + return channel; +} + +ChannelImpl::ChannelImpl(int sock) + : m_sock(-1), m_epollFd(-1), m_timerFd(-1), m_eventFd(-1), m_serialCounter(1), m_timeout(getIpcTimeout()), + m_eventTagCounter(1) +{ + if (!attachSocket(sock)) + { + throw std::runtime_error("Failed attach the socket"); + } + if (!initChannel()) + { + termChannel(); + throw std::runtime_error("Failed to initalise the channel"); + } + if (!isConnectedInternal()) + { + termChannel(); + throw std::runtime_error("Channel not connected"); + } +} + +ChannelImpl::ChannelImpl(const std::string &socketPath) + : m_sock(-1), m_epollFd(-1), m_timerFd(-1), m_eventFd(-1), m_serialCounter(1), m_timeout(getIpcTimeout()), + m_eventTagCounter(1) +{ + if (!createConnectedSocket(socketPath)) + { + throw std::runtime_error("Failed connect socket"); + } + if (!initChannel()) + { + termChannel(); + throw std::runtime_error("Failed to initalise the channel"); + } + if (!isConnectedInternal()) + { + termChannel(); + throw std::runtime_error("Channel not connected"); + } +} + +ChannelImpl::~ChannelImpl() +{ + termChannel(); +} + +bool ChannelImpl::createConnectedSocket(const std::string &socketPath) +{ + int sock = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (sock < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to create socket"); + return false; + } + + struct sockaddr_un addr = {0}; + memset(&addr, 0x00, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); + + if (::connect(sock, reinterpret_cast(&addr), sizeof(addr)) == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to connect to %s", socketPath.c_str()); + close(sock); + return false; + } + + m_sock = sock; + + return true; +} + +bool ChannelImpl::attachSocket(int sockFd) +{ + // sanity check the supplied socket is of the right type + struct sockaddr addr; + socklen_t len = sizeof(addr); + if ((getsockname(sockFd, &addr, &len) < 0) || (len < sizeof(sa_family_t))) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get name of supplied socket"); + return false; + } + if (addr.sa_family != AF_UNIX) + { + RIALTO_IPC_LOG_ERROR("supplied client socket is not a unix domain socket"); + return false; + } + + int type = 0; + len = sizeof(type); + if ((getsockopt(sockFd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) || (len != sizeof(type))) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get type of supplied socket"); + return false; + } + if (type != SOCK_SEQPACKET) + { + RIALTO_IPC_LOG_ERROR("supplied client socket is not of type SOCK_SEQPACKET"); + return false; + } + + // set the O_NONBLOCKING flag on the socket + int flags = fcntl(sockFd, F_GETFL); + if ((flags < 0) || (fcntl(sockFd, F_SETFL, flags | O_NONBLOCK) < 0)) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to set socket to non-blocking mode"); + return false; + } + + m_sock = sockFd; + + return true; +} + +bool ChannelImpl::initChannel() +{ + // create epoll so can listen for timeouts as well as socket messages + m_epollFd = epoll_create1(EPOLL_CLOEXEC); + if (m_epollFd < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll failed"); + return false; + } + + // add the socket to epoll + epoll_event sockEvent = {.events = EPOLLIN, .data = {.fd = m_sock}}; + if (epoll_ctl(m_epollFd, EPOLL_CTL_ADD, m_sock, &sockEvent) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add eventfd"); + return false; + } + + m_timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + if (m_timerFd < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "timerfd_create failed"); + return false; + } + + // add the timer event to epoll + epoll_event timerEvent = {.events = EPOLLIN, .data = {.fd = m_timerFd}}; + if (epoll_ctl(m_epollFd, EPOLL_CTL_ADD, m_timerFd, &timerEvent) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add eventfd"); + return false; + } + + // and lastly the eventfd to wake the poll loop + m_eventFd = eventfd(0, EFD_CLOEXEC); + if (m_eventFd < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "eventfd create failed"); + return false; + } + + // add the timer event to epoll + epoll_event wakeEvent = {.events = EPOLLIN, .data = {.fd = m_eventFd}}; + if (epoll_ctl(m_epollFd, EPOLL_CTL_ADD, m_eventFd, &wakeEvent) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add eventfd"); + return false; + } + + return true; +} + +void ChannelImpl::termChannel() +{ + // close the socket and the epoll and timer fds + if (m_sock >= 0) + disconnectNoLock(); + if ((m_epollFd >= 0) && (close(m_epollFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "closing epoll fd failed"); + if ((m_timerFd >= 0) && (close(m_timerFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "closing timer fd failed"); + if ((m_eventFd >= 0) && (close(m_eventFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "closing event fd failed"); + + // if any method calls are still outstanding then complete them with errors now + for (auto &entry : m_methodCalls) + { + completeWithError(&entry.second, "Channel destructed"); + } + + m_methodCalls.clear(); +} + +void ChannelImpl::disconnect() +{ + // disconnect from the socket + { + std::lock_guard locker(m_lock); + + if (m_sock < 0) + return; + + disconnectNoLock(); + } + + // wake the wait(...) call so client code is blocked there it is woken + if (m_eventFd >= 0) + { + uint64_t wakeup = 1; + if (TEMP_FAILURE_RETRY(write(m_eventFd, &wakeup, sizeof(wakeup))) != sizeof(wakeup)) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to write to wake event fd"); + } + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + + */ +void ChannelImpl::disconnectNoLock() +{ + if (m_sock < 0) + { + RIALTO_IPC_LOG_WARN("not connected\n"); + return; + } + + // remove the socket from epoll + if (epoll_ctl(m_epollFd, EPOLL_CTL_DEL, m_sock, nullptr) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to remove socket"); + } + + // shutdown and close the socket + if (shutdown(m_sock, SHUT_RDWR) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "shutdown error"); + } + if (close(m_sock) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "close error"); + } + + m_sock = -1; +} + +bool ChannelImpl::isConnected() const +{ + return isConnectedInternal(); +} + +bool ChannelImpl::isConnectedInternal() const +{ + std::lock_guard locker(m_lock); + return (m_sock >= 0); +} + +int ChannelImpl::fd() const +{ + return m_epollFd; +} + +bool ChannelImpl::wait(int timeoutMSecs) +{ + if ((m_epollFd < 0) || !isConnected()) + { + return false; + } + + // wait for any event (with timeout) + struct pollfd fds[2]; + fds[0].fd = m_epollFd; + fds[0].events = POLLIN; + + int rc = TEMP_FAILURE_RETRY(poll(fds, 1, timeoutMSecs)); + if (rc < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "poll failed?"); + return false; + } + + return isConnected(); +} + +bool ChannelImpl::process() +{ + if (!isConnected()) + return false; + + struct epoll_event events[3]; + int rc = TEMP_FAILURE_RETRY(epoll_wait(m_epollFd, events, 3, 0)); + if (rc < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_wait failed"); + return false; + } + + enum + { + HaveSocketEvent = 0x1, + HaveTimeoutEvent = 0x2, + HaveWakeEvent = 0x4 + }; + unsigned eventsMask = 0; + for (int i = 0; i < rc; i++) + { + if (events[i].data.fd == m_sock) + eventsMask |= HaveSocketEvent; + else if (events[i].data.fd == m_timerFd) + eventsMask |= HaveTimeoutEvent; + else if (events[i].data.fd == m_eventFd) + eventsMask |= HaveWakeEvent; + } + + if ((eventsMask & HaveSocketEvent) && !processSocketEvent()) + { + std::map callsToDelete; + { + std::lock_guard locker(m_lock); + callsToDelete = m_methodCalls; + m_methodCalls.clear(); + } + + for (auto &entry : callsToDelete) + { + completeWithError(&entry.second, "Socket down"); + } + return false; + } + + if (eventsMask & HaveTimeoutEvent) + processTimeoutEvent(); + + if (eventsMask & HaveWakeEvent) + processWakeEvent(); + + return isConnected(); +} + +bool ChannelImpl::unsubscribe(int eventTag) +{ + std::lock_guard locker(m_eventsLock); + bool success = false; + + auto it = std::find_if(m_eventHandlers.begin(), m_eventHandlers.end(), + [&](const auto &item) { return item.second.id == eventTag; }); + if (m_eventHandlers.end() != it) + { + m_eventHandlers.erase(it); + success = true; + } + + return success; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + + */ +bool ChannelImpl::processSocketEvent() +{ + static std::mutex bufLock; + std::lock_guard bufLocker(bufLock); + + static std::vector dataBuf(kMaxMessageSize); + static std::vector ctrlBuf(CMSG_SPACE(SCM_MAX_FD * sizeof(int))); + + // read all messages from the client socket, we break out if the socket is closed + // or EWOULDBLOCK is returned on a read (ie. no more messages to read) + while (true) + { + struct msghdr msg = {nullptr}; + struct iovec io = {.iov_base = dataBuf.data(), .iov_len = dataBuf.size()}; + + bzero(&msg, sizeof(msg)); + msg.msg_iov = &io; + msg.msg_iovlen = 1; + msg.msg_control = ctrlBuf.data(); + msg.msg_controllen = ctrlBuf.size(); + + // read one message + ssize_t rd = TEMP_FAILURE_RETRY(recvmsg(m_sock, &msg, MSG_CMSG_CLOEXEC)); + if (rd < 0) + { + if (errno != EWOULDBLOCK) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "error reading client socket"); + + std::lock_guard locker(m_lock); + disconnectNoLock(); + return false; + } + + break; + } + else if (rd == 0) + { + // server closed connection, and we've read all data + RIALTO_IPC_LOG_INFO("socket remote end closed, disconnecting channel"); + + std::lock_guard locker(m_lock); + disconnectNoLock(); + return false; + } + else if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) + { + RIALTO_IPC_LOG_WARN("received truncated message from server, discarding"); + + // make sure to close all the fds, otherwise we'll leak them, this + // will read the fds and return in a vector, which will then be + // destroyed, closing all the fds + readMessageFds(&msg, 16); + } + else + { + // if there is control data then assume fd(s) have been passed + std::vector fds; + if (msg.msg_controllen > 0) + { + fds = readMessageFds(&msg, 32); + } + + // process the message from the server + processServerMessage(dataBuf.data(), rd, &fds); + } + } + + return true; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Called from process() to check if the timerfd has expired and if so cancel + the any outstanding method calls that have now timed-out. + + */ +void ChannelImpl::processTimeoutEvent() +{ + // read the timerfd to clear any expirations + uint64_t expirations; + ssize_t rd = TEMP_FAILURE_RETRY(read(m_timerFd, &expirations, sizeof(expirations))); + if (rd < 0) + { + if (errno != EWOULDBLOCK) + RIALTO_IPC_LOG_SYS_ERROR(errno, "error reading timerfd"); + return; + } + + // check if any method call has no expired + std::unique_lock locker(m_lock); + + // stores the timed-out method calls + std::vector timedOuts; + + // remove the method calls that have expired + const auto kNow = std::chrono::steady_clock::now(); + auto it = m_methodCalls.begin(); + while (it != m_methodCalls.end()) + { + if (kNow >= it->second.timeoutDeadline) + { + timedOuts.emplace_back(it->second); + it = m_methodCalls.erase(it); + } + else + { + ++it; + } + } + + // if we still have method calls available, then re-calculate the timer for the next timeout + if (!m_methodCalls.empty()) + { + updateTimeoutTimer(); + } + + // drop the lock and now terminate the timed out method calls + locker.unlock(); + + for (auto &call : timedOuts) + { + completeWithError(&call, "Timed out"); + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Called from process() when the eventfd was used to wake the event loop. All + the function does is read the eventfd to clear it's value. + + */ +void ChannelImpl::processWakeEvent() +{ + uint64_t ignore; + if (TEMP_FAILURE_RETRY(read(m_eventFd, &ignore, sizeof(ignore))) != sizeof(ignore)) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "Failed to read wake eventfd to clear it"); + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Updates the timerfd to the time of the next method call timeout. If method + calls are pending then the timer is disabled. + + This should be called whenever a new method is called or a method has + completed. + + \note Must be called while holding the m_lock mutex. + + */ +void ChannelImpl::updateTimeoutTimer() +{ + struct itimerspec ts = {{0}}; + + // if no method calls then just disarm the timer + if (!m_methodCalls.empty()) + { + // otherwise, find the next soonest timeout + std::chrono::steady_clock::time_point nextTimeout = std::chrono::steady_clock::time_point::max(); + auto nextTimeoutCall = + std::min_element(m_methodCalls.begin(), m_methodCalls.end(), [](const auto &elem, const auto ¤tMin) + { return elem.second.timeoutDeadline < currentMin.second.timeoutDeadline; }); + if (nextTimeoutCall != m_methodCalls.end()) + { + nextTimeout = nextTimeoutCall->second.timeoutDeadline; + } + + // set the timerfd to the next duration + const std::chrono::microseconds kDuration = + std::chrono::duration_cast(nextTimeout - std::chrono::steady_clock::now()); + if (kDuration <= std::chrono::microseconds::zero()) + { + ts.it_value.tv_nsec = 1000; + } + else + { + ts.it_value.tv_sec = static_cast(std::chrono::duration_cast(kDuration).count()); + ts.it_value.tv_nsec = static_cast((kDuration.count() % 1000000) * 1000); + } + + RIALTO_IPC_LOG_DEBUG("next timeout in %" PRId64 "us - %ld.%09lds", kDuration.count(), ts.it_value.tv_sec, + ts.it_value.tv_nsec); + } + + // write the timeout value + if (timerfd_settime(m_timerFd, 0, &ts, nullptr) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to write to timerfd"); + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Processes a single message from the server, it may be a method call response + or an event. + + + */ +void ChannelImpl::processServerMessage(const uint8_t *data, size_t dataLen, std::vector *fds) +{ + // parse the message + transport::MessageFromServer message; + if (!message.ParseFromArray(data, static_cast(dataLen))) + { + RIALTO_IPC_LOG_ERROR("invalid message from server"); + return; + } + + // check if an event or a reply to a request + if (message.has_reply()) + { + processReplyFromServer(message.reply(), fds); + } + else if (message.has_error()) + { + processErrorFromServer(message.error()); + } + else if (message.has_event()) + { + processEventFromServer(message.event(), fds); + } + else + { + RIALTO_IPC_LOG_ERROR("message from server is missing reply or event type"); + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + + */ +void ChannelImpl::processReplyFromServer(const transport::MethodCallReply &reply, std::vector *fds) +{ + RIALTO_IPC_LOG_DEBUG("processing reply from server"); + + std::unique_lock locker(m_lock); + + // find the original request + const uint64_t kSerialId = reply.reply_id(); + auto it = m_methodCalls.find(kSerialId); + if (it == m_methodCalls.end()) + { + RIALTO_IPC_LOG_ERROR("failed to find request for received reply with id %" PRIu64 "", reply.reply_id()); + return; + } + + // take the method call and remove from the map of outstanding calls + MethodCall methodCall = it->second; + m_methodCalls.erase(it); + + // update the timeout timer now a method call has been processed + updateTimeoutTimer(); + + // can now drop the lock + locker.unlock(); + + // this is an actual reply so try and read it + if (!methodCall.response->ParseFromString(reply.reply_message())) + { + RIALTO_IPC_LOG_ERROR("failed to parse method reply from server"); + completeWithError(&methodCall, "Failed to parse reply message"); + } + else if (!addReplyFileDescriptors(methodCall.response, fds)) + { + RIALTO_IPC_LOG_ERROR("mismatch of file descriptors to the reply"); + completeWithError(&methodCall, "Mismatched file descriptors in message"); + } + else if (methodCall.closure) + { + RIALTO_IPC_LOG_DEBUG("reply{ serial %" PRIu64 " } - %s { %s }", kSerialId, + methodCall.response->GetTypeName().c_str(), methodCall.response->ShortDebugString().c_str()); + + complete(&methodCall); + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + + */ +void ChannelImpl::processErrorFromServer(const transport::MethodCallError &error) +{ + RIALTO_IPC_LOG_DEBUG("processing error from server"); + + std::unique_lock locker(m_lock); + + // find the original request + const uint64_t kSerialId = error.reply_id(); + auto it = m_methodCalls.find(kSerialId); + if (it == m_methodCalls.end()) + { + RIALTO_IPC_LOG_ERROR("failed to find request for received reply with id %" PRIu64 "", error.reply_id()); + return; + } + + // take the method call and remove from the map of outstanding calls + MethodCall methodCall = it->second; + m_methodCalls.erase(it); + + // update the timeout timer now a method call has been processed + updateTimeoutTimer(); + + // can now drop the lock + locker.unlock(); + + RIALTO_IPC_LOG_DEBUG("error{ serial %" PRIu64 " } - %s", kSerialId, error.error_reason().c_str()); + + // complete the call with an error + completeWithError(&methodCall, error.error_reason()); +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + + */ +void ChannelImpl::processEventFromServer(const transport::EventFromServer &event, std::vector *fds) +{ + RIALTO_IPC_LOG_DEBUG("processing event from server"); + + const std::string &kEventName = event.event_name(); + + std::lock_guard locker(m_eventsLock); + + auto range = m_eventHandlers.equal_range(kEventName); + if (range.first == range.second) + { + RIALTO_IPC_LOG_WARN("no handler for event %s", kEventName.c_str()); + return; + } + + const google::protobuf::Descriptor *kDescriptor = range.first->second.descriptor; + + const google::protobuf::Message *kPrototype = + google::protobuf::MessageFactory::generated_factory()->GetPrototype(kDescriptor); + if (!kPrototype) + { + RIALTO_IPC_LOG_ERROR("failed to create prototype for event %s", kEventName.c_str()); + return; + } + + std::shared_ptr message(kPrototype->New()); + if (!message) + { + RIALTO_IPC_LOG_ERROR("failed to create mutable message from prototype"); + return; + } + + if (!message->ParseFromString(event.message())) + { + RIALTO_IPC_LOG_ERROR("failed to parse message for event %s", kEventName.c_str()); + } + else if (!addReplyFileDescriptors(message.get(), fds)) + { + RIALTO_IPC_LOG_ERROR("mismatch of file descriptors to the reply"); + } + else + { + RIALTO_IPC_LOG_DEBUG("event{ %s } - %s { %s }", kEventName.c_str(), message->GetTypeName().c_str(), + message->ShortDebugString().c_str()); + + for (auto it = range.first; it != range.second; ++it) + { + it->second.handler(message); + } + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + \static + + Reads all the file descriptors from a unix domain socket received \a msg. + It returns the file descriptors as a vector of FileDescriptor objects, + these objects safely store the fd and close them when they're destructed. + + The \a limit specifies the maximum number of fds to store, if more were + sent then they are automatically closed and not returned in the vector. + + */ +std::vector ChannelImpl::readMessageFds(const struct msghdr *msg, size_t limit) +{ + std::vector fds; + + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != nullptr; + cmsg = CMSG_NXTHDR(const_cast(msg), cmsg)) + { + if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) + { + const unsigned kFdsLength = cmsg->cmsg_len - CMSG_LEN(0); + if ((kFdsLength < sizeof(int)) || ((kFdsLength % sizeof(int)) != 0)) + { + RIALTO_IPC_LOG_ERROR("invalid fd array size"); + } + else + { + const size_t n = kFdsLength / sizeof(int); + RIALTO_IPC_LOG_DEBUG("received %zu fds", n); + + fds.reserve(std::min(limit, n)); + + const int *kFds = reinterpret_cast(CMSG_DATA(cmsg)); + for (size_t i = 0; i < n; i++) + { + RIALTO_IPC_LOG_DEBUG("received fd %d", kFds[i]); + + if (fds.size() >= limit) + { + RIALTO_IPC_LOG_ERROR( + "received to many file descriptors, exceeding max per message, closing left overs"); + } + else + { + firebolt::rialto::ipc::FileDescriptor fileDescriptor(kFds[i]); + if (!fileDescriptor.isValid()) + { + RIALTO_IPC_LOG_ERROR("received invalid fd (couldn't dup)"); + } + else + { + fds.emplace_back(std::move(fileDescriptor)); + } + } + + if (close(kFds[i]) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close received fd"); + } + } + } + } + + return fds; +} + +// ----------------------------------------------------------------------------- +/*! + \static + \internal + + Places the received file descriptors into the protobuf message. + + It works by iterating over the fields in the message, finding ones that are + marked as 'field_is_fd' and then replacing the received integer value with + an actual file descriptor. + + */ +bool ChannelImpl::addReplyFileDescriptors(google::protobuf::Message *reply, + std::vector *fds) +{ + auto fdIterator = fds->begin(); + + const google::protobuf::Descriptor *kDescriptor = reply->GetDescriptor(); + const google::protobuf::Reflection *kReflection = nullptr; + + const int n = kDescriptor->field_count(); + for (int i = 0; i < n; i++) + { + auto fieldDescriptor = kDescriptor->field(i); + if (fieldDescriptor->options().HasExtension(::firebolt::rialto::ipc::field_is_fd) && + fieldDescriptor->options().GetExtension(::firebolt::rialto::ipc::field_is_fd)) + { + if (fieldDescriptor->type() != google::protobuf::FieldDescriptor::TYPE_INT32) + { + RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but not an int32 type"); + return false; + } + + if (!kReflection) + { + kReflection = reply->GetReflection(); + } + + if (kReflection->HasField(*reply, fieldDescriptor)) + { + if (fdIterator == fds->end()) + { + RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but none or too few were supplied"); + return false; + } + + kReflection->SetInt32(reply, fieldDescriptor, fdIterator->fd()); + ++fdIterator; + } + } + } + + if (fdIterator != fds->end()) + { + RIALTO_IPC_LOG_ERROR("received too many file descriptors in the message"); + return false; + } + + // we now need to release all the fds stored in the vector, otherwise they + // will be closed when the vector is destroyed. From now onwards it is the + // caller's responsibility to close the fds in the returned protobuf message + // object + for (firebolt::rialto::ipc::FileDescriptor &fd : *fds) + { + fd.release(); + } + + return true; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + \static + + + */ +void ChannelImpl::complete(MethodCall *call) +{ + if (call->closure) + { + call->closure->Run(); + call->closure = nullptr; + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + \static + + + */ +void ChannelImpl::completeWithError(MethodCall *call, std::string reason) +{ + RIALTO_IPC_LOG_DEBUG("completing method call with error '%s'", reason.c_str()); + + if (call->controller) + { + call->controller->setMethodCallFailed(std::move(reason)); + call->controller = nullptr; + } + + if (call->closure) + { + call->closure->Run(); + call->closure = nullptr; + } +} + +// ----------------------------------------------------------------------------- +/*! + \static + + Iterates through the message and finds any file descriptor type fields, if + found it adds the fds to the returned vector. + + */ +std::vector ChannelImpl::getMessageFds(const google::protobuf::Message &message) +{ + std::vector fds; + + auto descriptor = message.GetDescriptor(); + const int n = descriptor->field_count(); + for (int i = 0; i < n; i++) + { + auto fieldDescriptor = descriptor->field(i); + if (fieldDescriptor->options().HasExtension(::firebolt::rialto::ipc::field_is_fd) && + fieldDescriptor->options().GetExtension(::firebolt::rialto::ipc::field_is_fd)) + { + if (fieldDescriptor->type() != google::protobuf::FieldDescriptor::TYPE_INT32) + { + RIALTO_IPC_LOG_ERROR("field '%s' is marked as containing an fd but not an int32 type", + fieldDescriptor->full_name().c_str()); + } + else + { + auto reflection = message.GetReflection(); + int fileDescriptor = reflection->GetInt32(message, fieldDescriptor); + fds.emplace_back(fileDescriptor); + } + } + } + + return fds; +} + +// ----------------------------------------------------------------------------- +/*! + \overload + + \quote + Call the given method of the remote service. The signature of this + procedure looks the same as Service::CallMethod(), but the requirements + are less strict in one important way: the request and response objects + need not be of any specific class as long as their descriptors are + method->input_type() and method->output_type(). + + */ +void ChannelImpl::CallMethod(const google::protobuf::MethodDescriptor *method, // NOLINT(build/function_format) + google::protobuf::RpcController *controller, const google::protobuf::Message *request, + google::protobuf::Message *response, google::protobuf::Closure *done) +{ + MethodCall methodCall{std::chrono::steady_clock::now() + m_timeout, + dynamic_cast(controller), response, done}; + + // + const uint64_t kSerialId = m_serialCounter++; + + // create the transport request + transport::MessageToServer message; + transport::MethodCall *call = message.mutable_call(); + call->set_serial_id(kSerialId); + call->set_service_name(method->service()->full_name()); + call->set_method_name(method->name()); + + // copy in the actual message data + std::string reqString = request->SerializeAsString(); + call->set_request_message(std::move(reqString)); + + const size_t kRequiredDataLen = message.ByteSizeLong(); + if (kRequiredDataLen > kMaxMessageSize) + { + RIALTO_IPC_LOG_ERROR("method call to big to send (%zu, max %zu", kRequiredDataLen, kMaxMessageSize); + completeWithError(&methodCall, "Method call to big"); + return; + } + + // extract the fds from the message + const std::vector kFds = getMessageFds(*request); + const size_t kRequiredCtrlLen = kFds.empty() ? 0 : CMSG_SPACE(sizeof(int) * kFds.size()); + + // build the socket message to send + auto msgBuf = + m_sendBufPool.allocateShared(sizeof(msghdr) + sizeof(iovec) + kRequiredCtrlLen + kRequiredDataLen); + + auto *header = reinterpret_cast(msgBuf.get()); + bzero(header, sizeof(msghdr)); + + auto *ctrl = reinterpret_cast(msgBuf.get() + sizeof(msghdr)); + header->msg_control = ctrl; + header->msg_controllen = kRequiredCtrlLen; + + auto *iov = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen); + header->msg_iov = iov; + header->msg_iovlen = 1; + + auto *data = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen + sizeof(iovec)); + iov->iov_base = data; + iov->iov_len = kRequiredDataLen; + + // copy in the data + message.SerializeWithCachedSizesToArray(data); + + // next check if the request is sending any fd's + if (!kFds.empty()) + { + struct cmsghdr *cmsg = CMSG_FIRSTHDR(header); + if (!cmsg) + { + RIALTO_IPC_LOG_ERROR("odd, failed to get the first cmsg header"); + completeWithError(&methodCall, "Internal error"); + return; + } + + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int) * kFds.size()); + memcpy(CMSG_DATA(cmsg), kFds.data(), sizeof(int) * kFds.size()); + header->msg_controllen = cmsg->cmsg_len; + } + + // check if the method is expecting a reply + const bool kNoReplyExpected = method->options().HasExtension(::firebolt::rialto::ipc::no_reply) && + method->options().GetExtension(::firebolt::rialto::ipc::no_reply); + + // finally, send the message + std::unique_lock locker(m_lock); + + if (m_sock < 0) + { + locker.unlock(); + completeWithError(&methodCall, "Not connected"); + } + else if (sendmsg(m_sock, header, MSG_NOSIGNAL) != static_cast(kRequiredDataLen)) + { + locker.unlock(); + completeWithError(&methodCall, "Failed to send message"); + } + else + { + RIALTO_IPC_LOG_DEBUG("call{ serial %" PRIu64 " } - %s.%s { %s }", kSerialId, call->service_name().c_str(), + call->method_name().c_str(), request->ShortDebugString().c_str()); + + if (kNoReplyExpected) + { + // no reply from server is expected, however if the caller supplied + // a closure (it shouldn't) we should still call it now to indicate + // the method call has been made + if (done) + done->Run(); + } + else + { + // add the message to the queue so we pick-up the reply + m_methodCalls.emplace(kSerialId, methodCall); + + // update the single timeout timer + updateTimeoutTimer(); + } + } +} + +int ChannelImpl::subscribeImpl(const std::string &kEventName, const google::protobuf::Descriptor *descriptor, + EventHandler &&handler) +{ + std::lock_guard locker(m_eventsLock); + + const int kTag = m_eventTagCounter++; + m_eventHandlers.emplace(kEventName, Event{kTag, descriptor, std::move(handler)}); + + return kTag; +} +}; // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/client/source/IpcChannelImpl.h b/middleware/rialto-client/ipc/client/source/IpcChannelImpl.h new file mode 100644 index 000000000..a19cfdce9 --- /dev/null +++ b/middleware/rialto-client/ipc/client/source/IpcChannelImpl.h @@ -0,0 +1,147 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_IPC_CHANNEL_IMPL_H_ +#define FIREBOLT_RIALTO_IPC_IPC_CHANNEL_IMPL_H_ + +#include "FileDescriptor.h" +#include "IIpcChannel.h" +#include "IpcClientControllerImpl.h" +#include "SimpleBufferPool.h" + +#include "rialtoipc-transport.pb.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace firebolt::rialto::ipc +{ +class ChannelFactory : public IChannelFactory +{ +public: + ChannelFactory() = default; + ~ChannelFactory() override = default; + + std::shared_ptr createChannel(int sockFd) override; + std::shared_ptr createChannel(const std::string &socketPath) override; +}; + +class ChannelImpl final : public IChannel +{ +public: + explicit ChannelImpl(int sockFd); + explicit ChannelImpl(const std::string &socketPath); + ~ChannelImpl() final; + + void disconnect() override; + bool isConnected() const override; + + int fd() const override; + bool wait(int timeoutMSecs) override; + bool process() override; + bool unsubscribe(int eventTag) override; + + void CallMethod(const google::protobuf::MethodDescriptor *method, google::protobuf::RpcController *controller, + const google::protobuf::Message *request, google::protobuf::Message *response, + google::protobuf::Closure *done) override; + + using EventHandler = std::function &msg)>; + + int subscribeImpl(const std::string &name, const google::protobuf::Descriptor *descriptor, + EventHandler &&handler) override; + +private: + void disconnectNoLock(); + + bool processSocketEvent(); + void processTimeoutEvent(); + void processWakeEvent(); + + void processServerMessage(const uint8_t *data, size_t len, std::vector *fds); + void processReplyFromServer(const ::firebolt::rialto::ipc::transport::MethodCallReply &reply, + std::vector *fds); + void processErrorFromServer(const ::firebolt::rialto::ipc::transport::MethodCallError &error); + void processEventFromServer(const ::firebolt::rialto::ipc::transport::EventFromServer &event, + std::vector *fds); + + bool createConnectedSocket(const std::string &socketPath); + bool attachSocket(int sockFd); + bool initChannel(); + void termChannel(); + bool isConnectedInternal() const; // to avoid calling virtual method in constructor + + static std::vector readMessageFds(const struct msghdr *msg, size_t limit); + static std::vector getMessageFds(const google::protobuf::Message &message); + + static bool addReplyFileDescriptors(google::protobuf::Message *reply, std::vector *fds); + + struct MethodCall + { + std::chrono::steady_clock::time_point timeoutDeadline; + ClientControllerImpl *controller = nullptr; + google::protobuf::Message *response = nullptr; + google::protobuf::Closure *closure = nullptr; + }; + + void updateTimeoutTimer(); + + static void complete(MethodCall *call); + static void completeWithError(MethodCall *call, std::string reason); + +private: + int m_sock; + int m_epollFd; + int m_timerFd; + int m_eventFd; + + SimpleBufferPool m_sendBufPool; + + mutable std::mutex m_lock; + std::atomic m_serialCounter; + + const std::chrono::milliseconds m_timeout; + + std::map m_methodCalls; + + std::mutex m_eventsLock; + + int m_eventTagCounter; + + struct Event + { + int id; + const google::protobuf::Descriptor *descriptor; + EventHandler handler; + }; + + std::multimap m_eventHandlers; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_IPC_CHANNEL_IMPL_H_ diff --git a/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.cpp b/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.cpp new file mode 100644 index 000000000..91d3b27d9 --- /dev/null +++ b/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.cpp @@ -0,0 +1,146 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IpcClientControllerImpl.h" +#include "IpcControllerFactory.h" +#include "IpcLogging.h" +#include +#include + +namespace firebolt::rialto::ipc +{ +std::shared_ptr IControllerFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Failed to create the controller factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr ControllerFactory::create() +{ + return std::make_shared(); +} + +// ----------------------------------------------------------------------------- +/*! + \overload + + \quote + Resets the RpcController to its initial state so that it may be reused in + a new call. Must not be called while an RPC is in progress. + + + */ +void ClientControllerImpl::Reset() // NOLINT(build/function_format) +{ + std::lock_guard locker(m_lock); + m_failed = false; + m_reason.clear(); +} + +// ----------------------------------------------------------------------------- +/*! + \overload + + \quote + After a call has finished, returns true if the call failed. The possible + reasons for failure depend on the RPC implementation. Failed() must not + be called before a call has finished. If Failed() returns true, the + contents of the response message are undefined. + + */ +bool ClientControllerImpl::Failed() const // NOLINT(build/function_format) +{ + std::lock_guard locker(m_lock); + return m_failed; +} + +// ----------------------------------------------------------------------------- +/*! + \overload + + \quote + If Failed() is true, returns a human-readable description of the error. + + */ +std::string ClientControllerImpl::ErrorText() const // NOLINT(build/function_format) +{ + std::lock_guard locker(m_lock); + return m_reason; +} + +// ----------------------------------------------------------------------------- +/*! + \overload + \warning Not implemented + + \quote + Advises the RPC system that the caller desires that the RPC call be + canceled. The RPC system may cancel it immediately, may wait awhile and + then cancel it, or may not even cancel the call at all. If the call is + canceled, the "done" callback will still be called and the RpcController + will indicate that the call failed at that time. + + */ +void ClientControllerImpl::StartCancel() // NOLINT(build/function_format) +{ + RIALTO_IPC_LOG_WARN("Cancel not implemented"); +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Called from RialtoIpcChannelImpl when a method call failed for any reason. + + */ +void ClientControllerImpl::setMethodCallFailed(std::string reason) +{ + std::lock_guard locker(m_lock); + m_failed = true; + m_reason = std::move(reason); +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Called from RialtoIpcChannelImpl when a method call failed for any reason. + + */ +void ClientControllerImpl::setMethodCallFailed(const char *format, va_list ap) +{ + char buf[512]; + vsnprintf(buf, sizeof(buf), format, ap); + + std::lock_guard locker(m_lock); + m_failed = true; + m_reason.assign(buf); +} + +} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.h b/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.h new file mode 100644 index 000000000..61ce8fcd3 --- /dev/null +++ b/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.h @@ -0,0 +1,130 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_IPC_CLIENT_CONTROLLER_IMPL_H_ +#define FIREBOLT_RIALTO_IPC_IPC_CLIENT_CONTROLLER_IMPL_H_ + +#include + +#include +#include +#include + +namespace firebolt::rialto::ipc +{ +class ClientControllerImpl final : public google::protobuf::RpcController +{ +public: + ClientControllerImpl() = default; + ~ClientControllerImpl() final = default; + + /** + * Client-side methods + * Calls can only be made from the client side. Calling these apis from server side + * is undefined and could cause crashes. + */ + + /** + * @brief Reset the RpcController. + * + * So that the RpcController can be reused for a new call, sets to the inital state. + */ + void Reset() override; + + /** + * @brief Checks id the previosu call has failed. + * + * The reason for the failure depends on the implementaion of the RPC. Failed should only + * be called after after the call has finished. If this call returns true, the response + * structure returned from the failed call is undefined. + * + * @retval true if previous call failed. + */ + bool Failed() const override; + + /** + * @brief Returns a description of the error if the previous call has failed. + * + * @retval error string. + */ + std::string ErrorText() const override; + + /** + * @brief Starts the cancellation of a RPC call + * + * RPC may cancel the call immediatly, wait and cancel or not cancel at all. If a call is cancelled + * failure will be set for the client and "done" will still be called. + */ + void StartCancel() override; + + /** + * Server-side methods + * Calls can only be made from the server side. Calling these apis from client side + * is undefined and could cause crashes. + */ + + /** + * @brief Causes failure to be returned to the client. + * + * Failed() shall return true. The failure reason can be fetched from the ErrorText(). + * To return machine-readable info on failure, use the method response structure rather than + * SetFailed(). + * + * @param[in] reason : The reason for the falure. + */ + void SetFailed(const std::string &reason) override { (void)reason; } + + /** + * @brief Check if the client had cancelled the RPC. + * + * If true, indicates that the client canceled the RPC, so the server may + * as well give up on replying to it. The server should still call the + * final "done" callback. + * + * @retval true of cancelled, false otherwise. + */ + bool IsCanceled() const override { return false; } + + /** + * @brief Request a notification when RPC is cancelled. + * + * The callback will always be called exactly once. If the RPC completes without + * being canceled, the callback will be called after completion. If the RPC + * has already been canceled when NotifyOnCancel() is called, the callback + * will be called immediately. + * + * @param[in] callback : Callback method on cancelled. + */ + void NotifyOnCancel(google::protobuf::Closure *callback) override { (void)callback; } + +private: + friend class ChannelImpl; + + void setMethodCallFailed(std::string reason); + void setMethodCallFailed(const char *format, va_list ap) __attribute__((format(printf, 2, 0))); + +private: + mutable std::mutex m_lock; + bool m_failed = false; + std::string m_reason; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_IPC_CLIENT_CONTROLLER_IMPL_H_ diff --git a/middleware/rialto-client/ipc/client/source/IpcControllerFactory.h b/middleware/rialto-client/ipc/client/source/IpcControllerFactory.h new file mode 100644 index 000000000..1555fc458 --- /dev/null +++ b/middleware/rialto-client/ipc/client/source/IpcControllerFactory.h @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_IPC_CONTROLLER_FACTORY_H_ +#define FIREBOLT_RIALTO_IPC_IPC_CONTROLLER_FACTORY_H_ + +#include + +#include "IIpcControllerFactory.h" +#include + +namespace firebolt::rialto::ipc +{ +class ControllerFactory : public IControllerFactory +{ +public: + ControllerFactory() = default; + ~ControllerFactory() = default; + + std::shared_ptr create() override; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_IPC_CONTROLLER_FACTORY_H_ diff --git a/middleware/rialto-client/ipc/common/CMakeLists.txt b/middleware/rialto-client/ipc/common/CMakeLists.txt new file mode 100644 index 000000000..c2adf6395 --- /dev/null +++ b/middleware/rialto-client/ipc/common/CMakeLists.txt @@ -0,0 +1,59 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Find includes in corresponding build directories +set( CMAKE_INCLUDE_CURRENT_DIR ON ) + + +add_library( + RialtoIpcCommon + STATIC + + source/FileDescriptor.cpp + source/SimpleBufferPool.cpp + source/NamedSocket.cpp + + ) + +target_include_directories( + RialtoIpcCommon + + PUBLIC + include + $ + + PRIVATE + source + + ) + + +set_property( + TARGET RialtoIpcCommon + PROPERTY POSITION_INDEPENDENT_CODE ON + + ) + +target_link_libraries( + RialtoIpcCommon + + PRIVATE + RialtoProtobuf + + ) diff --git a/middleware/rialto-client/ipc/common/include/INamedSocket.h b/middleware/rialto-client/ipc/common/include/INamedSocket.h new file mode 100644 index 000000000..170a50b26 --- /dev/null +++ b/middleware/rialto-client/ipc/common/include/INamedSocket.h @@ -0,0 +1,52 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_I_NAMED_SOCKET_H_ +#define FIREBOLT_RIALTO_IPC_I_NAMED_SOCKET_H_ + +#include +#include + +namespace firebolt::rialto::ipc +{ +class INamedSocket; + +class INamedSocketFactory +{ +public: + virtual ~INamedSocketFactory() = default; + + static INamedSocketFactory &getFactory(); + virtual std::unique_ptr createNamedSocket() const = 0; + virtual std::unique_ptr createNamedSocket(const std::string &socketPath) const = 0; +}; + +class INamedSocket +{ +public: + virtual ~INamedSocket() = default; + virtual int getFd() const = 0; + virtual bool setSocketPermissions(unsigned int socketPermissions) const = 0; + virtual bool setSocketOwnership(const std::string &socketOwner, const std::string &socketGroup) const = 0; + virtual bool blockNewConnections() const = 0; + virtual bool bind(const std::string &socketPath) = 0; +}; +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_I_NAMED_SOCKET_H_ diff --git a/middleware/rialto-client/ipc/common/proto/rialtoipc-transport.proto b/middleware/rialto-client/ipc/common/proto/rialtoipc-transport.proto new file mode 120000 index 000000000..6225e1f25 --- /dev/null +++ b/middleware/rialto-client/ipc/common/proto/rialtoipc-transport.proto @@ -0,0 +1 @@ +../../../proto/rialtoipc-transport.proto \ No newline at end of file diff --git a/middleware/rialto-client/ipc/common/proto/rialtoipc.proto b/middleware/rialto-client/ipc/common/proto/rialtoipc.proto new file mode 120000 index 000000000..274045422 --- /dev/null +++ b/middleware/rialto-client/ipc/common/proto/rialtoipc.proto @@ -0,0 +1 @@ +../../../proto/rialtoipc.proto \ No newline at end of file diff --git a/middleware/rialto-client/ipc/common/source/FileDescriptor.cpp b/middleware/rialto-client/ipc/common/source/FileDescriptor.cpp new file mode 100644 index 000000000..88cd67507 --- /dev/null +++ b/middleware/rialto-client/ipc/common/source/FileDescriptor.cpp @@ -0,0 +1,126 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FileDescriptor.h" +#include "IpcLogging.h" + +#include +#include +#include + +namespace firebolt::rialto::ipc +{ +FileDescriptor::FileDescriptor() : m_fd(-1) {} + +FileDescriptor::FileDescriptor(int fd) : m_fd(-1) +{ + if (fd >= 0) + { + m_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (m_fd < 0) + RIALTO_IPC_LOG_SYS_WARN(errno, "failed to dup supplied fd"); + } +} + +FileDescriptor::FileDescriptor(const FileDescriptor &other) : m_fd(-1) +{ + if (other.m_fd >= 0) + { + m_fd = fcntl(other.m_fd, F_DUPFD_CLOEXEC, 3); + if (m_fd < 0) + RIALTO_IPC_LOG_SYS_WARN(errno, "failed to dup supplied fd"); + } +} + +FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other) noexcept +{ + if ((m_fd >= 0) && (::close(m_fd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close file descriptor"); + + m_fd = other.m_fd; + other.m_fd = -1; + + return *this; +} + +FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other) +{ + if (this == &other) + return *this; + + if ((m_fd >= 0) && (::close(m_fd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close file descriptor"); + + m_fd = -1; + + if (other.m_fd >= 0) + { + m_fd = fcntl(other.m_fd, F_DUPFD_CLOEXEC, 3); + if (m_fd < 0) + RIALTO_IPC_LOG_SYS_WARN(errno, "failed to dup supplied fd"); + } + + return *this; +} + +FileDescriptor::~FileDescriptor() +{ + reset(); +} + +bool FileDescriptor::isValid() const +{ + return (m_fd >= 0); +} + +int FileDescriptor::fd() const +{ + return m_fd; +} + +void FileDescriptor::reset(int fd) +{ + if ((m_fd >= 0) && (::close(m_fd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close file descriptor"); + + if (fd < 0) + { + m_fd = -1; + } + else + { + m_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); + if (m_fd < 0) + RIALTO_IPC_LOG_SYS_WARN(errno, "failed to dup supplied fd"); + } +} + +void FileDescriptor::clear() +{ + reset(); +} + +int FileDescriptor::release() +{ + int descriptor = m_fd; + m_fd = -1; + return descriptor; +} + +} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/common/source/FileDescriptor.h b/middleware/rialto-client/ipc/common/source/FileDescriptor.h new file mode 100644 index 000000000..2d01f81d4 --- /dev/null +++ b/middleware/rialto-client/ipc/common/source/FileDescriptor.h @@ -0,0 +1,66 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_FILE_DESCRIPTOR_H_ +#define FIREBOLT_RIALTO_IPC_FILE_DESCRIPTOR_H_ + +// ----------------------------------------------------------------------------- +/*! + \class FileDescriptor + \brief Light wrapper around a file descriptor so it can be used safely. + + Why do we need this? Because we want to safely pass a file descriptor + around. + + Why not just use an integer? Because although it's obviously fine to pass + an integer around there is no guarantee that the descriptor is still valid + when it's used. This class uses \c dup(2) to ensure that if the object was + created with a valid file descriptor in the first place then it and all copy + constructed objects will have a valid file descriptor. + +*/ + +namespace firebolt::rialto::ipc +{ +class FileDescriptor +{ +public: + FileDescriptor(); + explicit FileDescriptor(int fd); + FileDescriptor(const FileDescriptor &other); + FileDescriptor &operator=(FileDescriptor &&other) noexcept; + FileDescriptor &operator=(const FileDescriptor &other); + ~FileDescriptor(); + +public: + bool isValid() const; + int fd() const; + + void reset(int fd = -1); + void clear(); + + int release(); + +private: + int m_fd; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_FILE_DESCRIPTOR_H_ diff --git a/middleware/rialto-client/ipc/common/source/IpcLogging.h b/middleware/rialto-client/ipc/common/source/IpcLogging.h new file mode 100644 index 000000000..90c1705a7 --- /dev/null +++ b/middleware/rialto-client/ipc/common/source/IpcLogging.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef IPC_LOGGING_H_ +#define IPC_LOGGING_H_ + +#include "RialtoLogging.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RIALTO_IPC_LOG_FATAL(fmt, args...) RIALTO_LOG_FATAL(RIALTO_COMPONENT_IPC, fmt, ##args) +#define RIALTO_IPC_LOG_SYS_FATAL(err, fmt, args...) RIALTO_LOG_SYS_FATAL(RIALTO_COMPONENT_IPC, err, fmt, ##args) +#define RIALTO_IPC_LOG_ERROR(fmt, args...) RIALTO_LOG_ERROR(RIALTO_COMPONENT_IPC, fmt, ##args) +#define RIALTO_IPC_LOG_SYS_ERROR(err, fmt, args...) RIALTO_LOG_SYS_ERROR(RIALTO_COMPONENT_IPC, err, fmt, ##args) +#define RIALTO_IPC_LOG_WARN(fmt, args...) RIALTO_LOG_WARN(RIALTO_COMPONENT_IPC, fmt, ##args) +#define RIALTO_IPC_LOG_SYS_WARN(err, fmt, args...) RIALTO_LOG_SYS_WARN(RIALTO_COMPONENT_IPC, err, fmt, ##args) +#define RIALTO_IPC_LOG_MIL(fmt, args...) RIALTO_LOG_MIL(RIALTO_COMPONENT_IPC, fmt, ##args) +#define RIALTO_IPC_LOG_INFO(fmt, args...) RIALTO_LOG_INFO(RIALTO_COMPONENT_IPC, fmt, ##args) +#define RIALTO_IPC_LOG_DEBUG(fmt, args...) RIALTO_LOG_DEBUG(RIALTO_COMPONENT_IPC, fmt, ##args) + +#ifdef __cplusplus +} +#endif + +#endif // IPC_LOGGING_H_ diff --git a/middleware/rialto-client/ipc/common/source/NamedSocket.cpp b/middleware/rialto-client/ipc/common/source/NamedSocket.cpp new file mode 100644 index 000000000..f3565aa5b --- /dev/null +++ b/middleware/rialto-client/ipc/common/source/NamedSocket.cpp @@ -0,0 +1,313 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "NamedSocket.h" +#include "IpcLogging.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ +constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner +constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group +} // namespace + +namespace firebolt::rialto::ipc +{ +INamedSocketFactory &INamedSocketFactory::getFactory() +{ + static NamedSocketFactory factory; + return factory; +} + +std::unique_ptr NamedSocketFactory::createNamedSocket() const +try +{ + return std::make_unique(); +} +catch (const std::runtime_error &error) +{ + RIALTO_IPC_LOG_ERROR("Failed to create named socket: %s", error.what()); + return nullptr; +} + +std::unique_ptr NamedSocketFactory::createNamedSocket(const std::string &socketPath) const +try +{ + return std::make_unique(socketPath); +} +catch (const std::runtime_error &error) +{ + RIALTO_IPC_LOG_ERROR("Failed to create named socket: %s", error.what()); + return nullptr; +} + +NamedSocket::NamedSocket() +{ + RIALTO_IPC_LOG_MIL("Creating new socket without binding"); + + // Create the socket + m_sockFd = ::socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); + if (m_sockFd == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "socket error"); + throw std::runtime_error("socket error"); + } + + RIALTO_IPC_LOG_MIL("Socket created, fd: %d", m_sockFd); +} + +NamedSocket::NamedSocket(const std::string &socketPath) +{ + RIALTO_IPC_LOG_MIL("Creating named socket with name: %s", socketPath.c_str()); + m_sockPath = socketPath; + + // Create the socket + m_sockFd = ::socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); + if (m_sockFd == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "socket error"); + throw std::runtime_error("socket error"); + } + + // get the socket lock + if (!getSocketLock()) + { + closeListeningSocket(); + throw std::runtime_error("lock error"); + } + + // bind to the given path + struct sockaddr_un addr = {0}; + memset(&addr, 0x00, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); + + if (::bind(m_sockFd, reinterpret_cast(&addr), sizeof(addr)) == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "bind error"); + + closeListeningSocket(); + throw std::runtime_error("bind error"); + } + + RIALTO_IPC_LOG_MIL("Named socket with name: %s created, fd: %d", m_sockPath.c_str(), m_sockFd); +} + +NamedSocket::~NamedSocket() +{ + RIALTO_IPC_LOG_MIL("Close named socket with name: %s, fd: %d", m_sockPath.c_str(), m_sockFd); + closeListeningSocket(); +} + +int NamedSocket::getFd() const +{ + return m_sockFd; +} + +bool NamedSocket::setSocketPermissions(unsigned int socketPermissions) const +{ + errno = 0; + if (chmod(m_sockPath.c_str(), socketPermissions) != 0) + { + RIALTO_IPC_LOG_SYS_WARN(errno, "Failed to change the permissions on the IPC socket"); + return false; + } + return true; +} + +bool NamedSocket::setSocketOwnership(const std::string &socketOwner, const std::string &socketGroup) const +{ + uid_t ownerId = getSocketOwnerId(socketOwner); + gid_t groupId = getSocketGroupId(socketGroup); + + if (ownerId != kNoOwnerChange || groupId != kNoGroupChange) + { + errno = 0; + if (chown(m_sockPath.c_str(), ownerId, groupId) != 0) + { + RIALTO_IPC_LOG_SYS_WARN(errno, "Failed to change the owner/group for the IPC socket"); + } + } + return true; +} + +bool NamedSocket::blockNewConnections() const +{ + if (m_sockPath.empty()) + { + RIALTO_IPC_LOG_DEBUG("No need to block new connections - socket not configured"); + return true; + } + RIALTO_IPC_LOG_INFO("Block new connections for: %s", m_sockPath.c_str()); + if (listen(m_sockFd, 0) == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "blockNewConnections: listen error"); + return false; + } + return true; +} + +bool NamedSocket::bind(const std::string &socketPath) +{ + if (!m_sockPath.empty()) + { + RIALTO_IPC_LOG_DEBUG("no need to bind again"); + return true; + } + RIALTO_IPC_LOG_MIL("Binding socket with fd: %d with name: %s", m_sockFd, socketPath.c_str()); + m_sockPath = socketPath; + + // get the socket lock + if (!getSocketLock()) + { + closeListeningSocket(); + return false; + } + + // bind to the given path + struct sockaddr_un addr = {0}; + memset(&addr, 0x00, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); + + if (::bind(m_sockFd, reinterpret_cast(&addr), sizeof(addr)) == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "bind error"); + + closeListeningSocket(); + return false; + } + + RIALTO_IPC_LOG_MIL("Named socket with fd: %d bound with path: %s", m_sockFd, m_sockPath.c_str()); + + return true; +} + +void NamedSocket::closeListeningSocket() +{ + if (!m_sockPath.empty() && (unlink(m_sockPath.c_str()) != 0) && (errno != ENOENT)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket @ '%s'", m_sockPath.c_str()); + if ((m_sockFd >= 0) && (close(m_sockFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close listening socket"); + + if (!m_lockPath.empty() && (unlink(m_lockPath.c_str()) != 0) && (errno != ENOENT)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket lock file @ '%s'", m_lockPath.c_str()); + if ((m_lockFd >= 0) && (close(m_lockFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close socket lock file"); + + m_sockFd = -1; + m_sockPath.clear(); + + m_lockFd = -1; + m_lockPath.clear(); +} + +bool NamedSocket::getSocketLock() +{ + std::string lockPath = m_sockPath + ".lock"; + int fd = open(lockPath.c_str(), O_CREAT | O_CLOEXEC, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); + if (fd < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to create / open lockfile @ '%s' (check permissions)", lockPath.c_str()); + return false; + } + + if (flock(fd, LOCK_EX | LOCK_NB) < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to lock lockfile @ '%s', maybe another server is running", + lockPath.c_str()); + close(fd); + return false; + } + + struct stat sbuf = {0}; + if (stat(m_sockPath.c_str(), &sbuf) < 0) + { + if (errno != ENOENT) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "did not manage to stat existing socket @ '%s'", m_sockPath.c_str()); + close(fd); + return false; + } + } + else if ((sbuf.st_mode & S_IWUSR) || (sbuf.st_mode & S_IWGRP)) + { + unlink(m_sockPath.c_str()); + } + + m_lockFd = fd; + m_lockPath = std::move(lockPath); + + return true; +} + +uid_t NamedSocket::getSocketOwnerId(const std::string &socketOwner) const +{ + uid_t ownerId = kNoOwnerChange; + const size_t kBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (!socketOwner.empty() && kBufferSize > 0) + { + errno = 0; + passwd passwordStruct{}; + passwd *passwordResult = nullptr; + char buffer[kBufferSize]; + int result = getpwnam_r(socketOwner.c_str(), &passwordStruct, buffer, kBufferSize, &passwordResult); + if (result == 0 && passwordResult) + { + ownerId = passwordResult->pw_uid; + } + else + { + RIALTO_IPC_LOG_SYS_WARN(errno, "Failed to determine ownerId for '%s'", socketOwner.c_str()); + } + } + return ownerId; +} + +gid_t NamedSocket::getSocketGroupId(const std::string &socketGroup) const +{ + gid_t groupId = kNoGroupChange; + const size_t kBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); + if (!socketGroup.empty() && kBufferSize > 0) + { + errno = 0; + group groupStruct{}; + group *groupResult = nullptr; + char buffer[kBufferSize]; + int result = getgrnam_r(socketGroup.c_str(), &groupStruct, buffer, kBufferSize, &groupResult); + if (result == 0 && groupResult) + { + groupId = groupResult->gr_gid; + } + else + { + RIALTO_IPC_LOG_SYS_WARN(errno, "Failed to determine groupId for '%s'", socketGroup.c_str()); + } + } + return groupId; +} +} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/common/source/NamedSocket.h b/middleware/rialto-client/ipc/common/source/NamedSocket.h new file mode 100644 index 000000000..8ce2dca5a --- /dev/null +++ b/middleware/rialto-client/ipc/common/source/NamedSocket.h @@ -0,0 +1,63 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_NAMED_SOCKET_H_ +#define FIREBOLT_RIALTO_IPC_NAMED_SOCKET_H_ + +#include "INamedSocket.h" +#include +#include + +namespace firebolt::rialto::ipc +{ +class NamedSocketFactory : public INamedSocketFactory +{ +public: + std::unique_ptr createNamedSocket() const override; + std::unique_ptr createNamedSocket(const std::string &socketPath) const override; +}; + +class NamedSocket : public INamedSocket +{ +public: + NamedSocket(); + explicit NamedSocket(const std::string &socketPath); + ~NamedSocket() override; + + int getFd() const override; + bool setSocketPermissions(unsigned int socketPermissions) const override; + bool setSocketOwnership(const std::string &socketOwner, const std::string &socketGroup) const override; + bool blockNewConnections() const override; + bool bind(const std::string &socketPath) override; + +private: + void closeListeningSocket(); + bool getSocketLock(); + uid_t getSocketOwnerId(const std::string &socketOwner) const; + gid_t getSocketGroupId(const std::string &socketGroup) const; + +private: + int m_sockFd{-1}; + int m_lockFd{-1}; + std::string m_sockPath{}; + std::string m_lockPath{}; +}; +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_NAMED_SOCKET_H_ diff --git a/middleware/rialto-client/ipc/common/source/SimpleBufferPool.cpp b/middleware/rialto-client/ipc/common/source/SimpleBufferPool.cpp new file mode 100644 index 000000000..9bca47168 --- /dev/null +++ b/middleware/rialto-client/ipc/common/source/SimpleBufferPool.cpp @@ -0,0 +1,106 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "IpcLogging.h" +#include "SimpleBufferPool.h" + +SimpleBufferPool::SimpleBufferPool() : m_staticBuf(nullptr), m_staticBufSize(0) +{ + // allocate a 64kb 'static' buffer and split it up into smaller individual buffers + m_staticBufSize = 64 * 1024; + m_staticBuf = new uint8_t[m_staticBufSize]; + + uint8_t *p = m_staticBuf; + for (int i = 0; i < 8; i++) + { + m_staticBufMetaData.emplace(p, BufInfo{256, true}); + p += 256; + } + for (int i = 0; i < 6; i++) + { + m_staticBufMetaData.emplace(p, BufInfo{1024, true}); + p += 1024; + } + for (int i = 0; i < 2; i++) + { + m_staticBufMetaData.emplace(p, BufInfo{4096, true}); + p += 4096; + } + for (int i = 0; i < 1; i++) + { + m_staticBufMetaData.emplace(p, BufInfo{16384, true}); + p += 16384; + } + for (int i = 0; i < 1; i++) + { + m_staticBufMetaData.emplace(p, BufInfo{32768, true}); + p += 32768; + } +} + +SimpleBufferPool::~SimpleBufferPool() +{ + delete[] m_staticBuf; +} + +void *SimpleBufferPool::allocateImpl(size_t bytes) +{ + // try and find a free static buffer that is big enough + { + std::lock_guard locker(m_staticBufLock); + + auto entry = std::find_if(m_staticBufMetaData.begin(), m_staticBufMetaData.end(), [&](const auto &metadata) + { return (metadata.second.free && (metadata.second.size >= bytes)); }); + if (m_staticBufMetaData.end() != entry) + { + entry->second.free = false; + return entry->first; + } + } + + // RIALTO_IPC_LOG_DEBUG("no static buffers for alloc of size %zu", bytes); + + // failed, so revert to dynamic allocation + return malloc(bytes); +} + +void SimpleBufferPool::deallocate(void *p) +{ + // if the pointer is not within our static area then assume it was dynamically + // allocated, in which case just free it + if ((p < m_staticBuf) || (p >= (m_staticBuf + m_staticBufSize))) + { + free(p); + return; + } + + std::lock_guard locker(m_staticBufLock); + + // else find the meta-data on the buffer pointer and mark as freed + auto it = m_staticBufMetaData.find(p); + if (it == m_staticBufMetaData.end()) + { + RIALTO_IPC_LOG_FATAL("trying to free an unknown buffer from the pool!"); + return; + } + + it->second.free = true; +} diff --git a/middleware/rialto-client/ipc/common/source/SimpleBufferPool.h b/middleware/rialto-client/ipc/common/source/SimpleBufferPool.h new file mode 100644 index 000000000..ce7d55024 --- /dev/null +++ b/middleware/rialto-client/ipc/common/source/SimpleBufferPool.h @@ -0,0 +1,66 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SIMPLE_BUFFER_POOL_H_ +#define SIMPLE_BUFFER_POOL_H_ + +#include +#include +#include + +class SimpleBufferPool +{ +public: + SimpleBufferPool(); + ~SimpleBufferPool(); + SimpleBufferPool(const SimpleBufferPool &) = delete; + SimpleBufferPool(SimpleBufferPool &&) = delete; + SimpleBufferPool &operator=(const SimpleBufferPool &) = delete; + SimpleBufferPool &operator=(SimpleBufferPool &&) = delete; + + template T *allocate(size_t count) + { + return reinterpret_cast(allocateImpl(count * sizeof(T))); + } + + template std::shared_ptr allocateShared(size_t count) + { + return std::shared_ptr(allocate(count), [this](T *p) { deallocate(p); }); + } + + void deallocate(void *p); + +private: + void *allocateImpl(size_t bytes); + +private: + uint8_t *m_staticBuf; + size_t m_staticBufSize; + + struct BufInfo + { + size_t size; + bool free; + }; + + std::mutex m_staticBufLock; + std::map m_staticBufMetaData; +}; + +#endif // SIMPLE_BUFFER_POOL_H_ diff --git a/middleware/rialto-client/ipc/examples/CMakeLists.txt b/middleware/rialto-client/ipc/examples/CMakeLists.txt new file mode 100644 index 000000000..dc6126a0e --- /dev/null +++ b/middleware/rialto-client/ipc/examples/CMakeLists.txt @@ -0,0 +1,113 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Set the example include paths for the protoc compiler +set( Protobuf_IMPORT_DIRS "${CMAKE_CURRENT_LIST_DIR}/../common/proto" ) + +# Run the protoc tool to generate the code +include( FindProtobuf ) +protobuf_generate_cpp( PROTO_SRCS PROTO_HEADERS example.proto ) + +# Get the directory where header was generated +list( GET PROTO_HEADERS 0 FIRST_PROTO_HEADER ) +get_filename_component( PROTO_HEADER_DIR ${FIRST_PROTO_HEADER} DIRECTORY ) + +# Find includes in corresponding build directories +set( CMAKE_INCLUDE_CURRENT_DIR ON ) + + +# Create the example client +add_executable( ExampleClient + + ExampleClient.cpp + ${PROTO_SRCS} + ${PROTO_HEADERS} + + ) + +target_include_directories( ExampleClient + + PRIVATE + ${Protobuf_INCLUDE_DIRS} + + ) + +target_link_libraries( ExampleClient + + PRIVATE + RialtoIpcCommon + RialtoLogging + RialtoIpcClient + protobuf::libprotobuf + + ) + + +# Create the example server +add_executable( ExampleServer + + ExampleServer.cpp + ${PROTO_SRCS} + ${PROTO_HEADERS} + + ) + +target_include_directories( ExampleServer + + PRIVATE + ${Protobuf_INCLUDE_DIRS} + + ) + +target_link_libraries( ExampleServer + + PRIVATE + RialtoIpcCommon + RialtoLogging + RialtoIpcServer + protobuf::libprotobuf + + ) + +# Create the example with socket pair +add_executable( ExampleSocketPair + + ExampleSocketPair.cpp + ${PROTO_SRCS} + ${PROTO_HEADERS} + + ) + +target_include_directories( ExampleSocketPair + + PRIVATE + ${Protobuf_INCLUDE_DIRS} + + ) + +target_link_libraries( ExampleSocketPair + + PRIVATE + RialtoIpcCommon + RialtoLogging + RialtoIpcClient + RialtoIpcServer + protobuf::libprotobuf + + ) diff --git a/middleware/rialto-client/ipc/examples/ExampleClient.cpp b/middleware/rialto-client/ipc/examples/ExampleClient.cpp new file mode 100644 index 000000000..003f61e24 --- /dev/null +++ b/middleware/rialto-client/ipc/examples/ExampleClient.cpp @@ -0,0 +1,194 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "example.pb.h" + +#include + +#include + +// Callback invoked when the given event is received from the server +static void onSomeEvent(const std::shared_ptr<::example::SomeEvent> &event) +{ + printf("received event from server : %s\n", event->DebugString().c_str()); +} + +// Callback called when the RPC call completes with either a valid result or error +static void onComplete(bool *done) +{ + *done = true; +} + +// Example thread to show how you process the ipc channel event loop +static void runChannelEventLoop(const std::shared_ptr &channel) +{ + printf("Starting thread to process ipc channel events\n"); + + while (channel->wait(-1)) + { + if (!channel->process()) + break; + } + + printf("Stopping ipc process thread - channel disconnected\n"); +} + +int main(int argc, char *argv[]) +{ + // verify that the version of the library that we linked against is + // compatible with the version of the headers we compiled against. + GOOGLE_PROTOBUF_VERIFY_VERSION; + + // enable info level debugging + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, + RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_DEFAULT | RIALTO_DEBUG_LEVEL_INFO)); + + // connect to a socket created by the server + auto factory = firebolt::rialto::ipc::IChannelFactory::createFactory(); + auto channel = factory->createChannel("/tmp/rialto.example.socket"); + if (!channel) + { + fprintf(stderr, "Failed to connect to socket '/tmp/rialto.example.socket', is ExampleServer running?\n"); + return EXIT_FAILURE; + } + + // subscribe to an event from the server + channel->subscribe<::example::SomeEvent>(&onSomeEvent); + + // create the stub for rpc calls + ::example::ExampleService::Stub stub(channel.get()); + + // make a basic call and get the result polling on the channel + { + printf("Making RPC call ExampleService.exampleEcho()\n"); + + ::example::RequestEcho request; + ::example::ResponseEcho response; + + // populate the request message + request.set_text("the significant owl hoots in the night"); + + // create a controller which is used to check for any errors or cancel the rpc call + auto controllerFactory = IControllerFactory::createFactory(); + auto controller = controllerFactory->create(); + + // make the rpc call, onComplete will be called when it completes + bool done = false; + stub.exampleEcho(controller.get(), &request, &response, google::protobuf::NewCallback(onComplete, &done)); + + // process the event loop until the RPC call completes + while (channel->process() && !done) + { + channel->wait(-1); + } + + // check if the call failed with an error + if (controller->Failed()) + { + fprintf(stderr, "\texampleEcho IPC call failed with error '%s'\n", controller->ErrorText().c_str()); + } + else + { + printf("\treceived response '%s'\n", response.DebugString().c_str()); + } + } + + // example of spawning a thread to run the event loop + std::thread loop = std::thread(runChannelEventLoop, channel); + + // example making a call with no reply expected + { + printf("Making RPC call ExampleService.exampleWithNoReply()\n"); + + ::example::RequestWithNoReply request; + + // populate the request message + request.set_text("request with no reply expected"); + + // create a controller which is used to check for any errors or cancel the rpc call + auto controllerFactory = IControllerFactory::createFactory(); + auto controller = controllerFactory->create(); + + // make the rpc call, onComplete will be called when it completes + stub.exampleWithNoReply(controller.get(), &request, nullptr, nullptr); + + // check if the call failed - this will only happen if there was an issue sending the request (ie. channel disconnected) + if (controller->Failed()) + { + fprintf(stderr, "\texampleWithNoReply IPC call failed with error '%s'\n", controller->ErrorText().c_str()); + } + else + { + printf("\trequest send\n"); + } + } + + // example making a call sending and receiving file descriptors + { + printf("Making RPC call ExampleService.exampleWithFd()\n"); + + ::example::RequestWithFd request; + ::example::ResponseWithFd response; + + // populate the request message + request.set_fd(STDOUT_FILENO); + request.set_text("some test"); + + // create a controller which is used to check for any errors or cancel the rpc call + auto controllerFactory = IControllerFactory::createFactory(); + auto controller = controllerFactory->create(); + + // make the rpc call, onComplete will be called when it completes + bool done = false; + stub.exampleWithFd(controller.get(), &request, &response, google::protobuf::NewCallback(onComplete, &done)); + + // the complete callback will now be called on the runChannelEventLoop thread, so we just poll on done + // being set to true (this is not truely thread safe but provides a simple example) + while (!done) + { + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + } + + // check if the call failed with an error + if (controller->Failed()) + { + fprintf(stderr, "\texampleWithFd IPC call failed with error '%s'\n", controller->ErrorText().c_str()); + } + else + { + printf("\treceived response '%s'\n", response.DebugString().c_str()); + + // it is the callers responsibility to close the received file descriptor + if (close(response.fd()) != 0) + fprintf(stderr, "\tfailed to close the fd received from the server\n"); + } + } + + // disconnect from the server + channel->disconnect(); + + // this should terminate the processing thread + loop.join(); + + return EXIT_SUCCESS; +} diff --git a/middleware/rialto-client/ipc/examples/ExampleServer.cpp b/middleware/rialto-client/ipc/examples/ExampleServer.cpp new file mode 100644 index 000000000..839023daa --- /dev/null +++ b/middleware/rialto-client/ipc/examples/ExampleServer.cpp @@ -0,0 +1,124 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "example.pb.h" + +#include + +class MyExampleServiceServer : public ::example::ExampleService +{ +public: + void exampleEcho(google::protobuf::RpcController *controller, const ::example::RequestEcho *request, + ::example::ResponseEcho *response, google::protobuf::Closure *done) override + { + // convert received string to upper case and send back + std::string text = request->text(); + std::transform(text.begin(), text.end(), text.begin(), ::toupper); + response->set_text(text); + + printf("ExampleService::exampleEcho({%s}) -> {%s}\n", request->DebugString().c_str(), + response->DebugString().c_str()); + + // if you wanted to report an error you'd do this + // controller->SetFailed("Failed for some reason ..."); + + // complete + done->Run(); + } + + void exampleWithFd(google::protobuf::RpcController *controller, const ::example::RequestWithFd *request, + ::example::ResponseWithFd *response, google::protobuf::Closure *done) override + { + // expecting the request to contain an fd to stdout of the client, so just write a message to the client + int fd = request->fd(); + if (dprintf(fd, "hello from the server\n") < 0) + perror("dprintf failed\n"); + + // reply with our own stdout fd + response->set_fd(STDOUT_FILENO); + + printf("ExampleService::exampleWithFd({%s}) -> {%s}\n", request->DebugString().c_str(), + response->DebugString().c_str()); + + // complete + done->Run(); + } + + void exampleWithNoReply(google::protobuf::RpcController *controller, const ::example::RequestWithNoReply *request, + ::example::EmptyResponse *response, google::protobuf::Closure *done) override + { + fprintf(stderr, "ExampleService::exampleWithNoReply({%s})\n", request->DebugString().c_str()); + + // for 'no reply' calls both the response object and done closure are null + } +}; + +// Example callback for when a client connects +static void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) +{ + printf("Client connected, pid:%d, uid:%d gid:%d\n", client->getClientPid(), client->getClientUserId(), + client->getClientGroupId()); + + // export the example server to the client + client->exportService(std::make_shared()); + + // example of sending an async event to the client + auto someEvent = std::make_shared<::example::SomeEvent>(); + someEvent->set_id(1234); + someEvent->set_text("some event"); + client->sendEvent(someEvent); +} + +// Example callback for a client disconnects +static void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) +{ + printf("Client disconnected, pid:%d, uid:%d gid:%d\n", client->getClientPid(), client->getClientUserId(), + client->getClientGroupId()); +} + +int main(int argc, char *argv[]) +{ + // verify that the version of the library that we linked against is + // compatible with the version of the headers we compiled against. + GOOGLE_PROTOBUF_VERIFY_VERSION; + + // enable info level debugging + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, + RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_DEFAULT | RIALTO_DEBUG_LEVEL_INFO)); + + auto factory = ::firebolt::rialto::ipc::IServerFactory::createFactory(); + auto server = factory->create(); + + // add a listening socket for clients to connect to + server->addSocket("/tmp/rialto.example.socket", &clientConnected, &clientDisconnected); + + // loop processing all event (alternatively you can call server->fd() to get a file descriptor to add to your + // own poll loop and then when woken call server->process()) + while (server->process()) + { + server->wait(-1); + } + + return EXIT_SUCCESS; +} diff --git a/middleware/rialto-client/ipc/examples/ExampleSocketPair.cpp b/middleware/rialto-client/ipc/examples/ExampleSocketPair.cpp new file mode 100644 index 000000000..a210f4ccc --- /dev/null +++ b/middleware/rialto-client/ipc/examples/ExampleSocketPair.cpp @@ -0,0 +1,198 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "example.pb.h" + +#include +#include +#include + +class MyExampleService : public ::example::ExampleService +{ +public: + void exampleEcho(google::protobuf::RpcController *controller, const ::example::RequestEcho *request, + ::example::ResponseEcho *response, google::protobuf::Closure *done) override + { + // convert received string to upper case and send back + std::string text = request->text(); + std::transform(text.begin(), text.end(), text.begin(), ::toupper); + response->set_text(text); + + printf("[server] ExampleService::exampleEcho({%s}) -> {%s}\n", request->DebugString().c_str(), + response->DebugString().c_str()); + + // if you wanted to report an error you'd do this + // controller->SetFailed("Failed for some reason ..."); + + // complete + done->Run(); + } +}; + +// Callback called when the RPC call completes with either a valid result or error +static void onComplete(bool *done) +{ + *done = true; +} + +// Simple 'main' for the spawned example +static int childProcessMain(int sock) +{ + // create a channel to a socket created by the server + auto factory = firebolt::rialto::ipc::IChannelFactory::createFactory(); + auto channel = factory->createChannel(sock); + if (!channel) + { + fprintf(stderr, "[child] Failed to connect to socket fd '%d'\n", sock); + return EXIT_FAILURE; + } + + // create the stub for rpc calls + ::example::ExampleService::Stub stub(channel.get()); + + // make a basic call and get the result polling on the channel + { + printf("[child] Making IPC call ExampleService.exampleEcho()\n"); + + ::example::RequestEcho request; + ::example::ResponseEcho response; + + // populate the request message + request.set_text("the significant owl hoots in the night"); + + // create a controller which is used to check for any errors or cancel the rpc call + auto controllerFactory = IControllerFactory::createFactory(); + auto controller = controllerFactory->create(); + + // make the rpc call, onComplete will be called when it completes + bool done = false; + stub.exampleEcho(controller.get(), &request, &response, google::protobuf::NewCallback(onComplete, &done)); + + // process the event loop until the RPC call completes + while (channel->process() && !done) + { + channel->wait(-1); + } + + // check if the call failed with an error + if (controller->Failed()) + { + fprintf(stderr, "[child] \texampleEcho IPC call failed with error '%s'\n", controller->ErrorText().c_str()); + } + else + { + printf("[child] \treceived response '%s'\n", response.DebugString().c_str()); + } + } +} + +// Example of spawning a client and giving it the socket to talk back the server on +static pid_t spawnClient(int sock) +{ + // fork and exec the process + pid_t pid = fork(); + if (pid < 0) + { + fprintf(stderr, "fork failed - %s\n", strerror(errno)); + return -1; + } + + if (pid == 0) + { + // within spawned process + int ret = childProcessMain(sock); + _exit(ret); + } + else + { + // still in parent, close the socket + close(sock); + } + + return pid; +} + +// Example callback for a client disconnects +static void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::Client> &client) +{ + printf("Client disconnected, pid:%d, uid:%d gid:%d\n", client->getClientPid(), client->getClientUserId(), + client->getClientGroupId()); +} + +int main(int argc, char *argv[]) +{ + // verify that the version of the library that we linked against is + // compatible with the version of the headers we compiled against. + GOOGLE_PROTOBUF_VERIFY_VERSION; + + // enable info level debugging + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, + RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_DEFAULT | RIALTO_DEBUG_LEVEL_INFO)); + + auto factory = ::firebolt::rialto::ipc::IServerFactory::createFactory(); + auto server = factory->create(); + + // create a socket pair, one for the server and one for the spawned client + int socks[2] = {-1, -1}; + if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, socks) < 0) + { + fprintf(stderr, "socketpair failed - %s\n", strerror(errno)); + return EXIT_FAILURE; + } + + // give one socket to the server + auto client = server->addClient(socks[0], &clientDisconnected); + if (!client) + { + return EXIT_FAILURE; + } + + // export the example service to the client + client->exportService(std::make_shared()); + + // spawn off a client process, giving it the socket fd + pid_t childPid = spawnClient(socks[1]); + if (childPid <= 0) + { + return EXIT_FAILURE; + } + + // loop processing all event (alternatively you can call server->fd() to get a file descriptor to add to your + // own poll loop and then when woken call server->process()) + while (server->process() && client->isConnected()) + { + server->wait(-1); + } + + // ensure we reap the child process + int status; + if (waitpid(childPid, &status, 0) < 0) + { + fprintf(stderr, "waitpid failed - %s\n", strerror(errno)); + } + + return EXIT_SUCCESS; +} diff --git a/middleware/rialto-client/ipc/examples/example.proto b/middleware/rialto-client/ipc/examples/example.proto new file mode 100644 index 000000000..d02c31f13 --- /dev/null +++ b/middleware/rialto-client/ipc/examples/example.proto @@ -0,0 +1,74 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; + +import "google/protobuf/descriptor.proto"; +import "rialtoipc.proto"; + +package example; + +// You need this to generate the rpc service stubs +option cc_generic_services = true; + + +message RequestEcho { + required string text = 1; +} +message ResponseEcho { + required string text = 1; +} + + +message RequestWithFd { + optional string text = 1; + required int32 fd = 2 [(rialto.ipc.field_is_fd) = true]; +} +message ResponseWithFd { + optional string text = 1; + required int32 fd = 2 [(rialto.ipc.field_is_fd) = true]; +} + + +message RequestWithNoReply { + optional string text = 1; +} +message EmptyResponse { +} + + + +message SomeEvent { + required int32 id = 5; + optional string text = 1; +} + +service ExampleService { + + rpc exampleEcho(RequestEcho) returns (ResponseEcho) { + } + + rpc exampleWithFd(RequestWithFd) returns (ResponseWithFd) { + } + + rpc exampleWithNoReply(RequestWithNoReply) returns (EmptyResponse) { + option (rialto.ipc.no_reply) = true; + } + +} diff --git a/middleware/rialto-client/ipc/server/CMakeLists.txt b/middleware/rialto-client/ipc/server/CMakeLists.txt new file mode 100644 index 000000000..dd85f16af --- /dev/null +++ b/middleware/rialto-client/ipc/server/CMakeLists.txt @@ -0,0 +1,59 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + + +add_library( + RialtoIpcServer + STATIC + + source/IpcClientImpl.cpp + source/IpcServerImpl.cpp + source/IpcServerControllerImpl.cpp + + # $ + + ) + +target_include_directories( + RialtoIpcServer + + PUBLIC + include + $ + + PRIVATE + $ + + ) + +set_property( + TARGET RialtoIpcServer + PROPERTY POSITION_INDEPENDENT_CODE ON + + ) + +target_link_libraries( + RialtoIpcServer + + PRIVATE + RialtoIpcCommon + RialtoLogging + protobuf::libprotobuf + + ) diff --git a/middleware/rialto-client/ipc/server/include/IIpcController.h b/middleware/rialto-client/ipc/server/include/IIpcController.h new file mode 100644 index 000000000..7064f23b3 --- /dev/null +++ b/middleware/rialto-client/ipc/server/include/IIpcController.h @@ -0,0 +1,132 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_H_ +#define FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_H_ + +#include "IIpcServer.h" +#include + +#include +#include +#include + +namespace firebolt::rialto::ipc +{ +/** + * @brief Controller interface for the protobuf RPC service stubs. + * + * A pointer to this interface will be supplied as the first argument in every + * RPC stub call. It is an extensions of the google::protobuf::RpcController + * interface and provides an additional method to get the client that made the + * RPC call. + */ +class IController : public google::protobuf::RpcController +{ +public: + IController() = default; + virtual ~IController() = default; + + IController(const IController &) = delete; + IController &operator=(const IController &) = delete; + IController(IController &&) = delete; + IController &operator=(IController &&) = delete; + +public: + /** + * Client-side methods + * Calls can only be made from the client side. Calling these apis from server side + * is undefined and could cause crashes. + */ + + /** + * @brief Reset the RpcController. + * + * So that the RpcController can be reused for a new call, sets to the inital state. + */ + void Reset() override = 0; + + /** + * @brief Checks id the previosu call has failed. + * + * The reason for the failure depends on the implementaion of the RPC. Failed should only + * be called after after the call has finished. If this call returns true, the response + * structure returned from the failed call is undefined. + * + * @retval true if previous call failed. + */ + bool Failed() const override = 0; + + /** + * @brief Returns a description of the error if the previous call has failed. + * + * @retval error string. + */ + std::string ErrorText() const override = 0; + + /** + * @brief Starts the cancellation of a RPC call + * + * RPC may cancel the call immediatly, wait and cancel or not cancel at all. If a call is cancelled + * failure will be set for the client and "done" will still be called. + */ + void StartCancel() override = 0; + + /** + * Server-side methods + * Calls can only be made from the server side. Calling these apis from client side + * is undefined and could cause crashes. + */ + + /** + * @brief To be called during a method call. Returns a ptr to the client that made the call. + * + * @retval client that made the call. + */ + virtual std::shared_ptr getClient() const = 0; + + /** + * @brief Causes failure to be returned to the client. + * + * Failed() shall return true. The failure reason can be fetched from the ErrorText(). + * To return machine-readable info on failure, use the method response structure rather than + * SetFailed(). + * + * @param[in] reason : The reason for the falure. + */ + void SetFailed(const std::string &reason) override = 0; + + /** + * @brief Not supported. + * + * @retval false. + */ + bool IsCanceled() const override = 0; + + /** + * @brief Not supported. + * + * @param[in] callback : Callback on closure. + */ + void NotifyOnCancel(google::protobuf::Closure *callback) override = 0; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_H_ diff --git a/middleware/rialto-client/ipc/server/include/IIpcServer.h b/middleware/rialto-client/ipc/server/include/IIpcServer.h new file mode 100644 index 000000000..10a2a8936 --- /dev/null +++ b/middleware/rialto-client/ipc/server/include/IIpcServer.h @@ -0,0 +1,231 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_I_IPC_SERVER_H_ +#define FIREBOLT_RIALTO_IPC_I_IPC_SERVER_H_ + +#include +#include + +#include +#include +#include +#include +#include + +namespace firebolt::rialto::ipc +{ +/** + * @brief Interface to object describing a client connected to the server. + * + * An object of this interface is provided in the callbacks for when a client + * connects / disconnects. The interface can be used to query details above + * the client and send it asynchronous events. + */ +class IClient +{ +public: + IClient() = default; + virtual ~IClient() = default; + + IClient(const IClient &) = delete; + IClient &operator=(const IClient &) = delete; + IClient(IClient &&) = delete; + IClient &operator=(IClient &&) = delete; + +public: + /** + * @brief Gets the pid of the client that created the connection. + * + * \threadsafe + * + * @retval the pid. + */ + virtual pid_t getClientPid() const = 0; + + /** + * @brief Gets the userIdof the client that created the connection. + * + * \threadsafe + * + * @retval the userId. + */ + virtual uid_t getClientUserId() const = 0; + + /** + * @brief Gets the groupId of the client that created the connection. + * + * \threadsafe + * + * @retval the groupId. + */ + virtual gid_t getClientGroupId() const = 0; + + /** + * @brief Tells the server to disconnect the client. + * + * \threadsafe + * + * Typically you'd call this in the clientConnected method if you didn't want to accept the + * client's connection. + */ + virtual void disconnect() = 0; + + /** + * @brief Adds a service implementation for the client. + * + * \threadsafe + * + * After this the client will be able to call methods on the service. + * + * @param[in] service : service to export. + */ + virtual void exportService(const std::shared_ptr &service) = 0; + + /** + * @brief Sends a message out to the client connection. + * + * \threadsafe + * + * This method is thread safe + * and may be called from any context; internally it will queue the message + * on the client's message queue and the server process will send it + * + * @param[in] message : message to send. + * + * @retval true on success, false otherwise. + */ + virtual bool sendEvent(const std::shared_ptr &message) = 0; + + /** + * @brief The server object. + * + * \threadsafe + * + * It is safe to hold a + * shared_ptr to this object after the client has disconnected, but obviously + * sendEvent will fail and data like pid and userId will be invalid. + * + * @retval true if the client is still conn + */ + virtual bool isConnected() const = 0; +}; + +/** + * @brief The server object. + * + * You must run the server as part of an external event loop implementation, you + * can do that by setting up a loop that calls wait() and then process(). Or + * you can get the fd() and add it to an external poll loop, and when woken call + * process(). + */ +class IServer +{ +public: + IServer() = default; + virtual ~IServer() = default; + + IServer(const IServer &) = delete; + IServer &operator=(const IServer &) = delete; + IServer(IServer &&) = delete; + IServer &operator=(IServer &&) = delete; + + /** + * @brief Creates the listening socket to accept new connections. + * + * \threadsafe + * + * This does not blockwaiting for connections, it just creates the socket and adds to the poll loop. + * + * @retval true on success, false otherwise. + */ + inline bool addSocket(const std::string &socketPath) { return addSocket(socketPath, nullptr, nullptr); } + inline bool addSocket(const std::string &socketPath, + std::function &)> clientConnectedCb) + { + return addSocket(socketPath, std::move(clientConnectedCb), nullptr); + } + virtual bool addSocket(const std::string &socketPath, + std::function &)> clientConnectedCb, + std::function &)> clientDisconnectedCb) = 0; + virtual bool addSocket(int fd, std::function &)> clientConnectedCb, + std::function &)> clientDisconnectedCb) = 0; + + /** + * @brief Create a client. + * + * \threadsafe + * + * Given a file descriptor corresponding to one end of a socket, this function + * will create a client (std::shared_ptr) and add the new client to + * the internal clients list. At that point, the client is initialized and + * ready to run, as if the client had connected to the servers listening socket. + * + * The other end of the socket can be passed to firebolt::rialto::ipc::Channel::connect(int sockFd) + * function to create a client side IPC channel. + * + * When the other end of the socket is closed the clientDisconnectedCb will + * be called. + * + * The socketFd must be a unix domain socket of type SOCK_SEQPACKET, if a different + * socket type then this will fail and return a null std::shared_ptr. + * + * The server will dup the socketFd on success, so the caller can (and should) + * close the socketFd after this call completes if it no longer needs the socket. + * + * @param[in] socketFd : The file descriptor for the socket. + * @param[in] clientDisconnectedCb : Callback to be called on the closing of the socket. + * + * @retval client on success, nullptr otherwise. + */ + inline std::shared_ptr addClient(int socketFd) { return addClient(socketFd, nullptr); } + virtual std::shared_ptr + addClient(int socketFd, std::function &)> clientDisconnectedCb) = 0; + + /** + * @brief Returns an fd that can be added to an external event loop. This is NOT the + * server socket fd. + * + * @retval >= 0 on success, -1 otherwise. + */ + virtual int fd() const = 0; + + /** Waits for any I/O to occur on the socket or timeout from a method call. + * The call will block for a maximum of timeoutMSecs, to make the call wait + * indefinitely pass -1. + * + * @param[in] timeoutMSecs : The time to wait for I/O. + * + * @retval false if there was an error , true otherwise + */ + inline bool wait() { return this->wait(-1); } + virtual bool wait(int timeoutMSecs) = 0; + + /** + * @brief This is the heart of the server, it is where we wait for new incoming + * connections or data from clients, and send data back to clients. + * + * @retval false if there was an error, true otherwise + */ + virtual bool process() = 0; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_I_IPC_SERVER_H_ diff --git a/middleware/rialto-client/ipc/server/include/IIpcServerFactory.h b/middleware/rialto-client/ipc/server/include/IIpcServerFactory.h new file mode 100644 index 000000000..77f71cbd3 --- /dev/null +++ b/middleware/rialto-client/ipc/server/include/IIpcServerFactory.h @@ -0,0 +1,52 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_I_IPC_SERVER_FACTORY_H_ +#define FIREBOLT_RIALTO_IPC_I_IPC_SERVER_FACTORY_H_ + +#include "IIpcServer.h" + +#include + +namespace firebolt::rialto::ipc +{ +class IServerFactory +{ +public: + IServerFactory() = default; + virtual ~IServerFactory() = default; + + /** + * @brief Create a IServerFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Create a IServer object. + * + * @retval the server instance or null on error. + */ + virtual std::shared_ptr create() = 0; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_I_IPC_SERVER_FACTORY_H_ diff --git a/middleware/rialto-client/ipc/server/source/IpcClientImpl.cpp b/middleware/rialto-client/ipc/server/source/IpcClientImpl.cpp new file mode 100644 index 000000000..dceeeae45 --- /dev/null +++ b/middleware/rialto-client/ipc/server/source/IpcClientImpl.cpp @@ -0,0 +1,79 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IpcClientImpl.h" +#include "IpcServerImpl.h" +#include + +namespace firebolt::rialto::ipc +{ +ClientImpl::ClientImpl(const std::shared_ptr &server, uint64_t clientId, const struct ucred &creds) + : m_kServer(server), m_kClientId(clientId), m_kCredentials(creds) +{ +} + +pid_t ClientImpl::getClientPid() const +{ + return m_kCredentials.pid; +} + +uid_t ClientImpl::getClientUserId() const +{ + return m_kCredentials.uid; +} + +gid_t ClientImpl::getClientGroupId() const +{ + return m_kCredentials.gid; +} + +void ClientImpl::disconnect() +{ + auto server = m_kServer.lock(); + if (server) + { + server->disconnectClient(m_kClientId); + } +} + +void ClientImpl::exportService(const std::shared_ptr &service) +{ + auto descriptor = service->GetDescriptor(); + m_services.emplace(descriptor->full_name(), service); +} + +bool ClientImpl::sendEvent(const std::shared_ptr &message) +{ + auto server = m_kServer.lock(); + if (server) + return server->sendEvent(m_kClientId, message); + else + return false; +} + +bool ClientImpl::isConnected() const +{ + auto server = m_kServer.lock(); + if (server) + return server->isClientConnected(m_kClientId); + else + return false; +} + +} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/server/source/IpcClientImpl.h b/middleware/rialto-client/ipc/server/source/IpcClientImpl.h new file mode 100644 index 000000000..9c44b097c --- /dev/null +++ b/middleware/rialto-client/ipc/server/source/IpcClientImpl.h @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_IPC_CLIENT_IMPL_H_ +#define FIREBOLT_RIALTO_IPC_IPC_CLIENT_IMPL_H_ + +#include "IIpcServer.h" + +#include + +#include +#include +#include + +namespace firebolt::rialto::ipc +{ +class ServerImpl; + +class ClientImpl final : public IClient +{ +public: + ClientImpl(const std::shared_ptr &server, uint64_t clientId, const struct ucred &creds); + ~ClientImpl() final = default; + +public: + pid_t getClientPid() const override; + uid_t getClientUserId() const override; + gid_t getClientGroupId() const override; + + void disconnect() override; + + void exportService(const std::shared_ptr &service) override; + + bool sendEvent(const std::shared_ptr &message) override; + + bool isConnected() const override; + +protected: + friend class ServerImpl; + inline uint64_t id() const { return m_kClientId; } + +private: + const std::weak_ptr m_kServer; + const uint64_t m_kClientId{}; + const struct ucred m_kCredentials; + + std::map> m_services; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_IPC_CLIENT_IMPL_H_ diff --git a/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.cpp b/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.cpp new file mode 100644 index 000000000..2c0d100cc --- /dev/null +++ b/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.cpp @@ -0,0 +1,56 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IpcServerControllerImpl.h" +#include "IpcClientImpl.h" +#include +#include +#include + +namespace firebolt::rialto::ipc +{ +ServerControllerImpl::ServerControllerImpl(std::shared_ptr client, uint64_t serialId) + : m_kClient(std::move(client)), m_kSerialId(serialId) +{ +} + +void ServerControllerImpl::SetFailed(const std::string &reason) // NOLINT(build/function_format) +{ + m_failed = true; + m_failureReason = reason; +} + +bool ServerControllerImpl::IsCanceled() const // NOLINT(build/function_format) +{ + // neither client nor server support cancel + return false; +} + +void ServerControllerImpl::NotifyOnCancel(google::protobuf::Closure *callback) // NOLINT(build/function_format) +{ + // neither client nor server support cancel + (void)callback; +} + +std::shared_ptr ServerControllerImpl::getClient() const +{ + return m_kClient; +} + +} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.h b/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.h new file mode 100644 index 000000000..22a0e4b80 --- /dev/null +++ b/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.h @@ -0,0 +1,84 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_IPC_SERVER_CONTROLLER_IMPL_H_ +#define FIREBOLT_RIALTO_IPC_IPC_SERVER_CONTROLLER_IMPL_H_ + +#include "IIpcController.h" +#include "IpcClientImpl.h" +#include +#include + +namespace firebolt::rialto::ipc +{ +/** + * @brief Implementation of the RialtoIpcServerController interface, a pointer to an + * object of this type is supplied in each RPC call handler. + * + * This object is inherited from RialtoIpcServerController interface which in turn + * is inherited from google::protobuf::RpcController, and therefore meets the + * requirements of the protobuf RPC service handler. + * + * It implements the google::protobuf::RpcController::SetFailed(...) method + * which allows the server to return a failure on an RPC call. + * + * It also implements the RialtoIpcController::getClient(...) method which + * allows for returning a pointer to the RialtoIpc client that made the request. + * This is an extension to the google::protobuf::RpcController interface. + * If clients need this API then they are expected to perform a dynamic_cast + * on the controller pointer to a RialtoIpcController pointer. + */ +class ServerControllerImpl final : public IController +{ +public: + ~ServerControllerImpl() final = default; + +public: + /** + * Ignore Client-side methods + */ + void Reset() final {} + bool Failed() const final { return false; } + std::string ErrorText() const final { return std::string(); } + void StartCancel() final {} + +public: + /** + * Server-side methods + */ + void SetFailed(const std::string &reason) final; + bool IsCanceled() const final; + void NotifyOnCancel(google::protobuf::Closure *callback) final; + std::shared_ptr getClient() const final; + +protected: + friend class ServerImpl; + ServerControllerImpl(std::shared_ptr client, uint64_t serialId); + + const std::shared_ptr m_kClient; + const uint64_t m_serialId{}; + const uint64_t m_kSerialId; + + bool m_failed = false; + std::string m_failureReason; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_IPC_SERVER_CONTROLLER_IMPL_H_ diff --git a/middleware/rialto-client/ipc/server/source/IpcServerImpl.cpp b/middleware/rialto-client/ipc/server/source/IpcServerImpl.cpp new file mode 100644 index 000000000..f6cd2da73 --- /dev/null +++ b/middleware/rialto-client/ipc/server/source/IpcServerImpl.cpp @@ -0,0 +1,1417 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IpcServerImpl.h" +#include "IIpcServerFactory.h" +#include "IpcClientImpl.h" +#include "IpcLogging.h" +#include "IpcServerControllerImpl.h" + +#include "rialtoipc.pb.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WAKE_EVENT_ID uint64_t(0) +#define FIRST_LISTENING_SOCKET_ID uint64_t(1) +#define FIRST_CLIENT_ID uint64_t(10000) + +namespace firebolt::rialto::ipc +{ +const size_t ServerImpl::m_kMaxMessageLen = (128 * 1024); + +std::shared_ptr IServerFactory::createFactory() +{ + std::shared_ptr factory; + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_IPC_LOG_ERROR("Failed to create the server factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr ServerFactory::create() +{ + return std::make_shared(); +} + +ServerImpl::ServerImpl() + : m_pollFd(-1), m_wakeEventFd(-1), m_socketIdCounter(FIRST_LISTENING_SOCKET_ID), m_clientIdCounter(FIRST_CLIENT_ID), + m_recvDataBuf{0}, m_recvCtrlBuf{0} +{ + // create the eventfd use to wake the poll loop + m_wakeEventFd = eventfd(0, EFD_CLOEXEC); + if (m_wakeEventFd < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "eventfd failed"); + return; + } + + // create epoll loop + m_pollFd = epoll_create1(EPOLL_CLOEXEC); + if (m_pollFd < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_create1 failed"); + return; + } + + // add the wake event to epoll + epoll_event event = {.events = EPOLLIN, .data = {.u64 = WAKE_EVENT_ID}}; + if (epoll_ctl(m_pollFd, EPOLL_CTL_ADD, m_wakeEventFd, &event) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add eventfd"); + } +} + +ServerImpl::~ServerImpl() +{ + if ((m_pollFd >= 0) && (close(m_pollFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close epoll"); + + if ((m_wakeEventFd >= 0) && (close(m_wakeEventFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close eventfd"); + + for (const auto &entry : m_sockets) + { + const Socket &kSocket = entry.second; + + if (kSocket.isOwned) + { + if (unlink(kSocket.sockPath.c_str()) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket @ '%s'", kSocket.sockPath.c_str()); + if (close(kSocket.sockFd) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close listening socket"); + + if (unlink(kSocket.lockPath.c_str()) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket lock file @ '%s'", kSocket.lockPath.c_str()); + if (close(kSocket.lockFd) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close socket lock file"); + } + } +} + +// ----------------------------------------------------------------------------- +/*! + \static + \internal + + Creates (if required) and takes the file lock associated with the socket + path in the \a socket object. + + */ +bool ServerImpl::getSocketLock(Socket *socket) +{ + std::string lockPath = socket->sockPath + ".lock"; + int fileDescriptor = open(lockPath.c_str(), O_CREAT | O_CLOEXEC, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); + if (fileDescriptor < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to create / open lockfile @ '%s' (check permissions)", lockPath.c_str()); + return false; + } + + if (flock(fileDescriptor, LOCK_EX | LOCK_NB) < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to lock lockfile @ '%s', maybe another server is running", + lockPath.c_str()); + close(fileDescriptor); + return false; + } + + struct stat sbuf = {0}; + if (stat(socket->sockPath.c_str(), &sbuf) < 0) + { + if (errno != ENOENT) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "did not manage to stat existing socket @ '%s'", socket->sockPath.c_str()); + close(fileDescriptor); + return false; + } + } + else if ((sbuf.st_mode & S_IWUSR) || (sbuf.st_mode & S_IWGRP)) + { + unlink(socket->sockPath.c_str()); + } + + socket->lockFd = fileDescriptor; + socket->lockPath = std::move(lockPath); + + return true; +} + +// ----------------------------------------------------------------------------- +/*! + \static + \internal + + Closes the file descriptors and the deletes the files stored in the \a socket + object. + + */ +void ServerImpl::closeListeningSocket(Socket *socket) +{ + if (!socket->isOwned) + { + return; + } + + if (!socket->sockPath.empty() && (unlink(socket->sockPath.c_str()) != 0) && (errno != ENOENT)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket @ '%s'", socket->sockPath.c_str()); + if ((socket->sockFd >= 0) && (close(socket->sockFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close listening socket"); + + if (!socket->lockPath.empty() && (unlink(socket->lockPath.c_str()) != 0) && (errno != ENOENT)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket lock file @ '%s'", socket->lockPath.c_str()); + if ((socket->lockFd >= 0) && (close(socket->lockFd) != 0)) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close socket lock file"); + + socket->sockFd = -1; + socket->sockPath.clear(); + + socket->lockFd = -1; + socket->lockPath.clear(); +} + +bool ServerImpl::addSocket(const std::string &socketPath, + std::function &)> clientConnectedCb, + std::function &)> clientDisconnectedCb) +{ + // store the path + Socket socket; + socket.sockPath = socketPath; + + // create the socket + socket.sockFd = ::socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); + if (socket.sockFd == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "socket error"); + return false; + } + + // get the socket lock + if (!getSocketLock(&socket)) + { + closeListeningSocket(&socket); + return false; + } + + // bind to the given path + struct sockaddr_un addr = {0}; + memset(&addr, 0x00, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); + + if (bind(socket.sockFd, reinterpret_cast(&addr), sizeof(addr)) == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "bind error"); + + closeListeningSocket(&socket); + return false; + } + + // put in listening mode + if (listen(socket.sockFd, 1) == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "listen error"); + + closeListeningSocket(&socket); + return false; + } + + // create an id for the listening socket + const uint64_t kSocketId = m_socketIdCounter++; + if (kSocketId >= FIRST_CLIENT_ID) + { + // should never happen, we'd run out of file descriptors before + // we hit the 10k limit on listening sockets + RIALTO_IPC_LOG_ERROR("too many listening sockets"); + + closeListeningSocket(&socket); + return false; + } + + // add the socket to epoll + epoll_event event = {.events = EPOLLIN, .data = {.u64 = kSocketId}}; + if (epoll_ctl(m_pollFd, EPOLL_CTL_ADD, socket.sockFd, &event) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add listening socket"); + + closeListeningSocket(&socket); + return false; + } + + // store the client connected / disconnected callbacks + socket.connectedCb = clientConnectedCb; + socket.disconnectedCb = clientDisconnectedCb; + + // add to the internal map + std::lock_guard locker(m_socketsLock); + m_sockets.emplace(kSocketId, std::move(socket)); + + RIALTO_IPC_LOG_INFO("added listening socket '%s' to server", socketPath.c_str()); + + return true; +} + +bool ServerImpl::addSocket(int fd, std::function &)> clientConnectedCb, + std::function &)> clientDisconnectedCb) +{ + // store the path + Socket socket; + socket.isOwned = false; + socket.sockFd = fd; + + // put in listening mode + if (listen(socket.sockFd, 1) == -1) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "listen error"); + return false; + } + + // create an id for the listening socket + const uint64_t kSocketId = m_socketIdCounter++; + if (kSocketId >= FIRST_CLIENT_ID) + { + // should never happen, we'd run out of file descriptors before + // we hit the 10k limit on listening sockets + RIALTO_IPC_LOG_ERROR("too many listening sockets"); + return false; + } + + // add the socket to epoll + epoll_event event = {.events = EPOLLIN, .data = {.u64 = kSocketId}}; + if (epoll_ctl(m_pollFd, EPOLL_CTL_ADD, socket.sockFd, &event) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add listening socket"); + return false; + } + + // store the client connected / disconnected callbacks + socket.connectedCb = clientConnectedCb; + socket.disconnectedCb = clientDisconnectedCb; + + // add to the internal map + std::lock_guard locker(m_socketsLock); + m_sockets.emplace(kSocketId, std::move(socket)); + + RIALTO_IPC_LOG_INFO("added listening socket with fd: %d to server", fd); + + return true; +} + +std::shared_ptr ServerImpl::addClient(int socketFd, + std::function &)> clientDisconnectedCb) +{ + // sanity check the supplied socket is of the right type + struct sockaddr addr; + socklen_t len = sizeof(sockaddr); + if ((getsockname(socketFd, &addr, &len) < 0) || (len < sizeof(sa_family_t))) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get name of supplied socket"); + return nullptr; + } + if (addr.sa_family != AF_UNIX) + { + RIALTO_IPC_LOG_ERROR("supplied client socket is not a unix domain socket"); + return nullptr; + } + + int type = 0; + len = sizeof(type); + if ((getsockopt(socketFd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) || (len != sizeof(type))) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get type of supplied socket"); + return nullptr; + } + if (type != SOCK_SEQPACKET) + { + RIALTO_IPC_LOG_ERROR("supplied client socket is not of type SOCK_SEQPACKET"); + return nullptr; + } + + // dup the socket and set the O_CLOEXEC bit + int duppedFd = fcntl(socketFd, F_DUPFD_CLOEXEC, 3); + if (duppedFd < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get type of supplied socket"); + return nullptr; + } + + // ensure the SOCK_NONBLOCK flag is set + int flags = fcntl(duppedFd, F_GETFL); + if ((flags < 0) || (fcntl(duppedFd, F_SETFL, flags | O_NONBLOCK) < 0)) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to set socket to non-blocking mode"); + close(duppedFd); + return nullptr; + } + + // finally, add the socket to the list of clients + auto client = addClientSocket(duppedFd, "", std::move(clientDisconnectedCb)); + if (!client) + { + close(duppedFd); + } + + return client; +} + +int ServerImpl::fd() const +{ + return m_pollFd; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Writes to the eventfd to wake the event loop. Typically called when requesting + it to shutdown or external code has requested that a client be disconnected. + + */ +void ServerImpl::wakeEventLoop() const +{ + if (m_wakeEventFd < 0) + { + RIALTO_IPC_LOG_ERROR("invalid wake event fd"); + } + else + { + uint64_t value = 1; + if (TEMP_FAILURE_RETRY(::write(m_wakeEventFd, &value, sizeof(value))) != sizeof(value)) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to write to the event fd"); + } + } +} + +bool ServerImpl::wait(int timeoutMSecs) +{ + if (m_pollFd < 0) + { + return false; + } + + // wait for any event (with timeout) + struct pollfd fds[2]; + fds[0].fd = m_pollFd; + fds[0].events = POLLIN; + + int rc = TEMP_FAILURE_RETRY(poll(fds, 1, timeoutMSecs)); + if (rc < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "poll failed?"); + return false; + } + + return true; +} + +bool ServerImpl::process() +{ + if (m_pollFd < 0) + { + RIALTO_IPC_LOG_ERROR("missing epoll"); + return false; + } + + // read up to 32 events + const int kMaxEvents = 32; + struct epoll_event events[kMaxEvents]; + + int rc = TEMP_FAILURE_RETRY(epoll_wait(m_pollFd, events, kMaxEvents, 0)); + if (rc < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_wait failed"); + return false; + } + + // process the events (maybe 0 if timed out) + for (int i = 0; i < rc; i++) + { + const struct epoll_event &kEvent = events[i]; + + // check if a wake event, in which case just clear the eventfd + if (kEvent.data.u64 == WAKE_EVENT_ID) + { + uint64_t ignore; + if (TEMP_FAILURE_RETRY(::read(m_wakeEventFd, &ignore, sizeof(ignore))) != sizeof(ignore)) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to read wake eventfd"); + } + } + + // check for events on the listening socket + else if (kEvent.data.u64 < FIRST_CLIENT_ID) + { + if (kEvent.events & EPOLLIN) + processNewConnection(kEvent.data.u64); + if (kEvent.events & EPOLLERR) + RIALTO_IPC_LOG_ERROR("error occurred on listening socket"); + } + + // otherwise, the event must have come from a socket + else + { + processClientSocket(kEvent.data.u64, kEvent.events); + } + } + + // if we have client sockets that are condemned then we need to shut down + // and close them as well as remove from epoll + std::unique_lock locker(m_clientsLock); + if (!m_condemnedClients.empty()) + { + // take a copy of the set so we can process without the lock held + std::set theCondemned; + m_condemnedClients.swap(theCondemned); + + for (uint64_t clientId : theCondemned) + { + auto it = m_clients.find(clientId); + if (it == m_clients.end()) + { + RIALTO_IPC_LOG_ERROR("failed to find condemned client"); + continue; + } + + ClientDetails details = it->second; + + // remove from the list of clients + m_clients.erase(it); + + // drop the lock while closing the connection and removing from epoll + locker.unlock(); + + // remove the socket from epoll and close it + if (details.sock >= 0) + { + if (epoll_ctl(m_pollFd, EPOLL_CTL_DEL, details.sock, nullptr) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket from epoll"); + + if (shutdown(details.sock, SHUT_RDWR) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to shutdown socket"); + if (close(details.sock) != 0) + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close socket"); + } + + // let the installed handler know a client has disconnected + if (details.disconnectedCb) + details.disconnectedCb(details.client); + + // ensure client object is destructed without the client lock held + details.client.reset(); + + // re-take the lock for the next client + locker.lock(); + } + } + + return true; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Adds the \a socketFd to the internal list of client sockets. This is called + when a new connection is accepted on a listening socket, or when a client + fd is added via ServerImpl::addClient(...). + + Returns a nullptr if failed to add the socket. + + */ +std::shared_ptr ServerImpl::addClientSocket(int socketFd, const std::string &listeningSocketPath, + std::function &)> disconnectedCb) +{ + // get the client credentials + struct ucred clientCreds = {0}; + socklen_t clientCredsLen = sizeof(clientCreds); + + if ((getsockopt(socketFd, SOL_SOCKET, SO_PEERCRED, &clientCreds, &clientCredsLen) < 0) || + (clientCredsLen != sizeof(clientCreds))) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get client's details"); + return nullptr; + } + + // create a new unique client id for the connection + const uint64_t kClientId = m_clientIdCounter++; + + // add the new socket to the poll loop + epoll_event event = {.events = EPOLLIN, .data = {.u64 = kClientId}}; + if (epoll_ctl(m_pollFd, EPOLL_CTL_ADD, socketFd, &event) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add client socket"); + return nullptr; + } + + // create initial client object for the socket + auto client = std::make_shared(shared_from_this(), kClientId, clientCreds); + + // and the details for the internal list + ClientDetails clientDetails; + clientDetails.sock = socketFd; + clientDetails.disconnectedCb = std::move(disconnectedCb); + clientDetails.client = client; + + // add to the set of clients + { + std::lock_guard locker(m_clientsLock); + m_clients.emplace(kClientId, clientDetails); + } + + RIALTO_IPC_LOG_INFO("new client connected - giving id %" PRIu64, kClientId); + + return client; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Called when an event occurs on the listening socket. The code first accepts + the connection and retrieves the client details, it then calls the installed + handler to determine if we should drop this connection or not. + + + */ +void ServerImpl::processNewConnection(uint64_t socketId) +{ + RIALTO_IPC_LOG_DEBUG("processing new connection"); + + std::unique_lock socketLocker(m_socketsLock); + + // find matching socket object + auto it = m_sockets.find(socketId); + if (it == m_sockets.end()) + { + RIALTO_IPC_LOG_ERROR("failed to find listening socket with id %" PRIu64, socketId); + return; + } + + const Socket &kSocket = it->second; + + // accept the connection from the client + struct sockaddr clientAddr = {0}; + socklen_t clientAddrLen = sizeof(clientAddr); + + int clientSock = accept4(kSocket.sockFd, &clientAddr, &clientAddrLen, SOCK_NONBLOCK | SOCK_CLOEXEC); + if (clientSock < 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to accept client connection"); + return; + } + + const std::string kSockPath = kSocket.sockPath; + std::function &)> connectedCb = kSocket.connectedCb; + std::function &)> disconnectedCb = kSocket.disconnectedCb; + + socketLocker.unlock(); + + // attempt to add the socket to the client list + auto client = addClientSocket(clientSock, kSockPath, std::move(disconnectedCb)); + if (!client) + { + close(clientSock); + return; + } + + // notify the handler that a new connection has been made + if (connectedCb) + { + // tell the handler we have a new client + connectedCb(client); + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + \static + + Reads all the file descriptors from a message. It returns the file descriptors + as a vector of FileDescriptor objects, these objects safely store the fd and + close them when they're destructed. + + */ +static std::vector readMessageFds(const struct msghdr *msg, size_t limit) +{ + std::vector fds; + + for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != nullptr; + cmsg = CMSG_NXTHDR(const_cast(msg), cmsg)) + { + if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) + { + const unsigned kFdsLength = cmsg->cmsg_len - CMSG_LEN(0); + if ((kFdsLength < sizeof(int)) || ((kFdsLength % sizeof(int)) != 0)) + { + RIALTO_IPC_LOG_ERROR("invalid fd array size"); + } + else + { + const size_t n = kFdsLength / sizeof(int); + RIALTO_IPC_LOG_DEBUG("received %zu fds", n); + + fds.reserve(std::min(limit, n)); + + const int *kFds = reinterpret_cast(CMSG_DATA(cmsg)); + for (size_t i = 0; i < n; i++) + { + RIALTO_IPC_LOG_DEBUG("received fd %d", kFds[i]); + + if (fds.size() >= limit) + { + RIALTO_IPC_LOG_ERROR("received to many file descriptors, " + "exceeding max per message, closing left overs"); + } + else + { + FileDescriptor fd(kFds[i]); + if (!fd.isValid()) + { + RIALTO_IPC_LOG_ERROR("received invalid fd (couldn't dup)"); + } + else + { + fds.emplace_back(std::move(fd)); + } + } + + if (close(kFds[i]) != 0) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close received fd"); + } + } + } + } + } + + return fds; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Processes an event from a client socket. + + */ +void ServerImpl::processClientSocket(uint64_t clientId, unsigned events) +{ + // take the lock while accessing the client list + std::unique_lock locker(m_clientsLock); + + auto it = m_clients.find(clientId); + if (it == m_clients.end()) + { + // should never happen + RIALTO_IPC_LOG_ERROR("received an event from a socket with no matching client"); + return; + } + + // check if the client is marked for closure, if so then just ignore the data + if (m_condemnedClients.count(clientId) != 0) + { + return; + } + + // get the socket that corresponds to the client connection + const int kSockFd = it->second.sock; + + // get the client object + std::shared_ptr clientObj = it->second.client; + + // can safely release the lock now we have the clientId and client object + locker.unlock(); + + // if there was an error disconnect the socket + if (events & EPOLLERR) + { + RIALTO_IPC_LOG_ERROR("error detected on client socket - disconnecting client"); + disconnectClient(clientId); + return; + } + + if (events & EPOLLIN) + { + // read all messages from the client socket, we break out if the socket is closed + // or EWOULDBLOCK is returned on a read (ie. no more messages to read) + while (true) + { + struct msghdr msg = {nullptr}; + struct iovec io = {.iov_base = m_recvDataBuf, .iov_len = sizeof(m_recvDataBuf)}; + + bzero(&msg, sizeof(msg)); + msg.msg_iov = &io; + msg.msg_iovlen = 1; + msg.msg_control = m_recvCtrlBuf; + msg.msg_controllen = sizeof(m_recvCtrlBuf); + + // read one message + ssize_t rd = TEMP_FAILURE_RETRY(recvmsg(kSockFd, &msg, MSG_CMSG_CLOEXEC)); + if (rd < 0) + { + if (errno != EWOULDBLOCK) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "error reading client socket"); + disconnectClient(clientId); + } + + break; + } + else if (rd == 0) + { + // client closed connection, and we've read all data, add to the condemned set + // so is cleaned up once all the events are processed + disconnectClient(clientId); + + break; + } + else if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) + { + RIALTO_IPC_LOG_WARN("received message from client %" PRIu64 " truncated, discarding", clientId); + + // make sure to close all the fds, otherwise we'll leak them + readMessageFds(&msg, 16); + } + else + { + // if there is control data then assume fd(s) have been passed + if (msg.msg_controllen > 0) + { + processClientMessage(clientObj, m_recvDataBuf, rd, readMessageFds(&msg, 16)); + } + else + { + processClientMessage(clientObj, m_recvDataBuf, rd); + } + } + } + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Places the received file descriptors into the request message. + + It works by iterating over the fields in the message, finding ones that are + marked as 'field_is_fd' and then replacing the received integer value with + an actual file descriptor. + + */ +static bool addRequestFileDescriptors(google::protobuf::Message *request, const std::vector &requestFds) +{ + auto fdIterator = requestFds.begin(); + + const google::protobuf::Descriptor *kDescriptor = request->GetDescriptor(); + const google::protobuf::Reflection *kReflection = nullptr; + + const int n = kDescriptor->field_count(); + for (int i = 0; i < n; i++) + { + auto fieldDescriptor = kDescriptor->field(i); + if (fieldDescriptor->options().HasExtension(field_is_fd) && fieldDescriptor->options().GetExtension(field_is_fd)) + { + if (fieldDescriptor->type() != google::protobuf::FieldDescriptor::TYPE_INT32) + { + RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but not an int32 type"); + return false; + } + + if (!kReflection) + { + kReflection = request->GetReflection(); + } + + if (kReflection->HasField(*request, fieldDescriptor)) + { + if (fdIterator == requestFds.end()) + { + RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but one was supplied"); + return false; + } + + kReflection->SetInt32(request, fieldDescriptor, fdIterator->fd()); + ++fdIterator; + } + } + } + + if (fdIterator != requestFds.end()) + { + RIALTO_IPC_LOG_ERROR("received too many file descriptors in the message"); + return false; + } + + return true; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Processes a message received on a client socket. + + */ +void ServerImpl::processClientMessage(const std::shared_ptr &client, const uint8_t *data, size_t dataLen, + const std::vector &fds) +{ + RIALTO_IPC_LOG_DEBUG("processing client message of size %zu bytes (%zu fds) from client %" PRId64, dataLen, + fds.size(), client->id()); + + // parse the message + transport::MessageToServer message; + if (!message.ParseFromArray(data, static_cast(dataLen))) + { + RIALTO_IPC_LOG_ERROR("invalid request"); + return; + } + + if (message.has_call()) + { + processMethodCall(client, message.call(), fds); + } + else + { + RIALTO_IPC_LOG_WARN("received unknown message type from client"); + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Processes a method call requst from a client. + + */ +void ServerImpl::processMethodCall(const std::shared_ptr &client, const transport::MethodCall &call, + const std::vector &fds) +{ + // try and find the service with the given name + const std::string &kServiceName = call.service_name(); + auto it = client->m_services.find(kServiceName); + if (it == client->m_services.end()) + { + RIALTO_IPC_LOG_ERROR("unknown service request '%s'", kServiceName.c_str()); + + sendErrorReply(client, call.serial_id(), "Unknown service '%s'", kServiceName.c_str()); + return; + } + + std::shared_ptr service = it->second; + + // try and find the method + const std::string &kMethodName = call.method_name(); + const google::protobuf::MethodDescriptor *kMethod = service->GetDescriptor()->FindMethodByName(kMethodName); + if (!kMethod) + { + RIALTO_IPC_LOG_ERROR("no method with name '%s'", kMethodName.c_str()); + + sendErrorReply(client, call.serial_id(), "Unknown method '%s'", kMethodName.c_str()); + return; + } + + // check if the method is expecting a reply + const bool kNoReply = kMethod->options().HasExtension(no_reply) && kMethod->options().GetExtension(no_reply); + + // parse the request data + google::protobuf::Message *requestMessage = service->GetRequestPrototype(kMethod).New(); + if (!requestMessage->ParseFromString(call.request_message())) + { + RIALTO_IPC_LOG_ERROR("failed to parse method from array"); + } + else if (!addRequestFileDescriptors(requestMessage, fds)) + { + RIALTO_IPC_LOG_ERROR("mismatch of file descriptors to the request"); + } + else + { + RIALTO_IPC_LOG_DEBUG("call{ serial %" PRIu64 " } - %s.%s { %s }", call.serial_id(), kServiceName.c_str(), + kMethodName.c_str(), requestMessage->ShortDebugString().c_str()); + + auto *controller = new ServerControllerImpl(client, call.serial_id()); + + if (kNoReply) + { + // we should not send a reply for this call, so call the code to handle the + // request, but no need to pass a controller, response or closure object + static google::protobuf::internal::FunctionClosure0 nullClosure(&google::protobuf::DoNothing, false); + service->CallMethod(kMethod, controller, requestMessage, nullptr, &nullClosure); + + delete controller; + } + else + { + // create a response + google::protobuf::Message *responseMessage = service->GetResponsePrototype(kMethod).New(); + + // this is finally where we call the service implementation to process the request + service->CallMethod(kMethod, controller, requestMessage, responseMessage, + google::protobuf::NewCallback(this, &ServerImpl::handleResponse, controller, + responseMessage)); + } + } + + delete requestMessage; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + \threadsafe + + Sends a message to the given client if still connected. + + */ +void ServerImpl::sendReply(uint64_t clientId, const std::shared_ptr &msg) +{ + // now take the lock (so the socket is not closed beneath us) and send the reply + std::lock_guard locker(m_clientsLock); + + auto it = m_clients.find(clientId); + if (it == m_clients.end()) + { + RIALTO_IPC_LOG_WARN("socket removed before error reply could be sent"); + } + else if (it->second.sock < 0) + { + RIALTO_IPC_LOG_WARN("socket closed before error reply could be sent"); + } + else if (!msg) + { + RIALTO_IPC_LOG_WARN("invalid msg to send on socket, ignoring"); + } + else if (TEMP_FAILURE_RETRY(sendmsg(it->second.sock, msg.get(), MSG_NOSIGNAL)) != + static_cast(msg->msg_iov->iov_len)) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to send the complete error reply message"); + } +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Sends an error back to the client with a reason string in \a format. + + */ +void ServerImpl::sendErrorReply(const std::shared_ptr &client, uint64_t serialId, const char *format, ...) +{ + // construct the error string + va_list ap; + va_start(ap, format); + char reason[512]; + vsnprintf(reason, sizeof(reason), format, ap); + va_end(ap); + + // construct the reply message + auto msg = populateErrorReply(client, serialId, reason); + + // and send it + sendReply(client->id(), msg); +} + +// ----------------------------------------------------------------------------- +/*! + \internal + \threadsafe + + Called once the service handler code has processed the request and + completed it. This may be called from a different thread if the service + implementation decided to off-load the request to a processing thread. + + */ +void ServerImpl::handleResponse(ServerControllerImpl *controller, google::protobuf::Message *response) +{ + if (!controller || !controller->m_kClient) + { + RIALTO_IPC_LOG_ERROR("missing controller or attached client"); + return; + } + + const std::shared_ptr kClient = controller->m_kClient; + const uint64_t kClientId = kClient->id(); + + std::shared_ptr message; + if (!controller->m_failed) + { + message = populateReply(kClient, controller->m_kSerialId, response); + } + else + { + message = populateErrorReply(kClient, controller->m_kSerialId, controller->m_failureReason); + } + + // no longer need the controller or the response objects + delete response; + delete controller; + + // send the reply message to the given client + sendReply(kClientId, message); +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Gets all the file descriptors that are stored in the \a response message + and returns them as a vector of ints. + + It works by iterating over the fields in the message, finding ones that are + marked as 'field_is_fd' and inserting the fd value into control part of the + message. The actual integer sent in the data part of the message is set to + -1. + + */ +static std::vector getResponseFileDescriptors(google::protobuf::Message *response) +{ + std::vector fds; + + // process any file descriptors from the response message + const google::protobuf::Descriptor *kDescriptor = response->GetDescriptor(); + const google::protobuf::Reflection *kReflection = nullptr; + + const int n = kDescriptor->field_count(); + for (int i = 0; i < n; i++) + { + auto fieldDescriptor = kDescriptor->field(i); + if (fieldDescriptor->options().HasExtension(field_is_fd) && fieldDescriptor->options().GetExtension(field_is_fd)) + { + if (fieldDescriptor->type() != google::protobuf::FieldDescriptor::TYPE_INT32) + { + RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but not an int32 type"); + return {}; + } + + if (!kReflection) + { + kReflection = response->GetReflection(); + } + + if (kReflection->HasField(*response, fieldDescriptor)) + { + fds.push_back(kReflection->GetInt32(*response, fieldDescriptor)); + kReflection->SetInt32(response, fieldDescriptor, -1); + } + } + } + + return fds; +} + +// ----------------------------------------------------------------------------- +/*! + \internal + \static + + Populates tha socket message buffer with the reply data for the RPC request. + + */ +std::shared_ptr ServerImpl::populateReply(const std::shared_ptr &client, uint64_t serialId, + google::protobuf::Message *response) +{ + // create the base reply + transport::MessageFromServer message; + transport::MethodCallReply *reply = message.mutable_reply(); + if (!reply) + { + RIALTO_IPC_LOG_ERROR("failed to create mutable reply object"); + return nullptr; + } + + // convert the message response to a data string + std::string respString = response->SerializeAsString(); + + // wrap in a transport response and send that + reply->set_reply_id(serialId); + reply->set_reply_message(std::move(respString)); + + // next need to check if the response message has any file descriptors in + // it that need to be attached + const std::vector kFds = getResponseFileDescriptors(response); + const size_t kRequiredCtrlLen = kFds.empty() ? 0 : CMSG_SPACE(sizeof(int) * kFds.size()); + + // calculate the size of the reply + const size_t kRequiredDataLen = message.ByteSizeLong(); + if (kRequiredDataLen > m_kMaxMessageLen) + { + RIALTO_IPC_LOG_ERROR("reply exceeds maximum message limit (%zu, max %zu)", kRequiredDataLen, m_kMaxMessageLen); + + // error message is too big, replace with a generic error + return populateErrorReply(client, serialId, "Internal error - reply message to large"); + } + + // build the socket message to send + auto msgBuf = + m_sendBufPool.allocateShared(sizeof(msghdr) + sizeof(iovec) + kRequiredCtrlLen + kRequiredDataLen); + + auto *header = reinterpret_cast(msgBuf.get()); + bzero(header, sizeof(msghdr)); + + auto *ctrl = reinterpret_cast(msgBuf.get() + sizeof(msghdr)); + header->msg_control = ctrl; + header->msg_controllen = kRequiredCtrlLen; + + auto *iov = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen); + header->msg_iov = iov; + header->msg_iovlen = 1; + + auto *data = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen + sizeof(iovec)); + iov->iov_base = data; + iov->iov_len = kRequiredDataLen; + + // copy in the data + message.SerializeWithCachedSizesToArray(data); + + // add the fds + if (!kFds.empty()) + { + struct cmsghdr *cmsg = CMSG_FIRSTHDR(header); + if (!cmsg) + { + RIALTO_IPC_LOG_ERROR("odd, failed to get the first cmsg header"); + return nullptr; + } + + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int) * kFds.size()); + memcpy(CMSG_DATA(cmsg), kFds.data(), sizeof(int) * kFds.size()); + header->msg_controllen = cmsg->cmsg_len; + } + + RIALTO_IPC_LOG_DEBUG("reply{ serial %" PRIu64 " } - { %s }", serialId, response->ShortDebugString().c_str()); + + // std::reinterpret_pointer_cast is only implemented in C++17 and newer, so for + // now do it manually + return std::shared_ptr(msgBuf, reinterpret_cast(msgBuf.get())); +} + +// ----------------------------------------------------------------------------- +/*! + \internal + + Populates tha socket message buffer with a reply error message. + + */ +std::shared_ptr ServerImpl::populateErrorReply(const std::shared_ptr &client, + uint64_t serialId, const std::string &reason) +{ + // create the base reply + transport::MessageFromServer message; + transport::MethodCallError *error = message.mutable_error(); + error->set_reply_id(serialId); + error->set_error_reason(reason); + + // check the message will fit + size_t replySize = message.ByteSizeLong(); + if (replySize > m_kMaxMessageLen) + { + RIALTO_IPC_LOG_ERROR("error reply exceeds max message size"); + + // error message is to big, replace with a generic error + error->set_error_reason("Error message truncated"); + replySize = message.ByteSizeLong(); + } + + RIALTO_IPC_LOG_DEBUG("error{ serial %" PRIu64 " } - \"%s\"", serialId, reason.c_str()); + + // construct the message to send on the socket + auto msgBuf = m_sendBufPool.allocateShared(sizeof(msghdr) + sizeof(iovec) + replySize); + + auto *header = reinterpret_cast(msgBuf.get()); + bzero(header, sizeof(msghdr)); + + auto *iov = reinterpret_cast(msgBuf.get() + sizeof(msghdr)); + header->msg_iov = iov; + header->msg_iovlen = 1; + + auto *data = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + sizeof(iovec)); + iov->iov_base = data; + iov->iov_len = replySize; + + // serialise the reply to the message buffer + message.SerializeWithCachedSizesToArray(data); + + // std::reinterpret_pointer_cast is only implemented in C++17 and newer, so for + // now do it manually + return std::shared_ptr(msgBuf, reinterpret_cast(msgBuf.get())); +} + +// ----------------------------------------------------------------------------- +/*! + \threadsafe + + Returns \c true if the client with \a clientId is currently connected to + the server. + + */ +bool ServerImpl::isClientConnected(uint64_t clientId) const +{ + std::unique_lock locker(m_clientsLock); + return (m_clients.count(clientId) > 0); +} + +// ----------------------------------------------------------------------------- +/*! + \threadsafe + + May be called internally when there is an error on the socket, or externally + (possibly from a different thread) if the handler or service code decides to + close the client connection. + + */ +void ServerImpl::disconnectClient(uint64_t clientId) +{ + std::unique_lock locker(m_clientsLock); + m_condemnedClients.insert(clientId); + locker.unlock(); + + wakeEventLoop(); +} + +// ----------------------------------------------------------------------------- +/*! + \threadsafe + + Called via the IAVBusClient interface when an async event should be sent. + + This may be called from any thread, or from within the rpc message handler. + + The \a clientId is the client to send the event to. + + */ +bool ServerImpl::sendEvent(uint64_t clientId, const std::shared_ptr &eventMessage) +{ + // gets the file descriptors from the event message + const std::vector kFds = getResponseFileDescriptors(eventMessage.get()); + const size_t kRequiredCtrlLen = kFds.empty() ? 0 : CMSG_SPACE(sizeof(int) * kFds.size()); + + // create the base reply + transport::MessageFromServer message; + transport::EventFromServer *event = message.mutable_event(); + if (!event) + { + RIALTO_IPC_LOG_ERROR("failed to create mutable event object"); + return false; + } + + event->set_event_name(eventMessage->GetTypeName()); + + // convert the event to a data string + std::string respString = eventMessage->SerializeAsString(); + + // wrap in a transport response and send that + event->set_message(std::move(respString)); + + // check the reply will fit + size_t requiredDataLen = message.ByteSizeLong(); + if (requiredDataLen > m_kMaxMessageLen) + { + RIALTO_IPC_LOG_ERROR("event message to big to fit in buffer (size %zu, max size %zu)", requiredDataLen, + m_kMaxMessageLen); + return false; + } + + // build the socket message to send + auto msgBuf = + m_sendBufPool.allocateShared(sizeof(msghdr) + sizeof(iovec) + kRequiredCtrlLen + requiredDataLen); + + auto *header = reinterpret_cast(msgBuf.get()); + bzero(header, sizeof(msghdr)); + + auto *ctrl = reinterpret_cast(msgBuf.get() + sizeof(msghdr)); + header->msg_control = ctrl; + header->msg_controllen = kRequiredCtrlLen; + + auto *iov = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen); + header->msg_iov = iov; + header->msg_iovlen = 1; + + auto *data = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen + sizeof(iovec)); + iov->iov_base = data; + iov->iov_len = requiredDataLen; + + // copy in the data + message.SerializeWithCachedSizesToArray(data); + + // add the fds + if (!kFds.empty()) + { + struct cmsghdr *cmsg = CMSG_FIRSTHDR(header); + if (!cmsg) + { + RIALTO_IPC_LOG_ERROR("odd, failed to get the first cmsg header"); + return false; + } + + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int) * kFds.size()); + memcpy(CMSG_DATA(cmsg), kFds.data(), sizeof(int) * kFds.size()); + header->msg_controllen = cmsg->cmsg_len; + } + + // finally, take the lock (so the socket is not closed beneath us) and send the reply + std::unique_lock locker(m_clientsLock); + + auto it = m_clients.find(clientId); + if (it == m_clients.end() || it->second.sock < 0) + { + RIALTO_IPC_LOG_WARN("socket closed before event could be sent"); + return false; + } + else if (TEMP_FAILURE_RETRY(sendmsg(it->second.sock, header, MSG_NOSIGNAL)) != static_cast(requiredDataLen)) + { + RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to send the complete event message"); + return false; + } + + locker.unlock(); + + RIALTO_IPC_LOG_DEBUG("event{ %s } - { %s }", eventMessage->GetTypeName().c_str(), + eventMessage->ShortDebugString().c_str()); + + return true; +} +} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/server/source/IpcServerImpl.h b/middleware/rialto-client/ipc/server/source/IpcServerImpl.h new file mode 100644 index 000000000..591f2a80b --- /dev/null +++ b/middleware/rialto-client/ipc/server/source/IpcServerImpl.h @@ -0,0 +1,159 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_IPC_IPC_SERVER_IMPL_H_ +#define FIREBOLT_RIALTO_IPC_IPC_SERVER_IMPL_H_ + +#include "FileDescriptor.h" +#include "IIpcServer.h" +#include "IIpcServerFactory.h" +#include "IpcServerControllerImpl.h" +#include "SimpleBufferPool.h" + +#include "rialtoipc-transport.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !defined(SCM_MAX_FD) +#define SCM_MAX_FD 255 +#endif + +namespace firebolt::rialto::ipc +{ +class ClientImpl; + +class ServerFactory : public IServerFactory +{ +public: + ServerFactory() = default; + ~ServerFactory() override = default; + + std::shared_ptr create() override; +}; + +class ServerImpl final : public ::firebolt::rialto::ipc::IServer, public std::enable_shared_from_this +{ +public: + explicit ServerImpl(); + ~ServerImpl() final; + +public: + bool addSocket(const std::string &socketPath, std::function &)> clientConnectedCb, + std::function &)> clientDisconnectedCb) override; + bool addSocket(int fd, std::function &)> clientConnectedCb, + std::function &)> clientDisconnectedCb) override; + + std::shared_ptr + addClient(int socketFd, std::function &)> clientDisconnectedCb) override; + + int fd() const override; + bool wait(int timeoutMSecs) override; + bool process() override; + +protected: + friend class ClientImpl; + bool sendEvent(uint64_t clientId, const std::shared_ptr &message); + bool isClientConnected(uint64_t clientId) const; + void disconnectClient(uint64_t clientId); + +private: + struct Socket; + static bool getSocketLock(Socket *socket); + static void closeListeningSocket(Socket *socket); + + void wakeEventLoop() const; + + void processNewConnection(uint64_t socketId); + + void processClientSocket(uint64_t clientId, unsigned events); + void processClientMessage(const std::shared_ptr &client, const uint8_t *data, size_t dataLen, + const std::vector &fds = {}); + + void processMethodCall(const std::shared_ptr &client, const transport::MethodCall &call, + const std::vector &fds); + + std::shared_ptr addClientSocket(int socketFd, const std::string &listeningSocketPath, + std::function &)> disconnectedCb); + + void sendReply(uint64_t clientId, const std::shared_ptr &msg); + + void sendErrorReply(const std::shared_ptr &client, uint64_t serialId, const char *format, ...) + __attribute__((format(printf, 4, 5))); + + void handleResponse(ServerControllerImpl *controller, google::protobuf::Message *response); + + std::shared_ptr populateReply(const std::shared_ptr &client, uint64_t serialId, + google::protobuf::Message *response); + std::shared_ptr populateErrorReply(const std::shared_ptr &client, uint64_t serialId, + const std::string &reason); + +private: + static const size_t m_kMaxMessageLen; + + int m_pollFd; + int m_wakeEventFd; + + std::atomic m_socketIdCounter; + std::atomic m_clientIdCounter; + + struct Socket + { + int sockFd = -1; + int lockFd = -1; + std::string sockPath; + std::string lockPath; + std::function &)> connectedCb; + std::function &)> disconnectedCb; + bool isOwned = true; + }; + + std::mutex m_socketsLock; + std::map m_sockets; + + struct ClientDetails + { + int sock = -1; + std::shared_ptr client; + std::function &)> disconnectedCb; + }; + + mutable std::mutex m_clientsLock; + + std::map m_clients; + std::set m_condemnedClients; + + uint8_t m_recvDataBuf[128 * 1024]; + uint8_t m_recvCtrlBuf[SCM_MAX_FD * sizeof(int)]; + + SimpleBufferPool m_sendBufPool; +}; + +} // namespace firebolt::rialto::ipc + +#endif // FIREBOLT_RIALTO_IPC_IPC_SERVER_IMPL_H_ diff --git a/middleware/rialto-client/logging/CMakeLists.txt b/middleware/rialto-client/logging/CMakeLists.txt new file mode 100644 index 000000000..2c0751238 --- /dev/null +++ b/middleware/rialto-client/logging/CMakeLists.txt @@ -0,0 +1,53 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2025 Sky UK +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set(RialtoLogging_HEADERS + include/RialtoLogging.h + ) + +set(RialtoLogging_SOURCES + source/EnvVariableParser.cpp + source/EnvVariableParser.h + source/LogFileHandle.cpp + source/LogFileHandle.h + source/RialtoLogging.cpp + ) + +set(RialtoLogging_INCLUDES + "${CMAKE_CURRENT_SOURCE_DIR}/include" + ) + +add_library(RialtoLogging STATIC ${RialtoLogging_HEADERS} ${RialtoLogging_SOURCES}) +target_include_directories(RialtoLogging PUBLIC "$") +set_target_properties(RialtoLogging PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) +set_target_properties(RialtoLogging PROPERTIES POSITION_INDEPENDENT_CODE ON) + +find_package(EthanLog) +if (EthanLog_FOUND AND RIALTO_ENABLE_ETHAN_LOG) + message(STATUS "EthanLog is enabled") + add_library(RialtoEthanLog STATIC ${RialtoLogging_HEADERS} ${RialtoLogging_SOURCES}) + target_include_directories(RialtoEthanLog PUBLIC "$") + target_compile_definitions(RialtoEthanLog PRIVATE USE_ETHANLOG) + target_link_libraries(RialtoEthanLog PUBLIC EthanLog::EthanLog) + set_target_properties(RialtoEthanLog PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) + set_target_properties(RialtoEthanLog PROPERTIES POSITION_INDEPENDENT_CODE ON) +else () + message(STATUS "EthanLog is disabled") + add_library(RialtoEthanLog ALIAS RialtoLogging) +endif () diff --git a/middleware/rialto-client/logging/include/RialtoLogging.h b/middleware/rialto-client/logging/include/RialtoLogging.h new file mode 100644 index 000000000..ca97a228a --- /dev/null +++ b/middleware/rialto-client/logging/include/RialtoLogging.h @@ -0,0 +1,235 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_LOGGING_RIALTO_LOGGING_H_ +#define FIREBOLT_RIALTO_LOGGING_RIALTO_LOGGING_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + + /** + * Defined log levels used to set the required output logs for the component + */ + enum RIALTO_DEBUG_LEVEL + { + RIALTO_DEBUG_LEVEL_FATAL = (1u << 0), + RIALTO_DEBUG_LEVEL_ERROR = (1u << 1), + RIALTO_DEBUG_LEVEL_WARNING = (1u << 2), + RIALTO_DEBUG_LEVEL_MILESTONE = (1u << 3), + RIALTO_DEBUG_LEVEL_INFO = (1u << 4), + RIALTO_DEBUG_LEVEL_DEBUG = (1u << 5), + RIALTO_DEBUG_LEVEL_EXTERNAL = + (1u << 6), // Level controlled by an external variable, like e.g. GST_DEBUG. Keep it as last level. + + RIALTO_DEBUG_LEVEL_DEFAULT = (RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING | + RIALTO_DEBUG_LEVEL_MILESTONE) + }; + + /** + * Possible components for logging. + */ + enum RIALTO_COMPONENT + { + RIALTO_COMPONENT_DEFAULT = 0u, + RIALTO_COMPONENT_CLIENT, + RIALTO_COMPONENT_SERVER, + RIALTO_COMPONENT_IPC, + RIALTO_COMPONENT_SERVER_MANAGER, + RIALTO_COMPONENT_COMMON, + RIALTO_COMPONENT_EXTERNAL, // External component, like e.g. GStreamer. Keep it as last component. + RIALTO_COMPONENT_LAST, + }; + + /** + * Utility functions used by the logging macros to produce the log output + */ + extern void rialtoLogVPrintf(enum RIALTO_COMPONENT component, enum RIALTO_DEBUG_LEVEL level, const char *file, + const char *func, int line, const char *fmt, va_list ap) + __attribute__((format(printf, 6, 0))); + extern void rialtoLogPrintf(enum RIALTO_COMPONENT component, enum RIALTO_DEBUG_LEVEL level, const char *file, + const char *func, int line, const char *fmt, ...) __attribute__((format(printf, 6, 7))); + extern void rialtoLogSysPrintf(enum RIALTO_COMPONENT component, int err, enum RIALTO_DEBUG_LEVEL level, + const char *file, const char *func, int line, const char *fmt, ...) + __attribute__((format(printf, 7, 8))); + + /** + * Macros to be used for logging + */ + +#ifdef RIALTO_LOG_FATAL_ENABLED +#define RIALTO_LOG_FATAL(component, fmt, args...) \ + do \ + { \ + rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_FATAL, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) + +#define RIALTO_LOG_SYS_FATAL(component, err, fmt, args...) \ + do \ + { \ + rialtoLogSysPrintf(component, err, RIALTO_DEBUG_LEVEL_FATAL, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) +#else +#define RIALTO_LOG_FATAL(component, fmt, args...) +#define RIALTO_LOG_SYS_FATAL(component, err, fmt, args...) +#endif + +#ifdef RIALTO_LOG_ERROR_ENABLED +#define RIALTO_LOG_ERROR(component, fmt, args...) \ + do \ + { \ + rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_ERROR, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) + +#define RIALTO_LOG_SYS_ERROR(component, err, fmt, args...) \ + do \ + { \ + rialtoLogSysPrintf(component, err, RIALTO_DEBUG_LEVEL_ERROR, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) +#else +#define RIALTO_LOG_ERROR(component, fmt, args...) +#define RIALTO_LOG_SYS_ERROR(component, err, fmt, args...) +#endif + +#ifdef RIALTO_LOG_WARN_ENABLED +#define RIALTO_LOG_WARN(component, fmt, args...) \ + do \ + { \ + rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_WARNING, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) +#define RIALTO_LOG_SYS_WARN(component, err, fmt, args...) \ + do \ + { \ + rialtoLogSysPrintf(component, err, RIALTO_DEBUG_LEVEL_WARNING, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) +#else +#define RIALTO_LOG_WARN(component, fmt, args...) +#define RIALTO_LOG_SYS_WARN(component, err, fmt, args...) +#endif + +#ifdef RIALTO_LOG_MIL_ENABLED +#define RIALTO_LOG_MIL(component, fmt, args...) \ + do \ + { \ + rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_MILESTONE, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) +#else +#define RIALTO_LOG_MIL(component, fmt, args...) +#endif + +#ifdef RIALTO_LOG_INFO_ENABLED +#define RIALTO_LOG_INFO(component, fmt, args...) \ + do \ + { \ + rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_INFO, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) +#else +#define RIALTO_LOG_INFO(component, fmt, args...) +#endif + +#ifdef RIALTO_LOG_DEBUG_ENABLED +#define RIALTO_LOG_DEBUG(component, fmt, args...) \ + do \ + { \ + rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_DEBUG, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ + } while (false) +#else +#define RIALTO_LOG_DEBUG(component, fmt, args...) +#endif + +#define RIALTO_LOG_EXTERNAL(fmt, args...) \ + do \ + { \ + rialtoLogPrintf(RIALTO_COMPONENT_EXTERNAL, RIALTO_DEBUG_LEVEL_EXTERNAL, __FILE__, __FUNCTION__, __LINE__, fmt, \ + ##args); \ + } while (false) + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus + +#include + +namespace firebolt::rialto::logging +{ +/** + * Error Return Status. + */ +enum RialtoLoggingStatus : uint32_t +{ + RIALTO_LOGGING_STATUS_OK = 0u, + RIALTO_LOGGING_STATUS_ERROR, +}; + +/** + * @brief Set the logging levels required. + * + * See RIALTO_DEBUG_LEVEL_* for possible log levels. Multiple log levels can be set + * at once, for example: (RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR). + * Setting new log levels shall completely overwrite the previous log level set. + * @retval RIALTO_LOGGING_STATUS_OK on success. Note that if setLogHandler() has been + * called (for this component) with ignoreLogLevels==true then this will return + * RIALTO_LOGGING_STATUS_ERROR + * + * @param[in] logLevels : The levels of logging to set. + * @param[in] component : The component to set the log levels on. + */ +RialtoLoggingStatus setLogLevels(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL logLevels); + +/** + * @brief Get current logging levels. + * + * See RIALTO_DEBUG_LEVEL_* for possible log levels. + * If setLogHandler() has been called with ignoreLogLevels==true then this will return RIALTO_DEBUG_LEVEL_EXTERNAL + * + * @param[in] component : The component to get the log levels from. + */ +RIALTO_DEBUG_LEVEL getLogLevels(RIALTO_COMPONENT component); + +/** + * @brief Set the log handler used to process the logs. + * + * After requesting a logHandler then it can be cancelled by + * calling setLogHandler again with the handler passed as a nullptr + * + * @param[in] handler : The log handler. + * @param[in] component : The component to set the log handler on. + */ +using LogHandler = std::function; +RialtoLoggingStatus setLogHandler(RIALTO_COMPONENT component, LogHandler handler, bool ignoreLogLevels); + +/** + * @brief Checks if rialto logs to console. + * + * @retval: Returns true, if rialto is logging to console + */ +bool isConsoleLoggingEnabled(); + +} // namespace firebolt::rialto::logging + +#endif // defined(__cplusplus) + +#endif // FIREBOLT_RIALTO_LOGGING_RIALTO_LOGGING_H_ diff --git a/middleware/rialto-client/logging/source/EnvVariableParser.cpp b/middleware/rialto-client/logging/source/EnvVariableParser.cpp new file mode 100644 index 000000000..5ef89d89c --- /dev/null +++ b/middleware/rialto-client/logging/source/EnvVariableParser.cpp @@ -0,0 +1,223 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "EnvVariableParser.h" +#include "LogFileHandle.h" +#include +#include +#include +#include + +namespace +{ +std::string getRialtoDebug() +{ + const char *kDebugVar = getenv("RIALTO_DEBUG"); + if (kDebugVar) + { + return std::string(kDebugVar); + } + return ""; +} + +std::string getRialtoConsoleLog() +{ + const char *kDebugVar = getenv("RIALTO_CONSOLE_LOG"); + if (kDebugVar) + { + return std::string(kDebugVar); + } + return ""; +} + +std::string getRialtoLogPath() +{ + const char *kLogPathEnvVar = getenv("RIALTO_LOG_PATH"); + if (kLogPathEnvVar) + { + return std::string(kLogPathEnvVar); + } + return ""; +} + +inline bool isNumber(const std::string &str) +{ + return std::find_if(str.begin(), str.end(), [](unsigned char c) { return !std::isdigit(c); }) == str.end(); +} + +std::vector split(std::string s, const std::string &delimiter) +{ + std::vector result; + size_t pos = 0; + while ((pos = s.find(delimiter)) != std::string::npos) + { + result.push_back(s.substr(0, pos)); + s.erase(0, pos + delimiter.length()); + } + result.push_back(s); + return result; +} + +std::map parseEnvVar(const std::string &envVar) +{ + std::map flagValues; + auto componentsWithLevels{split(envVar, ";")}; + for (const auto &item : componentsWithLevels) + { + auto componentWithLevel{split(item, ":")}; + if (componentWithLevel.size() != 2 || !isNumber(componentWithLevel[1])) + continue; + flagValues[componentWithLevel[0]] = std::stoi(componentWithLevel[1]); + } + return flagValues; +} + +RIALTO_DEBUG_LEVEL levelFromNumber(int level) +{ + switch (level) + { + case 0: + return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL); + case 1: + return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR); + case 2: + return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING); + case 3: + return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING | + RIALTO_DEBUG_LEVEL_MILESTONE); + case 4: + return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING | + RIALTO_DEBUG_LEVEL_MILESTONE | RIALTO_DEBUG_LEVEL_INFO); + case 5: + return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING | + RIALTO_DEBUG_LEVEL_MILESTONE | RIALTO_DEBUG_LEVEL_INFO | RIALTO_DEBUG_LEVEL_DEBUG); + } + return RIALTO_DEBUG_LEVEL_DEFAULT; +} + +RIALTO_COMPONENT componentFromStr(const std::string &component) +{ + if ("client" == component) + { + return RIALTO_COMPONENT_CLIENT; + } + if ("sessionserver" == component) + { + return RIALTO_COMPONENT_SERVER; + } + if ("ipc" == component) + { + return RIALTO_COMPONENT_IPC; + } + if ("servermanager" == component) + { + return RIALTO_COMPONENT_SERVER_MANAGER; + } + if ("common" == component) + { + return RIALTO_COMPONENT_COMMON; + } + return RIALTO_COMPONENT_LAST; +} +} // namespace + +namespace firebolt::rialto::logging +{ +EnvVariableParser::EnvVariableParser() + : m_debugLevels{{RIALTO_COMPONENT_CLIENT, RIALTO_DEBUG_LEVEL_DEFAULT}, + {RIALTO_COMPONENT_SERVER, RIALTO_DEBUG_LEVEL_DEFAULT}, + {RIALTO_COMPONENT_IPC, RIALTO_DEBUG_LEVEL_DEFAULT}, + {RIALTO_COMPONENT_SERVER_MANAGER, RIALTO_DEBUG_LEVEL_DEFAULT}, + {RIALTO_COMPONENT_COMMON, RIALTO_DEBUG_LEVEL_DEFAULT}}, + m_logToConsole{false}, m_logFilePath{getRialtoLogPath()} +{ + configureRialtoDebug(); + configureRialtoConsoleLog(); + configureFileLogging(); +} + +void EnvVariableParser::configureRialtoDebug() +{ + std::string debugFlagEnvVar = getRialtoDebug(); + if (debugFlagEnvVar.empty()) + return; + if (isNumber(debugFlagEnvVar)) + { + int level = std::stoi(debugFlagEnvVar); + for (auto &elem : m_debugLevels) + elem.second = levelFromNumber(level); + return; + } + auto flagValues{parseEnvVar(debugFlagEnvVar)}; + auto defaultFlagIter = flagValues.find("*"); + if (defaultFlagIter != flagValues.end()) + { + for (auto &elem : m_debugLevels) + elem.second = levelFromNumber(defaultFlagIter->second); + flagValues.erase(defaultFlagIter); + } + for (const auto &value : flagValues) + { + auto currentLevelIter = m_debugLevels.find(componentFromStr(value.first)); + if (currentLevelIter != m_debugLevels.end()) + { + currentLevelIter->second = levelFromNumber(value.second); + } + } +} + +void EnvVariableParser::configureRialtoConsoleLog() +{ + std::string debugFlagEnvVar = getRialtoConsoleLog(); + if (debugFlagEnvVar == "1") + { + m_logToConsole = true; + } +} + +void EnvVariableParser::configureFileLogging() +{ + if (isFileLoggingEnabled()) + { + LogFileHandle::instance().init(m_logFilePath); + } +} + +RIALTO_DEBUG_LEVEL EnvVariableParser::getLevel(const RIALTO_COMPONENT &component) const +{ + if (RIALTO_COMPONENT_EXTERNAL == component) + { + return RIALTO_DEBUG_LEVEL_EXTERNAL; + } + auto levelIter = m_debugLevels.find(component); + if (levelIter == m_debugLevels.end()) + return RIALTO_DEBUG_LEVEL_DEFAULT; + return levelIter->second; +} + +bool EnvVariableParser::isConsoleLoggingEnabled() const +{ + return m_logToConsole; +} + +bool EnvVariableParser::isFileLoggingEnabled() const +{ + return !m_logFilePath.empty(); +} +} // namespace firebolt::rialto::logging diff --git a/middleware/rialto-client/logging/source/EnvVariableParser.h b/middleware/rialto-client/logging/source/EnvVariableParser.h new file mode 100644 index 000000000..82e8fee50 --- /dev/null +++ b/middleware/rialto-client/logging/source/EnvVariableParser.h @@ -0,0 +1,57 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_LOGGING_ENV_VARIABLE_PARSER_H_ +#define FIREBOLT_RIALTO_LOGGING_ENV_VARIABLE_PARSER_H_ +#ifdef __cplusplus + +#include "RialtoLogging.h" +#include +#include + +namespace firebolt::rialto::logging +{ +class EnvVariableParser +{ +public: + EnvVariableParser(); + ~EnvVariableParser() = default; + EnvVariableParser(const EnvVariableParser &) = delete; + EnvVariableParser(EnvVariableParser &&) = delete; + EnvVariableParser &operator=(const EnvVariableParser &) = delete; + EnvVariableParser &operator=(EnvVariableParser &&) = delete; + + RIALTO_DEBUG_LEVEL getLevel(const RIALTO_COMPONENT &component) const; + bool isConsoleLoggingEnabled() const; + bool isFileLoggingEnabled() const; + +private: + void configureRialtoDebug(); + void configureRialtoConsoleLog(); + void configureFileLogging(); + +private: + std::map m_debugLevels; + bool m_logToConsole; + std::string m_logFilePath; +}; +} // namespace firebolt::rialto::logging + +#endif // defined(__cplusplus) +#endif // FIREBOLT_RIALTO_LOGGING_ENV_VARIABLE_PARSER_H_ diff --git a/middleware/rialto-client/logging/source/LogFileHandle.cpp b/middleware/rialto-client/logging/source/LogFileHandle.cpp new file mode 100644 index 000000000..0b6b7bf1d --- /dev/null +++ b/middleware/rialto-client/logging/source/LogFileHandle.cpp @@ -0,0 +1,60 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LogFileHandle.h" + +#include +#include + +namespace firebolt::rialto::logging +{ +LogFileHandle &LogFileHandle::instance() +{ + static LogFileHandle handle; + return handle; +} + +void LogFileHandle::init(const std::string &path) +{ + if (-1 == m_fd) + { + m_fd = open(path.c_str(), O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC, 0664); + } +} + +int LogFileHandle::fd() const +{ + return m_fd; +} + +bool LogFileHandle::isOpen() const +{ + return m_fd != -1; +} + +LogFileHandle::LogFileHandle() : m_fd{-1} {} + +LogFileHandle::~LogFileHandle() +{ + if (-1 != m_fd) + { + close(m_fd); + } +} +} // namespace firebolt::rialto::logging diff --git a/middleware/rialto-client/logging/source/LogFileHandle.h b/middleware/rialto-client/logging/source/LogFileHandle.h new file mode 100644 index 000000000..e71deac29 --- /dev/null +++ b/middleware/rialto-client/logging/source/LogFileHandle.h @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_LOGGING_LOG_FILE_HANDLE_H_ +#define FIREBOLT_RIALTO_LOGGING_LOG_FILE_HANDLE_H_ +#ifdef __cplusplus + +#include + +namespace firebolt::rialto::logging +{ +class LogFileHandle +{ +public: + static LogFileHandle &instance(); + void init(const std::string &path); + int fd() const; + bool isOpen() const; + +private: + LogFileHandle(); + ~LogFileHandle(); + +private: + int m_fd; +}; +} // namespace firebolt::rialto::logging + +#endif // defined(__cplusplus) +#endif // FIREBOLT_RIALTO_LOGGING_LOG_FILE_HANDLE_H_ diff --git a/middleware/rialto-client/logging/source/RialtoLogging.cpp b/middleware/rialto-client/logging/source/RialtoLogging.cpp new file mode 100644 index 000000000..099599a69 --- /dev/null +++ b/middleware/rialto-client/logging/source/RialtoLogging.cpp @@ -0,0 +1,413 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 Sky UK + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "EnvVariableParser.h" +#include "LogFileHandle.h" +#include "RialtoLogging.h" + +#ifdef USE_ETHANLOG + +#include + +#define SYSTEM_LOG_FATAL(filename, function, line, ...) ethanlog(ETHAN_LOG_FATAL, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_ERROR(filename, function, line, ...) ethanlog(ETHAN_LOG_ERROR, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_WARN(filename, function, line, ...) \ + ethanlog(ETHAN_LOG_WARNING, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_MIL(filename, function, line, ...) \ + ethanlog(ETHAN_LOG_MILESTONE, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_INFO(filename, function, line, ...) ethanlog(ETHAN_LOG_INFO, filename, function, line, __VA_ARGS__) +#define SYSTEM_LOG_DEBUG(filename, function, line, ...) ethanlog(ETHAN_LOG_DEBUG, filename, function, line, __VA_ARGS__) + +#else + +#include + +#define SYSTEM_LOG_FATAL(filename, function, line, ...) syslog(LOG_CRIT, __VA_ARGS__) +#define SYSTEM_LOG_ERROR(filename, function, line, ...) syslog(LOG_ERR, __VA_ARGS__) +#define SYSTEM_LOG_WARN(filename, function, line, ...) syslog(LOG_WARNING, __VA_ARGS__) +#define SYSTEM_LOG_MIL(filename, function, line, ...) syslog(LOG_NOTICE, __VA_ARGS__) +#define SYSTEM_LOG_INFO(filename, function, line, ...) syslog(LOG_INFO, __VA_ARGS__) +#define SYSTEM_LOG_DEBUG(filename, function, line, ...) syslog(LOG_DEBUG, __VA_ARGS__) + +#endif + +namespace +{ +/** + * Log levels for each component. By default will print all fatals, errors, warnings & milestones. + */ +std::atomic g_rialtoLogLevels[RIALTO_COMPONENT_LAST] = {}; + +/** + * Default Log levels defined by RIALTO_DEBUG environment variable + */ +const firebolt::rialto::logging::EnvVariableParser g_envVariableParser; + +/** + * Log handler for each component. By default will use journaldLogHandler. + */ +void fdLogHandler(int fd, RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, + const char *function, const char *message, size_t messageLen); +void journaldLogHandler(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, + const char *function, const char *message, size_t messageLen); + +firebolt::rialto::logging::LogHandler g_logHandler[RIALTO_COMPONENT_LAST] = {}; +bool g_ignoreLogLevels[RIALTO_COMPONENT_LAST] = {}; +std::mutex g_logHandlerMutex; + +std::string componentToString(RIALTO_COMPONENT component); +std::string levelToString(RIALTO_DEBUG_LEVEL level); + +std::string componentToString(RIALTO_COMPONENT component) +{ + switch (component) + { + case RIALTO_COMPONENT_DEFAULT: + return "DEF"; + break; + case RIALTO_COMPONENT_CLIENT: + return "CLI"; + break; + case RIALTO_COMPONENT_SERVER: + return "SRV"; + break; + case RIALTO_COMPONENT_IPC: + return "IPC"; + break; + case RIALTO_COMPONENT_SERVER_MANAGER: + return "SMG"; + break; + case RIALTO_COMPONENT_COMMON: + return "COM"; + break; + case RIALTO_COMPONENT_EXTERNAL: + return "EXT"; + break; + default: + return "UNK"; + break; + } +} + +std::string levelToString(RIALTO_DEBUG_LEVEL level) +{ + switch (level) + { + case RIALTO_DEBUG_LEVEL_FATAL: + return "FTL"; + break; + case RIALTO_DEBUG_LEVEL_ERROR: + return "ERR"; + break; + case RIALTO_DEBUG_LEVEL_WARNING: + return "WRN"; + break; + case RIALTO_DEBUG_LEVEL_MILESTONE: + return "MIL"; + break; + case RIALTO_DEBUG_LEVEL_INFO: + return "NFO"; + break; + case RIALTO_DEBUG_LEVEL_DEBUG: + return "DBG"; + break; + case RIALTO_DEBUG_LEVEL_EXTERNAL: + return "EXT"; + break; + default: + return ":"; + break; + } +} + +/** + * File descriptor logging function for the library. + */ +void fdLogHandler(int fd, RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, + const char *function, const char *message, size_t messageLen) +{ + timespec ts = {0, 0}; + clock_gettime(CLOCK_MONOTONIC, &ts); + struct iovec iov[6]; + char tbuf[32]; + + iov[0].iov_base = tbuf; + iov[0].iov_len = snprintf(tbuf, sizeof(tbuf), "%.010lu.%.06lu ", ts.tv_sec, ts.tv_nsec / 1000); + iov[0].iov_len = std::min(iov[0].iov_len, sizeof(tbuf)); + + char lbuf[8]; + iov[1].iov_base = reinterpret_cast(lbuf); + iov[1].iov_len = + std::min(static_cast(snprintf(lbuf, sizeof(lbuf), "%s: ", levelToString(level).c_str())), sizeof(lbuf)); + + char cbuf[8]; + iov[2].iov_base = reinterpret_cast(cbuf); + iov[2].iov_len = + std::min(static_cast(snprintf(cbuf, sizeof(cbuf), "%s: ", componentToString(component).c_str())), + sizeof(cbuf)); + + static thread_local pid_t threadId = 0; + if (threadId <= 0) + threadId = syscall(SYS_gettid); + char fbuf[180]; + iov[3].iov_base = reinterpret_cast(fbuf); + + if (RIALTO_DEBUG_LEVEL_EXTERNAL == level) + { + iov[3].iov_len = snprintf(fbuf, sizeof(fbuf), "< T:%d >", threadId); + } + else if (!file || !function || (line <= 0)) + { + iov[3].iov_len = snprintf(fbuf, sizeof(fbuf), "< T:%d M:? F:? L:? > ", threadId); + } + else + { + iov[3].iov_len = + snprintf(fbuf, sizeof(fbuf), "< T:%d M:%.*s F:%.*s L:%d > ", threadId, 64, file, 64, function, line); + } + iov[3].iov_len = std::min(iov[3].iov_len, sizeof(fbuf)); + iov[4].iov_base = const_cast(reinterpret_cast(message)); + iov[4].iov_len = messageLen; + iov[5].iov_base = const_cast(reinterpret_cast("\n")); + iov[5].iov_len = 1; + // TODO(RIALTO-38): consider using standard write(2) and handle EINTR properly. + std::ignore = writev(fd, iov, 6); +} +/** + * Journald logging function for the library. + */ +void journaldLogHandler(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, + const char *function, const char *message, size_t messageLen) +{ + static thread_local pid_t threadId = 0; + if (threadId <= 0) + threadId = syscall(SYS_gettid); + char fbuf[180]; + if (RIALTO_DEBUG_LEVEL_EXTERNAL == level) + { + snprintf(fbuf, sizeof(fbuf), "%s: %s: < T:%d >", levelToString(level).c_str(), + componentToString(component).c_str(), threadId); + } + else if (!file || !function || (line <= 0)) + { + snprintf(fbuf, sizeof(fbuf), "%s: %s: < T:%d M:? F:? L:? >", levelToString(level).c_str(), + componentToString(component).c_str(), threadId); + } + else + { + snprintf(fbuf, sizeof(fbuf), "%s: %s: < T:%d M:%.*s F:%.*s L:%d >", levelToString(level).c_str(), + componentToString(component).c_str(), threadId, 64, file, 64, function, line); + } + + switch (level) + { + case RIALTO_DEBUG_LEVEL_FATAL: + SYSTEM_LOG_FATAL(file, function, line, "%s %s", fbuf, message); + break; + case RIALTO_DEBUG_LEVEL_ERROR: + SYSTEM_LOG_ERROR(file, function, line, "%s %s", fbuf, message); + break; + case RIALTO_DEBUG_LEVEL_WARNING: + SYSTEM_LOG_WARN(file, function, line, "%s %s", fbuf, message); + break; + case RIALTO_DEBUG_LEVEL_MILESTONE: + SYSTEM_LOG_MIL(file, function, line, "%s %s", fbuf, message); + break; + case RIALTO_DEBUG_LEVEL_INFO: + SYSTEM_LOG_INFO(file, function, line, "%s %s", fbuf, message); + break; + case RIALTO_DEBUG_LEVEL_DEBUG: + SYSTEM_LOG_DEBUG(file, function, line, "%s %s", fbuf, message); + break; + case RIALTO_DEBUG_LEVEL_EXTERNAL: + SYSTEM_LOG_INFO(file, function, line, "%s %s", fbuf, message); + break; + default: + break; + } +} + +void rialtoLog(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, const char *func, int line, + const char *fmt, va_list ap, const char *append) +{ + /* Must be valid component */ + if (component >= RIALTO_COMPONENT_LAST) + return; + + /* If log levels have not been set, set to Default */ + if (!g_rialtoLogLevels[component]) + g_rialtoLogLevels[component] = g_envVariableParser.getLevel(component); + + if (!(level & g_rialtoLogLevels[component]) && !g_ignoreLogLevels[component]) + return; + char mbuf[512]; + int len; + len = vsnprintf(mbuf, sizeof(mbuf), fmt, ap); + if (len < 1) + return; + if (len > static_cast(sizeof(mbuf) - 1)) + len = sizeof(mbuf) - 1; + if (mbuf[len - 1] == '\n') + len--; + mbuf[len] = '\0'; + if (append && (len < static_cast(sizeof(mbuf) - 1))) + { + size_t extra = std::min(strlen(append), (sizeof(mbuf) - len - 1)); + memcpy(mbuf + len, append, extra); + len += static_cast(extra); + mbuf[len] = '\0'; + } + const char *kFname = nullptr; + if (file) + { + if ((kFname = strrchr(file, '/')) == nullptr) + kFname = file; + else + kFname++; + } + + const auto &kLogFileHandle = firebolt::rialto::logging::LogFileHandle::instance(); + /* If log handler had not been set, use default */ + firebolt::rialto::logging::LogHandler logHandler = g_logHandler[component]; // local copy for thread safety + if (logHandler) + { + logHandler(level, kFname, line, func, mbuf, len); + } + else if (g_envVariableParser.isFileLoggingEnabled() && kLogFileHandle.isOpen()) + { + fdLogHandler(kLogFileHandle.fd(), component, level, kFname, line, func, mbuf, len); + } + else if (g_envVariableParser.isConsoleLoggingEnabled()) + { + fdLogHandler(STDERR_FILENO, component, level, kFname, line, func, mbuf, len); + } + else + { + journaldLogHandler(component, level, kFname, line, func, mbuf, len); + } +} + +} // namespace + +void rialtoLogVPrintf(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, const char *func, + int line, const char *fmt, va_list ap) +{ + rialtoLog(component, level, file, func, line, fmt, ap, nullptr); +} + +void rialtoLogPrintf(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, const char *func, int line, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + rialtoLog(component, level, file, func, line, fmt, ap, nullptr); + va_end(ap); +} + +void rialtoLogSysPrintf(RIALTO_COMPONENT component, int err, RIALTO_DEBUG_LEVEL level, const char *file, + const char *func, int line, const char *fmt, ...) +{ + va_list ap; + const char *kErrmsg{nullptr}; + char appendbuf[96]; + const char *kAppend = nullptr; +#if defined(__linux__) + char errbuf[64]; + kErrmsg = strerror_r(err, errbuf, sizeof(errbuf)); +#elif defined(__APPLE__) + char errbuf[64]; + if (strerror_r(err, errbuf, sizeof(errbuf)) != 0) + kErrmsg = "Unknown error"; + else + kErrmsg = errbuf; +#endif + if (kErrmsg) + { + snprintf(appendbuf, sizeof(appendbuf), " (%d - %s)", err, kErrmsg); + appendbuf[sizeof(appendbuf) - 1] = '\0'; + kAppend = appendbuf; + } + va_start(ap, fmt); + rialtoLog(component, level, file, func, line, fmt, ap, kAppend); + va_end(ap); +} + +namespace firebolt::rialto::logging +{ +RialtoLoggingStatus setLogLevels(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL logLevels) +{ + RialtoLoggingStatus status = RIALTO_LOGGING_STATUS_ERROR; + if (component < RIALTO_COMPONENT_LAST && !g_ignoreLogLevels[component]) + { + g_rialtoLogLevels[component] = logLevels; + status = RIALTO_LOGGING_STATUS_OK; + } + + return status; +} + +RIALTO_DEBUG_LEVEL getLogLevels(RIALTO_COMPONENT component) +{ + if (component < RIALTO_COMPONENT_LAST) + { + if (g_ignoreLogLevels[component]) + return RIALTO_DEBUG_LEVEL_EXTERNAL; + + if (!g_rialtoLogLevels[component]) + g_rialtoLogLevels[component] = g_envVariableParser.getLevel(component); + return g_rialtoLogLevels[component]; + } + return RIALTO_DEBUG_LEVEL_DEFAULT; +} + +RialtoLoggingStatus setLogHandler(RIALTO_COMPONENT component, LogHandler handler, bool ignoreLogLevels) +{ + RialtoLoggingStatus status = RIALTO_LOGGING_STATUS_ERROR; + if (component < RIALTO_COMPONENT_LAST) + { + std::unique_lock lock{g_logHandlerMutex}; + + g_logHandler[component] = std::move(handler); + + // Ignoring log levels is only an option if we're registering + // a non-null log handler + g_ignoreLogLevels[component] = (g_logHandler[component]) ? ignoreLogLevels : false; + + status = RIALTO_LOGGING_STATUS_OK; + } + + return status; +} + +bool isConsoleLoggingEnabled() +{ + return g_envVariableParser.isConsoleLoggingEnabled(); +} + +} // namespace firebolt::rialto::logging diff --git a/middleware/rialto-client/media/CMakeLists.txt b/middleware/rialto-client/media/CMakeLists.txt new file mode 100644 index 000000000..31389dcea --- /dev/null +++ b/middleware/rialto-client/media/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +add_subdirectory(public) +add_subdirectory(common) +add_subdirectory(client) + +if( ENABLE_SERVER ) + add_subdirectory(server) +endif() diff --git a/middleware/rialto-client/media/client/CMakeLists.txt b/middleware/rialto-client/media/client/CMakeLists.txt new file mode 100644 index 000000000..cc906105c --- /dev/null +++ b/middleware/rialto-client/media/client/CMakeLists.txt @@ -0,0 +1,22 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +add_subdirectory(main) +add_subdirectory(ipc) +add_subdirectory(common) diff --git a/middleware/rialto-client/media/client/common/CMakeLists.txt b/middleware/rialto-client/media/client/common/CMakeLists.txt new file mode 100644 index 000000000..7664f6a17 --- /dev/null +++ b/middleware/rialto-client/media/client/common/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +add_library( + RialtoClientCommon + INTERFACE + ) + +target_include_directories( + RialtoClientCommon + + INTERFACE + include + ) diff --git a/middleware/rialto-client/media/client/common/include/RialtoClientLogging.h b/middleware/rialto-client/media/client/common/include/RialtoClientLogging.h new file mode 100644 index 000000000..0bdb87d57 --- /dev/null +++ b/middleware/rialto-client/media/client/common/include/RialtoClientLogging.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RIALTO_CLIENT_LOGGING_H_ +#define RIALTO_CLIENT_LOGGING_H_ + +#include "RialtoLogging.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RIALTO_CLIENT_LOG_FATAL(fmt, args...) RIALTO_LOG_FATAL(RIALTO_COMPONENT_CLIENT, fmt, ##args) +#define RIALTO_CLIENT_LOG_SYS_FATAL(err, fmt, args...) RIALTO_LOG_SYS_FATAL(RIALTO_COMPONENT_CLIENT, err, fmt, ##args) +#define RIALTO_CLIENT_LOG_ERROR(fmt, args...) RIALTO_LOG_ERROR(RIALTO_COMPONENT_CLIENT, fmt, ##args) +#define RIALTO_CLIENT_LOG_SYS_ERROR(err, fmt, args...) RIALTO_LOG_SYS_ERROR(RIALTO_COMPONENT_CLIENT, err, fmt, ##args) +#define RIALTO_CLIENT_LOG_WARN(fmt, args...) RIALTO_LOG_WARN(RIALTO_COMPONENT_CLIENT, fmt, ##args) +#define RIALTO_CLIENT_LOG_SYS_WARN(err, fmt, args...) RIALTO_LOG_SYS_WARN(RIALTO_COMPONENT_CLIENT, err, fmt, ##args) +#define RIALTO_CLIENT_LOG_MIL(fmt, args...) RIALTO_LOG_MIL(RIALTO_COMPONENT_CLIENT, fmt, ##args) +#define RIALTO_CLIENT_LOG_INFO(fmt, args...) RIALTO_LOG_INFO(RIALTO_COMPONENT_CLIENT, fmt, ##args) +#define RIALTO_CLIENT_LOG_DEBUG(fmt, args...) RIALTO_LOG_DEBUG(RIALTO_COMPONENT_CLIENT, fmt, ##args) + +#ifdef __cplusplus +} +#endif + +#endif // RIALTO_CLIENT_LOGGING_H_ diff --git a/middleware/rialto-client/media/client/ipc/CMakeLists.txt b/middleware/rialto-client/media/client/ipc/CMakeLists.txt new file mode 100644 index 000000000..8df436d3a --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/CMakeLists.txt @@ -0,0 +1,70 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Find includes in corresponding build directories +set( CMAKE_INCLUDE_CURRENT_DIR ON ) + +add_library ( + RialtoClientIpcImpl + STATIC + + source/IpcClient.cpp + source/IpcModule.cpp + source/MediaPipelineIpc.cpp + source/MediaPipelineCapabilitiesIpc.cpp + source/ControlIpc.cpp + source/MediaKeysIpc.cpp + source/MediaKeysCapabilitiesIpc.cpp + source/RialtoCommonIpc.cpp + source/WebAudioPlayerIpc.cpp +) + +set_property ( + TARGET + RialtoClientIpcImpl + PROPERTY POSITION_INDEPENDENT_CODE ON +) + +target_include_directories ( + RialtoClientIpcImpl + + PUBLIC + interface + + PRIVATE + include + $ + $ + $ + $ + $ + $ +) + +target_link_libraries ( + RialtoClientIpcImpl + + PRIVATE + RialtoIpcClient + RialtoIpcCommon + RialtoCommon + RialtoPlayerCommon + RialtoEthanLog + RialtoProtobuf +) diff --git a/middleware/rialto-client/media/client/ipc/include/ControlIpc.h b/middleware/rialto-client/media/client/ipc/include/ControlIpc.h new file mode 100644 index 000000000..01093dd9b --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/ControlIpc.h @@ -0,0 +1,118 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_CONTROL_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_CONTROL_IPC_H_ + +#include "IConnectionObserver.h" +#include "IControlClient.h" +#include "IControlIpc.h" +#include "IEventThread.h" +#include "IpcModule.h" +#include + +#include "controlmodule.pb.h" + +namespace firebolt::rialto::client +{ +class ControlIpc; + +/** + * @brief IControlIpc factory class definition. + */ +class ControlIpcFactory : public IControlIpcFactory +{ +public: + ControlIpcFactory() = default; + ~ControlIpcFactory() override = default; + + std::shared_ptr createControlIpc(IControlClient *controlClient) override; + + /** + * @brief Create the generic control factory object. + * + * @retval the generic control factory instance or null on error. + */ + static std::shared_ptr createFactory(); +}; + +/** + * @brief The definition of the ControlIpc. + */ +class ControlIpc : public IControlIpc, public IpcModule, public IConnectionObserver +{ +public: + /** + * @brief The constructor. + */ + ControlIpc(IControlClient *controlClient, IIpcClient &ipcClient, + const std::shared_ptr &eventThreadFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~ControlIpc(); + + bool getSharedMemory(int32_t &fd, uint32_t &size) override; + bool registerClient() override; + +private: + bool createRpcStubs(const std::shared_ptr &ipcChannel) override; + bool subscribeToEvents(const std::shared_ptr &ipcChannel) override; + void onConnectionBroken() override; + + /** + * @brief Handler for a application state update from the server. + * + * @param[in] event : The app state changed event structure. + */ + void onApplicationStateUpdated(const std::shared_ptr &event); + + /** + * @brief Handler for a ping from the server. + * + * @param[in] event : The ping event structure. + */ + void onPing(const std::shared_ptr &event); + +private: + /** + * @brief Control client for handling messages from server + */ + IControlClient *m_controlClient; + + /** + * @brief The control handle for the current instance. + */ + std::atomic m_controlHandle; + + /** + * @brief Thread for handling media player events from the server. + */ + std::unique_ptr m_eventThread; + + /** + * @brief RPC stubs for the Control APIs. + */ + std::shared_ptr<::firebolt::rialto::ControlModule_Stub> m_controlStub; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_CONTROL_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/IConnectionObserver.h b/middleware/rialto-client/media/client/ipc/include/IConnectionObserver.h new file mode 100644 index 000000000..2857707fb --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/IConnectionObserver.h @@ -0,0 +1,35 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_CONNECTION_OBSERVER_H_ +#define FIREBOLT_RIALTO_CLIENT_I_CONNECTION_OBSERVER_H_ + +#include "ControlCommon.h" + +namespace firebolt::rialto::client +{ +class IConnectionObserver +{ +public: + virtual ~IConnectionObserver() = default; + virtual void onConnectionBroken() = 0; +}; +} // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_CONNECTION_OBSERVER_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/IIpcClient.h b/middleware/rialto-client/media/client/ipc/include/IIpcClient.h new file mode 100644 index 000000000..8455d4a6d --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/IIpcClient.h @@ -0,0 +1,120 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_IPC_CLIENT_H_ +#define FIREBOLT_RIALTO_CLIENT_I_IPC_CLIENT_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include "IConnectionObserver.h" + +namespace firebolt::rialto::client +{ +class IIpcClient; + +/** + * @brief IIpcClient accessor class definition. + */ +class IIpcClientAccessor +{ +public: + virtual ~IIpcClientAccessor() = default; + IIpcClientAccessor(const IIpcClientAccessor &) = delete; + IIpcClientAccessor &operator=(const IIpcClientAccessor &) = delete; + IIpcClientAccessor(IIpcClientAccessor &&) = delete; + IIpcClientAccessor &operator=(IIpcClientAccessor &&) = delete; + + /** + * @brief Get a IControlIpcAccessor instance. + * + * @retval the accessor instance + */ + static IIpcClientAccessor &instance(); + + /** + * @brief Get IpcClient object. + * + * @retval the reference to IpcClient singleton object + */ + virtual IIpcClient &getIpcClient() const = 0; + +protected: + IIpcClientAccessor() = default; +}; + +/** + * @brief The definition of the IIpcClient interface. + * + * This interface defines the control ipc APIs that are used to communicate with the Rialto server. + */ +class IIpcClient +{ +public: + IIpcClient() = default; + virtual ~IIpcClient() = default; + + IIpcClient(const IIpcClient &) = delete; + IIpcClient &operator=(const IIpcClient &) = delete; + IIpcClient(IIpcClient &&) = delete; + IIpcClient &operator=(IIpcClient &&) = delete; + + /** + * @brief Gets a weak ptr to the Ipc channel created by the IpcClient. + * + * @retval the ipc channel weak ptr. + */ + virtual std::weak_ptr getChannel() const = 0; + + /** + * @brief Create the blocking closure to be passed to the RPC stubs. + * + * @retval the blocking closure or null on error. + */ + virtual std::shared_ptr createBlockingClosure() = 0; + + /** + * @brief Create the rpc controller to be passed to the RPC stubs. + * + * @retval the rpc controller or null on error. + */ + virtual std::shared_ptr createRpcController() = 0; + + /** + * @brief Reconnect channel. + * + * @retval true on success. + */ + virtual bool reconnect() = 0; + + /** + * @brief Registers new connection observer. + */ + virtual void registerConnectionObserver(const std::weak_ptr &observer) = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_IPC_CLIENT_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/IpcClient.h b/middleware/rialto-client/media/client/ipc/include/IpcClient.h new file mode 100644 index 000000000..d6a8da658 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/IpcClient.h @@ -0,0 +1,117 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_IPC_CLIENT_H_ +#define FIREBOLT_RIALTO_CLIENT_IPC_CLIENT_H_ + +#include "IIpcClient.h" +#include +#include + +namespace firebolt::rialto::client +{ +class IpcClientAccessor : public IIpcClientAccessor +{ +public: + ~IpcClientAccessor() override = default; + IIpcClient &getIpcClient() const override; +}; + +/** + * @brief The definition of the IpcClient. + */ +class IpcClient : public IIpcClient +{ +public: + /** + * @brief The constructor. + */ + IpcClient(const std::shared_ptr &ipcChannelFactory, + const std::shared_ptr &ipcControllerFactory, + const std::shared_ptr &blockingClosureFactory); + + /** + * @brief Virtual destructor. + */ + ~IpcClient() override; + + std::weak_ptr getChannel() const override; + + std::shared_ptr createBlockingClosure() override; + + std::shared_ptr createRpcController() override; + + bool reconnect() override; + + void registerConnectionObserver(const std::weak_ptr &observer) override; + +protected: + /** + * @brief The ipc thread. + */ + std::thread m_ipcThread; + + /** + * @brief The connected ipc communication channel. + */ + std::shared_ptr m_ipcChannel; + + /** + * @brief Factory for creating the ipc controllers. + */ + std::shared_ptr m_ipcControllerFactory; + + /** + * @brief Factory for creating a connected ipc channel. + */ + std::shared_ptr m_ipcChannelFactory; + + /** + * @brief Factory for creating a blocking closure. + */ + std::shared_ptr m_blockingClosureFactory; + + /** + * @brief Whether disconnection of ipc has been requested by the client and is ongoing. + */ + std::atomic m_disconnecting; + + /** + * @brief Current connection status observer + */ + std::weak_ptr m_connectionObserver; + + /** + * @brief The processing loop for the ipc thread. + */ + void processIpcThread(); + + /** + * @brief Establish connection between Rialto Server and Rialto Client + */ + bool connect(); + + /** + * @brief Close connection between Rialto Server and Rialto Client + */ + bool disconnect(); +}; +} // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_IPC_CLIENT_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/IpcModule.h b/middleware/rialto-client/media/client/ipc/include/IpcModule.h new file mode 100644 index 000000000..5af617089 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/IpcModule.h @@ -0,0 +1,125 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_IPC_MODULE_H_ +#define FIREBOLT_RIALTO_CLIENT_IPC_MODULE_H_ + +#include "IIpcClient.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::client +{ +/** + * @brief The implementation of a IpcModule. + * + * This class defines common Ipc APIs for Ipc modules. + */ +class IpcModule +{ +public: + /** + * @brief The constructor. + * + * @param[in] ipcClient : The ipc client + */ + explicit IpcModule(IIpcClient &ipcClient); + + /** + * @brief Virtual destructor. + */ + virtual ~IpcModule(); + +protected: + /** + * @brief The ipc client singleton object. + */ + IIpcClient &m_ipc; + + /** + * @brief The ipc communication channel. + */ + std::weak_ptr m_ipcChannel; + + /** + * @brief Subscribed event tags. + */ + std::vector m_eventTags; + + /** + * @brief Create the Rpc stubs for the derived object. + * + * @param[in] ipcChannel : The ipc channel + * + * @retval true if the rpc stubs are created successfully, false otherwise. + */ + virtual bool createRpcStubs(const std::shared_ptr &ipcChannel) = 0; + + /** + * @brief Subscribes to the Ipc events for the derived object. + * + * @param[in] ipcChannel : The ipc channel + * + * @retval true if the events are subscribed successfully, false otherwise. + */ + virtual bool subscribeToEvents(const std::shared_ptr &ipcChannel) = 0; + + /** + * @brief Unsubscribes to all Ipc events. + * + * @param[in] ipcChannel : The ipc channel + * + * @retval true if the events are unsubscribed successfully, false otherwise. + */ + bool unsubscribeFromAllEvents(const std::shared_ptr &ipcChannel); + + /** + * @brief Attach the connected ipc client channel to the MediaKeysIpc object. + * + * @retval true if the channel attached successfully, false otherwise. + */ + bool attachChannel(); + + /** + * @brief Detach the ipc client channel from the MediaKeysIpc object. + */ + void detachChannel(); + + /** + * @brief If the channel is disconnected, this method will reattach the channel. + * + * @retval true if channel now connected, false otherwise. + */ + bool reattachChannelIfRequired(); + +private: + /** + * @brief Get connected IPC Channel + * + * @retval Ipc Channel if connected, nullptr otherwise + */ + std::shared_ptr getConnectedChannel(); +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_IPC_MODULE_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/MediaKeysCapabilitiesIpc.h b/middleware/rialto-client/media/client/ipc/include/MediaKeysCapabilitiesIpc.h new file mode 100644 index 000000000..93ef65e44 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/MediaKeysCapabilitiesIpc.h @@ -0,0 +1,96 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_IPC_H_ + +#include "IEventThread.h" +#include "IMediaKeysCapabilitiesIpcFactory.h" +#include "IpcModule.h" +#include +#include +#include +#include + +#include "mediakeyscapabilitiesmodule.pb.h" + +namespace firebolt::rialto::client +{ +/** + * @brief IMediaKeysCapabilitiesIpc factory class definition. + */ +class MediaKeysCapabilitiesIpcFactory : public IMediaKeysCapabilitiesIpcFactory +{ +public: + MediaKeysCapabilitiesIpcFactory() = default; + ~MediaKeysCapabilitiesIpcFactory() override = default; + + /** + * @brief Weak pointer to the singleton object. + */ + static std::weak_ptr m_mediaKeysCapabilitiesIpc; + + /** + * @brief Mutex protection for creation of the MediaKeysCapabilitiesIpc object. + */ + static std::mutex m_creationMutex; + + std::shared_ptr getMediaKeysCapabilitiesIpc() const override; +}; + +/** + * @brief The definition of the MediaKeysCapabilitiesIpc. + */ +class MediaKeysCapabilitiesIpc : public IMediaKeysCapabilities, public IpcModule +{ +public: + /** + * @brief The constructor. + * + * @param[in] ipcClient : The ipc client + */ + explicit MediaKeysCapabilitiesIpc(IIpcClient &ipcClientFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaKeysCapabilitiesIpc(); + + std::vector getSupportedKeySystems() override; + + bool supportsKeySystem(const std::string &keySystem) override; + + bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) override; + + bool isServerCertificateSupported(const std::string &keySystem) override; + +private: + /** + * @brief The ipc protobuf media keys capabilities stub. + */ + std::unique_ptr<::firebolt::rialto::MediaKeysCapabilitiesModule_Stub> m_mediaKeysCapabilitiesStub; + + bool createRpcStubs(const std::shared_ptr &ipcChannel) override; + + bool subscribeToEvents(const std::shared_ptr &ipcChannel) override { return true; } +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/MediaKeysIpc.h b/middleware/rialto-client/media/client/ipc/include/MediaKeysIpc.h new file mode 100644 index 000000000..0ecf5c744 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/MediaKeysIpc.h @@ -0,0 +1,183 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_IPC_H_ + +#include "IEventThread.h" +#include "IMediaKeysClient.h" +#include "IMediaKeysIpcFactory.h" +#include "IpcModule.h" +#include +#include +#include + +#include "mediakeysmodule.pb.h" + +namespace firebolt::rialto::client +{ +/** + * @brief IMediaKeysIpc factory class definition. + */ +class MediaKeysIpcFactory : public IMediaKeysIpcFactory +{ +public: + MediaKeysIpcFactory() = default; + ~MediaKeysIpcFactory() override = default; + + std::unique_ptr createMediaKeysIpc(const std::string &keySystem) const override; +}; + +/** + * @brief The definition of the MediaKeysIpc. + */ +class MediaKeysIpc : public IMediaKeys, public IpcModule +{ +public: + /** + * @brief The constructor. + * + * @param[in] keySystem : The key system for which to create a Media Keys Ipc instance + * @param[in] ipcClient : The ipc client + * @param[in] eventThreadFactory : The event thread factory + */ + MediaKeysIpc(const std::string &keySystem, IIpcClient &ipcClient, + const std::shared_ptr &eventThreadFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaKeysIpc(); + + MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) override; + + bool containsKey(int32_t keySessionId, const std::vector &keyId) override; + + MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, bool isLDL, + int32_t &keySessionId) override; + + MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) override; + + MediaKeyErrorStatus loadSession(int32_t keySessionId) override; + + MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) override; + + MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) override; + + MediaKeyErrorStatus closeKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus removeKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus deleteDrmStore() override; + + MediaKeyErrorStatus deleteKeyStore() override; + + MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) override; + + MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) override; + + MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) override; + + MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) override; + + MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) override; + + MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) override; + + MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) override; + +private: + /** + * @brief The ipc protobuf media keys stub. + */ + std::unique_ptr<::firebolt::rialto::MediaKeysModule_Stub> m_mediaKeysStub; + + /** + * @brief The media key handle for the current session. + */ + std::atomic m_mediaKeysHandle; + + /** + * @brief Thread for handling media player events from the server. + */ + std::unique_ptr m_eventThread; + + /** + * @brief The media keys client ipc. + */ + std::weak_ptr m_mediaKeysIpcClient; + + bool createRpcStubs(const std::shared_ptr &ipcChannel) override; + + bool subscribeToEvents(const std::shared_ptr &ipcChannel) override; + + /** + * @brief Handler for a license request from the server. + * + * @param[in] event : The license request event structure. + */ + void onLicenseRequest(const std::shared_ptr &event); + + /** + * @brief Handler for a license renewal from the server. + * + * @param[in] event : The license renewal event structure. + */ + void onLicenseRenewal(const std::shared_ptr &event); + + /** + * @brief Handler for a key statues change from the server. + * + * @param[in] event : The key statues change event structure. + */ + void onKeyStatusesChanged(const std::shared_ptr &event); + + /** + * @brief Create a new media keys instance. + * + * @retval true on success, false otherwise. + */ + bool createMediaKeys(const std::string &keySystem); + + /** + * @brief Destroy the current media keys instance. + */ + void destroyMediaKeys(); + + /** + * @brief Checks the Ipc controller and ProtoMediaKeyErrorStatus for failures and return the MediaKeyErrorStatus. + * + * @param[in] methodName : The name of the ipc method. + * @param[in] controller : The rpc controller object. + * @param[in] status : The protobuf response status. + * + * @retval The MediaKeyErrorStatus to return. + */ + MediaKeyErrorStatus + getMediaKeyErrorStatusFromResponse(const std::string methodName, + const std::shared_ptr &controller, + ProtoMediaKeyErrorStatus status); +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h b/middleware/rialto-client/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h new file mode 100644 index 000000000..0078aa340 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h @@ -0,0 +1,117 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_IPC_H_ + +#include "IMediaPipelineCapabilitiesIpcFactory.h" +#include "IpcModule.h" +#include +#include +#include + +#include "mediapipelinecapabilitiesmodule.pb.h" + +namespace firebolt::rialto::client +{ +/** + * @brief IMediaPipelineCapabilitiesIpc factory class definition. + */ +class MediaPipelineCapabilitiesIpcFactory : public IMediaPipelineCapabilitiesIpcFactory +{ +public: + MediaPipelineCapabilitiesIpcFactory() = default; + ~MediaPipelineCapabilitiesIpcFactory() override = default; + + std::unique_ptr createMediaPipelineCapabilitiesIpc() const override; +}; + +/** + * @brief The definition of the MediaPipelineCapabilitiesIpc. + */ +class MediaPipelineCapabilitiesIpc : public IMediaPipelineCapabilities, public IpcModule +{ +public: + /** + * @brief The constructor. + * + * @param[in] ipcClient : The ipc client + */ + explicit MediaPipelineCapabilitiesIpc(IIpcClient &ipcClient); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaPipelineCapabilitiesIpc(); + + /** + * @brief Returns the MSE mime types supported by Rialto for \a sourceType + * + * @param[in] sourceType : source type + * + * @retval The supported mime types. + */ + std::vector getSupportedMimeTypes(MediaSourceType sourceType) override; + + /** + * @brief Indicates if the specified mime type is supported. + * + * This method should be called to ensure that the specified mime + * type is supported by Rialto. + * + * @param[in] mimeType : The mime type to check. + * + * @retval true if supported. + */ + bool isMimeTypeSupported(const std::string &mimeType) override; + + /** + * @brief Check sinks and decoders for supported properties + * + * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched + * @param[in] propertyNames : A vector of property names to look for + * + * @retval Returns the subset of propertyNames that are supported by the mediaType + */ + std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) override; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + bool isVideoMaster(bool &isVideoMaster) override; + +private: + /** + * @brief The ipc protobuf media Pipeline capabilities stub. + */ + std::unique_ptr<::firebolt::rialto::MediaPipelineCapabilitiesModule_Stub> m_mediaPipelineCapabilitiesStub; + + bool createRpcStubs(const std::shared_ptr &ipcChannel) override; + + bool subscribeToEvents(const std::shared_ptr &ipcChannel) override { return true; } +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/MediaPipelineIpc.h b/middleware/rialto-client/media/client/ipc/include/MediaPipelineIpc.h new file mode 100644 index 000000000..a398159d7 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/MediaPipelineIpc.h @@ -0,0 +1,300 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_IPC_H_ + +#include "IEventThread.h" +#include "IMediaPipelineIpc.h" +#include "IpcModule.h" +#include +#include +#include + +#include "mediapipelinemodule.pb.h" + +namespace firebolt::rialto::client +{ +/** + * @brief IMediaPipelineIpc factory class definition. + */ +class MediaPipelineIpcFactory : public IMediaPipelineIpcFactory +{ +public: + /** + * @brief Weak pointer to the singleton factory object. + */ + static std::weak_ptr m_factory; + + std::unique_ptr createMediaPipelineIpc(IMediaPipelineIpcClient *client, + const VideoRequirements &videoRequirements, + std::weak_ptr ipcClient) override; +}; + +/** + * @brief The definition of the MediaPipelineIpc. + */ +class MediaPipelineIpc : public IMediaPipelineIpc, public IpcModule +{ +public: + /** + * @brief The constructor. + * + * @param[in] client : The Rialto ipc media player client. + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. + * @param[in] ipcClient : The ipc client + * @param[in] eventThreadFactory : The event thread factory + */ + MediaPipelineIpc(IMediaPipelineIpcClient *client, const VideoRequirements &videoRequirements, IIpcClient &ipcClient, + const std::shared_ptr &eventThreadFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaPipelineIpc(); + + bool attachSource(const std::unique_ptr &source, int32_t &sourceId) override; + + bool removeSource(int32_t sourceId) override; + + bool allSourcesAttached() override; + + bool load(MediaType type, const std::string &mimeType, const std::string &url) override; + + bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + + bool play() override; + + bool pause() override; + + bool stop() override; + + bool haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t requestId) override; + + bool setPosition(int64_t position) override; + + bool getPosition(int64_t &position) override; + + bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override; + + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override; + + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; + + bool setPlaybackRate(double rate) override; + + bool renderFrame() override; + + bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override; + + bool getVolume(double &volume) override; + + bool setMute(int32_t sourceId, bool mute) override; + + bool getMute(int32_t sourceId, bool &mute) override; + + bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; + + bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; + + bool setLowLatency(bool lowLatency) override; + + bool setSync(bool sync) override; + + bool getSync(bool &sync) override; + + bool setSyncOff(bool syncOff) override; + + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; + + bool getStreamSyncMode(int32_t &streamSyncMode) override; + + bool flush(int32_t sourceId, bool resetTime, bool &async) override; + + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) override; + + bool setSubtitleOffset(int32_t sourceId, int64_t position) override; + + bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; + + bool setBufferingLimit(uint32_t limitBufferingMs) override; + + bool getBufferingLimit(uint32_t &limitBufferingMs) override; + + bool setUseBuffering(bool useBuffering) override; + + bool getUseBuffering(bool &useBuffering) override; + + bool switchSource(const std::unique_ptr &source) override; + +private: + /** + * @brief The media player client ipc. + */ + IMediaPipelineIpcClient *m_mediaPipelineIpcClient; + + /** + * @brief The ipc protobuf media player stub. + */ + std::unique_ptr<::firebolt::rialto::MediaPipelineModule_Stub> m_mediaPipelineStub; + + /** + * @brief The session id of the current session. + */ + // onPlaybackStateUpdated() can be called before createSession() therefore + // initialise m_sessionId to -1 which is an invalid session_id + std::atomic m_sessionId{-1}; + + /** + * @brief Thread for handling media player events from the server. + */ + std::unique_ptr m_eventThread; + + bool createRpcStubs(const std::shared_ptr &ipcChannel) override; + + bool subscribeToEvents(const std::shared_ptr &ipcChannel) override; + + /** + * @brief Handler for a playback state update from the server. + * + * @param[in] event : The player state changed event structure. + */ + void onPlaybackStateUpdated(const std::shared_ptr &event); + + /** + * @brief Handler for a playback position update from the server. + * + * @param[in] event : The playback position changed event structure. + */ + void onPositionUpdated(const std::shared_ptr &event); + + /** + * @brief Handler for a network state update from the server. + * + * @param[in] event : The player state changed event structure. + */ + void onNetworkStateUpdated(const std::shared_ptr &event); + + /** + * @brief Handler for a need data request from the server. + * + * @param[in] event : The need data event structure. + */ + void onNeedMediaData(const std::shared_ptr &event); + + /** + * @brief Handler for a QOS update from the server. + * + * @param[in] event : The qos event structure. + */ + void onQos(const std::shared_ptr &event); + + /** + * @brief Handler for a buffer underflow notification from the server. + * + * @param[in] event : The buffer underflow event structure. + */ + void onBufferUnderflow(const std::shared_ptr &event); + + /** + * @brief Handler for a playback error notification from the server. + * + * @param[in] event : The playback error event structure. + */ + void onPlaybackError(const std::shared_ptr &event); + + /** + * @brief Handler for a source flushed notification from the server. + * + * @param[in] event : The source flushed event structure. + */ + void onSourceFlushed(const std::shared_ptr &event); + + /** + * @brief Create a new player session. + * + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. + * + * @retval true on success, false otherwise. + */ + bool createSession(const VideoRequirements &videoRequirements); + + /** + * @brief Destroy the current player session. + */ + void destroySession(); + + /** + * @brief Converts the MediaType enum to protobuf LoadRequest MediaType. + */ + firebolt::rialto::LoadRequest_MediaType convertLoadRequestMediaType(MediaType mediaType) const; + + /** + * @brief Converts the MediaSourceStatus enum to protobuf HaveDataRequest MediaSourceStatus. + */ + firebolt::rialto::HaveDataRequest_MediaSourceStatus + convertHaveDataRequestMediaSourceStatus(MediaSourceStatus status) const; + + /** + * @brief Converts the SegmentAlignment enum to protobuf AttachSourceRequest SegmentAlignment. + */ + firebolt::rialto::AttachSourceRequest_SegmentAlignment + convertSegmentAlignment(const firebolt::rialto::SegmentAlignment &alignment) const; + + /** + * @brief Converts the StreamFormat enum to protobuf AttachSourceRequest StreamFormat. + */ + firebolt::rialto::AttachSourceRequest_StreamFormat + convertStreamFormat(const firebolt::rialto::StreamFormat &streamFormat) const; + + firebolt::rialto::AttachSourceRequest_ConfigType + convertConfigType(const firebolt::rialto::SourceConfigType &configType) const; + + /** + * @brief Converts the CodecDataType enum to protobuf AttachSourceRequest CodecDataType. + */ + firebolt::rialto::AttachSourceRequest_CodecData_Type + convertCodecDataType(const firebolt::rialto::CodecDataType &codecDataType) const; + + /** + * @brief Converts the Format enum to protobuf AttachSourceRequest Format. + */ + firebolt::rialto::AttachSourceRequest_AudioConfig_Format convertFormat(const firebolt::rialto::Format &format) const; + + /** + * @brief Converts the Layout enum to protobuf AttachSourceRequest Layout. + */ + firebolt::rialto::AttachSourceRequest_AudioConfig_Layout convertLayout(const firebolt::rialto::Layout &layout) const; + + /** + * @brief Converts the EaseType enum to protobuf SetVolumeRequest EaseType. + */ + firebolt::rialto::SetVolumeRequest_EaseType convertEaseType(const firebolt::rialto::EaseType &easeType) const; + + /** + * @brief Sets AttachSourceRequest parameters based on given MediaSource + */ + bool buildAttachSourceRequest(firebolt::rialto::AttachSourceRequest &request, + const std::unique_ptr &source) const; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/RialtoCommonIpc.h b/middleware/rialto-client/media/client/ipc/include/RialtoCommonIpc.h new file mode 100644 index 000000000..44044d38d --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/RialtoCommonIpc.h @@ -0,0 +1,31 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_RIALTO_COMMON_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_RIALTO_COMMON_IPC_H_ + +#include "MediaCommon.h" +#include "rialtocommon.pb.h" + +namespace firebolt::rialto::client +{ +firebolt::rialto::ProtoMediaSourceType convertProtoMediaSourceType(MediaSourceType mediaSourceType); +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_RIALTO_COMMON_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/WebAudioPlayerIpc.h b/middleware/rialto-client/media/client/ipc/include/WebAudioPlayerIpc.h new file mode 100644 index 000000000..beb364777 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/include/WebAudioPlayerIpc.h @@ -0,0 +1,119 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_IPC_H_ + +#include "IEventThread.h" +#include "IWebAudioPlayerIpc.h" +#include "IpcModule.h" +#include +#include +#include + +#include "webaudioplayermodule.pb.h" + +namespace firebolt::rialto::client +{ +/** + * @brief IWebAudioPlayerIpc factory class definition. + */ +class WebAudioPlayerIpcFactory : public IWebAudioPlayerIpcFactory +{ +public: + std::unique_ptr + createWebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config, std::weak_ptr ipcClient) override; +}; + +/** + * @brief The definition of the WebAudioPlayerIpc. + */ +class WebAudioPlayerIpc : public IWebAudioPlayerIpc, public IpcModule +{ +public: + /** + * @brief The constructor. + * + * @param[in] client : The Rialto ipc web audio player client. + * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM) + * @param[in] priority : Priority value for this pipeline. + * @param[in] config : Additional type dependent configuration data or nullptr + * @param[in] ipcClient : The ipc client + * @param[in] eventThreadFactory : The event thread factory + */ + WebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config, IIpcClient &ipcClient, + const std::shared_ptr &eventThreadFactory); + + virtual ~WebAudioPlayerIpc(); + + bool play() override; + + bool pause() override; + + bool setEos() override; + + bool getBufferAvailable(uint32_t &availableFrames, const std::shared_ptr &webAudioShmInfo) override; + + bool getBufferDelay(uint32_t &delayFrames) override; + + bool writeBuffer(const uint32_t numberOfFrames) override; + + bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override; + + bool setVolume(double volume) override; + + bool getVolume(double &volume) override; + +private: + bool createWebAudioPlayer(const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config); + + void destroyWebAudioPlayer(); + + bool createRpcStubs(const std::shared_ptr &ipcChannel) override; + + bool subscribeToEvents(const std::shared_ptr &ipcChannel) override; + + void onPlaybackStateUpdated(const std::shared_ptr &event); + /** + * @brief The web audio player client ipc. + */ + IWebAudioPlayerIpcClient *m_webAudioPlayerIpcClient; + + /** + * @brief The ipc protobuf web audio player stub. + */ + std::unique_ptr<::firebolt::rialto::WebAudioPlayerModule_Stub> m_webAudioPlayerStub; + + /** + * @brief Thread for handling web audio player events from the server. + */ + std::unique_ptr m_eventThread; + + /** + * @brief Handle to an IPC connection to the server. + */ + int32_t m_webAudioPlayerHandle; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IControlIpc.h b/middleware/rialto-client/media/client/ipc/interface/IControlIpc.h new file mode 100644 index 000000000..a68a285a9 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/interface/IControlIpc.h @@ -0,0 +1,93 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_CONTROL_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_I_CONTROL_IPC_H_ + +#include "IControlClient.h" +#include + +#include +#include + +namespace firebolt::rialto::client +{ +class IControlIpc; + +/** + * @brief IControlIpc factory class, returns a singlton of IControlIpc + */ +class IControlIpcFactory +{ +public: + IControlIpcFactory() = default; + virtual ~IControlIpcFactory() = default; + + /** + * @brief Create a IControlIpcFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Gets the IControlIpc singleton object. + * + * @retval the rialto controller ipc instance or null on error. + */ + virtual std::shared_ptr createControlIpc(IControlClient *controlClient) = 0; +}; + +/** + * @brief The definition of the IControlIpc interface. + * + * This interface defines the rialto control ipc APIs that are used to communicate with the Rialto server. + */ +class IControlIpc +{ +public: + IControlIpc() = default; + virtual ~IControlIpc() = default; + + IControlIpc(const IControlIpc &) = delete; + IControlIpc &operator=(const IControlIpc &) = delete; + IControlIpc(IControlIpc &&) = delete; + IControlIpc &operator=(IControlIpc &&) = delete; + + /** + * @brief Gets shared memory information to map. + * + * @param[in] fd : The file descriptor of the shared memory region. + * @param[in] size : The size of the shared memory region. + * + * @retval true success, false otherwise. + */ + virtual bool getSharedMemory(int32_t &fd, uint32_t &size) = 0; + + /** + * @brief Register new client + * + * @retval true success, false otherwise. + */ + virtual bool registerClient() = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_CONTROL_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaKeysCapabilitiesIpcFactory.h b/middleware/rialto-client/media/client/ipc/interface/IMediaKeysCapabilitiesIpcFactory.h new file mode 100644 index 000000000..bff31562e --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/interface/IMediaKeysCapabilitiesIpcFactory.h @@ -0,0 +1,62 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_CAPABILITIES_IPC_FACTORY_H_ +#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_CAPABILITIES_IPC_FACTORY_H_ + +/** + * @file IMediaKeysCapabilities.h + * + * The definition of the IMediaKeysCapabilities interface. + */ + +#include "IMediaKeysCapabilities.h" +#include +#include +#include + +namespace firebolt::rialto::client +{ +/** + * @brief IMediaKeysCapabilities factory class, for getting the IMediaKeysCapabilities singleton object for ipc. + */ +class IMediaKeysCapabilitiesIpcFactory +{ +public: + IMediaKeysCapabilitiesIpcFactory() = default; + virtual ~IMediaKeysCapabilitiesIpcFactory() = default; + + /** + * @brief Gets the IMediaKeysCapabilitiesIpcFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Gets the IMediaKeysCapabilities singleton object for ipc. + * + * @retval the MediaKeysCapabilities for ipc instance or null on error. + */ + virtual std::shared_ptr getMediaKeysCapabilitiesIpc() const = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_CAPABILITIES_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaKeysIpcFactory.h b/middleware/rialto-client/media/client/ipc/interface/IMediaKeysIpcFactory.h new file mode 100644 index 000000000..7b8a3ee33 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/interface/IMediaKeysIpcFactory.h @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_IPC_FACTORY_H_ +#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_IPC_FACTORY_H_ + +/** + * @file IMediaKeys.h + * + * The definition of the IMediaKeys interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content. + */ + +#include +#include +#include + +#include "IMediaKeys.h" +#include "MediaCommon.h" + +namespace firebolt::rialto::client +{ +/** + * @brief IMediaKeys factory class, returns a concrete implementation of IMediaKeys for Ipc + */ +class IMediaKeysIpcFactory +{ +public: + IMediaKeysIpcFactory() = default; + virtual ~IMediaKeysIpcFactory() = default; + + /** + * @brief Create a IMediaKeysIpcFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMediaKeys factory method, returns a concrete implementation of IMediaKeys for Ipc + * + * @param[in] keySystem : The key system for which to create a Media Keys instance + * + * @retval the new media keys for ipc instance or null on error. + */ + virtual std::unique_ptr createMediaKeysIpc(const std::string &keySystem) const = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineCapabilitiesIpcFactory.h b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineCapabilitiesIpcFactory.h new file mode 100644 index 000000000..cec92eba6 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineCapabilitiesIpcFactory.h @@ -0,0 +1,62 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_CAPABILITIES_IPC_FACTORY_H_ +#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_CAPABILITIES_IPC_FACTORY_H_ + +/** + * @file IMediaPipelineCapabilities.h + * + * The definition of the IMediaPipelineCapabilities interface. + */ + +#include "IMediaPipelineCapabilities.h" +#include +#include +#include + +namespace firebolt::rialto::client +{ +/** + * @brief IMediaPipelineCapabilities factory class, for getting the IMediaPipelineCapabilities singleton object for ipc. + */ +class IMediaPipelineCapabilitiesIpcFactory +{ +public: + IMediaPipelineCapabilitiesIpcFactory() = default; + virtual ~IMediaPipelineCapabilitiesIpcFactory() = default; + + /** + * @brief Gets the IMediaPipelineCapabilitiesIpcFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Gets the IMediaPipelineCapabilities singleton object for ipc. + * + * @retval the MediaPipelineCapabilities for ipc instance or null on error. + */ + virtual std::unique_ptr createMediaPipelineCapabilitiesIpc() const = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_CAPABILITIES_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpc.h b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpc.h new file mode 100644 index 000000000..6a727e551 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpc.h @@ -0,0 +1,458 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_H_ + +#include + +#include +#include + +#include "IMediaPipeline.h" +#include "IMediaPipelineIpcClient.h" +#include "MediaCommon.h" + +namespace firebolt::rialto::client +{ +class IMediaPipelineIpc; +class IIpcClient; + +/** + * @brief IMediaPipelineIpc factory class, returns a concrete implementation of IMediaPipelineIpc + */ +class IMediaPipelineIpcFactory +{ +public: + IMediaPipelineIpcFactory() = default; + virtual ~IMediaPipelineIpcFactory() = default; + + /** + * @brief Gets the IMediaPipelineIpcFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Creates a IMediaPipelineIpc object. + * + * @param[in] client : The Rialto ipc media player client. + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. + * + * @retval the new media player ipc instance or null on error. + */ + virtual std::unique_ptr createMediaPipelineIpc(IMediaPipelineIpcClient *client, + const VideoRequirements &videoRequirements, + std::weak_ptr ipcClient = {}) = 0; +}; + +/** + * @brief The definition of the IMediaPipelineIpc interface. + * + * This interface defines the media player ipc APIs that are used to communicate with the Rialto server. + */ +class IMediaPipelineIpc +{ +public: + IMediaPipelineIpc() = default; + virtual ~IMediaPipelineIpc() = default; + + IMediaPipelineIpc(const IMediaPipelineIpc &) = delete; + IMediaPipelineIpc &operator=(const IMediaPipelineIpc &) = delete; + IMediaPipelineIpc(IMediaPipelineIpc &&) = delete; + IMediaPipelineIpc &operator=(IMediaPipelineIpc &&) = delete; + + /** + * @brief Request to attach the source to the server backend. + * + * @param[in] source : The source. + * @param[out] sourceId : The unique id of the media source. + * + * @retval true on success. + */ + virtual bool attachSource(const std::unique_ptr &source, int32_t &sourceId) = 0; + + /** + * @brief Request to remove the source to the server backend. + * + * @param[in] sourceId : The unique id of the media source. + * + * @retval true on success. + */ + virtual bool removeSource(int32_t sourceId) = 0; + + virtual bool allSourcesAttached() = 0; + + /** + * @brief Request to load the media pipeline. + * + * @param[in] type : The media type. + * @param[in] mimeType : The MIME type. + * @param[in] url : The URL. + * + * @retval true on success. + */ + virtual bool load(MediaType type, const std::string &mimeType, const std::string &url) = 0; + + /** + * @brief Request to set the coordinates of the video window. + * + * @param[in] x : The x position in pixels. + * @param[in] y : The y position in pixels. + * @param[in] width : The width in pixels. + * @param[in] height : The height in pixels. + * + * @retval true on success. + */ + virtual bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; + + /** + * @brief Request play on the playback session. + * + * @retval true on success. + */ + virtual bool play() = 0; + + /** + * @brief Request pause on the playback session. + * + * @retval true on success. + */ + virtual bool pause() = 0; + + /** + * @brief Request stop on the playback session. + * + * @retval true on success. + */ + virtual bool stop() = 0; + + /** + * @brief Notify server that the data has been written to the shared memory. + * + * @param[in] status : The status. + * @param[in] requestId : The Need data request id. + * + * @retval true on success. + */ + virtual bool haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t requestId) = 0; + + /** + * @brief Request new playback position. + * + * @param[in] position : The playback position in nanoseconds. + * + * @retval true on success. + */ + virtual bool setPosition(int64_t position) = 0; + + /** + * @brief Get the playback position in nanoseconds. + * + * This method is sychronous, it returns current playback position + * + * @param[out] position : The playback position in nanoseconds + * + * @retval true on success. + */ + virtual bool getPosition(int64_t &position) = 0; + + /** + * @brief Sets the "Immediate Output" property for this source. + * + * This method is asynchronous + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] immediateOutput : The desired immediate output mode on the sink + * + * @retval true on success. + */ + virtual bool setImmediateOutput(int32_t sourceId, bool immediateOutput) = 0; + + /** + * @brief Gets the "Immediate Output" property for this source. + * + * This method is sychronous + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[out] immediateOutput : Returns the immediate output mode of the sink + * + * @retval true on success. + */ + virtual bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) = 0; + + /** + * @brief Get stats for this source. + * + * This method is sychronous, it returns dropped frames and rendered frames + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[out] droppedFrames : The number of dropped frames + * @param[out] renderedFrames : The number of rendered frames + * + * @retval true on success. + */ + virtual bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; + + /** + * @brief Request new playback rate. + * + * @param[in] rate : The playback rate. + * + * @retval true on success. + */ + virtual bool setPlaybackRate(double rate) = 0; + + /** + * @brief Requests to render a prerolled frame + */ + virtual bool renderFrame() = 0; + + /** + * @brief Set level and transition of audio attenuation. + * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume) + * + * @param[in] targetVolume : Target volume level (0.0 - 1.0) + * @param[in] volumeDuration : Duration of the volume transition in milliseconds + * @param[in] ease_type : Easing type for the volume transition + * + * @retval true on success false otherwise + */ + virtual bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) = 0; + + /** + * @brief Get current audio level. Fetches the current volume level for the pipeline. + * + * @param[out] volume Current volume level (range 0.0 - 1.0) + * + * @retval true on success false otherwise + */ + virtual bool getVolume(double &volume) = 0; + + /** + * @brief Set mute status of pipeline. + * + * Change mute status of media source + * + * @param[in] sourceId Source, which mute status should be changed + * @param[in] mute Desired mute state, true=muted, false=not muted + * + * @retval true on success false otherwise + */ + virtual bool setMute(int32_t sourceId, bool mute) = 0; + + /** + * @brief Get current mute status of the media source + * + * @param[in] sourceId Source, which mute status should be fetched + * @param[out] mute Current mute state + * + * @retval true on success false otherwise + */ + virtual bool getMute(int32_t sourceId, bool &mute) = 0; + + /** + * @brief Change Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + virtual bool setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; + + /** + * @brief Get Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; + + /** + * @brief Set low latency property on the pipeline. Default false. + * + * @param[in] lowLatency : The low latency value to set. + * + * @retval true on success false otherwise + */ + virtual bool setLowLatency(bool lowLatency) = 0; + + /** + * @brief Set sync property on the pipeline. Default false. + * + * @param[in] sync : The sync value to set. + * + * @retval true on success false otherwise + */ + virtual bool setSync(bool sync) = 0; + + /** + * @brief Get sync property on the pipeline. + * + * @param[out] sync : Current sync value. + * + * @retval true on success false otherwise + */ + virtual bool getSync(bool &sync) = 0; + + /** + * @brief Set sync off property on the pipeline. Default false. + * + * @param[in] syncOff : The sync off value to set. + * + * @retval true on success false otherwise + */ + virtual bool setSyncOff(bool syncOff) = 0; + + /** + * @brief Set stream sync mode property on the pipeline. Default 0. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] streamSyncMode : The stream sync mode value to set. + * + * @retval true on success false otherwise + */ + virtual bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) = 0; + + /** + * @brief Get stream sync mode property on the pipeline. + * + * @param[out] streamSyncMode : Current stream sync mode value. + * + * @retval true on success false otherwise + */ + virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; + + /** + * @brief Flushes a source. + * + * This method is called by Rialto Client to flush out all queued data for a media source stream. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] resetTime : True if time should be reset + * @param[out] async : True if flushed source is asynchronous (will preroll after flush) + * + * @retval true on success. + */ + virtual bool flush(int32_t sourceId, bool resetTime, bool &async) = 0; + + /** + * @brief Set the source position in nanoseconds. + * + * This method sets the start position for a source. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] position : The position in nanoseconds. + * @param[in] resetTime : True if time should be reset + * @param[in] appliedRate : The applied rate after seek + * @param[in] stopPosition : The position of last pushed buffer + * + * @retval true on success. + */ + virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) = 0; + + /** + * @brief Set the subtitle offset in nanoseconds. + * + * This method sets the subtitle offset for a subtitle source. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] position : The offset position in nanoseconds. + * + * @retval true on success. + */ + virtual bool setSubtitleOffset(int32_t sourceId, int64_t position) = 0; + + /** + * @brief Process audio gap + * + * This method handles audio gap in order to avoid audio pops during transitions. + * + * @param[in] position : Audio pts fade pts value + * @param[in] duration : Audio pts fade duration + * @param[in] discontinuityGap : Audio discontinuity gap + * @param[in] audioAac : True if audio codec is AAC + * + * @retval true on success. + */ + virtual bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; + + /** + * @brief Set buffering limit + * + * This method enables/disables limit buffering and sets millisecond threshold used. + * Use kInvalidLimitBuffering to disable limit buffering + * + * @param[in] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + virtual bool setBufferingLimit(uint32_t limitBufferingMs) = 0; + + /** + * @brief Get buffering limit + * + * This method returns current value of buffering limit in milliseconds + * Method will return kInvalidLimitBuffering limit buffering is disabled + * + * @param[out] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; + + /** + * @brief Enables/disables the buffering option + * + * This method enables the buffering option so that BUFFERING messages are + * emitted based on low-/high-percent thresholds. + * + * @param[in] useBuffering : true if buffering option enabled. + * + * @retval true on success. + */ + virtual bool setUseBuffering(bool useBuffering) = 0; + + /** + * @brief Check, if buffering is enabled + * + * This method returns true, if buffering is enabled + * + * @param[out] useBuffering : true if buffering option is enabled. + * + * @retval true on success. + */ + virtual bool getUseBuffering(bool &useBuffering) = 0; + + /** + * @brief Request to switch the source to the server backend. + * + * @param[in] source : The source. + * + * @retval true on success. + */ + virtual bool switchSource(const std::unique_ptr &source) = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpcClient.h b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpcClient.h new file mode 100644 index 000000000..9e50a3a23 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpcClient.h @@ -0,0 +1,121 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_CLIENT_H_ +#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_CLIENT_H_ + +#include +#include +#include +#include + +/** + * @file IMediaPipelineIpcClient.h + * + * The definition of the IMediaPipelineIpcClient interface. + */ + +namespace firebolt::rialto::client +{ +/** + * @brief The Rialto media player client ipc interface. + */ +class IMediaPipelineIpcClient +{ +public: + IMediaPipelineIpcClient() = default; + virtual ~IMediaPipelineIpcClient() = default; + + IMediaPipelineIpcClient(const IMediaPipelineIpcClient &) = delete; + IMediaPipelineIpcClient &operator=(const IMediaPipelineIpcClient &) = delete; + IMediaPipelineIpcClient(IMediaPipelineIpcClient &&) = delete; + IMediaPipelineIpcClient &operator=(IMediaPipelineIpcClient &&) = delete; + + /** + * @brief Notifies the rialto client of the playback state. + * + * @param[in] state : The new playback state. + */ + virtual void notifyPlaybackState(PlaybackState state) = 0; + + /** + * @brief Handler for a playback position update from the server. + * + * @param[in] event : The playback position changed event structure. + */ + virtual void notifyPosition(int64_t position) = 0; + + /** + * @brief Notifies the rialto client of the network state. + * + * @param[in] state : The new network state. + */ + virtual void notifyNetworkState(NetworkState state) = 0; + + /** + * @brief Notifies the rialto client of a need data request. + * + * @param[in] sourceId : The source to read data from. + * @param[in] frameCount : The number of frames to read. + * @param[in] requestId : Need data request id. + * @param[in] shmInfo : Information for populating the shared memory (null if not applicable to the client). + */ + virtual void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId, + const std::shared_ptr &shmInfo) = 0; + + /** + * @brief Notifies the rialto client of a Quality Of Service update. + * + * @param[in] sourceId : The id of the source that produced the Qos. + * @param[in] qosInfo : The information provided in the update. + */ + virtual void notifyQos(int32_t sourceId, const QosInfo &qosInfo) = 0; + + /** + * @brief Notifies the client that buffer underflow occurred. + * + * Notification shall be sent whenever a video/audio buffer underflow occurs + * + * @param[in] sourceId : The id of the source that produced the buffer underflow + */ + virtual void notifyBufferUnderflow(int32_t sourceId) = 0; + + /** + * @brief Notifies the client that a non-fatal error has occurred in the player. + * + * PlaybackState remains unchanged when an error occurs. + * + * @param[in] sourceId : The id of the source that produced the error. + * @param[in] error : The type of error that occurred. + */ + virtual void notifyPlaybackError(int32_t sourceId, PlaybackError error) = 0; + + /** + * @brief Notifies the client that the source has been flushed. + * + * Notification shall be sent whenever a flush procedure is finished. + * + * @param[in] sourceId : The id of the source that has been flushed. + */ + virtual void notifySourceFlushed(int32_t sourceId) = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_CLIENT_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpc.h b/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpc.h new file mode 100644 index 000000000..a8bc997cd --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpc.h @@ -0,0 +1,170 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_H_ +#define FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_H_ + +#include + +#include +#include + +#include +#include + +#include "IWebAudioPlayerIpcClient.h" + +namespace firebolt::rialto::client +{ +class IWebAudioPlayerIpc; +class IIpcClient; + +/** + * @brief IWebAudioPlayerIpc factory class, returns a concrete implementation of IWebAudioPlayerIpc + */ +class IWebAudioPlayerIpcFactory +{ +public: + IWebAudioPlayerIpcFactory() = default; + virtual ~IWebAudioPlayerIpcFactory() = default; + + /** + * @brief Gets the IWebAudioPlayerIpcFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Creates a IWebAudioPlayerIpc object. + * + * @param[in] client : The Rialto ipc web audio player client. + * + * @retval the new web audio player ipc instance or null on error. + */ + virtual std::unique_ptr + createWebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config, std::weak_ptr ipcClient = {}) = 0; +}; + +/** + * @brief The definition of the IWebAudioPlayerIpc interface. + * + * This interface defines the web audio player ipc APIs that are used to communicate with the Rialto server. + */ +class IWebAudioPlayerIpc +{ +public: + IWebAudioPlayerIpc() = default; + virtual ~IWebAudioPlayerIpc() = default; + + IWebAudioPlayerIpc(const IWebAudioPlayerIpc &) = delete; + IWebAudioPlayerIpc &operator=(const IWebAudioPlayerIpc &) = delete; + IWebAudioPlayerIpc(IWebAudioPlayerIpc &&) = delete; + IWebAudioPlayerIpc &operator=(IWebAudioPlayerIpc &&) = delete; + + /** + * @brief Play the web audio. + * + * @retval true on success. + */ + virtual bool play() = 0; + + /** + * @brief Pause the web audio. + * + * @retval true on success. + */ + virtual bool pause() = 0; + + /** + * @brief Notify EOS. + * + * @retval true on success. + */ + virtual bool setEos() = 0; + + /** + * @brief Get the available frames. + * + * @param[out] availableFrames : Number of frames available to be written. + * @param[out] webAudioShmInfo : Location in shm to write the data. + * + * @retval true on success. + */ + virtual bool getBufferAvailable(uint32_t &availableFrames, + const std::shared_ptr &webAudioShmInfo) = 0; + + /** + * @brief Get the delay frames. + * + * Gets the frame delay of the playback from Rialto. Frame delay is the number + * of frames left to play by the server. + * + * @param[out] delayFrames : Number of frames to be played. + * + * @retval true on success. + */ + virtual bool getBufferDelay(uint32_t &delayFrames) = 0; + + /** + * @brief Write audio frames + * + * Sends a buffer of audio data for playback + * + * @param[in] numberOfFrames : Number of frames written to shared memory. + * + * @retval true on success. + */ + virtual bool writeBuffer(const uint32_t numberOfFrames) = 0; + + /** + * @brief Get device information. + * + * @param[out] preferredFrames : preferred number of frames to be commited. + * @param[out] maximumFrames : Maximum number of frames that can be commited. + * @param[out] supportDeferredPlay : Whether defered play is supported. + * + * @retval true on success. + */ + virtual bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) = 0; + + /** + * + * @brief Set level and transition of audio attenuation + * + * @param[in] volume : Target volume level (0.0 - 1.0) + * + * @retval true on success false otherwise + */ + virtual bool setVolume(double volume) = 0; + + /** + * @brief Get current audio level + * + * @param[out] volume : Current volume level (range 0.0 - 1.0) + * + * @retval true on success false otherwise + */ + virtual bool getVolume(double &volume) = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpcClient.h b/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpcClient.h new file mode 100644 index 000000000..370207cbd --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpcClient.h @@ -0,0 +1,58 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_CLIENT_H_ +#define FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_CLIENT_H_ + +#include + +/** + * @file IWebAudioPlayerIpcClient.h + * + * The definition of the IWebAudioPlayerIpcClient interface. + */ + +namespace firebolt::rialto::client +{ +/** + * @brief The Rialto web audio player client ipc interface. + */ +class IWebAudioPlayerIpcClient +{ +public: + IWebAudioPlayerIpcClient() = default; + virtual ~IWebAudioPlayerIpcClient() = default; + + IWebAudioPlayerIpcClient(const IWebAudioPlayerIpcClient &) = delete; + IWebAudioPlayerIpcClient &operator=(const IWebAudioPlayerIpcClient &) = delete; + IWebAudioPlayerIpcClient(IWebAudioPlayerIpcClient &&) = delete; + IWebAudioPlayerIpcClient &operator=(IWebAudioPlayerIpcClient &&) = delete; + + /** + * @brief Notifies the client of the playback state. + * @param[in] state : The new playback state. + * + * @retval true on success. + */ + virtual void notifyState(WebAudioPlayerState state) = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_CLIENT_H_ diff --git a/middleware/rialto-client/media/client/ipc/proto/controlmodule.proto b/middleware/rialto-client/media/client/ipc/proto/controlmodule.proto new file mode 120000 index 000000000..6e95f531f --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/proto/controlmodule.proto @@ -0,0 +1 @@ +../../../../proto/controlmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/mediakeyscapabilitiesmodule.proto b/middleware/rialto-client/media/client/ipc/proto/mediakeyscapabilitiesmodule.proto new file mode 120000 index 000000000..e508c1392 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/proto/mediakeyscapabilitiesmodule.proto @@ -0,0 +1 @@ +../../../../proto/mediakeyscapabilitiesmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/mediakeysmodule.proto b/middleware/rialto-client/media/client/ipc/proto/mediakeysmodule.proto new file mode 120000 index 000000000..98b44b620 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/proto/mediakeysmodule.proto @@ -0,0 +1 @@ +../../../../proto/mediakeysmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/mediapipelinecapabilitiesmodule.proto b/middleware/rialto-client/media/client/ipc/proto/mediapipelinecapabilitiesmodule.proto new file mode 120000 index 000000000..7af44cdd7 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/proto/mediapipelinecapabilitiesmodule.proto @@ -0,0 +1 @@ +../../../../proto/mediapipelinecapabilitiesmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/mediapipelinemodule.proto b/middleware/rialto-client/media/client/ipc/proto/mediapipelinemodule.proto new file mode 120000 index 000000000..6f1b4bdbe --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/proto/mediapipelinemodule.proto @@ -0,0 +1 @@ +../../../../proto/mediapipelinemodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/rialtocommon.proto b/middleware/rialto-client/media/client/ipc/proto/rialtocommon.proto new file mode 120000 index 000000000..2c6e7a2bb --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/proto/rialtocommon.proto @@ -0,0 +1 @@ +../../../../proto/rialtocommon.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/webaudioplayermodule.proto b/middleware/rialto-client/media/client/ipc/proto/webaudioplayermodule.proto new file mode 120000 index 000000000..4c84680f4 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/proto/webaudioplayermodule.proto @@ -0,0 +1 @@ +../../../../proto/webaudioplayermodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/source/ControlIpc.cpp b/middleware/rialto-client/media/client/ipc/source/ControlIpc.cpp new file mode 100644 index 000000000..5b277d154 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/ControlIpc.cpp @@ -0,0 +1,265 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ControlIpc.h" +#include "RialtoClientLogging.h" +#include "SchemaVersion.h" + +namespace +{ +firebolt::rialto::ApplicationState +convertApplicationState(const firebolt::rialto::ApplicationStateChangeEvent_ApplicationState &state) +{ + switch (state) + { + case firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_RUNNING: + return firebolt::rialto::ApplicationState::RUNNING; + case firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_INACTIVE: + return firebolt::rialto::ApplicationState::INACTIVE; + case firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_UNKNOWN: + break; + } + return firebolt::rialto::ApplicationState::UNKNOWN; +} +} // namespace + +namespace firebolt::rialto::client +{ +std::shared_ptr IControlIpcFactory::createFactory() +{ + return ControlIpcFactory::createFactory(); +} + +std::shared_ptr ControlIpcFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the rialto control ipc factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr ControlIpcFactory::createControlIpc(IControlClient *controlClient) +{ + auto &ipcClient{IIpcClientAccessor::instance().getIpcClient()}; + auto controlIpc{std::make_shared(controlClient, ipcClient, + firebolt::rialto::common::IEventThreadFactory::createFactory())}; + ipcClient.registerConnectionObserver(controlIpc); + return controlIpc; +} + +ControlIpc::ControlIpc(IControlClient *controlClient, IIpcClient &ipcClient, + const std::shared_ptr &eventThreadFactory) + : IpcModule(ipcClient), m_controlClient(controlClient), + m_eventThread(eventThreadFactory->createEventThread("rialto-control-events")) +{ + if (!attachChannel()) + { + throw std::runtime_error("Failed attach to the ipc channel"); + } +} + +ControlIpc::~ControlIpc() +{ + // detach the Ipc channel + detachChannel(); + + // destroy the thread processing async notifications + m_eventThread.reset(); +} + +bool ControlIpc::getSharedMemory(int32_t &fd, uint32_t &size) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + std::shared_ptr<::firebolt::rialto::ControlModule_Stub> controlStub = m_controlStub; + + firebolt::rialto::GetSharedMemoryRequest request; + + firebolt::rialto::GetSharedMemoryResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + controlStub->getSharedMemory(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get the shared memory due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + fd = response.fd(); + size = response.size(); + + return true; +} + +bool ControlIpc::registerClient() +{ + const auto kCurrentSchemaVersion{common::getCurrentSchemaVersion()}; + + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + std::shared_ptr<::firebolt::rialto::ControlModule_Stub> controlStub = m_controlStub; + + firebolt::rialto::RegisterClientRequest request; + firebolt::rialto::RegisterClientResponse response; + firebolt::rialto::SchemaVersion clientSchemaVersion; + request.mutable_client_schema_version()->set_major(kCurrentSchemaVersion.major()); + request.mutable_client_schema_version()->set_minor(kCurrentSchemaVersion.minor()); + request.mutable_client_schema_version()->set_patch(kCurrentSchemaVersion.patch()); + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + controlStub->registerClient(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to register client due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + m_controlHandle = response.control_handle(); + + if (!response.has_server_schema_version()) + { + RIALTO_CLIENT_LOG_WARN("Server proto schema version not known"); + return true; + } + + const common::SchemaVersion kServerSchemaVersion{response.server_schema_version().major(), + response.server_schema_version().minor(), + response.server_schema_version().patch()}; + if (kCurrentSchemaVersion == kServerSchemaVersion) + { + RIALTO_CLIENT_LOG_DEBUG("Server and Client proto schema versions are equal"); + } + else if (kCurrentSchemaVersion.isCompatible(kServerSchemaVersion)) + { + RIALTO_CLIENT_LOG_INFO("Server and Client proto schema versions are compatible. Server schema version: %s, " + "Client schema version: %s", + kServerSchemaVersion.str().c_str(), kCurrentSchemaVersion.str().c_str()); + } + else + { + RIALTO_CLIENT_LOG_ERROR("Server and Client proto schema versions are not compatible. Server schema version: " + "%s, Client schema version: %s", + kServerSchemaVersion.str().c_str(), kCurrentSchemaVersion.str().c_str()); + return false; + } + + return true; +} + +bool ControlIpc::createRpcStubs(const std::shared_ptr &ipcChannel) +{ + m_controlStub = std::make_unique<::firebolt::rialto::ControlModule_Stub>(ipcChannel.get()); + if (!m_controlStub) + { + return false; + } + return true; +} + +bool ControlIpc::subscribeToEvents(const std::shared_ptr &ipcChannel) +{ + if (!ipcChannel) + { + return false; + } + + int eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&ControlIpc::onApplicationStateUpdated, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&ControlIpc::onPing, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + return true; +} + +void ControlIpc::onConnectionBroken() +{ + m_eventThread->add([this]() { m_controlClient->notifyApplicationState(ApplicationState::UNKNOWN); }); +} + +void ControlIpc::onApplicationStateUpdated(const std::shared_ptr &event) +{ + // It's possible, that ApplicationStateChangeEvent comes before RegisterClientResponse, so do not check control_handle() here. + m_controlClient->notifyApplicationState(convertApplicationState(event->application_state())); +} + +void ControlIpc::onPing(const std::shared_ptr &event) +{ + if (m_controlHandle != event->control_handle()) + { + RIALTO_CLIENT_LOG_WARN("PingEvent received with wrong handle"); + return; + } + + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return; + } + firebolt::rialto::AckRequest request; + request.set_control_handle(m_controlHandle); + request.set_id(event->id()); + firebolt::rialto::AckResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_controlStub->ack(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to ack due to '%s'", ipcController->ErrorText().c_str()); + } +} +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/IpcClient.cpp b/middleware/rialto-client/media/client/ipc/source/IpcClient.cpp new file mode 100644 index 000000000..1e1aa4881 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/IpcClient.cpp @@ -0,0 +1,219 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IpcClient.h" +#include "RialtoClientLogging.h" + +namespace firebolt::rialto::client +{ +IIpcClientAccessor &IIpcClientAccessor::instance() +{ + static IpcClientAccessor factory; + return factory; +} + +IIpcClient &IpcClientAccessor::getIpcClient() const +{ + static IpcClient ipcClient{ipc::IChannelFactory::createFactory(), ipc::IControllerFactory::createFactory(), + ipc::IBlockingClosureFactory::createFactory()}; + return ipcClient; +} + +IpcClient::IpcClient(const std::shared_ptr &ipcChannelFactory, + const std::shared_ptr &ipcControllerFactory, + const std::shared_ptr &blockingClosureFactory) + : m_ipcControllerFactory(ipcControllerFactory), m_ipcChannelFactory(ipcChannelFactory), + m_blockingClosureFactory(blockingClosureFactory), m_disconnecting(false) +{ + // For now, always connect the client on construction + if (!connect()) + { + throw std::runtime_error("Could not connect client"); + } +} + +IpcClient::~IpcClient() +{ + if (!disconnect()) + { + RIALTO_CLIENT_LOG_WARN("Could not disconnect client"); + } +} + +bool IpcClient::connect() +{ + if (m_ipcChannel) + { + RIALTO_CLIENT_LOG_INFO("Client already connected"); + return true; + } + + // Verify that the version of the library that we linked against is + // compatible with the version of the headers we compiled against. + GOOGLE_PROTOBUF_VERIFY_VERSION; + + // check if either of following env vars are set to determine the location of the rialto socket + // - RIALTO_SOCKET_PATH should specify the absolute path to the socket to connect to + // - RIALTO_SOCKET_FD should specify the number of a file descriptor of the socket to connect to + const char *kRialtoPath = getenv("RIALTO_SOCKET_PATH"); + const char *kRialtoFd = getenv("RIALTO_SOCKET_FD"); + if (kRialtoFd) + { + char *end = nullptr; + int fd = strtol(kRialtoFd, &end, 10); + if ((errno != 0) || (kRialtoFd == end) || (*end != '\0')) + { + RIALTO_CLIENT_LOG_SYS_ERROR(errno, "Invalid value set in RIALTO_SOCKET_FD env var"); + return false; + } + + m_ipcChannel = m_ipcChannelFactory->createChannel(fd); + } + else if (kRialtoPath) + { + m_ipcChannel = m_ipcChannelFactory->createChannel(kRialtoPath); + } + else + { + RIALTO_CLIENT_LOG_ERROR("No rialto socket specified"); + return false; + } + + // check if the channel was opened + if (!m_ipcChannel) + { + RIALTO_CLIENT_LOG_ERROR("Failed to open a connection to the ipc socket"); + return false; + } + + // spin up the thread that runs the IPC event loop + m_ipcThread = std::thread(&IpcClient::processIpcThread, this); + if (!m_ipcThread.joinable()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create thread for IPC"); + return false; + } + + return true; +} + +bool IpcClient::disconnect() +{ + // Increase reference in case client disconnects from another thread + std::shared_ptr ipcChannel = m_ipcChannel; + if (!ipcChannel) + { + // The ipc channel may have disconnected unexpectedly, join the ipc thread if possible + if (m_ipcThread.joinable()) + m_ipcThread.join(); + + RIALTO_CLIENT_LOG_INFO("Client already disconnect"); + return true; + } + + RIALTO_CLIENT_LOG_INFO("closing IPC channel"); + m_disconnecting = true; + + // disconnect from the server, this should terminate the thread so join that too + ipcChannel->disconnect(); + + if (m_ipcThread.joinable()) + m_ipcThread.join(); + + // destroy the IPC channel + m_ipcChannel.reset(); + + m_disconnecting = false; + + return true; +} + +void IpcClient::processIpcThread() +{ + pthread_setname_np(pthread_self(), "rialto-ipc"); + + RIALTO_CLIENT_LOG_INFO("started ipc thread"); + + while (m_ipcChannel->process()) + { + m_ipcChannel->wait(-1); + } + + if (!m_disconnecting) + { + RIALTO_CLIENT_LOG_ERROR("The ipc channel unexpectedly disconnected, destroying the channel"); + + // Safe to destroy the ipc objects in the ipc thread as the client has already disconnected. + // This ensures the channel is destructed and that all ongoing ipc calls are unblocked. + m_ipcChannel.reset(); + + auto connectionObserver{m_connectionObserver.lock()}; + if (connectionObserver) + { + connectionObserver->onConnectionBroken(); + } + } + + RIALTO_CLIENT_LOG_INFO("exiting ipc thread"); +} + +std::weak_ptr<::firebolt::rialto::ipc::IChannel> IpcClient::getChannel() const +{ + return m_ipcChannel; +} + +std::shared_ptr IpcClient::createBlockingClosure() +{ + // Increase reference in case client disconnects from another thread + std::shared_ptr ipcChannel = m_ipcChannel; + if (!ipcChannel) + { + RIALTO_CLIENT_LOG_ERROR("ipc channel not connected"); + return nullptr; + } + + // check which thread we're being called from, this determines if we pump + // event loop from within the wait() method or not + if (m_ipcThread.get_id() == std::this_thread::get_id()) + return m_blockingClosureFactory->createBlockingClosurePoll(ipcChannel); + else + return m_blockingClosureFactory->createBlockingClosureSemaphore(); +} + +std::shared_ptr IpcClient::createRpcController() +{ + return m_ipcControllerFactory->create(); +} + +bool IpcClient::reconnect() +{ + RIALTO_CLIENT_LOG_INFO("Trying to reconnect channel"); + if (disconnect()) + { + return connect(); + } + return false; +} + +void IpcClient::registerConnectionObserver(const std::weak_ptr &observer) +{ + m_connectionObserver = observer; +} + +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/IpcModule.cpp b/middleware/rialto-client/media/client/ipc/source/IpcModule.cpp new file mode 100644 index 000000000..11418c640 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/IpcModule.cpp @@ -0,0 +1,136 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IpcModule.h" +#include "RialtoClientLogging.h" + +namespace firebolt::rialto::client +{ +IpcModule::IpcModule(IIpcClient &ipcClient) : m_ipc{ipcClient} +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); +} + +IpcModule::~IpcModule() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); +} + +bool IpcModule::unsubscribeFromAllEvents(const std::shared_ptr &ipcChannel) +{ + if (!ipcChannel) + { + return false; + } + + bool result = true; + for (auto it = m_eventTags.begin(); it != m_eventTags.end(); it++) + { + if (!ipcChannel->unsubscribe(*it)) + { + result = false; + } + } + m_eventTags.clear(); + + return result; +} + +bool IpcModule::attachChannel() +{ + // get the channel + std::shared_ptr ipcChannel{getConnectedChannel()}; + + // If not connected, try to recover and reconnect first + if (!ipcChannel) + { + RIALTO_CLIENT_LOG_WARN("Channel not connected. Trying to recover..."); + if (!m_ipc.reconnect()) + { + RIALTO_CLIENT_LOG_ERROR("Reconnection failed."); + return false; + } + + ipcChannel = getConnectedChannel(); + if (!ipcChannel) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get the ipc channel"); + return false; + } + } + + // create the RPC stubs + if (!createRpcStubs(ipcChannel)) + { + RIALTO_CLIENT_LOG_ERROR("Could not create the ipc module stubs"); + return false; + } + + // install listeners + if (!subscribeToEvents(ipcChannel)) + { + RIALTO_CLIENT_LOG_ERROR("Could not subscribe to ipc module events"); + unsubscribeFromAllEvents(ipcChannel); + return false; + } + + m_ipcChannel = ipcChannel; + + return true; +} + +void IpcModule::detachChannel() +{ + // uninstalls listeners + if (!unsubscribeFromAllEvents(m_ipcChannel.lock())) + { + RIALTO_CLIENT_LOG_ERROR("Failed to unsubscribe to some ipc module events, this can lead to core dumps in IPC"); + } + + // remove IPC + m_ipcChannel.reset(); +} + +bool IpcModule::reattachChannelIfRequired() +{ + std::shared_ptr ipcChannel = m_ipcChannel.lock(); + if ((nullptr == ipcChannel) || (!ipcChannel->isConnected())) + { + RIALTO_CLIENT_LOG_INFO("Ipc channel no longer connected, attach new channel"); + detachChannel(); + if (!attachChannel()) + { + RIALTO_CLIENT_LOG_ERROR("Failed attach to the ipc channel"); + return false; + } + } + + return true; +} + +std::shared_ptr IpcModule::getConnectedChannel() +{ + std::shared_ptr ipcChannel = m_ipc.getChannel().lock(); + if (ipcChannel && ipcChannel->isConnected()) + { + return ipcChannel; + } + return nullptr; +} +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/MediaKeysCapabilitiesIpc.cpp b/middleware/rialto-client/media/client/ipc/source/MediaKeysCapabilitiesIpc.cpp new file mode 100644 index 000000000..e5f63a2d0 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/MediaKeysCapabilitiesIpc.cpp @@ -0,0 +1,216 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaKeysCapabilitiesIpc.h" +#include "RialtoClientLogging.h" + +namespace firebolt::rialto::client +{ +std::weak_ptr MediaKeysCapabilitiesIpcFactory::m_mediaKeysCapabilitiesIpc; +std::mutex MediaKeysCapabilitiesIpcFactory::m_creationMutex; + +std::shared_ptr IMediaKeysCapabilitiesIpcFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys capabilities ipc factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr MediaKeysCapabilitiesIpcFactory::getMediaKeysCapabilitiesIpc() const +{ + std::lock_guard lock{m_creationMutex}; + + std::shared_ptr mediaKeysCapabilitiesIpc = + MediaKeysCapabilitiesIpcFactory::m_mediaKeysCapabilitiesIpc.lock(); + + if (!mediaKeysCapabilitiesIpc) + { + try + { + mediaKeysCapabilitiesIpc = + std::make_shared(IIpcClientAccessor::instance().getIpcClient()); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys capabilities ipc, reason: %s", e.what()); + } + + MediaKeysCapabilitiesIpcFactory::m_mediaKeysCapabilitiesIpc = mediaKeysCapabilitiesIpc; + } + + return mediaKeysCapabilitiesIpc; +} + +MediaKeysCapabilitiesIpc::MediaKeysCapabilitiesIpc(IIpcClient &ipcClient) : IpcModule(ipcClient) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + if (!attachChannel()) + { + throw std::runtime_error("Failed attach to the ipc channel"); + } +} + +MediaKeysCapabilitiesIpc::~MediaKeysCapabilitiesIpc() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + detachChannel(); +} + +bool MediaKeysCapabilitiesIpc::createRpcStubs(const std::shared_ptr &ipcChannel) +{ + m_mediaKeysCapabilitiesStub = + std::make_unique<::firebolt::rialto::MediaKeysCapabilitiesModule_Stub>(ipcChannel.get()); + if (!m_mediaKeysCapabilitiesStub) + { + return false; + } + return true; +} + +std::vector MediaKeysCapabilitiesIpc::getSupportedKeySystems() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return {}; + } + + firebolt::rialto::GetSupportedKeySystemsRequest request; + firebolt::rialto::GetSupportedKeySystemsResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysCapabilitiesStub->getSupportedKeySystems(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get supported key systems due to '%s'", ipcController->ErrorText().c_str()); + return {}; + } + + return std::vector{response.key_systems().begin(), response.key_systems().end()}; +} + +bool MediaKeysCapabilitiesIpc::supportsKeySystem(const std::string &keySystem) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SupportsKeySystemRequest request; + request.set_key_system(keySystem); + + firebolt::rialto::SupportsKeySystemResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysCapabilitiesStub->supportsKeySystem(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to supports key system due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return response.is_supported(); +} + +bool MediaKeysCapabilitiesIpc::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetSupportedKeySystemVersionRequest request; + request.set_key_system(keySystem); + + firebolt::rialto::GetSupportedKeySystemVersionResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysCapabilitiesStub->getSupportedKeySystemVersion(ipcController.get(), &request, &response, + blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get supported key system version due to '%s'", + ipcController->ErrorText().c_str()); + return false; + } + version = response.version(); + + return true; +} + +bool MediaKeysCapabilitiesIpc::isServerCertificateSupported(const std::string &keySystem) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::IsServerCertificateSupportedRequest request; + request.set_key_system(keySystem); + + firebolt::rialto::IsServerCertificateSupportedResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysCapabilitiesStub->isServerCertificateSupported(ipcController.get(), &request, &response, + blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to check if server certificate is supported due to '%s'", + ipcController->ErrorText().c_str()); + return false; + } + + return response.is_supported(); +} + +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/MediaKeysIpc.cpp b/middleware/rialto-client/media/client/ipc/source/MediaKeysIpc.cpp new file mode 100644 index 000000000..68a8b0e98 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/MediaKeysIpc.cpp @@ -0,0 +1,936 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaKeysIpc.h" +#include "RialtoClientLogging.h" + +namespace +{ +firebolt::rialto::MediaKeyErrorStatus +convertMediaKeyErrorStatus(const firebolt::rialto::ProtoMediaKeyErrorStatus &errorStatus) +{ + switch (errorStatus) + { + case firebolt::rialto::ProtoMediaKeyErrorStatus::OK: + { + return firebolt::rialto::MediaKeyErrorStatus::OK; + } + case firebolt::rialto::ProtoMediaKeyErrorStatus::BAD_SESSION_ID: + { + return firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID; + } + case firebolt::rialto::ProtoMediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: + { + return firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED; + } + case firebolt::rialto::ProtoMediaKeyErrorStatus::BUFFER_TOO_SMALL: + { + return firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL; + } + case firebolt::rialto::ProtoMediaKeyErrorStatus::NOT_SUPPORTED: + { + return firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED; + } + case firebolt::rialto::ProtoMediaKeyErrorStatus::INVALID_STATE: + { + return firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE; + } + case firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL: + { + return firebolt::rialto::MediaKeyErrorStatus::FAIL; + } + } + return firebolt::rialto::MediaKeyErrorStatus::FAIL; +} + +firebolt::rialto::KeyStatus convertKeyStatus(const firebolt::rialto::KeyStatusesChangedEvent_KeyStatus &protoKeyStatus) +{ + switch (protoKeyStatus) + { + case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_USABLE: + { + return firebolt::rialto::KeyStatus::USABLE; + } + case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_EXPIRED: + { + return firebolt::rialto::KeyStatus::EXPIRED; + } + case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_OUTPUT_RESTRICTED: + { + return firebolt::rialto::KeyStatus::OUTPUT_RESTRICTED; + } + case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_PENDING: + { + return firebolt::rialto::KeyStatus::PENDING; + } + case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_INTERNAL_ERROR: + { + return firebolt::rialto::KeyStatus::INTERNAL_ERROR; + } + case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_RELEASED: + { + return firebolt::rialto::KeyStatus::RELEASED; + } + } + return firebolt::rialto::KeyStatus::INTERNAL_ERROR; +} + +const char *toString(const firebolt::rialto::MediaKeyErrorStatus &errorStatus) +{ + switch (errorStatus) + { + case firebolt::rialto::MediaKeyErrorStatus::OK: + { + return "OK"; + } + case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: + { + return "BAD_SESSION_ID"; + } + case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: + { + return "INTERFACE_NOT_IMPLEMENTED"; + } + case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: + { + return "BUFFER_TOO_SMALL"; + } + case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: + { + return "NOT_SUPPORTED"; + } + case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: + { + return "INVALID_STATE"; + } + case firebolt::rialto::MediaKeyErrorStatus::FAIL: + { + return "FAIL"; + } + } + return "UNKNOWN"; +} +} // namespace + +namespace firebolt::rialto::client +{ +std::shared_ptr IMediaKeysIpcFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys ipc factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr MediaKeysIpcFactory::createMediaKeysIpc(const std::string &keySystem) const +{ + std::unique_ptr mediaKeysIpc; + try + { + mediaKeysIpc = + std::make_unique(keySystem, IIpcClientAccessor::instance().getIpcClient(), + firebolt::rialto::common::IEventThreadFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys ipc, reason: %s", e.what()); + } + + return mediaKeysIpc; +} + +MediaKeysIpc::MediaKeysIpc(const std::string &keySystem, IIpcClient &ipcClient, + const std::shared_ptr &eventThreadFactory) + : IpcModule(ipcClient), m_eventThread(eventThreadFactory->createEventThread("rialto-media-keys-events")) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + if (!attachChannel()) + { + throw std::runtime_error("Failed attach to the ipc channel"); + } + + if (!createMediaKeys(keySystem)) + { + detachChannel(); + throw std::runtime_error("Could not create the media keys instance"); + } +} + +MediaKeysIpc::~MediaKeysIpc() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + destroyMediaKeys(); + + detachChannel(); + + m_eventThread.reset(); +} + +bool MediaKeysIpc::createRpcStubs(const std::shared_ptr &ipcChannel) +{ + m_mediaKeysStub = std::make_unique<::firebolt::rialto::MediaKeysModule_Stub>(ipcChannel.get()); + if (!m_mediaKeysStub) + { + return false; + } + return true; +} + +bool MediaKeysIpc::subscribeToEvents(const std::shared_ptr &ipcChannel) +{ + if (!ipcChannel) + { + return false; + } + + int eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaKeysIpc::onLicenseRequest, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaKeysIpc::onLicenseRenewal, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaKeysIpc::onKeyStatusesChanged, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + return true; +} + +bool MediaKeysIpc::createMediaKeys(const std::string &keySystem) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::CreateMediaKeysRequest request; + + request.set_key_system(keySystem); + + firebolt::rialto::CreateMediaKeysResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->createMediaKeys(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to create media keys due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + m_mediaKeysHandle = response.media_keys_handle(); + + return true; +} + +void MediaKeysIpc::destroyMediaKeys() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return; + } + + firebolt::rialto::DestroyMediaKeysRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + + firebolt::rialto::DestroyMediaKeysResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->destroyMediaKeys(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to destroy media keys due to '%s'", ipcController->ErrorText().c_str()); + } +} + +MediaKeyErrorStatus MediaKeysIpc::selectKeyId(int32_t keySessionId, const std::vector &keyId) +{ + RIALTO_CLIENT_LOG_ERROR("Not Implemented"); + return MediaKeyErrorStatus::FAIL; +} + +bool MediaKeysIpc::containsKey(int32_t keySessionId, const std::vector &keyId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::ContainsKeyRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + for (const auto &keyIdItem : keyId) + { + request.add_key_id(keyIdItem); + } + + firebolt::rialto::ContainsKeyResponse response; + // Default return value to false + response.set_contains_key(false); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->containsKey(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("containsKey failed due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return response.contains_key(); +} + +MediaKeyErrorStatus MediaKeysIpc::createKeySession(KeySessionType sessionType, std::weak_ptr client, + bool isLDL, int32_t &keySessionId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + CreateKeySessionRequest_KeySessionType protoSessionType = CreateKeySessionRequest_KeySessionType_UNKNOWN; + switch (sessionType) + { + case KeySessionType::TEMPORARY: + protoSessionType = CreateKeySessionRequest_KeySessionType_TEMPORARY; + break; + case KeySessionType::PERSISTENT_LICENCE: + protoSessionType = CreateKeySessionRequest_KeySessionType_PERSISTENT_LICENCE; + break; + case KeySessionType::PERSISTENT_RELEASE_MESSAGE: + protoSessionType = CreateKeySessionRequest_KeySessionType_PERSISTENT_RELEASE_MESSAGE; + break; + default: + RIALTO_CLIENT_LOG_WARN("Recieved unknown key session type"); + break; + } + + firebolt::rialto::CreateKeySessionRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_session_type(protoSessionType); + request.set_is_ldl(isLDL); + + firebolt::rialto::CreateKeySessionResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->createKeySession(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + MediaKeyErrorStatus status = + getMediaKeyErrorStatusFromResponse("createKeySession", ipcController, response.error_status()); + if (MediaKeyErrorStatus::OK == status) + { + keySessionId = response.key_session_id(); + m_mediaKeysIpcClient = client; + } + + return status; +} + +MediaKeyErrorStatus MediaKeysIpc::generateRequest(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + GenerateRequestRequest_InitDataType protoInitDataType = GenerateRequestRequest_InitDataType_UNKNOWN; + switch (initDataType) + { + case InitDataType::CENC: + protoInitDataType = GenerateRequestRequest_InitDataType_CENC; + break; + case InitDataType::KEY_IDS: + protoInitDataType = GenerateRequestRequest_InitDataType_KEY_IDS; + break; + case InitDataType::WEBM: + protoInitDataType = GenerateRequestRequest_InitDataType_WEBM; + break; + case InitDataType::DRMHEADER: + protoInitDataType = GenerateRequestRequest_InitDataType_DRMHEADER; + break; + default: + RIALTO_CLIENT_LOG_WARN("Recieved unknown init data type"); + break; + } + + firebolt::rialto::GenerateRequestRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + request.set_init_data_type(protoInitDataType); + + for (auto it = initData.begin(); it != initData.end(); it++) + { + request.add_init_data(*it); + } + + firebolt::rialto::GenerateRequestResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->generateRequest(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("generateRequest", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::loadSession(int32_t keySessionId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::LoadSessionRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + + firebolt::rialto::LoadSessionResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->loadSession(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("loadSession", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::updateSession(int32_t keySessionId, const std::vector &responseData) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::UpdateSessionRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + + for (auto it = responseData.begin(); it != responseData.end(); it++) + { + request.add_response_data(*it); + } + + firebolt::rialto::UpdateSessionResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->updateSession(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("updateSession", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::setDrmHeader(int32_t keySessionId, const std::vector &requestData) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::SetDrmHeaderRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + for (const auto &requestDataItem : requestData) + { + request.add_request_data(requestDataItem); + } + + firebolt::rialto::SetDrmHeaderResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->setDrmHeader(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("setDrmHeader", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::closeKeySession(int32_t keySessionId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + // Reset client + m_mediaKeysIpcClient.reset(); + + firebolt::rialto::CloseKeySessionRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + + firebolt::rialto::CloseKeySessionResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->closeKeySession(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("closeKeySession", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::removeKeySession(int32_t keySessionId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::RemoveKeySessionRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + + firebolt::rialto::RemoveKeySessionResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->removeKeySession(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("removeKeySession", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::deleteDrmStore() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::DeleteDrmStoreRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + + firebolt::rialto::DeleteDrmStoreResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->deleteDrmStore(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("deleteDrmStore", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::deleteKeyStore() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::DeleteKeyStoreRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + + firebolt::rialto::DeleteKeyStoreResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->deleteKeyStore(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("deleteKeyStore", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::getDrmStoreHash(std::vector &drmStoreHash) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::GetDrmStoreHashRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + + firebolt::rialto::GetDrmStoreHashResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->getDrmStoreHash(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + if (ProtoMediaKeyErrorStatus::OK == response.error_status()) + { + drmStoreHash = std::vector(response.drm_store_hash().begin(), response.drm_store_hash().end()); + } + + return getMediaKeyErrorStatusFromResponse("getDrmStoreHash", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::getKeyStoreHash(std::vector &keyStoreHash) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::GetKeyStoreHashRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + + firebolt::rialto::GetKeyStoreHashResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->getKeyStoreHash(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + if (ProtoMediaKeyErrorStatus::OK == response.error_status()) + { + keyStoreHash = std::vector(response.key_store_hash().begin(), response.key_store_hash().end()); + } + + return getMediaKeyErrorStatusFromResponse("getKeyStoreHash", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::getLdlSessionsLimit(uint32_t &ldlLimit) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::GetLdlSessionsLimitRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + + firebolt::rialto::GetLdlSessionsLimitResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->getLdlSessionsLimit(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + if (ProtoMediaKeyErrorStatus::OK == response.error_status()) + { + ldlLimit = response.ldl_limit(); + } + + return getMediaKeyErrorStatusFromResponse("getLdlSessionsLimit", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::getLastDrmError(int32_t keySessionId, uint32_t &errorCode) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::GetLastDrmErrorRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + + firebolt::rialto::GetLastDrmErrorResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->getLastDrmError(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + if (ProtoMediaKeyErrorStatus::OK == response.error_status()) + { + errorCode = response.error_code(); + } + + return getMediaKeyErrorStatusFromResponse("getLastDrmError", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::getDrmTime(uint64_t &drmTime) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::GetDrmTimeRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + + firebolt::rialto::GetDrmTimeResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->getDrmTime(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + if (ProtoMediaKeyErrorStatus::OK == response.error_status()) + { + drmTime = response.drm_time(); + } + + return getMediaKeyErrorStatusFromResponse("getDrmTime", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::GetCdmKeySessionIdRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + + firebolt::rialto::GetCdmKeySessionIdResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->getCdmKeySessionId(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + cdmKeySessionId = response.cdm_key_session_id(); + + return getMediaKeyErrorStatusFromResponse("getCdmKeySessionId", ipcController, response.error_status()); +} + +MediaKeyErrorStatus MediaKeysIpc::releaseKeySession(int32_t keySessionId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + // Reset client + m_mediaKeysIpcClient.reset(); + + firebolt::rialto::ReleaseKeySessionRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + request.set_key_session_id(keySessionId); + + firebolt::rialto::ReleaseKeySessionResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->releaseKeySession(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + return getMediaKeyErrorStatusFromResponse("releaseKeySession", ipcController, response.error_status()); +} + +void MediaKeysIpc::onLicenseRequest(const std::shared_ptr &event) +{ + std::shared_ptr mediaKeysIpcClient = m_mediaKeysIpcClient.lock(); + + /* Ignore event if not for this session or no client */ + if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient)) + { + std::vector messageVector = std::vector{event->license_request_message().begin(), + event->license_request_message().end()}; + mediaKeysIpcClient->onLicenseRequest(event->key_session_id(), messageVector, event->url()); + } +} + +void MediaKeysIpc::onLicenseRenewal(const std::shared_ptr &event) +{ + std::shared_ptr mediaKeysIpcClient = m_mediaKeysIpcClient.lock(); + + /* Ignore event if not for this session or no client */ + if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient)) + { + std::vector messageVector = std::vector{event->license_renewal_message().begin(), + event->license_renewal_message().end()}; + mediaKeysIpcClient->onLicenseRenewal(event->key_session_id(), messageVector); + } +} + +void MediaKeysIpc::onKeyStatusesChanged(const std::shared_ptr &event) +{ + std::shared_ptr mediaKeysIpcClient = m_mediaKeysIpcClient.lock(); + + /* Ignore event if not for this session or no client */ + if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient)) + { + KeyStatusVector keyStatuses; + for (auto it = event->key_statuses().begin(); it != event->key_statuses().end(); it++) + { + std::vector keyVector = std::vector{it->key_id().begin(), it->key_id().end()}; + KeyStatus keyStatus = convertKeyStatus(it->key_status()); + keyStatuses.push_back(std::make_pair(keyVector, keyStatus)); + } + mediaKeysIpcClient->onKeyStatusesChanged(event->key_session_id(), keyStatuses); + } +} + +MediaKeyErrorStatus +MediaKeysIpc::getMediaKeyErrorStatusFromResponse(const std::string methodName, + const std::shared_ptr &controller, + ProtoMediaKeyErrorStatus status) +{ + if (controller->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("%s failed due to '%s'", methodName.c_str(), controller->ErrorText().c_str()); + return MediaKeyErrorStatus::FAIL; + } + MediaKeyErrorStatus returnStatus = convertMediaKeyErrorStatus(status); + if (MediaKeyErrorStatus::OK != returnStatus) + { + RIALTO_CLIENT_LOG_ERROR("%s failed due to MediaKeyErrorStatus '%s'", methodName.c_str(), toString(returnStatus)); + return returnStatus; + } + + return returnStatus; +} + +MediaKeyErrorStatus MediaKeysIpc::getMetricSystemData(std::vector &buffer) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return MediaKeyErrorStatus::FAIL; + } + + firebolt::rialto::GetMetricSystemDataRequest request; + request.set_media_keys_handle(m_mediaKeysHandle); + + firebolt::rialto::GetMetricSystemDataResponse response; + // Default error status to FAIL + response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); + + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaKeysStub->getMetricSystemData(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + if (ProtoMediaKeyErrorStatus::OK == response.error_status()) + { + buffer = std::vector(response.buffer().begin(), response.buffer().end()); + } + + return getMediaKeyErrorStatusFromResponse("getMetricSystemData", ipcController, response.error_status()); +} + +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp b/middleware/rialto-client/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp new file mode 100644 index 000000000..e9f7b125a --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp @@ -0,0 +1,208 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaPipelineCapabilitiesIpc.h" +#include "RialtoClientLogging.h" +#include "RialtoCommonIpc.h" + +namespace firebolt::rialto::client +{ +std::shared_ptr IMediaPipelineCapabilitiesIpcFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media pipeline capabilities ipc factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr MediaPipelineCapabilitiesIpcFactory::createMediaPipelineCapabilitiesIpc() const +{ + std::unique_ptr mediaPipelineCapabilitiesIpc; + + try + { + mediaPipelineCapabilitiesIpc = + std::make_unique(IIpcClientAccessor::instance().getIpcClient()); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media pipeline capabilities ipc, reason: %s", e.what()); + } + + return mediaPipelineCapabilitiesIpc; +} + +MediaPipelineCapabilitiesIpc::MediaPipelineCapabilitiesIpc(IIpcClient &ipcClient) : IpcModule(ipcClient) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + if (!attachChannel()) + { + throw std::runtime_error("Failed attach to the ipc channel"); + } +} + +MediaPipelineCapabilitiesIpc::~MediaPipelineCapabilitiesIpc() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + detachChannel(); +} + +bool MediaPipelineCapabilitiesIpc::createRpcStubs(const std::shared_ptr &ipcChannel) +{ + m_mediaPipelineCapabilitiesStub = + std::make_unique<::firebolt::rialto::MediaPipelineCapabilitiesModule_Stub>(ipcChannel.get()); + if (!m_mediaPipelineCapabilitiesStub) + { + return false; + } + return true; +} + +std::vector MediaPipelineCapabilitiesIpc::getSupportedMimeTypes(MediaSourceType sourceType) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return {}; + } + + firebolt::rialto::GetSupportedMimeTypesRequest request; + request.set_media_type(convertProtoMediaSourceType(sourceType)); + + firebolt::rialto::GetSupportedMimeTypesResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineCapabilitiesStub->getSupportedMimeTypes(ipcController.get(), &request, &response, + blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get supported mime types due to '%s'", ipcController->ErrorText().c_str()); + return {}; + } + + return std::vector{response.mime_types().begin(), response.mime_types().end()}; +} + +bool MediaPipelineCapabilitiesIpc::isMimeTypeSupported(const std::string &mimeType) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::IsMimeTypeSupportedRequest request; + request.set_mime_type(mimeType); + + firebolt::rialto::IsMimeTypeSupportedResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineCapabilitiesStub->isMimeTypeSupported(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to check if mime type '%s' is supported due to '%s'", mimeType.c_str(), + ipcController->ErrorText().c_str()); + return false; + } + + return response.is_supported(); +} + +std::vector MediaPipelineCapabilitiesIpc::getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return {}; + } + + firebolt::rialto::GetSupportedPropertiesRequest request; + request.set_media_type(convertProtoMediaSourceType(mediaType)); + for (const std::string &property : propertyNames) + request.add_property_names(property); + + firebolt::rialto::GetSupportedPropertiesResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineCapabilitiesStub->getSupportedProperties(ipcController.get(), &request, &response, + blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed due to '%s'", ipcController->ErrorText().c_str()); + return std::vector{}; + } + + return std::vector{response.supported_properties().begin(), response.supported_properties().end()}; +} + +bool MediaPipelineCapabilitiesIpc::isVideoMaster(bool &isVideoMaster) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return {}; + } + + firebolt::rialto::IsVideoMasterRequest request; + firebolt::rialto::IsVideoMasterResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineCapabilitiesStub->isVideoMaster(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + isVideoMaster = response.is_video_master(); + + return true; +} +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/MediaPipelineIpc.cpp b/middleware/rialto-client/media/client/ipc/source/MediaPipelineIpc.cpp new file mode 100644 index 000000000..4ce1930e9 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/MediaPipelineIpc.cpp @@ -0,0 +1,1910 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "MediaPipelineIpc.h" +#include "RialtoClientLogging.h" +#include "RialtoCommonIpc.h" +#include "mediapipelinemodule.pb.h" +#include +#include + +namespace firebolt::rialto::client +{ +std::weak_ptr MediaPipelineIpcFactory::m_factory; + +std::shared_ptr IMediaPipelineIpcFactory::getFactory() +{ + std::shared_ptr factory = MediaPipelineIpcFactory::m_factory.lock(); + + if (!factory) + { + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media player ipc factory, reason: %s", e.what()); + } + + MediaPipelineIpcFactory::m_factory = factory; + } + + return factory; +} + +std::unique_ptr MediaPipelineIpcFactory::createMediaPipelineIpc( + IMediaPipelineIpcClient *client, const VideoRequirements &videoRequirements, std::weak_ptr ipcClientParam) +{ + std::unique_ptr mediaPipelineIpc; + try + { + std::shared_ptr ipcClient = ipcClientParam.lock(); + mediaPipelineIpc = + std::make_unique(client, videoRequirements, + ipcClient ? *ipcClient : IIpcClientAccessor::instance().getIpcClient(), + firebolt::rialto::common::IEventThreadFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media player ipc, reason: %s", e.what()); + } + + return mediaPipelineIpc; +} + +MediaPipelineIpc::MediaPipelineIpc(IMediaPipelineIpcClient *client, const VideoRequirements &videoRequirements, + IIpcClient &ipcClient, + const std::shared_ptr &eventThreadFactory) + : IpcModule(ipcClient), m_mediaPipelineIpcClient(client), + m_eventThread(eventThreadFactory->createEventThread("rialto-media-player-events")) +{ + if (!attachChannel()) + { + throw std::runtime_error("Failed attach to the ipc channel"); + } + + // create media player session + if (!createSession(videoRequirements)) + { + detachChannel(); + throw std::runtime_error("Could not create the media player session"); + } +} + +MediaPipelineIpc::~MediaPipelineIpc() +{ + // destroy media player session + destroySession(); + + // detach the Ipc channel + detachChannel(); + + // destroy the thread processing async notifications + m_eventThread.reset(); +} + +bool MediaPipelineIpc::createRpcStubs(const std::shared_ptr &ipcChannel) +{ + m_mediaPipelineStub = std::make_unique<::firebolt::rialto::MediaPipelineModule_Stub>(ipcChannel.get()); + if (!m_mediaPipelineStub) + { + return false; + } + return true; +} + +bool MediaPipelineIpc::subscribeToEvents(const std::shared_ptr &ipcChannel) +{ + if (!ipcChannel) + { + return false; + } + + int eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaPipelineIpc::onPlaybackStateUpdated, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaPipelineIpc::onPositionUpdated, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaPipelineIpc::onNetworkStateUpdated, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaPipelineIpc::onNeedMediaData, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaPipelineIpc::onQos, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaPipelineIpc::onBufferUnderflow, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaPipelineIpc::onPlaybackError, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&MediaPipelineIpc::onSourceFlushed, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + return true; +} + +bool MediaPipelineIpc::load(MediaType type, const std::string &mimeType, const std::string &url) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::LoadRequest request; + + request.set_session_id(m_sessionId); + request.set_type(convertLoadRequestMediaType(type)); + request.set_mime_type(mimeType); + request.set_url(url); + + firebolt::rialto::LoadResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->load(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to load media due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::attachSource(const std::unique_ptr &source, int32_t &sourceId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::AttachSourceRequest request; + + request.set_session_id(m_sessionId); + request.set_switch_source(false); + if (!buildAttachSourceRequest(request, source)) + { + RIALTO_CLIENT_LOG_ERROR("Failed to parse source"); + return false; + } + + firebolt::rialto::AttachSourceResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->attachSource(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to attach source due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + sourceId = response.source_id(); + + return true; +} + +bool MediaPipelineIpc::removeSource(int32_t sourceId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::RemoveSourceRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + + firebolt::rialto::RemoveSourceResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->removeSource(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to remove source due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::allSourcesAttached() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::AllSourcesAttachedRequest request; + request.set_session_id(m_sessionId); + + firebolt::rialto::AllSourcesAttachedResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->allSourcesAttached(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to notify about all sources attached due to '%s'", + ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetVideoWindowRequest request; + + request.set_session_id(m_sessionId); + request.set_x(x); + request.set_y(y); + request.set_width(width); + request.set_height(height); + + firebolt::rialto::SetVideoWindowResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setVideoWindow(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set the video window due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::play() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::PlayRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::PlayResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->play(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to play due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::pause() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::PauseRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::PauseResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->pause(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to pause due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::stop() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::StopRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::StopResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->stop(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to stop due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t requestId) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::HaveDataRequest request; + + request.set_session_id(m_sessionId); + request.set_status(convertHaveDataRequestMediaSourceStatus(status)); + request.set_num_frames(numFrames); + request.set_request_id(requestId); + + firebolt::rialto::HaveDataResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->haveData(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to stop due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::setPosition(int64_t position) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetPositionRequest request; + + request.set_session_id(m_sessionId); + request.set_position(position); + + firebolt::rialto::SetPositionResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setPosition(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set position due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getPosition(int64_t &position) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetPositionRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::GetPositionResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getPosition(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get position due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + position = response.position(); + return true; +} + +bool MediaPipelineIpc::setImmediateOutput(int32_t sourceId, bool immediateOutput) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetImmediateOutputRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + request.set_immediate_output(immediateOutput); + + firebolt::rialto::SetImmediateOutputResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setImmediateOutput(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set immediate-output due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getImmediateOutput(int32_t sourceId, bool &immediateOutput) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetImmediateOutputRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + + firebolt::rialto::GetImmediateOutputResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getImmediateOutput(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get immediate-output due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + else + { + immediateOutput = response.immediate_output(); + } + + return true; +} + +bool MediaPipelineIpc::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetStatsRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + + firebolt::rialto::GetStatsResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getStats(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get stats due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + renderedFrames = response.rendered_frames(); + droppedFrames = response.dropped_frames(); + return true; +} + +bool MediaPipelineIpc::setPlaybackRate(double rate) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetPlaybackRateRequest request; + + request.set_session_id(m_sessionId); + request.set_rate(rate); + + firebolt::rialto::SetPlaybackRateResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setPlaybackRate(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set playback rate due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::renderFrame() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::RenderFrameRequest request; + request.set_session_id(m_sessionId); + + firebolt::rialto::RenderFrameResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->renderFrame(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to render frame due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetVolumeRequest request; + + request.set_session_id(m_sessionId); + request.set_volume(targetVolume); + request.set_volume_duration(volumeDuration); + request.set_ease_type(convertEaseType(easeType)); + + firebolt::rialto::SetVolumeResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setVolume(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set volume due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getVolume(double &volume) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetVolumeRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::GetVolumeResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getVolume(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get volume due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + volume = response.volume(); + + return true; +} + +bool MediaPipelineIpc::setMute(int32_t sourceId, bool mute) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetMuteRequest request; + + request.set_session_id(m_sessionId); + request.set_mute(mute); + request.set_source_id(sourceId); + + firebolt::rialto::SetMuteResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setMute(ipcController.get(), &request, &response, blockingClosure.get()); + + // waiting for call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set mute due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getMute(std::int32_t sourceId, bool &mute) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetMuteRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + + firebolt::rialto::GetMuteResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getMute(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get mute due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + mute = response.mute(); + + return true; +} + +bool MediaPipelineIpc::setTextTrackIdentifier(const std::string &textTrackIdentifier) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetTextTrackIdentifierRequest request; + + request.set_session_id(m_sessionId); + request.set_text_track_identifier(textTrackIdentifier); + + firebolt::rialto::SetTextTrackIdentifierResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setTextTrackIdentifier(ipcController.get(), &request, &response, blockingClosure.get()); + + // waiting for call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set text track identifier due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getTextTrackIdentifier(std::string &textTrackIdentifier) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetTextTrackIdentifierRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::GetTextTrackIdentifierResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getTextTrackIdentifier(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get mute due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + textTrackIdentifier = response.text_track_identifier(); + + return true; +} + +bool MediaPipelineIpc::setLowLatency(bool lowLatency) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetLowLatencyRequest request; + + request.set_session_id(m_sessionId); + request.set_low_latency(lowLatency); + + firebolt::rialto::SetLowLatencyResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setLowLatency(ipcController.get(), &request, &response, blockingClosure.get()); + // waiting for call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set low-latency due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::setSync(bool sync) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetSyncRequest request; + + request.set_session_id(m_sessionId); + request.set_sync(sync); + + firebolt::rialto::SetSyncResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setSync(ipcController.get(), &request, &response, blockingClosure.get()); + + // waiting for call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set sync due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getSync(bool &sync) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetSyncRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::GetSyncResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getSync(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get sync due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + sync = response.sync(); + + return true; +} + +bool MediaPipelineIpc::setSyncOff(bool syncOff) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetSyncOffRequest request; + + request.set_session_id(m_sessionId); + request.set_sync_off(syncOff); + + firebolt::rialto::SetSyncOffResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setSyncOff(ipcController.get(), &request, &response, blockingClosure.get()); + + // waiting for call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set sync-off due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetStreamSyncModeRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + request.set_stream_sync_mode(streamSyncMode); + + firebolt::rialto::SetStreamSyncModeResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setStreamSyncMode(ipcController.get(), &request, &response, blockingClosure.get()); + + // waiting for call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set stream-sync-mode due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getStreamSyncMode(int32_t &streamSyncMode) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetStreamSyncModeRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::GetStreamSyncModeResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getStreamSyncMode(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get stream-sync-mode due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + streamSyncMode = response.stream_sync_mode(); + + return true; +} + +bool MediaPipelineIpc::flush(int32_t sourceId, bool resetTime, bool &async) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::FlushRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + request.set_reset_time(resetTime); + + firebolt::rialto::FlushResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->flush(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to flush due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + // Async is true by default + async = response.has_async() ? response.async() : true; + + return true; +} + +bool MediaPipelineIpc::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetSourcePositionRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + request.set_position(position); + request.set_reset_time(resetTime); + request.set_applied_rate(appliedRate); + request.set_stop_position(stopPosition); + + firebolt::rialto::SetSourcePositionResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setSourcePosition(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set source position due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::setSubtitleOffset(int32_t sourceId, int64_t position) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetSubtitleOffsetRequest request; + + request.set_session_id(m_sessionId); + request.set_source_id(sourceId); + request.set_position(position); + + firebolt::rialto::SetSubtitleOffsetResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setSubtitleOffset(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set subtitle offset due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::ProcessAudioGapRequest request; + + request.set_session_id(m_sessionId); + request.set_position(position); + request.set_duration(duration); + request.set_discontinuity_gap(discontinuityGap); + request.set_audio_aac(audioAac); + + firebolt::rialto::ProcessAudioGapResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->processAudioGap(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to process audio gap due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::setBufferingLimit(uint32_t limitBufferingMs) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetBufferingLimitRequest request; + + request.set_session_id(m_sessionId); + request.set_limit_buffering_ms(limitBufferingMs); + + firebolt::rialto::SetBufferingLimitResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setBufferingLimit(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set buffering limit due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getBufferingLimit(uint32_t &limitBufferingMs) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetBufferingLimitRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::GetBufferingLimitResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getBufferingLimit(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get buffering limit due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + limitBufferingMs = response.limit_buffering_ms(); + + return true; +} + +bool MediaPipelineIpc::setUseBuffering(bool useBuffering) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::SetUseBufferingRequest request; + + request.set_session_id(m_sessionId); + request.set_use_buffering(useBuffering); + + firebolt::rialto::SetUseBufferingResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->setUseBuffering(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to set use buffering due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool MediaPipelineIpc::getUseBuffering(bool &useBuffering) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::GetUseBufferingRequest request; + + request.set_session_id(m_sessionId); + + firebolt::rialto::GetUseBufferingResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->getUseBuffering(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to get use buffering due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + useBuffering = response.use_buffering(); + + return true; +} + +bool MediaPipelineIpc::switchSource(const std::unique_ptr &source) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::AttachSourceRequest request; + + request.set_session_id(m_sessionId); + request.set_switch_source(true); + if (!buildAttachSourceRequest(request, source)) + { + RIALTO_CLIENT_LOG_ERROR("Failed to parse source"); + return false; + } + + firebolt::rialto::AttachSourceResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->attachSource(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to attach source due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +void MediaPipelineIpc::onPlaybackStateUpdated(const std::shared_ptr &event) +{ + /* Ignore event if not for this session */ + if (event->session_id() == m_sessionId) + { + PlaybackState playbackState = PlaybackState::UNKNOWN; + switch (event->state()) + { + case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_IDLE: + playbackState = PlaybackState::IDLE; + break; + case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PLAYING: + playbackState = PlaybackState::PLAYING; + break; + case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PAUSED: + playbackState = PlaybackState::PAUSED; + break; + case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEKING: + playbackState = PlaybackState::SEEKING; + break; + case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEK_DONE: + playbackState = PlaybackState::SEEK_DONE; + break; + case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_STOPPED: + playbackState = PlaybackState::STOPPED; + break; + case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_END_OF_STREAM: + playbackState = PlaybackState::END_OF_STREAM; + break; + case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_FAILURE: + playbackState = PlaybackState::FAILURE; + break; + default: + RIALTO_CLIENT_LOG_WARN("Received unknown playback state"); + break; + } + + m_mediaPipelineIpcClient->notifyPlaybackState(playbackState); + } +} + +void MediaPipelineIpc::onPositionUpdated(const std::shared_ptr &event) +{ + // Ignore event if not for this session + if (event->session_id() == m_sessionId) + { + int64_t position = event->position(); + m_mediaPipelineIpcClient->notifyPosition(position); + } +} + +void MediaPipelineIpc::onNetworkStateUpdated(const std::shared_ptr &event) +{ + // Ignore event if not for this session + if (event->session_id() == m_sessionId) + { + NetworkState networkState = NetworkState::UNKNOWN; + switch (event->state()) + { + case firebolt::rialto::NetworkStateChangeEvent_NetworkState_IDLE: + networkState = NetworkState::IDLE; + break; + case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING: + networkState = NetworkState::BUFFERING; + break; + case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING_PROGRESS: + networkState = NetworkState::BUFFERING_PROGRESS; + break; + case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERED: + networkState = NetworkState::BUFFERED; + break; + case firebolt::rialto::NetworkStateChangeEvent_NetworkState_STALLED: + networkState = NetworkState::STALLED; + break; + case firebolt::rialto::NetworkStateChangeEvent_NetworkState_FORMAT_ERROR: + networkState = NetworkState::FORMAT_ERROR; + break; + case firebolt::rialto::NetworkStateChangeEvent_NetworkState_NETWORK_ERROR: + networkState = NetworkState::NETWORK_ERROR; + break; + default: + RIALTO_CLIENT_LOG_WARN("Received unknown network state"); + break; + } + + m_mediaPipelineIpcClient->notifyNetworkState(networkState); + } +} + +void MediaPipelineIpc::onNeedMediaData(const std::shared_ptr &event) +{ + // Ignore event if not for this session + if (event->session_id() == m_sessionId) + { + std::shared_ptr shmInfo; + if (event->has_shm_info()) + { + shmInfo = std::make_shared(); + shmInfo->maxMetadataBytes = event->shm_info().max_metadata_bytes(); + shmInfo->metadataOffset = event->shm_info().metadata_offset(); + shmInfo->mediaDataOffset = event->shm_info().media_data_offset(); + shmInfo->maxMediaBytes = event->shm_info().max_media_bytes(); + } + m_mediaPipelineIpcClient->notifyNeedMediaData(event->source_id(), event->frame_count(), event->request_id(), + shmInfo); + } +} + +void MediaPipelineIpc::onQos(const std::shared_ptr &event) +{ + // Ignore event if not for this session + if (event->session_id() == m_sessionId) + { + QosInfo qosInfo = {event->qos_info().processed(), event->qos_info().dropped()}; + m_mediaPipelineIpcClient->notifyQos(event->source_id(), qosInfo); + } +} + +void MediaPipelineIpc::onBufferUnderflow(const std::shared_ptr &event) +{ + // Ignore event if not for this session + if (event->session_id() == m_sessionId) + { + m_mediaPipelineIpcClient->notifyBufferUnderflow(event->source_id()); + } +} + +void MediaPipelineIpc::onPlaybackError(const std::shared_ptr &event) +{ + // Ignore event if not for this session + if (event->session_id() == m_sessionId) + { + PlaybackError playbackError = PlaybackError::UNKNOWN; + switch (event->error()) + { + case firebolt::rialto::PlaybackErrorEvent_PlaybackError_DECRYPTION: + playbackError = PlaybackError::DECRYPTION; + break; + default: + RIALTO_CLIENT_LOG_WARN("Received unknown playback error"); + break; + } + + m_mediaPipelineIpcClient->notifyPlaybackError(event->source_id(), playbackError); + } +} + +void MediaPipelineIpc::onSourceFlushed(const std::shared_ptr &event) +{ + // Ignore event if not for this session + if (event->session_id() == m_sessionId) + { + m_mediaPipelineIpcClient->notifySourceFlushed(event->source_id()); + } +} + +bool MediaPipelineIpc::createSession(const VideoRequirements &videoRequirements) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::CreateSessionRequest request; + + request.set_max_width(videoRequirements.maxWidth); + request.set_max_height(videoRequirements.maxHeight); + + firebolt::rialto::CreateSessionResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->createSession(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to create session due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + m_sessionId = response.session_id(); + + return true; +} + +void MediaPipelineIpc::destroySession() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return; + } + + firebolt::rialto::DestroySessionRequest request; + request.set_session_id(m_sessionId); + + firebolt::rialto::DestroySessionResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_mediaPipelineStub->destroySession(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("failed to destroy session due to '%s'", ipcController->ErrorText().c_str()); + } +} + +firebolt::rialto::LoadRequest_MediaType MediaPipelineIpc::convertLoadRequestMediaType(MediaType mediaType) const +{ + firebolt::rialto::LoadRequest_MediaType protoMediaType = firebolt::rialto::LoadRequest_MediaType_UNKNOWN; + switch (mediaType) + { + case MediaType::MSE: + protoMediaType = firebolt::rialto::LoadRequest_MediaType_MSE; + break; + default: + break; + } + + return protoMediaType; +} + +firebolt::rialto::HaveDataRequest_MediaSourceStatus +MediaPipelineIpc::convertHaveDataRequestMediaSourceStatus(MediaSourceStatus status) const +{ + firebolt::rialto::HaveDataRequest_MediaSourceStatus protoMediaSourceStatus = + firebolt::rialto::HaveDataRequest_MediaSourceStatus_UNKNOWN; + switch (status) + { + case MediaSourceStatus::OK: + protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_OK; + break; + case MediaSourceStatus::EOS: + protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_EOS; + break; + case MediaSourceStatus::ERROR: + protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_ERROR; + break; + case MediaSourceStatus::CODEC_CHANGED: + protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_CODEC_CHANGED; + break; + case MediaSourceStatus::NO_AVAILABLE_SAMPLES: + protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_NO_AVAILABLE_SAMPLES; + break; + default: + break; + } + + return protoMediaSourceStatus; +} + +firebolt::rialto::AttachSourceRequest_ConfigType +MediaPipelineIpc::convertConfigType(const firebolt::rialto::SourceConfigType &configType) const +{ + switch (configType) + { + case firebolt::rialto::SourceConfigType::UNKNOWN: + { + return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_UNKNOWN; + } + case firebolt::rialto::SourceConfigType::AUDIO: + { + return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_AUDIO; + } + case firebolt::rialto::SourceConfigType::VIDEO: + { + return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO; + } + case firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION: + { + return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO_DOLBY_VISION; + } + case firebolt::rialto::SourceConfigType::SUBTITLE: + { + return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_SUBTITLE; + } + } + return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_UNKNOWN; +} + +firebolt::rialto::SetVolumeRequest_EaseType MediaPipelineIpc::convertEaseType(const firebolt::rialto::EaseType &easeType) const +{ + switch (easeType) + { + case firebolt::rialto::EaseType::EASE_LINEAR: + { + return firebolt::rialto::SetVolumeRequest_EaseType_EASE_LINEAR; + } + case firebolt::rialto::EaseType::EASE_IN_CUBIC: + { + return firebolt::rialto::SetVolumeRequest_EaseType_EASE_IN_CUBIC; + } + case firebolt::rialto::EaseType::EASE_OUT_CUBIC: + { + return firebolt::rialto::SetVolumeRequest_EaseType_EASE_OUT_CUBIC; + } + } + return firebolt::rialto::SetVolumeRequest_EaseType_EASE_LINEAR; +} + +firebolt::rialto::AttachSourceRequest_SegmentAlignment +MediaPipelineIpc::convertSegmentAlignment(const firebolt::rialto::SegmentAlignment &alignment) const +{ + switch (alignment) + { + case firebolt::rialto::SegmentAlignment::UNDEFINED: + { + return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_UNDEFINED; + } + case firebolt::rialto::SegmentAlignment::NAL: + { + return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_NAL; + } + case firebolt::rialto::SegmentAlignment::AU: + { + return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_AU; + } + } + return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_UNDEFINED; +} + +firebolt::rialto::AttachSourceRequest_StreamFormat +MediaPipelineIpc::convertStreamFormat(const firebolt::rialto::StreamFormat &streamFormat) const +{ + switch (streamFormat) + { + case firebolt::rialto::StreamFormat::UNDEFINED: + { + return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_UNDEFINED; + } + case firebolt::rialto::StreamFormat::RAW: + { + return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_RAW; + } + case firebolt::rialto::StreamFormat::AVC: + { + return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_AVC; + } + case firebolt::rialto::StreamFormat::BYTE_STREAM: + { + return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_BYTE_STREAM; + } + case firebolt::rialto::StreamFormat::HVC1: + { + return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HVC1; + } + case firebolt::rialto::StreamFormat::HEV1: + { + return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HEV1; + } + } + return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_UNDEFINED; +} + +firebolt::rialto::AttachSourceRequest_CodecData_Type +MediaPipelineIpc::convertCodecDataType(const firebolt::rialto::CodecDataType &codecDataType) const +{ + if (firebolt::rialto::CodecDataType::STRING == codecDataType) + { + return firebolt::rialto::AttachSourceRequest_CodecData_Type_STRING; + } + return firebolt::rialto::AttachSourceRequest_CodecData_Type_BUFFER; +} + +firebolt::rialto::AttachSourceRequest_AudioConfig_Format +MediaPipelineIpc::convertFormat(const firebolt::rialto::Format &format) const +{ + static const std::unordered_map + kFormatConversionMap{ + {firebolt::rialto::Format::S8, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S8}, + {firebolt::rialto::Format::U8, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U8}, + {firebolt::rialto::Format::S16LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16LE}, + {firebolt::rialto::Format::S16BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16BE}, + {firebolt::rialto::Format::U16LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16LE}, + {firebolt::rialto::Format::U16BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16BE}, + {firebolt::rialto::Format::S24_32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32LE}, + {firebolt::rialto::Format::S24_32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32BE}, + {firebolt::rialto::Format::U24_32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32LE}, + {firebolt::rialto::Format::U24_32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32BE}, + {firebolt::rialto::Format::S32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32LE}, + {firebolt::rialto::Format::S32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32BE}, + {firebolt::rialto::Format::U32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32LE}, + {firebolt::rialto::Format::U32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32BE}, + {firebolt::rialto::Format::S24LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24LE}, + {firebolt::rialto::Format::S24BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24BE}, + {firebolt::rialto::Format::U24LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24LE}, + {firebolt::rialto::Format::U24BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24BE}, + {firebolt::rialto::Format::S20LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20LE}, + {firebolt::rialto::Format::S20BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20BE}, + {firebolt::rialto::Format::U20LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20LE}, + {firebolt::rialto::Format::U20BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20BE}, + {firebolt::rialto::Format::S18LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18LE}, + {firebolt::rialto::Format::S18BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18BE}, + {firebolt::rialto::Format::U18LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18LE}, + {firebolt::rialto::Format::U18BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18BE}, + {firebolt::rialto::Format::F32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32LE}, + {firebolt::rialto::Format::F32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32BE}, + {firebolt::rialto::Format::F64LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64LE}, + {firebolt::rialto::Format::F64BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64BE}}; + const auto kIt = kFormatConversionMap.find(format); + if (kFormatConversionMap.end() != kIt) + { + return kIt->second; + } + return firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S8; +} + +firebolt::rialto::AttachSourceRequest_AudioConfig_Layout +MediaPipelineIpc::convertLayout(const firebolt::rialto::Layout &layout) const +{ + static const std::unordered_map + kLayoutConversionMap{{firebolt::rialto::Layout::INTERLEAVED, + firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_INTERLEAVED}, + {firebolt::rialto::Layout::NON_INTERLEAVED, + firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_NON_INTERLEAVED}}; + const auto kIt = kLayoutConversionMap.find(layout); + if (kLayoutConversionMap.end() != kIt) + { + return kIt->second; + } + return firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_INTERLEAVED; +} + +bool MediaPipelineIpc::buildAttachSourceRequest(firebolt::rialto::AttachSourceRequest &request, + const std::unique_ptr &source) const +{ + SourceConfigType configType = source->getConfigType(); + request.set_config_type(convertConfigType(configType)); + request.set_mime_type(source->getMimeType()); + request.set_has_drm(source->getHasDrm()); + + if (configType == SourceConfigType::VIDEO_DOLBY_VISION || configType == SourceConfigType::VIDEO || + configType == SourceConfigType::AUDIO) + { + IMediaPipeline::MediaSourceAV *mediaSourceAV = dynamic_cast(source.get()); + if (!mediaSourceAV) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get the audio video source"); + return false; + } + request.set_segment_alignment(convertSegmentAlignment(mediaSourceAV->getSegmentAlignment())); + + if (mediaSourceAV->getCodecData()) + { + request.mutable_codec_data()->set_data(mediaSourceAV->getCodecData()->data.data(), + mediaSourceAV->getCodecData()->data.size()); + request.mutable_codec_data()->set_type(convertCodecDataType(mediaSourceAV->getCodecData()->type)); + } + request.set_stream_format(convertStreamFormat(mediaSourceAV->getStreamFormat())); + + if (configType == SourceConfigType::VIDEO_DOLBY_VISION) + { + IMediaPipeline::MediaSourceVideoDolbyVision *mediaSourceDolby = + dynamic_cast(source.get()); + if (!mediaSourceDolby) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get the video dolby vision media source"); + return false; + } + request.set_width(mediaSourceDolby->getWidth()); + request.set_height(mediaSourceDolby->getHeight()); + request.set_dolby_vision_profile(mediaSourceDolby->getDolbyVisionProfile()); + } + else if (configType == SourceConfigType::VIDEO) + { + IMediaPipeline::MediaSourceVideo *mediaSourceVideo = + dynamic_cast(source.get()); + if (!mediaSourceVideo) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get the video media source"); + return false; + } + request.set_width(mediaSourceVideo->getWidth()); + request.set_height(mediaSourceVideo->getHeight()); + } + else if (configType == SourceConfigType::AUDIO) + { + IMediaPipeline::MediaSourceAudio *mediaSourceAudio = + dynamic_cast(source.get()); + if (!mediaSourceAudio) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get the audio media source"); + return false; + } + request.mutable_audio_config()->set_number_of_channels(mediaSourceAudio->getAudioConfig().numberOfChannels); + request.mutable_audio_config()->set_sample_rate(mediaSourceAudio->getAudioConfig().sampleRate); + if (!mediaSourceAudio->getAudioConfig().codecSpecificConfig.empty()) + { + request.mutable_audio_config() + ->set_codec_specific_config(mediaSourceAudio->getAudioConfig().codecSpecificConfig.data(), + mediaSourceAudio->getAudioConfig().codecSpecificConfig.size()); + } + if (mediaSourceAudio->getAudioConfig().format.has_value()) + { + request.mutable_audio_config()->set_format( + convertFormat(mediaSourceAudio->getAudioConfig().format.value())); + } + if (mediaSourceAudio->getAudioConfig().layout.has_value()) + { + request.mutable_audio_config()->set_layout( + convertLayout(mediaSourceAudio->getAudioConfig().layout.value())); + } + if (mediaSourceAudio->getAudioConfig().channelMask.has_value()) + { + request.mutable_audio_config()->set_channel_mask(mediaSourceAudio->getAudioConfig().channelMask.value()); + } + for (auto &header : mediaSourceAudio->getAudioConfig().streamHeader) + { + request.mutable_audio_config()->add_stream_header(header.data(), header.size()); + } + if (mediaSourceAudio->getAudioConfig().framed.has_value()) + { + request.mutable_audio_config()->set_framed(mediaSourceAudio->getAudioConfig().framed.value()); + } + } + } + else if (configType == SourceConfigType::SUBTITLE) + { + IMediaPipeline::MediaSourceSubtitle *mediaSourceSubtitle = + dynamic_cast(source.get()); + if (!mediaSourceSubtitle) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get the subtitle source"); + return false; + } + request.set_text_track_identifier(mediaSourceSubtitle->getTextTrackIdentifier()); + } + else + { + RIALTO_CLIENT_LOG_ERROR("Unknown source type"); + return false; + } + return true; +} +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/RialtoCommonIpc.cpp b/middleware/rialto-client/media/client/ipc/source/RialtoCommonIpc.cpp new file mode 100644 index 000000000..911b474d2 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/RialtoCommonIpc.cpp @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "RialtoCommonIpc.h" + +namespace firebolt::rialto::client +{ +firebolt::rialto::ProtoMediaSourceType convertProtoMediaSourceType(MediaSourceType mediaSourceType) +{ + firebolt::rialto::ProtoMediaSourceType protoMediaSourceType = firebolt::rialto::ProtoMediaSourceType::UNKNOWN; + switch (mediaSourceType) + { + case MediaSourceType::AUDIO: + protoMediaSourceType = firebolt::rialto::ProtoMediaSourceType::AUDIO; + break; + case MediaSourceType::VIDEO: + protoMediaSourceType = firebolt::rialto::ProtoMediaSourceType::VIDEO; + break; + case MediaSourceType::SUBTITLE: + protoMediaSourceType = firebolt::rialto::ProtoMediaSourceType::SUBTITLE; + break; + default: + break; + } + + return protoMediaSourceType; +} +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/WebAudioPlayerIpc.cpp b/middleware/rialto-client/media/client/ipc/source/WebAudioPlayerIpc.cpp new file mode 100644 index 000000000..ad1fa7903 --- /dev/null +++ b/middleware/rialto-client/media/client/ipc/source/WebAudioPlayerIpc.cpp @@ -0,0 +1,513 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "WebAudioPlayerIpc.h" +#include "RialtoClientLogging.h" +#include "RialtoCommonIpc.h" +#include "webaudioplayermodule.pb.h" +#include + +namespace firebolt::rialto::client +{ + +std::shared_ptr IWebAudioPlayerIpcFactory::getFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player ipc factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr +WebAudioPlayerIpcFactory::createWebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config, + std::weak_ptr ipcClientParam) +{ + std::unique_ptr webAudioPlayerIpc; + try + { + std::shared_ptr ipcClient = ipcClientParam.lock(); + webAudioPlayerIpc = + std::make_unique(client, audioMimeType, priority, config, + ipcClient ? *ipcClient : IIpcClientAccessor::instance().getIpcClient(), + firebolt::rialto::common::IEventThreadFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player ipc, reason: %s", e.what()); + } + + return webAudioPlayerIpc; +} + +WebAudioPlayerIpc::WebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config, + IIpcClient &ipcClient, + const std::shared_ptr &eventThreadFactory) + : IpcModule(ipcClient), m_webAudioPlayerIpcClient(client), + m_eventThread(eventThreadFactory->createEventThread("rialto-web-audio-player-events")), m_webAudioPlayerHandle(-1) +{ + if (!attachChannel()) + { + throw std::runtime_error("Failed attach to the ipc channel"); + } + + if (!createWebAudioPlayer(audioMimeType, priority, config)) + { + detachChannel(); + throw std::runtime_error("Could not create the web audio player"); + } +} + +WebAudioPlayerIpc::~WebAudioPlayerIpc() +{ + // destroy web audio player session + destroyWebAudioPlayer(); + + // detach the Ipc channel + detachChannel(); + + // destroy the thread processing async notifications + m_eventThread.reset(); +} + +bool WebAudioPlayerIpc::createRpcStubs(const std::shared_ptr &ipcChannel) +{ + m_webAudioPlayerStub = std::make_unique<::firebolt::rialto::WebAudioPlayerModule_Stub>(ipcChannel.get()); + if (!m_webAudioPlayerStub) + { + return false; + } + return true; +} + +bool WebAudioPlayerIpc::subscribeToEvents(const std::shared_ptr &ipcChannel) +{ + if (!ipcChannel) + { + return false; + } + + int eventTag = ipcChannel->subscribe( + [this](const std::shared_ptr &event) + { m_eventThread->add(&WebAudioPlayerIpc::onPlaybackStateUpdated, this, event); }); + if (eventTag < 0) + return false; + m_eventTags.push_back(eventTag); + + return true; +} + +void WebAudioPlayerIpc::onPlaybackStateUpdated(const std::shared_ptr &event) +{ + if (event->web_audio_player_handle() == m_webAudioPlayerHandle) + { + firebolt::rialto::WebAudioPlayerState playerState = firebolt::rialto::WebAudioPlayerState::UNKNOWN; + switch (event->state()) + { + case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_UNKNOWN: + playerState = firebolt::rialto::WebAudioPlayerState::UNKNOWN; + break; + case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_IDLE: + playerState = firebolt::rialto::WebAudioPlayerState::IDLE; + break; + case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_PLAYING: + playerState = firebolt::rialto::WebAudioPlayerState::PLAYING; + break; + case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_PAUSED: + playerState = firebolt::rialto::WebAudioPlayerState::PAUSED; + break; + case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_END_OF_STREAM: + playerState = firebolt::rialto::WebAudioPlayerState::END_OF_STREAM; + break; + case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_FAILURE: + playerState = firebolt::rialto::WebAudioPlayerState::FAILURE; + break; + default: + RIALTO_CLIENT_LOG_WARN("Recieved unknown web audio player state"); + break; + } + + m_webAudioPlayerIpcClient->notifyState(playerState); + } +} + +bool WebAudioPlayerIpc::play() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioPlayRequest request; + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioPlayResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->play(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to play due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool WebAudioPlayerIpc::pause() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioPauseRequest request; + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioPauseResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->pause(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to pause due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool WebAudioPlayerIpc::setEos() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioSetEosRequest request; + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioSetEosResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->setEos(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to set eos due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool WebAudioPlayerIpc::getBufferAvailable(uint32_t &availableFrames, + const std::shared_ptr &webAudioShmInfo) +{ + if (!webAudioShmInfo) + { + RIALTO_CLIENT_LOG_ERROR("webAudioShmInfo parameter can't be null!"); + return false; + } + + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioGetBufferAvailableRequest request; + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioGetBufferAvailableResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->getBufferAvailable(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get buffer available due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + availableFrames = response.available_frames(); + webAudioShmInfo->offsetMain = response.shm_info().offset_main(); + webAudioShmInfo->lengthMain = response.shm_info().length_main(); + webAudioShmInfo->offsetWrap = response.shm_info().offset_wrap(); + webAudioShmInfo->lengthWrap = response.shm_info().length_wrap(); + + return true; +} + +bool WebAudioPlayerIpc::getBufferDelay(uint32_t &delayFrames) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioGetBufferDelayRequest request; + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioGetBufferDelayResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->getBufferDelay(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get buffer delay source due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + delayFrames = response.delay_frames(); + + return true; +} + +bool WebAudioPlayerIpc::writeBuffer(const uint32_t numberOfFrames) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioWriteBufferRequest request; + + request.set_number_of_frames(numberOfFrames); + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioWriteBufferResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->writeBuffer(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to write to the buffer due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool WebAudioPlayerIpc::getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioGetDeviceInfoRequest request; + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioGetDeviceInfoResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->getDeviceInfo(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get device info source due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + preferredFrames = response.preferred_frames(); + maximumFrames = response.maximum_frames(); + supportDeferredPlay = response.support_deferred_play(); + + return true; +} + +bool WebAudioPlayerIpc::setVolume(double volume) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioSetVolumeRequest request; + request.set_volume(volume); + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioSetVolumeResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->setVolume(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to set volume due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + return true; +} + +bool WebAudioPlayerIpc::getVolume(double &volume) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::WebAudioGetVolumeRequest request; + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::WebAudioGetVolumeResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->getVolume(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get volume due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + volume = response.volume(); + return true; +} + +bool WebAudioPlayerIpc::createWebAudioPlayer(const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr webAudioConfig) +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return false; + } + + firebolt::rialto::CreateWebAudioPlayerRequest request; + request.set_audio_mime_type(audioMimeType); + request.set_priority(priority); + std::shared_ptr kConfig = webAudioConfig.lock(); + if (kConfig) + { + ::firebolt::rialto::CreateWebAudioPlayerRequest_WebAudioPcmConfig pcm_config; + pcm_config.set_rate(kConfig->pcm.rate); + pcm_config.set_channels(kConfig->pcm.channels); + pcm_config.set_sample_size(kConfig->pcm.sampleSize); + pcm_config.set_is_big_endian(kConfig->pcm.isBigEndian); + pcm_config.set_is_signed(kConfig->pcm.isSigned); + pcm_config.set_is_float(kConfig->pcm.isFloat); + request.mutable_config()->mutable_pcm()->CopyFrom(pcm_config); + } + + firebolt::rialto::CreateWebAudioPlayerResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->createWebAudioPlayer(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create web audio player due to '%s'", ipcController->ErrorText().c_str()); + return false; + } + + m_webAudioPlayerHandle = response.web_audio_player_handle(); + + return true; +} + +void WebAudioPlayerIpc::destroyWebAudioPlayer() +{ + if (!reattachChannelIfRequired()) + { + RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); + return; + } + + firebolt::rialto::DestroyWebAudioPlayerRequest request; + request.set_web_audio_player_handle(m_webAudioPlayerHandle); + + firebolt::rialto::DestroyWebAudioPlayerResponse response; + auto ipcController = m_ipc.createRpcController(); + auto blockingClosure = m_ipc.createBlockingClosure(); + m_webAudioPlayerStub->destroyWebAudioPlayer(ipcController.get(), &request, &response, blockingClosure.get()); + + // wait for the call to complete + blockingClosure->wait(); + + // check the result + if (ipcController->Failed()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to destroy web audio player due to '%s'", ipcController->ErrorText().c_str()); + } +} + +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/CMakeLists.txt b/middleware/rialto-client/media/client/main/CMakeLists.txt new file mode 100644 index 000000000..c0da47d75 --- /dev/null +++ b/middleware/rialto-client/media/client/main/CMakeLists.txt @@ -0,0 +1,95 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set(CMAKE_C_STANDARD 99) +set(CMAKE_CXX_STANDARD 17) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCCompilerFlag ) +include( CheckCXXCompilerFlag ) + +set(LIB_RIALTO_CLIENT_SOURCES + source/AttachedSources.cpp + source/ClientController.cpp + source/ClientLogControl.cpp + source/Control.cpp + source/KeyIdMap.cpp + source/MediaKeys.cpp + source/MediaKeysCapabilities.cpp + source/MediaPipeline.cpp + source/MediaPipelineCapabilities.cpp + source/SharedMemoryHandle.cpp + source/WebAudioPlayer.cpp + ) + +add_library( RialtoClient + SHARED + ${LIB_RIALTO_CLIENT_SOURCES} + + ) + +target_compile_options( + RialtoClient + + PUBLIC + -DRIALTO_SERVER_SUPPORTS_DECRYPTION=1 + ) + +target_include_directories( + RialtoClient + + PUBLIC + ${PROJECT_SOURCE_DIR}/include + $ + $ + + PRIVATE + $ + $ + $ + $ + $ + + ) + +set_target_properties( + RialtoClient + PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" + SOVERSION ${PROJECT_VERSION_MAJOR} + VERSION ${CMAKE_PROJECT_VERSION} + ) + +target_link_libraries( + RialtoClient + + PRIVATE + RialtoPlayerCommon + RialtoClientIpcImpl + RialtoCommon + RialtoEthanLog + + Threads::Threads + + ) + +include( GNUInstallDirs ) + +install( TARGETS RialtoClient LIBRARY + DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) diff --git a/middleware/rialto-client/media/client/main/include/AttachedSources.h b/middleware/rialto-client/media/client/main/include/AttachedSources.h new file mode 100644 index 000000000..43c0f7fc1 --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/AttachedSources.h @@ -0,0 +1,58 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_ATTACHED_SOURCES_H_ +#define FIREBOLT_RIALTO_CLIENT_ATTACHED_SOURCES_H_ + +#include "MediaCommon.h" +#include +#include +#include + +namespace firebolt::rialto::client +{ +class AttachedSources +{ + struct Source + { + MediaSourceType type{MediaSourceType::UNKNOWN}; + bool isFlushing{false}; + }; + +public: + AttachedSources() = default; + ~AttachedSources() = default; + AttachedSources(const AttachedSources &) = delete; + AttachedSources(AttachedSources &&) = delete; + AttachedSources &operator=(const AttachedSources &) = delete; + AttachedSources &operator=(AttachedSources &&) = delete; + + void add(std::uint32_t id, const MediaSourceType &mediaSourceType); + void remove(std::uint32_t id); + MediaSourceType getType(std::uint32_t id) const; + bool isFlushing(std::uint32_t id) const; + void setFlushing(std::uint32_t id, bool flushing); + +private: + mutable std::mutex m_mutex; + std::map m_attachedSources; +}; +} // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_ATTACHED_SOURCES_H_ diff --git a/middleware/rialto-client/media/client/main/include/ClientController.h b/middleware/rialto-client/media/client/main/include/ClientController.h new file mode 100644 index 000000000..92f495c2b --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/ClientController.h @@ -0,0 +1,116 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_CLIENT_CONTROLLER_H_ +#define FIREBOLT_RIALTO_CLIENT_CLIENT_CONTROLLER_H_ + +#include +#include +#include +#include + +#include "IClientController.h" +#include "IControlClient.h" +#include "IControlIpc.h" + +namespace firebolt::rialto::client +{ +class ClientControllerAccessor : public IClientControllerAccessor +{ +public: + ~ClientControllerAccessor() override = default; + IClientController &getClientController() const override; +}; + +class ClientController : public IClientController, public IControlClient +{ +public: + explicit ClientController(const std::shared_ptr &ControlIpcFactory); + ~ClientController() override; + + std::shared_ptr getSharedMemoryHandle() override; + bool registerClient(std::weak_ptr client, ApplicationState &appState) override; + bool unregisterClient(std::weak_ptr client) override; + +private: + void notifyApplicationState(ApplicationState state) override; + + /** + * @brief Initalised the shared memory for media playback. + * + * @retval true on success, false otherwise. + */ + bool initSharedMemory(); + + /** + * @brief Terminates the shared memory. + */ + void termSharedMemory(); + + /** + * @brief Coverts a ApplicationState to string. + * + * @param[in] state : The application state. + * + * @retval the application state string, or "" on error. + */ + std::string stateToString(ApplicationState state); + + /** + * @brief Forwards new ApplicationState to subscribed clients + * + * @param[in] state : The new application state. + * + */ + void changeStateAndNotifyClients(ApplicationState state); + +private: + /** + * @brief Mutex protection for class attributes. + */ + std::mutex m_mutex; + + /** + * @brief The current application state + */ + ApplicationState m_currentState; + + /** + * @brief Flag indicating if registerRequest has to be sent to Rialto Server + */ + bool m_registrationRequired; + + /** + * @brief The shared memory buffer handle. + */ + std::shared_ptr m_shmHandle; + + /** + * @brief The rialto control ipc factory. + */ + std::shared_ptr m_controlIpc; + + /** + * @brief List of clients to notify. + */ + std::list> m_clients; +}; +} // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_CLIENT_CONTROLLER_H_ diff --git a/middleware/rialto-client/media/client/main/include/ClientLogControl.h b/middleware/rialto-client/media/client/main/include/ClientLogControl.h new file mode 100644 index 000000000..7549aac3b --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/ClientLogControl.h @@ -0,0 +1,87 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_CLIENT_LOG_CONTROL_H_ +#define FIREBOLT_RIALTO_CLIENT_CLIENT_LOG_CONTROL_H_ + +#include +#include +#include +#include + +#include "IClientLogControl.h" +#include "RialtoLogging.h" + +namespace firebolt::rialto::client +{ +/** + * @brief IClientLogControl factory class definition. + */ +class ClientLogControlFactory : public IClientLogControlFactory +{ +public: + ClientLogControlFactory() = default; + ~ClientLogControlFactory() override = default; + + IClientLogControl &createClientLogControl() override; + + /** + * @brief Create the (singleton) object. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); +}; + +/** + * @brief The definition of the Control. + */ +class ClientLogControl : public IClientLogControl +{ +public: + /** + * @brief The constructor. + */ + ClientLogControl(); + + ClientLogControl(const ClientLogControl &) = delete; + ClientLogControl &operator=(const ClientLogControl &) = delete; + + /** + * @brief Virtual destructor. + */ + ~ClientLogControl() override; + + bool registerLogHandler(const std::shared_ptr &handler, bool ignoreLogLevels) override; + +private: + void forwardLog(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, + const char *function, const char *message, std::size_t messageLen); + void cancelLogHandler(); + + /** + * @brief The registered log handler + */ + std::shared_ptr m_logHandler; + std::mutex m_logHandlerMutex; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_CLIENT_LOG_CONTROL_H_ diff --git a/middleware/rialto-client/media/client/main/include/Control.h b/middleware/rialto-client/media/client/main/include/Control.h new file mode 100644 index 000000000..8ad5e6329 --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/Control.h @@ -0,0 +1,86 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_CONTROL_H_ +#define FIREBOLT_RIALTO_CLIENT_CONTROL_H_ + +#include +#include +#include + +#include "IClientController.h" +#include "IControl.h" +#include "IControlClient.h" +#include "RialtoLogging.h" + +namespace firebolt::rialto::client +{ +/** + * @brief IControl factory class definition. + */ +class ControlFactory : public IControlFactory +{ +public: + ControlFactory() = default; + ~ControlFactory() override = default; + + std::shared_ptr createControl() const override; + /** + * @brief Create the control factory object. + * + * @retval the control factory instance or null on error. + */ + static std::shared_ptr createFactory(); +}; + +/** + * @brief The definition of the Control. + */ +class Control : public IControl +{ +public: + /** + * @brief The constructor. + */ + explicit Control(IClientController &clientController); + + /** + * @brief Virtual destructor. + */ + ~Control() override; + + bool registerClient(std::weak_ptr client, ApplicationState &appState) override; + +private: + /** + * @brief The control clients which have been registered with m_clientController + * and are kept so that they can be unregistered upon destruction of this + * object + */ + std::vector> m_clientsToUnregister; + + /** + * @brief The rialto client controller object. + */ + IClientController &m_clientController; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_CONTROL_H_ diff --git a/middleware/rialto-client/media/client/main/include/IClientController.h b/middleware/rialto-client/media/client/main/include/IClientController.h new file mode 100644 index 000000000..b6402c25e --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/IClientController.h @@ -0,0 +1,110 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_CLIENT_CONTROLLER_H_ +#define FIREBOLT_RIALTO_CLIENT_I_CLIENT_CONTROLLER_H_ + +#include +#include +#include + +#include "IClientLogHandler.h" +#include "IControlClient.h" +#include "ISharedMemoryHandle.h" + +namespace firebolt::rialto::client +{ +class IClientController; + +/** + * @brief IClientController accessor class definition. + */ +class IClientControllerAccessor +{ +public: + virtual ~IClientControllerAccessor() = default; + IClientControllerAccessor(const IClientControllerAccessor &) = delete; + IClientControllerAccessor &operator=(const IClientControllerAccessor &) = delete; + IClientControllerAccessor(IClientControllerAccessor &&) = delete; + IClientControllerAccessor &operator=(IClientControllerAccessor &&) = delete; + + /** + * @brief Get a IClientControllerAccessor instance. + * + * @retval the accessor instance + */ + static IClientControllerAccessor &instance(); + + /** + * @brief Get ClientController object. + * + * @retval the reference to ClientController singleton object + */ + virtual IClientController &getClientController() const = 0; + +protected: + IClientControllerAccessor() = default; +}; + +/** + * @brief The definition of the IClientController interface. + * + * This interface defines the internal API querying shared memory. + */ +class IClientController +{ +public: + IClientController() = default; + virtual ~IClientController() = default; + + IClientController(const IClientController &) = delete; + IClientController &operator=(const IClientController &) = delete; + IClientController(IClientController &&) = delete; + IClientController &operator=(IClientController &&) = delete; + + /** + * @brief Gets the handle to the mapped shared memory. + * + * @retval shared pointer to shm handle. + */ + virtual std::shared_ptr getSharedMemoryHandle() = 0; + + /** + * @brief Register a client notify when the shared buffer changes. + * + * @param[in] client : Client to register. + * @param[out] appState : Current application state + * + * @retval true on success, false otherwise. + */ + virtual bool registerClient(std::weak_ptr client, ApplicationState &appState) = 0; + + /** + * @brief Unregister a client. + * + * @param[in] client : Client to unregister. + * + * @retval true on success, false otherwise. + */ + virtual bool unregisterClient(std::weak_ptr client) = 0; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_CLIENT_CONTROLLER_H_ diff --git a/middleware/rialto-client/media/client/main/include/ISharedMemoryHandle.h b/middleware/rialto-client/media/client/main/include/ISharedMemoryHandle.h new file mode 100644 index 000000000..6ff1128df --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/ISharedMemoryHandle.h @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_I_SHARED_MEMORY_HANDLE_H_ +#define FIREBOLT_RIALTO_CLIENT_I_SHARED_MEMORY_HANDLE_H_ + +#include + +namespace firebolt::rialto::client +{ +class ISharedMemoryHandle +{ +public: + ISharedMemoryHandle() = default; + ISharedMemoryHandle(const ISharedMemoryHandle &) = delete; + ISharedMemoryHandle(ISharedMemoryHandle &&) = delete; + ISharedMemoryHandle &operator=(const ISharedMemoryHandle &) = delete; + ISharedMemoryHandle &operator=(ISharedMemoryHandle &&) = delete; + virtual ~ISharedMemoryHandle() = default; + + virtual std::uint8_t *getShm() const = 0; +}; +} // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_I_SHARED_MEMORY_HANDLE_H_ diff --git a/middleware/rialto-client/media/client/main/include/KeyIdMap.h b/middleware/rialto-client/media/client/main/include/KeyIdMap.h new file mode 100644 index 000000000..978f7d6ab --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/KeyIdMap.h @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_KEY_IDMAP_H_ +#define FIREBOLT_RIALTO_CLIENT_KEY_IDMAP_H_ + +#include +#include +#include +#include + +namespace firebolt::rialto::client +{ +class KeyIdMap +{ +public: + static KeyIdMap &instance(); + void addSession(std::int32_t keySessionId); + bool updateKey(std::int32_t keySessionId, const std::vector &keyId); + std::vector get(std::int32_t keySessionId) const; + void erase(std::int32_t keySessionId); + +private: + KeyIdMap() = default; + ~KeyIdMap() = default; + KeyIdMap(const KeyIdMap &) = delete; + KeyIdMap(KeyIdMap &&) = delete; + KeyIdMap &operator=(const KeyIdMap &) = delete; + KeyIdMap &operator=(KeyIdMap &&) = delete; + +private: + mutable std::mutex m_mutex; + std::map> m_keyIdMap; +}; +} // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_KEY_IDMAP_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaKeys.h b/middleware/rialto-client/media/client/main/include/MediaKeys.h new file mode 100644 index 000000000..f5e6bb485 --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/MediaKeys.h @@ -0,0 +1,132 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_H_ +#define FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_H_ + +#include "IMediaKeys.h" +#include "IMediaKeysIpcFactory.h" +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief IMediaKeys factory class definition. + */ +class MediaKeysFactory : public IMediaKeysFactory +{ +public: + MediaKeysFactory() = default; + ~MediaKeysFactory() override = default; + + std::unique_ptr createMediaKeys(const std::string &keySystem) const override; + + /** + * @brief IMediaKeys factory method with factory parameters for mock injection. + * + * @param[in] keySystem : The key system for which to create a Media Keys instance + * @param[in] mediaKeysIpcFactory : This was added for the test environment where a mock object needs to be passed in. + * + * @retval the new media keys instance or null on error. + */ + std::unique_ptr + createMediaKeys(const std::string &keySystem, + std::weak_ptr mediaKeysIpcFactory) const; +}; + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +/** + * @brief The definition of the MediaKeys. + */ +class MediaKeys : public IMediaKeys +{ +public: + /** + * @brief The constructor. + * + * @param[in] keySystem : The key system for which to create a Media Keys instance. + * @param[in] mediaKeysIpcFactory : The media keys ipc factory. + */ + explicit MediaKeys(const std::string &keySystem, const std::shared_ptr &mediaKeysIpcFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaKeys(); + + MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) override; + + bool containsKey(int32_t keySessionId, const std::vector &keyId) override; + + MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, bool isLDL, + int32_t &keySessionId) override; + + MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) override; + + MediaKeyErrorStatus loadSession(int32_t keySessionId) override; + + MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) override; + + MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) override; + + MediaKeyErrorStatus closeKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus removeKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus deleteDrmStore() override; + + MediaKeyErrorStatus deleteKeyStore() override; + + MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) override; + + MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) override; + + MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) override; + + MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) override; + + MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) override; + + MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) override; + + MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) override; + +private: + /** + * @brief The media keys ipc object. + */ + std::unique_ptr m_mediaKeysIpc; + + /** + * @brief The key system. + */ + std::string m_keySystem; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaKeysCapabilities.h b/middleware/rialto-client/media/client/main/include/MediaKeysCapabilities.h new file mode 100644 index 000000000..c1974f606 --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/MediaKeysCapabilities.h @@ -0,0 +1,93 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_H_ + +#include "IMediaKeysCapabilities.h" +#include "IMediaKeysCapabilitiesIpcFactory.h" +#include +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief IMediaKeysCapabilities factory class definition. + */ +class MediaKeysCapabilitiesFactory : public IMediaKeysCapabilitiesFactory +{ +public: + MediaKeysCapabilitiesFactory() = default; + ~MediaKeysCapabilitiesFactory() override = default; + + /** + * @brief Weak pointer to the singleton object. + */ + static std::weak_ptr m_mediaKeysCapabilities; + + /** + * @brief Mutex protection for creation of the MediaKeysCapabilities object. + */ + static std::mutex m_creationMutex; + + std::shared_ptr getMediaKeysCapabilities() const override; +}; + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +/** + * @brief The definition of the MediaKeysCapabilities. + */ +class MediaKeysCapabilities : public IMediaKeysCapabilities +{ +public: + /** + * @brief The constructor. + * + * @param[in] mediaKeysCapabilitiesIpcFactory : The media keys capabilities ipc factory. + */ + explicit MediaKeysCapabilities(const std::shared_ptr &MediaKeysCapabilitiesIpcFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaKeysCapabilities(); + + std::vector getSupportedKeySystems() override; + + bool supportsKeySystem(const std::string &keySystem) override; + + bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) override; + + bool isServerCertificateSupported(const std::string &keySystem) override; + +private: + /** + * @brief The media keys capabilities ipc object. + */ + std::shared_ptr m_mediaKeysCapabilitiesIpc; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaPipeline.h b/middleware/rialto-client/media/client/main/include/MediaPipeline.h new file mode 100644 index 000000000..b9e97a430 --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/MediaPipeline.h @@ -0,0 +1,336 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_MEDIA_PIPELINE_H_ +#define FIREBOLT_RIALTO_MEDIA_PIPELINE_H_ + +#include "AttachedSources.h" +#include "IClientController.h" +#include "IControlClient.h" +#include "IMediaFrameWriter.h" +#include "IMediaPipeline.h" +#include "IMediaPipelineIpc.h" +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief IMediaPipeline factory class definition. + */ +class MediaPipelineFactory : public IMediaPipelineFactory +{ +public: + MediaPipelineFactory() = default; + ~MediaPipelineFactory() override = default; + + std::unique_ptr createMediaPipeline(std::weak_ptr client, + const VideoRequirements &videoRequirements) const override; + + /** + * @brief IMediaPipeline factory method with factory parameters for mock injection. + * + * @param[in] client : The Rialto media player client. + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. + * @param[in] mediaPipelineIpcFactory : This was added for the test environment where a mock object needs to be passed in. + * @param[in] clientController : This was added for the test environment where a mock object needs to be passed in. + * + * @retval the new backend instance or null on error. + */ + std::unique_ptr + createMediaPipeline(std::weak_ptr client, const VideoRequirements &videoRequirements, + std::weak_ptr mediaPipelineIpcFactory, + std::weak_ptr clientController) const; +}; + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +class IMediaPipelineAndIControlClient : public IMediaPipeline, public IControlClient +{ +}; + +/** + * @brief The definition of the MediaPipeline. + */ +class MediaPipeline : public IMediaPipelineAndIControlClient, public IMediaPipelineIpcClient +{ +public: + /** + * @brief The possible states of the MediaPipeline. + */ + enum class State + { + IDLE, /**< The MediaPipeline is idle. */ + BUFFERING, /**< The MediaPipeline is buffering data. */ + PLAYING, /**< The MediaPipeline is playing. */ + SEEKING, /**< The MediaPipeline is seeking position. */ + FAILURE, /**< The MediaPipeline is failed. */ + END_OF_STREAM /**< The MediaPipeline is at the end of stream. */ + }; + + /** + * @brief The constructor. + * + * @param[in] client : The Rialto media player client. + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. + * @param[in] mediaPipelineIpcFactory : The media player ipc factory. + * @param[in] mediaFrameWriterFactory : The media frame writer factory. + * @param[in] clientController : The shared memory manager. + */ + MediaPipeline(std::weak_ptr client, const VideoRequirements &videoRequirements, + const std::shared_ptr &mediaPipelineIpcFactory, + const std::shared_ptr &mediaFrameWriterFactory, + IClientController &clientController); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaPipeline(); + + bool load(MediaType type, const std::string &mimeType, const std::string &url) override; + + bool attachSource(const std::unique_ptr &source) override; + + bool removeSource(int32_t id) override; + + bool allSourcesAttached() override; + + bool play() override; + + bool pause() override; + + bool stop() override; + + bool setPlaybackRate(double rate) override; + + bool setPosition(int64_t position) override; + + bool getPosition(int64_t &position) override; + + bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override; + + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override; + + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; + bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + + bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override; + + AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; + + std::weak_ptr getClient() override; + + void notifyPlaybackState(PlaybackState state) override; + + void notifyPosition(int64_t position) override; + + void notifyNetworkState(NetworkState state) override; + + void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId, + const std::shared_ptr &shmInfo) override; + + void notifyQos(int32_t sourceId, const QosInfo &qosInfo) override; + + void notifyBufferUnderflow(int32_t sourceId) override; + + void notifyPlaybackError(int32_t sourceId, PlaybackError error) override; + + void notifySourceFlushed(int32_t sourceId) override; + + bool renderFrame() override; + + bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override; + + bool getVolume(double ¤tVolume) override; + + bool setMute(int32_t sourceId, bool mute) override; + + bool getMute(int32_t sourceId, bool &mute) override; + + bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; + + bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; + + bool setLowLatency(bool lowLatency) override; + + bool setSync(bool sync) override; + + bool getSync(bool &sync) override; + + bool setSyncOff(bool syncOff) override; + + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; + + bool getStreamSyncMode(int32_t &streamSyncMode) override; + + bool flush(int32_t sourceId, bool resetTime, bool &async) override; + + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) override; + + bool setSubtitleOffset(int32_t sourceId, int64_t position) override; + + bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; + + bool setBufferingLimit(uint32_t limitBufferingMs) override; + + bool getBufferingLimit(uint32_t &limitBufferingMs) override; + + bool setUseBuffering(bool useBuffering) override; + + bool getUseBuffering(bool &useBuffering) override; + + bool switchSource(const std::unique_ptr &source) override; + + void notifyApplicationState(ApplicationState state) override; + +protected: + /** + * @brief The need data request data. + */ + struct NeedDataRequest + { + int32_t sourceId; /**< The source id. */ + std::shared_ptr shmInfo; /**< The shared memory information. */ + std::unique_ptr frameWriter; /**< The frame writer used to add segments. */ + }; + + /** + * @brief The media player client. + */ + std::weak_ptr m_mediaPipelineClient; + + /** + * @brief The media player ipc object. + */ + std::unique_ptr m_mediaPipelineIpc; + + /** + * @brief The rialto shared memory manager object. + */ + IClientController &m_clientController; + + /** + * @brief The Need data request map. + * Key: requestId + * Value: NeedDataRequest + */ + std::map> m_needDataRequestMap; + + /** + * @brief The current application state. Protected by m_needDataRequestMapMutex + */ + ApplicationState m_currentAppState; + + /** + * @brief The need data request map mutex. + */ + std::mutex m_needDataRequestMapMutex; + + /** + * @brief The media frame writer factory. + */ + std::shared_ptr m_mediaFrameWriterFactory; + + /** + * @brief The shared memory mutex. + */ + std::mutex m_shmMutex; + + /** + * @brief The current state of the MediaPipeline. + */ + std::atomic m_currentState; + + /** + * @brief The flush request mutex. + */ + std::mutex m_flushMutex; + + /** + * @brief The attach source mutex. + */ + std::mutex m_attachSourceMutex; + + /** + * @brief The attach source condition variable. + */ + std::condition_variable m_attachSourceCond; + + /** + * @brief Whether attachSource is currently in progress. + */ + bool m_attachingSource; + + /** + * @brief The container with attached source id <-> MediaSourceType mapping + */ + AttachedSources m_attachedSources; + + /** + * @brief Sets the new internal MediaPipeline state based on the NetworkState. + * + * @param[in] state : The new NeworkState. + */ + void updateState(NetworkState state); + + /** + * @brief Sets the new internal MediaPipeline state based on the PlaybackState. + * + * @param[in] state : The new PlaybackState. + */ + void updateState(PlaybackState state); + + /** + * @brief Handles a have data request. + * + * @param[in] status : The status + * @param[in] needDataRequestId : Need data request id + * + * @retval true on success. + */ + bool handleHaveData(MediaSourceStatus status, uint32_t needDataRequestId); + + /** + * @brief Handles a set position request. + * + * @param[in] position : The playback position in nanoseconds. + * + * @retval true on success. + */ + bool handleSetPosition(int64_t position); + + /** + * @brief Discards the need data request with id. + * + * @param[in] needDataRequestId : Need data request id + */ + void discardNeedDataRequest(uint32_t needDataRequestId); +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_MEDIA_PIPELINE_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaPipelineCapabilities.h b/middleware/rialto-client/media/client/main/include/MediaPipelineCapabilities.h new file mode 100644 index 000000000..591cab712 --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/MediaPipelineCapabilities.h @@ -0,0 +1,116 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_H_ + +#include "IMediaPipelineCapabilities.h" +#include "IMediaPipelineCapabilitiesIpcFactory.h" +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief IMediaPipelineCapabilitiesFactory factory class definition. + */ +class MediaPipelineCapabilitiesFactory : public IMediaPipelineCapabilitiesFactory +{ +public: + MediaPipelineCapabilitiesFactory() = default; + ~MediaPipelineCapabilitiesFactory() override = default; + + std::unique_ptr createMediaPipelineCapabilities() const override; +}; + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +/** + * @brief The definition of the MediaPipelineCapabilities. + */ +class MediaPipelineCapabilities : public IMediaPipelineCapabilities +{ +public: + /** + * @brief The constructor. + * + * @param[in] mediaPipelineCapabilitiesIpcFactory : The media pipeline capabilities ipc factory. + */ + explicit MediaPipelineCapabilities( + const std::shared_ptr &MediaPipelineCapabilitiesIpcFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaPipelineCapabilities(); + + /** + * @brief Returns the MSE mime types supported by Rialto for \a sourceType + * + * @param[in] sourceType : source type + * + * @retval The supported mime types. + */ + std::vector getSupportedMimeTypes(MediaSourceType sourceType) override; + + /** + * @brief Indicates if the specified mime type is supported. + * + * This method should be called to ensure that the specified mime + * type is supported by Rialto. + * + * @param[in] mimeType : The mime type to check. + * + * @retval true if supported. + */ + bool isMimeTypeSupported(const std::string &mimeTypee) override; + + /** + * @brief Check sinks and decoders for supported properties + * + * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched + * @param[in] propertyNames : A vector of property names to look for + * + * @retval Returns the subset of propertyNames that are supported by the mediaType + */ + std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) override; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + bool isVideoMaster(bool &isVideoMaster) override; + +private: + /** + * @brief The media pipeline capabilities ipc object. + */ + std::unique_ptr m_mediaPipelineCapabilitiesIpc; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaPipelineProxy.h b/middleware/rialto-client/media/client/main/include/MediaPipelineProxy.h new file mode 100644 index 000000000..3747f5535 --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/MediaPipelineProxy.h @@ -0,0 +1,186 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_PROXY_H_ +#define FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_PROXY_H_ + +#include + +#include +#include + +#include "MediaPipeline.h" + +namespace firebolt::rialto::client +{ +class MediaPipelineProxy : public IMediaPipelineAndIControlClient +{ +public: + MediaPipelineProxy(const std::shared_ptr &mediaPipeline, + client::IClientController &clientController); + virtual ~MediaPipelineProxy(); + + std::weak_ptr getClient() override { return m_mediaPipeline->getClient(); } + + bool load(MediaType type, const std::string &mimeType, const std::string &url) override + { + return m_mediaPipeline->load(type, mimeType, url); + } + + bool attachSource(const std::unique_ptr &source) override + { + return m_mediaPipeline->attachSource(source); + } + + bool removeSource(int32_t id) override { return m_mediaPipeline->removeSource(id); } + + bool allSourcesAttached() override { return m_mediaPipeline->allSourcesAttached(); } + + bool play() override { return m_mediaPipeline->play(); } + + bool pause() override { return m_mediaPipeline->pause(); } + + bool stop() override { return m_mediaPipeline->stop(); } + + bool setPlaybackRate(double rate) override { return m_mediaPipeline->setPlaybackRate(rate); } + + bool setPosition(int64_t position) override { return m_mediaPipeline->setPosition(position); } + + bool getPosition(int64_t &position) override { return m_mediaPipeline->getPosition(position); } + + bool setImmediateOutput(int32_t sourceId, bool immediateOutput) + { + return m_mediaPipeline->setImmediateOutput(sourceId, immediateOutput); + } + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) + { + return m_mediaPipeline->getImmediateOutput(sourceId, immediateOutput); + } + + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) + { + return m_mediaPipeline->getStats(sourceId, renderedFrames, droppedFrames); + } + + bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override + { + return m_mediaPipeline->setVideoWindow(x, y, width, height); + } + + bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override + { + return m_mediaPipeline->haveData(status, needDataRequestId); + } + + AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override + { + return m_mediaPipeline->addSegment(needDataRequestId, mediaSegment); + } + + bool renderFrame() override { return m_mediaPipeline->renderFrame(); } + + bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override + { + return m_mediaPipeline->setVolume(targetVolume, volumeDuration, easeType); + } + + bool getVolume(double ¤tVolume) override { return m_mediaPipeline->getVolume(currentVolume); } + + bool setMute(int32_t sourceId, bool mute) override { return m_mediaPipeline->setMute(sourceId, mute); } + + bool getMute(int32_t sourceId, bool &mute) override { return m_mediaPipeline->getMute(sourceId, mute); } + + bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override + { + return m_mediaPipeline->setTextTrackIdentifier(textTrackIdentifier); + } + + bool getTextTrackIdentifier(std::string &textTrackIdentifier) override + { + return m_mediaPipeline->getTextTrackIdentifier(textTrackIdentifier); + } + + bool setLowLatency(bool lowLatency) override { return m_mediaPipeline->setLowLatency(lowLatency); } + + bool setSync(bool sync) override { return m_mediaPipeline->setSync(sync); } + + bool getSync(bool &sync) override { return m_mediaPipeline->getSync(sync); } + + bool setSyncOff(bool syncOff) override { return m_mediaPipeline->setSyncOff(syncOff); } + + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override + { + return m_mediaPipeline->setStreamSyncMode(sourceId, streamSyncMode); + } + + bool getStreamSyncMode(int32_t &streamSyncMode) override + { + return m_mediaPipeline->getStreamSyncMode(streamSyncMode); + } + + bool flush(int32_t sourceId, bool resetTime, bool &async) override + { + return m_mediaPipeline->flush(sourceId, resetTime, async); + } + + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) override + { + return m_mediaPipeline->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition); + } + + bool setSubtitleOffset(int32_t sourceId, int64_t position) override + { + return m_mediaPipeline->setSubtitleOffset(sourceId, position); + } + + bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override + { + return m_mediaPipeline->processAudioGap(position, duration, discontinuityGap, audioAac); + } + + bool setBufferingLimit(uint32_t limitBufferingMs) override + { + return m_mediaPipeline->setBufferingLimit(limitBufferingMs); + } + + bool getBufferingLimit(uint32_t &limitBufferingMs) override + { + return m_mediaPipeline->getBufferingLimit(limitBufferingMs); + } + + bool setUseBuffering(bool useBuffering) override { return m_mediaPipeline->setUseBuffering(useBuffering); } + + bool getUseBuffering(bool &useBuffering) override { return m_mediaPipeline->getUseBuffering(useBuffering); } + + bool switchSource(const std::unique_ptr &source) override + { + return m_mediaPipeline->switchSource(source); + } + + void notifyApplicationState(ApplicationState state) override { m_mediaPipeline->notifyApplicationState(state); } + +private: + std::shared_ptr m_mediaPipeline; + client::IClientController &m_clientController; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_PROXY_H_ diff --git a/middleware/rialto-client/media/client/main/include/SharedMemoryHandle.h b/middleware/rialto-client/media/client/main/include/SharedMemoryHandle.h new file mode 100644 index 000000000..7c0ae2f3b --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/SharedMemoryHandle.h @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_SHARED_MEMORY_HANDLE_H_ +#define FIREBOLT_RIALTO_CLIENT_SHARED_MEMORY_HANDLE_H_ + +#include "ISharedMemoryHandle.h" + +namespace firebolt::rialto::client +{ +class SharedMemoryHandle : public ISharedMemoryHandle +{ +public: + SharedMemoryHandle(std::int32_t shmFd, std::uint32_t shmBufferLen); + ~SharedMemoryHandle() override; + + std::uint8_t *getShm() const override; + +private: + /** + * @brief The shared memory file descriptor. + */ + std::int32_t m_shmFd; + + /** + * @brief The shared memory buffer length. + */ + std::uint32_t m_shmBufferLen; + + /** + * @brief The shared memory buffer pointer. + */ + std::uint8_t *m_shmBuffer; +}; +} // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_SHARED_MEMORY_HANDLE_H_ diff --git a/middleware/rialto-client/media/client/main/include/WebAudioPlayer.h b/middleware/rialto-client/media/client/main/include/WebAudioPlayer.h new file mode 100644 index 000000000..2c5b11f9a --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/WebAudioPlayer.h @@ -0,0 +1,165 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_H_ +#define FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_H_ + +#include "IClientController.h" +#include "IControlClient.h" +#include "IWebAudioPlayer.h" +#include "IWebAudioPlayerIpc.h" +#include "IWebAudioPlayerIpcClient.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief IWebAudioPlayer factory class definition. + */ +class WebAudioPlayerFactory : public IWebAudioPlayerFactory +{ +public: + WebAudioPlayerFactory() = default; + ~WebAudioPlayerFactory() override = default; + + std::unique_ptr createWebAudioPlayer(std::weak_ptr client, + const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config) const override; + + /** + * @brief IWebAudioPlayer factory method with factory parameters for mock injection. + * + * @param[in] client : The Web Audio Player client. + * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM). + * @param[in] priority : Priority value for this pipeline. + * @param[in] config : Additional type dependent configuration data or nullptr. + * @param[in] webAudioPlayerIpcFactory : This was added for the test environment where a mock object needs to be + * passed in. + * @param[in] clientController : This was added for the test environment where a mock object needs to be + * passed in. + * + * @retval the new Web Audio Player instance or null on error. + */ + virtual std::unique_ptr + createWebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config, + std::weak_ptr webAudioPlayerIpcFactory, + std::weak_ptr clientController) const; +}; + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +class IWebAudioPlayerAndIControlClient : public IWebAudioPlayer, public IControlClient +{ +}; + +/** + * @brief The definition of the WebAudioPlayer. + */ +class WebAudioPlayer : public IWebAudioPlayerAndIControlClient, public client::IWebAudioPlayerIpcClient +{ +public: + /** + * @brief The constructor. + * + * @param[in] client : The Web Audio Player client + * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM) + * @param[in] priority : Priority value for this pipeline. + * @param[in] config : Additional type dependent configuration data or nullptr + */ + WebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config, + const std::shared_ptr &webAudioPlayerIpcFactory, + IClientController &clientController); + + /** + * @brief Virtual destructor. + */ + virtual ~WebAudioPlayer(); + + bool play() override; + + bool pause() override; + + bool setEos() override; + + bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) override; + + bool getBufferDelay(uint32_t &delayFrames) override; + + bool writeBuffer(const uint32_t numberOfFrames, void *data) override; + + bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override; + + bool setVolume(double volume) override; + + bool getVolume(double &volume) override; + + std::weak_ptr getClient() override; + + void notifyState(WebAudioPlayerState state) override; + + void notifyApplicationState(ApplicationState state) override; + +protected: + /** + * @brief The web audio player client. + */ + std::weak_ptr m_webAudioPlayerClient; + + /** + * @brief The media player ipc object. + */ + std::unique_ptr m_webAudioPlayerIpc; + + /** + * @brief The rialto client controller object. + */ + IClientController &m_clientController; + + /** + * @brief The shared memory region info. + */ + std::shared_ptr m_webAudioShmInfo; + + /** + * @brief Ensure thread safety for clients by preventing concurrent writing to the buffer. + */ + std::mutex m_bufLock; + + /** + * @brief The bytes per frame for this audio playback. + */ + uint32_t m_bytesPerFrame; + + /** + * @brief The current application state. + */ + std::atomic m_currentAppState; +}; + +}; // namespace firebolt::rialto::client + +#endif // FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_H_ diff --git a/middleware/rialto-client/media/client/main/include/WebAudioPlayerProxy.h b/middleware/rialto-client/media/client/main/include/WebAudioPlayerProxy.h new file mode 100644 index 000000000..2902f818c --- /dev/null +++ b/middleware/rialto-client/media/client/main/include/WebAudioPlayerProxy.h @@ -0,0 +1,75 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_WEB_AUDIO_PLAYER_PROXY_H_ +#define FIREBOLT_RIALTO_WEB_AUDIO_PLAYER_PROXY_H_ + +#include +#include + +#include "WebAudioPlayer.h" + +namespace firebolt::rialto +{ +class WebAudioPlayerProxy : public client::IWebAudioPlayerAndIControlClient +{ +public: + WebAudioPlayerProxy(const std::shared_ptr &webAudioPlayer, + client::IClientController &clientController); + virtual ~WebAudioPlayerProxy(); + + bool play() override { return m_webAudioPlayer->play(); } + + bool pause() override { return m_webAudioPlayer->pause(); } + + bool setEos() override { return m_webAudioPlayer->setEos(); } + + bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) override + { + return m_webAudioPlayer->getBufferAvailable(availableFrames, webAudioShmInfo); + } + + bool getBufferDelay(uint32_t &delayFrames) override { return m_webAudioPlayer->getBufferDelay(delayFrames); } + + bool writeBuffer(const uint32_t numberOfFrames, void *data) override + { + return m_webAudioPlayer->writeBuffer(numberOfFrames, data); + } + + bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override + { + return m_webAudioPlayer->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay); + } + + bool setVolume(double volume) override { return m_webAudioPlayer->setVolume(volume); } + + bool getVolume(double &volume) override { return m_webAudioPlayer->getVolume(volume); } + + std::weak_ptr getClient() override { return m_webAudioPlayer->getClient(); } + + void notifyApplicationState(ApplicationState state) override { m_webAudioPlayer->notifyApplicationState(state); } + +private: + std::shared_ptr m_webAudioPlayer; + client::IClientController &m_clientController; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_WEB_AUDIO_PLAYER_PROXY_H_ diff --git a/middleware/rialto-client/media/client/main/source/AttachedSources.cpp b/middleware/rialto-client/media/client/main/source/AttachedSources.cpp new file mode 100644 index 000000000..a0980f512 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/AttachedSources.cpp @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AttachedSources.h" + +namespace firebolt::rialto::client +{ +void AttachedSources::add(std::uint32_t id, const MediaSourceType &mediaSourceType) +{ + std::unique_lock lock{m_mutex}; + m_attachedSources.emplace(id, Source{mediaSourceType}); +} + +void AttachedSources::remove(std::uint32_t id) +{ + std::unique_lock lock{m_mutex}; + m_attachedSources.erase(id); +} + +MediaSourceType AttachedSources::getType(std::uint32_t id) const +{ + std::unique_lock lock{m_mutex}; + auto iter = m_attachedSources.find(id); + if (m_attachedSources.end() == iter) + { + return MediaSourceType::UNKNOWN; + } + return iter->second.type; +} + +bool AttachedSources::isFlushing(std::uint32_t id) const +{ + std::unique_lock lock{m_mutex}; + auto iter = m_attachedSources.find(id); + if (m_attachedSources.end() == iter) + { + return false; + } + return iter->second.isFlushing; +} + +void AttachedSources::setFlushing(std::uint32_t id, bool flushing) +{ + std::unique_lock lock{m_mutex}; + auto iter = m_attachedSources.find(id); + if (m_attachedSources.end() == iter) + { + return; + } + iter->second.isFlushing = flushing; +} +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/ClientController.cpp b/middleware/rialto-client/media/client/main/source/ClientController.cpp new file mode 100644 index 000000000..3b1a6fdb7 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/ClientController.cpp @@ -0,0 +1,281 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ClientController.h" +#include "RialtoClientLogging.h" +#include "SharedMemoryHandle.h" +#include +#include +#include +#include +#include + +namespace +{ +// The following error would be reported if a client is deleted +// before unregisterClient() was called. Calling unregisterClient can +// be automated via a proxy class (like the class MediaPipelineProxy) +const std::string kClientPointerNotLocked{"A client could not be locked"}; +}; // namespace + +namespace firebolt::rialto::client +{ +IClientControllerAccessor &IClientControllerAccessor::instance() +{ + static ClientControllerAccessor factory; + return factory; +} + +IClientController &ClientControllerAccessor::getClientController() const +{ + static ClientController ClientController{IControlIpcFactory::createFactory()}; + return ClientController; +} + +ClientController::ClientController(const std::shared_ptr &ControlIpcFactory) + : m_currentState{ApplicationState::UNKNOWN}, m_registrationRequired{true} +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + const char kSrcRev[] = SRCREV; + const char kTags[] = TAGS; + + if (std::strlen(kSrcRev) > 0) + { + if (std::strlen(kTags) > 0) + { + RIALTO_CLIENT_LOG_MIL("Release Tag(s): %s (Commit ID: %s)", kTags, kSrcRev); + } + else + { + RIALTO_CLIENT_LOG_MIL("Release Tag(s): No Release Tags! (Commit ID: %s)", kSrcRev); + } + } + else + { + RIALTO_CLIENT_LOG_WARN("Failed to get git commit ID!"); + } + + m_controlIpc = ControlIpcFactory->createControlIpc(this); + if (nullptr == m_controlIpc) + { + throw std::runtime_error("Failed to create the ControlIpc object"); + } +} + +ClientController::~ClientController() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + termSharedMemory(); +} + +std::shared_ptr ClientController::getSharedMemoryHandle() +{ + std::lock_guard lock{m_mutex}; + return m_shmHandle; +} + +bool ClientController::registerClient(std::weak_ptr client, ApplicationState &appState) +{ + std::shared_ptr clientLocked = client.lock(); + if (!clientLocked) + { + RIALTO_CLIENT_LOG_ERROR("Client ptr is null"); + return false; + } + + std::lock_guard lock{m_mutex}; + if (m_registrationRequired) + { + if (!m_controlIpc->registerClient()) + { + RIALTO_CLIENT_LOG_ERROR("Failed to register client"); + return false; + } + } + m_registrationRequired = false; + + bool alreadyRegistered{std::find_if(m_clients.begin(), m_clients.end(), + [&](auto &i) + { + std::shared_ptr iLocked = i.lock(); + return (iLocked == clientLocked); + }) != m_clients.end()}; + if (!alreadyRegistered) + m_clients.push_back(client); + appState = m_currentState; + + return true; +} + +bool ClientController::unregisterClient(std::weak_ptr client) +{ + std::shared_ptr clientLocked = client.lock(); + if (!clientLocked) + { + RIALTO_CLIENT_LOG_ERROR("Client ptr is null"); + return false; + } + + std::lock_guard lock{m_mutex}; + + bool found{false}; + for (auto i = m_clients.begin(); i != m_clients.end();) + { + std::shared_ptr iLocked = i->lock(); + if (!iLocked) + { + RIALTO_CLIENT_LOG_ERROR("%s", kClientPointerNotLocked.c_str()); + i = m_clients.erase(i); + } + else if (iLocked == clientLocked) + { + i = m_clients.erase(i); + found = true; + break; + } + else + ++i; + } + + if (!found) + { + RIALTO_CLIENT_LOG_ERROR("Client not found"); + return false; + } + + return true; +} + +bool ClientController::initSharedMemory() +try +{ + std::lock_guard lock{m_mutex}; + int32_t shmFd{-1}; + uint32_t shmBufferLen{0U}; + if (!m_controlIpc->getSharedMemory(shmFd, shmBufferLen)) + { + RIALTO_CLIENT_LOG_ERROR("Failed to get the shared memory"); + return false; + } + m_shmHandle = std::make_shared(shmFd, shmBufferLen); + + RIALTO_CLIENT_LOG_INFO("Shared buffer was successfully initialised"); + return true; +} +catch (const std::exception &e) +{ + RIALTO_CLIENT_LOG_ERROR("Failed to initialise shared memory: %s", e.what()); + return false; +} + +void ClientController::termSharedMemory() +{ + std::lock_guard lock{m_mutex}; + m_shmHandle.reset(); +} + +void ClientController::notifyApplicationState(ApplicationState state) +{ + { + std::lock_guard lock{m_mutex}; + if (ApplicationState::UNKNOWN == state) + { + RIALTO_CLIENT_LOG_DEBUG("Application state changed to unknown. Client will have to register next time"); + m_registrationRequired = true; + } + if (m_currentState == state) + { + RIALTO_CLIENT_LOG_WARN("Rialto application state already set, %s", stateToString(m_currentState).c_str()); + return; + } + } + + switch (state) + { + case ApplicationState::RUNNING: + { + if (!initSharedMemory()) + { + RIALTO_CLIENT_LOG_ERROR("Could not initalise the shared memory"); + return; + } + // Inform clients after memory initialisation + changeStateAndNotifyClients(state); + break; + } + case ApplicationState::INACTIVE: + case ApplicationState::UNKNOWN: + { + // Inform clients before memory termination + changeStateAndNotifyClients(state); + termSharedMemory(); + break; + } + } +} + +std::string ClientController::stateToString(ApplicationState state) +{ + switch (state) + { + case ApplicationState::RUNNING: + { + return "RUNNING"; + } + case ApplicationState::INACTIVE: + { + return "INACTIVE"; + } + case ApplicationState::UNKNOWN: + default: + { + return "UNKNOWN"; + } + } +} + +void ClientController::changeStateAndNotifyClients(ApplicationState state) +{ + std::vector> currentClients; + { + std::lock_guard lock{m_mutex}; + RIALTO_CLIENT_LOG_MIL("Rialto application state changed from %s to %s", stateToString(m_currentState).c_str(), + stateToString(state).c_str()); + m_currentState = state; + for (const std::weak_ptr &client : m_clients) + { + std::shared_ptr clientLocked{client.lock()}; + if (clientLocked) + { + currentClients.push_back(clientLocked); + } + else + { + RIALTO_CLIENT_LOG_ERROR("%s", kClientPointerNotLocked.c_str()); + } + } + } + for (const auto &client : currentClients) + { + client->notifyApplicationState(state); + } +} +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/ClientLogControl.cpp b/middleware/rialto-client/media/client/main/source/ClientLogControl.cpp new file mode 100644 index 000000000..c5b695d04 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/ClientLogControl.cpp @@ -0,0 +1,143 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ClientLogControl.h" +#include "RialtoClientLogging.h" + +namespace +{ +const std::vector kAllComponentsToLog{RIALTO_COMPONENT_CLIENT, RIALTO_COMPONENT_IPC, + RIALTO_COMPONENT_COMMON}; + +firebolt::rialto::IClientLogHandler::Level convertLevel(const RIALTO_DEBUG_LEVEL &level) +{ + switch (level) + { + case RIALTO_DEBUG_LEVEL_FATAL: + return firebolt::rialto::IClientLogHandler::Level::Fatal; + case RIALTO_DEBUG_LEVEL_ERROR: + return firebolt::rialto::IClientLogHandler::Level::Error; + case RIALTO_DEBUG_LEVEL_WARNING: + return firebolt::rialto::IClientLogHandler::Level::Warning; + case RIALTO_DEBUG_LEVEL_MILESTONE: + return firebolt::rialto::IClientLogHandler::Level::Milestone; + case RIALTO_DEBUG_LEVEL_INFO: + return firebolt::rialto::IClientLogHandler::Level::Info; + case RIALTO_DEBUG_LEVEL_DEBUG: + return firebolt::rialto::IClientLogHandler::Level::Debug; + case RIALTO_DEBUG_LEVEL_EXTERNAL: + return firebolt::rialto::IClientLogHandler::Level::External; + case RIALTO_DEBUG_LEVEL_DEFAULT: + return firebolt::rialto::IClientLogHandler::Level::Milestone; + } + return firebolt::rialto::IClientLogHandler::Level::Debug; +} +} // namespace + +namespace firebolt::rialto +{ +std::shared_ptr IClientLogControlFactory::createFactory() +{ + return client::ClientLogControlFactory::createFactory(); +} +} // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +std::shared_ptr ClientLogControlFactory::createFactory() +{ + return std::make_shared(); +} + +IClientLogControl &ClientLogControlFactory::createClientLogControl() +{ + static std::unique_ptr clientLogControl{std::make_unique()}; + return *clientLogControl; +} + +ClientLogControl::ClientLogControl() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); +} + +ClientLogControl::~ClientLogControl() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + std::unique_lock lock{m_logHandlerMutex}; + if (m_logHandler) + cancelLogHandler(); +} + +bool ClientLogControl::registerLogHandler(const std::shared_ptr &handler, bool ignoreLogLevels) +{ + std::unique_lock lock{m_logHandlerMutex}; + + if (m_logHandler) + { + if (handler) + { + RIALTO_CLIENT_LOG_WARN("Replacing old log handler"); + } + cancelLogHandler(); + } + + m_logHandler = handler; + + if (!handler) + return true; + + for (auto component : kAllComponentsToLog) + { + if (firebolt::rialto::logging::setLogHandler(component, + std::bind(&ClientLogControl::forwardLog, this, component, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4, + std::placeholders::_5, std::placeholders::_6), + ignoreLogLevels) != + firebolt::rialto::logging::RIALTO_LOGGING_STATUS_OK) + { + RIALTO_CLIENT_LOG_WARN("Unable to register log handler"); + cancelLogHandler(); + return false; + } + } + return true; +} + +void ClientLogControl::cancelLogHandler() +{ + RIALTO_CLIENT_LOG_INFO("Cancelling log handler"); + for (auto component : kAllComponentsToLog) + { + firebolt::rialto::logging::setLogHandler(component, nullptr, false); + } + m_logHandler = nullptr; +} + +void ClientLogControl::forwardLog(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, + const char *function, const char *message, std::size_t messageLen) +{ + // Take a local copy to ensure thread safety + std::shared_ptr logHandler{m_logHandler}; + if (logHandler) + { + logHandler->log(convertLevel(level), std::string(file), line, std::string(function), std::string(message)); + } +} +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/Control.cpp b/middleware/rialto-client/media/client/main/source/Control.cpp new file mode 100644 index 000000000..9bd12f063 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/Control.cpp @@ -0,0 +1,86 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Control.h" +#include "IControlIpc.h" +#include "RialtoClientLogging.h" + +namespace firebolt::rialto +{ +std::shared_ptr IControlFactory::createFactory() +{ + return client::ControlFactory::createFactory(); +} +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +std::shared_ptr ControlFactory::createFactory() +{ + std::shared_ptr factory; + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the rialto control factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr ControlFactory::createControl() const +try +{ + return std::make_shared(IClientControllerAccessor::instance().getClientController()); +} +catch (const std::exception &e) +{ + RIALTO_CLIENT_LOG_ERROR("Failed to create the rialto control, reason: %s", e.what()); + return nullptr; +} + +Control::Control(IClientController &clientController) : m_clientController(clientController) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); +} + +Control::~Control() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + for (const auto &client : m_clientsToUnregister) + { + m_clientController.unregisterClient(client); + } +} + +bool Control::registerClient(std::weak_ptr client, ApplicationState &appState) +{ + std::shared_ptr lockedClient = client.lock(); + if (lockedClient && m_clientController.registerClient(lockedClient, appState)) + { + m_clientsToUnregister.push_back(lockedClient); + return true; + } + RIALTO_CLIENT_LOG_WARN("Unable to register client"); + return false; +} + +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/KeyIdMap.cpp b/middleware/rialto-client/media/client/main/source/KeyIdMap.cpp new file mode 100644 index 000000000..9444b5e1f --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/KeyIdMap.cpp @@ -0,0 +1,64 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "KeyIdMap.h" + +namespace firebolt::rialto::client +{ +KeyIdMap &KeyIdMap::instance() +{ + static KeyIdMap keyIdMap; + return keyIdMap; +} + +void KeyIdMap::addSession(std::int32_t keySessionId) +{ + std::unique_lock lock{m_mutex}; + m_keyIdMap.insert(std::make_pair(keySessionId, std::vector())); +} + +bool KeyIdMap::updateKey(std::int32_t keySessionId, const std::vector &keyId) +{ + std::unique_lock lock{m_mutex}; + auto keyIdIter{m_keyIdMap.find(keySessionId)}; + if (m_keyIdMap.end() == keyIdIter) + { + return false; + } + keyIdIter->second = keyId; + return true; +} + +std::vector KeyIdMap::get(std::int32_t keySessionId) const +{ + std::unique_lock lock{m_mutex}; + auto keyIdIter{m_keyIdMap.find(keySessionId)}; + if (m_keyIdMap.end() == keyIdIter) + { + return std::vector(); + } + return keyIdIter->second; +} + +void KeyIdMap::erase(std::int32_t keySessionId) +{ + std::unique_lock lock{m_mutex}; + m_keyIdMap.erase(keySessionId); +} +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/MediaKeys.cpp b/middleware/rialto-client/media/client/main/source/MediaKeys.cpp new file mode 100644 index 000000000..0324cf828 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/MediaKeys.cpp @@ -0,0 +1,244 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "KeyIdMap.h" +#include "MediaKeys.h" +#include "RialtoClientLogging.h" + +namespace +{ +bool isPlayready(const std::string &keySystem) +{ + return keySystem.find("playready") != std::string::npos; +} +} // namespace + +namespace firebolt::rialto +{ +std::shared_ptr IMediaKeysFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr MediaKeysFactory::createMediaKeys(const std::string &keySystem) const +{ + return createMediaKeys(keySystem, {}); +} + +std::unique_ptr +MediaKeysFactory::createMediaKeys(const std::string &keySystem, + std::weak_ptr mediaKeysIpcFactory) const +{ + std::unique_ptr mediaKeys; + try + { + std::shared_ptr mediaKeysIpcFactoryLocked = + mediaKeysIpcFactory.lock(); + mediaKeys = std::make_unique(keySystem, mediaKeysIpcFactoryLocked + ? mediaKeysIpcFactoryLocked + : client::IMediaKeysIpcFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys, reason: %s", e.what()); + } + + return mediaKeys; +} +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +MediaKeys::MediaKeys(const std::string &keySystem, const std::shared_ptr &mediaKeysIpcFactory) + : m_keySystem{keySystem} +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + m_mediaKeysIpc = mediaKeysIpcFactory->createMediaKeysIpc(keySystem); + if (!m_mediaKeysIpc) + { + throw std::runtime_error("Media keys ipc could not be created"); + } +} + +MediaKeys::~MediaKeys() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_mediaKeysIpc.reset(); +} + +MediaKeyErrorStatus MediaKeys::selectKeyId(int32_t keySessionId, const std::vector &keyId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + if (KeyIdMap::instance().updateKey(keySessionId, keyId)) + { + return MediaKeyErrorStatus::OK; + } + return MediaKeyErrorStatus::FAIL; +} + +bool MediaKeys::containsKey(int32_t keySessionId, const std::vector &keyId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->containsKey(keySessionId, keyId); +} + +MediaKeyErrorStatus MediaKeys::createKeySession(KeySessionType sessionType, std::weak_ptr client, + bool isLDL, int32_t &keySessionId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + auto result{m_mediaKeysIpc->createKeySession(sessionType, client, isLDL, keySessionId)}; + if (isPlayready(m_keySystem) && MediaKeyErrorStatus::OK == result) + { + KeyIdMap::instance().addSession(keySessionId); + } + return result; +} + +MediaKeyErrorStatus MediaKeys::generateRequest(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->generateRequest(keySessionId, initDataType, initData); +} + +MediaKeyErrorStatus MediaKeys::loadSession(int32_t keySessionId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->loadSession(keySessionId); +} + +MediaKeyErrorStatus MediaKeys::updateSession(int32_t keySessionId, const std::vector &responseData) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->updateSession(keySessionId, responseData); +} + +MediaKeyErrorStatus MediaKeys::setDrmHeader(int32_t keySessionId, const std::vector &requestData) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->setDrmHeader(keySessionId, requestData); +} + +MediaKeyErrorStatus MediaKeys::closeKeySession(int32_t keySessionId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + if (isPlayready(m_keySystem)) + { + KeyIdMap::instance().erase(keySessionId); + } + return m_mediaKeysIpc->closeKeySession(keySessionId); +} + +MediaKeyErrorStatus MediaKeys::removeKeySession(int32_t keySessionId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->removeKeySession(keySessionId); +} + +MediaKeyErrorStatus MediaKeys::deleteDrmStore() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->deleteDrmStore(); +} + +MediaKeyErrorStatus MediaKeys::deleteKeyStore() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->deleteKeyStore(); +} + +MediaKeyErrorStatus MediaKeys::getDrmStoreHash(std::vector &drmStoreHash) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->getDrmStoreHash(drmStoreHash); +} + +MediaKeyErrorStatus MediaKeys::getKeyStoreHash(std::vector &keyStoreHash) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->getKeyStoreHash(keyStoreHash); +} + +MediaKeyErrorStatus MediaKeys::getLdlSessionsLimit(uint32_t &ldlLimit) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->getLdlSessionsLimit(ldlLimit); +} + +MediaKeyErrorStatus MediaKeys::getLastDrmError(int32_t keySessionId, uint32_t &errorCode) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->getLastDrmError(keySessionId, errorCode); +} + +MediaKeyErrorStatus MediaKeys::getDrmTime(uint64_t &drmTime) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->getDrmTime(drmTime); +} + +MediaKeyErrorStatus MediaKeys::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->getCdmKeySessionId(keySessionId, cdmKeySessionId); +} + +MediaKeyErrorStatus MediaKeys::releaseKeySession(int32_t keySessionId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaKeysIpc->releaseKeySession(keySessionId); +} + +MediaKeyErrorStatus MediaKeys::getMetricSystemData(std::vector &buffer) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysIpc->getMetricSystemData(buffer); +} +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/MediaKeysCapabilities.cpp b/middleware/rialto-client/media/client/main/source/MediaKeysCapabilities.cpp new file mode 100644 index 000000000..1508b2fd1 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/MediaKeysCapabilities.cpp @@ -0,0 +1,123 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "IMediaKeysCapabilitiesIpcFactory.h" +#include "MediaKeysCapabilities.h" +#include "RialtoClientLogging.h" + +namespace firebolt::rialto +{ +std::weak_ptr MediaKeysCapabilitiesFactory::m_mediaKeysCapabilities; +std::mutex MediaKeysCapabilitiesFactory::m_creationMutex; + +std::shared_ptr IMediaKeysCapabilitiesFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys capabilities factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr MediaKeysCapabilitiesFactory::getMediaKeysCapabilities() const +{ + std::lock_guard lock{m_creationMutex}; + + std::shared_ptr mediaKeysCapabilities = + MediaKeysCapabilitiesFactory::m_mediaKeysCapabilities.lock(); + + if (!mediaKeysCapabilities) + { + try + { + mediaKeysCapabilities = std::make_shared( + client::IMediaKeysCapabilitiesIpcFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys capabilities, reason: %s", e.what()); + } + + MediaKeysCapabilitiesFactory::m_mediaKeysCapabilities = mediaKeysCapabilities; + } + + return mediaKeysCapabilities; +} + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +MediaKeysCapabilities::MediaKeysCapabilities( + const std::shared_ptr &MediaKeysCapabilitiesIpcFactory) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_mediaKeysCapabilitiesIpc = MediaKeysCapabilitiesIpcFactory->getMediaKeysCapabilitiesIpc(); + if (!m_mediaKeysCapabilitiesIpc) + { + throw std::runtime_error("Media keys capabilities ipc could not be created"); + } +} + +MediaKeysCapabilities::~MediaKeysCapabilities() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_mediaKeysCapabilitiesIpc.reset(); +} + +std::vector MediaKeysCapabilities::getSupportedKeySystems() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysCapabilitiesIpc->getSupportedKeySystems(); +} + +bool MediaKeysCapabilities::supportsKeySystem(const std::string &keySystem) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysCapabilitiesIpc->supportsKeySystem(keySystem); +} + +bool MediaKeysCapabilities::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysCapabilitiesIpc->getSupportedKeySystemVersion(keySystem, version); +} + +bool MediaKeysCapabilities::isServerCertificateSupported(const std::string &keySystem) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaKeysCapabilitiesIpc->isServerCertificateSupported(keySystem); +} + +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/MediaPipeline.cpp b/middleware/rialto-client/media/client/main/source/MediaPipeline.cpp new file mode 100644 index 000000000..c7c6913a5 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/MediaPipeline.cpp @@ -0,0 +1,901 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "KeyIdMap.h" +#include "MediaPipeline.h" +#include "MediaPipelineProxy.h" +#include "RialtoClientLogging.h" + +namespace +{ +const char *toString(const firebolt::rialto::client::MediaPipeline::State &state) +{ + switch (state) + { + case firebolt::rialto::client::MediaPipeline::State::IDLE: + return "IDLE"; + case firebolt::rialto::client::MediaPipeline::State::BUFFERING: + return "BUFFERING"; + case firebolt::rialto::client::MediaPipeline::State::PLAYING: + return "PLAYING"; + case firebolt::rialto::client::MediaPipeline::State::SEEKING: + return "SEEKING"; + case firebolt::rialto::client::MediaPipeline::State::FAILURE: + return "FAILURE"; + case firebolt::rialto::client::MediaPipeline::State::END_OF_STREAM: + return "END_OF_STREAM"; + } + return "UNKNOWN"; +} + +const char *toString(const firebolt::rialto::PlaybackState &state) +{ + switch (state) + { + case firebolt::rialto::PlaybackState::IDLE: + return "IDLE"; + case firebolt::rialto::PlaybackState::PLAYING: + return "PLAYING"; + case firebolt::rialto::PlaybackState::PAUSED: + return "PAUSED"; + case firebolt::rialto::PlaybackState::SEEKING: + return "SEEKING"; + case firebolt::rialto::PlaybackState::SEEK_DONE: + return "SEEK_DONE"; + case firebolt::rialto::PlaybackState::STOPPED: + return "STOPPED"; + case firebolt::rialto::PlaybackState::END_OF_STREAM: + return "END_OF_STREAM"; + case firebolt::rialto::PlaybackState::FAILURE: + return "FAILURE"; + case firebolt::rialto::PlaybackState::UNKNOWN: + return "UNKNOWN"; + } + return "UNKNOWN"; +} + +const char *toString(const firebolt::rialto::NetworkState &state) +{ + switch (state) + { + case firebolt::rialto::NetworkState::IDLE: + return "IDLE"; + case firebolt::rialto::NetworkState::BUFFERING: + return "BUFFERING"; + case firebolt::rialto::NetworkState::BUFFERING_PROGRESS: + return "BUFFERING_PROGRESS"; + case firebolt::rialto::NetworkState::BUFFERED: + return "BUFFERED"; + case firebolt::rialto::NetworkState::STALLED: + return "STALLED"; + case firebolt::rialto::NetworkState::FORMAT_ERROR: + return "FORMAT_ERROR"; + case firebolt::rialto::NetworkState::NETWORK_ERROR: + return "NETWORK_ERROR"; + case firebolt::rialto::NetworkState::DECODE_ERROR: + return "DECODE_ERROR"; + case firebolt::rialto::NetworkState::UNKNOWN: + return "UNKNOWN"; + } + return "UNKNOWN"; +} +} // namespace + +namespace firebolt::rialto +{ +std::shared_ptr IMediaPipelineFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media player factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr MediaPipelineFactory::createMediaPipeline(std::weak_ptr client, + const VideoRequirements &videoRequirements) const +{ + return createMediaPipeline(client, videoRequirements, {}, {}); +} + +std::unique_ptr +MediaPipelineFactory::createMediaPipeline(std::weak_ptr client, + const VideoRequirements &videoRequirements, + std::weak_ptr mediaPipelineIpcFactory, + std::weak_ptr clientController) const +{ + std::unique_ptr mediaPipeline; + try + { + std::shared_ptr mediaPipelineIpcFactoryLocked = mediaPipelineIpcFactory.lock(); + std::shared_ptr clientControllerLocked = clientController.lock(); + firebolt::rialto::client::IClientController &cc = + clientControllerLocked ? *clientControllerLocked + : client::IClientControllerAccessor::instance().getClientController(); + + auto mp{std::make_shared(client, videoRequirements, + mediaPipelineIpcFactoryLocked + ? mediaPipelineIpcFactoryLocked + : client::IMediaPipelineIpcFactory::getFactory(), + common::IMediaFrameWriterFactory::getFactory(), cc)}; + mediaPipeline = std::move(std::make_unique(mp, cc)); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media player, reason: %s", e.what()); + } + + return mediaPipeline; +} + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +MediaPipelineProxy::MediaPipelineProxy(const std::shared_ptr &mediaPipeline, + IClientController &clientController) + : m_mediaPipeline{mediaPipeline}, m_clientController{clientController} +{ + ApplicationState state{ApplicationState::UNKNOWN}; + if (!m_clientController.registerClient(m_mediaPipeline, state)) + { + throw std::runtime_error("Failed to register client with clientController"); + } + m_mediaPipeline->notifyApplicationState(state); +} + +MediaPipelineProxy::~MediaPipelineProxy() +{ + if (!m_clientController.unregisterClient(m_mediaPipeline)) + { + RIALTO_CLIENT_LOG_WARN("Failed to unregister client with clientController"); + } +} + +MediaPipeline::MediaPipeline(std::weak_ptr client, const VideoRequirements &videoRequirements, + const std::shared_ptr &mediaPipelineIpcFactory, + const std::shared_ptr &mediaFrameWriterFactory, + IClientController &clientController) + : m_mediaPipelineClient(client), m_clientController{clientController}, m_currentAppState{ApplicationState::UNKNOWN}, + m_mediaFrameWriterFactory(mediaFrameWriterFactory), m_currentState(State::IDLE) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_mediaPipelineIpc = mediaPipelineIpcFactory->createMediaPipelineIpc(this, videoRequirements); + + if (!m_mediaPipelineIpc) + { + throw std::runtime_error("Media player ipc could not be created"); + } +} + +MediaPipeline::~MediaPipeline() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_mediaPipelineIpc.reset(); +} + +bool MediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->load(type, mimeType, url); +} + +bool MediaPipeline::attachSource(const std::unique_ptr &source) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + // We should not process needDatas while attach source is ongoing + { + std::unique_lock lock{m_attachSourceMutex}; + m_attachingSource = true; + } + + int32_t sourceId = -1; + + bool status = m_mediaPipelineIpc->attachSource(source, sourceId); + if (status) + { + source->setId(sourceId); + m_attachedSources.add(sourceId, source->getType()); + } + + // Unblock needDatas + { + std::unique_lock lock{m_attachSourceMutex}; + m_attachingSource = false; + m_attachSourceCond.notify_all(); + } + return status; +} + +bool MediaPipeline::removeSource(int32_t id) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + m_attachedSources.remove(id); + return m_mediaPipelineIpc->removeSource(id); +} + +bool MediaPipeline::allSourcesAttached() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->allSourcesAttached(); +} + +bool MediaPipeline::play() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->play(); +} + +bool MediaPipeline::pause() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->pause(); +} + +bool MediaPipeline::stop() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_currentState = State::IDLE; + + return m_mediaPipelineIpc->stop(); +} + +bool MediaPipeline::setPlaybackRate(double rate) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->setPlaybackRate(rate); +} + +bool MediaPipeline::setPosition(int64_t position) +{ + switch (m_currentState) + { + case State::PLAYING: + case State::BUFFERING: + case State::SEEKING: + case State::END_OF_STREAM: + { + return handleSetPosition(position); + } + case State::IDLE: + case State::FAILURE: + default: + { + RIALTO_CLIENT_LOG_WARN("SetPosition received in unexpected state '%s'", toString(m_currentState)); + return false; + } + } +} + +bool MediaPipeline::getPosition(int64_t &position) +{ + return m_mediaPipelineIpc->getPosition(position); +} + +bool MediaPipeline::setImmediateOutput(int32_t sourceId, bool immediateOutput) +{ + return m_mediaPipelineIpc->setImmediateOutput(sourceId, immediateOutput); +} + +bool MediaPipeline::getImmediateOutput(int32_t sourceId, bool &immediateOutput) +{ + return m_mediaPipelineIpc->getImmediateOutput(sourceId, immediateOutput); +} + +bool MediaPipeline::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) +{ + return m_mediaPipelineIpc->getStats(sourceId, renderedFrames, droppedFrames); +} + +bool MediaPipeline::handleSetPosition(int64_t position) +{ + // needData requests no longer valid + { + std::lock_guard lock{m_needDataRequestMapMutex}; + m_needDataRequestMap.clear(); + } + return m_mediaPipelineIpc->setPosition(position); +} + +bool MediaPipeline::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->setVideoWindow(x, y, width, height); +} + +bool MediaPipeline::haveData(MediaSourceStatus status, uint32_t needDataRequestId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + switch (m_currentState) + { + case State::BUFFERING: + case State::PLAYING: + { + return handleHaveData(status, needDataRequestId); + } + case State::SEEKING: + { + RIALTO_CLIENT_LOG_INFO("HaveData received while seeking, discarding NeedData request %u", needDataRequestId); + discardNeedDataRequest(needDataRequestId); + return true; + } + case State::IDLE: + case State::END_OF_STREAM: + case State::FAILURE: + default: + { + RIALTO_CLIENT_LOG_WARN("HaveData received in unexpected state '%s', discarding NeedData request %u", + toString(m_currentState), needDataRequestId); + discardNeedDataRequest(needDataRequestId); + return false; + } + } +} + +bool MediaPipeline::handleHaveData(MediaSourceStatus status, uint32_t needDataRequestId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + std::shared_ptr needDataRequest; + + // Find the needDataRequest for this needDataRequestId + // The needData request can be cancelled from another thread + { + std::lock_guard lock{m_needDataRequestMapMutex}; + + auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId); + if (needDataRequestIt == m_needDataRequestMap.end()) + { + // Return success here as the data written is just ignored + RIALTO_CLIENT_LOG_WARN("Could not find need data request, with id %u", needDataRequestId); + return true; + } + + needDataRequest = needDataRequestIt->second; + m_needDataRequestMap.erase(needDataRequestIt); + } + if (m_attachedSources.isFlushing(needDataRequest->sourceId)) + { + RIALTO_CLIENT_LOG_WARN("Source %d is flushing. Ignoring need data request, with id %u", + needDataRequest->sourceId, needDataRequestId); + return true; + } + + uint32_t numFrames = needDataRequest->frameWriter ? needDataRequest->frameWriter->getNumFrames() : 0; + return m_mediaPipelineIpc->haveData(status, numFrames, needDataRequestId); +} + +AddSegmentStatus MediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + if (nullptr == mediaSegment || nullptr == mediaSegment->getData()) + { + return AddSegmentStatus::ERROR; + } + + std::lock_guard lock{m_needDataRequestMapMutex}; + auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId); + if (needDataRequestIt == m_needDataRequestMap.end()) + { + RIALTO_CLIENT_LOG_ERROR("Could not find need data request, with id %u", needDataRequestId); + return AddSegmentStatus::ERROR; + } + + std::shared_ptr needDataRequest = needDataRequestIt->second; + std::shared_ptr shmHandle = m_clientController.getSharedMemoryHandle(); + if (nullptr == shmHandle || nullptr == shmHandle->getShm()) + { + RIALTO_CLIENT_LOG_ERROR("Shared buffer no longer valid"); + return AddSegmentStatus::ERROR; + } + + // This block of code is only for playready apps using rialto c++ interface + // Widevine apps and playready apps using rialto-ocdm set MediaSegment::keyId earlier + if (mediaSegment->isEncrypted()) + { + auto keyId = KeyIdMap::instance().get(mediaSegment->getMediaKeySessionId()); + if (!keyId.empty() && mediaSegment->getKeyId().empty()) + { + RIALTO_CLIENT_LOG_DEBUG("Adding Playready keyID to media segment"); + mediaSegment->setKeyId(keyId); + } + } + + if (!needDataRequest->frameWriter) + { + if (firebolt::rialto::MediaSourceType::UNKNOWN != mediaSegment->getType()) + { + needDataRequest->frameWriter = + m_mediaFrameWriterFactory->createFrameWriter(shmHandle->getShm(), needDataRequest->shmInfo); + } + else + { + RIALTO_CLIENT_LOG_ERROR("Unrecognised type %u", static_cast(mediaSegment->getType())); + return AddSegmentStatus::ERROR; + } + + if (!needDataRequest->frameWriter) + { + RIALTO_CLIENT_LOG_ERROR("Could not create frame writer"); + return AddSegmentStatus::ERROR; + } + } + + return needDataRequest->frameWriter->writeFrame(mediaSegment); +} + +bool MediaPipeline::renderFrame() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->renderFrame(); +} + +bool MediaPipeline::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->setVolume(targetVolume, volumeDuration, easeType); +} + +bool MediaPipeline::getVolume(double ¤tVolume) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->getVolume(currentVolume); +} + +bool MediaPipeline::setMute(int32_t sourceId, bool mute) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->setMute(sourceId, mute); +} + +bool MediaPipeline::getMute(int32_t sourceId, bool &mute) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->getMute(sourceId, mute); +} + +bool MediaPipeline::setTextTrackIdentifier(const std::string &textTrackIdentifier) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->setTextTrackIdentifier(textTrackIdentifier); +} + +bool MediaPipeline::getTextTrackIdentifier(std::string &textTrackIdentifier) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->getTextTrackIdentifier(textTrackIdentifier); +} + +bool MediaPipeline::setLowLatency(bool lowLatency) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->setLowLatency(lowLatency); +} + +bool MediaPipeline::setSync(bool sync) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->setSync(sync); +} + +bool MediaPipeline::getSync(bool &sync) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->getSync(sync); +} + +bool MediaPipeline::setSyncOff(bool syncOff) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->setSyncOff(syncOff); +} + +bool MediaPipeline::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->setStreamSyncMode(sourceId, streamSyncMode); +} + +bool MediaPipeline::getStreamSyncMode(int32_t &streamSyncMode) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + return m_mediaPipelineIpc->getStreamSyncMode(streamSyncMode); +} + +bool MediaPipeline::flush(int32_t sourceId, bool resetTime, bool &async) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + std::unique_lock flushLock{m_flushMutex}; + if (m_mediaPipelineIpc->flush(sourceId, resetTime, async)) + { + m_attachedSources.setFlushing(sourceId, true); + flushLock.unlock(); + + // Clear all need datas for flushed source + std::lock_guard lock{m_needDataRequestMapMutex}; + for (auto it = m_needDataRequestMap.begin(); it != m_needDataRequestMap.end();) + { + if (it->second->sourceId == sourceId) + { + it = m_needDataRequestMap.erase(it); + } + else + { + ++it; + } + } + return true; + } + return false; +} + +bool MediaPipeline::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition); +} + +bool MediaPipeline::setSubtitleOffset(int32_t sourceId, int64_t position) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->setSubtitleOffset(sourceId, position); +} + +bool MediaPipeline::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->processAudioGap(position, duration, discontinuityGap, audioAac); +} + +bool MediaPipeline::setBufferingLimit(uint32_t limitBufferingMs) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->setBufferingLimit(limitBufferingMs); +} + +bool MediaPipeline::getBufferingLimit(uint32_t &limitBufferingMs) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->getBufferingLimit(limitBufferingMs); +} + +bool MediaPipeline::setUseBuffering(bool useBuffering) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->setUseBuffering(useBuffering); +} + +bool MediaPipeline::getUseBuffering(bool &useBuffering) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->getUseBuffering(useBuffering); +} + +bool MediaPipeline::switchSource(const std::unique_ptr &source) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineIpc->switchSource(source); +} + +void MediaPipeline::discardNeedDataRequest(uint32_t needDataRequestId) +{ + // Find the needDataRequest for this needDataRequestId + // The needData request can be cancelled from another thread + { + std::lock_guard lock{m_needDataRequestMapMutex}; + + auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId); + if (needDataRequestIt == m_needDataRequestMap.end()) + { + RIALTO_CLIENT_LOG_INFO("Could not find need data request, with id %u", needDataRequestId); + } + else + { + RIALTO_CLIENT_LOG_INFO("Discarding need data request with id %u", needDataRequestId); + m_needDataRequestMap.erase(needDataRequestIt); + } + } +} + +std::weak_ptr MediaPipeline::getClient() +{ + return m_mediaPipelineClient; +} + +void MediaPipeline::updateState(NetworkState state) +{ + State newState = m_currentState; + + switch (state) + { + case NetworkState::BUFFERING: + case NetworkState::BUFFERING_PROGRESS: + case NetworkState::STALLED: + { + newState = State::BUFFERING; + break; + } + case NetworkState::FORMAT_ERROR: + case NetworkState::NETWORK_ERROR: + case NetworkState::DECODE_ERROR: + { + newState = State::FAILURE; + break; + } + default: + { + break; + } + } + + RIALTO_CLIENT_LOG_DEBUG("Received network state '%s', old state '%s', new state '%s'", toString(state), + toString(m_currentState), toString(newState)); + m_currentState = newState; +} + +void MediaPipeline::updateState(PlaybackState state) +{ + State newState = m_currentState; + + switch (state) + { + case PlaybackState::PLAYING: + case PlaybackState::PAUSED: + { + newState = State::PLAYING; + break; + } + case PlaybackState::SEEKING: + { + newState = State::SEEKING; + break; + } + case PlaybackState::STOPPED: + { + newState = State::IDLE; + break; + } + case PlaybackState::SEEK_DONE: + { + newState = State::BUFFERING; + break; + } + case PlaybackState::END_OF_STREAM: + { + newState = State::END_OF_STREAM; + break; + } + case PlaybackState::FAILURE: + { + newState = State::FAILURE; + break; + } + default: + { + break; + } + } + + RIALTO_CLIENT_LOG_DEBUG("Received playback state '%s', old state '%s', new state '%s'", toString(state), + toString(m_currentState), toString(newState)); + m_currentState = newState; +} + +void MediaPipeline::notifyPlaybackState(PlaybackState state) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + updateState(state); + + std::shared_ptr client = m_mediaPipelineClient.lock(); + if (client) + { + client->notifyPlaybackState(state); + } +} + +void MediaPipeline::notifyPosition(int64_t position) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + std::shared_ptr client = m_mediaPipelineClient.lock(); + if (client) + { + client->notifyPosition(position); + } +} + +void MediaPipeline::notifyNetworkState(NetworkState state) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + updateState(state); + + std::shared_ptr client = m_mediaPipelineClient.lock(); + if (client) + { + client->notifyNetworkState(state); + } +} + +void MediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId, + const std::shared_ptr &shmInfo) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + // If attach source is ongoing wait till it has completed so that all sources are attached + { + std::unique_lock lock{m_attachSourceMutex}; + if (m_attachingSource) + m_attachSourceCond.wait(lock, [this] { return !m_attachingSource; }); + } + + if (MediaSourceType::UNKNOWN == m_attachedSources.getType(sourceId)) + { + RIALTO_CLIENT_LOG_WARN("NeedMediaData received for unknown source %d, ignoring request id %u", sourceId, + requestId); + return; + } + if (m_attachedSources.isFlushing(sourceId)) + { + RIALTO_CLIENT_LOG_WARN("NeedMediaData received for flushing source %d, ignoring request id %u", sourceId, + requestId); + return; + } + + switch (m_currentState) + { + case State::BUFFERING: + case State::PLAYING: + { + std::shared_ptr needDataRequest = std::make_shared(); + needDataRequest->sourceId = sourceId; + needDataRequest->shmInfo = shmInfo; + + { + std::lock_guard lock{m_needDataRequestMapMutex}; + if (ApplicationState::RUNNING != m_currentAppState) + { + RIALTO_CLIENT_LOG_INFO("NeedMediaData received in state != RUNNING, ignoring request id %u", requestId); + break; + } + m_needDataRequestMap[requestId] = needDataRequest; + } + + std::shared_ptr client = m_mediaPipelineClient.lock(); + if (client) + { + client->notifyNeedMediaData(sourceId, frameCount, requestId, nullptr); + } + + break; + } + case State::SEEKING: + { + RIALTO_CLIENT_LOG_INFO("NeedMediaData received while seeking, ignoring request id %u", requestId); + break; + } + case State::IDLE: + case State::END_OF_STREAM: + case State::FAILURE: + default: + { + RIALTO_CLIENT_LOG_WARN("NeedMediaData received in unexpected state '%s', ignoring request id %u", + toString(m_currentState), requestId); + break; + } + } +} + +void MediaPipeline::notifyApplicationState(ApplicationState state) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + std::lock_guard lock{m_needDataRequestMapMutex}; + m_currentAppState = state; + if (ApplicationState::RUNNING != state) + { + // If shared memory in use, wait for it to finish before returning + m_needDataRequestMap.clear(); + } +} + +void MediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + std::shared_ptr client = m_mediaPipelineClient.lock(); + if (client) + { + client->notifyQos(sourceId, qosInfo); + } +} + +void MediaPipeline::notifyBufferUnderflow(int32_t sourceId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + std::shared_ptr client = m_mediaPipelineClient.lock(); + if (client) + { + client->notifyBufferUnderflow(sourceId); + } +} + +void MediaPipeline::notifyPlaybackError(int32_t sourceId, PlaybackError error) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + std::shared_ptr client = m_mediaPipelineClient.lock(); + if (client) + { + client->notifyPlaybackError(sourceId, error); + } +} + +void MediaPipeline::notifySourceFlushed(int32_t sourceId) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + { + std::lock_guard lock{m_flushMutex}; + m_attachedSources.setFlushing(sourceId, false); + } + std::shared_ptr client = m_mediaPipelineClient.lock(); + if (client) + { + client->notifySourceFlushed(sourceId); + } + + State expected = State::END_OF_STREAM; + m_currentState.compare_exchange_strong(expected, State::BUFFERING); +} + +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/MediaPipelineCapabilities.cpp b/middleware/rialto-client/media/client/main/source/MediaPipelineCapabilities.cpp new file mode 100644 index 000000000..f5a20aea8 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/MediaPipelineCapabilities.cpp @@ -0,0 +1,111 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "IMediaPipelineCapabilitiesIpcFactory.h" +#include "MediaPipelineCapabilities.h" +#include "RialtoClientLogging.h" + +namespace firebolt::rialto +{ +std::shared_ptr IMediaPipelineCapabilitiesFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media pipeline capabilities factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr MediaPipelineCapabilitiesFactory::createMediaPipelineCapabilities() const +{ + std::unique_ptr mediaPipelineCapabilities; + try + { + mediaPipelineCapabilities = std::make_unique( + client::IMediaPipelineCapabilitiesIpcFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the media pipeline capabilities, reason: %s", e.what()); + } + + return mediaPipelineCapabilities; +} + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +MediaPipelineCapabilities::MediaPipelineCapabilities( + const std::shared_ptr &MediaPipelineCapabilitiesIpcFactory) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_mediaPipelineCapabilitiesIpc = MediaPipelineCapabilitiesIpcFactory->createMediaPipelineCapabilitiesIpc(); + if (!m_mediaPipelineCapabilitiesIpc) + { + throw std::runtime_error("Media pipeline capabilities ipc could not be created"); + } +} + +MediaPipelineCapabilities::~MediaPipelineCapabilities() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_mediaPipelineCapabilitiesIpc.reset(); +} + +std::vector MediaPipelineCapabilities::getSupportedMimeTypes(MediaSourceType sourceType) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineCapabilitiesIpc->getSupportedMimeTypes(sourceType); +} + +bool MediaPipelineCapabilities::isMimeTypeSupported(const std::string &mimeType) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineCapabilitiesIpc->isMimeTypeSupported(mimeType); +} + +std::vector MediaPipelineCapabilities::getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineCapabilitiesIpc->getSupportedProperties(mediaType, propertyNames); +} + +bool MediaPipelineCapabilities::isVideoMaster(bool &isVideoMaster) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_mediaPipelineCapabilitiesIpc->isVideoMaster(isVideoMaster); +} +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/SharedMemoryHandle.cpp b/middleware/rialto-client/media/client/main/source/SharedMemoryHandle.cpp new file mode 100644 index 000000000..e632dc6fe --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/SharedMemoryHandle.cpp @@ -0,0 +1,76 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SharedMemoryHandle.h" +#include "RialtoClientLogging.h" +#include +#include +#include +#include + +namespace firebolt::rialto::client +{ +SharedMemoryHandle::SharedMemoryHandle(std::int32_t shmFd, std::uint32_t shmBufferLen) + : m_shmFd{shmFd}, m_shmBufferLen{shmBufferLen} +{ + if ((-1 == m_shmFd) || (0U == m_shmBufferLen)) + { + throw std::runtime_error("Shared buffer invalid"); + } + + m_shmBuffer = reinterpret_cast(mmap(NULL, m_shmBufferLen, PROT_READ | PROT_WRITE, MAP_SHARED, m_shmFd, 0)); + if (MAP_FAILED == m_shmBuffer) + { + close(m_shmFd); + m_shmFd = -1; + m_shmBuffer = nullptr; + m_shmBufferLen = 0U; + throw std::runtime_error("Failed to map databuffer: " + std::string(strerror(errno))); + } +} + +SharedMemoryHandle::~SharedMemoryHandle() +{ + if (-1 == m_shmFd) + { + RIALTO_CLIENT_LOG_WARN("Shared memory not initalised"); + return; + } + + int32_t ret = munmap(m_shmBuffer, m_shmBufferLen); + if (-1 == ret) + { + RIALTO_CLIENT_LOG_ERROR("Failed to unmap databuffer: %s", strerror(errno)); + } + else + { + RIALTO_CLIENT_LOG_INFO("Shared buffer was successfully terminated"); + } + + close(m_shmFd); + m_shmBuffer = nullptr; + m_shmFd = -1; + m_shmBufferLen = 0U; +} + +std::uint8_t *SharedMemoryHandle::getShm() const +{ + return m_shmBuffer; +} +} // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/WebAudioPlayer.cpp b/middleware/rialto-client/media/client/main/source/WebAudioPlayer.cpp new file mode 100644 index 000000000..d4a504245 --- /dev/null +++ b/middleware/rialto-client/media/client/main/source/WebAudioPlayer.cpp @@ -0,0 +1,280 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "IWebAudioPlayerIpc.h" +#include "IWebAudioPlayerIpcClient.h" +#include "RialtoClientLogging.h" +#include "WebAudioPlayer.h" +#include "WebAudioPlayerProxy.h" + +namespace firebolt::rialto +{ +std::shared_ptr IWebAudioPlayerFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr +WebAudioPlayerFactory::createWebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config) const +{ + return createWebAudioPlayer(client, audioMimeType, priority, config, {}, {}); +} + +std::unique_ptr +WebAudioPlayerFactory::createWebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config, + std::weak_ptr webAudioPlayerIpcFactory, + std::weak_ptr clientController) const +{ + std::unique_ptr webAudioPlayer; + try + { + std::shared_ptr webAudioPlayerIpcFactoryLocked = + webAudioPlayerIpcFactory.lock(); + std::shared_ptr clientControllerLocked = clientController.lock(); + client::IClientController &cc = clientControllerLocked + ? *clientControllerLocked + : client::IClientControllerAccessor::instance().getClientController(); + + auto wap{std::make_shared(client, audioMimeType, priority, config, + webAudioPlayerIpcFactoryLocked + ? webAudioPlayerIpcFactoryLocked + : client::IWebAudioPlayerIpcFactory::getFactory(), + cc)}; + webAudioPlayer = std::make_unique(wap, cc); + } + catch (const std::exception &e) + { + RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player, reason: %s", e.what()); + } + + return webAudioPlayer; +} + +WebAudioPlayerProxy::WebAudioPlayerProxy(const std::shared_ptr &ptr, + client::IClientController &clientController) + : m_webAudioPlayer(ptr), m_clientController{clientController} +{ + ApplicationState state{ApplicationState::UNKNOWN}; + if (!m_clientController.registerClient(m_webAudioPlayer, state)) + { + throw std::runtime_error("Failed to register client with clientController"); + } + m_webAudioPlayer->notifyApplicationState(state); +} + +WebAudioPlayerProxy::~WebAudioPlayerProxy() +{ + if (!m_clientController.unregisterClient(m_webAudioPlayer)) + { + RIALTO_CLIENT_LOG_WARN("Failed to unregister client with clientController"); + } +} + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::client +{ +WebAudioPlayer::WebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr webAudioConfig, + const std::shared_ptr &webAudioPlayerIpcFactory, + IClientController &clientController) + : m_webAudioPlayerClient(client), m_clientController{clientController}, m_bytesPerFrame{0}, + m_currentAppState{ApplicationState::UNKNOWN} +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + if (audioMimeType == "audio/x-raw") + { + std::shared_ptr kConfig = webAudioConfig.lock(); + if (!kConfig) + { + throw std::runtime_error("Config is null for 'audio/x-raw'"); + } + m_bytesPerFrame = kConfig->pcm.channels * (kConfig->pcm.sampleSize / CHAR_BIT); + if (m_bytesPerFrame == 0) + { + throw std::runtime_error("Bytes per frame cannot be 0, channels " + std::to_string(kConfig->pcm.channels) + + ", sampleSize " + std::to_string(kConfig->pcm.sampleSize)); + } + } + + if (!webAudioPlayerIpcFactory) + { + throw std::runtime_error("Web audio player ipc factory could not be null"); + } + + m_webAudioPlayerIpc = + webAudioPlayerIpcFactory->createWebAudioPlayerIpc(this, audioMimeType, priority, webAudioConfig); + if (!m_webAudioPlayerIpc) + { + throw std::runtime_error("Web audio player ipc could not be created"); + } +} + +WebAudioPlayer::~WebAudioPlayer() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + m_webAudioPlayerIpc.reset(); +} + +bool WebAudioPlayer::play() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_webAudioPlayerIpc->play(); +} + +bool WebAudioPlayer::pause() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_webAudioPlayerIpc->pause(); +} + +bool WebAudioPlayer::setEos() +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_webAudioPlayerIpc->setEos(); +} + +bool WebAudioPlayer::getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + std::lock_guard bufLocker(m_bufLock); + if (!m_webAudioShmInfo) + { + m_webAudioShmInfo = std::make_shared(); + } + return m_webAudioPlayerIpc->getBufferAvailable(availableFrames, m_webAudioShmInfo); +} + +bool WebAudioPlayer::getBufferDelay(uint32_t &delayFrames) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_webAudioPlayerIpc->getBufferDelay(delayFrames); +} + +bool WebAudioPlayer::writeBuffer(const uint32_t numberOfFrames, void *data) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + std::lock_guard bufLocker(m_bufLock); + if (!m_webAudioShmInfo) + { + RIALTO_CLIENT_LOG_ERROR("Web audio shared info is null!"); + return false; + } + + uint32_t dataLength = numberOfFrames * m_bytesPerFrame; + uint32_t availableDataLength = m_webAudioShmInfo->lengthMain + m_webAudioShmInfo->lengthWrap; + if (dataLength > availableDataLength) + { + RIALTO_CLIENT_LOG_ERROR("The number of frames to write exceeds the available space!"); + return false; + } + + if (ApplicationState::RUNNING != m_currentAppState) + { + RIALTO_CLIENT_LOG_ERROR("Current ApplicationState is not RUNNING!"); + return false; + } + + std::shared_ptr shmHandle = m_clientController.getSharedMemoryHandle(); + if (nullptr == shmHandle || nullptr == shmHandle->getShm()) + { + RIALTO_CLIENT_LOG_ERROR("Shared buffer no longer valid"); + return false; + } + + if (dataLength > m_webAudioShmInfo->lengthMain) + { + std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetMain, data, m_webAudioShmInfo->lengthMain); + std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetWrap, + reinterpret_cast(data) + m_webAudioShmInfo->lengthMain, + dataLength - m_webAudioShmInfo->lengthMain); + } + else + { + std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetMain, data, dataLength); + } + return m_webAudioPlayerIpc->writeBuffer(numberOfFrames); +} + +bool WebAudioPlayer::getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_webAudioPlayerIpc->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay); +} + +bool WebAudioPlayer::setVolume(double volume) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_webAudioPlayerIpc->setVolume(volume); +} + +bool WebAudioPlayer::getVolume(double &volume) +{ + RIALTO_CLIENT_LOG_DEBUG("entry:"); + + return m_webAudioPlayerIpc->getVolume(volume); +} + +std::weak_ptr WebAudioPlayer::getClient() +{ + return m_webAudioPlayerClient; +} + +void WebAudioPlayer::notifyState(WebAudioPlayerState state) +{ + std::shared_ptr client = m_webAudioPlayerClient.lock(); + if (client) + { + client->notifyState(state); + } +} + +void WebAudioPlayer::notifyApplicationState(ApplicationState state) +{ + m_currentAppState = state; +} + +}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/common/CMakeLists.txt b/middleware/rialto-client/media/common/CMakeLists.txt new file mode 100644 index 000000000..b393eec72 --- /dev/null +++ b/middleware/rialto-client/media/common/CMakeLists.txt @@ -0,0 +1,77 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +# Find includes in corresponding build directories +set( CMAKE_INCLUDE_CURRENT_DIR ON ) + +add_library( + RialtoPlayerCommon + STATIC + + source/ByteWriter.cpp + source/MediaFrameWriterFactory.cpp + source/MediaFrameWriterV1.cpp + source/MediaFrameWriterV2.cpp + source/SchemaVersion.cpp + source/TypeConverters.cpp + ) + +set_property ( + TARGET + RialtoPlayerCommon + PROPERTY POSITION_INDEPENDENT_CODE ON +) + +target_include_directories( + RialtoPlayerCommon + + PUBLIC + interface + + PRIVATE + include + $ + $ + $ + $ + ) + +set ( + RIALTO_PLAYER_COMMON_PUBLIC_HEADERS + interface/ShmCommon.h + interface/IMediaFrameWriter.h +) + +install ( + FILES ${RIALTO_PLAYER_COMMON_PUBLIC_HEADERS} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rialto +) + +target_link_libraries ( + RialtoPlayerCommon + + PRIVATE + RialtoLogging + RialtoProtobuf + ) diff --git a/middleware/rialto-client/media/common/include/ByteWriter.h b/middleware/rialto-client/media/common/include/ByteWriter.h new file mode 100644 index 000000000..c3931d7fd --- /dev/null +++ b/middleware/rialto-client/media/common/include/ByteWriter.h @@ -0,0 +1,102 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_BYTE_WRITER_H_ +#define FIREBOLT_RIALTO_COMMON_BYTE_WRITER_H_ + +#include +#include +#include + +namespace firebolt::rialto::common +{ +class ByteWriter +{ +public: + /** + * @brief Virtual destructor + */ + virtual ~ByteWriter() {} + /** + * @brief Write a byte to the buffer + * + * @param[in] buf : the buffer pointer. + * @param[in] off : the offset within the buffer. + * @param[in] byte : the byte to write; + * + * @retval the new offset. + */ + virtual size_t writeByte(uint8_t *buf, size_t off, uint8_t byte) const; + + /** + * @brief Writes a number of bytes to the buffer + * + * @param[in] buf : the buffer pointer. + * @param[in] off : the offset within the buffer. + * @param[in] bytes : the bytes to write. + * @param[in] count : the number of bytes to write. + * + * @retval the new offset. + */ + virtual size_t writeBytes(uint8_t *buf, size_t off, const uint8_t *bytes, size_t count) const; + /** + * @brief Fills the buffer with a number of bytes. + * + * @param[in] buf : the buffer pointer. + * @param[in] off : the offset within the buffer. + * @param[in] byte : the byte to write. + * @param[in] count : the number of bytes to write. + * + * @retval the new offset. + */ + virtual size_t fillBytes(uint8_t *buf, size_t off, uint8_t byte, size_t count) const; + /** + * @brief Write a 32 bit unsigned int to the buffer + * + * @param[in] buf : the buffer pointer. + * @param[in] off : the offset within the buffer. + * @param[in] val : the value to write; + * + * @retval the new offset. + */ + virtual size_t writeUint32(uint8_t *buf, size_t off, uint32_t val) const; + /** + * @brief Write a 64 bit signed int to the buffer + * + * @param[in] buf : the buffer pointer. + * @param[in] off : the offset within the buffer. + * @param[in] val : the value to write; + * + * @retval the new offset. + */ + virtual size_t writeInt64(uint8_t *buf, size_t off, int64_t val) const; + /** + * @brief Write a C string to the buffer including terminating null. + * + * @param[in] buf : the buffer pointer. + * @param[in] off : the offset within the buffer. + * @param[in] str : the str to write; + * + * @retval the new offset. + */ + virtual size_t writeCString(uint8_t *buf, size_t off, const char *str) const; +}; +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_BYTE_WRITER_H_ diff --git a/middleware/rialto-client/media/common/include/MediaFrameWriterFactory.h b/middleware/rialto-client/media/common/include/MediaFrameWriterFactory.h new file mode 100644 index 000000000..6597b0917 --- /dev/null +++ b/middleware/rialto-client/media/common/include/MediaFrameWriterFactory.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITER_FACTORY_H_ +#define FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITER_FACTORY_H_ + +#include "IMediaFrameWriter.h" +#include + +namespace firebolt::rialto::common +{ +/** + * @brief IMediaFrameWriter factory class definition. + */ +class MediaFrameWriterFactory : public IMediaFrameWriterFactory +{ +public: + MediaFrameWriterFactory(); + std::unique_ptr createFrameWriter(uint8_t *shmBuffer, + const std::shared_ptr &shminfo) override; + +private: + int m_metadataVersion; +}; + +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITER_FACTORY_H_ diff --git a/middleware/rialto-client/media/common/include/MediaFrameWriterV1.h b/middleware/rialto-client/media/common/include/MediaFrameWriterV1.h new file mode 100644 index 000000000..8174ef76a --- /dev/null +++ b/middleware/rialto-client/media/common/include/MediaFrameWriterV1.h @@ -0,0 +1,147 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV1_H_ +#define FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV1_H_ + +#include "ByteWriter.h" +#include "IMediaFrameWriter.h" +#include +#include + +namespace firebolt::rialto::common +{ +/** + * @brief The definition of the MediaFrameWriterV1. + */ +class MediaFrameWriterV1 : public IMediaFrameWriter +{ +public: + /** + * @brief The constructor. + * + * @param[in] shmBuffer : The shared buffer pointer. + * @param[in] shmInfo : The information for populating the shared memory. + */ + MediaFrameWriterV1(uint8_t *shmBuffer, const std::shared_ptr &shminfo); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaFrameWriterV1() {} + + /** + * @brief Write the frame data. + * + * @param[in] data : Media Segment data. + * + * @retval true on success. + */ + AddSegmentStatus writeFrame(const std::unique_ptr &data) override; + + /** + * @brief Gets number of written frames + * + * @retval number of written frames + */ + uint32_t getNumFrames() override { return m_numFrames; } + + /** + * @brief The version of metadata this object shall write. + */ + static const uint32_t m_kMetadataVersion = 1U; + + /** + * @brief The size of the encryption metadata set if the frame is encrypted. + */ + static const uint32_t m_kEncryptionMetadataSizeBytes = 32U; + +private: + /** + * @brief Pointer to the shared memory buffer. + */ + uint8_t *m_shmBuffer; + + /** + * @brief The maximum amout of media data that can be written. + */ + const uint32_t m_kMaxMediaBytes; + + /** + * @brief The maximum amout of metadata the shared buffer can hold. + */ + const uint32_t m_kMaxMetadataBytes; + + /** + * @brief The amount of metadata bytes written to the shared buffer. + */ + uint32_t m_metadataBytesWritten; + + /** + * @brief The amount of media bytes written to the shared buffer. + */ + uint32_t m_mediaBytesWritten; + + /** + * @brief The offset of the shared memory to write the data. + */ + uint32_t m_mediaDataOffset; + + /** + * @brief The offset of the shared memory to write the metadata. + */ + uint32_t m_metadataOffset; + + /** + * @brief ByteWriter object. + */ + ByteWriter m_bytewriter; + + uint32_t m_numFrames = 0; + + /** + * @brief Write the generic frame meta data. + * + * @param[in] data : Media Segment data. + * + * @retval true on success. + */ + bool writeMetaDataGeneric(const std::unique_ptr &data); + + /** + * @brief Write the generic frame meta data. + * + * @param[in] data : Media Segment data. + * + * @retval true on success. + */ + bool writeMetaDataTypeSpecific(const std::unique_ptr &data); + + /** + * @brief Write the sample data. + * + * @param[in] data : Media Segment data. + * + * @retval true on success. + */ + bool writeData(const std::unique_ptr &data); +}; +}; // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV1_H_ diff --git a/middleware/rialto-client/media/common/include/MediaFrameWriterV2.h b/middleware/rialto-client/media/common/include/MediaFrameWriterV2.h new file mode 100644 index 000000000..cd27b1e78 --- /dev/null +++ b/middleware/rialto-client/media/common/include/MediaFrameWriterV2.h @@ -0,0 +1,111 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV2_H_ +#define FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV2_H_ + +#include "ByteWriter.h" +#include "IMediaFrameWriter.h" +#include "metadata.pb.h" +#include +#include + +namespace firebolt::rialto::common +{ +/** + * @brief The definition of the MediaFrameWriterV2. + */ +class MediaFrameWriterV2 : public IMediaFrameWriter +{ +public: + /** + * @brief The constructor. + * + * @param[in] shmBuffer : The shared buffer pointer. + * @param[in] shmInfo : The information for populating the shared memory. + */ + MediaFrameWriterV2(uint8_t *shmBuffer, const std::shared_ptr &shmInfo); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaFrameWriterV2() = default; + + /** + * @brief Write the frame data. + * + * @param[in] data : Media Segment data. + * + * @retval true on success. + */ + AddSegmentStatus writeFrame(const std::unique_ptr &data) override; + + /** + * @brief Gets number of written frames + * + * @retval number of written frames + */ + uint32_t getNumFrames() override { return m_numFrames; } + +private: + /** + * @brief Builds metadata proto object + * + * @param[in] data : Media Segment data. + * + * @warning Method may throw! + * + * @retval MediaSegmentMetadata proto object + */ + MediaSegmentMetadata buildMetadata(const std::unique_ptr &data) const; + +private: + /** + * @brief ByteWriter object. + */ + ByteWriter m_byteWriter; + + /** + * @brief Pointer to the shared memory buffer. + */ + uint8_t *m_shmBuffer; + + /** + * @brief The maximum amout of data that can be written. + */ + const uint32_t m_kMaxBytes; + + /** + * @brief The amount of media bytes written to the shared buffer. + */ + uint32_t m_bytesWritten; + + /** + * @brief The offset of the shared memory to write the data. + */ + uint32_t m_dataOffset; + + /** + * @brief Number of frames written. + */ + uint32_t m_numFrames; +}; +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV2_H_ diff --git a/middleware/rialto-client/media/common/interface/IMediaFrameWriter.h b/middleware/rialto-client/media/common/interface/IMediaFrameWriter.h new file mode 100644 index 000000000..e92051bdb --- /dev/null +++ b/middleware/rialto-client/media/common/interface/IMediaFrameWriter.h @@ -0,0 +1,99 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_I_MEDIA_FRAME_WRITER_H_ +#define FIREBOLT_RIALTO_COMMON_I_MEDIA_FRAME_WRITER_H_ + +#include + +#include +#include + +#include "IMediaPipeline.h" +#include +#include + +namespace firebolt::rialto::common +{ +class IMediaFrameWriter; + +/** + * @brief IMediaFrameWriter factory class, returns a concrete implementation of IMediaFrameWriter + */ +class IMediaFrameWriterFactory +{ +public: + IMediaFrameWriterFactory() = default; + virtual ~IMediaFrameWriterFactory() = default; + + /** + * @brief Gets the IMediaFrameWriterFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Creates a IMediaFrameWriter object. + * + * @param[in] shmBuffer : The shared buffer pointer. + * @param[in] shmInfo : The information for populating the shared memory. + * + * @retval the new media frame writer audio instance or null on error. + */ + virtual std::unique_ptr createFrameWriter(uint8_t *shmBuffer, + const std::shared_ptr &shminfo) = 0; +}; + +/** + * @brief The definition of the IMediaFrameWriter interface. + * + * This interface defines the media frame writer APIs that are used to write data the shared memory. + */ +class IMediaFrameWriter +{ +public: + IMediaFrameWriter() = default; + virtual ~IMediaFrameWriter() = default; + + IMediaFrameWriter(const IMediaFrameWriter &) = delete; + IMediaFrameWriter &operator=(const IMediaFrameWriter &) = delete; + IMediaFrameWriter(IMediaFrameWriter &&) = delete; + IMediaFrameWriter &operator=(IMediaFrameWriter &&) = delete; + + /** + * @brief Write the frame data. + * + * @param[in] data : Media Segment data. + * + * @retval true on success. + */ + virtual AddSegmentStatus writeFrame(const std::unique_ptr &data) = 0; + + /** + * @brief Gets number of written frames + * + * @retval number of written frames + */ + virtual uint32_t getNumFrames() = 0; +}; + +}; // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_I_MEDIA_FRAME_WRITER_H_ diff --git a/middleware/rialto-client/media/common/interface/SchemaVersion.h b/middleware/rialto-client/media/common/interface/SchemaVersion.h new file mode 100644 index 000000000..ada394ba2 --- /dev/null +++ b/middleware/rialto-client/media/common/interface/SchemaVersion.h @@ -0,0 +1,51 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_SCHEMA_VERSION_H_ +#define FIREBOLT_RIALTO_COMMON_SCHEMA_VERSION_H_ + +#include +#include + +namespace firebolt::rialto::common +{ +class SchemaVersion +{ +public: + SchemaVersion(std::uint32_t major, std::uint32_t minor, std::uint32_t patch); + ~SchemaVersion() = default; + + bool operator==(const SchemaVersion &other) const; + bool isCompatible(const SchemaVersion &other) const; + std::string str() const; + std::uint32_t major() const; + std::uint32_t minor() const; + std::uint32_t patch() const; + +private: + std::uint32_t m_major; + std::uint32_t m_minor; + std::uint32_t m_patch; +}; + +// Current schema version, common for server and client. Taken from main CMakeLists.txt file +SchemaVersion getCurrentSchemaVersion(); +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_SCHEMA_VERSION_H_ diff --git a/middleware/rialto-client/media/common/interface/ShmCommon.h b/middleware/rialto-client/media/common/interface/ShmCommon.h new file mode 100644 index 000000000..e24134e26 --- /dev/null +++ b/middleware/rialto-client/media/common/interface/ShmCommon.h @@ -0,0 +1,43 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_SHM_COMMON_H_ +#define FIREBOLT_RIALTO_COMMON_SHM_COMMON_H_ + +#include + +namespace firebolt::rialto::common +{ +/** + * @brief Metadata v1 size per frame in bytes. + */ +const uint32_t VERSION_SIZE_BYTES = 4U; + +/** + * @brief Maximum bytes of extra data. + */ +const uint32_t MAX_EXTRA_DATA_SIZE = 32U; + +/** + * @brief Metadata v1 size per frame in bytes. + */ +const uint32_t METADATA_V1_SIZE_PER_FRAME_BYTES = 104U; +}; // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_SHM_COMMON_H_ diff --git a/middleware/rialto-client/media/common/interface/TypeConverters.h b/middleware/rialto-client/media/common/interface/TypeConverters.h new file mode 100644 index 000000000..e2afddca1 --- /dev/null +++ b/middleware/rialto-client/media/common/interface/TypeConverters.h @@ -0,0 +1,32 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_COMMON_TYPE_CONVERTERS_H_ +#define FIREBOLT_RIALTO_COMMON_TYPE_CONVERTERS_H_ + +#include "MediaCommon.h" + +namespace firebolt::rialto::common +{ +const char *convertMediaSourceType(const MediaSourceType &mediaSourceType); +const char *convertLayout(const Layout &layout); +const char *convertFormat(const Format &format); +} // namespace firebolt::rialto::common + +#endif // FIREBOLT_RIALTO_COMMON_TYPE_CONVERTERS_H_ diff --git a/middleware/rialto-client/media/common/proto/metadata.proto b/middleware/rialto-client/media/common/proto/metadata.proto new file mode 120000 index 000000000..4376a45ba --- /dev/null +++ b/middleware/rialto-client/media/common/proto/metadata.proto @@ -0,0 +1 @@ +../../../proto/metadata.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/common/source/ByteWriter.cpp b/middleware/rialto-client/media/common/source/ByteWriter.cpp new file mode 100644 index 000000000..e1634e57d --- /dev/null +++ b/middleware/rialto-client/media/common/source/ByteWriter.cpp @@ -0,0 +1,76 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ByteWriter.h" +#include + +namespace firebolt::rialto::common +{ +size_t ByteWriter::writeByte(uint8_t *buf, size_t off, uint8_t byte) const +{ + buf[off++] = byte; + return off; +} + +size_t ByteWriter::writeBytes(uint8_t *buf, size_t off, const uint8_t *bytes, size_t count) const +{ + if (count) + memcpy(buf + off, bytes, count); + return off + count; +} + +size_t ByteWriter::fillBytes(uint8_t *buf, size_t off, uint8_t byte, size_t count) const +{ + if (count) + memset(buf + off, byte, count); + return off + count; +} + +size_t ByteWriter::writeUint32(uint8_t *buf, size_t off, uint32_t val) const +{ + buf[off++] = (uint8_t)((val & 0x000000ff) >> 0); + buf[off++] = (uint8_t)((val & 0x0000ff00) >> 8); + buf[off++] = (uint8_t)((val & 0x00ff0000) >> 16); + buf[off++] = (uint8_t)((val & 0xff000000) >> 24); + return off; +} + +size_t ByteWriter::writeInt64(uint8_t *buf, size_t off, int64_t val) const +{ + buf[off++] = (uint8_t)((val & 0x00000000000000ff) >> 0); + buf[off++] = (uint8_t)((val & 0x000000000000ff00) >> 8); + buf[off++] = (uint8_t)((val & 0x0000000000ff0000) >> 16); + buf[off++] = (uint8_t)((val & 0x00000000ff000000) >> 24); + buf[off++] = (uint8_t)((val & 0x000000ff00000000) >> 32); + buf[off++] = (uint8_t)((val & 0x0000ff0000000000) >> 40); + buf[off++] = (uint8_t)((val & 0x00ff000000000000) >> 48); + buf[off++] = (uint8_t)((val & 0xff00000000000000) >> 56); + return off; +} + +size_t ByteWriter::writeCString(uint8_t *buf, size_t off, const char *str) const +{ + while (*str) + { + buf[off++] = *str++; + } + buf[off++] = *str; + return off; +} +} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/MediaFrameWriterFactory.cpp b/middleware/rialto-client/media/common/source/MediaFrameWriterFactory.cpp new file mode 100644 index 000000000..baa142fae --- /dev/null +++ b/middleware/rialto-client/media/common/source/MediaFrameWriterFactory.cpp @@ -0,0 +1,83 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaFrameWriterFactory.h" +#include "MediaFrameWriterV1.h" +#include "MediaFrameWriterV2.h" +#include "RialtoCommonLogging.h" +#include +#include +#include + +namespace +{ +constexpr int kLatestMetadataVersion{2}; +const char *kMetadataEnvVariableName{"RIALTO_METADATA_VERSION"}; +} // namespace + +namespace firebolt::rialto::common +{ +std::shared_ptr IMediaFrameWriterFactory::getFactory() +try +{ + return std::make_shared(); +} +catch (const std::exception &e) +{ + RIALTO_COMMON_LOG_ERROR("Failed to create the media frame writer factory, reason: %s", e.what()); + return nullptr; +} + +MediaFrameWriterFactory::MediaFrameWriterFactory() : m_metadataVersion{kLatestMetadataVersion} +{ + const char *kEnvVar = getenv(kMetadataEnvVariableName); + if (!kEnvVar) + { + return; + } + std::string envVarStr{kEnvVar}; + try + { + m_metadataVersion = std::stoi(envVarStr); + } + catch (const std::exception &e) + { + } + if (m_metadataVersion > kLatestMetadataVersion) + { + m_metadataVersion = kLatestMetadataVersion; + } +} + +std::unique_ptr +MediaFrameWriterFactory::createFrameWriter(uint8_t *shmBuffer, const std::shared_ptr &shmInfo) +try +{ + if (1 == m_metadataVersion) + { + return std::make_unique(shmBuffer, shmInfo); + } + return std::make_unique(shmBuffer, shmInfo); +} +catch (const std::exception &e) +{ + RIALTO_COMMON_LOG_ERROR("Failed to create the frame writer, reason: %s", e.what()); + return nullptr; +} +} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/MediaFrameWriterV1.cpp b/middleware/rialto-client/media/common/source/MediaFrameWriterV1.cpp new file mode 100644 index 000000000..5a5d3cc62 --- /dev/null +++ b/middleware/rialto-client/media/common/source/MediaFrameWriterV1.cpp @@ -0,0 +1,157 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaFrameWriterV1.h" +#include "RialtoCommonLogging.h" + +namespace firebolt::rialto::common +{ +MediaFrameWriterV1::MediaFrameWriterV1(uint8_t *shmBuffer, const std::shared_ptr &shmInfo) + : m_shmBuffer(shmBuffer), m_kMaxMediaBytes(shmInfo->maxMediaBytes), m_kMaxMetadataBytes(shmInfo->maxMetadataBytes), + m_mediaBytesWritten(0U), m_mediaDataOffset(shmInfo->mediaDataOffset), m_metadataOffset(shmInfo->metadataOffset) +{ + RIALTO_COMMON_LOG_INFO("We are using a writer for Metadata V1"); + + // Zero metadata memory + m_bytewriter.fillBytes(m_shmBuffer, m_metadataOffset, 0, m_kMaxMetadataBytes); + + // Set metadata version + m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, m_kMetadataVersion); + + // Track the amount of metadata bytes written + m_metadataBytesWritten = sizeof(m_kMetadataVersion); +} + +AddSegmentStatus MediaFrameWriterV1::writeFrame(const std::unique_ptr &data) +{ + if (!writeMetaDataGeneric(data)) + { + RIALTO_COMMON_LOG_ERROR("Failed to write metadata"); + return AddSegmentStatus::NO_SPACE; + } + if (!writeData(data)) + { + RIALTO_COMMON_LOG_ERROR("Failed to write segment data"); + return AddSegmentStatus::NO_SPACE; + } + if (!writeMetaDataTypeSpecific(data)) + { + return AddSegmentStatus::ERROR; + } + + // Track the amount of metadata bytes written + m_numFrames++; + m_metadataBytesWritten += METADATA_V1_SIZE_PER_FRAME_BYTES; + + return AddSegmentStatus::OK; +} + +bool MediaFrameWriterV1::writeMetaDataGeneric(const std::unique_ptr &data) +{ + // Check that there is enough metadata space for the next frame + if (m_metadataBytesWritten + METADATA_V1_SIZE_PER_FRAME_BYTES > m_kMaxMetadataBytes) + { + RIALTO_COMMON_LOG_ERROR("Not enough space to write metadata, max size %u, current size %u, frame metadata size " + "%u", + m_kMaxMetadataBytes, m_metadataBytesWritten, METADATA_V1_SIZE_PER_FRAME_BYTES); + return false; + } + else + { + m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, m_mediaDataOffset); + m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, data->getDataLength()); + m_metadataOffset = m_bytewriter.writeInt64(m_shmBuffer, m_metadataOffset, data->getTimeStamp()); + m_metadataOffset = m_bytewriter.writeInt64(m_shmBuffer, m_metadataOffset, data->getDuration()); + m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, static_cast(data->getId())); + m_metadataOffset = + m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, static_cast(data->getExtraData().size())); + + if (0 != data->getExtraData().size()) + { + m_metadataOffset = m_bytewriter.writeBytes(m_shmBuffer, m_metadataOffset, + const_cast(&(data->getExtraData()[0])), + data->getExtraData().size()); + } + m_metadataOffset = + m_bytewriter.fillBytes(m_shmBuffer, m_metadataOffset, 0, MAX_EXTRA_DATA_SIZE - data->getExtraData().size()); + + // Not encrypted so skip the encrypted section of the metadata + m_metadataOffset += m_kEncryptionMetadataSizeBytes; + } + + return true; +} + +bool MediaFrameWriterV1::writeMetaDataTypeSpecific(const std::unique_ptr &data) +{ + if (MediaSourceType::AUDIO == data->getType()) + { + IMediaPipeline::MediaSegmentAudio *audioSegment = dynamic_cast(data.get()); + if (audioSegment) + { + m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, + static_cast(audioSegment->getSampleRate())); + m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, + static_cast(audioSegment->getNumberOfChannels())); + } + else + { + RIALTO_COMMON_LOG_ERROR("Failed to get the audio segment"); + return false; + } + } + else if (MediaSourceType::VIDEO == data->getType()) + { + IMediaPipeline::MediaSegmentVideo *videoSegment = dynamic_cast(data.get()); + if (videoSegment) + { + m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, videoSegment->getWidth()); + m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, videoSegment->getHeight()); + } + else + { + RIALTO_COMMON_LOG_ERROR("Failed to get the video segment"); + return false; + } + } + else + { + RIALTO_COMMON_LOG_ERROR("Failed to write type specific metadata - media source type not known"); + return false; + } + return true; +} + +bool MediaFrameWriterV1::writeData(const std::unique_ptr &data) +{ + if (m_mediaBytesWritten + data->getDataLength() > m_kMaxMediaBytes) + { + RIALTO_COMMON_LOG_ERROR("Not enough space to write media data, max size %u, current size %u, size to write %u", + m_kMaxMediaBytes, m_mediaBytesWritten, data->getDataLength()); + return false; + } + + m_mediaDataOffset = m_bytewriter.writeBytes(m_shmBuffer, m_mediaDataOffset, data->getData(), data->getDataLength()); + + // Track the amount of media bytes written + m_mediaBytesWritten += data->getDataLength(); + + return true; +} +}; // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/MediaFrameWriterV2.cpp b/middleware/rialto-client/media/common/source/MediaFrameWriterV2.cpp new file mode 100644 index 000000000..72879b28f --- /dev/null +++ b/middleware/rialto-client/media/common/source/MediaFrameWriterV2.cpp @@ -0,0 +1,215 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaFrameWriterV2.h" +#include "RialtoCommonLogging.h" + +namespace +{ +/** + * @brief The version of metadata this object shall write. + */ +constexpr uint32_t kMetadataVersion = 2U; + +/** + * @brief Convert SegmentAlignment to protobuf object + */ +firebolt::rialto::MediaSegmentMetadata_SegmentAlignment +convertSegmentAlignment(const firebolt::rialto::SegmentAlignment &alignment) +{ + switch (alignment) + { + case firebolt::rialto::SegmentAlignment::UNDEFINED: + { + return firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_UNDEFINED; + } + case firebolt::rialto::SegmentAlignment::NAL: + { + return firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_NAL; + } + case firebolt::rialto::SegmentAlignment::AU: + { + return firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_AU; + } + } + return firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_UNDEFINED; +} + +/** + * @brief Convert CipherMode to protobuf object + */ +firebolt::rialto::MediaSegmentMetadata_CipherMode convertCipherMode(const firebolt::rialto::CipherMode &cipherMode) +{ + switch (cipherMode) + { + case firebolt::rialto::CipherMode::UNKNOWN: + { + return firebolt::rialto::MediaSegmentMetadata_CipherMode_UNKNOWN; + } + case firebolt::rialto::CipherMode::CENC: + { + return firebolt::rialto::MediaSegmentMetadata_CipherMode_CENC; + } + case firebolt::rialto::CipherMode::CBC1: + { + return firebolt::rialto::MediaSegmentMetadata_CipherMode_CBC1; + } + case firebolt::rialto::CipherMode::CENS: + { + return firebolt::rialto::MediaSegmentMetadata_CipherMode_CENS; + } + case firebolt::rialto::CipherMode::CBCS: + { + return firebolt::rialto::MediaSegmentMetadata_CipherMode_CBCS; + } + } + return firebolt::rialto::MediaSegmentMetadata_CipherMode_UNKNOWN; +} + +firebolt::rialto::MediaSegmentMetadata_CodecData_Type convertCodecDataType(const firebolt::rialto::CodecDataType &type) +{ + if (firebolt::rialto::CodecDataType::STRING == type) + { + return firebolt::rialto::MediaSegmentMetadata_CodecData_Type_STRING; + } + return firebolt::rialto::MediaSegmentMetadata_CodecData_Type_BUFFER; +} + +} // namespace + +namespace firebolt::rialto::common +{ +MediaFrameWriterV2::MediaFrameWriterV2(uint8_t *shmBuffer, const std::shared_ptr &shmInfo) + : m_shmBuffer(shmBuffer), m_kMaxBytes(shmInfo->maxMediaBytes), m_bytesWritten(0U), + m_dataOffset(shmInfo->mediaDataOffset), m_numFrames{0} +{ + RIALTO_COMMON_LOG_INFO("We are using a writer for Metadata V2"); + + // Zero memory + m_byteWriter.fillBytes(m_shmBuffer, shmInfo->metadataOffset, 0, shmInfo->maxMetadataBytes); + m_byteWriter.fillBytes(m_shmBuffer, m_dataOffset, 0, m_kMaxBytes); + + // Set metadata version + m_byteWriter.writeUint32(m_shmBuffer, shmInfo->metadataOffset, kMetadataVersion); +} + +AddSegmentStatus MediaFrameWriterV2::writeFrame(const std::unique_ptr &data) +try +{ + auto metadata{buildMetadata(data)}; + size_t metadataSize{metadata.ByteSizeLong()}; + if (m_bytesWritten + sizeof(metadataSize) + metadataSize + data->getDataLength() > m_kMaxBytes) + { + RIALTO_COMMON_LOG_ERROR("Not enough memory available to write MediaSegment"); + return AddSegmentStatus::NO_SPACE; + } + m_dataOffset = m_byteWriter.writeUint32(m_shmBuffer, m_dataOffset, static_cast(metadataSize)); + if (!metadata.SerializeToArray(m_shmBuffer + m_dataOffset, metadataSize)) + { + RIALTO_COMMON_LOG_ERROR("Failed to write type specific metadata - protobuf serialization failed."); + m_dataOffset -= 4; // size of metadata size written in previous step + return AddSegmentStatus::ERROR; + } + m_dataOffset += metadataSize; + m_dataOffset = m_byteWriter.writeBytes(m_shmBuffer, m_dataOffset, data->getData(), data->getDataLength()); + + // Track the amount of bytes written + m_bytesWritten += sizeof(metadataSize) + metadataSize + data->getDataLength(); + ++m_numFrames; + + return AddSegmentStatus::OK; +} +catch (std::exception &e) +{ + RIALTO_COMMON_LOG_ERROR("Failed to write type specific metadata - exception occured"); + return AddSegmentStatus::ERROR; +} + +MediaSegmentMetadata MediaFrameWriterV2::buildMetadata(const std::unique_ptr &data) const +{ + MediaSegmentMetadata metadata; + metadata.set_length(data->getDataLength()); + metadata.set_time_position(data->getTimeStamp()); + metadata.set_sample_duration(data->getDuration()); + metadata.set_stream_id(static_cast(data->getId())); + if (data->getDisplayOffset()) + { + metadata.set_display_offset(data->getDisplayOffset().value()); + } + if (MediaSourceType::AUDIO == data->getType()) + { + IMediaPipeline::MediaSegmentAudio &audioSegment = dynamic_cast(*data); + metadata.set_sample_rate(static_cast(audioSegment.getSampleRate())); + metadata.set_channels_num(static_cast(audioSegment.getNumberOfChannels())); + metadata.set_clipping_start(audioSegment.getClippingStart()); + metadata.set_clipping_end(audioSegment.getClippingEnd()); + } + else if (MediaSourceType::VIDEO == data->getType()) + { + IMediaPipeline::MediaSegmentVideo &videoSegment = dynamic_cast(*data); + metadata.set_width(videoSegment.getWidth()); + metadata.set_height(videoSegment.getHeight()); + metadata.mutable_frame_rate()->set_numerator(videoSegment.getFrameRate().numerator); + metadata.mutable_frame_rate()->set_denominator(videoSegment.getFrameRate().denominator); + } + else if (MediaSourceType::SUBTITLE != data->getType()) + { + RIALTO_COMMON_LOG_ERROR("Failed to write type specific metadata - media source type unsupported"); + throw std::exception(); + } + + if (!data->getExtraData().empty()) + { + metadata.set_extra_data(std::string(data->getExtraData().begin(), data->getExtraData().end())); + } + if (SegmentAlignment::UNDEFINED != data->getSegmentAlignment()) + { + metadata.set_segment_alignment(convertSegmentAlignment(data->getSegmentAlignment())); + } + if (data->getCodecData()) + { + metadata.mutable_codec_data()->set_data( + std::string(data->getCodecData()->data.begin(), data->getCodecData()->data.end())); + metadata.mutable_codec_data()->set_type(convertCodecDataType(data->getCodecData()->type)); + } + if (data->isEncrypted()) + { + metadata.set_media_key_session_id(data->getMediaKeySessionId()); + metadata.set_key_id(std::string(data->getKeyId().begin(), data->getKeyId().end())); + metadata.set_init_vector(std::string(data->getInitVector().begin(), data->getInitVector().end())); + metadata.set_init_with_last_15(data->getInitWithLast15()); + metadata.set_cipher_mode(convertCipherMode(data->getCipherMode())); + uint32_t crypt{0}; + uint32_t skip{0}; + if (data->getEncryptionPattern(crypt, skip)) + { + metadata.set_crypt(crypt); + metadata.set_skip(skip); + } + + for (const auto &subSample : data->getSubSamples()) + { + auto subSamplePair = metadata.mutable_sub_sample_info()->Add(); + subSamplePair->set_num_clear_bytes(static_cast(subSample.numClearBytes)); + subSamplePair->set_num_encrypted_bytes(static_cast(subSample.numEncryptedBytes)); + } + } + return metadata; +} +} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/SchemaVersion.cpp b/middleware/rialto-client/media/common/source/SchemaVersion.cpp new file mode 100644 index 000000000..8ed388546 --- /dev/null +++ b/middleware/rialto-client/media/common/source/SchemaVersion.cpp @@ -0,0 +1,71 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SchemaVersion.h" + +namespace firebolt::rialto::common +{ +SchemaVersion::SchemaVersion(std::uint32_t major, std::uint32_t minor, std::uint32_t patch) + : m_major{major}, m_minor{minor}, m_patch{patch} +{ +} + +bool SchemaVersion::operator==(const SchemaVersion &other) const +{ + return this->m_major == other.m_major && this->m_minor == other.m_minor && this->m_patch == other.m_patch; +} + +bool SchemaVersion::isCompatible(const SchemaVersion &other) const +{ + return this->m_major == other.m_major; +} + +std::string SchemaVersion::str() const +{ + return std::to_string(m_major) + "." + std::to_string(m_minor) + "." + std::to_string(m_patch); +} + +std::uint32_t SchemaVersion::major() const +{ + return m_major; +} + +std::uint32_t SchemaVersion::minor() const +{ + return m_minor; +} + +std::uint32_t SchemaVersion::patch() const +{ + return m_patch; +} + +SchemaVersion getCurrentSchemaVersion() +try +{ + return SchemaVersion{static_cast(std::stoul(PROJECT_VER_MAJOR)), + static_cast(std::stoul(PROJECT_VER_MINOR)), + static_cast(std::stoul(PROJECT_VER_PATCH))}; +} +catch (const std::exception &e) +{ + // If conversion can't be performed, return default version + return SchemaVersion{1, 0, 0}; +} +} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/TypeConverters.cpp b/middleware/rialto-client/media/common/source/TypeConverters.cpp new file mode 100644 index 000000000..422d6ca7f --- /dev/null +++ b/middleware/rialto-client/media/common/source/TypeConverters.cpp @@ -0,0 +1,91 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "TypeConverters.h" +#include + +namespace firebolt::rialto::common +{ +const char *convertMediaSourceType(const MediaSourceType &mediaSourceType) +{ + static const std::unordered_map + kMediaSourceTypeToStr{{MediaSourceType::AUDIO, "Audio"}, + {MediaSourceType::VIDEO, "Video"}, + {MediaSourceType::SUBTITLE, "Subtitle"}, + {MediaSourceType::UNKNOWN, "Unknown"}}; + const auto kIt = kMediaSourceTypeToStr.find(mediaSourceType); + if (kMediaSourceTypeToStr.end() != kIt) + { + return kIt->second; + } + return "Unknown"; +} + +const char *convertLayout(const Layout &layout) +{ + static const std::unordered_map kLayoutToStr{{Layout::INTERLEAVED, "interleaved"}, + {Layout::NON_INTERLEAVED, "non-interleaved"}}; + const auto kIt = kLayoutToStr.find(layout); + if (kLayoutToStr.end() != kIt) + { + return kIt->second; + } + return ""; +} + +const char *convertFormat(const Format &format) +{ + static const std::unordered_map kFormatToStr{{Format::S8, "S8"}, + {Format::U8, "U8"}, + {Format::S16LE, "S16LE"}, + {Format::S16BE, "S16BE"}, + {Format::U16LE, "U16LE"}, + {Format::U16BE, "U16BE"}, + {Format::S24_32LE, "S24_32LE"}, + {Format::S24_32BE, "S24_32BE"}, + {Format::U24_32LE, "U24_32LE"}, + {Format::U24_32BE, "U24_32BE"}, + {Format::S32LE, "S32LE"}, + {Format::S32BE, "S32BE"}, + {Format::U32LE, "U32LE"}, + {Format::U32BE, "U32BE"}, + {Format::S24LE, "S24LE"}, + {Format::S24BE, "S24BE"}, + {Format::U24LE, "U24LE"}, + {Format::U24BE, "U24BE"}, + {Format::S20LE, "S20LE"}, + {Format::S20BE, "S20BE"}, + {Format::U20LE, "U20LE"}, + {Format::U20BE, "U20BE"}, + {Format::S18LE, "S18LE"}, + {Format::S18BE, "S18BE"}, + {Format::U18LE, "U18LE"}, + {Format::U18BE, "U18BE"}, + {Format::F32LE, "F32LE"}, + {Format::F32BE, "F32BE"}, + {Format::F64LE, "F64LE"}, + {Format::F64BE, "F64BE"}}; + const auto kIt = kFormatToStr.find(format); + if (kFormatToStr.end() != kIt) + { + return kIt->second; + } + return ""; +} +} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/public/CMakeLists.txt b/middleware/rialto-client/media/public/CMakeLists.txt new file mode 100644 index 000000000..97dffa3f6 --- /dev/null +++ b/middleware/rialto-client/media/public/CMakeLists.txt @@ -0,0 +1,58 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +add_library( + RialtoPlayerPublic + INTERFACE + ) + +target_include_directories( + RialtoPlayerPublic + INTERFACE + $ + include + ) + +set ( + RIALTO_PLAYER_PUBLIC_HEADERS + include/ControlCommon.h + include/IClientLogControl.h + include/IClientLogHandler.h + include/IControl.h + include/IControlClient.h + include/IMediaKeys.h + include/IMediaKeysCapabilities.h + include/IMediaKeysClient.h + include/IMediaPipeline.h + include/IMediaPipelineCapabilities.h + include/IMediaPipelineClient.h + include/IWebAudioPlayer.h + include/IWebAudioPlayerClient.h + include/MediaCommon.h +) + +install ( + FILES ${RIALTO_PLAYER_PUBLIC_HEADERS} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rialto +) diff --git a/middleware/rialto-client/media/public/include/ControlCommon.h b/middleware/rialto-client/media/public/include/ControlCommon.h new file mode 100644 index 000000000..c2a8ee16b --- /dev/null +++ b/middleware/rialto-client/media/public/include/ControlCommon.h @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_CONTROL_COMMON_H_ +#define FIREBOLT_RIALTO_CONTROL_COMMON_H_ + +/** + * @file ControlCommon.h + * + * The definition of the Control Common types + * + */ + +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief The application state. + */ +enum class ApplicationState +{ + UNKNOWN, + RUNNING, + INACTIVE +}; +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_CONTROL_COMMON_H_ diff --git a/middleware/rialto-client/media/public/include/IClientLogControl.h b/middleware/rialto-client/media/public/include/IClientLogControl.h new file mode 100644 index 000000000..2347bef93 --- /dev/null +++ b/middleware/rialto-client/media/public/include/IClientLogControl.h @@ -0,0 +1,103 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ +#define FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ + +/** + * @file IClientLogControl.h + * + * The definition of the IClientLogControl interface. + * + * Via this interface the logging of the Rialto Client can + * be redirected to a user specified call handler + */ + +#include +#include + +#include "ControlCommon.h" +#include "IClientLogHandler.h" +#include "IControlClient.h" + +namespace firebolt::rialto +{ +class IClientLogControl; + +/** + * @brief IClientLogControl factory class, returns a concrete implementation of IClientLogControl + */ +class IClientLogControlFactory +{ +public: + IClientLogControlFactory() = default; + virtual ~IClientLogControlFactory() = default; + + /** + * @brief Creates the IClientLogControlFactory + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IClientLogControl factory method, returns a concrete singleton implementation of IClientLogControl + * + * @retval the new IClientLogControl instance or null on error. + */ + virtual IClientLogControl &createClientLogControl() = 0; +}; + +/** + * @brief The definition of the IClientLogControl interface. + * + * This interface defines the public API for controlling Rialto client's + * log handling. This class is a singleton + * + */ +class IClientLogControl +{ +public: + IClientLogControl() = default; + virtual ~IClientLogControl() = default; + + IClientLogControl(const IClientLogControl &) = delete; + IClientLogControl &operator=(const IClientLogControl &) = delete; + IClientLogControl(IClientLogControl &&) = delete; + IClientLogControl &operator=(IClientLogControl &&) = delete; + + /** + * @brief Register a new log handler + * + * @param[in] handler : The user can pass in an object that will henceforth + * receive callbacks to it's log(...) method for rialto client log events. + * Please see IClientLogHandler for the parameters that log() must accept. + * To cancel callbacks then call this method again but pass a nullptr for + * the handler. + * @param[in] ignoreLogLevels : If true then the handler will receive ALL log level messages regardless of the + * currently configured log level + * + * @retval true if successful + */ + virtual bool registerLogHandler(const std::shared_ptr &handler, bool ignoreLogLevels) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ diff --git a/middleware/rialto-client/media/public/include/IClientLogHandler.h b/middleware/rialto-client/media/public/include/IClientLogHandler.h new file mode 100644 index 000000000..4afc91c3e --- /dev/null +++ b/middleware/rialto-client/media/public/include/IClientLogHandler.h @@ -0,0 +1,84 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @file ILogHandler.h + * + * This file comprises the class definition of ILogHandler. + * An interface, which provides API of custom server manager logging handler + */ + +#ifndef FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ +#define FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ + +/** + * @file IClientLogHandler.h + * + * The definition of the IClientLogHandler interface. + * + * This interface allows the user to define their own log handler for + * any messages generated by the rialto client library + */ + +#include + +namespace firebolt::rialto +{ +/** + * @brief IClientLogHandler allows the user to define their own log handler for + * any messages generated by the rialto client library + */ +class IClientLogHandler +{ +public: + IClientLogHandler() = default; + virtual ~IClientLogHandler() = default; + IClientLogHandler(const IClientLogHandler &) = delete; + IClientLogHandler &operator=(const IClientLogHandler &) = delete; + IClientLogHandler(IClientLogHandler &&) = delete; + IClientLogHandler &operator=(IClientLogHandler &&) = delete; + + /** + * @brief All possible log levels that could be used in the log callback + */ + + enum class Level + { + Fatal, + Error, + Warning, + Milestone, + Info, + Debug, + External + }; + + /** + * @brief A callback method for every log item generated by the rialto client library + * + * @param[in] level : The log level + * @param[in] file : The source code file where the log is defined + * @param[in] line : The line number within the file where the log is defined + * @param[in] function : The source code function within which the log is defined + * @param[in] message : The message of the log + */ + virtual void log(Level level, const std::string &file, int line, const std::string &function, + const std::string &message) = 0; +}; +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ diff --git a/middleware/rialto-client/media/public/include/IControl.h b/middleware/rialto-client/media/public/include/IControl.h new file mode 100644 index 000000000..740d4f236 --- /dev/null +++ b/middleware/rialto-client/media/public/include/IControl.h @@ -0,0 +1,99 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_CONTROL_H_ +#define FIREBOLT_RIALTO_I_CONTROL_H_ + +/** + * @file IControl.h + * + * The definition of the IControl interface. + * + * This interface defines the public API of Rialto for control of Rialto, + * including the IPC connection and shared memory. + */ + +#include +#include + +#include "ControlCommon.h" +#include "IControlClient.h" + +namespace firebolt::rialto +{ +class IControl; + +/** + * @brief IControl factory class, returns a concrete implementation of IControl + */ +class IControlFactory +{ +public: + IControlFactory() = default; + virtual ~IControlFactory() = default; + + /** + * @brief Creates a IControlFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IControl factory method, returns a concrete implementation of IControl + * + * @retval the new IControl instance or null on error. + */ + virtual std::shared_ptr createControl() const = 0; +}; + +/** + * @brief The definition of the IControl interface. + * + * This interface defines the public API for control of the ipc and shared memory. + * + */ +class IControl +{ +public: + IControl() = default; + virtual ~IControl() = default; + + IControl(const IControl &) = delete; + IControl &operator=(const IControl &) = delete; + IControl(IControl &&) = delete; + IControl &operator=(IControl &&) = delete; + + /** + * @brief Register new IControlClient. This method will hold a shared_ptr + * to the client until the destruction of the IControl object. + * At destruction the client will be unregistered and the + * shared_ptr will be released. + * + * @param[in] client : Client object for callbacks + * @param[out] appState : Current application state + * + * @retval true on success, false otherwise. + */ + virtual bool registerClient(std::weak_ptr client, ApplicationState &appState) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_CONTROL_H_ diff --git a/middleware/rialto-client/media/public/include/IControlClient.h b/middleware/rialto-client/media/public/include/IControlClient.h new file mode 100644 index 000000000..9f9539706 --- /dev/null +++ b/middleware/rialto-client/media/public/include/IControlClient.h @@ -0,0 +1,61 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ +#define FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ + +/** + * @file IControlClient.h + * + * The definition of the IControlClient interface. + * + * This file comprises the definition of the IControlClient abstract + * class. This is the API by which a IControl implementation will + * pass notifications to its client. + */ + +#include "ControlCommon.h" + +namespace firebolt::rialto +{ +/** + * @brief The Rialto control client interface. + * + * This is The Rialto control client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the + * state of the rialto server. + */ +class IControlClient +{ +public: + /** + * @brief Virtual destructor + */ + virtual ~IControlClient() = default; + + /** + * @brief Notifies the client that rialto server reached new application state + * + * @param[in] state: The new application state. + */ + virtual void notifyApplicationState(ApplicationState state) = 0; +}; +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaKeys.h b/middleware/rialto-client/media/public/include/IMediaKeys.h new file mode 100644 index 000000000..d8b8a01cd --- /dev/null +++ b/middleware/rialto-client/media/public/include/IMediaKeys.h @@ -0,0 +1,306 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ +#define FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ + +/** + * @file IMediaKeys.h + * + * The definition of the IMediaKeys interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content. + */ + +#include +#include +#include + +#include "IMediaKeysClient.h" +#include "MediaCommon.h" + +namespace firebolt::rialto +{ +class IMediaKeys; + +/** + * @brief IMediaKeys factory class, returns a concrete implementation of IMediaKeys + */ +class IMediaKeysFactory +{ +public: + IMediaKeysFactory() = default; + virtual ~IMediaKeysFactory() = default; + + /** + * @brief Create a IMediaKeysFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMediaKeys factory method, returns a concrete implementation of IMediaKeys + * + * @param[in] keySystem : The key system for which to create a Media Keys instance. + * + * @retval the new media keys instance or null on error. + */ + virtual std::unique_ptr createMediaKeys(const std::string &keySystem) const = 0; +}; + +/** + * @brief The definition of the IMediaKeys interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content + * which should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaKeys +{ +public: + IMediaKeys() = default; + virtual ~IMediaKeys() = default; + + IMediaKeys(const IMediaKeys &) = delete; + IMediaKeys &operator=(const IMediaKeys &) = delete; + IMediaKeys(IMediaKeys &&) = delete; + IMediaKeys &operator=(IMediaKeys &&) = delete; + + /** + * @brief Selects the specified keyId for the key session. Netflix specific API. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] keyId : The key id to select. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) = 0; + + /** + * @brief Returns true if the Key Session object contains the specified key. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] keyId : The key id. + * + * @retval true if it contains the key. + */ + virtual bool containsKey(int32_t keySessionId, const std::vector &keyId) = 0; + + /** + * @brief Creates a session and returns the session id. + * + * This method creates a new session and returns the session id in + * the specified string. Any other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] sessionType : The session type. + * @param[in] client : Client object for callbacks + * @param[in] isLDL : Is this an LDL + * @param[out] keySessionId: The key session id + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, + bool isLDL, int32_t &keySessionId) = 0; + + /** + * @brief Generates a licence request. + * + * This method triggers generation of a licence request. If the session + * id does not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the + * session type or init data type is not supported a + * MediaKeyErrorStatus:NOT_SUPPORTED value is be returned. Any other + * errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] initDataType : The init data type. + * @param[in] initData : The init data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) = 0; + + /** + * @brief Loads an existing key session + * + * This method loads an existing key session. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the + * session type or init data type is not supported a + * MediaKeyErrorStatus:NOT_SUPPORTED value must be returned. If the session + * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any + * other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id for the session. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus loadSession(int32_t keySessionId) = 0; + + /** + * @brief Updates a key session's state. + * + * This method updates a session's state. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the session + * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any + * other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] responseData : The license response data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) = 0; + + /** + * @brief Set DRM Header for a key session + * + * This method updates a key session's DRM header. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned.If the session + * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any + * other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The session id for the session. + * @param[in] requestData : The request data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) = 0; + + /** + * @brief Closes a key session + * + * This method closes an open session. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other + * errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus closeKeySession(int32_t keySessionId) = 0; + + /** + * @brief Removes a key session + * + * This method removes an open session. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other + * errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus removeKeySession(int32_t keySessionId) = 0; + + /** + * @brief Delete the DRM store for the object's key system + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus deleteDrmStore() = 0; + + /** + * @brief Delete the key store for the object's key system + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus deleteKeyStore() = 0; + + /** + * @brief Gets a hash of the DRM store for the object's key system + * + * @param[out] drmStoreHash : the hash value + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) = 0; + + /** + * @brief Gets a hash of the Key store for the object's key system + * + * @param[out] keyStoreHash : the hash value + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) = 0; + + /** + * @brief Get the limit on the number of ldl key sessions for the object's key system + * + * @param[out] ldlLimit : the limit on the number of ldl key sessions. + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) = 0; + + /** + * @brief Get the last cdm specific DRM error code + * + * @param[in] keySessionId : The key session id. + * @param[out] errorCode : the error code. + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) = 0; + + /** + * @brief Get the DRM system time for the object's key system + * + * @param[out] drmTime : the DRM system time + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) = 0; + + /** + * @brief Get the internal CDM key session ID + * + * @param[in] keySessionId : The key session id for the session. + * @param[out] cdmKeySessionId : The internal CDM key session ID + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) = 0; + + /** + * @brief Releases a key session + * + * This method releases an open session. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other + * errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) = 0; + + /** + * @brief Get metrics for a DRM system + * + * @param[out] buffer : Buffer that can hold the metric data + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaKeysCapabilities.h b/middleware/rialto-client/media/public/include/IMediaKeysCapabilities.h new file mode 100644 index 000000000..4269bf754 --- /dev/null +++ b/middleware/rialto-client/media/public/include/IMediaKeysCapabilities.h @@ -0,0 +1,122 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ + +/** + * @file IMediaKeysCapabilities.h + * + * The definition of the IMediaKeysCapabilities interface. + */ + +#include +#include +#include + +namespace firebolt::rialto +{ +class IMediaKeysCapabilities; + +/** + * @brief IMediaKeysCapabilities factory class, for getting the IMediaKeysCapabilities singleton object. + */ +class IMediaKeysCapabilitiesFactory +{ +public: + IMediaKeysCapabilitiesFactory() = default; + virtual ~IMediaKeysCapabilitiesFactory() = default; + + /** + * @brief Gets the IMediaKeysCapabilitiesFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Gets the IMediaKeysCapabilities singleton object. + * + * @retval the MediaKeysCapabilities instance or null on error. + */ + virtual std::shared_ptr getMediaKeysCapabilities() const = 0; +}; + +/** + * @brief The definition of the IMediaKeysCapabilities interface. + * + * This interface defines the public API of Rialto for querying EME decryption capabilities. + * It should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaKeysCapabilities +{ +public: + IMediaKeysCapabilities() = default; + virtual ~IMediaKeysCapabilities() = default; + + IMediaKeysCapabilities(const IMediaKeysCapabilities &) = delete; + IMediaKeysCapabilities &operator=(const IMediaKeysCapabilities &) = delete; + IMediaKeysCapabilities(IMediaKeysCapabilities &&) = delete; + IMediaKeysCapabilities &operator=(IMediaKeysCapabilities &&) = delete; + + /** + * @brief Returns the EME key systems supported by Rialto + * + * @retval The supported key systems. + */ + virtual std::vector getSupportedKeySystems() = 0; + + /** + * @brief Indicates if the specified key system is supported. + * + * This method should be called to ensure that the specified key + * system is supported by Rialto. + * + * @param[in] keySystem : The key system. + * + * @retval true if supported. + */ + virtual bool supportsKeySystem(const std::string &keySystem) = 0; + + /** + * @brief Returns version of supported key system + * + * @param[in] keySystem : The key system. + * @param[out] version : The supported version of the key system + * + * @retval true if operation was successful + */ + virtual bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) = 0; + + /** + * @brief Gets support server certificate. + * + * Some DRMs (e.g. WideVine) use a system-wide server certificate. This method + * gets if system has support for that certificate. + * + * @param[in] keySystem : The key system. + * + * @retval true if server certificate is supported + */ + virtual bool isServerCertificateSupported(const std::string &keySystem) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaKeysClient.h b/middleware/rialto-client/media/public/include/IMediaKeysClient.h new file mode 100644 index 000000000..fe2d89e83 --- /dev/null +++ b/middleware/rialto-client/media/public/include/IMediaKeysClient.h @@ -0,0 +1,83 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ +#define FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ + +/** + * @file IMediaKeysClient.h + * + * The definition of the IMediaKeysClient interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content. + * This is the Rialto media keys client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the state + * of a key session. + */ + +#include "MediaCommon.h" +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief The definition of the IMediaKeysClient interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content + * which should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaKeysClient +{ +public: + /** + * @brief The virtual destructor. + */ + virtual ~IMediaKeysClient() {} + + /** + * @brief Notification that a license is required + * + * @param[in] keySessionId : The idea of the session triggering the callback + * @param[in] licenseRequestMessage : The license request message blob + * @param[in] url : URL to which the message should be sent or empty string + */ + virtual void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, + const std::string &url) = 0; + + /** + * @brief Notification that a license renewal is required + * + * @param[in] keySessionId : The idea of the session triggering the callback + * @param[in] licenseRenewalMessage : The license renewal message blob + */ + virtual void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) = 0; + + /** + * @brief Notification that the status of one or more keys in the key session has changed + * + * @param[in] keySessionId : The idea of the session triggering the callback + * @param[in] keyStatuses : Vector of key ID/key status pairs + */ + virtual void onKeyStatusesChanged(int32_t keySessionId, const KeyStatusVector &keyStatuses) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaPipeline.h b/middleware/rialto-client/media/public/include/IMediaPipeline.h new file mode 100644 index 000000000..30de4ee70 --- /dev/null +++ b/middleware/rialto-client/media/public/include/IMediaPipeline.h @@ -0,0 +1,1542 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ +#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ + +/** + * @file IMediaPipeline.h + * + * The definition of the IMediaPipeline interface. + * + * This interface defines the public API of Rialto for playback of AV content. + */ + +#include + +#include +#include +#include +#include +#include + +#include "IMediaPipelineClient.h" +#include "MediaCommon.h" + +namespace firebolt::rialto +{ +class IMediaPipeline; + +/** + * @brief IMediaPipeline factory class, returns a concrete implementation of IMediaPipeline + */ +class IMediaPipelineFactory +{ +public: + IMediaPipelineFactory() = default; + virtual ~IMediaPipelineFactory() = default; + + /** + * @brief Create a IMediaPipelineFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMediaPipeline factory method, returns a concrete implementation of IMediaPipeline + * + * @param[in] client : The Rialto media player client. + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session + * + * @retval the new backend instance or null on error. + */ + virtual std::unique_ptr createMediaPipeline(std::weak_ptr client, + const VideoRequirements &videoRequirements) const = 0; +}; + +/** + * @brief The definition of the IMediaPipeline interface. + * + * This interface defines the public API of Rialto for playback of AV content which + * should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaPipeline +{ +public: + IMediaPipeline() = default; + virtual ~IMediaPipeline() = default; + + IMediaPipeline(const IMediaPipeline &) = delete; + IMediaPipeline &operator=(const IMediaPipeline &) = delete; + IMediaPipeline(IMediaPipeline &&) = delete; + IMediaPipeline &operator=(IMediaPipeline &&) = delete; + + /** + * @brief A class that represents a source of media data. + */ + class MediaSource + { + public: + /** + * @brief Virtual destructor. + */ + virtual ~MediaSource() {} + + /** + * @brief Create a copy + */ + virtual std::unique_ptr copy() const = 0; + + /** + * @brief Return the source type. + */ + virtual MediaSourceType getType() const { return MediaSourceType::UNKNOWN; } + + /** + * @brief Return the MIME type. + */ + std::string getMimeType() const { return m_mimeType; } + + /** + * @brief Return if source has drm + */ + bool getHasDrm() const { return m_hasDrm; } + + /** + * @brief Return the source config type. + */ + SourceConfigType getConfigType() const { return m_configType; } + + /** + * @brief Return the source id. + */ + int32_t getId() const { return m_id; } + + /** + * @brief Set the source id. + */ + void setId(int32_t id) { m_id = id; } + + protected: + /** + * @brief Default constructor. + * + * @param[in] configType : The source config type. + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + */ + explicit MediaSource(SourceConfigType configType = SourceConfigType::UNKNOWN, + const std::string &mimeType = std::string(), bool hasDrm = true) + : m_id(0), m_configType(configType), m_mimeType(mimeType), m_hasDrm(hasDrm) + { + } + /** + * @brief The source id. Parameter will be set by a successful call to attachSource() + */ + int32_t m_id; + + /** + * @brief The source config type. + */ + SourceConfigType m_configType; + + /** + * @brief The MIME type. + */ + std::string m_mimeType; + + /** + * @brief Parameter to check if encrypted frames will be used for this source. + */ + bool m_hasDrm; + }; + + /** + * @brief A class that represents media source audio and video derived from MediaSource class, which represents the + * source of media data + */ + class MediaSourceAV : public MediaSource + { + public: + ~MediaSourceAV() {} + std::unique_ptr copy() const { return std::make_unique(*this); } + + /** + * @brief Gets the segment alignment + */ + SegmentAlignment getSegmentAlignment() const { return m_alignment; } + + /** + * @brief Gets the codec data + */ + const std::shared_ptr &getCodecData() const { return m_codecData; } + + /** + * @brief Gets the stream format + */ + StreamFormat getStreamFormat() const { return m_streamFormat; } + + protected: + /** + * @brief Default constructor. + * + * @param[in] configType : The source config type. + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + explicit MediaSourceAV(SourceConfigType configType = SourceConfigType::UNKNOWN, + const std::string &mimeType = std::string(), bool hasDrm = true, + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSource(configType, mimeType, hasDrm), m_alignment(alignment), m_streamFormat(streamFormat), + m_codecData(codecData) + { + } + /** + * @brief The alignment of media segment + */ + SegmentAlignment m_alignment; + + /** + * @brief The stream format + */ + StreamFormat m_streamFormat; + + /** + * @brief Additional data for decoder + */ + std::shared_ptr m_codecData; + }; + + /** + * @brief A class that represents media source audio derived from MediaSource class, which represents the source of + * media data + */ + + class MediaSourceAudio : public MediaSourceAV + { + public: + /** + * @brief Constructor for audio specific configuration. + * + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + * @param[in] audioConfig : The audio specific configuration. + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + MediaSourceAudio(const std::string &mimeType, bool hasDrm = true, const AudioConfig &audioConfig = AudioConfig(), + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSourceAV(SourceConfigType::AUDIO, mimeType, hasDrm, alignment, streamFormat, codecData), + m_audioConfig(audioConfig) + { + } + + ~MediaSourceAudio() {} + + MediaSourceType getType() const override { return MediaSourceType::AUDIO; } + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Gets the audio specific configuration + * + * @retval audio specific configuration + */ + const AudioConfig &getAudioConfig() const { return m_audioConfig; } + + protected: + /** + * @brief Variable that stores the audio specific configuration + */ + AudioConfig m_audioConfig; + }; + + /** + * @brief A class that represents media source video derived from MediaSource class, which represents the source of + * media data + */ + + class MediaSourceVideo : public MediaSourceAV + { + public: + /** + * @brief Constructor for video specific configuration. + * + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + * @param[in] width : The width of the video + * @param[in] height : The height of the video + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + MediaSourceVideo(const std::string &mimeType, bool hasDrm = true, + int32_t width = firebolt::rialto::kUndefinedSize, + int32_t height = firebolt::rialto::kUndefinedSize, + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSourceAV(SourceConfigType::VIDEO, mimeType, hasDrm, alignment, streamFormat, codecData), + m_width(width), m_height(height) + { + } + ~MediaSourceVideo() {} + + MediaSourceType getType() const override { return MediaSourceType::VIDEO; } + std::unique_ptr copy() const { return std::make_unique(*this); } + + /** + * @brief Gets the width of the video + * + * @retval width of the video + */ + int32_t getWidth() const { return m_width; } + + /** + * @brief Gets the height of the video + * + * @retval height of the video + */ + int32_t getHeight() const { return m_height; } + + protected: + /** + * @brief Constructor for video specific configuration. + * + * @param[in] sourceConfigType : The source config type + * @param[in] mimeType : The mime type string. + * @param[in] hasDrm : Information if source will use drm + * @param[in] width : The width of the video + * @param[in] height : The height of the video + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + MediaSourceVideo(SourceConfigType sourceConfigType, const std::string &mimeType, bool hasDrm = true, + int32_t width = firebolt::rialto::kUndefinedSize, + int32_t height = firebolt::rialto::kUndefinedSize, + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSourceAV(sourceConfigType, mimeType, hasDrm, alignment, streamFormat, codecData), m_width(width), + m_height(height) + { + } + + private: + /** + * @brief The video width + */ + int m_width; + + /** + * @brief The video height + */ + int m_height; + }; + + /** + * @brief A class that represents media source video dolby vision derived from media source video data + */ + + class MediaSourceVideoDolbyVision : public MediaSourceVideo + { + public: + /** + * @brief Constructor for dolby vision specific configuration. + * + * @param[in] mimeType : The mime type string. + * @param[in] dolbyVisionProfile : The dolby vision profile + * @param[in] hasDrm : Information if source will use drm + * @param[in] width : The width of the video + * @param[in] height : The height of the video + * @param[in] alignment : The alignment of media segment. + * @param[in] streamFormat : The stream format + * @param[in] codecData : The additional data for decoder + */ + MediaSourceVideoDolbyVision(const std::string &mimeType, int32_t dolbyVisionProfile, bool hasDrm = true, + int32_t width = firebolt::rialto::kUndefinedSize, + int32_t height = firebolt::rialto::kUndefinedSize, + SegmentAlignment alignment = SegmentAlignment::UNDEFINED, + StreamFormat streamFormat = StreamFormat::UNDEFINED, + const std::shared_ptr &codecData = nullptr) + : MediaSourceVideo(SourceConfigType::VIDEO_DOLBY_VISION, mimeType, hasDrm, width, height, alignment, + streamFormat, codecData), + m_dolbyVisionProfile(dolbyVisionProfile) + { + } + ~MediaSourceVideoDolbyVision() {} + std::unique_ptr copy() const { return std::make_unique(*this); } + + /** + * @brief Gets the dolby vision profile + * + * @retval dolby vision profile + */ + uint32_t getDolbyVisionProfile() const { return m_dolbyVisionProfile; } + + protected: + /** + * @brief Variable that stores the Dolby Vision Profile + */ + uint32_t m_dolbyVisionProfile; + }; + + /** + * @brief A class that represents media source subtitle derived from media source video data + */ + class MediaSourceSubtitle : public MediaSource + { + public: + /** + * @brief Construct a new Media Source Subtitle object + * + * @param mimeType : The mime type string + * @param textTrackIdentifier : The text track identifier string + */ + MediaSourceSubtitle(const std::string &mimeType, const std::string &textTrackIdentifier) + : MediaSource(SourceConfigType::SUBTITLE, mimeType, false), m_textTrackIdentifier(textTrackIdentifier) + { + } + + ~MediaSourceSubtitle() {} + + MediaSourceType getType() const override { return MediaSourceType::SUBTITLE; } + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Get the Text Track Identifier object + * + * @return the text track identifier + */ + const std::string &getTextTrackIdentifier() const { return m_textTrackIdentifier; } + + protected: + /** + * @brief Variable that stores the text track identifier + */ + std::string m_textTrackIdentifier; + }; + + /** + * @brief A class that represents a media segment + */ + class MediaSegment + { + public: + /** + * @brief Default constructor. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] type : The source type. + * @param[in] timeStamp : The timestamp in nanoseconds. + * @param[in] duration : The duration in nanoseconds. + */ + MediaSegment(int32_t sourceId = 0, MediaSourceType type = MediaSourceType::UNKNOWN, int64_t timeStamp = 0, + int64_t duration = 0) + : m_sourceId(sourceId), m_type(type), m_data(nullptr), m_dataLength(0u), m_timeStamp(timeStamp), + m_duration(duration), m_encrypted(false), m_mediaKeySessionId(0), m_initWithLast15(0), + m_alignment(SegmentAlignment::UNDEFINED), m_cipherMode(CipherMode::UNKNOWN), m_crypt(0), m_skip(0), + m_encryptionPatternSet(false), m_displayOffset(std::nullopt) + { + } + + /** + * @brief Virtual destructor. + */ + virtual ~MediaSegment() {} + + /** + * @brief Makes a shallow copy of the segment + * + * @retval Shallow copy of the segment + */ + virtual std::unique_ptr copy() const { return std::make_unique(*this); } + + /** + * @brief Return the source id. + * + * @retval the source id. + */ + int32_t getId() const { return m_sourceId; } + + /** + * @brief The source type for the data. + * + * @retval the source type. + */ + MediaSourceType getType() const { return m_type; } + + /** + * @brief Returns a pointer to the data. + * + * @retval the data. + */ + const uint8_t *getData() const { return m_data; } + + /** + * @brief Returns a the data length. + * + * @retval the data. + */ + uint32_t getDataLength() const { return m_dataLength; } + + /** + * @brief Returns the time stamp. + * + * @retval the timestamp in nanoseconds. + */ + int64_t getTimeStamp() const { return m_timeStamp; } + + /** + * @brief Sets the time stamp (value in nanoseconds). + */ + void setTimeStamp(int64_t timeStamp) { m_timeStamp = timeStamp; } + + /** + * @brief Returns the duration. + * + * @retval the duration in nanoseconds. + */ + int64_t getDuration() const { return m_duration; } + + /** + * @brief Returns a pointer to the extra data. + * + * @retval the data. + */ + const std::vector &getExtraData() const { return m_extraData; } + + /** + * @brief Indicates that the data is encrypted. + * + * @retval true if the data is encrypted. + */ + bool isEncrypted() const { return m_encrypted; } + + /** + * @brief Returns the media key session id. Empty if unencrypted. + * + * @retval the media key session id. + */ + const int32_t getMediaKeySessionId() const { return m_mediaKeySessionId; } + + /** + * @brief Returns the key id. Empty if unencrypted. + * + * @retval the key id. + */ + const std::vector &getKeyId() const { return m_keyId; } + + /** + * @brief Returns the initialisation vector. Empty if unencrypted. + * + * @retval the initialisation vector. + */ + const std::vector &getInitVector() const { return m_initVector; } + + /** + * @brief Returns the sub samples. Empty if unencrypted. + * + * @retval the sub samples. + */ + const std::vector &getSubSamples() const { return m_subSamples; } + + /** + * @brief Returns the initWithLast15 value + * + * @retval the initWithLast15 value. + */ + const uint32_t getInitWithLast15() const { return m_initWithLast15; } + + /** + * @brief Returns the segment alignment + * + * @retval the segment alignment + */ + const SegmentAlignment getSegmentAlignment() const { return m_alignment; } + + /** + * @brief Gets the codec data + * + * @retval the codec data + */ + const std::shared_ptr &getCodecData() const { return m_codecData; } + + /** + * @brief Gets the cipher mode for common encryption + * + * @retval cipher mode uses for this sample + */ + const CipherMode &getCipherMode() const { return m_cipherMode; } + + /** + * @brief Gets the crypt & skip byte block for pattern encryption + * + * @param[out] crypt : Crypt byte block value + * @param[out] skip : Skip byte block value + * + * @retval if the encryption pattern has been set + */ + const bool getEncryptionPattern(uint32_t &crypt, uint32_t &skip) const + { + crypt = m_crypt; + skip = m_skip; + return m_encryptionPatternSet; + } + + /** + * @brief Gets the display offset + * + * @retval The offset in the source file of the beginning of the media segment. + */ + std::optional getDisplayOffset() const { return m_displayOffset; } + + protected: + /** + * @brief The source id. + */ + int32_t m_sourceId; + + /** + * @brief The source type. + */ + MediaSourceType m_type; + + /** + * @brief The data + */ + const uint8_t *m_data; + + /** + * @brief The data length + */ + uint32_t m_dataLength; + + /** + * @brief The time stamp. + */ + int64_t m_timeStamp; + + /** + * @brief The duration. + */ + int64_t m_duration; + + /** + * @brief Additional data for decoder + */ + std::shared_ptr m_codecData; + + /** + * @brief The data + */ + std::vector m_extraData; + + /** + * @brief Indicates the data is encrypted. + */ + bool m_encrypted; + + /** + * @brief Key session ID to use for decryption - only required for Netflix. + */ + int32_t m_mediaKeySessionId; + + /** + * @brief The encryption key id. + */ + std::vector m_keyId; + + /** + * @brief The encryption key initialisation vector. + */ + std::vector m_initVector; + + /** + * @brief The sub-sample pairs. + */ + std::vector m_subSamples; + + /** + * @brief Whether decryption context needs to be initialized with + * last 15 bytes. Currently this only applies to PlayReady DRM. + */ + uint32_t m_initWithLast15; + + /** + * @brief The alignment of media segment + */ + SegmentAlignment m_alignment; + + /** + * @brief Cipher mode of the sample. + */ + CipherMode m_cipherMode; + + /** + * @brief Crypt byte block value. + */ + uint32_t m_crypt; + + /** + * @brief Skip byte block value. + */ + uint32_t m_skip; + + /** + * @brief Whether the encryption pattern has been set. + */ + bool m_encryptionPatternSet; + + /** + * @brief The offset in the source file of the beginning of the media segment. + */ + std::optional m_displayOffset; + + public: + /** + * @brief Sets the segment data. + * + * @warning Note that the caller must guarantee that the buffer referenced by 'data' must remain + * valid until the corresponding call to haveData() has completed (at which point the data will + * have been copied out). + * + * @note This is for performance reasons to avoid multiple copies of AV data. A raw pointer is + * used for the same reason since most runtimes will expose a raw pointer to the data. + * + * @retval true on success. + */ + bool setData(uint32_t dataLength, const uint8_t *data) + { + m_dataLength = dataLength; + m_data = data; + return true; + } + + /** + * @brief Sets the extra data. + * + * @retval true on success. + */ + bool setExtraData(const std::vector &extraData) + { + m_extraData = extraData; + return true; + } + + /** + * @brief Sets the segment alignment + * + * @param[in] alignment : The new segment alignment + */ + void setSegmentAlignment(const SegmentAlignment &alignment) { m_alignment = alignment; } + + /** + * @brief Sets new codec_data for the segment. + * + * @note Should only be called if the codec data changes + * + * @param[in] codecData The updated codec data for the source + */ + void setCodecData(const std::shared_ptr &codecData) { m_codecData = codecData; } + + /** + * @brief Sets the encrypted flag. + * + * @param[in] encrypted : Set true to indicated encrypted data. + */ + void setEncrypted(bool encrypted) { m_encrypted = encrypted; } + + /** + * @brief Sets the media key session id. + * + * @param[in] mksId : the media key session id. + */ + void setMediaKeySessionId(int32_t mksId) { m_mediaKeySessionId = mksId; } + + /** + * @brief Sets the key id. + * + * @param[in] keyId : The key id. + */ + void setKeyId(const std::vector &keyId) { m_keyId = keyId; } + + /** + * @brief Sets the encryption initialisation vector. + * + * @param[in] initVector : The initialisation vector. + */ + void setInitVector(const std::vector &initVector) { m_initVector = initVector; } + + /** + * @brief Adds a sub-sample pair to the sub samples. + * + * @param[in] numClearBytes : The number of clear bytes. + * @param[in] numEncryptedBytes : The number of encrypted bytes. + */ + void addSubSample(size_t numClearBytes, size_t numEncryptedBytes) + { + m_subSamples.emplace_back(SubSamplePair{numClearBytes, numEncryptedBytes}); + } + + /** + * @brief Sets initWithLast15 value + * + * @param[in] initWithLast15 : initWithLast15 value + */ + void setInitWithLast15(uint32_t initWithLast15) { m_initWithLast15 = initWithLast15; } + + /** + * @brief Sets the cipher mode for common encryption. + * + * @param[in] cipherMode : Specifies cipher mode uses for this sample. + */ + void setCipherMode(CipherMode cipherMode) { m_cipherMode = cipherMode; } + + /** + * @brief Sets the crypt & skip byte block for pattern encryption + * + * @param[in] crypt : Crypt byte block value + * @param[in] skip : Skip byte block value + */ + void setEncryptionPattern(uint32_t crypt, uint32_t skip) + { + m_crypt = crypt; + m_skip = skip; + m_encryptionPatternSet = true; + } + + /** + * @brief Sets the display offset + * + * @param[in] displayOffset : The offset in the source file of the beginning of the media segment. + */ + void setDisplayOffset(uint64_t displayOffset) { m_displayOffset = displayOffset; } + + /** + * @brief Copies the data from other to this. + */ + void copy(const MediaSegment &other); + }; + + /** + * @brief A class that represents media source audio data + */ + class MediaSegmentAudio : public MediaSegment + { + public: + /** + * @brief Default constructor. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] timeStamp : The timestamp in nanoseconds. + * @param[in] duration : The duration in nanoseconds. + * @param[in] sampleRate : The sample rate in samples per second. + * @param[in] numberOfChannels : The number of audio channels. + * @param[in] clippingStart : The amount of audio to clip from start of buffer + * @param[in] clippingEnd : The amount of audio to clip from end of buffer + */ + MediaSegmentAudio(int32_t sourceId = 0, int64_t timeStamp = 0, int64_t duration = 0, int32_t sampleRate = 0, + int32_t numberOfChannels = 0, uint64_t clippingStart = 0, uint64_t clippingEnd = 0) + : MediaSegment(sourceId, MediaSourceType::AUDIO, timeStamp, duration), m_sampleRate(sampleRate), + m_numberOfChannels(numberOfChannels), m_clippingStart(clippingStart), m_clippingEnd(clippingEnd) + { + } + + /** + * @brief Copy constructor. + */ + MediaSegmentAudio(const MediaSegmentAudio &other) : MediaSegment(other) + { + m_sampleRate = other.m_sampleRate; + m_numberOfChannels = other.m_numberOfChannels; + } + + /** + * @brief Makes a shallow copy of the segment + * + * @retval Shallow copy of the segment + */ + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Return the audio sample rate. + * + * @retval the sample rate in samples per second. + */ + int32_t getSampleRate() const { return m_sampleRate; } + + /** + * @brief Return the number of audio channels. + * + * @retval the number of channels. + */ + int32_t getNumberOfChannels() const { return m_numberOfChannels; } + + /** + * @brief Return the amount of audio to clip from start of buffer + * + * @retval the amount of audio to clip from start of buffer + */ + uint64_t getClippingStart() const { return m_clippingStart; } + + /** + * @brief Return the amount of audio to clip from end of buffer + * + * @retval the amount of audio to clip from end of buffer + */ + uint64_t getClippingEnd() const { return m_clippingEnd; } + + /** + * @brief Copy assignment operator. + * + * @retval the copy. + */ + MediaSegmentAudio &operator=(const MediaSegmentAudio &other) + { + copy(other); + return *this; + } + + protected: + /** + * @brief Copies the data from other to this. + */ + void copy(const MediaSegmentAudio &other); + + /** + * @brief The audio sample rate. + */ + int32_t m_sampleRate; + + /** + * @brief The number of audio channels. + */ + int32_t m_numberOfChannels; + + /** + * @brief The amount of audio to clip from start of buffer + */ + uint64_t m_clippingStart; + + /** + * @brief The amount of audio to clip from end of buffer + */ + uint64_t m_clippingEnd; + }; + + /** + * @brief A class that represents media source video data + */ + class MediaSegmentVideo : public MediaSegment + { + public: + /** + * @brief Default constructor. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] timeStamp : The timestamp in nanoseconds. + * @param[in] duration : The duration in nanoseconds. + * @param[in] width : The video width in pixels. + * @param[in] height : The video height in pixels. + * @param[in] frameRate : The fractional framerate of the sample. + */ + MediaSegmentVideo(int32_t sourceId = 0, int64_t timeStamp = 0, int64_t duration = 0, + int32_t width = firebolt::rialto::kUndefinedSize, + int32_t height = firebolt::rialto::kUndefinedSize, + firebolt::rialto::Fraction frameRate = {firebolt::rialto::kUndefinedSize, + firebolt::rialto::kUndefinedSize}) + : MediaSegment(sourceId, MediaSourceType::VIDEO, timeStamp, duration), m_width(width), m_height(height), + m_frameRate(frameRate) + { + } + + /** + * @brief Copy constructor. + */ + MediaSegmentVideo(const MediaSegmentVideo &other) : MediaSegment(other) + { + m_width = other.m_width; + m_height = other.m_height; + m_frameRate = other.m_frameRate; + } + + /** + * @brief Makes a shallow copy of the segment + * + * @retval Shallow copy of the segment + */ + std::unique_ptr copy() const override { return std::make_unique(*this); } + + /** + * @brief Return the video width. + * + * @retval the video width in pixels. + */ + int32_t getWidth() const { return m_width; } + + /** + * @brief Return the video height. + * + * @retval the video height in pixels. + */ + int32_t getHeight() const { return m_height; } + + /** + * @brief Return the video frameRate. + * + * @retval the fractional framerate of the sample. + */ + firebolt::rialto::Fraction getFrameRate() const { return m_frameRate; } + + /** + * @brief Copy assignment operator. + * + * @retval the copy. + */ + MediaSegmentVideo &operator=(const MediaSegmentVideo &other) + { + copy(other); + return *this; + } + + protected: + /** + * @brief Copies the data from other to this. + */ + void copy(const MediaSegmentVideo &other); + + /** + * @brief The video width in pixels. + */ + int32_t m_width; + + /** + * @brief The video height in pixels. + */ + int32_t m_height; + + /** + * @brief The fractional framerate of the sample. + */ + firebolt::rialto::Fraction m_frameRate; + }; + + /** + * @brief A vector that contains one or more media segments. + */ + typedef std::vector> MediaSegmentVector; + + /** + * @brief Returns the media player client. + * + * @retval The media player client. + */ + virtual std::weak_ptr getClient() = 0; + + /** + * @brief Loads the media and backend delegate. + * + * This method loads the media and backend appropriate for the media. + * The media type determines the backend delegate to use to play back + * the media. The MIME type confirms the type and CODECs for the media. + * The URL will comprise the media URL for types MediaType::URL and + * MediaType::HLS. For MediaType::MSE the URL will comprise a blob URL + * as the data is loaded by the browser. + * + * @param[in] type : The media type. + * @param[in] mimeType : The MIME type. + * @param[in] url : The URL. + */ + virtual bool load(MediaType type, const std::string &mimeType, const std::string &url) = 0; + + /** + * @brief Attaches a source stream to the backend. + * + * This method is called by Rialto Client to attach a media source stream to + * the backend. It is only called when Media Source Extensions are + * being used. I.e. if the MediaType value in load() is + * MediaType::MSE. + * + * @param[in] source : The source. + * + * @retval true on success. + */ + virtual bool attachSource(const std::unique_ptr &source) = 0; + + /** + * @brief Unattaches a source. + * + * This method is called by Rialto Client to detach a media source stream from + * the backend. It is only called when Media Source Extensions are + * being used. I.e. if the MediaType value in load() is + * MediaType::MSE. + * + * @param[in] id : The source id. Value should be set to the MediaSource.id returned after attachSource() + * + * @retval true on success. + */ + virtual bool removeSource(int32_t id) = 0; + + /** + * @brief Notifies Rialto Server that all sources were attached + * + * This method is called by Rialto Client to notify the RialtoServer + * that all sources were attached. + * + * Must be called, otherwise streaming cannot commence. + * Can be called only once. + * + * @retval true on success. + */ + virtual bool allSourcesAttached() = 0; + + /** + * @brief Starts playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request playback and then return. + * + * Once the backend is successfully playing it should notify the + * media player client of playback state + * IMediaPipelineClient::PlaybackState::PLAYING. + * + * @retval true on success. + */ + virtual bool play() = 0; + + /** + * @brief Pauses playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the playback pause and then return. + * + * Once the backend is successfully playing it should notify the + * media player client of playback state + *IMediaPipelineClient::PlaybackState::PAUSED. + * + * @retval true on success. + */ + virtual bool pause() = 0; + + /** + * @brief Stops playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the playback stop and then return. + * + * Once the backend is successfully stopped it should notify the + * media player client of playback state + * IMediaPipelineClient::PlaybackState::STOPPED. + * + * @retval true on success. + */ + virtual bool stop() = 0; + + /** + * @brief Set the playback rate + * + * This method sets the playback rate. The supported playback rates + * are dependent upon the backend playback method. + * + * @param[in] rate : The playback rate. + * + * @retval true on success. + */ + virtual bool setPlaybackRate(double rate) = 0; + + /** + * @brief Set the playback position in nanoseconds. + * + * If playback has not started this method sets the start position + * for playback. If playback has started this method performs a seek. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the new playback position and then return. + * + * Once the backend is seeking it should notify the media player + * client of playback state + * IMediaPipelineClient::PlaybackState::SEEKING. When seeking has + * completed the state IMediaPipelineClient::PlaybackState::SEEK_DONE + * should be notified followed by + * IMediaPipelineClient::PlaybackState::PLAYING. + * + * @param[in] position : The playback position in nanoseconds. + * + * @retval true on success. + */ + virtual bool setPosition(int64_t position) = 0; + + /** + * @brief Get the playback position in nanoseconds. + * + * This method is sychronous, it returns current playback position + * + * @param[out] position : The playback position in nanoseconds + * + * @retval true on success. + */ + virtual bool getPosition(int64_t &position) = 0; + + /** + * @brief Get stats for this source. + * + * This method is sychronous, it returns dropped frames and rendered frames + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[out] renderedFrames : The number of rendered frames + * @param[out] droppedFrames : The number of dropped frames + * + * @retval true on success. + */ + virtual bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; + + /** + * @brief Sets the "Immediate Output" property for this source. + * + * This method is asynchronous, it will set the "Immediate Output" property + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] immediateOutput : Set immediate output mode on the sink + * + * @retval true on success. + */ + virtual bool setImmediateOutput(int32_t sourceId, bool immediateOutput) = 0; + + /** + * @brief Gets the "Immediate Output" property for this source. + * + * This method is sychronous, it gets the "Immediate Output" property + * + * @param[in] sourceId : The source id. Value should be get to the MediaSource.id returned after attachSource() + * @param[out] immediateOutput : Get immediate output mode on the sink + * + * @retval true on success. + */ + virtual bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) = 0; + + /** + * @brief Sets the coordinates of where the video should be displayed. + * + * @param[in] x : The x position in pixels. + * @param[in] y : The y position in pixels. + * @param[in] width : The width in pixels. + * @param[in] height : The height in pixels. + * + * @retval true on success. + */ + virtual bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; + + /** + * @brief Returns data requested using notifyNeedMediaData(). + * + * This method is called as a result of calling notifyNeedMediaData() on + * the media client. The status value indicates the success or + * otherwise of the request. The client must first call addSegment() for + * for each media segment to be sent. + * A status of MediaSourceStatus::OK indicates success and there will + * be data within the data vector. A status of MediaSourceStatus::EOS + * indicates success but the end of the stream was reached. Again + * there will be data in the vector. A status of + * MediaSourceStatus::ERROR indicates an error occurred and no data + * was returned. + * + * + * @param[in] status : The status + * @param[in] needDataRequestId : Need data request id + */ + virtual bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) = 0; + + /** + * @brief Adds a single segment to Rialto in response to notifyNeedData() + * + * This method is should be called by the client as a result of a notifyNeedData() + * notification. The client should call this API for each segment to be sent in + * response to the notification and then call haveData() when all segments + * have been 'added'. + * + * If the return code is NO_SPACE the segment has not been accepted but this is + * not an error. The client should retain the segment until the next notifyNeedData() + * is received for the source and immediately call haveData() to trigger Rialto + * to start processing the segments already added. + * + * @param[in] needDataRequestId : The status + * @param[in] mediaSegment : The data returned. + * + * @retval status of adding segment + */ + virtual AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) = 0; + + /** + * @brief Requests to render a prerolled frame + */ + virtual bool renderFrame() = 0; + + /** + * @brief Set the target volume level and transition duration with easing type. + * By default volume is set immediately if duration and type are not set. + * + * @param[in] targetVolume : Target volume level (0.0 - 1.0) + * @param[in] volumeDuration : (Optional) Duration of the volume transition in milliseconds + * @param[in] easeType : (Optional) Easing type for the volume transition + * + * @retval true on success, false otherwise. + */ + virtual bool setVolume(double targetVolume, uint32_t volumeDuration = 0, + EaseType easeType = EaseType::EASE_LINEAR) = 0; + + /** + * @brief Get current audio level. Fetches the current volume level for the pipeline. + * + * @param[out] currentVolume : Current volume level (range 0.0 - 1.0) + * + * @retval true on success, false otherwise. + */ + virtual bool getVolume(double ¤tVolume) = 0; + + /** + * @brief Set mute status of pipeline. + * + * Change mute status of media source + * + * @param[in] sourceId Source, which mute status should be changed + * @param[in] mute Desired mute state, true=muted, false=not muted + * + * @retval true on success false otherwise + */ + virtual bool setMute(int32_t sourceId, bool mute) = 0; + + /** + * @brief Get current mute status of the media source + * + * @param[in] sourceId Source, which mute status should be fetched + * @param[out] mute Current mute state + * + * @retval true on success false otherwise + */ + virtual bool getMute(int32_t sourceId, bool &mute) = 0; + + /** + * @brief Change Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + virtual bool setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; + + /** + * @brief Get Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; + + /** + * @brief Set low latency property on the audio sink. Default false. + * + * For use with gaming (no audio decoding, no a/v sync). + * + * @param[in] lowLatency : The low latency value to set. + * + * @retval true on success false otherwise + */ + virtual bool setLowLatency(bool lowLatency) = 0; + + /** + * @brief Set sync property on the audio sink. Default false. + * + * Syncs the stream on the clock. + * + * @param[in] sync : The sync value to set. + * + * @retval true on success false otherwise + */ + virtual bool setSync(bool sync) = 0; + + /** + * @brief Get sync property on the audio sink. + * + * @param[out] sync : Current sync value. + * + * @retval true on success false otherwise + */ + virtual bool getSync(bool &sync) = 0; + + /** + * @brief Set sync off property on the audio decoder. Default false. + * + * Turn on free running audio. Must be set before pipeline is PLAYING state. + * + * @param[in] syncOff : The sync off value to set. + * + * @retval true on success false otherwise + */ + virtual bool setSyncOff(bool syncOff) = 0; + + /** + * @brief Set stream sync mode property on the audio decoder or video filter. Default 0. + * + * 1 - Frame to decode frame will immediately proceed next frame sync. + * 0 - Frame decoded with no frame sync. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] streamSyncMode : The stream sync mode value to set. + * + * @retval true on success false otherwise + */ + virtual bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) = 0; + + /** + * @brief Get stream sync mode property on the audio decoder. + * + * @param[out] streamSyncMode : Current stream sync mode value. + * + * @retval true on success false otherwise + */ + virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; + + /** + * @brief Flushes a source. + * + * This method is called by Rialto Client to flush out all queued data for a media source stream. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] resetTime : True if time should be reset + * @param[out] async : True if flushed source is asynchronous (will preroll after flush) + * + * @retval true on success. + */ + virtual bool flush(int32_t sourceId, bool resetTime, bool &async) = 0; + + /** + * @brief Set the source position in nanoseconds. + * + * This method sets the start position for a source. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] position : The position in nanoseconds. + * @param[in] resetTime : True if time should be reset + * @param[in] appliedRate : The applied rate after seek. Default value is 1.0. + * @param[in] stopPosition : The position of last pushed buffer + * + * @retval true on success. + */ + virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, + uint64_t stopPosition = kUndefinedPosition) = 0; + + /** + * @brief Set the subtitle offset in nanoseconds. + * + * This method sets the subtitle offset for a subtitle source. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] position : The offset position in nanoseconds. + * + * @retval true on success. + */ + virtual bool setSubtitleOffset(int32_t sourceId, int64_t position) = 0; + + /** + * @brief Process audio gap + * + * This method handles audio gap in order to avoid audio pops during transitions. + * + * @param[in] position : Audio pts fade position + * @param[in] duration : Audio pts fade duration + * @param[in] discontinuityGap : Audio discontinuity gap + * @param[in] audioAac : True if audio codec is AAC + * + * @retval true on success. + */ + virtual bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; + + /** + * @brief Set buffering limit + * + * This method enables/disables limit buffering and sets millisecond threshold used. + * Use kInvalidLimitBuffering to disable limit buffering + * + * @param[in] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + virtual bool setBufferingLimit(uint32_t limitBufferingMs) = 0; + + /** + * @brief Get buffering limit + * + * This method returns current value of buffering limit in milliseconds + * Method will return kInvalidLimitBuffering limit buffering is disabled + * + * @param[out] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; + + /** + * @brief Enables/disables the buffering option + * + * This method enables the buffering option so that BUFFERING messages are + * emitted based on low-/high-percent thresholds. + * + * @param[in] useBuffering : true if buffering option enabled. + * + * @retval true on success. + */ + virtual bool setUseBuffering(bool useBuffering) = 0; + + /** + * @brief Checks, if buffering is enabled + * + * This method returns true, if buffering is enabled + * + * @param[out] useBuffering : true if buffering option is enabled. + * + * @retval true on success. + */ + virtual bool getUseBuffering(bool &useBuffering) = 0; + + /** + * @brief Switches a source stream. + * + * This method is called to switch a media source stream. + * + * @param[in] source : The source. + * + * @retval true on success. + */ + virtual bool switchSource(const std::unique_ptr &source) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaPipelineCapabilities.h b/middleware/rialto-client/media/public/include/IMediaPipelineCapabilities.h new file mode 100644 index 000000000..f63a816c4 --- /dev/null +++ b/middleware/rialto-client/media/public/include/IMediaPipelineCapabilities.h @@ -0,0 +1,123 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ + +/** + * @file IMediaPipelineCapabilities.h + * + * The definition of the IMediaPipelineCapabilities interface. + */ + +#include "MediaCommon.h" +#include +#include +#include + +namespace firebolt::rialto +{ +class IMediaPipelineCapabilities; + +/** + * @brief IMediaPipelineCapabilities factory class, for getting the IMediaPipelineCapabilities object. + */ +class IMediaPipelineCapabilitiesFactory +{ +public: + IMediaPipelineCapabilitiesFactory() = default; + virtual ~IMediaPipelineCapabilitiesFactory() = default; + + /** + * @brief Gets the IMediaPipelineCapabilitiesFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates the IMediaPipelineCapabilities object. + * + * @retval the MediaPipelineCapabilities instance or null on error. + */ + virtual std::unique_ptr createMediaPipelineCapabilities() const = 0; +}; + +/** + * @brief The definition of the IMediaPipelineCapabilities interface. + * + * This interface defines the public API of Rialto for querying EME decryption capabilities. + * It should be implemented by both Rialto Client & Rialto Server. + */ +class IMediaPipelineCapabilities +{ +public: + IMediaPipelineCapabilities() = default; + virtual ~IMediaPipelineCapabilities() = default; + + IMediaPipelineCapabilities(const IMediaPipelineCapabilities &) = delete; + IMediaPipelineCapabilities &operator=(const IMediaPipelineCapabilities &) = delete; + IMediaPipelineCapabilities(IMediaPipelineCapabilities &&) = delete; + IMediaPipelineCapabilities &operator=(IMediaPipelineCapabilities &&) = delete; + + /** + * @brief Returns the MSE mime types supported by Rialto for \a sourceType + * + * @param[in] sourceType : source type + * + * @retval The supported mime types. + */ + virtual std::vector getSupportedMimeTypes(MediaSourceType sourceType) = 0; + + /** + * @brief Indicates if the specified mime type is supported. + * + * This method should be called to ensure that the specified mime + * type is supported by Rialto. + * + * @param[in] mimeType : The mime type to check. + * + * @retval true if supported. + */ + virtual bool isMimeTypeSupported(const std::string &mimeType) = 0; + + /** + * @brief Check sinks and decoders for supported properties + * + * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched + * @param[in] propertyNames : A vector of property names to look for + * + * @retval Returns the subset of propertyNames that are supported by the mediaType + */ + virtual std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) = 0; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + virtual bool isVideoMaster(bool &isVideoMaster) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaPipelineClient.h b/middleware/rialto-client/media/public/include/IMediaPipelineClient.h new file mode 100644 index 000000000..ad66f152a --- /dev/null +++ b/middleware/rialto-client/media/public/include/IMediaPipelineClient.h @@ -0,0 +1,222 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ +#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ + +#include +#include +#include +#include + +/** + * @file IMediaPipelineClient.h + * + * The definition of the IMediaPipelineClient interface. + * + * This file comprises the definition of the IMediaPipelineClient abstract + * class. This is the API by which a IMediaPipeline implementation will + * pass notifications to its client. + */ + +namespace firebolt::rialto +{ +/* Values representing custom duration values, used by IMediaPipelineClient::notifyDuration() method*/ +/** + * @brief Stream duration is unknown or undefined + * + */ +constexpr int64_t kDurationUnknown{-1}; +/** + * @brief Stream duration is unending or live + */ +constexpr int64_t kDurationUnending{-2}; + +/** + * @brief The Rialto media player client interface. + * + * This is The Rialto media player client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the + * state of the player or that provides data for media playback. + */ +class IMediaPipelineClient +{ +public: + /** + * @brief Virtual destructor + */ + virtual ~IMediaPipelineClient() {} + + /** + * @brief Notifies the client of the total duration of the media. + * + * This method notifies the client of the total duration of the + * media in nanoseconds. If this is unknown or undefined then a value + * of kDurationUnknown. If the stream is unending, for example + * live, then a value of kDurationUnending should be used. + * + * @param[in] duration : The duration of the media in seconds. + */ + virtual void notifyDuration(int64_t duration) = 0; + + /** + * @brief Notifies the client of the current playback position. + * + * This method notifies the client of the current playback position + * in nanoseconds. + * + * When playing this should be called often enough to provide + * sufficient granularity of position reporting. Typically this will + * be every 0.25s. + * + * @param[in] position : The playback position in nanoseconds. + */ + virtual void notifyPosition(int64_t position) = 0; + + /** + * @brief Notifies the client of the native size of the video and + the pixel aspect ratio. + * + * This method should be called one or more times to reporting the + * native video size. If the video size changes the method should be + * called with the updated size or aspect ratio. + * + * @param[in] width : The width in pixels. + * @param[in] height : The height in pixels. + * @param[in] aspect : The pixel aspect ratio. + */ + virtual void notifyNativeSize(uint32_t width, uint32_t height, double aspect = 1.0) = 0; + + /** + * @brief Notifies the client of the network state. + * + * The network state reflects the state of the network. For backend + * streaming, this is important as the backend uses the network to obtain the media data directly. + * + * For streaming that uses the browser to obtain data, say Media Source + * Extensions playback, only the states NetworkState::IDLE, + * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be + * indicated by the backend. + * + * @param[in] state : The new network state. + */ + virtual void notifyNetworkState(NetworkState state) = 0; + + /** + * @brief Notifies the client of the playback state. + * + * The player will start IDLE. Once play() has been called the player + * will be PLAYING, or once pause() has been called the player will be + * PAUSED. A seek() request will result in SEEKING and once the seek + * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED + * state will be issued after a stop() request. + * + * @param[in] state : The new playback state. + */ + virtual void notifyPlaybackState(PlaybackState state) = 0; + + /** + * @brief Notifies the client that video data is available + * + * @param[in] hasData: true if video data is available. + */ + virtual void notifyVideoData(bool hasData) = 0; + + /** + * @brief Notifies the client that audio data is available + * + * @param[in] hasData: true if audio data is available. + */ + virtual void notifyAudioData(bool hasData) = 0; + + /** + * @brief Notifies the client that we need media data. + * + * This method notifies the client that we need media data from the + * client. This is only used when Media Source Extensions are used. + * In that case media is read by JavaScript and buffered by the + * browser before being passed to this API for decoding. + * + * You cannot request data if a data request is currently pending. + * + * The frames the client sends should meet the criteria: + * numFramesSent <= frameCount + * numBytesSent <= maxMediaBytes + * + * @param[in] sourceId : The source to read data from. + * @param[in] frameCount : The number of frames to read. + * @param[in] needDataRequestId : Need data request id. + * @param[in] shmInfo : Information for populating the shared memory (null if not applicable to the client). + */ + virtual void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, + const std::shared_ptr &shmInfo) = 0; + + /** + * @brief Notifies the client to cancel any outstand need request. + * + * This method notifies the client to cancel any data request made using + * notifyNeedMediaData(). It is not an error to cancel a request for data + * when one is not pending. + * + * @param[in] sourceId : The source id to cancel the request for. + */ + virtual void notifyCancelNeedMediaData(int32_t sourceId) = 0; + + /** + * @brief Notifies the client of a Quality Of Service update from the Player. + * + * Notification shall be sent whenever a video/audio buffer drops a frame/sample. + * + * @param[in] sourceId : The id of the source that produced the Qos. + * @param[in] qosInfo : The information provided in the update. + */ + virtual void notifyQos(int32_t sourceId, const QosInfo &qosInfo) = 0; + + /** + * @brief Notifies the client that buffer underflow occurred. + * + * Notification shall be sent whenever a video/audio buffer underflow occurs + * + * @param[in] sourceId : The id of the source that produced the buffer underflow + */ + virtual void notifyBufferUnderflow(int32_t sourceId) = 0; + + /** + * @brief Notifies the client that a non-fatal error has occurred in the player. + * + * PlaybackState remains unchanged when an error occurs. + * + * @param[in] sourceId : The id of the source that produced the error. + * @param[in] error : The type of error that occured. + */ + virtual void notifyPlaybackError(int32_t sourceId, PlaybackError error) = 0; + + /** + * @brief Notifies the client that the source has been flushed. + * + * Notification shall be sent whenever a flush procedure is finished. + * + * @param[in] sourceId : The id of the source that has been flushed. + */ + virtual void notifySourceFlushed(int32_t sourceId) = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ diff --git a/middleware/rialto-client/media/public/include/IWebAudioPlayer.h b/middleware/rialto-client/media/public/include/IWebAudioPlayer.h new file mode 100644 index 000000000..d29d6677a --- /dev/null +++ b/middleware/rialto-client/media/public/include/IWebAudioPlayer.h @@ -0,0 +1,216 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ +#define FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ + +/** + * @file IWebAudioPlayer.h + * + * The definition of the IWebAudioPlayer interface. + * + * This interface defines the public API of Rialto for mixing PCM audio with + * current audio output. + */ + +#include +#include +#include + +#include "IWebAudioPlayerClient.h" +#include "MediaCommon.h" + +namespace firebolt::rialto +{ +class IWebAudioPlayer; + +/** + * @brief IWebAudioPlayer factory class, returns a concrete implementation of IWebAudioPlayer + */ +class IWebAudioPlayerFactory +{ +public: + IWebAudioPlayerFactory() = default; + virtual ~IWebAudioPlayerFactory() = default; + + /** + * @brief Create a IWebAudioPlayerFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IWebAudioPlayer factory method, returns a concrete implementation of + * IWebAudioPlayer for playback of audio. + * + * @param[in] client: The Web Audio Player client + * @param[in] audioMimeType: The audio encoding format, currently only "audio/x-raw" (PCM) + * @param[in] priority: Priority value for this pipeline. + * @param[in] config: Additional type dependent configuration data or nullptr + * + * Some platforms have limited numbers of audio playbacks that can be mixed. The client application + * should therefore assign a priority to each audio player it creates, starting with priority 1 for + * the most important, priority 2 for the next etc. If a platform supports 'n' players, then any + * player with priority>n will appear to function normally by but the audio data will be silently + * discarded. + * + * @retval the new Web Audio Player instance or null on error. + */ + virtual std::unique_ptr createWebAudioPlayer(std::weak_ptr client, + const std::string &audioMimeType, + const uint32_t priority, + std::weak_ptr config) const = 0; +}; + +/** + * @brief The definition of the IWebAudioPlayer interface. + * + * This interface defines the public API of Rialto for mixing PCM audio with + * current audio output. It should be implemented by both Rialto Client & + * Rialto Server. + */ +class IWebAudioPlayer +{ +public: + IWebAudioPlayer() = default; + virtual ~IWebAudioPlayer() = default; + + IWebAudioPlayer(const IWebAudioPlayer &) = delete; + IWebAudioPlayer &operator=(const IWebAudioPlayer &) = delete; + IWebAudioPlayer(IWebAudioPlayer &&) = delete; + IWebAudioPlayer &operator=(IWebAudioPlayer &&) = delete; + + /** + * @brief Play the web audio. + * + * Sets the player to the PLAYING state (it is IDLE when created). + * + * @retval true on success. + */ + virtual bool play() = 0; + + /** + * @brief Pause the web audio. + * + * Sets the player to the PAUSED state (it is IDLE when created). + * + * @retval true on success. + */ + virtual bool pause() = 0; + + /** + * @brief Notify EOS. + * + * Notifies the player that no further frames will be provided. When + * all buffered frames are played the player will enter the EOS state. + * + * @retval true on success. + */ + virtual bool setEos() = 0; + + /** + * @brief Get the available frames. + * + * Gets the available buffer space for sending more frames. Client should not + * write more than the number of frames returned by this API. + * + * webAudioShmInfo is not required by the client application and can be ignored. + * + * @param[out] availableFrames : Number of frames available to be written. + * @param[out] webAudioShmInfo : Location in shm to write the data (Server only). + * + * @retval true on success. + */ + virtual bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) = 0; + + /** + * @brief Get the delay frames. + * + * Gets the frame delay of the playback from Rialto. Frame delay is the number + * of frames left to play by the server. + * + * @param[out] delayFrames : Number of frames to be played. + * + * @retval true on success. + */ + virtual bool getBufferDelay(uint32_t &delayFrames) = 0; + + /** + * @brief Write audio frames + * + * Sends a buffer of audio data for playback + * + * @param[in] numberOfFrames : Number of frames of audio in 'data'. + * @param[in] data : Pointer to the data, byte length = numberOfFrames*sampleSize + * + * @retval true on success. + */ + virtual bool writeBuffer(const uint32_t numberOfFrames, void *data) = 0; + + /** + * @brief Get device information. + * + * Gets information for the web audio playback. + * This information is used to determine the preferred buffer size to commit, + * the maximum buffer size an application can commit and whether buffers can + * be committed before a Play request. + * + * @param[out] preferredFrames : preferred number of frames to be commited. + * @param[out] maximumFrames : Maximum number of frames that can be commited. + * @param[out] supportDeferredPlay : Whether defered play is supported. + * + * @retval true on success. + */ + virtual bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) = 0; + + /** + * + * @brief Set level and transition of audio attenuation + * + * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume) + * + * @param[in] volume : Target volume level (0.0 - 1.0) + * + * @retval true on success false otherwise + */ + virtual bool setVolume(double volume) = 0; + + /** + * @brief Get current audio level + * + * Fetches the current volume level for the pipeline. + * + * @param[out] volume : Current volume level (range 0.0 - 1.0) + * + * @retval true on success false otherwise + */ + virtual bool getVolume(double &volume) = 0; + + /** + * @brief Returns the web audio player client. + * + * @retval The web audio player client. + */ + virtual std::weak_ptr getClient() = 0; +}; + +}; // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ diff --git a/middleware/rialto-client/media/public/include/IWebAudioPlayerClient.h b/middleware/rialto-client/media/public/include/IWebAudioPlayerClient.h new file mode 100644 index 000000000..0c58dbef3 --- /dev/null +++ b/middleware/rialto-client/media/public/include/IWebAudioPlayerClient.h @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ +#define FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ + +/** + * @file IWebAudioPlayerClient.h + * + * The definition of the IWebAudioPlayerClient interface. + * + * This is the API by which a IWebAudioPlayer implementation will + * pass notifications to its client. + */ + +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief The Rialto web audio client interface. + * + * This is The Rialto web audio player client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the + * state of the web audio player. + */ +class IWebAudioPlayerClient +{ +public: + /** + * @brief Virtual destructor + */ + virtual ~IWebAudioPlayerClient() {} + + /** + * @brief Notifies the client of the playback state. + * + * The player will start IDLE. Once play() has been called the player + * will be PLAYING. When pause() is call3d the player will be PAUSED. + * When no further frames available for playout and setEos() has been + * called the player will be END_OF_STREAM. + * + * @param[in] state : The new playback state. + */ + virtual void notifyState(WebAudioPlayerState state) = 0; +}; + +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ diff --git a/middleware/rialto-client/media/public/include/MediaCommon.h b/middleware/rialto-client/media/public/include/MediaCommon.h new file mode 100644 index 000000000..199ffaf98 --- /dev/null +++ b/middleware/rialto-client/media/public/include/MediaCommon.h @@ -0,0 +1,470 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_MEDIA_COMMON_H_ +#define FIREBOLT_RIALTO_MEDIA_COMMON_H_ + +/** + * @file MediaCommon.h + * + * The definition of the Rialto Common types + * + */ + +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief The value of an invalid key session. + */ +constexpr int32_t kInvalidSessionId{-1}; + +/** + * @brief The value of an invalid audio channels number. + */ +constexpr uint32_t kInvalidAudioChannels{0}; + +/** + * @brief The value of an invalid audio sampling rate. + */ +constexpr uint32_t kInvalidAudioSampleRate{0}; + +/** + * @brief The value of an undefined size + */ +constexpr int32_t kUndefinedSize{0}; + +/** + * @brief The value of an invalid limitBuffering + */ +constexpr uint32_t kInvalidLimitBuffering{std::numeric_limits::max()}; + +/** + * @brief The value of undefined position + */ +constexpr uint64_t kUndefinedPosition{std::numeric_limits::max()}; + +/** + * @brief The supported types of media source. + */ +enum class MediaSourceType +{ + UNKNOWN, + AUDIO, + VIDEO, + SUBTITLE +}; + +/** + * @brief Shows the types of source configuration. + */ +enum class SourceConfigType +{ + UNKNOWN, + AUDIO, + VIDEO, + VIDEO_DOLBY_VISION, + SUBTITLE +}; + +/** + * @brief The supported audio ease types. + */ +enum class AudioEaseType +{ + LINEAR = 0, + INCUBIC, + OUTCUBIC +}; + +/** + * @brief The media type of media to be played. + */ +enum class MediaType +{ + UNKNOWN, /**< Media type not known. */ + MSE /**< Media is MSE and will request data. */ +}; + +/** + * @brief The media source status. This is the status of the source + * after a read. + */ +enum class MediaSourceStatus +{ + OK, /**< Source data provided without error. */ + EOS, /**< Source reached the end of stream. */ + ERROR, /**< There was an error providing source data. */ + CODEC_CHANGED, /**< The codec has changed and the decoder must be reconfigured */ + NO_AVAILABLE_SAMPLES /**< Could not retrieve media samples. */ +}; + +/** + * @brief The Network State + * + * The network state reflects the state of the network. For backend + * streaming, say using MediaPipelineURLDelegate, this is important + * as the backend uses the network to obtain the media data directly. + * + * For streaming that uses the browser to obtain data, say Media Source + * Extensions playback, only the states NetworkState::IDLE, + * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be + * indicated by the backend. + */ +enum class NetworkState +{ + UNKNOWN, /**< An unknown or undefined network state. */ + IDLE, /**< The network is idle. */ + BUFFERING, /**< The network is buffering data before playing. */ + BUFFERING_PROGRESS, /**< The network is buffering data whilst playing. */ + BUFFERED, /**< All the data is buffered. */ + STALLED, /**< The network has stalled but may recover. */ + FORMAT_ERROR, /**< The data is the wrong format. */ + NETWORK_ERROR, /**< There has been a network error. Playback stops. */ + DECODE_ERROR /**< There has been a decode error of the data. */ +}; + +/** + * @brief The Playback State + * + * The player will start IDLE. Once play() has been called the player + * will be PLAYING, or once pause() has been called the player will be + * PAUSED. A seek() request will result in SEEKING and once the seek + * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED + * state will be issued after a stop() request. + */ +enum class PlaybackState +{ + UNKNOWN, /**< An unknown or undefined playback state. */ + IDLE, /**< The backend player is idle. */ + PLAYING, /**< The backend player is playing media. */ + PAUSED, /**< The backend player is paused. */ + SEEKING, /**< The backend player is seeking a new playback position. */ + SEEK_DONE, /**< The backend player has finished seek. */ + STOPPED, /**< The backend player has stopped playback. */ + END_OF_STREAM, /**< The backend player has got to the end of playback. */ + FAILURE /**< The backend player failed to set playback state. */ +}; + +/** + * @brief The Format of the audio samples. Used by the raw audio media types + */ +enum class Format +{ + S8, + U8, + S16LE, + S16BE, + U16LE, + U16BE, + S24_32LE, + S24_32BE, + U24_32LE, + U24_32BE, + S32LE, + S32BE, + U32LE, + U32BE, + S24LE, + S24BE, + U24LE, + U24BE, + S20LE, + S20BE, + U20LE, + U20BE, + S18LE, + S18BE, + U18LE, + U18BE, + F32LE, + F32BE, + F64LE, + F64BE +}; + +/** + * @brief The layout of channels within a buffer. Used by the raw audio media types + */ +enum class Layout +{ + INTERLEAVED, + NON_INTERLEAVED +}; + +/** + * @brief Audio specific configuration + */ +struct AudioConfig +{ + uint32_t numberOfChannels = kInvalidAudioChannels; /**< The number of channels. */ + uint32_t sampleRate = kInvalidAudioSampleRate; /**< The sampling rate.*/ + std::vector codecSpecificConfig; /**< The audio specific config. Zero length if no specific config*/ + std::optional format; /**< The Format of the audio samples.*/ + std::optional layout; /**< The layout of channels within a buffer.*/ + std::optional channelMask; /**< Bitmask of channel positions present. */ + std::vector> streamHeader; /**< Stream header. Zero length if not present.*/ + std::optional + framed; /**< True if each buffer passed through the pipeline contains a complete, self-contained media unit*/ +}; + +/** + * @brief AddSegmentStatus + * + * The add segment status. This is the status adding new segment to Rialto + */ +enum class AddSegmentStatus +{ + OK, /**< Segment accepted. */ + NO_SPACE, /**< Too many frames sent or Rialto does not currently have space for this segment. */ + ERROR /**< Unexpected error. */ +}; + +/** + * @brief A pair describing the clear and encrypted bytes + * in a sub-sample. + */ +struct SubSamplePair +{ + size_t numClearBytes; /**< The number of clear bytes in the sample. */ + size_t numEncryptedBytes; /**< The number of encrypted bytes in the sample. */ +}; + +/** + * @brief Video decoder requirements used to allocate a suitable decoder for a MediaPipeline session + */ +struct VideoRequirements +{ + uint32_t maxWidth; /**< Maximum width of video frames to be decoded. */ + uint32_t maxHeight; /**< Maximum height of video frames to be decoded. */ +}; + +/** + * @brief Information about the shared memory required for writting data. + */ +struct MediaPlayerShmInfo +{ + uint32_t maxMetadataBytes; /**< The maximum amount of metadata that can be written. */ + uint32_t metadataOffset; /**< The offset to write the metadata. */ + uint32_t mediaDataOffset; /**< The offset to write the media data. */ + uint32_t maxMediaBytes; /**< The maximum amount of mediadata that can be written. */ +}; + +/** + * @brief The information provided in a QOS update. + */ +struct QosInfo +{ + uint64_t processed; /**< The total number of video frames/audio samples processed since MediaPipeline:load. */ + uint64_t dropped; /**< The total number of video frames/audio samples dropped since MediaPipeline:load. */ +}; + +/** + * @brief The error return status for session management methods. + */ +enum class MediaKeyErrorStatus +{ + OK, /**< No error. */ + FAIL, /**< An unspecified error occurred. */ + BAD_SESSION_ID, /**< The session id is not recognised. */ + NOT_SUPPORTED, /**< The request parameters are not supported. */ + INVALID_STATE, /**< The object is in an invalid state for the operation. */ + INTERFACE_NOT_IMPLEMENTED, /**< The interface is not implemented. */ + BUFFER_TOO_SMALL /**< The size of the buffer is too small. */ +}; + +/** + * @brief The media key session type. + */ +enum class KeySessionType +{ + UNKNOWN, /**< The session type is unknown. */ + TEMPORARY, /**< The session is a temporary session. */ + PERSISTENT_LICENCE, /**< The session is a persistent session. */ + PERSISTENT_RELEASE_MESSAGE /**< The session's persistent licence should be released. */ +}; + +/** + * @brief The init data type. + */ +enum class InitDataType +{ + UNKNOWN, /**< The init data type is unknown. */ + CENC, /**< The init data is in CENC format. */ + KEY_IDS, /**< The init data is key ids. */ + WEBM, /**< The init data is in WEBM format. */ + DRMHEADER /**< The init data is in DrmHeader format. */ +}; + +/** + * @brief The key status. + */ +enum class KeyStatus +{ + USABLE, + EXPIRED, + OUTPUT_RESTRICTED, + PENDING, + INTERNAL_ERROR, + RELEASED +}; + +/** + * @brief The alignment of media segment + */ +enum class SegmentAlignment +{ + UNDEFINED, + NAL, + AU +}; + +/** + * @brief The Stream Format of media segment + */ +enum class StreamFormat +{ + UNDEFINED, + RAW, + AVC, + BYTE_STREAM, + HVC1, + HEV1 +}; + +/** + * @brief A vector of key ID/key status pairs. + */ +typedef std::vector, KeyStatus>> KeyStatusVector; + +/** + * @brief Information about the shared memory required for writting data for the web audio playback. + */ +struct WebAudioShmInfo +{ + uint32_t offsetMain; /**< The offset to start writing the audio data. */ + uint32_t lengthMain; /**< The maximum number of bytes to write at offsetMain. */ + uint32_t offsetWrap; /**< The offset to continue writing the audio data if buffer wrapped. */ + uint32_t lengthWrap; /**< The maximum number of bytes to write at offsetWrap. */ +}; + +/** + * @brief Pcm config information. + */ +struct WebAudioPcmConfig +{ + uint32_t rate; /**< Rate of web audio (Hz) */ + uint32_t channels; /**< Number of channels */ + uint32_t sampleSize; /**< Size of each sample (bits) */ + bool isBigEndian; /**< Specifies if sample is stored as big-endian or little-endian format */ + bool isSigned; /**< Specifies if samples are signed or unsigned */ + bool isFloat; /**< Specifies if samples are float values or interger values*/ +}; + +/** + * @brief Type dependent configuration data. + */ +union WebAudioConfig +{ + /** + * @brief PCM audio configuration. + */ + WebAudioPcmConfig pcm; +}; + +/** + * @brief The Web Audio Player State. + */ +enum class WebAudioPlayerState +{ + UNKNOWN, /**< An unknown or undefined playback state. */ + IDLE, /**< The player is ready to play media. */ + PLAYING, /**< The player is playing media. */ + PAUSED, /**< The player is has paused media playback. */ + END_OF_STREAM, /**< The player has got to the end of playback. */ + FAILURE /**< The player failed to set playback state. */ +}; + +/** + * @brief Cipher mode for common encryption, see https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-3:v1:en + */ +enum class CipherMode +{ + UNKNOWN, + CENC, /* AES-CTR scheme */ + CBC1, /* AES-CBC scheme */ + CENS, /* AES-CTR subsample pattern encryption scheme */ + CBCS /* AES-CBC subsample pattern encryption scheme */ +}; + +/** + * @brief Fraction type. + */ +struct Fraction +{ + int32_t numerator; /**< The numerator */ + int32_t denominator; /**< The denominator */ +}; + +/** + * @brief Codec data type. + */ +enum class CodecDataType +{ + BUFFER, + STRING +}; + +/** + * @brief Codec data with type. + */ +struct CodecData +{ + std::vector data{}; /**< The codec data */ + CodecDataType type{CodecDataType::BUFFER}; /**< The codec data type */ +}; + +/** + * @brief None fatal asynchronous errors reported by the player. + */ +enum class PlaybackError +{ + UNKNOWN, + DECRYPTION, /* Player failed to decrypt a buffer and the frame has been dropped */ +}; + +/** + * @brief Ease type for audio volume changes. + */ +enum class EaseType +{ + EASE_LINEAR, + EASE_IN_CUBIC, + EASE_OUT_CUBIC +}; + +} // namespace firebolt::rialto + +#endif // FIREBOLT_RIALTO_MEDIA_COMMON_H_ diff --git a/middleware/rialto-client/media/server/CMakeLists.txt b/middleware/rialto-client/media/server/CMakeLists.txt new file mode 100644 index 000000000..665b3a9d8 --- /dev/null +++ b/middleware/rialto-client/media/server/CMakeLists.txt @@ -0,0 +1,77 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +add_subdirectory(common) +add_subdirectory(gstplayer) +add_subdirectory(main) +add_subdirectory(ipc) +add_subdirectory(service) + +add_executable ( + RialtoServer + + service/source/main.cpp +) + + +target_include_directories ( + RialtoServer + + PRIVATE + $ + $ + $ + $ + $ + $ + $ + $ +) + +set_target_properties( + RialtoServer + PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" +) + +target_link_libraries( + RialtoServer + + PRIVATE + RialtoServerIpc + RialtoServerMain + RialtoServerService + protobuf::libprotobuf +) + +if( NATIVE_BUILD ) + set_target_properties( + RialtoServer + PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" +) +endif() + +install( + TARGETS RialtoServer + DESTINATION bin +) diff --git a/middleware/rialto-client/media/server/common/CMakeLists.txt b/middleware/rialto-client/media/server/common/CMakeLists.txt new file mode 100644 index 000000000..69f9e7bbf --- /dev/null +++ b/middleware/rialto-client/media/server/common/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +add_library( + RialtoServerCommon + INTERFACE + ) + +target_include_directories( + RialtoServerCommon + + INTERFACE + include + ) diff --git a/middleware/rialto-client/media/server/common/include/RialtoServerLogging.h b/middleware/rialto-client/media/server/common/include/RialtoServerLogging.h new file mode 100644 index 000000000..d6400a271 --- /dev/null +++ b/middleware/rialto-client/media/server/common/include/RialtoServerLogging.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RIALTO_SERVER_LOGGING_H_ +#define RIALTO_SERVER_LOGGING_H_ + +#include "RialtoLogging.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RIALTO_SERVER_LOG_FATAL(fmt, args...) RIALTO_LOG_FATAL(RIALTO_COMPONENT_SERVER, fmt, ##args) +#define RIALTO_SERVER_LOG_SYS_FATAL(err, fmt, args...) RIALTO_LOG_SYS_FATAL(RIALTO_COMPONENT_SERVER, err, fmt, ##args) +#define RIALTO_SERVER_LOG_ERROR(fmt, args...) RIALTO_LOG_ERROR(RIALTO_COMPONENT_SERVER, fmt, ##args) +#define RIALTO_SERVER_LOG_SYS_ERROR(err, fmt, args...) RIALTO_LOG_SYS_ERROR(RIALTO_COMPONENT_SERVER, err, fmt, ##args) +#define RIALTO_SERVER_LOG_WARN(fmt, args...) RIALTO_LOG_WARN(RIALTO_COMPONENT_SERVER, fmt, ##args) +#define RIALTO_SERVER_LOG_SYS_WARN(err, fmt, args...) RIALTO_LOG_SYS_WARN(RIALTO_COMPONENT_SERVER, err, fmt, ##args) +#define RIALTO_SERVER_LOG_MIL(fmt, args...) RIALTO_LOG_MIL(RIALTO_COMPONENT_SERVER, fmt, ##args) +#define RIALTO_SERVER_LOG_INFO(fmt, args...) RIALTO_LOG_INFO(RIALTO_COMPONENT_SERVER, fmt, ##args) +#define RIALTO_SERVER_LOG_DEBUG(fmt, args...) RIALTO_LOG_DEBUG(RIALTO_COMPONENT_SERVER, fmt, ##args) + +#ifdef __cplusplus +} +#endif + +#endif // RIALTO_SERVER_LOGGING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/CMakeLists.txt b/middleware/rialto-client/media/server/gstplayer/CMakeLists.txt new file mode 100644 index 000000000..8bc7291e7 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/CMakeLists.txt @@ -0,0 +1,147 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Find includes in corresponding build directories +set( CMAKE_INCLUDE_CURRENT_DIR ON ) + +# RIALTO-197: deprecated-declarations error in the latest stable2 for gstreamer. +# Should be removed once the issue is fixed. +add_compile_options( + "-Wno-deprecated-declarations" +) + +find_package( PkgConfig REQUIRED ) +pkg_check_modules( GStreamerApp REQUIRED IMPORTED_TARGET gstreamer-app-1.0 gstreamer-pbutils-1.0 gstreamer-audio-1.0) + +add_library( + RialtoServerGstPlayer + STATIC + + source/tasks/generic/AttachSamples.cpp + source/tasks/generic/AttachSource.cpp + source/tasks/generic/CheckAudioUnderflow.cpp + source/tasks/generic/DeepElementAdded.cpp + source/tasks/generic/EnoughData.cpp + source/tasks/generic/Eos.cpp + source/tasks/generic/FinishSetupSource.cpp + source/tasks/generic/Flush.cpp + source/tasks/generic/GenericPlayerTaskFactory.cpp + source/tasks/generic/HandleBusMessage.cpp + source/tasks/generic/NeedData.cpp + source/tasks/generic/Pause.cpp + source/tasks/generic/Ping.cpp + source/tasks/generic/Play.cpp + source/tasks/generic/ProcessAudioGap.cpp + source/tasks/generic/ReadShmDataAndAttachSamples.cpp + source/tasks/generic/RemoveSource.cpp + source/tasks/generic/RenderFrame.cpp + source/tasks/generic/ReportPosition.cpp + source/tasks/generic/SetBufferingLimit.cpp + source/tasks/generic/SetImmediateOutput.cpp + source/tasks/generic/SetLowLatency.cpp + source/tasks/generic/SetMute.cpp + source/tasks/generic/SetPlaybackRate.cpp + source/tasks/generic/SetPosition.cpp + source/tasks/generic/SetSourcePosition.cpp + source/tasks/generic/SetSubtitleOffset.cpp + source/tasks/generic/SetStreamSyncMode.cpp + source/tasks/generic/SetSync.cpp + source/tasks/generic/SetSyncOff.cpp + source/tasks/generic/SetTextTrackIdentifier.cpp + source/tasks/generic/SetUseBuffering.cpp + source/tasks/generic/SetVideoGeometry.cpp + source/tasks/generic/SetVolume.cpp + source/tasks/generic/SetupElement.cpp + source/tasks/generic/SetupSource.cpp + source/tasks/generic/Shutdown.cpp + source/tasks/generic/Stop.cpp + source/tasks/generic/SwitchSource.cpp + source/tasks/generic/SynchroniseSubtitleClock.cpp + source/tasks/generic/Underflow.cpp + source/tasks/generic/UpdatePlaybackGroup.cpp + + source/tasks/webAudio/Eos.cpp + source/tasks/webAudio/HandleBusMessage.cpp + source/tasks/webAudio/Pause.cpp + source/tasks/webAudio/Ping.cpp + source/tasks/webAudio/Play.cpp + source/tasks/webAudio/SetCaps.cpp + source/tasks/webAudio/SetVolume.cpp + source/tasks/webAudio/Shutdown.cpp + source/tasks/webAudio/Stop.cpp + source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp + source/tasks/webAudio/WriteBuffer.cpp + + source/CapsBuilder.cpp + source/FlushWatcher.cpp + source/GstCapabilities.cpp + source/GstDecryptor.cpp + source/GstDispatcherThread.cpp + source/GstGenericPlayer.cpp + source/GstInitialiser.cpp + source/GstLogForwarding.cpp + source/GstProtectionMetadata.cpp + source/GstProtectionMetadataHelper.cpp + source/GstSrc.cpp + source/GstTextTrackSink.cpp + source/GstWebAudioPlayer.cpp + source/NeedDataMapping.cpp + source/Utils.cpp + source/WorkerThread.cpp + ) + +target_include_directories( + RialtoServerGstPlayer + + PUBLIC + interface + + PRIVATE + include + include/tasks + include/tasks/generic + include/tasks/webAudio + $ + $ + $ + $ + $ + $ + ${GStreamerApp_INCLUDE_DIRS} + + ) + + +set_property( + TARGET RialtoServerGstPlayer + PROPERTY POSITION_INDEPENDENT_CODE ON + + ) + +target_link_libraries( + RialtoServerGstPlayer + + PRIVATE + RialtoLogging + RialtoServerMain + RialtoWrappers + RialtoCommon + RialtoPlayerCommon + ${GStreamerApp_LIBRARIES} + ) diff --git a/middleware/rialto-client/media/server/gstplayer/include/CapsBuilder.h b/middleware/rialto-client/media/server/gstplayer/include/CapsBuilder.h new file mode 100644 index 000000000..21201258e --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/CapsBuilder.h @@ -0,0 +1,99 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_CAPS_BUILDER_H_ +#define FIREBOLT_RIALTO_SERVER_CAPS_BUILDER_H_ + +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "IMediaPipeline.h" +#include +#include + +namespace firebolt::rialto::server +{ +class MediaSourceCapsBuilder +{ +public: + MediaSourceCapsBuilder(std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const firebolt::rialto::IMediaPipeline::MediaSourceAV &source); + virtual ~MediaSourceCapsBuilder() = default; + virtual GstCaps *buildCaps(); + +protected: + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + const IMediaPipeline::MediaSourceAV &m_attachedSource; + + GstCaps *buildCommonCaps(); + void addAlignmentToCaps(GstCaps *caps) const; + void addCodecDataToCaps(GstCaps *caps) const; + void addStreamFormatToCaps(GstCaps *caps) const; +}; + +class MediaSourceAudioCapsBuilder : public MediaSourceCapsBuilder +{ +public: + MediaSourceAudioCapsBuilder(std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const IMediaPipeline::MediaSourceAudio &source); + ~MediaSourceAudioCapsBuilder() override = default; + GstCaps *buildCaps() override; + +protected: + GstCaps *createOpusCaps(); + GstCaps *getAudioSpecificConfiguration() const; + void addSampleRateAndChannelsToCaps(GstCaps *caps) const; + void addMpegVersion4ToCaps(GstCaps *caps) const; + void addMp3Caps(GstCaps *caps) const; + void addRawAudioData(GstCaps *caps) const; + void addFlacSpecificData(GstCaps *caps) const; + + const IMediaPipeline::MediaSourceAudio &m_attachedAudioSource; +}; + +class MediaSourceVideoCapsBuilder : public MediaSourceCapsBuilder +{ +public: + MediaSourceVideoCapsBuilder(std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const IMediaPipeline::MediaSourceVideo &source); + ~MediaSourceVideoCapsBuilder() override = default; + GstCaps *buildCaps() override; + +protected: + const IMediaPipeline::MediaSourceVideo &m_attachedVideoSource; +}; + +class MediaSourceVideoDolbyVisionCapsBuilder : public MediaSourceVideoCapsBuilder +{ +public: + MediaSourceVideoDolbyVisionCapsBuilder(std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const IMediaPipeline::MediaSourceVideoDolbyVision &source); + ~MediaSourceVideoDolbyVisionCapsBuilder() override = default; + GstCaps *buildCaps() override; + +protected: + const IMediaPipeline::MediaSourceVideoDolbyVision &m_attachedDolbySource; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_CAPS_BUILDER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/FlushWatcher.h b/middleware/rialto-client/media/server/gstplayer/include/FlushWatcher.h new file mode 100644 index 000000000..86865570e --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/FlushWatcher.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_H_ +#define FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_H_ + +#include "IFlushWatcher.h" +#include +#include + +namespace firebolt::rialto::server +{ +class FlushWatcher : public IFlushWatcher +{ +public: + FlushWatcher() = default; + ~FlushWatcher() override = default; + + void setFlushing(const MediaSourceType &type, bool async) override; + void setFlushed(const MediaSourceType &type) override; + bool isFlushOngoing() const override; + bool isAsyncFlushOngoing() const override; + +private: + mutable std::mutex m_mutex; + std::map m_flushingSources; +}; +} // namespace firebolt::rialto::server +#endif // FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GenericPlayerContext.h b/middleware/rialto-client/media/server/gstplayer/include/GenericPlayerContext.h new file mode 100644 index 000000000..b366cd196 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GenericPlayerContext.h @@ -0,0 +1,271 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_CONTEXT_H_ +#define FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_CONTEXT_H_ + +#include "IGstSrc.h" +#include "IRdkGstreamerUtilsWrapper.h" +#include "ITimer.h" +#include "MediaCommon.h" +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +constexpr double kNoPendingPlaybackRate{0.0}; + +enum class EosState +{ + PENDING, + SET +}; + +/** + * @brief Structure used for video geometry + */ +struct Rectangle +{ + int x, y, width, height; + constexpr Rectangle() : x(0), y(0), width(0), height(0) {} + constexpr Rectangle(int x_, int y_, int w_, int h_) : x(x_), y(y_), width(w_), height(h_) {} + Rectangle(const Rectangle &rhs) = default; + inline constexpr bool empty() { return (width == 0) || (height == 0); } + inline void clear() { x = y = width = height = 0; } +}; + +/** + * @brief Structure used for set source position + */ +struct SegmentData +{ + int64_t position; + bool resetTime; + double appliedRate; + uint64_t stopPosition; +}; + +struct GenericPlayerContext +{ + /** + * @brief The rialto src object. + */ + std::shared_ptr gstSrc{nullptr}; + + /** + * @brief The gstreamer pipeline. + */ + GstElement *pipeline{nullptr}; + + /** + * @brief The gstreamer source. + */ + GstElement *source{nullptr}; + + /** + * @brief A map of streams attached to the source. + */ + StreamInfoMap streamInfo{}; + + /** + * @brief Child sink of the autovideosink. + */ + GstElement *autoVideoChildSink{nullptr}; + + /** + * @brief Child sink of the autoaudiosink. + */ + GstElement *autoAudioChildSink{nullptr}; + + /** + * @brief The subtitle sink + */ + GstElement *subtitleSink{nullptr}; + + /** + * @brief The video sink + */ + GstElement *videoSink{nullptr}; + + /** + * @brief Flag used to check, if video decoder handle has been set. + */ + bool isVideoHandleSet{false}; + + /** + * @brief Flag used to check, if BUFFERED notification has been sent. + * + * Flag can be used only in worker thread + */ + bool bufferedNotificationSent{false}; + + /** + * @brief Flag used to check, if the playback is in the playing state + * + * Flag can be used only in worker thread + */ + bool isPlaying{false}; + + /** + * @brief Flag used to check, if EOS has been notified to the client + * + * Flag can be used only in worker thread + */ + bool eosNotified{false}; + + /** + * @brief Pending video geometry + */ + Rectangle pendingGeometry; + + /** + * @brief Current playback rate + */ + double playbackRate{1.0}; + + /** + * @brief Pending playback rate + */ + double pendingPlaybackRate{kNoPendingPlaybackRate}; + + /** + * @brief Pending immediate output for MediaSourceType::VIDEO + */ + std::optional pendingImmediateOutputForVideo{}; + + /** + * @brief Pending low latency + */ + std::optional pendingLowLatency{}; + + /** + * @brief Pending sync + */ + std::optional pendingSync{}; + + /** + * @brief Pending sync off + */ + std::optional pendingSyncOff{}; + + /** + * @brief Pending buffering limit + */ + std::optional pendingBufferingLimit{}; + + /** + * @brief Pending use buffering + */ + std::optional pendingUseBuffering{}; + + /** + * @brief Pending stream sync mode + */ + std::map pendingStreamSyncMode{}; + + /** + * @brief Pending render frame + */ + bool pendingRenderFrame{false}; + + /** + * @brief Pending show video window + */ + std::optional pendingShowVideoWindow{}; + + /** + * @brief Last audio sample timestamps + * TODO(LLDEV-31012) Needed to detect audio stream underflow + */ + int64_t lastAudioSampleTimestamps{0}; + + /** + * @brief The decryption service. + */ + IDecryptionService *decryptionService{nullptr}; + + /** + * @brief Flag used to check, if audio source has been recently removed + * + * Flag can be used only in worker thread + */ + bool audioSourceRemoved{false}; + + /** + * @brief Audio elements of gst pipeline. + * + * Attribute can be used only in worker thread + */ + firebolt::rialto::wrappers::PlaybackGroupPrivate playbackGroup; + + /** + * @brief A map of streams that have ended. + */ + std::unordered_map endOfStreamInfo{}; + + /** + * @brief Flag used to check if client already notified server that all sources were attached + * + * Attribute can be used only in worker thread + */ + bool wereAllSourcesAttached{false}; + + /** + * @brief Flag used to check if FinishSetupSource is finished. It is needed to avoid need data overwriting. + * + * Attribute can be used only in worker thread + */ + bool setupSourceFinished{false}; + + /** + * @brief Queued source positions. Used by SetSourcePosition task to request pushing new sample. + * + * Attribute can be used only in worker thread + */ + std::map> initialPositions; + + /** + * @brief Currently set position of a source. Used to check, if additional segment should be pushed. + * + * Attribute can be used only in worker thread + */ + std::map currentPosition; + + /** + * @brief The mutex, which protects properties, which are read/written by main/worker thread. + * This mutex should be removed in future, when we find out better solution for + * property read-write. + */ + std::mutex propertyMutex; + + /** + * @brief Flag used to check if audio fade is enabled + * + * Attribute can be used only in worker thread + */ + std::atomic_bool audioFadeEnabled{false}; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_CONTEXT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstCapabilities.h b/middleware/rialto-client/media/server/gstplayer/include/GstCapabilities.h new file mode 100644 index 000000000..41e5854c8 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstCapabilities.h @@ -0,0 +1,167 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_SERVER_GST_CAPABILITIES_H_ + +#include "IGlibWrapper.h" +#include "IGstCapabilities.h" +#include "IGstInitialiser.h" +#include "IGstWrapper.h" +#include "IRdkGstreamerUtilsWrapper.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief GstCapabilities factory class, returns a concrete implementation of GstCapabilities + */ +class GstCapabilitiesFactory : public IGstCapabilitiesFactory +{ +public: + /** + * @brief Weak pointer to the singleton factory object. + */ + static std::weak_ptr m_factory; + + /** + * @brief Creates a IGstCapabilities object. + * + * @retval the new gstreamer capabilities instance or null on error. + */ + std::unique_ptr createGstCapabilities() override; +}; + +class GstCapabilities : public IGstCapabilities +{ +public: + explicit GstCapabilities( + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr &rdkGstreamerUtilsWrapper, + const IGstInitialiser &gstInitialiser); + ~GstCapabilities(); + + GstCapabilities(const GstCapabilities &) = delete; + GstCapabilities &operator=(const GstCapabilities &) = delete; + GstCapabilities(GstCapabilities &&) = delete; + GstCapabilities &operator=(GstCapabilities &&) = delete; + + /** + * @brief Gets vector of mime types supported by gstreamer + * + * @retval vector of mime types supported by gstreamer + */ + std::vector getSupportedMimeTypes(MediaSourceType sourceType) override; + + /** + * @brief Checks is \a mimeType is supported by gstreamer + * + * @retval True if mime type is supported by gstreamer + */ + bool isMimeTypeSupported(const std::string &mimeType) override; + + /** + * @brief Check sinks and decoders for supported properties + * + * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched + * @param[in] propertyNames : A vector of property names to look for + * + * @retval Returns the subset of propertyNames that are supported by the mediaType + */ + std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) override; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + bool isVideoMaster(bool &isVideoMaster) override; + +private: + /** + * @brief Sets list of supported mime types + */ + void fillSupportedMimeTypes(); + + /** + * @brief Appends all unique caps from parser->decoders chains' sink pads to \a supportedCaps + */ + void appendLinkableCapsFromParserDecoderChains(std::vector &supportedCaps); + + /** + * @brief Appends all unique caps from \a type pads to \a supportedCaps + */ + void appendSupportedCapsFromFactoryType(const GstElementFactoryListType &type, std::vector &supportedCaps); + + /** + * @brief Adds unique sink pads from \a padTemplates list to \a capsVector + */ + void addAllUniqueSinkPadsCapsToVector(std::vector &capsVector, const GList *padTemplates); + + /** + * @brief Checks if any src pad of parser can be connected to decoder + * + * @retval True if it's possible + */ + bool canCreateParserDecoderChain(GstCaps *decoderCaps, const GList *parserPadTemplates); + + /** + * @brief Checks if caps equal to \a caps is already in \a capsVector + * + * @retval True if there is equal caps + */ + bool isCapsInVector(const std::vector &capsVector, GstCaps *caps) const; + + /** + * @brief Waits for supportd mime types initialisation + */ + void waitForInitialisation(); + + /** + * @brief Set of mime types which are supported by gstreamer + */ + std::unordered_set m_supportedMimeTypes; + + /** + * @brief The gstreamer wrapper object. + */ + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + std::shared_ptr m_rdkGstreamerUtilsWrapper; + const IGstInitialiser &m_gstInitialiser; + std::thread m_initialisationThread; + std::mutex m_initialisationMutex; + std::condition_variable m_initialisationCv; + bool m_isInitialised{false}; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorElementFactory.h b/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorElementFactory.h new file mode 100644 index 000000000..ccea1bd61 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorElementFactory.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_ELEMENT_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_ELEMENT_FACTORY_H_ + +#include "IGstDecryptorElementFactory.h" +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IGstDecryptorElement factory class definition. + */ +class GstDecryptorElementFactory : public IGstDecryptorElementFactory +{ +public: + GstDecryptorElementFactory() = default; + ~GstDecryptorElementFactory() override = default; + + GstElement * + createDecryptorElement(const gchar *name, firebolt::rialto::server::IDecryptionService *decryptionService, + const std::shared_ptr &gstWrapper) const override; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_ELEMENT_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorPrivate.h b/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorPrivate.h new file mode 100644 index 000000000..8659aae15 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorPrivate.h @@ -0,0 +1,107 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_PRIVATE_H_ +#define FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_PRIVATE_H_ + +#include "IDecryptionService.h" +#include "IGlibWrapper.h" +#include "IGstProtectionMetadataHelper.h" +#include "IGstWrapper.h" +#include +#include + +namespace firebolt::rialto::server +{ +class GstRialtoDecryptorPrivate +{ +public: + /** + * @brief The constructor. + + * @param[in] parentElement : The parent decryptor element. + * @param[in] gstWrapperFactory : The gstreamer wrapper factory. + * @param[in] glibWrapperFactory : The glib wrapper factory. + */ + GstRialtoDecryptorPrivate(GstBaseTransform *parentElement, + const std::shared_ptr &gstWrapperFactory, + const std::shared_ptr &glibWrapperFactory); + + /** + * @brief Decrypts the gst buffer. + * + * @param[in] buffer : The gst buffer to decrypt. + * @param[in] caps : The gst caps of buffer. + * + * @retval the gst flow return status. + */ + GstFlowReturn decrypt(GstBuffer *buffer, GstCaps *caps); + + /** + * @brief Set the decryption service object. + * + * @param[in] decryptionService : The service that performs decryption. + */ + void setDecryptionService(IDecryptionService *decryptionService); + + /** + * @brief Set the protection metadata object + * + * @param[in] metadataWrapper : The protection metadata object + */ + void setProtectionMetadataWrapper(std::unique_ptr &&metadataWrapper); + +private: + /** + * @brief The gstreamer wrapper object. + */ + std::shared_ptr m_gstWrapper; + + /** + * @brief The glib wrapper object. + */ + std::shared_ptr m_glibWrapper; + + /** + * @brief The parent decryptor element. + */ + GstBaseTransform *m_decryptorElement; + + /** + * @brief The service to perform decryption. + */ + IDecryptionService *m_decryptionService; + + /** + * @brief The protection metadata object + */ + std::unique_ptr m_metadataWrapper; + + /** + * @brief Creates the protection meta structure. + * + * @param[in] protectionData : The rialto protection data. + * + * @retval the gst structure of the protection meta. + */ + GstStructure *createProtectionMetaInfo(GstRialtoProtectionData *protectionData); +}; +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_PRIVATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstDispatcherThread.h b/middleware/rialto-client/media/server/gstplayer/include/GstDispatcherThread.h new file mode 100644 index 000000000..fa5ad3ac5 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstDispatcherThread.h @@ -0,0 +1,78 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_DISPATCHER_THREAD_H_ +#define FIREBOLT_RIALTO_SERVER_GST_DISPATCHER_THREAD_H_ + +#include "IGstDispatcherThread.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class GstDispatcherThreadFactory : public IGstDispatcherThreadFactory +{ +public: + ~GstDispatcherThreadFactory() override = default; + std::unique_ptr + createGstDispatcherThread(IGstDispatcherThreadClient &client, GstElement *pipeline, + const std::shared_ptr &gstWrapper) const override; +}; + +class GstDispatcherThread : public IGstDispatcherThread +{ +public: + GstDispatcherThread(IGstDispatcherThreadClient &client, GstElement *pipeline, + const std::shared_ptr &gstWrapper); + ~GstDispatcherThread() override; + +private: + /** + * @brief For handling gst bus messages in Gstreamer dispatcher thread + * + * @param[in] pipeline : The pipeline + */ + void gstBusEventHandler(GstElement *pipeline); + +private: + /** + * @brief The listening client. + */ + IGstDispatcherThreadClient &m_client; + + /** + * @brief The gstreamer wrapper object. + */ + std::shared_ptr m_gstWrapper; + + /** + * @brief Flag used to check, if task thread is active + */ + std::atomic m_isGstreamerDispatcherActive; + + /** + * @brief Thread for handling gst bus callbacks + */ + std::thread m_gstBusDispatcherThread; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_DISPATCHER_THREAD_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstGenericPlayer.h b/middleware/rialto-client/media/server/gstplayer/include/GstGenericPlayer.h new file mode 100644 index 000000000..3b495cf17 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstGenericPlayer.h @@ -0,0 +1,425 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_GENERIC_PLAYER_H_ +#define FIREBOLT_RIALTO_SERVER_GST_GENERIC_PLAYER_H_ + +#include "GenericPlayerContext.h" +#include "IFlushWatcher.h" +#include "IGlibWrapper.h" +#include "IGstDispatcherThread.h" +#include "IGstDispatcherThreadClient.h" +#include "IGstGenericPlayer.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstInitialiser.h" +#include "IGstProtectionMetadataHelperFactory.h" +#include "IGstSrc.h" +#include "IGstWrapper.h" +#include "ITimer.h" +#include "IWorkerThread.h" +#include "NeedDataMapping.h" +#include "tasks/IGenericPlayerTaskFactory.h" +#include "tasks/IPlayerTask.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +constexpr uint32_t kMinPrimaryVideoWidth{1920}; +constexpr uint32_t kMinPrimaryVideoHeight{1080}; + +/** + * @brief IGstGenericPlayer factory class definition. + */ +class GstGenericPlayerFactory : public IGstGenericPlayerFactory +{ +public: + /** + * @brief Weak pointer to the singleton factory object. + */ + static std::weak_ptr m_factory; + + std::unique_ptr + createGstGenericPlayer(IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, + const VideoRequirements &videoRequirements, + const std::shared_ptr + &rdkGstreamerUtilsWrapperFactory) override; +}; + +/** + * @brief The definition of the GstGenericPlayer. + */ +class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPrivate, public IGstDispatcherThreadClient +{ +public: + /** + * @brief The constructor. + * + * @param[in] client : The gstreamer player client. + * @param[in] decryptionService : The decryption service + * @param[in] type : The media type the gstreamer player shall support. + * @param[in] videoRequirements : The video requirements for the playback. + * @param[in] gstWrapper : The gstreamer wrapper. + * @param[in] glibWrapper : The glib wrapper. + * @param[in] gstInitialiser : The gst initialiser + * @param[in] flushWatcher : The flush watcher + * @param[in] gstSrcFactory : The gstreamer rialto src factory. + * @param[in] timerFactory : The Timer factory + * @param[in] taskFactory : The task factory + * @param[in] workerThreadFactory : The worker thread factory + * @param[in] gstDispatcherThreadFactory : The gst dispatcher thread factory + */ + GstGenericPlayer(IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, + const VideoRequirements &videoRequirements, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr &rdkGstreamerUtilsWrapper, + const IGstInitialiser &gstInitialiser, std::unique_ptr &&flushWatcher, + const std::shared_ptr &gstSrcFactory, + std::shared_ptr timerFactory, + std::unique_ptr taskFactory, + std::unique_ptr workerThreadFactory, + std::unique_ptr gstDispatcherThreadFactory, + std::shared_ptr gstProtectionMetadataFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~GstGenericPlayer(); + + void attachSource(const std::unique_ptr &mediaSource) override; + void removeSource(const MediaSourceType &mediaSourceType) override; + void allSourcesAttached() override; + void play() override; + void pause() override; + void stop() override; + void attachSamples(const IMediaPipeline::MediaSegmentVector &mediaSegments) override; + void attachSamples(const std::shared_ptr &dataReader) override; + void setPosition(std::int64_t position) override; + void setVideoGeometry(int x, int y, int width, int height) override; + void setEos(const firebolt::rialto::MediaSourceType &type) override; + void setPlaybackRate(double rate) override; + bool getPosition(std::int64_t &position) override; + bool setImmediateOutput(const MediaSourceType &mediaSourceType, bool immediateOutput) override; + bool getImmediateOutput(const MediaSourceType &mediaSourceType, bool &immediateOutput) override; + bool getStats(const MediaSourceType &mediaSourceType, uint64_t &renderedFrames, uint64_t &droppedFrames) override; + void setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType) override; + bool getVolume(double &volume) override; + void setMute(const MediaSourceType &mediaSourceType, bool mute) override; + bool getMute(const MediaSourceType &mediaSourceType, bool &mute) override; + void setTextTrackIdentifier(const std::string &textTrackIdentifier) override; + bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; + bool setLowLatency(bool lowLatency) override; + bool setSync(bool sync) override; + bool getSync(bool &sync) override; + bool setSyncOff(bool syncOff) override; + bool setStreamSyncMode(const MediaSourceType &mediaSourceType, int32_t streamSyncMode) override; + bool getStreamSyncMode(int32_t &streamSyncMode) override; + void ping(std::unique_ptr &&heartbeatHandler) override; + void flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) override; + void setSourcePosition(const MediaSourceType &mediaSourceType, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) override; + void setSubtitleOffset(int64_t position) override; + void processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; + void setBufferingLimit(uint32_t limitBufferingMs) override; + bool getBufferingLimit(uint32_t &limitBufferingMs) override; + void setUseBuffering(bool useBuffering) override; + bool getUseBuffering(bool &useBuffering) override; + void switchSource(const std::unique_ptr &mediaSource) override; + +private: + void scheduleNeedMediaData(GstAppSrc *src) override; + void scheduleEnoughData(GstAppSrc *src) override; + void scheduleAudioUnderflow() override; + void scheduleVideoUnderflow() override; + void scheduleAllSourcesAttached() override; + bool setVideoSinkRectangle() override; + bool setImmediateOutput() override; + bool setShowVideoWindow() override; + bool setLowLatency() override; + bool setSync() override; + bool setSyncOff() override; + bool setStreamSyncMode(const MediaSourceType &type) override; + bool setRenderFrame() override; + bool setBufferingLimit() override; + bool setUseBuffering() override; + void notifyNeedMediaData(const MediaSourceType mediaSource) override; + GstBuffer *createBuffer(const IMediaPipeline::MediaSegment &mediaSegment) const override; + void attachData(const firebolt::rialto::MediaSourceType mediaType) override; + void updateAudioCaps(int32_t rate, int32_t channels, const std::shared_ptr &codecData) override; + void updateVideoCaps(int32_t width, int32_t height, Fraction frameRate, + const std::shared_ptr &codecData) override; + void addAudioClippingToBuffer(GstBuffer *buffer, uint64_t clippingStart, uint64_t clippingEnd) const override; + bool changePipelineState(GstState newState) override; + int64_t getPosition(GstElement *element) override; + void startPositionReportingAndCheckAudioUnderflowTimer() override; + void stopPositionReportingAndCheckAudioUnderflowTimer() override; + void startSubtitleClockResyncTimer() override; + void stopSubtitleClockResyncTimer() override; + void stopWorkerThread() override; + void cancelUnderflow(firebolt::rialto::MediaSourceType mediaSource) override; + void setPendingPlaybackRate() override; + void renderFrame() override; + void handleBusMessage(GstMessage *message, bool priority) override; + void updatePlaybackGroup(GstElement *typefind, const GstCaps *caps) override; + + void addAutoVideoSinkChild(GObject *object) override; + void addAutoAudioSinkChild(GObject *object) override; + void removeAutoVideoSinkChild(GObject *object) override; + void removeAutoAudioSinkChild(GObject *object) override; + void setPlaybinFlags(bool enableAudio = true) override; + void pushSampleIfRequired(GstElement *source, const std::string &typeStr) override; + bool reattachSource(const std::unique_ptr &source) override; + bool hasSourceType(const MediaSourceType &mediaSourceType) const override; + GstElement *getSink(const MediaSourceType &mediaSourceType) const override; + void setSourceFlushed(const MediaSourceType &mediaSourceType) override; + bool isAsync(const MediaSourceType &mediaSourceType) const; + void clearNeedDataScheduled(GstAppSrc *src) override; + +private: + /** + * @brief Initialises the player pipeline for MSE playback. + */ + void initMsePipeline(); + + /** + * @brief Gets the flag from gstreamer. + * + * @param[in] nick : The name of the flag in gstreamer. + * + * @retval Value of the flag or 0 on error. + */ + unsigned getGstPlayFlag(const char *nick); + + /** + * @brief Callback on source-setup. Called by the Gstreamer thread + * + * @param[in] pipeline : The pipeline the signal was fired from. + * @param[in] source : The source to setup. + * @param[in] self : Reference to the calling object. + */ + static void setupSource(GstElement *pipeline, GstElement *source, GstGenericPlayer *self); + + /** + * @brief Callback on element-setup. Called by the Gstreamer thread + * + * @param[in] pipeline : The pipeline the signal was fired from. + * @param[in] element : an element that was added to the playbin hierarchy + * @param[in] self : Reference to the calling object. + */ + static void setupElement(GstElement *pipeline, GstElement *element, GstGenericPlayer *self); + + /** + * @brief Callback on element-setup. Called by the Gstreamer thread + * + * @param[in] pipeline : The pipeline the signal was fired from. + * @param[in] bin : the GstBin the element was added to + * @param[in] element : an element that was added to the playbin hierarchy + * @param[in] self : Reference to the calling object. + */ + static void deepElementAdded(GstBin *pipeline, GstBin *bin, GstElement *element, GstGenericPlayer *self); + + /** + * @brief Creates a Westeros sink and sets the res-usage flag for a secondary video. + * + * @retval true on success. + */ + bool setWesterossinkSecondaryVideo(); + + /** + * @brief Creates an "erm" gstreamer context in the pipeline + * + * @retval true on success. + */ + bool setErmContext(); + + /** + * @brief Terminates the player pipeline. + */ + void termPipeline(); + + /** + * @brief Shutdown and destroys the worker thread. + */ + void resetWorkerThread(); + + /** + * @brief Whether native audio should be enabled on the current platform. + */ + bool shouldEnableNativeAudio(); + + /** + * @brief Sets codec_data in GstCaps if available + * + * @retval True if caps were changed + */ + bool setCodecData(GstCaps *caps, const std::shared_ptr &codecData) const; + + /** + * @brief Gets the video sink element child sink if present. + * Only gets children for GstAutoVideoSink's. + * + * @param[in] sink : Sink element to check. + * + * @retval Underlying child video sink or 'sink' if there are no children. + */ + GstElement *getSinkChildIfAutoVideoSink(GstElement *sink) const; + + /** + * @brief Gets the audio sink element child sink if present. + * Only gets children for GstAutoAudioSink's. + * + * @param[in] sink : Sink element to check. + * + * @retval Underlying child audio sink or 'sink' if there are no children. + */ + GstElement *getSinkChildIfAutoAudioSink(GstElement *sink) const; + + /** + * @brief Gets the decoder element for source type. + * + * @param[in] mediaSourceType : the source type to obtain the decoder for + * + * @retval The decoder, NULL if not found + */ + GstElement *getDecoder(const MediaSourceType &mediaSourceType); + + /** + * @brief Gets the parser element for source type. + * + * @param[in] mediaSourceType : the source type to obtain the parser for + * + * @retval The parser, NULL if not found + */ + GstElement *getParser(const MediaSourceType &mediaSourceType); + + /** + * @brief Constructs new Audio Attributes structure based on MediaSource + * Called by worker thread only! + * + * @param[in] source : the media source, which contains params needed by Audio Attributes struct + * + * @retval The Audio Attributes structure on success, std::nullopt on failure + */ + std::optional + createAudioAttributes(const std::unique_ptr &source) const; + + /** + * @brief Sets text track position before pushing data + * + * @param[in] source : the subtitle media source + */ + void setTextTrackPositionIfRequired(GstElement *source); + + /** + * @brief GstAppSrc does not replace segment, if it's the same as previous one. + * It causes problems with position reporing in amlogic devices, so we need to push + * two segments with different reset time value. + * + * @param[in] source : the media source + */ + void pushAdditionalSegmentIfRequired(GstElement *source); + +private: + /** + * @brief The player context. + */ + GenericPlayerContext m_context; + + /** + * @brief The gstreamer player client. + */ + IGstGenericPlayerClient *m_gstPlayerClient = nullptr; + + /** + * @brief The gstreamer wrapper object. + */ + std::shared_ptr m_gstWrapper; + + /** + * @brief The glib wrapper object. + */ + std::shared_ptr m_glibWrapper; + + /** + * @brief The rdk gstreamer utils wrapper object + */ + std::shared_ptr m_rdkGstreamerUtilsWrapper; + + /** + * @brief Thread for handling player tasks. + */ + std::unique_ptr m_workerThread; + + /** + * @brief Thread for handling gst bus callbacks + */ + std::unique_ptr m_gstDispatcherThread; + + /** + * @brief Factory creating timers + * + */ + std::shared_ptr m_timerFactory; + + /** + * @brief Timer to trigger FinishSourceSetup + */ + std::unique_ptr m_finishSourceSetupTimer{nullptr}; + + /** + * @brief Timer reporting playback position and check audio underflow + * + * Variable can be used only in worker thread + */ + std::unique_ptr m_positionReportingAndCheckAudioUnderflowTimer{nullptr}; + + /** + * @brief Timer to resync subtitle clock with AV clock + * + * Variable can be used only in worker thread + */ + std::unique_ptr m_subtitleClockResyncTimer{nullptr}; + + /** + * @brief The GstGenericPlayer task factory + */ + std::unique_ptr m_taskFactory; + + /** + * @brief The protection metadata wrapper + */ + std::unique_ptr m_protectionMetadataWrapper; + + /** + * @brief The object used to check flushing state for all sources + */ + std::unique_ptr m_flushWatcher; + + /** + * @brief The object used to check if NeedData is scheduled for given source + */ + NeedDataMapping m_scheduledNeedDatas; +}; + +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_GENERIC_PLAYER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstInitialiser.h b/middleware/rialto-client/media/server/gstplayer/include/GstInitialiser.h new file mode 100644 index 000000000..6ea8ba147 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstInitialiser.h @@ -0,0 +1,50 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_INITIALISER_H_ +#define FIREBOLT_RIALTO_SERVER_GST_INITIALISER_H_ + +#include "IGstInitialiser.h" +#include "IGstWrapper.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class GstInitialiser : public IGstInitialiser +{ +public: + GstInitialiser() = default; + ~GstInitialiser(); + + void initialise(int *argc, char ***argv) override; + void waitForInitialisation() const override; + +private: + bool m_isInitialised{false}; + mutable std::mutex m_mutex; + mutable std::condition_variable m_cv; + std::thread m_thread; + std::shared_ptr m_gstWrapper; +}; +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_INITIALISER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstLogForwarding.h b/middleware/rialto-client/media/server/gstplayer/include/GstLogForwarding.h new file mode 100644 index 000000000..2744995fb --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstLogForwarding.h @@ -0,0 +1,28 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_LOG_FORWARDING_H_ +#define FIREBOLT_RIALTO_SERVER_GST_LOG_FORWARDING_H_ + +namespace firebolt::rialto::server +{ +void enableGstLogForwarding(); +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_LOG_FORWARDING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstMimeMapping.h b/middleware/rialto-client/media/server/gstplayer/include/GstMimeMapping.h new file mode 100644 index 000000000..bb8e63bef --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstMimeMapping.h @@ -0,0 +1,123 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_MIME_MAPPING_H_ +#define FIREBOLT_RIALTO_SERVER_GST_MIME_MAPPING_H_ + +#include "GstCapabilities.h" +#include "IGstWrapper.h" +#include "IMediaPipeline.h" +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ + +/** + * @brief Converts MIME types to simple caps. + * + * @param[in] m_gstWrapper : Member variable that is a shared pointer to an object of type IGstWrapper + * @param[in] m_attachedSource : A const reference to an object of type MediaSource + * + * @retval the pointer to the GstCaps object, which represents the simple caps for the given MIME type. If MIME type is + * not found, an empty GstCaps object is returned + */ + +inline GstCaps *createSimpleCapsFromMimeType(std::shared_ptr m_gstWrapper, + const IMediaPipeline::MediaSource &m_attachedSource) +{ + static const std::unordered_map mimeToMediaType = + {{"video/h264", "video/x-h264"}, {"video/h265", "video/x-h265"}, + {"video/x-av1", "video/x-av1"}, {"video/x-vp9", "video/x-vp9"}, + {"video/mp4", "video/mpeg"}, {"audio/mp4", "audio/mpeg"}, + {"audio/mp3", "audio/mpeg"}, {"audio/aac", "audio/mpeg"}, + {"audio/x-eac3", "audio/x-eac3"}, {"audio/x-opus", "audio/x-opus"}, + {"audio/b-wav", "audio/b-wav"}, {"audio/x-raw", "audio/x-raw"}, + {"audio/x-flac", "audio/x-flac"}, {"text/vtt", "application/x-subtitle-vtt"}, + {"text/ttml", "application/ttml+xml"}, {"text/cc", "subtitle/x-subtitle-cc"}}; + auto mimeToMediaTypeIt = mimeToMediaType.find(m_attachedSource.getMimeType()); + if (mimeToMediaTypeIt != mimeToMediaType.end()) + { + return m_gstWrapper->gstCapsNewEmptySimple(mimeToMediaTypeIt->second.c_str()); + } + + return m_gstWrapper->gstCapsNewEmpty(); +} + +/** + * @brief Converts simple caps to MIME types. + * + * @param[in] supportedCaps : A const reference to a vector of pointers to GstCaps objects representing the supported caps + * @param[in] m_gstWrapper : Member variable that is a shared pointer to an object of type IGstWrapper + * + * @retval an unordered set of strings representing the supported MIME types + */ + +inline std::unordered_set +convertFromCapsVectorToMimeSet(const std::vector &supportedCaps, + std::shared_ptr m_gstWrapper) +{ + std::vector>> capsToMimeVec = + {{m_gstWrapper->gstCapsFromString("audio/mpeg, mpegversion=(int)4"), {"audio/mp4", "audio/aac", "audio/x-eac3"}}, + {m_gstWrapper->gstCapsFromString("audio/mpeg, mpegversion=(int)1, layer=(int)3"), {"audio/mp3"}}, + {m_gstWrapper->gstCapsFromString("audio/x-eac3"), {"audio/x-eac3"}}, + {m_gstWrapper->gstCapsFromString("audio/b-wav"), {"audio/b-wav"}}, + {m_gstWrapper->gstCapsFromString("audio/x-raw"), {"audio/x-raw"}}, + {m_gstWrapper->gstCapsFromString("audio/x-opus"), {"audio/x-opus"}}, + {m_gstWrapper->gstCapsFromString("audio/x-opus, channel-mapping-family=(int)0"), {"audio/x-opus"}}, + {m_gstWrapper->gstCapsFromString("audio/x-flac"), {"audio/x-flac"}}, + {m_gstWrapper->gstCapsFromString("video/x-av1"), {"video/x-av1"}}, + {m_gstWrapper->gstCapsFromString("video/x-h264"), {"video/h264"}}, + {m_gstWrapper->gstCapsFromString("video/x-h265"), {"video/h265"}}, + {m_gstWrapper->gstCapsFromString("video/x-vp9"), {"video/x-vp9"}}, + {m_gstWrapper->gstCapsFromString("video/mpeg, mpegversion=(int)4"), {"video/mp4"}}, + {m_gstWrapper->gstCapsFromString("video/x-h264(memory:DMABuf)"), {"video/h264"}}, + {m_gstWrapper->gstCapsFromString("video/x-h265(memory:DMABuf)"), {"video/h265"}}, + {m_gstWrapper->gstCapsFromString("video/x-av1(memory:DMABuf)"), {"video/x-av1"}}, + {m_gstWrapper->gstCapsFromString("video/x-vp9(memory:DMABuf)"), {"video/x-vp9"}}}; + + std::unordered_set supportedMimes; + + for (GstCaps *caps : supportedCaps) + { + for (const auto &capsToMime : capsToMimeVec) + { + if (m_gstWrapper->gstCapsCanIntersect(capsToMime.first, caps)) + { + supportedMimes.insert(capsToMime.second.begin(), capsToMime.second.end()); + } + } + } + + for (auto &capsToMime : capsToMimeVec) + { + if (capsToMime.first) + m_gstWrapper->gstCapsUnref(capsToMime.first); + } + + return supportedMimes; +} + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_MIME_MAPPING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadata.h b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadata.h new file mode 100644 index 000000000..28769bef0 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadata.h @@ -0,0 +1,58 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_H_ // NOLINT(build/header_guard) +#define FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_H_ + +#include "IDecryptionService.h" +#include + +G_BEGIN_DECLS + +#define GST_RIALTO_PROTECTION_METADATA_GET_TYPE (rialto_eme_protection_metadata_get_type()) +#define GST_RIALTO_PROTECTION_METADATA_INFO (rialto_mse_protection_metadata_get_info()) + +struct GstRialtoProtectionData +{ + int32_t keySessionId = 0; + uint32_t subsampleCount = 0; + uint32_t initWithLast15 = 0; + GstBuffer *key = nullptr; + GstBuffer *iv = nullptr; + GstBuffer *subsamples = nullptr; + firebolt::rialto::CipherMode cipherMode = firebolt::rialto::CipherMode::UNKNOWN; + uint32_t crypt = 0; + uint32_t skip = 0; + bool encryptionPatternSet = false; + firebolt::rialto::server::IDecryptionService *decryptionService = nullptr; +}; + +struct _GstRialtoProtectionMetadata +{ + GstMeta parent; + GstRialtoProtectionData data; +}; + +typedef struct _GstRialtoProtectionMetadata GstRialtoProtectionMetadata; + +GType rialto_eme_protection_metadata_get_type(); // NOLINT(build/function_format) +const GstMetaInfo *rialto_mse_protection_metadata_get_info(); // NOLINT(build/function_format) +G_END_DECLS + +#endif // FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelper.h b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelper.h new file mode 100644 index 000000000..5b7b4a368 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelper.h @@ -0,0 +1,49 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_H_ +#define FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_H_ + +#include "IGstProtectionMetadataHelper.h" +#include "IGstWrapper.h" +#include + +namespace firebolt::rialto::server +{ +class GstProtectionMetadataHelper : public IGstProtectionMetadataHelper +{ +public: + explicit GstProtectionMetadataHelper(const std::shared_ptr &gstWrapper) + : m_gstWrapper(gstWrapper) + { + } + ~GstProtectionMetadataHelper() override = default; + GstMeta *addProtectionMetadata(GstBuffer *gstBuffer, GstRialtoProtectionData &data) override; + GstRialtoProtectionData *getProtectionMetadataData(GstBuffer *gstBuffer) override; + void removeProtectionMetadata(GstBuffer *gstBuffer) override; + +private: + /** + * @brief The gstreamer wrapper object. + */ + std::shared_ptr m_gstWrapper; +}; +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelperFactory.h b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelperFactory.h new file mode 100644 index 000000000..9ad92324f --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelperFactory.h @@ -0,0 +1,43 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ + +#include "IGstProtectionMetadataHelperFactory.h" +#include + +namespace firebolt::rialto::server +{ +/** + * @brief GstProtectionMetadataHelperFactory factory class, for the creation of a GstProtectionMetadataHelper. + */ +class GstProtectionMetadataHelperFactory : public IGstProtectionMetadataHelperFactory +{ +public: + GstProtectionMetadataHelperFactory() = default; + ~GstProtectionMetadataHelperFactory() override = default; + + std::unique_ptr createProtectionMetadataWrapper( + const std::shared_ptr &gstWrapper) const override; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstRialtoTextTrackSinkPrivate.h b/middleware/rialto-client/media/server/gstplayer/include/GstRialtoTextTrackSinkPrivate.h new file mode 100644 index 000000000..859e97988 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstRialtoTextTrackSinkPrivate.h @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_RIALTO_TEXT_TRACK_SINK_PRIVATE_H_ +#define FIREBOLT_RIALTO_SERVER_GST_RIALTO_TEXT_TRACK_SINK_PRIVATE_H_ + +#include "ITextTrackSession.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +struct GstRialtoTextTrackSinkPrivate +{ + std::unique_ptr m_textTrackSession; + std::atomic m_isMuted{false}; + std::string m_textTrackIdentifier; + uint64_t m_videoDecoderIdentifier{0}; + bool m_capsSet{false}; + std::optional m_position; + std::optional m_queuedPosition; + std::optional m_offset; + std::optional m_queuedOffset; + std::mutex m_mutex; +}; +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_RIALTO_TEXT_TRACK_SINK_PRIVATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstSrc.h b/middleware/rialto-client/media/server/gstplayer/include/GstSrc.h new file mode 100644 index 000000000..b795c49b4 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstSrc.h @@ -0,0 +1,162 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_SRC_H_ +#define FIREBOLT_RIALTO_SERVER_GST_SRC_H_ + +#include "IGlibWrapper.h" +#include "IGstDecryptorElementFactory.h" +#include "IGstSrc.h" +#include "IGstWrapper.h" + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_RIALTO_TYPE_SRC (gst_rialto_src_get_type()) +#define GST_RIALTO_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_RIALTO_TYPE_SRC, GstRialtoSrc)) +#define GST_RIALTO_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST((klass), GST_RIALTO_TYPE_SRC, GstRialtoSrcClass)) +#define GST_IS_RIALTO_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_RIALTO_TYPE_SRC)) +#define GST_IS_RIALTO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_RIALTO_TYPE_SRC)) + +typedef struct _GstRialtoSrc GstRialtoSrc; +typedef struct _GstRialtoSrcClass GstRialtoSrcClass; +typedef struct _GstRialtoSrcPrivate GstRialtoSrcPrivate; + +struct _GstRialtoSrc +{ + GstBin parent; + GstRialtoSrcPrivate *priv; +}; + +struct _GstRialtoSrcClass +{ + GstBinClass parentClass; +}; + +GType gst_rialto_src_get_type(void); // NOLINT(build/function_format) + +struct _GstRialtoSrcPrivate +{ + gchar *uri; + guint appsrc_count; + gboolean async_start; + gboolean async_done; +}; + +enum +{ + PROP_0, + PROP_LOCATION +}; + +G_END_DECLS + +namespace firebolt::rialto::server +{ +/** + * @brief IGstSrc factory class definition. + */ +class GstSrcFactory : public IGstSrcFactory +{ +public: + /** + * @brief Weak pointer to the singleton factroy object. + */ + static std::weak_ptr m_factory; + + /** + * @brief Weak pointer to the singleton object. + */ + static std::weak_ptr m_gstSrc; + + /** + * @brief Mutex protection for creation of the GstSrc object. + */ + static std::mutex m_creationMutex; + + std::shared_ptr getGstSrc() override; +}; + +/** + * @brief The definition of the GstSrc. + */ +class GstSrc : public IGstSrc +{ +public: + /** + * @brief The constructor. + * + * @param[in] gstWrapperFactory : The gstreamer wrapper factory. + * @param[in] glibWrapperFactory : The glib wrapper factory. + * @param[in] decryptorFactory : The decryptor factory. + */ + GstSrc(const std::shared_ptr &gstWrapperFactory, + const std::shared_ptr &glibWrapperFactory, + const std::shared_ptr &decryptorFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~GstSrc() {} + + void initSrc() override; + + void setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, + GstAppSrcCallbacks *callbacks, gpointer userData, + firebolt::rialto::MediaSourceType type) override; + + void allAppSrcsAdded(GstElement *element) override; + +protected: + /* + * @brief sets the default stream format if needed. + */ + void setDefaultStreamFormatIfNeeded(GstElement *appSrc); + + /** + * @brief The gstreamer wrapper object. + */ + std::shared_ptr m_gstWrapper; + + /** + * @brief The glib wrapper object. + */ + std::shared_ptr m_glibWrapper; + + /** + * @brief The gst decryptor element factory object. + */ + std::shared_ptr m_decryptorFactory; + + /** + * @brief Create a payloader element. + * + * @retval the payloader element. + */ + GstElement *createPayloader(); +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_SRC_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstTextTrackSinkFactory.h b/middleware/rialto-client/media/server/gstplayer/include/GstTextTrackSinkFactory.h new file mode 100644 index 000000000..34c2b8a58 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstTextTrackSinkFactory.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_TEXT_TRACK_SINK_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_GST_TEXT_TRACK_SINK_FACTORY_H_ + +#include "IGstTextTrackSinkFactory.h" +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IGstTextTrackSink factory class definition. + */ +class GstTextTrackSinkFactory : public IGstTextTrackSinkFactory +{ +public: + GstTextTrackSinkFactory() = default; + ~GstTextTrackSinkFactory() override = default; + + GstElement *createGstTextTrackSink() const override; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_TEXT_TRACK_SINK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstWebAudioPlayer.h b/middleware/rialto-client/media/server/gstplayer/include/GstWebAudioPlayer.h new file mode 100644 index 000000000..f32f05b75 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/GstWebAudioPlayer.h @@ -0,0 +1,190 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GST_WEB_AUDIO_PLAYER_H_ +#define FIREBOLT_RIALTO_SERVER_GST_WEB_AUDIO_PLAYER_H_ + +#include "IGlibWrapper.h" +#include "IGstDispatcherThread.h" +#include "IGstDispatcherThreadClient.h" +#include "IGstInitialiser.h" +#include "IGstSrc.h" +#include "IGstWebAudioPlayer.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IWorkerThread.h" +#include "WebAudioPlayerContext.h" +#include "tasks/IPlayerTask.h" +#include "tasks/IWebAudioPlayerTaskFactory.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IGstWebAudioPlayer factory class definition. + */ +class GstWebAudioPlayerFactory : public IGstWebAudioPlayerFactory +{ +public: + /** + * @brief Weak pointer to the singleton factory object. + */ + static std::weak_ptr m_factory; + + std::unique_ptr createGstWebAudioPlayer(IGstWebAudioPlayerClient *client, + const uint32_t priority) override; +}; + +/** + * @brief The definition of the GstWebAudioPlayer. + */ +class GstWebAudioPlayer : public IGstWebAudioPlayer, public IGstWebAudioPlayerPrivate, public IGstDispatcherThreadClient +{ +public: + /** + * @brief The constructor. + * + * @param[in] client : The gstreamer player client. + * @param[in] priority : Priority value for this pipeline. + * @param[in] gstWrapper : The gstreamer wrapper. + * @param[in] glibWrapper : The glib wrapper. + * @param[in] gstInitialiser : The gst initialiser + * @param[in] gstSrcFactory : The gstreamer rialto src factory. + * @param[in] taskFactory : The task factory + * @param[in] workerThreadFactory : The worker thread factory + * @param[in] gstDispatcherThreadFactory : The gst dispatcher thread factory + */ + GstWebAudioPlayer(IGstWebAudioPlayerClient *client, const uint32_t priority, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const IGstInitialiser &gstInitialiser, const std::shared_ptr &gstSrcFactory, + std::unique_ptr taskFactory, + std::unique_ptr workerThreadFactory, + std::unique_ptr gstDispatcherThreadFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~GstWebAudioPlayer(); + + void setCaps(const std::string &audioMimeType, std::weak_ptr config) override; + void play() override; + void pause() override; + void setVolume(double volume) override; + bool getVolume(double &volume) override; + uint32_t writeBuffer(uint8_t *mainPtr, uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength) override; + void setEos() override; + uint64_t getQueuedBytes() override; + + bool changePipelineState(GstState newState) override; + void stopWorkerThread() override; + void handleBusMessage(GstMessage *message, bool priority) override; + void ping(std::unique_ptr &&heartbeatHandler) override; + +private: + /** + * @brief Initialises the player pipeline for WebAudio playback. + * + * @param[in] priority : Priority value for this pipeline. + * + * @retval true on success false otherwise. + */ + bool initWebAudioPipeline(const uint32_t priority); + + /** + * @brief Creates a amlhalasink audio sink element and adds it to the pipeline. + * + * @retval constructed sink element or nullptr on failure. + */ + GstElement *createAmlhalaSink(); + + /** + * @brief Creates a rtkaudiosink audio sink element and adds it to the pipeline. + * + * @retval constructed sink element or nullptr on failure. + */ + GstElement *createRtkAudioSink(); + + /** + * @brief Creates a autoaudiosink sink element and adds it to the pipeline. + * + * @retval constructed sink element or nullptr on failure. + */ + GstElement *createAutoSink(); + + /** + * @brief Links the sink, audio convert and audio resample to the src. + * + * @param[in] sink : The constructed sink to link to the src. + * + * @retval true on success false otherwise. + */ + bool linkElementsToSrc(GstElement *sink); + + /** + * @brief Terminates the player pipeline for WebAudio playback. + */ + void termWebAudioPipeline(); + + /** + * @brief Shutdown and destroys the worker thread. + */ + void resetWorkerThread(); + +private: + /** + * @brief The player context. + */ + WebAudioPlayerContext m_context; + + /** + * @brief The gstreamer player client. + */ + IGstWebAudioPlayerClient *m_gstPlayerClient{nullptr}; + + /** + * @brief The gstreamer wrapper object. + */ + std::shared_ptr m_gstWrapper; + + /** + * @brief The glib wrapper object. + */ + std::shared_ptr m_glibWrapper; + + /** + * @brief Thread for handling player tasks. + */ + std::unique_ptr m_workerThread; + + /** + * @brief Thread for handling gst bus callbacks + */ + std::unique_ptr m_gstDispatcherThread; + + /** + * @brief The GstWebAudioPlayer task factory + */ + std::unique_ptr m_taskFactory; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GST_WEB_AUDIO_PLAYER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IFlushWatcher.h b/middleware/rialto-client/media/server/gstplayer/include/IFlushWatcher.h new file mode 100644 index 000000000..c469f6950 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IFlushWatcher.h @@ -0,0 +1,38 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_FLUSH_WATCHER_H_ +#define FIREBOLT_RIALTO_SERVER_I_FLUSH_WATCHER_H_ + +#include "MediaCommon.h" + +namespace firebolt::rialto::server +{ +class IFlushWatcher +{ +public: + virtual ~IFlushWatcher() = default; + + virtual void setFlushing(const MediaSourceType &type, bool async) = 0; + virtual void setFlushed(const MediaSourceType &type) = 0; + virtual bool isFlushOngoing() const = 0; + virtual bool isAsyncFlushOngoing() const = 0; +}; +} // namespace firebolt::rialto::server +#endif // FIREBOLT_RIALTO_SERVER_I_FLUSH_WATCHER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstDecryptorElementFactory.h b/middleware/rialto-client/media/server/gstplayer/include/IGstDecryptorElementFactory.h new file mode 100644 index 000000000..32fed9597 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstDecryptorElementFactory.h @@ -0,0 +1,61 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_DECRYPTOR_ELEMENT_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_DECRYPTOR_ELEMENT_FACTORY_H_ + +#include "IDecryptionService.h" +#include "IGstWrapper.h" +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IGstDecryptorElement factory class, for the creation of a GstDecryptorElement. + */ +class IGstDecryptorElementFactory +{ +public: + IGstDecryptorElementFactory() = default; + virtual ~IGstDecryptorElementFactory() = default; + + /** + * @brief Creates a IGstDecryptorElementFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a IGstDecryptorElement. + * + * @param[in] decryptionService : The service used to decrypt frames. + * @param[in] gstWrapper : The gstreamer wrapper. + * + * @retval a decryptor element instance or null on error. + */ + virtual GstElement * + createDecryptorElement(const gchar *name, firebolt::rialto::server::IDecryptionService *decryptionService, + const std::shared_ptr &gstWrapper) const = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_DECRYPTOR_ELEMENT_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThread.h b/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThread.h new file mode 100644 index 000000000..ce3d93c3f --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThread.h @@ -0,0 +1,55 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_H_ + +#include "IGstDispatcherThreadClient.h" +#include "IGstWrapper.h" +#include + +namespace firebolt::rialto::server +{ +class IGstDispatcherThread; + +class IGstDispatcherThreadFactory +{ +public: + IGstDispatcherThreadFactory() = default; + virtual ~IGstDispatcherThreadFactory() = default; + + virtual std::unique_ptr + createGstDispatcherThread(IGstDispatcherThreadClient &client, GstElement *pipeline, + const std::shared_ptr &gstWrapper) const = 0; +}; + +class IGstDispatcherThread +{ +public: + IGstDispatcherThread() = default; + virtual ~IGstDispatcherThread() = default; + + IGstDispatcherThread(const IGstDispatcherThread &) = delete; + IGstDispatcherThread(IGstDispatcherThread &&) = delete; + IGstDispatcherThread &operator=(const IGstDispatcherThread &) = delete; + IGstDispatcherThread &operator=(IGstDispatcherThread &&) = delete; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThreadClient.h b/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThreadClient.h new file mode 100644 index 000000000..5a945239b --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThreadClient.h @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_CLIENT_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_CLIENT_H_ + +#include + +namespace firebolt::rialto::server +{ +class IGstDispatcherThreadClient +{ +public: + IGstDispatcherThreadClient() = default; + virtual ~IGstDispatcherThreadClient() = default; + + IGstDispatcherThreadClient(const IGstDispatcherThreadClient &) = delete; + IGstDispatcherThreadClient(IGstDispatcherThreadClient &&) = delete; + IGstDispatcherThreadClient &operator=(const IGstDispatcherThreadClient &) = delete; + IGstDispatcherThreadClient &operator=(IGstDispatcherThreadClient &&) = delete; + + /** + * @brief Callback on a new bus message. + * + * @param[in] message : The new Gst message. + */ + virtual void handleBusMessage(GstMessage *message, bool priority) = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstGenericPlayerPrivate.h b/middleware/rialto-client/media/server/gstplayer/include/IGstGenericPlayerPrivate.h new file mode 100644 index 000000000..44af949c2 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstGenericPlayerPrivate.h @@ -0,0 +1,323 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_PRIVATE_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_PRIVATE_H_ + +#include "IMediaPipeline.h" + +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IGstGenericPlayerPrivate +{ +public: + IGstGenericPlayerPrivate() = default; + virtual ~IGstGenericPlayerPrivate() = default; + + IGstGenericPlayerPrivate(const IGstGenericPlayerPrivate &) = delete; + IGstGenericPlayerPrivate &operator=(const IGstGenericPlayerPrivate &) = delete; + IGstGenericPlayerPrivate(IGstGenericPlayerPrivate &&) = delete; + IGstGenericPlayerPrivate &operator=(IGstGenericPlayerPrivate &&) = delete; + + /** + * @brief Schedules need media data task. Called by the worker thread. + */ + virtual void scheduleNeedMediaData(GstAppSrc *src) = 0; + + /** + * @brief Schedules enough data task. Called by the worker thread. + */ + virtual void scheduleEnoughData(GstAppSrc *src) = 0; + + /** + * @brief Schedules audio underflow task. Called by the worker thread. + */ + virtual void scheduleAudioUnderflow() = 0; + + /** + * @brief Schedules video underflow task. Called by the worker thread. + */ + virtual void scheduleVideoUnderflow() = 0; + + /** + * @brief Schedules all sources attached task. Called by the worker thread. + */ + virtual void scheduleAllSourcesAttached() = 0; + + /** + * @brief Sets video sink rectangle. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setVideoSinkRectangle() = 0; + + /** + * @brief Sets immediate output. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setImmediateOutput() = 0; + + /** + * @brief Sets the low latency property. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setLowLatency() = 0; + + /** + * @brief Sets the sync property. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setSync() = 0; + + /** + * @brief Sets the sync off property. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setSyncOff() = 0; + + /** + * @brief Sets the stream sync mode property. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setStreamSyncMode(const MediaSourceType &type) = 0; + + /** + * @brief Sets frame rendering. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setRenderFrame() = 0; + + /** + * @brief Sets buffering limit. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setBufferingLimit() = 0; + + /** + * @brief Sets use buffering. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setUseBuffering() = 0; + + /** + * @brief Sets Show Video Window property. Called by the worker thread. + * + * @retval true on success. + */ + virtual bool setShowVideoWindow() = 0; + + /** + * @brief Sends NeedMediaData notification. Called by the worker thread. + */ + virtual void notifyNeedMediaData(const MediaSourceType mediaSource) = 0; + + /** + * @brief Constructs a new buffer with data from media segment. Does not perform decryption. + * Called by the worker thread. + */ + virtual GstBuffer *createBuffer(const IMediaPipeline::MediaSegment &mediaSegment) const = 0; + + virtual void attachData(const firebolt::rialto::MediaSourceType mediaType) = 0; + + /** + * @brief Checks the new audio mediaSegment metadata and updates the caps accordingly. + */ + virtual void updateAudioCaps(int32_t rate, int32_t channels, const std::shared_ptr &codecData) = 0; + + /** + * @brief Checks the new video mediaSegment metadata and updates the caps accordingly. + */ + virtual void updateVideoCaps(int32_t width, int32_t height, Fraction frameRate, + const std::shared_ptr &codecData) = 0; + + /** + * @brief Adds clipping meta to the audio buffer. + * + * @param buffer the buffer to add the clipping meta to + * @param clippingStart the start of the clipping + * @param clippingEnd the end of the clipping + */ + virtual void addAudioClippingToBuffer(GstBuffer *buffer, uint64_t clippingStart, uint64_t clippingEnd) const = 0; + + /** + * @brief Changes pipeline state. + * + * @param[in] newState : The desired state. + * + * @retval true on success. + */ + virtual bool changePipelineState(GstState newState) = 0; + + /** + * @brief Gets the current position of the element + * + * @param[in] element : The GstElement to check. + * + * @retval position of the element; -1 in case of failure + */ + virtual int64_t getPosition(GstElement *element) = 0; + + /** + * @brief Starts position reporting and check audio underflow. Called by the worker thread. + */ + virtual void startPositionReportingAndCheckAudioUnderflowTimer() = 0; + + /** + * @brief Stops position reporting and check audio underflow. Called by the worker thread. + */ + virtual void stopPositionReportingAndCheckAudioUnderflowTimer() = 0; + + /** + * @brief Starts subtitle clock resync. Called by the worker thread. + */ + virtual void startSubtitleClockResyncTimer() = 0; + + /** + * @brief Stops subtitle clock resync. Called by the worker thread. + */ + virtual void stopSubtitleClockResyncTimer() = 0; + + /** + * @brief Stops worker thread. Called by the worker thread. + */ + virtual void stopWorkerThread() = 0; + + /** + * @brief Restores playback after underflow. Called by the worker thread. + * + * @param[in] underflowFlag : The audio or video underflow flag to be cleared. + */ + virtual void cancelUnderflow(firebolt::rialto::MediaSourceType mediaSource) = 0; + + /** + * @brief Sets pending playback rate after reaching PLAYING state + * + */ + virtual void setPendingPlaybackRate() = 0; + + /** + * @brief Updates Playback Group in PlayerContext. + */ + virtual void updatePlaybackGroup(GstElement *typefind, const GstCaps *caps) = 0; + + /** + * @brief Notification that a new child element has been added to the autovideosink. + * Stores the child video sink in the player context. + * + * @param[in] object : Element added to the autovideosink. + */ + virtual void addAutoVideoSinkChild(GObject *object) = 0; + + /** + * @brief Notification that a new child element has been added to the autoaudiosink. + * Stores the child audio sink in the player context. + * + * @param[in] object : Element added to the autoaudiosink. + */ + virtual void addAutoAudioSinkChild(GObject *object) = 0; + + /** + * @brief Notification that a child element has been removed from the autovideosink. + * Removes the child video sink in the player context if it has been stored. + * + * @param[in] object : Element removed from the autovideosink. + */ + virtual void removeAutoVideoSinkChild(GObject *object) = 0; + + /** + * @brief Notification that a child element has been removed from the autoaudiosink. + * Removes the child audio sink in the player context if it has been stored. + * + * @param[in] object : Element removed from the autoaudiosink. + */ + virtual void removeAutoAudioSinkChild(GObject *object) = 0; + + /** + * @brief Gets the sink element for source type. + * + * @param[in] mediaSourceType : the source type to obtain the sink for + * + * @retval The sink, NULL if not found. Please call getObjectUnref() if it's non-null + */ + virtual GstElement *getSink(const MediaSourceType &mediaSourceType) const = 0; + + /** + * @brief Sets the audio and video flags on the pipeline based on the input. + * + * @param[in] enableAudio : Whether to enable audio flags. + */ + virtual void setPlaybinFlags(bool enableAudio) = 0; + + /** + * @brief Pushes GstSample if playback position has changed or new segment needs to be sent. + * + * @param[in] source : The Gst Source element, that should receive new sample + * @param[in] typeStr : The media source type string + */ + virtual void pushSampleIfRequired(GstElement *source, const std::string &typeStr) = 0; + + /** + * @brief Reattaches source (or switches it) + * + * @param[in] source : The new media source + * + * @retval True on success + */ + virtual bool reattachSource(const std::unique_ptr &source) = 0; + + /** + * @brief Checks if the player has a source of the given type. + * + * @param[in] mediaSourceType : The source type to check + * + * @retval True if the player has a source of the given type, false otherwise + */ + virtual bool hasSourceType(const MediaSourceType &mediaSourceType) const = 0; + + /** + * @brief Sets source state flushed + * + * @param[in] mediaSourceType : the source type that has been flushed + */ + virtual void setSourceFlushed(const MediaSourceType &mediaSourceType) = 0; + + /** + * @brief Clears need data scheduled flag + * + * @param[in] src : the app source + */ + virtual void clearNeedDataScheduled(GstAppSrc *src) = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_PRIVATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelper.h b/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelper.h new file mode 100644 index 000000000..daad25344 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelper.h @@ -0,0 +1,38 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_H_ + +#include "GstProtectionMetadata.h" + +namespace firebolt::rialto::server +{ +class IGstProtectionMetadataHelper +{ +public: + IGstProtectionMetadataHelper() = default; + virtual ~IGstProtectionMetadataHelper() = default; + virtual GstMeta *addProtectionMetadata(GstBuffer *gstBuffer, GstRialtoProtectionData &data) = 0; + virtual GstRialtoProtectionData *getProtectionMetadataData(GstBuffer *gstBuffer) = 0; + virtual void removeProtectionMetadata(GstBuffer *gstBuffer) = 0; +}; +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelperFactory.h b/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelperFactory.h new file mode 100644 index 000000000..af872d8e9 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelperFactory.h @@ -0,0 +1,58 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ + +#include "IDecryptionService.h" +#include "IGstProtectionMetadataHelper.h" +#include "IGstWrapper.h" +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IGstProtectionMetadataHelperFactory factory class, for the creation of a GstProtectionMetadataHelper. + */ +class IGstProtectionMetadataHelperFactory +{ +public: + IGstProtectionMetadataHelperFactory() = default; + virtual ~IGstProtectionMetadataHelperFactory() = default; + + /** + * @brief Creates a IGstProtectionMetadataHelperFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a IGstProtectionMetadataHelperFactory. + * + * @retval a decryptor element instance or null on error. + */ + virtual std::unique_ptr + createProtectionMetadataWrapper(const std::shared_ptr &gstWrapper) const = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstSrc.h b/middleware/rialto-client/media/server/gstplayer/include/IGstSrc.h new file mode 100644 index 000000000..97b443934 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstSrc.h @@ -0,0 +1,123 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_SRC_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_SRC_H_ + +#include "IDecryptionService.h" +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IGstSrc; + +/** + * @brief IGstSrc factory class, for the IGstSrc singleton object. + */ +class IGstSrcFactory +{ +public: + IGstSrcFactory() = default; + virtual ~IGstSrcFactory() = default; + + /** + * @brief Gets the IGstSrcFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Gets a IGstSrc singleton object. + * + * @retval the src instance or null on error. + */ + virtual std::shared_ptr getGstSrc() = 0; +}; + +/** + * @brief Structure used for stream info + */ +struct StreamInfo +{ + explicit StreamInfo(GstElement *appSrc_ = nullptr, bool hasDrm_ = true) : appSrc(appSrc_), hasDrm(hasDrm_) {} + bool operator==(const StreamInfo &other) const + { + return appSrc == other.appSrc && hasDrm == other.hasDrm && isDataNeeded == other.isDataNeeded && + isNeedDataPending == other.isNeedDataPending && isDataPushed == other.isDataPushed; + } + GstElement *appSrc; + bool hasDrm; + bool isDataNeeded{false}; + bool isNeedDataPending{false}; + bool isDataPushed{false}; + std::list buffers{}; + bool underflowOccured{false}; +}; +/** + * @brief Definition of a stream info map. + */ +using StreamInfoMap = std::unordered_map; + +class IGstSrc +{ +public: + IGstSrc() = default; + virtual ~IGstSrc() = default; + + IGstSrc(const IGstSrc &) = delete; + IGstSrc &operator=(const IGstSrc &) = delete; + IGstSrc(IGstSrc &&) = delete; + IGstSrc &operator=(IGstSrc &&) = delete; + + /** + * @brief Initalise rialto src. + */ + virtual void initSrc() = 0; + + /** + * @brief Sets up the app source. + * + * @param[in] source : The source element. + * @param[in] appsrc : The app source to attach. + * @param[in] callbacks : Callbacks to be set on the app source. + * @param[in] userData : Data to be passed to the callbacks. + * @param[in] type : The media type of the source. + */ + virtual void setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, + GstAppSrcCallbacks *callbacks, gpointer userData, + firebolt::rialto::MediaSourceType type) = 0; + + /** + * @brief Notify rialto source that all app sources have been added. + * + * @param[in] element : The source element. + */ + virtual void allAppSrcsAdded(GstElement *element) = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_SRC_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstTextTrackSinkFactory.h b/middleware/rialto-client/media/server/gstplayer/include/IGstTextTrackSinkFactory.h new file mode 100644 index 000000000..9a9c52b06 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstTextTrackSinkFactory.h @@ -0,0 +1,56 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_TEXT_TRACK_SINK_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_TEXT_TRACK_SINK_FACTORY_H_ + +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IGstTextTrackSinkFactory factory class, for the creation of a GstTextTrackSink. + */ +class IGstTextTrackSinkFactory +{ +public: + IGstTextTrackSinkFactory() = default; + virtual ~IGstTextTrackSinkFactory() = default; + + /** + * @brief Creates a IGstTextTrackSinkFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a GstTextTrackSink. + * + * @param[in] gstWrapper : The gstreamer wrapper. + * + * @retval an element instance or null on error. + */ + virtual GstElement *createGstTextTrackSink() const = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_TEXT_TRACK_SINK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h b/middleware/rialto-client/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h new file mode 100644 index 000000000..c147dcd4f --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h @@ -0,0 +1,54 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_PRIVATE_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_PRIVATE_H_ + +#include + +namespace firebolt::rialto::server +{ +class IGstWebAudioPlayerPrivate +{ +public: + IGstWebAudioPlayerPrivate() = default; + virtual ~IGstWebAudioPlayerPrivate() = default; + + IGstWebAudioPlayerPrivate(const IGstWebAudioPlayerPrivate &) = delete; + IGstWebAudioPlayerPrivate &operator=(const IGstWebAudioPlayerPrivate &) = delete; + IGstWebAudioPlayerPrivate(IGstWebAudioPlayerPrivate &&) = delete; + IGstWebAudioPlayerPrivate &operator=(IGstWebAudioPlayerPrivate &&) = delete; + + /** + * @brief Changes pipeline state. + * + * @param[in] newState : The desired state. + * + * @retval true on success. + */ + virtual bool changePipelineState(GstState newState) = 0; + + /** + * @brief Stops worker thread. Called by the worker thread. + */ + virtual void stopWorkerThread() = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_PRIVATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IWorkerThread.h b/middleware/rialto-client/media/server/gstplayer/include/IWorkerThread.h new file mode 100644 index 000000000..9ea65b8a0 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/IWorkerThread.h @@ -0,0 +1,66 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_WORKER_THREAD_H_ +#define FIREBOLT_RIALTO_SERVER_I_WORKER_THREAD_H_ + +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server +{ +class IWorkerThread; +class IWorkerThreadFactory +{ +public: + IWorkerThreadFactory() = default; + virtual ~IWorkerThreadFactory() = default; + + virtual std::unique_ptr createWorkerThread() const = 0; +}; + +class IWorkerThread +{ +public: + IWorkerThread() = default; + virtual ~IWorkerThread() = default; + IWorkerThread(const IWorkerThread &) = delete; + IWorkerThread(IWorkerThread &&) = delete; + IWorkerThread &operator=(const IWorkerThread &) = delete; + IWorkerThread &operator=(IWorkerThread &&) = delete; + + /** + * @brief Stops the task thread + */ + virtual void stop() = 0; + + /** + * @brief Joins the task thread + */ + virtual void join() = 0; + + /** + * @brief Queues a task in the task queue. + */ + virtual void enqueueTask(std::unique_ptr &&task) = 0; + virtual void enqueuePriorityTask(std::unique_ptr &&task) = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_WORKER_THREAD_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/NeedDataMapping.h b/middleware/rialto-client/media/server/gstplayer/include/NeedDataMapping.h new file mode 100644 index 000000000..6cb0a7fef --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/NeedDataMapping.h @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_NEED_DATA_MAPPING_H_ +#define FIREBOLT_RIALTO_SERVER_NEED_DATA_MAPPING_H_ + +#include +#include +#include + +namespace firebolt::rialto::server +{ +class NeedDataMapping +{ +public: + NeedDataMapping() = default; + ~NeedDataMapping() = default; + NeedDataMapping(const NeedDataMapping &) = delete; + NeedDataMapping(NeedDataMapping &&) = delete; + NeedDataMapping &operator=(const NeedDataMapping &) = delete; + NeedDataMapping &operator=(NeedDataMapping &&) = delete; + + bool isNeedDataScheduled(GstAppSrc *src) const; + void setNeedDataScheduled(GstAppSrc *src); + void clearNeedDataScheduled(GstAppSrc *src); + +private: + mutable std::mutex m_mutex; + std::set m_scheduledNeedDatas; +}; +} // namespace firebolt::rialto::server +#endif // FIREBOLT_RIALTO_SERVER_NEED_DATA_MAPPING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/Utils.h b/middleware/rialto-client/media/server/gstplayer/include/Utils.h new file mode 100644 index 000000000..923545668 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/Utils.h @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_UTILS_H_ +#define FIREBOLT_RIALTO_SERVER_UTILS_H_ + +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "IMediaPipeline.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +bool isVideoDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +bool isAudioDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +bool isVideoParser(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +bool isVideoSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +bool isAudioSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +bool isSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +bool isDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +bool isAudio(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +bool isVideo(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); +std::optional getUnderflowSignalName(const firebolt::rialto::wrappers::IGlibWrapper &glibWrapper, + GstElement *element); +GstCaps *createCapsFromMediaSource(const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::unique_ptr &source); +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_UTILS_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/WebAudioPlayerContext.h b/middleware/rialto-client/media/server/gstplayer/include/WebAudioPlayerContext.h new file mode 100644 index 000000000..8819e93be --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/WebAudioPlayerContext.h @@ -0,0 +1,81 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_CONTEXT_H_ +#define FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_CONTEXT_H_ + +#include +#include + +#include +#include +#include +#include + +#include "IGstSrc.h" + +namespace firebolt::rialto::server +{ +constexpr uint32_t kMaxWebAudioBytes{10 * 1024}; + +struct WebAudioPlayerContext +{ + /** + * @brief The rialto src object. + */ + std::shared_ptr gstSrc{nullptr}; + + /** + * @brief The gstreamer pipeline. + */ + GstElement *pipeline{nullptr}; + + /** + * @brief The gstreamer audio source. + */ + GstElement *source{nullptr}; + + /** + * @brief Write buffer mutex. + */ + std::mutex writeBufferMutex; + + /** + * @brief Write buffer condition variable. + */ + std::condition_variable writeBufferCond; + + /** + * @brief The previous number of bytes written to the gstreamer buffers. + */ + uint32_t lastBytesWritten{}; + + /** + * @brief The number of bytes per sample. + */ + uint32_t bytesPerSample{}; + + /** + * @brief Pointer to the gstreamer volume element + */ + GstStreamVolume *gstVolumeElement{nullptr}; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_CONTEXT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/WorkerThread.h b/middleware/rialto-client/media/server/gstplayer/include/WorkerThread.h new file mode 100644 index 000000000..af6164ec7 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/WorkerThread.h @@ -0,0 +1,91 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_WORKER_THREAD_H_ +#define FIREBOLT_RIALTO_SERVER_WORKER_THREAD_H_ + +#include "IWorkerThread.h" +#include "tasks/IPlayerTask.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class WorkerThreadFactory : public IWorkerThreadFactory +{ +public: + std::unique_ptr createWorkerThread() const override; +}; + +class WorkerThread : public IWorkerThread +{ +public: + WorkerThread(); + ~WorkerThread() override; + + void stop() override; + void join() override; + void enqueueTask(std::unique_ptr &&task) override; + void enqueuePriorityTask(std::unique_ptr &&task) override; + +private: + /** + * @brief For handling new tasks in the worker thread. + */ + void taskHandler(); + + /** + * @brief Gets the next task or wait for a task on the queue. + * + * @retval Next task to process. + */ + std::unique_ptr waitForTask(); + +private: + /** + * @brief Flag used to check, if task thread is active + */ + bool m_isTaskThreadActive{true}; + + /** + * @brief Thread for handling player tasks. + */ + std::thread m_taskThread{}; + + /** + * @brief Mutex to protect the task handling. + */ + std::mutex m_taskMutex{}; + + /** + * @brief New task condition varaible. + */ + std::condition_variable m_taskCV{}; + + /** + * @brief Queue to store new tasks. + */ + std::deque> m_taskQueue{}; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_WORKER_THREAD_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h new file mode 100644 index 000000000..71b462675 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h @@ -0,0 +1,550 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GENERIC_PLAYER_TASK_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_I_GENERIC_PLAYER_TASK_FACTORY_H_ + +#include "GenericPlayerContext.h" +#include "IDataReader.h" +#include "IFlushWatcher.h" +#include "IGstGenericPlayerPrivate.h" +#include "IHeartbeatHandler.h" +#include "IMediaPipeline.h" +#include "IPlayerTask.h" +#include "MediaCommon.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IGenericPlayerTaskFactory factory class, returns a concrete implementation of IPlayerTask + */ +class IGenericPlayerTaskFactory +{ +public: + IGenericPlayerTaskFactory() = default; + virtual ~IGenericPlayerTaskFactory() = default; + + /** + * @brief Creates a AttachSamples task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] mediaSegments : The media segments to attach + * + * @retval the new AttachSamples task instance. + */ + virtual std::unique_ptr + createAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const IMediaPipeline::MediaSegmentVector &mediaSegments) const = 0; + + /** + * @brief Creates a AttachSource task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] source : The source to attach. + * + * @retval the new AttachSource task instance. + */ + virtual std::unique_ptr + createAttachSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::unique_ptr &source) const = 0; + + /** + * @brief Creates a DeepElementAdded task. + * + * @param[in] context : The GstPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] pipeline : The pipeline the signal was fired from. + * @param[in] bin : the GstBin the element was added to + * @param[in] element : an element that was added to the playbin hierarchy + * + * @retval the new DeepElementAdded task instance. + */ + virtual std::unique_ptr createDeepElementAdded(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, GstBin *pipeline, + GstBin *bin, GstElement *element) const = 0; + + /** + * @brief Creates a EnoughData task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] src : The source, which reports enough data. + * + * @retval the new EnoughData task instance. + */ + virtual std::unique_ptr createEnoughData(GenericPlayerContext &context, GstAppSrc *src) const = 0; + + /** + * @brief Creates a Eos task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] type : The media source type, which reports eos. + * + * @retval the new Eos task instance. + */ + virtual std::unique_ptr createEos(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type) const = 0; + + /** + * @brief Creates a FinishSetupSource task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * + * @retval the new FinishSetupSource task instance. + */ + virtual std::unique_ptr createFinishSetupSource(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const = 0; + + /** + * @brief Creates a HandleBusMessage task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] message : The message to be handled. + * @param[in] flushWatcher : Flush watcher instance + * + * @retval the new HandleBusMessage task instance. + */ + virtual std::unique_ptr createHandleBusMessage(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, GstMessage *message, + const IFlushWatcher &flushWatcher) const = 0; + + /** + * @brief Creates a NeedData task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] src : The source, which reports need data. + * + * @retval the new NeedData task instance. + */ + virtual std::unique_ptr createNeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + GstAppSrc *src) const = 0; + + /** + * @brief Creates a Pause task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * + * @retval the new Pause task instance. + */ + virtual std::unique_ptr createPause(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const = 0; + + /** + * @brief Creates a Play task. + * + * @param[in] player : The GstGenericPlayer instance + * + * @retval the new Play task instance. + */ + virtual std::unique_ptr createPlay(IGstGenericPlayerPrivate &player) const = 0; + + /** + * @brief Creates a ReadShmDataAndAttachSamples task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] dataReader : The shared memory data reader + * + * @retval the new ReadShmDataAndAttachSamples task instance. + */ + virtual std::unique_ptr + createReadShmDataAndAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::shared_ptr &dataReader) const = 0; + + /** + * @brief Creates a Remove Source task. + * + * @param[in] context : The GstPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] type : The media source type to remove + * + * @retval the new Remove Source task instance. + */ + virtual std::unique_ptr createRemoveSource(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type) const = 0; + + /** + * @brief Creates a ReportPosition task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * + * @retval the new ReportPosition task instance. + */ + virtual std::unique_ptr createReportPosition(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const = 0; + + /** + * @brief Creates a CheckAudioUnderflow task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * + * @retval the new CheckAudioUnderflow task instance. + */ + virtual std::unique_ptr createCheckAudioUnderflow(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const = 0; + + /** + * @brief Creates a SetPlaybackRate task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] rate : The new playback rate. + * + * @retval the new SetPlaybackRate task instance. + */ + virtual std::unique_ptr createSetPlaybackRate(GenericPlayerContext &context, double rate) const = 0; + + /** + * @brief Creates a SetPosition task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] position : The position to be set + * + * @retval the new SetPosition task instance. + */ + virtual std::unique_ptr + createSetPosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, std::int64_t position) const = 0; + + /** + * @brief Creates a SetupElement task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] element : The element to be setup. + * + * @retval the new SetupElement task instance. + */ + virtual std::unique_ptr + createSetupElement(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstElement *element) const = 0; + + /** + * @brief Creates a SetupSource task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] source : The source to be setup. + * + * @retval the new SetupSource task instance. + */ + virtual std::unique_ptr + createSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstElement *source) const = 0; + + /** + * @brief Creates a SetVideoGeometry task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] rectangle : The video geometry data. + * + * @retval the new SetVideoGeometry task instance. + */ + virtual std::unique_ptr createSetVideoGeometry(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const Rectangle &rectangle) const = 0; + + /** + * @brief Creates a SetVolume task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] volume : The volume to be set + * + * @retval the new SetVolume task instance. + */ + virtual std::unique_ptr createSetVolume(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + double targetVolume, uint32_t volumeDuration, + firebolt::rialto::EaseType easeType) const = 0; + + /** + * @brief Creates a SetMute task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] mediaSourceType : The media source type to set mute + * @param[in] mute : The mute state to be set + * + * @retval the new SetMute task instance. + */ + virtual std::unique_ptr createSetMute(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const MediaSourceType &mediaSourceType, bool mute) const = 0; + + /** + * @brief Creates a SetTextTrackIdentifier task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] textTrackIdentifier : The text track identifier to be set + * + * @retval the new SetTextTrackIdentifier task instance. + */ + virtual std::unique_ptr createSetTextTrackIdentifier(GenericPlayerContext &context, + const std::string &textTrackIdentifier) const = 0; + + /** + * @brief Creates a SetLowLatency task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] lowLatency : The low latency value to set + * + * @retval the new SetLowLatency task instance. + */ + virtual std::unique_ptr createSetLowLatency(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, bool lowLatency) const = 0; + + /** + * @brief Creates a SetSync task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] sync : The sync value to set + * + * @retval the new SetSync task instance. + */ + virtual std::unique_ptr createSetSync(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + bool sync) const = 0; + + /** + * @brief Creates a SetSyncOff task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] syncOff : The syncOff value to set + * + * @retval the new SetSyncOff task instance. + */ + virtual std::unique_ptr createSetSyncOff(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, bool syncOff) const = 0; + + /** + * @brief Creates a SetStreamSyncMode task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] type : The media source type to set stream sync mode + * @param[in] streamSyncMode : The streamSyncMode value to set + * + * @retval the new SetStreamSyncMode task instance. + */ + virtual std::unique_ptr createSetStreamSyncMode(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + int32_t streamSyncMode) const = 0; + + /** + * @brief Creates a Shutdown task. + * + * @param[in] context : The GstGenericPlayer context + * + * @retval the new Shutdown task instance. + */ + virtual std::unique_ptr createShutdown(IGstGenericPlayerPrivate &player) const = 0; + + /** + * @brief Creates a Stop task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * + * @retval the new Stop task instance. + */ + virtual std::unique_ptr createStop(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const = 0; + + /** + * @brief Creates an Underflow task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstPlayer instance + * @param[in] underflowEnabled : The underflow enabled flag (audio or video). + * + * @retval the new Underflow task instance. + */ + virtual std::unique_ptr createUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + bool underflowEnabled, MediaSourceType sourceType) const = 0; + + /** + * @brief Creates an UpdatePlaybackGroup task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] typefind : The typefind element. + * @param[in] caps : The GstCaps of added element + * + * @retval the new UpdatePlaybackGroup task instance. + */ + virtual std::unique_ptr createUpdatePlaybackGroup(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + GstElement *typefind, const GstCaps *caps) const = 0; + + /** + * @brief Creates a RenderFrame task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstPlayer instance + * + * @retval the new RenderFrame task instance. + */ + virtual std::unique_ptr createRenderFrame(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const = 0; + + /** + * @brief Creates a Ping task. + * + * @param[in] heartbeatHandler : The HeartbeatHandler instance + * + * @retval the new Ping task instance. + */ + virtual std::unique_ptr createPing(std::unique_ptr &&heartbeatHandler) const = 0; + + /** + * @brief Creates a Flush task. + * + * @param[in] context : The GstPlayer context + * @param[in] type : The media source type to flush + * @param[in] resetTime : True if time should be reset + * + * @retval the new Flush task instance. + */ + virtual std::unique_ptr createFlush(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + bool resetTime) const = 0; + + /** + * @brief Creates a SetSourcePosition task. + * + * @param[in] context : The GstPlayer context + * @param[in] player : The GstGenericPlayer instance + * @param[in] type : The media source type to set position + * @param[in] position : The new source position + * @param[in] resetTime : True if time should be reset + * @param[in] appliedRate : The applied rate after seek + * @param[in] stopPosition : The position of last pushed buffer + * + * @retval the new SetSourcePosition task instance. + */ + virtual std::unique_ptr createSetSourcePosition(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + std::int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) const = 0; + + /** + * @brief Creates a SetSubtitleOffset task. + * + * @param[in] context : The GstPlayer context + * @param[in] position : The subtitle offset position in nanoseconds + * + * @retval the new SetSubtitleOffset task instance. + */ + virtual std::unique_ptr createSetSubtitleOffset(GenericPlayerContext &context, + std::int64_t position) const = 0; + + /** + * @brief Creates a ProcessAudioGap task. + * + * @param[in] context : The GstPlayer context + * @param[in] position : Audio pts fade position + * @param[in] duration : Audio pts fade duration + * @param[in] discontinuityGap : Audio discontinuity gap + * @param[in] audioAac : True if audio codec is AAC + * + * @retval the new ProcessAudioGap task instance. + */ + virtual std::unique_ptr createProcessAudioGap(GenericPlayerContext &context, std::int64_t position, + std::uint32_t duration, std::int64_t discontinuityGap, + bool audioAac) const = 0; + + /** + * @brief Creates a SetImmediateOutput task. + * + * @param[in] context : The GstPlayer context + * @param[in] player : The GstPlayer instance + * @param[in] type : The media source type + * @param[in] immediateOutput : the value to set for immediate-output + * + * @retval the new ProcessAudioGap task instance. + */ + virtual std::unique_ptr createSetImmediateOutput(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + bool immediateOutput) const = 0; + + /** + * @brief Creates a SetBufferingLimit task. + * + * @param[in] context : The GstPlayer context + * @param[in] player : The GstPlayer instance + * @param[in] limit : the value to set for buffering limit + * + * @retval the new ProcessAudioGap task instance. + */ + virtual std::unique_ptr createSetBufferingLimit(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + std::uint32_t limit) const = 0; + + /** + * @brief Creates a SetUseBuffering task. + * + * @param[in] context : The GstPlayer context + * @param[in] player : The GstPlayer instance + * @param[in] useBuffering : the value to set for use buffering + * + * @retval the new ProcessAudioGap task instance. + */ + virtual std::unique_ptr + createSetUseBuffering(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool useBuffering) const = 0; + + /** + * @brief Creates a SwitchSource task. + * + * @param[in] player : The GstGenericPlayer instance + * @param[in] source : The source to switch. + * + * @retval the new SwitchSource task instance. + */ + virtual std::unique_ptr + createSwitchSource(IGstGenericPlayerPrivate &player, + const std::unique_ptr &source) const = 0; + + /** + * @brief Creates a SynchroniseSubtitleClock task. + * + * @param[in] context : The GstGenericPlayer context + * @param[in] player : The GstGenericPlayer instance + * + * @retval the new SynchroniseSubtitleClock task instance. + */ + virtual std::unique_ptr createSynchroniseSubtitleClock(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const = 0; +}; + +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GENERIC_PLAYER_TASK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/IPlayerTask.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/IPlayerTask.h new file mode 100644 index 000000000..4dc31f36a --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/IPlayerTask.h @@ -0,0 +1,39 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_PLAYER_TASK_H_ +#define FIREBOLT_RIALTO_SERVER_I_PLAYER_TASK_H_ + +namespace firebolt::rialto::server +{ +class IPlayerTask +{ +public: + IPlayerTask() = default; + virtual ~IPlayerTask() = default; + IPlayerTask(const IPlayerTask &) = delete; + IPlayerTask(IPlayerTask &&) = delete; + IPlayerTask &operator=(const IPlayerTask &) = delete; + IPlayerTask &operator=(IPlayerTask &&) = delete; + + virtual void execute() const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_PLAYER_TASK_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h new file mode 100644 index 000000000..a067f68a4 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h @@ -0,0 +1,148 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ + +#include "IGstWebAudioPlayerPrivate.h" +#include "IHeartbeatHandler.h" +#include "IPlayerTask.h" +#include "WebAudioPlayerContext.h" +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IWebAudioPlayerTaskFactory factory class, returns a concrete implementation of IPlayerTask + */ +class IWebAudioPlayerTaskFactory +{ +public: + IWebAudioPlayerTaskFactory() = default; + virtual ~IWebAudioPlayerTaskFactory() = default; + + /** + * @brief Creates a Shutdown task. + * + * @param[in] player : The GstWebAudioPlayer instance + * + * @retval the new Shutdown task instance. + */ + virtual std::unique_ptr createShutdown(IGstWebAudioPlayerPrivate &player) const = 0; + + /** + * @brief Creates a Stop task. + * + * @param[in] player : The GstWebAudioPlayer instance + * + * @retval the new Stop task instance. + */ + virtual std::unique_ptr createStop(IGstWebAudioPlayerPrivate &player) const = 0; + + /** + * @brief Creates a Play task. + * + * @param[in] player : The GstWebAudioPlayer instance + * + * @retval the new Play task instance. + */ + virtual std::unique_ptr createPlay(IGstWebAudioPlayerPrivate &player) const = 0; + + /** + * @brief Creates a Pause task. + * + * @param[in] player : The GstWebAudioPlayer instance + * + * @retval the new Pause task instance. + */ + virtual std::unique_ptr createPause(IGstWebAudioPlayerPrivate &player) const = 0; + + /** + * @brief Creates a SetCaps task. + * + * @param[in] context : The GstWebAudioPlayer context + * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM) + * @param[in] config : Additional type dependent configuration data or nullptr + * + * @retval the new SetCaps task instance. + */ + virtual std::unique_ptr createSetCaps(WebAudioPlayerContext &context, const std::string &audioMimeType, + std::weak_ptr config) const = 0; + + /** + * @brief Creates a Eos task. + * + * @param[in] context : The GstWebAudioPlayer context + * + * @retval the new Eos task instance. + */ + virtual std::unique_ptr createEos(WebAudioPlayerContext &context) const = 0; + + /** + * @brief Creates a SetVolume task. + * + * @param[in] context : The GstWebAudioPlayer context + * @param[in] volume : The volume to set + * + * @retval the new SetVolume task instance. + */ + virtual std::unique_ptr createSetVolume(WebAudioPlayerContext &context, double volume) const = 0; + + /** + * @brief Creates a WriteBuffer task. + * + * @param[in] context : The GstWebAudioPlayer context + * @param[in] mainPtr : Pointer to the start of the data + * @param[in] mainLength : Amount of bytes to write from the mainPtr + * @param[in] wrapPtr : Pointer to the start of the wrapped data + * @param[in] wrapLength : Amount of bytes to write from the wrapPtr + * + * @retval the new SetVolume task instance. + */ + virtual std::unique_ptr createWriteBuffer(WebAudioPlayerContext &context, uint8_t *mainPtr, + uint32_t mainLength, uint8_t *wrapPtr, + uint32_t wrapLength) const = 0; + + /** + * @brief Creates a HandleBusMessage task. + * + * @param[in] context : The GstWebAudioPlayer context + * @param[in] player : The GstWebAudioPlayer instance + * @param[in] message : The message to be handled + * + * @retval the new HandleBusMessage task instance. + */ + virtual std::unique_ptr createHandleBusMessage(WebAudioPlayerContext &context, + IGstWebAudioPlayerPrivate &player, + GstMessage *message) const = 0; + + /** + * @brief Creates a Ping task. + * + * @param[in] heartbeatHandler : The HeartbeatHandler instance + * + * @retval the new Ping task instance. + */ + virtual std::unique_ptr createPing(std::unique_ptr &&heartbeatHandler) const = 0; +}; + +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSamples.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSamples.h new file mode 100644 index 000000000..5c51d6bc7 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSamples.h @@ -0,0 +1,72 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SAMPLES_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SAMPLES_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IMediaPipeline.h" +#include "IPlayerTask.h" +#include +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class AttachSamples : public IPlayerTask +{ +public: + AttachSamples(GenericPlayerContext &context, + const std::shared_ptr &gstWrapper, + IGstGenericPlayerPrivate &player, const IMediaPipeline::MediaSegmentVector &mediaSegments); + ~AttachSamples() override; + void execute() const override; + +private: + void attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const; + struct AudioData + { + GstBuffer *buffer; + int32_t rate; + int32_t channels; + std::shared_ptr codecData; + uint64_t clippingStart; + uint64_t clippingEnd; + }; + struct VideoData + { + GstBuffer *buffer; + int32_t width; + int32_t height; + Fraction frameRate; + std::shared_ptr codecData; + }; + + GenericPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + IGstGenericPlayerPrivate &m_player; + std::vector m_audioData; + std::vector m_videoData; + std::vector m_subtitleData; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SAMPLES_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSource.h new file mode 100644 index 000000000..b9f1f83d6 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSource.h @@ -0,0 +1,61 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SOURCE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SOURCE_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstTextTrackSinkFactory.h" +#include "IGstWrapper.h" +#include "IMediaPipeline.h" +#include "IPlayerTask.h" +#include "IRdkGstreamerUtilsWrapper.h" +#include +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class AttachSource : public IPlayerTask +{ +public: + AttachSource(GenericPlayerContext &context, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr &gstTextTrackSinkFactory, + IGstGenericPlayerPrivate &player, const std::unique_ptr &source); + ~AttachSource() override; + void execute() const override; + +private: + void addSource() const; + void reattachAudioSource() const; + + GenericPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + std::shared_ptr m_gstTextTrackSinkFactory; + IGstGenericPlayerPrivate &m_player; + std::unique_ptr m_attachedSource; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/CheckAudioUnderflow.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/CheckAudioUnderflow.h new file mode 100644 index 000000000..5b36dd130 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/CheckAudioUnderflow.h @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_CHECK_AUDIO_UNDERFLOW_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_CHECK_AUDIO_UNDERFLOW_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class CheckAudioUnderflow : public IPlayerTask +{ +public: + CheckAudioUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + std::shared_ptr gstWrapper); + ~CheckAudioUnderflow() override = default; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; + std::shared_ptr m_gstWrapper; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_CHECK_AUDIO_UNDERFLOW_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/DeepElementAdded.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/DeepElementAdded.h new file mode 100644 index 000000000..424d61e81 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/DeepElementAdded.h @@ -0,0 +1,56 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_DEEP_ELEMENT_ADDED_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_DEEP_ELEMENT_ADDED_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class DeepElementAdded : public IPlayerTask +{ +public: + DeepElementAdded(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, GstBin *pipeline, + GstBin *bin, GstElement *element); + ~DeepElementAdded() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + GstBin *m_pipeline; + GstBin *m_bin; + GstElement *m_element; + gchar *m_elementName; + bool m_callbackRegistered; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_DEEP_ELEMENT_ADDED_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/EnoughData.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/EnoughData.h new file mode 100644 index 000000000..debc39bed --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/EnoughData.h @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ENOUGH_DATA_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ENOUGH_DATA_H_ + +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server +{ +struct GenericPlayerContext; +} // namespace firebolt::rialto::server + +namespace firebolt::rialto::server::tasks::generic +{ +class EnoughData : public IPlayerTask +{ +public: + EnoughData(GenericPlayerContext &context, GstAppSrc *src); + ~EnoughData() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + GstAppSrc *m_src; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ENOUGH_DATA_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Eos.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Eos.h new file mode 100644 index 000000000..650a64ab2 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Eos.h @@ -0,0 +1,49 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_EOS_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_EOS_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include "MediaCommon.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class Eos : public IPlayerTask +{ +public: + Eos(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::shared_ptr gstWrapper, + const firebolt::rialto::MediaSourceType &type); + ~Eos() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + std::shared_ptr m_gstWrapper; + firebolt::rialto::MediaSourceType m_type; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_EOS_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/FinishSetupSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/FinishSetupSource.h new file mode 100644 index 000000000..2bdc52869 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/FinishSetupSource.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FINISH_SETUP_SOURCE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FINISH_SETUP_SOURCE_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class FinishSetupSource : public IPlayerTask +{ +public: + FinishSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client); + ~FinishSetupSource() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FINISH_SETUP_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Flush.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Flush.h new file mode 100644 index 000000000..77b795d17 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Flush.h @@ -0,0 +1,51 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FLUSH_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FLUSH_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class Flush : public IPlayerTask +{ +public: + Flush(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + std::shared_ptr gstWrapper, const MediaSourceType &type, + bool resetTime); + ~Flush() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; + std::shared_ptr m_gstWrapper; + MediaSourceType m_type; + bool m_resetTime; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FLUSH_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h new file mode 100644 index 000000000..87cc76f45 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h @@ -0,0 +1,145 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_TASK_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_TASK_FACTORY_H_ + +#include "IGenericPlayerTaskFactory.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerClient.h" +#include "IGstTextTrackSinkFactory.h" +#include "IGstWrapper.h" +#include "IMediaPipeline.h" +#include +#include + +namespace firebolt::rialto::server +{ +class GenericPlayerTaskFactory : public IGenericPlayerTaskFactory +{ +public: + GenericPlayerTaskFactory( + IGstGenericPlayerClient *client, const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr &rdkGstreamerUtilsWrapper, + const std::shared_ptr &gstTextTrackSinkFactory); + ~GenericPlayerTaskFactory() override = default; + + std::unique_ptr createAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const IMediaPipeline::MediaSegmentVector &mediaSegments) const override; + std::unique_ptr + createAttachSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::unique_ptr &source) const override; + std::unique_ptr createDeepElementAdded(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + GstBin *pipeline, GstBin *bin, + GstElement *element) const override; + std::unique_ptr createEnoughData(GenericPlayerContext &context, GstAppSrc *src) const override; + std::unique_ptr createEos(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type) const override; + std::unique_ptr createFinishSetupSource(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const override; + std::unique_ptr createHandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + GstMessage *message, + const IFlushWatcher &flushWatcher) const override; + std::unique_ptr createNeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + GstAppSrc *src) const override; + std::unique_ptr createPause(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const override; + std::unique_ptr createPlay(IGstGenericPlayerPrivate &player) const override; + std::unique_ptr + createReadShmDataAndAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::shared_ptr &dataReader) const override; + std::unique_ptr createRemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type) const override; + std::unique_ptr createReportPosition(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const override; + std::unique_ptr createCheckAudioUnderflow(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const override; + std::unique_ptr createSetPlaybackRate(GenericPlayerContext &context, double rate) const override; + std::unique_ptr createSetPosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::int64_t position) const override; + std::unique_ptr createSetupElement(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + GstElement *element) const override; + std::unique_ptr createSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + GstElement *source) const override; + std::unique_ptr createSetVideoGeometry(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const Rectangle &rectangle) const override; + std::unique_ptr createSetVolume(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + double targetVolume, uint32_t volumeDuration, + firebolt::rialto::EaseType easeType) const override; + std::unique_ptr createSetMute(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const MediaSourceType &mediaSourceType, bool mute) const override; + std::unique_ptr createSetTextTrackIdentifier(GenericPlayerContext &context, + const std::string &textTrackIdentifier) const override; + std::unique_ptr createSetLowLatency(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + bool lowLatency) const override; + std::unique_ptr createSetSync(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + bool sync) const override; + std::unique_ptr createSetSyncOff(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + bool syncOff) const override; + std::unique_ptr createSetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + int32_t streamSyncMode) const override; + std::unique_ptr createShutdown(IGstGenericPlayerPrivate &player) const override; + std::unique_ptr createStop(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const override; + std::unique_ptr createUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + bool underflowEnable, MediaSourceType sourceType) const override; + std::unique_ptr createUpdatePlaybackGroup(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, GstElement *typefind, + const GstCaps *caps) const override; + std::unique_ptr createRenderFrame(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const override; + std::unique_ptr createPing(std::unique_ptr &&heartbeatHandler) const override; + std::unique_ptr createFlush(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + bool resetTime) const override; + std::unique_ptr createSetSourcePosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + std::int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) const override; + std::unique_ptr createSetSubtitleOffset(GenericPlayerContext &context, + std::int64_t position) const override; + std::unique_ptr createProcessAudioGap(GenericPlayerContext &context, std::int64_t position, + std::uint32_t duration, std::int64_t discontinuityGap, + bool audioAac) const override; + std::unique_ptr createSetImmediateOutput(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + bool immediateOutput) const override; + std::unique_ptr createSetBufferingLimit(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::uint32_t limit) const override; + std::unique_ptr createSetUseBuffering(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + bool useBuffering) const override; + std::unique_ptr + createSwitchSource(IGstGenericPlayerPrivate &player, + const std::unique_ptr &source) const override; + + std::unique_ptr createSynchroniseSubtitleClock(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const override; + +private: + IGstGenericPlayerClient *m_client; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + std::shared_ptr m_rdkGstreamerUtilsWrapper; + std::shared_ptr m_gstTextTrackSinkFactory; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_TASK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h new file mode 100644 index 000000000..87760d802 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h @@ -0,0 +1,60 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_HANDLE_BUS_MESSAGE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_HANDLE_BUS_MESSAGE_H_ + +#include "GenericPlayerContext.h" +#include "IFlushWatcher.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class HandleBusMessage : public IPlayerTask +{ +public: + HandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, GstMessage *message, + const IFlushWatcher &flushWatcher); + ~HandleBusMessage() override; + void execute() const override; + +private: + bool allSourcesEos() const; + + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + GstMessage *m_message; + const IFlushWatcher &m_flushWatcher; + bool m_isFlushOngoingDuringCreation; + bool m_isAsyncFlushOngoingDuringCreation; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_HANDLE_BUS_MESSAGE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/NeedData.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/NeedData.h new file mode 100644 index 000000000..47bac3d9c --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/NeedData.h @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_NEED_DATA_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_NEED_DATA_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class NeedData : public IPlayerTask +{ +public: + NeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + GstAppSrc *src); + ~NeedData() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; + GstAppSrc *m_src; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_NEED_DATA_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Pause.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Pause.h new file mode 100644 index 000000000..0e4339b17 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Pause.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PAUSE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PAUSE_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class Pause : public IPlayerTask +{ +public: + explicit Pause(GenericPlayerContext &context, IGstGenericPlayerPrivate &player); + ~Pause() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PAUSE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Ping.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Ping.h new file mode 100644 index 000000000..55f2a1978 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Ping.h @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PING_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PING_H_ + +#include "IHeartbeatHandler.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class Ping : public IPlayerTask +{ +public: + explicit Ping(std::unique_ptr &&heartbeatHandler); + ~Ping() override; + void execute() const override; + +private: + std::unique_ptr m_heartbeatHandler; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Play.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Play.h new file mode 100644 index 000000000..bd4717569 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Play.h @@ -0,0 +1,40 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PLAY_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PLAY_H_ + +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class Play : public IPlayerTask +{ +public: + explicit Play(IGstGenericPlayerPrivate &player); + ~Play() override; + void execute() const override; + +private: + IGstGenericPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PLAY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ProcessAudioGap.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ProcessAudioGap.h new file mode 100644 index 000000000..1d77ff028 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ProcessAudioGap.h @@ -0,0 +1,56 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PROCESS_AUDIO_GAP_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PROCESS_AUDIO_GAP_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include "IRdkGstreamerUtilsWrapper.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class ProcessAudioGap : public IPlayerTask +{ +public: + ProcessAudioGap(GenericPlayerContext &context, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr rdkGstreamerUtilsWrapper, + std::int64_t position, std::uint32_t duration, std::int64_t discontinuityGap, bool audioAac); + ~ProcessAudioGap() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + std::shared_ptr m_rdkGstreamerUtilsWrapper; + std::int64_t m_position; + std::uint32_t m_duration; + std::int64_t m_discontinuityGap; + bool m_audioAac; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PROCESS_AUDIO_GAP_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReadShmDataAndAttachSamples.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReadShmDataAndAttachSamples.h new file mode 100644 index 000000000..80844112b --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReadShmDataAndAttachSamples.h @@ -0,0 +1,50 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_READ_SHM_DATA_AND_ATTACH_SAMPLES_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_READ_SHM_DATA_AND_ATTACH_SAMPLES_H_ + +#include "GenericPlayerContext.h" +#include "IDataReader.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class ReadShmDataAndAttachSamples : public IPlayerTask +{ +public: + ReadShmDataAndAttachSamples(GenericPlayerContext &context, + const std::shared_ptr &gstWrapper, + IGstGenericPlayerPrivate &player, const std::shared_ptr &dataReader); + ~ReadShmDataAndAttachSamples() override; + void execute() const override; + +private: + void attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const; + GenericPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + IGstGenericPlayerPrivate &m_player; + std::shared_ptr m_dataReader; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_READ_SHM_DATA_AND_ATTACH_SAMPLES_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RemoveSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RemoveSource.h new file mode 100644 index 000000000..8e3eb1b68 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RemoveSource.h @@ -0,0 +1,49 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REMOVE_SOURCE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REMOVE_SOURCE_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class RemoveSource : public IPlayerTask +{ +public: + RemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + std::shared_ptr gstWrapper, const MediaSourceType &type); + ~RemoveSource() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; + std::shared_ptr m_gstWrapper; + MediaSourceType m_type; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REMOVE_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RenderFrame.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RenderFrame.h new file mode 100644 index 000000000..c5e9801bf --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RenderFrame.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_RENDER_FRAME_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_RENDER_FRAME_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class RenderFrame : public IPlayerTask +{ +public: + RenderFrame(GenericPlayerContext &context, IGstGenericPlayerPrivate &player); + ~RenderFrame() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_RENDER_FRAME_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReportPosition.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReportPosition.h new file mode 100644 index 000000000..cbe98b5bf --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReportPosition.h @@ -0,0 +1,49 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REPORT_POSITION_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REPORT_POSITION_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class ReportPosition : public IPlayerTask +{ +public: + ReportPosition(GenericPlayerContext &context, IGstGenericPlayerClient *client, + const std::shared_ptr &gstWrapper, + IGstGenericPlayerPrivate &player); + ~ReportPosition() override = default; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerClient *m_gstPlayerClient; + std::shared_ptr m_gstWrapper; + IGstGenericPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REPORT_POSITION_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetBufferingLimit.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetBufferingLimit.h new file mode 100644 index 000000000..70ecfa2c3 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetBufferingLimit.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_BUFFERING_LIMIT_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_BUFFERING_LIMIT_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetBufferingLimit : public IPlayerTask +{ +public: + SetBufferingLimit(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, std::uint32_t limit); + ~SetBufferingLimit() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + std::uint32_t m_limit; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_BUFFERING_LIMIT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetImmediateOutput.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetImmediateOutput.h new file mode 100644 index 000000000..a5fdbb8fd --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetImmediateOutput.h @@ -0,0 +1,49 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_IMMEDIATE_OUTPUT_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_IMMEDIATE_OUTPUT_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" + +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetImmediateOutput : public IPlayerTask +{ +public: + explicit SetImmediateOutput(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const MediaSourceType &type, bool immediateOutput); + ~SetImmediateOutput() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + const MediaSourceType m_type; + bool m_immediateOutput; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_IMMEDIATE_OUTPUT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetLowLatency.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetLowLatency.h new file mode 100644 index 000000000..0094dab8e --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetLowLatency.h @@ -0,0 +1,43 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_LOW_LATENCY_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_LOW_LATENCY_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class SetLowLatency : public IPlayerTask +{ +public: + SetLowLatency(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool lowLatency); + ~SetLowLatency() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + bool m_lowLatency; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_LOW_LATENCY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetMute.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetMute.h new file mode 100644 index 000000000..92b6f91c8 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetMute.h @@ -0,0 +1,52 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_MUTE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_MUTE_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetMute : public IPlayerTask +{ +public: + SetMute(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const MediaSourceType &mediaSourceType, bool mute); + ~SetMute() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + const MediaSourceType &m_mediaSourceType; + bool m_mute; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_MUTE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPlaybackRate.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPlaybackRate.h new file mode 100644 index 000000000..9ca3acf6f --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPlaybackRate.h @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_PLAYBACK_RATE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_PLAYBACK_RATE_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetPlaybackRate : public IPlayerTask +{ +public: + SetPlaybackRate(GenericPlayerContext &context, std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, double rate); + ~SetPlaybackRate() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + double m_rate; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_PLAYBACK_RATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPosition.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPosition.h new file mode 100644 index 000000000..974509cf9 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPosition.h @@ -0,0 +1,50 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_POSITION_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_POSITION_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetPosition : public IPlayerTask +{ +public: + SetPosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + std::shared_ptr gstWrapper, std::int64_t position); + ~SetPosition() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; + std::shared_ptr m_gstWrapper; + std::int64_t m_position; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_POSITION_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSourcePosition.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSourcePosition.h new file mode 100644 index 000000000..253ab55f1 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSourcePosition.h @@ -0,0 +1,58 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SOURCE_POSITION_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SOURCE_POSITION_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetSourcePosition : public IPlayerTask +{ +public: + SetSourcePosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + const std::shared_ptr &glibWrapper, const MediaSourceType &type, + std::int64_t position, bool resetTime, double appliedRate, uint64_t stopPosition); + ~SetSourcePosition() override; + void execute() const override; + +private: + void setSubtitlePosition(GstElement *source) const; + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; + std::shared_ptr m_glibWrapper; + MediaSourceType m_type; + std::int64_t m_position; + bool m_resetTime; + double m_appliedRate; + uint64_t m_stopPosition; +}; + +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SOURCE_POSITION_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetStreamSyncMode.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetStreamSyncMode.h new file mode 100644 index 000000000..7085cc5d0 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetStreamSyncMode.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_STREAM_SYNC_MODE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_STREAM_SYNC_MODE_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class SetStreamSyncMode : public IPlayerTask +{ +public: + SetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, const MediaSourceType &type, + int32_t streamSyncMode); + ~SetStreamSyncMode() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + MediaSourceType m_type; + int32_t m_streamSyncMode; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_STREAM_SYNC_MODE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSubtitleOffset.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSubtitleOffset.h new file mode 100644 index 000000000..e8533409d --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSubtitleOffset.h @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SUBTITLE_OFFSET_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SUBTITLE_OFFSET_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetSubtitleOffset : public IPlayerTask +{ +public: + SetSubtitleOffset(GenericPlayerContext &context, const std::shared_ptr &glibWrapper, + std::int64_t position); + ~SetSubtitleOffset() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + std::shared_ptr m_glibWrapper; + std::int64_t m_position; +}; + +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SUBTITLE_OFFSET_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSync.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSync.h new file mode 100644 index 000000000..9810ab8bf --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSync.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetSync : public IPlayerTask +{ +public: + SetSync(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool sync); + ~SetSync() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + bool m_sync; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSyncOff.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSyncOff.h new file mode 100644 index 000000000..ac10f98e0 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSyncOff.h @@ -0,0 +1,43 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_OFF_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_OFF_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class SetSyncOff : public IPlayerTask +{ +public: + SetSyncOff(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool syncOff); + ~SetSyncOff() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + bool m_syncOff; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_OFF_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetTextTrackIdentifier.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetTextTrackIdentifier.h new file mode 100644 index 000000000..01dad493f --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetTextTrackIdentifier.h @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_TEXT_TRACK_IDENTIFIER_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_TEXT_TRACK_IDENTIFIER_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetTextTrackIdentifier : public IPlayerTask +{ +public: + SetTextTrackIdentifier(GenericPlayerContext &context, + std::shared_ptr glibWrapper, + const std::string &textTrackIdentifier); + ~SetTextTrackIdentifier() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + std::shared_ptr m_glibWrapper; + const std::string m_textTrackIdentifier; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_TEXT_TRACK_IDENTIFIER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetUseBuffering.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetUseBuffering.h new file mode 100644 index 000000000..67d6514a8 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetUseBuffering.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_USE_BUFFERING_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_USE_BUFFERING_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetUseBuffering : public IPlayerTask +{ +public: + SetUseBuffering(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool useBuffering); + ~SetUseBuffering() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + bool m_useBuffering; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_USE_BUFFERING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVideoGeometry.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVideoGeometry.h new file mode 100644 index 000000000..be7e47974 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVideoGeometry.h @@ -0,0 +1,43 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VIDEO_GEOMETRY_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VIDEO_GEOMETRY_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class SetVideoGeometry : public IPlayerTask +{ +public: + SetVideoGeometry(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, const Rectangle &rectangle); + ~SetVideoGeometry() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + Rectangle m_rectangle; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VIDEO_GEOMETRY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVolume.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVolume.h new file mode 100644 index 000000000..347bd33f4 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVolume.h @@ -0,0 +1,55 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VOLUME_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VOLUME_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetVolume : public IPlayerTask +{ +public: + SetVolume(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + std::shared_ptr rdkGstreamerUtilsWrapper, + double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType); + ~SetVolume() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + std::shared_ptr m_rdkGstreamerUtilsWrapper; + double m_targetVolume; + uint32_t m_volumeDuration; + firebolt::rialto::EaseType m_easeType; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VOLUME_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupElement.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupElement.h new file mode 100644 index 000000000..dc3afb377 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupElement.h @@ -0,0 +1,51 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_ELEMENT_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_ELEMENT_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetupElement : public IPlayerTask +{ +public: + SetupElement(GenericPlayerContext &context, std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + IGstGenericPlayerPrivate &player, GstElement *element); + ~SetupElement() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + IGstGenericPlayerPrivate &m_player; + GstElement *m_element; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_ELEMENT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupSource.h new file mode 100644 index 000000000..bfcad97a9 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupSource.h @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_SOURCE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_SOURCE_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SetupSource : public IPlayerTask +{ +public: + SetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstElement *source); + ~SetupSource() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + GstElement *m_source; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Shutdown.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Shutdown.h new file mode 100644 index 000000000..32bf6d89e --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Shutdown.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ + +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server +{ +class IGstGenericPlayerPrivate; +} // namespace firebolt::rialto::server + +namespace firebolt::rialto::server::tasks::generic +{ +class Shutdown : public IPlayerTask +{ +public: + explicit Shutdown(IGstGenericPlayerPrivate &player); + ~Shutdown() override; + void execute() const override; + +private: + IGstGenericPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Stop.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Stop.h new file mode 100644 index 000000000..13316c78c --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Stop.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_STOP_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_STOP_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::generic +{ +class Stop : public IPlayerTask +{ +public: + Stop(GenericPlayerContext &context, IGstGenericPlayerPrivate &player); + ~Stop() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_STOP_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SwitchSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SwitchSource.h new file mode 100644 index 000000000..e9a082fd5 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SwitchSource.h @@ -0,0 +1,49 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SWITCH_SOURCE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SWITCH_SOURCE_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IMediaPipeline.h" +#include "IPlayerTask.h" +#include "IRdkGstreamerUtilsWrapper.h" +#include +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SwitchSource : public IPlayerTask +{ +public: + SwitchSource(IGstGenericPlayerPrivate &player, const std::unique_ptr &source); + ~SwitchSource() override; + void execute() const override; + +private: + IGstGenericPlayerPrivate &m_player; + std::unique_ptr m_source; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SWITCH_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SynchroniseSubtitleClock.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SynchroniseSubtitleClock.h new file mode 100644 index 000000000..f38a1ccbb --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SynchroniseSubtitleClock.h @@ -0,0 +1,50 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SYNCHRONISE_SUBTITLE_CLOCK_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SYNCHRONISE_SUBTITLE_CLOCK_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class SynchroniseSubtitleClock : public IPlayerTask +{ +public: + SynchroniseSubtitleClock(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper); + ~SynchroniseSubtitleClock() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SYNCHRONISE_SUBTITLE_CLOCK_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Underflow.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Underflow.h new file mode 100644 index 000000000..fc9507e63 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Underflow.h @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UNDERFLOW_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UNDERFLOW_H_ + +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class Underflow : public IPlayerTask +{ +public: + Underflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + bool underflowEnabled, MediaSourceType sourceType); + ~Underflow() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + IGstGenericPlayerClient *m_gstPlayerClient; + bool m_underflowEnabled; + MediaSourceType m_sourceType; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UNDERFLOW_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/UpdatePlaybackGroup.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/UpdatePlaybackGroup.h new file mode 100644 index 000000000..6ecdd0eaf --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/UpdatePlaybackGroup.h @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UPDATE_PLAYBACK_GROUP_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UPDATE_PLAYBACK_GROUP_H_ + +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +class UpdatePlaybackGroup : public IPlayerTask +{ +public: + UpdatePlaybackGroup(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, GstElement *typefind, + const GstCaps *caps); + ~UpdatePlaybackGroup() override; + void execute() const override; + +private: + GenericPlayerContext &m_context; + IGstGenericPlayerPrivate &m_player; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + GstElement *m_typefind; + const GstCaps *m_caps; +}; +} // namespace firebolt::rialto::server::tasks::generic + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UPDATE_PLAYBACK_GROUP_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Eos.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Eos.h new file mode 100644 index 000000000..27a8b16ad --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Eos.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_EOS_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_EOS_H_ + +#include "IGstWebAudioPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include "MediaCommon.h" +#include "WebAudioPlayerContext.h" +#include + +namespace firebolt::rialto::server::tasks::webaudio +{ +class Eos : public IPlayerTask +{ +public: + Eos(WebAudioPlayerContext &context, std::shared_ptr gstWrapper); + ~Eos() override; + void execute() const override; + +private: + WebAudioPlayerContext &m_context; + std::shared_ptr m_gstWrapper; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_EOS_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/HandleBusMessage.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/HandleBusMessage.h new file mode 100644 index 000000000..996e6c258 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/HandleBusMessage.h @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_HANDLE_BUS_MESSAGE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_HANDLE_BUS_MESSAGE_H_ + +#include "IGlibWrapper.h" +#include "IGstWebAudioPlayerClient.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include "WebAudioPlayerContext.h" +#include +#include + +namespace firebolt::rialto::server::tasks::webaudio +{ +class HandleBusMessage : public IPlayerTask +{ +public: + HandleBusMessage(WebAudioPlayerContext &context, IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, GstMessage *message); + ~HandleBusMessage() override; + void execute() const override; + +private: + WebAudioPlayerContext &m_context; + IGstWebAudioPlayerPrivate &m_player; + IGstWebAudioPlayerClient *m_gstPlayerClient; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + GstMessage *m_message; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_HANDLE_BUS_MESSAGE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Pause.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Pause.h new file mode 100644 index 000000000..da6c327bb --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Pause.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PAUSE_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PAUSE_H_ + +#include "IGstWebAudioPlayerClient.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +class Pause : public IPlayerTask +{ +public: + explicit Pause(IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client); + ~Pause() override; + void execute() const override; + +private: + IGstWebAudioPlayerPrivate &m_player; + IGstWebAudioPlayerClient *m_gstPlayerClient; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PAUSE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Ping.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Ping.h new file mode 100644 index 000000000..4e9d38cb6 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Ping.h @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PING_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PING_H_ + +#include "IHeartbeatHandler.h" +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server::tasks::webaudio +{ +class Ping : public IPlayerTask +{ +public: + explicit Ping(std::unique_ptr &&heartbeatHandler); + ~Ping() override; + void execute() const override; + +private: + std::unique_ptr m_heartbeatHandler; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Play.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Play.h new file mode 100644 index 000000000..476335b61 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Play.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PLAY_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PLAY_H_ + +#include "IGstWebAudioPlayerClient.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +class Play : public IPlayerTask +{ +public: + Play(IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client); + ~Play() override; + void execute() const override; + +private: + IGstWebAudioPlayerPrivate &m_player; + IGstWebAudioPlayerClient *m_gstPlayerClient; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PLAY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetCaps.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetCaps.h new file mode 100644 index 000000000..fefafd0c3 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetCaps.h @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_CAPS_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_CAPS_H_ + +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include "WebAudioPlayerContext.h" +#include +#include + +namespace firebolt::rialto::server::tasks::webaudio +{ +class SetCaps : public IPlayerTask +{ +public: + SetCaps(WebAudioPlayerContext &context, std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, const std::string &audioMimeType, + std::weak_ptr config); + ~SetCaps() override; + void execute() const override; + +private: + GstCaps *createCapsFromMimeType() const; + void setBytesPerSample() const; + + WebAudioPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; + const std::string m_audioMimeType; + WebAudioConfig m_config; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_CAPS_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetVolume.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetVolume.h new file mode 100644 index 000000000..7355621f2 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetVolume.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_VOLUME_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_VOLUME_H_ + +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include "WebAudioPlayerContext.h" +#include + +namespace firebolt::rialto::server::tasks::webaudio +{ +class SetVolume : public IPlayerTask +{ +public: + SetVolume(WebAudioPlayerContext &context, std::shared_ptr gstWrapper, + double volume); + ~SetVolume() override; + void execute() const override; + +private: + WebAudioPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + double m_volume; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_VOLUME_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Shutdown.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Shutdown.h new file mode 100644 index 000000000..1721730c8 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Shutdown.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ + +#include "IPlayerTask.h" +#include + +namespace firebolt::rialto::server +{ +class IGstWebAudioPlayerPrivate; +} // namespace firebolt::rialto::server + +namespace firebolt::rialto::server::tasks::webaudio +{ +class Shutdown : public IPlayerTask +{ +public: + explicit Shutdown(IGstWebAudioPlayerPrivate &player); + ~Shutdown() override; + void execute() const override; + +private: + IGstWebAudioPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Stop.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Stop.h new file mode 100644 index 000000000..519d84f19 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Stop.h @@ -0,0 +1,40 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_STOP_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_STOP_H_ + +#include "IGstWebAudioPlayerPrivate.h" +#include "IPlayerTask.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +class Stop : public IPlayerTask +{ +public: + explicit Stop(IGstWebAudioPlayerPrivate &player); + ~Stop() override; + void execute() const override; + +private: + IGstWebAudioPlayerPrivate &m_player; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_STOP_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h new file mode 100644 index 000000000..c1cbdc059 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h @@ -0,0 +1,61 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ + +#include "IGlibWrapper.h" +#include "IGstWebAudioPlayerClient.h" +#include "IGstWrapper.h" +#include "IWebAudioPlayerTaskFactory.h" +#include +#include + +namespace firebolt::rialto::server +{ +class WebAudioPlayerTaskFactory : public IWebAudioPlayerTaskFactory +{ +public: + WebAudioPlayerTaskFactory(IGstWebAudioPlayerClient *client, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper); + ~WebAudioPlayerTaskFactory() override = default; + + std::unique_ptr createShutdown(IGstWebAudioPlayerPrivate &player) const override; + std::unique_ptr createStop(IGstWebAudioPlayerPrivate &player) const override; + std::unique_ptr createPlay(IGstWebAudioPlayerPrivate &player) const override; + std::unique_ptr createPause(IGstWebAudioPlayerPrivate &player) const override; + std::unique_ptr createSetCaps(WebAudioPlayerContext &context, const std::string &audioMimeType, + std::weak_ptr config) const override; + std::unique_ptr createEos(WebAudioPlayerContext &context) const override; + std::unique_ptr createSetVolume(WebAudioPlayerContext &context, double volume) const override; + std::unique_ptr createWriteBuffer(WebAudioPlayerContext &context, uint8_t *mainPtr, uint32_t mainLength, + uint8_t *wrapPtr, uint32_t wrapLength) const override; + std::unique_ptr createHandleBusMessage(WebAudioPlayerContext &context, IGstWebAudioPlayerPrivate &player, + GstMessage *message) const override; + std::unique_ptr createPing(std::unique_ptr &&heartbeatHandler) const override; + +private: + IGstWebAudioPlayerClient *m_client; + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WriteBuffer.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WriteBuffer.h new file mode 100644 index 000000000..f8957250b --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WriteBuffer.h @@ -0,0 +1,50 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_WRITE_BUFFER_H_ +#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_WRITE_BUFFER_H_ + +#include "IGstWebAudioPlayerPrivate.h" +#include "IGstWrapper.h" +#include "IPlayerTask.h" +#include "MediaCommon.h" +#include "WebAudioPlayerContext.h" +#include + +namespace firebolt::rialto::server::tasks::webaudio +{ +class WriteBuffer : public IPlayerTask +{ +public: + WriteBuffer(WebAudioPlayerContext &context, std::shared_ptr gstWrapper, + uint8_t *mainPtr, uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength); + ~WriteBuffer() override; + void execute() const override; + +private: + WebAudioPlayerContext &m_context; + std::shared_ptr m_gstWrapper; + const uint8_t *m_mainPtr; + const uint64_t m_mainLength; + const uint8_t *m_wrapPtr; + const uint64_t m_wrapLength; +}; +} // namespace firebolt::rialto::server::tasks::webaudio + +#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_WRITE_BUFFER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstCapabilities.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstCapabilities.h new file mode 100644 index 000000000..1d0780ce6 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/interface/IGstCapabilities.h @@ -0,0 +1,105 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_CAPABILITIES_H_ + +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IGstCapabilities; + +/** + * @brief IGstCapabilities factory class, returns a concrete implementation of IGstCapabilities + */ +class IGstCapabilitiesFactory +{ +public: + IGstCapabilitiesFactory() = default; + virtual ~IGstCapabilitiesFactory() = default; + + /** + * @brief Gets the IGstCapabilitiesFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Creates a IGstCapabilities object. + * + * + * @retval the new gstreamer capabilities instance or null on error. + */ + virtual std::unique_ptr createGstCapabilities() = 0; +}; + +class IGstCapabilities +{ +public: + IGstCapabilities() = default; + virtual ~IGstCapabilities() = default; + + IGstCapabilities(const IGstCapabilities &) = delete; + IGstCapabilities &operator=(const IGstCapabilities &) = delete; + IGstCapabilities(IGstCapabilities &&) = delete; + IGstCapabilities &operator=(IGstCapabilities &&) = delete; + + /** + * @brief Gets vector of mime types supported by gstreamer + * + * @retval vector of mime types supported by gstreamer + */ + virtual std::vector getSupportedMimeTypes(MediaSourceType sourceType) = 0; + + /** + * @brief Checks is \a mimeType is supported by gstreamer + * + * @retval True if mime type is supported by gstreamer + */ + virtual bool isMimeTypeSupported(const std::string &mimeType) = 0; + + /** + * @brief Check sinks and decoders for supported properties + * + * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched + * @param[in] propertyNames : A vector of property names to look for + * + * @retval Returns the subset of propertyNames that are supported by the mediaType + */ + virtual std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) = 0; + + /** + * @brief Checks if the platform is video master. + * + * @param[out] isVideoMaster : The output value. True if video is master otherwise false. + * + * @retval true on success false otherwise + */ + virtual bool isVideoMaster(bool &isVideoMaster) = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayer.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayer.h new file mode 100644 index 000000000..74bc67919 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayer.h @@ -0,0 +1,460 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_H_ + +#include +#include +#include +#include + +#include "IDataReader.h" +#include "IDecryptionService.h" +#include "IGstGenericPlayerClient.h" +#include "IHeartbeatHandler.h" +#include "IMediaPipeline.h" +#include "IRdkGstreamerUtilsWrapper.h" + +namespace firebolt::rialto::server +{ +class IGstGenericPlayer; + +/** + * @brief IGstGenericPlayer factory class, returns a concrete implementation of IGstGenericPlayer + */ +class IGstGenericPlayerFactory +{ +public: + IGstGenericPlayerFactory() = default; + virtual ~IGstGenericPlayerFactory() = default; + + /** + * @brief Gets the IGstGenericPlayerFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Creates a IGstGenericPlayer object. + * + * @param[in] client : The gstreamer player client. + * @param[in] decryptionService : The decryption service. + * @param[in] type : The media type the gstreamer player shall support. + * @param[in] videoRequirements : The video requirements for the playback. + * + * @retval the new player instance or null on error. + */ + virtual std::unique_ptr + createGstGenericPlayer(IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, + const VideoRequirements &videoRequirements, + const std::shared_ptr + &rdkGstreamerUtilsWrapperFactory) = 0; +}; + +class IGstGenericPlayer +{ +public: + IGstGenericPlayer() = default; + virtual ~IGstGenericPlayer() = default; + + IGstGenericPlayer(const IGstGenericPlayer &) = delete; + IGstGenericPlayer &operator=(const IGstGenericPlayer &) = delete; + IGstGenericPlayer(IGstGenericPlayer &&) = delete; + IGstGenericPlayer &operator=(IGstGenericPlayer &&) = delete; + + /** + * @brief Attaches a source to gstreamer. + * + * @param[in] mediaSource : The media source. + * + */ + virtual void attachSource(const std::unique_ptr &mediaSource) = 0; + + /** + * @brief Unattaches a source. + * + * @param[in] mediaSourceType : The media source type. + * + */ + virtual void removeSource(const MediaSourceType &mediaSourceType) = 0; + + /** + * @brief Handles notification that all sources were attached + * + */ + virtual void allSourcesAttached() = 0; + + /** + * @brief Starts playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request playback and then return. + * + * Once the backend is successfully playing it should notify the + * media player client of playback state PlaybackState::PLAYING. + * + */ + virtual void play() = 0; + + /** + * @brief Pauses playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the playback pause and then return. + * + * Once the backend is successfully paused it should notify the + * media player client of playback state PlaybackState::PAUSED. + * + */ + virtual void pause() = 0; + + /** + * @brief Stops playback of the media. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the playback stop and then return. + * + * Once the backend is successfully stopped it should notify the + * media player client of playback state PlaybackState::STOPPED. + * + */ + virtual void stop() = 0; + + /** + * @brief Sets video geometry + * + * @param[in] x : X position of rectangle on video + * @param[in] y : Y position of rectangle on video + * @param[in] width : width of rectangle + * @param[in] height : height of rectangle + * + */ + virtual void setVideoGeometry(int x, int y, int width, int height) = 0; + + /** + * @brief Queues the end of stream notification at the end of the gstreamer buffers. + * + * @param[in] type : the media source type to set eos + * + */ + virtual void setEos(const firebolt::rialto::MediaSourceType &type) = 0; + + /** + * @brief Attaches new samples + * + * This method is considered to be asynchronous and MUST NOT block + * but should request to attach new sample and then return. + */ + virtual void attachSamples(const IMediaPipeline::MediaSegmentVector &mediaSegments) = 0; + + /** + * @brief Attaches new samples + * + * This method is considered to be asynchronous and MUST NOT block + * but should request to attach new sample and then return. + */ + virtual void attachSamples(const std::shared_ptr &dataReader) = 0; + + /** + * @brief Set the playback position in nanoseconds. + * + * If playback has not started this method sets the start position + * for playback. If playback has started this method performs a seek. + * + * @param[in] position : The playback position in nanoseconds. + * + */ + virtual void setPosition(std::int64_t position) = 0; + + /** + * @brief Get the playback position in nanoseconds. + * + * @param[out] position : The playback position in nanoseconds. + * + * @retval True on success + */ + virtual bool getPosition(std::int64_t &position) = 0; + + /** + * @brief Sets the "Immediate Output" property for this source. + * + * @param[in] mediaSourceType : The media source type + * @param[in] immediateOutput : Set immediate output mode on the sink + * + * @retval true on success. + */ + virtual bool setImmediateOutput(const MediaSourceType &mediaSourceType, bool immediateOutput) = 0; + + /** + * @brief Gets the "Immediate Output" property for this source. + * + * @param[in] mediaSourceType : The media source type + * @param[out] immediateOutput : Get immediate output mode on the sink + * + * @retval true on success. + */ + virtual bool getImmediateOutput(const MediaSourceType &mediaSourceType, bool &immediateOutput) = 0; + + /** + * @brief Get stats for this source. + * + * @param[in] mediaSourceType : The media source type to get stats for + * @param[out] renderedFrames : The number of rendered frames + * @param[out] droppedFrames : The number of dropped frames + * + * @retval true on success. + */ + virtual bool getStats(const MediaSourceType &mediaSourceType, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; + + /** + * @brief Set the playback rate. + * + * @param[in] rate : The playback rate. + * + */ + virtual void setPlaybackRate(double rate) = 0; + + /** + * @brief Requests to render a prerolled frame + * + */ + virtual void renderFrame() = 0; + + /** + * @brief Set level and transition of audio attenuation. + * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume) + * + * @param[in] volume : Target volume level (0.0 - 1.0) + */ + virtual void setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType) = 0; + + /** + * @brief Get current audio level. Fetches the current volume level for the pipeline. + * + * @param[out] volume : Current volume level (range 0.0 - 1.0) + * + * @retval True on success + */ + virtual bool getVolume(double &volume) = 0; + + /** + * @brief Set mute status of pipeline + * + * Muting does not change the underlying volyme setting so when + * unmuted the user will hear audio at the same volume as previously + * set. + * + * @param[in] mute : Desired mute state, true=muted, false=not muted + */ + virtual void setMute(const MediaSourceType &mediaSourceType, bool mute) = 0; + + /** + * @brief Get current mute status of the pipeline + * + * @param[out] mute : Current mute state + * + * @retval True in success, false otherwise + */ + virtual bool getMute(const MediaSourceType &mediaSourceType, bool &mute) = 0; + + /** + * @brief Change Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + virtual void setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; + + /** + * @brief Get Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; + + /** + * @brief Set low latency property on the pipeline. Default false. + * + * @param[in] lowLatency : The low latency value to set. + * + * @retval true on success false otherwise + */ + virtual bool setLowLatency(bool lowLatency) = 0; + + /** + * @brief Set sync property on the pipeline. Default false. + * + * @param[in] sync : The sync value to set. + * + * @retval true on success false otherwise + */ + virtual bool setSync(bool sync) = 0; + + /** + * @brief Get sync property on the pipeline. + * + * @param[out] sync : Current sync value. + * + * @retval true on success false otherwise + */ + virtual bool getSync(bool &sync) = 0; + + /** + * @brief Set sync off property on the pipeline. Default false. + * + * @param[in] syncOff : The sync off value to set. + * + * @retval true on success false otherwise + */ + virtual bool setSyncOff(bool syncOff) = 0; + + /** + * @brief Set stream sync mode property on the pipeline. Default 0. + * + * @param[in] mediaSourceType : The media source type to set stream sync mode. + * @param[in] streamSyncMode : The stream sync mode value to set. + * + * @retval true on success false otherwise + */ + virtual bool setStreamSyncMode(const MediaSourceType &mediaSourceType, int32_t streamSyncMode) = 0; + + /** + * @brief Get stream sync mode property on the pipeline. + * + * @param[out] streamSyncMode : Current stream sync mode value. + * + * @retval true on success false otherwise + */ + virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; + + /** + * @brief Checks if worker thread is not deadlocked + * + * @param[out] heartbeatHandler : The heartbeat handler instance + * + */ + virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; + + /** + * @brief Flushes a source. + * + * @param[in] mediaSourceType : The media source type to flush. + * @param[in] resetTime : True if time should be reset + * @param[out] async : True if flushed source is asynchronous (will preroll after flush) + * + */ + virtual void flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) = 0; + + /** + * @brief Set the source position in nanoseconds. + * + * This method sets the start position for a source. + * + * @param[in] mediaSourceType : The media source type to flush. + * @param[in] position : The position in nanoseconds. + * @param[in] resetTime : True if time should be reset + * @param[in] appliedRate : The applied rate after seek + * @param[in] stopPosition : The position of last pushed buffer + */ + virtual void setSourcePosition(const MediaSourceType &mediaSourceType, int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) = 0; + + /** + * @brief Sets the subtitle offset. + * + * This method sets the subtitle offset to synchronize subtitle timing. + * + * @param[in] position : The subtitle offset position in nanoseconds. + */ + virtual void setSubtitleOffset(int64_t position) = 0; + + /** + * @brief Process audio gap + * + * This method handles audio gap in order to avoid audio pops during transitions. + * + * @param[in] position : Audio pts fade position value + * @param[in] duration : Audio pts fade duration + * @param[in] discontinuityGap : Audio discontinuity gap + * @param[in] audioAac : True if audio codec is AAC + */ + virtual void processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; + + /** + * @brief Set buffering limit + * + * This method enables/disables limit buffering and sets millisecond threshold used. + * Use kInvalidLimitBuffering to disable limit buffering + * + * @param[in] limitBufferingMs : buffering limit in ms + * + */ + virtual void setBufferingLimit(uint32_t limitBufferingMs) = 0; + + /** + * @brief Get buffering limit + * + * This method returns current value of buffering limit in milliseconds + * Method will return kInvalidLimitBuffering limit buffering is disabled + * + * @param[out] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; + + /** + * @brief Enables/disables the buffering option + * + * This method enables the buffering option so that BUFFERING messages are + * emitted based on low-/high-percent thresholds. + * + * @param[in] useBuffering : true if buffering option enabled. + * + */ + virtual void setUseBuffering(bool useBuffering) = 0; + + /** + * @brief Checks, if buffering is enabled + * + * This method returns true, if buffering is enabled + * + * @param[out] useBuffering : true if buffering option is enabled. + * + * @retval true on success. + */ + virtual bool getUseBuffering(bool &useBuffering) = 0; + + /** + * @brief Switches a source. + * + * @param[in] mediaSource : The media source. + * + */ + virtual void switchSource(const std::unique_ptr &mediaSource) = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayerClient.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayerClient.h new file mode 100644 index 000000000..29925b5d8 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayerClient.h @@ -0,0 +1,175 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_CLIENT_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_CLIENT_H_ + +#include +#include +#include + +/** + * @file IGstGenericPlayerClient.h + * + * The definition of the IGstGenericPlayerClient interface. + * + * This file comprises the definition of the IGstGenericPlayerClient abstract + * class. This is the API by which a IGstGenericPlayer implementation will + * pass notifications to its client. + */ + +namespace firebolt::rialto::server +{ +/** + * @brief The Rialto gstreamer player client interface. + * + * This is The Rialto gstreamer player client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the + * state of the gstreamer player or that provides data for playback. + */ +class IGstGenericPlayerClient +{ +public: + IGstGenericPlayerClient() = default; + virtual ~IGstGenericPlayerClient() = default; + + IGstGenericPlayerClient(const IGstGenericPlayerClient &) = delete; + IGstGenericPlayerClient &operator=(const IGstGenericPlayerClient &) = delete; + IGstGenericPlayerClient(IGstGenericPlayerClient &&) = delete; + IGstGenericPlayerClient &operator=(IGstGenericPlayerClient &&) = delete; + + /** + * @brief Notifies the client of the playback state. + * + * The player will start IDLE. Once play() has been called the player + * will be PLAYING, or once pause() has been called the player will be + * PAUSED. A seek() request will result in SEEKING and once the seek + * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED + * state will be issued after a stop() request. + * + * @param[in] state : The new playback state. + */ + virtual void notifyPlaybackState(PlaybackState state) = 0; + + /** + * @brief Notifies the client that we need media data. + * + * This method notifies the client that we need media data from the + * client. This is only used when Media Source Extensions are used. + * In that case media is read by JavaScript and buffered by the + * browser before being passed to this API for decoding. + * + * You cannot request data if a data request is currently pending. + * + * The frames the client sends should meet the criteria: + * numFramesSent <= frameCount + * numBytesSent <= maxBytes + * + * @param[in] mediaSourceType : The media type of source to read data from. + * + * @retval True on success. + */ + virtual bool notifyNeedMediaData(MediaSourceType mediaSourceType) = 0; + + /** + * @brief Notifies the client of the current playback position. + * + * This method notifies the client of the current playback position + * in nanoseconds. + * + * When playing this should be called often enough to provide + * sufficient granularity of position reporting. Typically this will + * be every 0.25s. + * + * @param[in] position : The playback position in nanoseconds. + * + */ + virtual void notifyPosition(std::int64_t position) = 0; + + /** + * @brief Notifies the client of the network state. + * + * The network state reflects the state of the network. For backend + * streaming, say using MediaPipelineURLDelegate, this is important + * as the backend uses the network to obtain the media data directly. + * + * For streaming that uses the browser to obtain data, say Media Source + * Extensions playback, only the states NetworkState::IDLE, + * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be + * indicated by the backend. + * + * @param[in] state : The new network state. + * + */ + virtual void notifyNetworkState(NetworkState state) = 0; + + /** + * @brief Clears all active NeedMediaDataRequests cache for session + * + */ + virtual void clearActiveRequestsCache() = 0; + + /** + * @brief Clears all active NeedMediaDataRequests cache for given Media Source Type + * + * @param[in] type : Media source type. + * + */ + virtual void invalidateActiveRequests(const MediaSourceType &type) = 0; + + /** + * @brief Notifies the client of a Quality Of Service update from the Player. + * + * @param[in] qosInfo : The Qos infomation extracted from the message. + * @param[in] sourceType : The type of source that sent the message. + */ + virtual void notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo) = 0; + + /** + * @brief Notifies the client that buffer underflow occurred. + * + * Notification shall be sent whenever a video/audio buffer underflow occurs + * + * @param[in] mediaSourceType : The type of the source that produced the buffer underflow + */ + virtual void notifyBufferUnderflow(MediaSourceType mediaSourceType) = 0; + + /** + * @brief Notifies the client that a non-fatal error has occurred in the player. + * + * PlaybackState remains unchanged when an error occurs. + * + * @param[in] mediaSourceType : The type of the source that produced the error. + * @param[in] error : The type of error that occurred. + */ + virtual void notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error) = 0; + + /** + * @brief Notifies the client that the source has been flushed. + * + * Notification shall be sent whenever a flush procedure is finished. + * + * @param[in] mediaSourceType : The type of the source that has been flushed. + */ + virtual void notifySourceFlushed(MediaSourceType mediaSourceType) = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstInitialiser.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstInitialiser.h new file mode 100644 index 000000000..75972ed10 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/interface/IGstInitialiser.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_INITIALISER_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_INITIALISER_H_ + +namespace firebolt::rialto::server +{ +class IGstInitialiser +{ +protected: + IGstInitialiser() = default; + virtual ~IGstInitialiser() = default; + IGstInitialiser(const IGstInitialiser &) = delete; + IGstInitialiser(IGstInitialiser &&) = delete; + IGstInitialiser &operator=(const IGstInitialiser &) = delete; + IGstInitialiser &operator=(IGstInitialiser &&) = delete; + +public: + static IGstInitialiser &instance(); + virtual void initialise(int *argc, char ***argv) = 0; + virtual void waitForInitialisation() const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_INITIALISER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayer.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayer.h new file mode 100644 index 000000000..f72ca12c3 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayer.h @@ -0,0 +1,154 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_H_ + +#include "IGstWebAudioPlayerClient.h" +#include "IHeartbeatHandler.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IGstWebAudioPlayer; + +/** + * @brief IGstWebAudioPlayer factory class, returns a concrete implementation of IGstWebAudioPlayer + */ +class IGstWebAudioPlayerFactory +{ +public: + IGstWebAudioPlayerFactory() = default; + virtual ~IGstWebAudioPlayerFactory() = default; + + /** + * @brief Gets the IGstWebAudioPlayerFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr getFactory(); + + /** + * @brief Creates a IGstWebAudioPlayer object. + * + * @param[in] client : The gstreamer web audio player client. + * @param[in] priority : Priority value for this pipeline. + * + * @retval the new player instance or null on error. + */ + virtual std::unique_ptr createGstWebAudioPlayer(IGstWebAudioPlayerClient *client, + const uint32_t priority) = 0; +}; + +class IGstWebAudioPlayer +{ +public: + IGstWebAudioPlayer() = default; + virtual ~IGstWebAudioPlayer() = default; + + IGstWebAudioPlayer(const IGstWebAudioPlayer &) = delete; + IGstWebAudioPlayer &operator=(const IGstWebAudioPlayer &) = delete; + IGstWebAudioPlayer(IGstWebAudioPlayer &&) = delete; + IGstWebAudioPlayer &operator=(IGstWebAudioPlayer &&) = delete; + + /** + * @brief Sets the capabilities on the audio source. + * + * @param[in] audioMimeType: The audio encoding format, currently only "audio/x-raw" (PCM). + * @param[in] config: Additional type dependent configuration data or nullptr, + */ + virtual void setCaps(const std::string &audioMimeType, std::weak_ptr config) = 0; + + /** + * @brief Starts playback of the web audio. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request playback and then return. + * + * Once the backend is successfully playing it should notify the + * web audio player client of state WebAudioPlayerState::PLAYING. + */ + virtual void play() = 0; + + /** + * @brief Pauses playback of the web audio. + * + * This method is considered to be asynchronous and MUST NOT block + * but should request the playback pause and then return. + * + * Once the backend is successfully paused it should notify the + * web audio player client of state WebAudioPlayerState::PAUSED. + */ + virtual void pause() = 0; + + /** + * @brief Set level and transition of audio attenuation. + * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume). + * + * @param[in] volume : Target volume level (0.0 - 1.0) + */ + virtual void setVolume(double volume) = 0; + + /** + * @brief Get current audio level. Fetches the current volume level for the pipeline. + * + * @param[out] volume : Current volume level (range 0.0 - 1.0) + * + * @retval True on success. + */ + virtual bool getVolume(double &volume) = 0; + + /** + * @brief Write the buffer to gstreamer buffer. + * + * @param[in] mainPtr : Pointer to the start of the data. + * @param[in] mainLength : Amount of bytes to write from the mainPtr. + * @param[in] wrapPtr : Pointer to the start of the wrapped data. + * @param[in] wrapLength : Amount of bytes to write from the wrapPtr. + * + * @retval The number of bytes written to gstreamer. + */ + virtual uint32_t writeBuffer(uint8_t *mainPtr, uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength) = 0; + + /** + * @brief Notify EOS at the end of the gstreamer buffers. + */ + virtual void setEos() = 0; + + /** + * @brief Gets the amount of bytes queued for playback on the app source. + * + * @retval The number of bytes queued. + */ + virtual uint64_t getQueuedBytes() = 0; + + /** + * @brief Checks if worker thread is not deadlocked + * + * @param[out] heartbeatHandler : The heartbeat handler instance + * + */ + virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayerClient.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayerClient.h new file mode 100644 index 000000000..7c505fd08 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayerClient.h @@ -0,0 +1,70 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_CLIENT_H_ +#define FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_CLIENT_H_ + +#include +#include + +/** + * @file IGstWebAudioPlayerClient.h + * + * The definition of the IGstWebAudioPlayerClient interface. + * + * This file comprises the definition of the IGstWebAudioPlayerClient abstract + * class. This is the API by which a IGstWebAudioPlayer implementation will + * pass notifications to its client. + */ + +namespace firebolt::rialto::server +{ +/** + * @brief The Rialto gstreamer player client interface. + * + * This is The Rialto gstreamer player client abstract base class. It should be + * implemented by any object that wishes to be notified by changes in the + * state of the gstreamer player or that provides data for playback. + */ +class IGstWebAudioPlayerClient +{ +public: + IGstWebAudioPlayerClient() = default; + virtual ~IGstWebAudioPlayerClient() = default; + + IGstWebAudioPlayerClient(const IGstWebAudioPlayerClient &) = delete; + IGstWebAudioPlayerClient &operator=(const IGstWebAudioPlayerClient &) = delete; + IGstWebAudioPlayerClient(IGstWebAudioPlayerClient &&) = delete; + IGstWebAudioPlayerClient &operator=(IGstWebAudioPlayerClient &&) = delete; + + /** + * @brief Notifies the client of the web audio state. + * + * The player will start IDLE. Once play() has been called the player + * will be PLAYING, or once pause() has been called the player will be + * PAUSED. Once the stream has reached end of the media EOS wibe notified. + * + * @param[in] state : The new web audio state. + */ + virtual void notifyState(WebAudioPlayerState state) = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/source/CapsBuilder.cpp b/middleware/rialto-client/media/server/gstplayer/source/CapsBuilder.cpp new file mode 100644 index 000000000..55713943a --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/CapsBuilder.cpp @@ -0,0 +1,262 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "CapsBuilder.h" +#include "GstMimeMapping.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server +{ +MediaSourceCapsBuilder::MediaSourceCapsBuilder(std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const firebolt::rialto::IMediaPipeline::MediaSourceAV &source) + : m_gstWrapper(gstWrapper), m_glibWrapper(glibWrapper), m_attachedSource(source) +{ +} +GstCaps *MediaSourceCapsBuilder::buildCaps() +{ + return buildCommonCaps(); +} + +GstCaps *MediaSourceCapsBuilder::buildCommonCaps() +{ + GstCaps *caps = firebolt::rialto::server::createSimpleCapsFromMimeType(m_gstWrapper, m_attachedSource); + + addAlignmentToCaps(caps); + addCodecDataToCaps(caps); + addStreamFormatToCaps(caps); + + return caps; +} + +void MediaSourceCapsBuilder::addAlignmentToCaps(GstCaps *caps) const +{ + static const std::unordered_map aligmentMap = + {{firebolt::rialto::SegmentAlignment::AU, "au"}, {firebolt::rialto::SegmentAlignment::NAL, "nal"}}; + + auto aligmentMapIt = aligmentMap.find(m_attachedSource.getSegmentAlignment()); + if (aligmentMapIt != aligmentMap.end()) + { + m_gstWrapper->gstCapsSetSimple(caps, "alignment", G_TYPE_STRING, aligmentMapIt->second.c_str(), nullptr); + } +} + +void MediaSourceCapsBuilder::addCodecDataToCaps(GstCaps *caps) const +{ + const std::shared_ptr &kCodecData = m_attachedSource.getCodecData(); + if (kCodecData && CodecDataType::BUFFER == kCodecData->type) + { + gpointer memory = m_glibWrapper->gMemdup(kCodecData->data.data(), kCodecData->data.size()); + GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, kCodecData->data.size()); + m_gstWrapper->gstCapsSetSimple(caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr); + m_gstWrapper->gstBufferUnref(buf); + } + else if (kCodecData && CodecDataType::STRING == kCodecData->type) + { + std::string codecDataStr{kCodecData->data.begin(), kCodecData->data.end()}; + m_gstWrapper->gstCapsSetSimple(caps, "codec_data", G_TYPE_STRING, codecDataStr.c_str(), nullptr); + } +} + +void MediaSourceCapsBuilder::addStreamFormatToCaps(GstCaps *caps) const +{ + static const std::unordered_map formatMap = + {{firebolt::rialto::StreamFormat::RAW, "raw"}, + {firebolt::rialto::StreamFormat::AVC, "avc"}, + {firebolt::rialto::StreamFormat::BYTE_STREAM, "byte-stream"}, + {firebolt::rialto::StreamFormat::HVC1, "hvc1"}, + {firebolt::rialto::StreamFormat::HEV1, "hev1"}}; + + auto formatMapIt = formatMap.find(m_attachedSource.getStreamFormat()); + if (formatMapIt != formatMap.end()) + { + m_gstWrapper->gstCapsSetSimple(caps, "stream-format", G_TYPE_STRING, formatMapIt->second.c_str(), nullptr); + } +} + +MediaSourceAudioCapsBuilder::MediaSourceAudioCapsBuilder( + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, const IMediaPipeline::MediaSourceAudio &source) + : MediaSourceCapsBuilder(gstWrapper, glibWrapper, source), m_attachedAudioSource(source) +{ +} + +GstCaps *MediaSourceAudioCapsBuilder::buildCaps() +{ + std::string mimeType = m_attachedSource.getMimeType(); + if (mimeType == "audio/x-opus") + { + return createOpusCaps(); + } + + GstCaps *caps = MediaSourceCapsBuilder::buildCaps(); + if (mimeType == "audio/mp4" || mimeType == "audio/aac") + { + addMpegVersion4ToCaps(caps); + } + else if (mimeType == "audio/mp3") + { + addMp3Caps(caps); + } + else if (mimeType == "audio/b-wav" || mimeType == "audio/x-raw") + { + addRawAudioData(caps); + } + else if (mimeType == "audio/x-flac") + { + addFlacSpecificData(caps); + } + addSampleRateAndChannelsToCaps(caps); + + return caps; +} + +GstCaps *MediaSourceAudioCapsBuilder::createOpusCaps() +{ + GstCaps *caps = getAudioSpecificConfiguration(); + if (!caps) + { + caps = m_gstWrapper->gstCapsNewSimple("audio/x-opus", "channel-mapping-family", G_TYPE_INT, 0, nullptr); + addSampleRateAndChannelsToCaps(caps); + } + + return caps; +} + +GstCaps *MediaSourceAudioCapsBuilder::getAudioSpecificConfiguration() const +{ + GstCaps *caps = nullptr; + firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); + if (audioConfig.codecSpecificConfig.size()) + { + gsize codec_priv_size = audioConfig.codecSpecificConfig.size(); + gconstpointer codec_priv = audioConfig.codecSpecificConfig.data(); + + caps = m_gstWrapper->gstCodecUtilsOpusCreateCapsFromHeader(codec_priv, codec_priv_size); + if (!caps) + { + RIALTO_SERVER_LOG_ERROR("Failed to parse opus header"); + } + } + + return caps; +} + +void MediaSourceAudioCapsBuilder::addSampleRateAndChannelsToCaps(GstCaps *caps) const +{ + firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); + + if (audioConfig.numberOfChannels != firebolt::rialto::kInvalidAudioChannels) + m_gstWrapper->gstCapsSetSimple(caps, "channels", G_TYPE_INT, audioConfig.numberOfChannels, nullptr); + + if (audioConfig.sampleRate != firebolt::rialto::kInvalidAudioSampleRate) + m_gstWrapper->gstCapsSetSimple(caps, "rate", G_TYPE_INT, audioConfig.sampleRate, nullptr); +} + +void MediaSourceAudioCapsBuilder::addMpegVersion4ToCaps(GstCaps *caps) const +{ + m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 4, nullptr); +} + +void MediaSourceAudioCapsBuilder::addMp3Caps(GstCaps *caps) const +{ + m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 1, nullptr); + m_gstWrapper->gstCapsSetSimple(caps, "layer", G_TYPE_INT, 3, nullptr); +} + +void MediaSourceAudioCapsBuilder::addRawAudioData(GstCaps *caps) const +{ + firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); + if (audioConfig.format.has_value()) + m_gstWrapper->gstCapsSetSimple(caps, "format", G_TYPE_STRING, common::convertFormat(audioConfig.format.value()), + nullptr); + if (audioConfig.layout.has_value()) + m_gstWrapper->gstCapsSetSimple(caps, "layout", G_TYPE_STRING, common::convertLayout(audioConfig.layout.value()), + nullptr); + if (audioConfig.channelMask.has_value()) + m_gstWrapper->gstCapsSetSimple(caps, "channel-mask", GST_TYPE_BITMASK, audioConfig.channelMask.value(), nullptr); +} + +void MediaSourceAudioCapsBuilder::addFlacSpecificData(GstCaps *caps) const +{ + firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); + if (audioConfig.streamHeader.size()) + { + GValue streamHeaderArray = G_VALUE_INIT; + m_glibWrapper->gValueInit(&streamHeaderArray, GST_TYPE_ARRAY); + for (const auto &header : audioConfig.streamHeader) + { + gpointer memory = m_glibWrapper->gMemdup(header.data(), header.size()); + GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, header.size()); + GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_HEADER); + + GValue value = G_VALUE_INIT; + m_glibWrapper->gValueInit(&value, GST_TYPE_BUFFER); + m_gstWrapper->gstValueSetBuffer(&value, buf); + m_gstWrapper->gstValueArrayAppendValue(&streamHeaderArray, &value); + + m_glibWrapper->gValueUnset(&value); + m_gstWrapper->gstBufferUnref(buf); + } + m_gstWrapper->gstStructureSetValue(m_gstWrapper->gstCapsGetStructure(caps, 0), "streamheader", + &streamHeaderArray); + m_glibWrapper->gValueUnset(&streamHeaderArray); + } + if (audioConfig.framed.has_value()) + { + m_gstWrapper->gstCapsSetSimple(caps, "framed", G_TYPE_BOOLEAN, audioConfig.framed.value(), nullptr); + } +} + +MediaSourceVideoCapsBuilder::MediaSourceVideoCapsBuilder( + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, const IMediaPipeline::MediaSourceVideo &source) + : MediaSourceCapsBuilder(gstWrapper, glibWrapper, source), m_attachedVideoSource(source) +{ +} + +GstCaps *MediaSourceVideoCapsBuilder::buildCaps() +{ + GstCaps *caps = MediaSourceCapsBuilder::buildCaps(); + if (m_attachedVideoSource.getWidth() != firebolt::rialto::kUndefinedSize) + m_gstWrapper->gstCapsSetSimple(caps, "width", G_TYPE_INT, m_attachedVideoSource.getWidth(), nullptr); + if (m_attachedVideoSource.getHeight() != firebolt::rialto::kUndefinedSize) + m_gstWrapper->gstCapsSetSimple(caps, "height", G_TYPE_INT, m_attachedVideoSource.getHeight(), nullptr); + + return caps; +} + +MediaSourceVideoDolbyVisionCapsBuilder::MediaSourceVideoDolbyVisionCapsBuilder( + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const IMediaPipeline::MediaSourceVideoDolbyVision &source) + : MediaSourceVideoCapsBuilder(gstWrapper, glibWrapper, source), m_attachedDolbySource(source) +{ +} + +GstCaps *MediaSourceVideoDolbyVisionCapsBuilder::buildCaps() +{ + GstCaps *caps = MediaSourceVideoCapsBuilder::buildCaps(); + m_gstWrapper->gstCapsSetSimple(caps, "dovi-stream", G_TYPE_BOOLEAN, true, nullptr); + m_gstWrapper->gstCapsSetSimple(caps, "dv_profile", G_TYPE_UINT, m_attachedDolbySource.getDolbyVisionProfile(), + nullptr); + return caps; +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/FlushWatcher.cpp b/middleware/rialto-client/media/server/gstplayer/source/FlushWatcher.cpp new file mode 100644 index 000000000..b1c63d686 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/FlushWatcher.cpp @@ -0,0 +1,52 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "FlushWatcher.h" +#include + +namespace firebolt::rialto::server +{ +void FlushWatcher::setFlushing(const MediaSourceType &type, bool async) +{ + std::unique_lock lock{m_mutex}; + if (MediaSourceType::UNKNOWN != type) + { + m_flushingSources[type] = async; + } +} + +void FlushWatcher::setFlushed(const MediaSourceType &type) +{ + std::unique_lock lock{m_mutex}; + m_flushingSources.erase(type); +} + +bool FlushWatcher::isFlushOngoing() const +{ + std::unique_lock lock{m_mutex}; + return !m_flushingSources.empty(); +} + +bool FlushWatcher::isAsyncFlushOngoing() const +{ + std::unique_lock lock{m_mutex}; + return !m_flushingSources.empty() && std::any_of(m_flushingSources.begin(), m_flushingSources.end(), + [](const auto &source) { return source.second; }); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstCapabilities.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstCapabilities.cpp new file mode 100644 index 000000000..d5d0a33ed --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstCapabilities.cpp @@ -0,0 +1,464 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "GstCapabilities.h" +#include "GstMimeMapping.h" +#include "RialtoServerLogging.h" + +namespace +{ +const char *toString(const GstElementFactoryListType &listType) +{ + switch (listType) + { + case GST_ELEMENT_FACTORY_TYPE_ANY: + return "Any"; + case GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS: + return "AudioVideo Sinks"; + case GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER: + return "Audio Encoder"; + case GST_ELEMENT_FACTORY_TYPE_DECODABLE: + return "Decodable"; + case GST_ELEMENT_FACTORY_TYPE_DECODER: + return "Decoder"; + case GST_ELEMENT_FACTORY_TYPE_DECRYPTOR: + return "Decryptor"; + case GST_ELEMENT_FACTORY_TYPE_DEMUXER: + return "Demuxer"; + case GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER: + return "Depayloader"; + case GST_ELEMENT_FACTORY_TYPE_ENCODER: + return "Encoder"; + case GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR: + return "Encryptor"; + case GST_ELEMENT_FACTORY_TYPE_FORMATTER: + return "Formatter"; + case GST_ELEMENT_FACTORY_TYPE_HARDWARE: + return "Hardware"; + case GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS: + return "Max Elements"; + case GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY: + return "Media Any"; + case GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO: + return "Media Audio"; + case GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE: + return "Media Image"; + case GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA: + return "Media Metadata"; + case GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE: + return "Media Subtitle"; + case GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO: + return "Media Video"; + case GST_ELEMENT_FACTORY_TYPE_MUXER: + return "Muxer"; + case GST_ELEMENT_FACTORY_TYPE_PARSER: + return "Parser"; + case GST_ELEMENT_FACTORY_TYPE_PAYLOADER: + return "Payloader"; + case GST_ELEMENT_FACTORY_TYPE_SINK: + return "Sink"; + case GST_ELEMENT_FACTORY_TYPE_SRC: + return "Source"; + case GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER: + return "Video Encoder"; + default: + return "Unknown"; + } +} +} // namespace + +namespace firebolt::rialto::server +{ +std::weak_ptr GstCapabilitiesFactory::m_factory; + +std::shared_ptr IGstCapabilitiesFactory::getFactory() +{ + std::shared_ptr factory = GstCapabilitiesFactory::m_factory.lock(); + + if (!factory) + { + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer capabilities factory, reason: %s", e.what()); + } + + GstCapabilitiesFactory::m_factory = factory; + } + + return factory; +} + +std::unique_ptr GstCapabilitiesFactory::createGstCapabilities() +{ + std::unique_ptr gstCapabilities; + try + { + std::shared_ptr gstWrapperFactory = + firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); + std::shared_ptr gstWrapper; + + if ((!gstWrapperFactory) || (!(gstWrapper = gstWrapperFactory->getGstWrapper()))) + { + throw std::runtime_error("Cannot create GstWrapper"); + } + + std::shared_ptr glibWrapperFactory = + firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(); + std::shared_ptr glibWrapper; + + if ((!glibWrapperFactory) || (!(glibWrapper = glibWrapperFactory->getGlibWrapper()))) + { + throw std::runtime_error("Cannot create GlibWrapper"); + } + + std::shared_ptr rdkGstreamerUtilsWrapperFactory = + firebolt::rialto::wrappers::IRdkGstreamerUtilsWrapperFactory::getFactory(); + std::shared_ptr rdkGstreamerUtilsWrapper; + + if ((!rdkGstreamerUtilsWrapperFactory) || + (!(rdkGstreamerUtilsWrapper = rdkGstreamerUtilsWrapperFactory->createRdkGstreamerUtilsWrapper()))) + { + throw std::runtime_error("Cannot create RdkGstreamerUtilsWrapper"); + } + + gstCapabilities = std::make_unique(gstWrapper, glibWrapper, rdkGstreamerUtilsWrapper, + IGstInitialiser::instance()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer capabilities, reason: %s", e.what()); + } + + return gstCapabilities; +} + +GstCapabilities::GstCapabilities( + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr &rdkGstreamerUtilsWrapper, + const IGstInitialiser &gstInitialiser) + : m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, + m_gstInitialiser{gstInitialiser} +{ + m_initialisationThread = std::thread( + [this]() + { + std::unique_lock lock{m_initialisationMutex}; + + m_gstInitialiser.waitForInitialisation(); + fillSupportedMimeTypes(); + m_isInitialised = true; + m_initialisationCv.notify_all(); + }); +} + +GstCapabilities::~GstCapabilities() +{ + if (m_initialisationThread.joinable()) + { + m_initialisationThread.join(); + } +} + +std::vector GstCapabilities::getSupportedMimeTypes(MediaSourceType sourceType) +{ + waitForInitialisation(); + + std::vector supportedMimeTypesSource; + std::string type; + if (sourceType == MediaSourceType::VIDEO) + { + type = "video/"; + } + else if (sourceType == MediaSourceType::AUDIO) + { + type = "audio/"; + } + else if (sourceType == MediaSourceType::SUBTITLE) + { + return {"text/vtt", "text/ttml", "text/cc"}; + } + else + { + RIALTO_SERVER_LOG_WARN("Unsupported media type"); + return {}; + } + + std::copy_if(m_supportedMimeTypes.begin(), m_supportedMimeTypes.end(), std::back_inserter(supportedMimeTypesSource), + [&type](const std::string &supportedMimeType) { return supportedMimeType.find(type) == 0; }); + + return supportedMimeTypesSource; +} + +bool GstCapabilities::isMimeTypeSupported(const std::string &mimeType) +{ + waitForInitialisation(); + return m_supportedMimeTypes.find(mimeType) != m_supportedMimeTypes.end(); +} + +std::vector GstCapabilities::getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) +{ + waitForInitialisation(); + + // Get gstreamer element factories. The following flag settings will fetch both SINK and DECODER types + // of gstreamer classes... + GstElementFactoryListType factoryListType{GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_DECODER | + GST_ELEMENT_FACTORY_TYPE_PARSER}; + { + // If MediaSourceType::AUDIO is specified then adjust the flag so that we + // restrict the list to gstreamer AUDIO element types (and likewise for video and subtitle)... + static const std::unordered_map + kLookupExtraConditions{{MediaSourceType::AUDIO, GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO}, + {MediaSourceType::VIDEO, GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO}, + {MediaSourceType::SUBTITLE, GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE}}; + auto i = kLookupExtraConditions.find(mediaType); + if (i != kLookupExtraConditions.end()) + factoryListType |= i->second; + } + + GList *factories{m_gstWrapper->gstElementFactoryListGetElements(factoryListType, GST_RANK_NONE)}; + + // Scan all returned elements for the specified properties... + std::unordered_set propertiesToLookFor{propertyNames.begin(), propertyNames.end()}; + std::vector propertiesFound; + for (GList *iter = factories; iter != nullptr && !propertiesToLookFor.empty(); iter = iter->next) + { + GstElementFactory *factory = GST_ELEMENT_FACTORY(iter->data); + + // WORKAROUND: initialising element "rtkv1sink" causes that another playback's video goes black + // we don't need to scan this element, so ignore it + if (std::string{GST_OBJECT_NAME(GST_OBJECT(factory))} == "rtkv1sink") + { + RIALTO_SERVER_LOG_DEBUG("Ignoring rtkv1sink element"); + continue; + } + + GstElement *elementObj{nullptr}; + + // We instantiate an object because fetching the class, even after gstPluginFeatureLoad, + // was found to sometimes return a class with no properties. A code branch is + // kept with this feature "supportedPropertiesViaClass" + elementObj = m_gstWrapper->gstElementFactoryCreate(factory, nullptr); + if (elementObj) + { + GParamSpec **props; + guint nProps; + props = m_glibWrapper->gObjectClassListProperties(G_OBJECT_GET_CLASS(elementObj), &nProps); + if (props) + { + for (guint j = 0; j < nProps && !propertiesToLookFor.empty(); ++j) + { + const std::string kPropName{props[j]->name}; + auto it = propertiesToLookFor.find(kPropName); + if (it != propertiesToLookFor.end()) + { + RIALTO_SERVER_LOG_DEBUG("Found property '%s'", kPropName.c_str()); + propertiesFound.push_back(kPropName); + propertiesToLookFor.erase(it); + } + } + m_glibWrapper->gFree(props); + } + m_gstWrapper->gstObjectUnref(elementObj); + } + } + + // Some sinks do not specifically support the "audio-fade" property, but the mechanism is supported through the use + // of the rdk_gstreamer_utils library. Check for audio fade support if the property is required and we haven't found it in the sinks. + if (propertiesToLookFor.find("audio-fade") != propertiesToLookFor.end()) + { + bool socAudioFadeSupported = m_rdkGstreamerUtilsWrapper->isSocAudioFadeSupported(); + if (socAudioFadeSupported) + { + RIALTO_SERVER_LOG_DEBUG("Audio fade property is supported by the SoC"); + propertiesFound.push_back("audio-fade"); // Add "audio-fade" if supported by SoC + } + } + // Cleanup + m_gstWrapper->gstPluginFeatureListFree(factories); + return propertiesFound; +} + +void GstCapabilities::fillSupportedMimeTypes() +{ + std::vector supportedCaps; + appendSupportedCapsFromFactoryType(GST_ELEMENT_FACTORY_TYPE_DECODER, supportedCaps); + + // Only append caps from decoder parser if they can link with the decoder + appendLinkableCapsFromParserDecoderChains(supportedCaps); + + // Sink caps do not require decoder support + appendSupportedCapsFromFactoryType(GST_ELEMENT_FACTORY_TYPE_SINK, supportedCaps); + + if (supportedCaps.empty()) + { + RIALTO_SERVER_LOG_WARN("There are no supported caps"); + return; + } + + m_supportedMimeTypes = firebolt::rialto::server::convertFromCapsVectorToMimeSet(supportedCaps, m_gstWrapper); + + for (GstCaps *caps : supportedCaps) + { + m_gstWrapper->gstCapsUnref(caps); + } +} + +void GstCapabilities::appendLinkableCapsFromParserDecoderChains(std::vector &supportedCaps) +{ + if (supportedCaps.empty()) + { + return; + } + + std::vector decoderSupportedCaps = supportedCaps; + + GList *parserFactories = + m_gstWrapper->gstElementFactoryListGetElements(GST_ELEMENT_FACTORY_TYPE_PARSER, GST_RANK_MARGINAL); + if (!parserFactories) + { + RIALTO_SERVER_LOG_WARN("Could not find any parser"); + return; + } + + for (GstCaps *decoderCaps : decoderSupportedCaps) + { + for (GList *factoriesIter = parserFactories; factoriesIter; factoriesIter = factoriesIter->next) + { + GstElementFactory *factory = static_cast(factoriesIter->data); + const GList *kParserPadTemplates = m_gstWrapper->gstElementFactoryGetStaticPadTemplates(factory); + + if (canCreateParserDecoderChain(decoderCaps, kParserPadTemplates)) + { + addAllUniqueSinkPadsCapsToVector(supportedCaps, kParserPadTemplates); + } + } + } + + m_gstWrapper->gstPluginFeatureListFree(parserFactories); +} + +void GstCapabilities::appendSupportedCapsFromFactoryType(const GstElementFactoryListType &type, + std::vector &supportedCaps) +{ + GList *factories = m_gstWrapper->gstElementFactoryListGetElements(type, GST_RANK_MARGINAL); + if (!factories) + { + RIALTO_SERVER_LOG_WARN("Could not find any %s", toString(type)); + return; + } + + for (GList *factoriesIter = factories; factoriesIter; factoriesIter = factoriesIter->next) + { + GstElementFactory *factory = static_cast(factoriesIter->data); + const GList *kPadTemplates = m_gstWrapper->gstElementFactoryGetStaticPadTemplates(factory); + + addAllUniqueSinkPadsCapsToVector(supportedCaps, kPadTemplates); + } + + m_gstWrapper->gstPluginFeatureListFree(factories); +} + +bool GstCapabilities::canCreateParserDecoderChain(GstCaps *decoderCaps, const GList *kParserPadTemplates) +{ + for (const GList *padTemplateIter = kParserPadTemplates; padTemplateIter; padTemplateIter = padTemplateIter->next) + { + GstStaticPadTemplate *padTemplate = static_cast(padTemplateIter->data); + if (padTemplate->direction == GST_PAD_SRC) + { + GstCaps *padTemplateCaps = m_gstWrapper->gstStaticCapsGet(&padTemplate->static_caps); + + // check if parser's src pad can be connected to decoder's sink pad + bool canIntersect = m_gstWrapper->gstCapsCanIntersect(decoderCaps, padTemplateCaps); + m_gstWrapper->gstCapsUnref(padTemplateCaps); + if (canIntersect) + { + return true; + } + } + } + + return false; +} + +void GstCapabilities::addAllUniqueSinkPadsCapsToVector(std::vector &capsVector, const GList *padTemplates) +{ + for (const GList *padTemplateIter = padTemplates; padTemplateIter; padTemplateIter = padTemplateIter->next) + { + GstStaticPadTemplate *padTemplate = static_cast(padTemplateIter->data); + if (padTemplate->direction == GST_PAD_SINK) + { + GstCaps *padTemplateCaps = m_gstWrapper->gstStaticCapsGet(&padTemplate->static_caps); + if (!isCapsInVector(capsVector, padTemplateCaps)) + { + capsVector.push_back(padTemplateCaps); + } + else + { + m_gstWrapper->gstCapsUnref(padTemplateCaps); + } + } + } +} + +bool GstCapabilities::isCapsInVector(const std::vector &capsVector, GstCaps *caps) const +{ + return std::find_if(capsVector.begin(), capsVector.end(), [&](const GstCaps *comparedCaps) + { return m_gstWrapper->gstCapsIsStrictlyEqual(caps, comparedCaps); }) != capsVector.end(); +} + +void GstCapabilities::waitForInitialisation() +{ + std::unique_lock lock{m_initialisationMutex}; + m_initialisationCv.wait(lock, [this]() { return m_isInitialised; }); +} + +bool GstCapabilities::isVideoMaster(bool &isVideoMaster) +{ + waitForInitialisation(); + + GstRegistry *reg = m_gstWrapper->gstRegistryGet(); + if (!reg) + { + RIALTO_SERVER_LOG_ERROR("Failed get the gst registry"); + return false; + } + GstPluginFeature *feature{nullptr}; + isVideoMaster = true; + if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "amlhalasink"))) + { + isVideoMaster = false; + m_gstWrapper->gstObjectUnref(feature); + } + return true; +} + +} // namespace firebolt::rialto::server + +// namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstDecryptor.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstDecryptor.cpp new file mode 100644 index 000000000..33206d494 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstDecryptor.cpp @@ -0,0 +1,372 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GstDecryptorElementFactory.h" +#include "GstDecryptorPrivate.h" +#include "GstProtectionMetadataHelperFactory.h" +#include "RialtoServerLogging.h" +#include + +#include +#include + +G_BEGIN_DECLS + +#define GST_RIALTO_DECRYPTOR_TYPE (gst_rialto_decryptor_get_type()) +#define GST_RIALTO_DECRYPTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_RIALTO_DECRYPTOR_TYPE, GstRialtoDecryptor)) +#define GST_RIALTO_DECRYPTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_RIALTO_DECRYPTOR_TYPE, GstRialtoDecryptorClass)) + +typedef struct _GstRialtoDecryptor GstRialtoDecryptor; +typedef struct _GstRialtoDecryptorClass GstRialtoDecryptorClass; +typedef struct firebolt::rialto::server::GstRialtoDecryptorPrivate GstRialtoDecryptorPrivate; + +GType gst_rialto_decryptor_get_type(void); // NOLINT(build/function_format) + +struct _GstRialtoDecryptor +{ + GstBaseTransform parent; + GstRialtoDecryptorPrivate *priv; +}; + +struct _GstRialtoDecryptorClass +{ + GstBaseTransformClass parentClass; +}; + +G_END_DECLS + +static GstStaticPadTemplate sinkTemplate = + GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate srcTemplate = + GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY(gst_rialto_decryptor_debug_category); +#define GST_CAT_DEFAULT gst_rialto_decryptor_debug_category + +#define gst_rialto_decryptor_parent_class parent_class +G_DEFINE_TYPE_WITH_PRIVATE(GstRialtoDecryptor, gst_rialto_decryptor, GST_TYPE_BASE_TRANSFORM); + +static void gst_rialto_decryptor_finalize(GObject *); // NOLINT(build/function_format) +static GstCaps *gst_rialto_decryptor_transform_caps(GstBaseTransform *, // NOLINT(build/function_format) + GstPadDirection, GstCaps *, GstCaps *); +static GstFlowReturn gst_rialto_decryptor_transform_ip(GstBaseTransform *base, // NOLINT(build/function_format) + GstBuffer *buffer); + +static const char *toString(const firebolt::rialto::CipherMode &cipherMode) +{ + switch (cipherMode) + { + case firebolt::rialto::CipherMode::CBCS: + { + return "cbcs"; + } + case firebolt::rialto::CipherMode::CENC: + { + return "cenc"; + } + case firebolt::rialto::CipherMode::CBC1: + { + return "cbc1"; + } + case firebolt::rialto::CipherMode::CENS: + { + return "cens"; + } + case firebolt::rialto::CipherMode::UNKNOWN: + default: + { + return "unknown"; + } + } +} + +static void gst_rialto_decryptor_class_init(GstRialtoDecryptorClass *klass) // NOLINT(build/function_format) +{ + GST_DEBUG_CATEGORY_INIT(gst_rialto_decryptor_debug_category, "rialtodecryptor", 0, "Decryptor for Rialto"); + + GObjectClass *gobject_class = G_OBJECT_CLASS(klass); + gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_rialto_decryptor_finalize); + + GstElementClass *element_class = GST_ELEMENT_CLASS(klass); + gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sinkTemplate)); + gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&srcTemplate)); + gst_element_class_set_static_metadata(element_class, "Rialto Decryptor", GST_ELEMENT_FACTORY_KLASS_DECRYPTOR, + "Decryptor for Rialto.", + "Luke Williamson \n" + "Adam Czynszak "); + + GstBaseTransformClass *base_transform_class = GST_BASE_TRANSFORM_CLASS(klass); + base_transform_class->transform_caps = GST_DEBUG_FUNCPTR(gst_rialto_decryptor_transform_caps); + base_transform_class->transform_ip = GST_DEBUG_FUNCPTR(gst_rialto_decryptor_transform_ip); + base_transform_class->transform_ip_on_passthrough = FALSE; +} + +static void gst_rialto_decryptor_init(GstRialtoDecryptor *self) // NOLINT(build/function_format) +{ + GstRialtoDecryptorPrivate *priv = + reinterpret_cast(gst_rialto_decryptor_get_instance_private(self)); + GstBaseTransform *base = GST_BASE_TRANSFORM(self); + + self->priv = new (priv) GstRialtoDecryptorPrivate(base, firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(), + firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory()); + + gst_base_transform_set_in_place(base, TRUE); + gst_base_transform_set_passthrough(base, FALSE); + gst_base_transform_set_gap_aware(base, FALSE); +} + +static void gst_rialto_decryptor_finalize(GObject *object) // NOLINT(build/function_format) +{ + GstRialtoDecryptor *self = GST_RIALTO_DECRYPTOR(object); + GstRialtoDecryptorPrivate *priv = + reinterpret_cast(gst_rialto_decryptor_get_instance_private(self)); + + priv->~GstRialtoDecryptorPrivate(); + + GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); +} + +static GstCaps *gst_rialto_decryptor_transform_caps(GstBaseTransform *base, // NOLINT(build/function_format) + GstPadDirection direction, GstCaps *caps, GstCaps *filter) +{ + if (direction == GST_PAD_UNKNOWN) + return nullptr; + + GstRialtoDecryptor *self = GST_RIALTO_DECRYPTOR(base); + + GST_DEBUG_OBJECT(self, "Transform in direction: %s, caps %" GST_PTR_FORMAT ", filter %" GST_PTR_FORMAT, + direction == GST_PAD_SINK ? "GST_PAD_SINK" : "GST_PAD_SRC", caps, filter); + + return GST_BASE_TRANSFORM_CLASS(parent_class)->transform_caps(base, direction, caps, filter); +} + +static GstFlowReturn gst_rialto_decryptor_transform_ip(GstBaseTransform *base, // NOLINT(build/function_format) + GstBuffer *buffer) +{ + GstRialtoDecryptor *self = GST_RIALTO_DECRYPTOR(base); + GstRialtoDecryptorPrivate *priv = + reinterpret_cast(gst_rialto_decryptor_get_instance_private(self)); + + GST_TRACE_OBJECT(self, "Transform in place buf=(%" GST_PTR_FORMAT ")", buffer); + + GstPad *sink_pad = gst_element_get_static_pad(GST_ELEMENT(self), "sink"); + GstCaps *caps = gst_pad_get_current_caps(sink_pad); + + GstFlowReturn result = priv->decrypt(buffer, caps); + gst_caps_unref(caps); + gst_object_unref(sink_pad); + + return result; +} + +namespace firebolt::rialto::server +{ +std::shared_ptr IGstDecryptorElementFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the decryptor element factory, reason: %s", e.what()); + } + + return factory; +} + +GstElement *GstDecryptorElementFactory::createDecryptorElement( + const gchar *name, firebolt::rialto::server::IDecryptionService *decryptionService, + const std::shared_ptr &gstWrapper) const +{ + // Bypass the glib wrapper here, this is the only place we can create a proper Decryptor element + GstRialtoDecryptor *decryptor = GST_RIALTO_DECRYPTOR(g_object_new(GST_RIALTO_DECRYPTOR_TYPE, nullptr)); + if (name) + { + if (!gstWrapper->gstObjectSetName(GST_OBJECT(decryptor), name)) + { + RIALTO_SERVER_LOG_ERROR("Failed to set the decryptor name to %s", name); + g_object_unref(GST_OBJECT(decryptor)); + return nullptr; + } + } + + GstRialtoDecryptorPrivate *priv = + reinterpret_cast(gst_rialto_decryptor_get_instance_private(decryptor)); + std::shared_ptr metadataFactory = + firebolt::rialto::server::IGstProtectionMetadataHelperFactory::createFactory(); + if (priv) + { + priv->setDecryptionService(decryptionService); + priv->setProtectionMetadataWrapper(metadataFactory->createProtectionMetadataWrapper(gstWrapper)); + return GST_ELEMENT(decryptor); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to create the decryptor element"); + g_object_unref(GST_OBJECT(decryptor)); + return nullptr; + } +} + +GstRialtoDecryptorPrivate::GstRialtoDecryptorPrivate( + GstBaseTransform *parentElement, + const std::shared_ptr &gstWrapperFactory, + const std::shared_ptr &glibWrapperFactory) + : m_decryptorElement(parentElement) +{ + if ((!gstWrapperFactory) || (!(m_gstWrapper = gstWrapperFactory->getGstWrapper()))) + { + throw std::runtime_error("Cannot create GstWrapper"); + } + + if ((!glibWrapperFactory) || (!(m_glibWrapper = glibWrapperFactory->getGlibWrapper()))) + { + throw std::runtime_error("Cannot create GlibWrapper"); + } +} + +GstFlowReturn GstRialtoDecryptorPrivate::decrypt(GstBuffer *buffer, GstCaps *caps) +{ + GstRialtoDecryptor *self = GST_RIALTO_DECRYPTOR(m_decryptorElement); + GstRialtoProtectionData *protectionData = m_metadataWrapper->getProtectionMetadataData(buffer); + GstFlowReturn returnStatus = GST_BASE_TRANSFORM_FLOW_DROPPED; // By default drop frame on failure + if (!protectionData) + { + GST_TRACE_OBJECT(self, "Clear sample"); + returnStatus = GST_FLOW_OK; + } + else + { + if (!m_decryptionService) + { + GST_ERROR_OBJECT(self, "No decryption service object"); + } + else + { + if (protectionData->cipherMode == firebolt::rialto::CipherMode::CBC1 || + protectionData->cipherMode == firebolt::rialto::CipherMode::CENS) + { + GST_WARNING_OBJECT(self, "Untested cipher mode '%s'", toString(protectionData->cipherMode)); + } + + if (protectionData->encryptionPatternSet) + { + if (protectionData->cipherMode == firebolt::rialto::CipherMode::CENC || + protectionData->cipherMode == firebolt::rialto::CipherMode::CBC1) + { + GST_WARNING_OBJECT(self, "Encryption pattern set for non-pattern cipherMode '%s'", + toString(protectionData->cipherMode)); + } + } + + if (protectionData->key && m_decryptionService->isPlayreadyKeySystem(protectionData->keySessionId)) + { + GstMapInfo keyMap; + if (m_gstWrapper->gstBufferMap(protectionData->key, &keyMap, GST_MAP_READ)) + { + std::vector playreadyKey(keyMap.data, keyMap.data + keyMap.size); + m_gstWrapper->gstBufferUnmap(protectionData->key, &keyMap); + m_decryptionService->selectKeyId(protectionData->keySessionId, playreadyKey); + m_gstWrapper->gstBufferUnref(protectionData->key); + protectionData->key = m_gstWrapper->gstBufferNew(); + } + else + { + GST_ERROR_OBJECT(self, "Failed to map playready key id"); + } + } + + // Create new GstProtectionMeta decrypt + GstStructure *info = createProtectionMetaInfo(protectionData); + GstProtectionMeta *meta = m_gstWrapper->gstBufferAddProtectionMeta(buffer, info); + if (meta == nullptr) + { + GST_ERROR_OBJECT(self, "Failed to add protection meta to the buffer"); + } + else + { + firebolt::rialto::MediaKeyErrorStatus status = + m_decryptionService->decrypt(protectionData->keySessionId, buffer, caps); + if (firebolt::rialto::MediaKeyErrorStatus::OK != status) + { + GST_ERROR_OBJECT(self, "Failed decrypt the buffer"); + } + else + { + GST_TRACE_OBJECT(self, "Decryption successful"); + returnStatus = GST_FLOW_OK; + } + } + } + + m_metadataWrapper->removeProtectionMetadata(buffer); + } + + if (GST_BASE_TRANSFORM_FLOW_DROPPED == returnStatus) + { + // Notify dropped frame upstream as a non-fatal message + std::string message = "Failed to decrypt buffer, dropping frame and continuing"; + GError *gError{m_glibWrapper->gErrorNewLiteral(GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT, message.c_str())}; + gboolean result = + m_gstWrapper->gstElementPostMessage(GST_ELEMENT_CAST(self), + m_gstWrapper->gstMessageNewWarning(GST_OBJECT_CAST(self), gError, + message.c_str())); + if (!result) + { + GST_WARNING_OBJECT(self, "Could not post decrypt warning"); + } + m_glibWrapper->gErrorFree(gError); + } + return returnStatus; +} + +GstStructure *GstRialtoDecryptorPrivate::createProtectionMetaInfo(GstRialtoProtectionData *protectionData) +{ + GstStructure *info = m_gstWrapper->gstStructureNew("application/x-cenc", "kid", GST_TYPE_BUFFER, + protectionData->key, "iv", GST_TYPE_BUFFER, protectionData->iv, + "subsample_count", G_TYPE_UINT, protectionData->subsampleCount, + "subsamples", GST_TYPE_BUFFER, protectionData->subsamples, + "encryption_scheme", G_TYPE_UINT, 0, "init_with_last_15", + G_TYPE_UINT, protectionData->initWithLast15, "cipher-mode", + G_TYPE_STRING, toString(protectionData->cipherMode), NULL); + + if (protectionData->encryptionPatternSet) + { + m_gstWrapper->gstStructureSet(info, "crypt_byte_block", G_TYPE_UINT, protectionData->crypt, NULL); + m_gstWrapper->gstStructureSet(info, "skip_byte_block", G_TYPE_UINT, protectionData->skip, NULL); + } + return info; +} + +void GstRialtoDecryptorPrivate::setDecryptionService(IDecryptionService *decryptionService) +{ + m_decryptionService = decryptionService; +} + +void GstRialtoDecryptorPrivate::setProtectionMetadataWrapper(std::unique_ptr &&metadataWrapper) +{ + m_metadataWrapper = std::move(metadataWrapper); +} + +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstDispatcherThread.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstDispatcherThread.cpp new file mode 100644 index 000000000..6fd473bb0 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstDispatcherThread.cpp @@ -0,0 +1,124 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GstDispatcherThread.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server +{ +std::unique_ptr GstDispatcherThreadFactory::createGstDispatcherThread( + IGstDispatcherThreadClient &client, GstElement *pipeline, + const std::shared_ptr &gstWrapper) const +{ + return std::make_unique(client, pipeline, gstWrapper); +} + +GstDispatcherThread::GstDispatcherThread(IGstDispatcherThreadClient &client, GstElement *pipeline, + const std::shared_ptr &gstWrapper) + : m_client{client}, m_gstWrapper{gstWrapper}, m_isGstreamerDispatcherActive{true} +{ + RIALTO_SERVER_LOG_INFO("GstDispatcherThread is starting"); + m_gstBusDispatcherThread = std::thread(&GstDispatcherThread::gstBusEventHandler, this, pipeline); +} + +GstDispatcherThread::~GstDispatcherThread() +{ + RIALTO_SERVER_LOG_INFO("Stopping GstDispatcherThread"); + m_isGstreamerDispatcherActive = false; + if (m_gstBusDispatcherThread.joinable()) + { + m_gstBusDispatcherThread.join(); + } +} + +void GstDispatcherThread::gstBusEventHandler(GstElement *pipeline) +{ + GstBus *bus = m_gstWrapper->gstPipelineGetBus(GST_PIPELINE(pipeline)); + if (!bus) + { + RIALTO_SERVER_LOG_ERROR("Failed to get gst bus"); + return; + } + + while (m_isGstreamerDispatcherActive) + { + GstMessage *message = + m_gstWrapper->gstBusTimedPopFiltered(bus, 100 * GST_MSECOND, + static_cast(GST_MESSAGE_STATE_CHANGED | + GST_MESSAGE_QOS | GST_MESSAGE_EOS | + GST_MESSAGE_ERROR | GST_MESSAGE_WARNING)); + + if (message) + { + bool shouldHandleMessage{true}; + bool isPrioritised{false}; + if (GST_MESSAGE_SRC(message) == GST_OBJECT(pipeline)) + { + switch (GST_MESSAGE_TYPE(message)) + { + case GST_MESSAGE_STATE_CHANGED: + { + isPrioritised = true; + GstState oldState, newState, pending; + m_gstWrapper->gstMessageParseStateChanged(message, &oldState, &newState, &pending); + switch (newState) + { + case GST_STATE_NULL: + { + m_isGstreamerDispatcherActive = false; + } + case GST_STATE_READY: + case GST_STATE_PAUSED: + case GST_STATE_PLAYING: + case GST_STATE_VOID_PENDING: + { + break; + } + } + break; + } + case GST_MESSAGE_ERROR: + { + m_isGstreamerDispatcherActive = false; + break; + } + default: + { + break; + } + } + } + else if (GST_MESSAGE_STATE_CHANGED == GST_MESSAGE_TYPE(message)) + { + // Skip handling GST_MESSAGE_STATE_CHANGED for non-pipeline objects. + // It signifficantly slows down rialto gst worker thread + shouldHandleMessage = false; + } + + if (shouldHandleMessage) + { + m_client.handleBusMessage(message, isPrioritised); + } + } + } + + RIALTO_SERVER_LOG_INFO("Gstbus dispatcher exitting"); + m_gstWrapper->gstObjectUnref(bus); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstGenericPlayer.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstGenericPlayer.cpp new file mode 100644 index 000000000..7aa7105da --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstGenericPlayer.cpp @@ -0,0 +1,2270 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "FlushWatcher.h" +#include "GstDispatcherThread.h" +#include "GstGenericPlayer.h" +#include "GstProtectionMetadata.h" +#include "IGstTextTrackSinkFactory.h" +#include "IMediaPipeline.h" +#include "ITimer.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" +#include "Utils.h" +#include "WorkerThread.h" +#include "tasks/generic/GenericPlayerTaskFactory.h" + +namespace +{ +/** + * @brief Report position interval in ms. + * The position reporting timer should be started whenever the PLAYING state is entered and stopped + * whenever the session moves to another playback state. + */ +constexpr std::chrono::milliseconds kPositionReportTimerMs{250}; +constexpr std::chrono::seconds kSubtitleClockResyncInterval{10}; + +bool operator==(const firebolt::rialto::server::SegmentData &lhs, const firebolt::rialto::server::SegmentData &rhs) +{ + return (lhs.position == rhs.position) && (lhs.resetTime == rhs.resetTime) && (lhs.appliedRate == rhs.appliedRate) && + (lhs.stopPosition == rhs.stopPosition); +} +} // namespace + +namespace firebolt::rialto::server +{ +std::weak_ptr GstGenericPlayerFactory::m_factory; + +std::shared_ptr IGstGenericPlayerFactory::getFactory() +{ + std::shared_ptr factory = GstGenericPlayerFactory::m_factory.lock(); + + if (!factory) + { + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer player factory, reason: %s", e.what()); + } + + GstGenericPlayerFactory::m_factory = factory; + } + + return factory; +} + +std::unique_ptr GstGenericPlayerFactory::createGstGenericPlayer( + IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, + const VideoRequirements &videoRequirements, + const std::shared_ptr &rdkGstreamerUtilsWrapperFactory) +{ + std::unique_ptr gstPlayer; + + try + { + auto gstWrapperFactory = firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); + auto glibWrapperFactory = firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(); + std::shared_ptr gstWrapper; + std::shared_ptr glibWrapper; + std::shared_ptr rdkGstreamerUtilsWrapper; + if ((!gstWrapperFactory) || (!(gstWrapper = gstWrapperFactory->getGstWrapper()))) + { + throw std::runtime_error("Cannot create GstWrapper"); + } + if ((!glibWrapperFactory) || (!(glibWrapper = glibWrapperFactory->getGlibWrapper()))) + { + throw std::runtime_error("Cannot create GlibWrapper"); + } + if ((!rdkGstreamerUtilsWrapperFactory) || + (!(rdkGstreamerUtilsWrapper = rdkGstreamerUtilsWrapperFactory->createRdkGstreamerUtilsWrapper()))) + { + throw std::runtime_error("Cannot create RdkGstreamerUtilsWrapper"); + } + gstPlayer = std::make_unique< + GstGenericPlayer>(client, decryptionService, type, videoRequirements, gstWrapper, glibWrapper, + rdkGstreamerUtilsWrapper, IGstInitialiser::instance(), std::make_unique(), + IGstSrcFactory::getFactory(), common::ITimerFactory::getFactory(), + std::make_unique(client, gstWrapper, glibWrapper, + rdkGstreamerUtilsWrapper, + IGstTextTrackSinkFactory::createFactory()), + std::make_unique(), std::make_unique(), + IGstProtectionMetadataHelperFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer player, reason: %s", e.what()); + } + + return gstPlayer; +} + +GstGenericPlayer::GstGenericPlayer( + IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, + const VideoRequirements &videoRequirements, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr &rdkGstreamerUtilsWrapper, + const IGstInitialiser &gstInitialiser, std::unique_ptr &&flushWatcher, + const std::shared_ptr &gstSrcFactory, std::shared_ptr timerFactory, + std::unique_ptr taskFactory, std::unique_ptr workerThreadFactory, + std::unique_ptr gstDispatcherThreadFactory, + std::shared_ptr gstProtectionMetadataFactory) + : m_gstPlayerClient(client), m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, + m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, m_timerFactory{timerFactory}, + m_taskFactory{std::move(taskFactory)}, m_flushWatcher{std::move(flushWatcher)} +{ + RIALTO_SERVER_LOG_DEBUG("GstGenericPlayer is constructed."); + + gstInitialiser.waitForInitialisation(); + + m_context.decryptionService = &decryptionService; + + if ((!gstSrcFactory) || (!(m_context.gstSrc = gstSrcFactory->getGstSrc()))) + { + throw std::runtime_error("Cannot create GstSrc"); + } + + if (!timerFactory) + { + throw std::runtime_error("TimeFactory is invalid"); + } + + if ((!gstProtectionMetadataFactory) || + (!(m_protectionMetadataWrapper = gstProtectionMetadataFactory->createProtectionMetadataWrapper(m_gstWrapper)))) + { + throw std::runtime_error("Cannot create protection metadata wrapper"); + } + + // Ensure that rialtosrc has been initalised + m_context.gstSrc->initSrc(); + + // Start task thread + if ((!workerThreadFactory) || (!(m_workerThread = workerThreadFactory->createWorkerThread()))) + { + throw std::runtime_error("Failed to create the worker thread"); + } + + // Initialise pipeline + switch (type) + { + case MediaType::MSE: + { + initMsePipeline(); + break; + } + default: + { + resetWorkerThread(); + throw std::runtime_error("Media type not supported"); + } + } + + // Check the video requirements for a limited video. + // If the video requirements are set to anything lower than the minimum, this playback is assumed to be a secondary + // video in a dual video scenario. + if ((kMinPrimaryVideoWidth > videoRequirements.maxWidth) || (kMinPrimaryVideoHeight > videoRequirements.maxHeight)) + { + RIALTO_SERVER_LOG_MIL("Secondary video playback selected"); + bool westerossinkSecondaryVideoResult = setWesterossinkSecondaryVideo(); + bool ermContextResult = setErmContext(); + if (!westerossinkSecondaryVideoResult && !ermContextResult) + { + resetWorkerThread(); + termPipeline(); + throw std::runtime_error("Could not set secondary video"); + } + } + else + { + RIALTO_SERVER_LOG_MIL("Primary video playback selected"); + } + + m_gstDispatcherThread = + gstDispatcherThreadFactory->createGstDispatcherThread(*this, m_context.pipeline, m_gstWrapper); +} + +GstGenericPlayer::~GstGenericPlayer() +{ + RIALTO_SERVER_LOG_DEBUG("GstGenericPlayer is destructed."); + m_gstDispatcherThread.reset(); + + resetWorkerThread(); + + termPipeline(); +} + +void GstGenericPlayer::initMsePipeline() +{ + // Make playbin + m_context.pipeline = m_gstWrapper->gstElementFactoryMake("playbin", "media_pipeline"); + // Set pipeline flags + setPlaybinFlags(true); + + // Set callbacks + m_glibWrapper->gSignalConnect(m_context.pipeline, "source-setup", G_CALLBACK(&GstGenericPlayer::setupSource), this); + m_glibWrapper->gSignalConnect(m_context.pipeline, "element-setup", G_CALLBACK(&GstGenericPlayer::setupElement), this); + m_glibWrapper->gSignalConnect(m_context.pipeline, "deep-element-added", + G_CALLBACK(&GstGenericPlayer::deepElementAdded), this); + + // Set uri + m_glibWrapper->gObjectSet(m_context.pipeline, "uri", "rialto://", nullptr); + + // Check playsink + GstElement *playsink = (m_gstWrapper->gstBinGetByName(GST_BIN(m_context.pipeline), "playsink")); + if (playsink) + { + m_glibWrapper->gObjectSet(G_OBJECT(playsink), "send-event-mode", 0, nullptr); + m_gstWrapper->gstObjectUnref(playsink); + } + else + { + GST_WARNING("No playsink ?!?!?"); + } + if (GST_STATE_CHANGE_FAILURE == m_gstWrapper->gstElementSetState(m_context.pipeline, GST_STATE_READY)) + { + GST_WARNING("Failed to set pipeline to READY state"); + } + RIALTO_SERVER_LOG_MIL("New RialtoServer's pipeline created"); +} + +void GstGenericPlayer::resetWorkerThread() +{ + // Shutdown task thread + m_workerThread->enqueueTask(m_taskFactory->createShutdown(*this)); + m_workerThread->join(); + m_workerThread.reset(); +} + +void GstGenericPlayer::termPipeline() +{ + if (m_finishSourceSetupTimer && m_finishSourceSetupTimer->isActive()) + { + m_finishSourceSetupTimer->cancel(); + } + + m_finishSourceSetupTimer.reset(); + + for (auto &elem : m_context.streamInfo) + { + StreamInfo &streamInfo = elem.second; + for (auto &buffer : streamInfo.buffers) + { + m_gstWrapper->gstBufferUnref(buffer); + } + + streamInfo.buffers.clear(); + } + + m_taskFactory->createStop(m_context, *this)->execute(); + GstBus *bus = m_gstWrapper->gstPipelineGetBus(GST_PIPELINE(m_context.pipeline)); + m_gstWrapper->gstBusSetSyncHandler(bus, nullptr, nullptr, nullptr); + m_gstWrapper->gstObjectUnref(bus); + + if (m_context.source) + { + m_gstWrapper->gstObjectUnref(m_context.source); + } + if (m_context.subtitleSink) + { + m_gstWrapper->gstObjectUnref(m_context.subtitleSink); + m_context.subtitleSink = nullptr; + } + + if (m_context.videoSink) + { + m_gstWrapper->gstObjectUnref(m_context.videoSink); + m_context.videoSink = nullptr; + } + + // Delete the pipeline + m_gstWrapper->gstObjectUnref(m_context.pipeline); + + RIALTO_SERVER_LOG_MIL("RialtoServer's pipeline terminated"); +} + +unsigned GstGenericPlayer::getGstPlayFlag(const char *nick) +{ + GFlagsClass *flagsClass = + static_cast(m_glibWrapper->gTypeClassRef(m_glibWrapper->gTypeFromName("GstPlayFlags"))); + GFlagsValue *flag = m_glibWrapper->gFlagsGetValueByNick(flagsClass, nick); + return flag ? flag->value : 0; +} + +void GstGenericPlayer::setupSource(GstElement *pipeline, GstElement *source, GstGenericPlayer *self) +{ + self->m_gstWrapper->gstObjectRef(source); + if (self->m_workerThread) + { + self->m_workerThread->enqueueTask(self->m_taskFactory->createSetupSource(self->m_context, *self, source)); + } +} + +void GstGenericPlayer::setupElement(GstElement *pipeline, GstElement *element, GstGenericPlayer *self) +{ + RIALTO_SERVER_LOG_DEBUG("Element %s added to the pipeline", GST_ELEMENT_NAME(element)); + self->m_gstWrapper->gstObjectRef(element); + if (self->m_workerThread) + { + self->m_workerThread->enqueueTask(self->m_taskFactory->createSetupElement(self->m_context, *self, element)); + } +} + +void GstGenericPlayer::deepElementAdded(GstBin *pipeline, GstBin *bin, GstElement *element, GstGenericPlayer *self) +{ + RIALTO_SERVER_LOG_DEBUG("Deep element %s added to the pipeline", GST_ELEMENT_NAME(element)); + if (self->m_workerThread) + { + self->m_workerThread->enqueueTask( + self->m_taskFactory->createDeepElementAdded(self->m_context, *self, pipeline, bin, element)); + } +} + +void GstGenericPlayer::attachSource(const std::unique_ptr &attachedSource) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createAttachSource(m_context, *this, attachedSource)); + } +} + +void GstGenericPlayer::removeSource(const MediaSourceType &mediaSourceType) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createRemoveSource(m_context, *this, mediaSourceType)); + } +} + +void GstGenericPlayer::allSourcesAttached() +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createFinishSetupSource(m_context, *this)); + } +} + +void GstGenericPlayer::attachSamples(const IMediaPipeline::MediaSegmentVector &mediaSegments) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createAttachSamples(m_context, *this, mediaSegments)); + } +} + +void GstGenericPlayer::attachSamples(const std::shared_ptr &dataReader) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createReadShmDataAndAttachSamples(m_context, *this, dataReader)); + } +} + +void GstGenericPlayer::setPosition(std::int64_t position) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetPosition(m_context, *this, position)); + } +} + +void GstGenericPlayer::setPlaybackRate(double rate) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetPlaybackRate(m_context, rate)); + } +} + +bool GstGenericPlayer::getPosition(std::int64_t &position) +{ + // We are on main thread here, but m_context.pipeline can be used, because it's modified only in GstGenericPlayer + // constructor and destructor. GstGenericPlayer is created/destructed on main thread, so we won't have a crash here. + position = getPosition(m_context.pipeline); + if (position == -1) + { + RIALTO_SERVER_LOG_WARN("Query position failed"); + return false; + } + + return true; +} + +GstElement *GstGenericPlayer::getSink(const MediaSourceType &mediaSourceType) const +{ + const char *kSinkName{nullptr}; + GstElement *sink{nullptr}; + switch (mediaSourceType) + { + case MediaSourceType::AUDIO: + kSinkName = "audio-sink"; + break; + case MediaSourceType::VIDEO: + kSinkName = "video-sink"; + break; + default: + break; + } + if (!kSinkName) + { + RIALTO_SERVER_LOG_WARN("mediaSourceType not supported %d", static_cast(mediaSourceType)); + } + else + { + if (m_context.pipeline == nullptr) + { + RIALTO_SERVER_LOG_WARN("Pipeline is NULL!"); + } + else + { + RIALTO_SERVER_LOG_DEBUG("Pipeline is valid: %p", m_context.pipeline); + } + m_glibWrapper->gObjectGet(m_context.pipeline, kSinkName, &sink, nullptr); + if (sink) + { + GstElement *autoSink{sink}; + if (firebolt::rialto::MediaSourceType::VIDEO == mediaSourceType) + autoSink = getSinkChildIfAutoVideoSink(sink); + else if (firebolt::rialto::MediaSourceType::AUDIO == mediaSourceType) + autoSink = getSinkChildIfAutoAudioSink(sink); + + // Is this an auto-sink?... + if (autoSink != sink) + { + m_gstWrapper->gstObjectUnref(GST_OBJECT(sink)); + + // increase the reference count of the auto sink + sink = GST_ELEMENT(m_gstWrapper->gstObjectRef(GST_OBJECT(autoSink))); + } + } + else + { + RIALTO_SERVER_LOG_WARN("%s could not be obtained", kSinkName); + } + } + return sink; +} + +void GstGenericPlayer::setSourceFlushed(const MediaSourceType &mediaSourceType) +{ + m_flushWatcher->setFlushed(mediaSourceType); +} + +GstElement *GstGenericPlayer::getDecoder(const MediaSourceType &mediaSourceType) +{ + GstIterator *it = m_gstWrapper->gstBinIterateRecurse(GST_BIN(m_context.pipeline)); + GValue item = G_VALUE_INIT; + gboolean done = FALSE; + + while (!done) + { + switch (m_gstWrapper->gstIteratorNext(it, &item)) + { + case GST_ITERATOR_OK: + { + GstElement *element = GST_ELEMENT(m_glibWrapper->gValueGetObject(&item)); + GstElementFactory *factory = m_gstWrapper->gstElementGetFactory(element); + + if (factory) + { + GstElementFactoryListType type = GST_ELEMENT_FACTORY_TYPE_DECODER; + if (mediaSourceType == MediaSourceType::AUDIO) + { + type |= GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO; + } + else if (mediaSourceType == MediaSourceType::VIDEO) + { + type |= GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO; + } + + if (m_gstWrapper->gstElementFactoryListIsType(factory, type)) + { + m_glibWrapper->gValueUnset(&item); + m_gstWrapper->gstIteratorFree(it); + return GST_ELEMENT(m_gstWrapper->gstObjectRef(element)); + } + } + + m_glibWrapper->gValueUnset(&item); + break; + } + case GST_ITERATOR_RESYNC: + m_gstWrapper->gstIteratorResync(it); + break; + case GST_ITERATOR_ERROR: + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + + RIALTO_SERVER_LOG_WARN("Could not find decoder"); + + m_glibWrapper->gValueUnset(&item); + m_gstWrapper->gstIteratorFree(it); + + return nullptr; +} + +GstElement *GstGenericPlayer::getParser(const MediaSourceType &mediaSourceType) +{ + GstIterator *it = m_gstWrapper->gstBinIterateRecurse(GST_BIN(m_context.pipeline)); + GValue item = G_VALUE_INIT; + gboolean done = FALSE; + + while (!done) + { + switch (m_gstWrapper->gstIteratorNext(it, &item)) + { + case GST_ITERATOR_OK: + { + GstElement *element = GST_ELEMENT(m_glibWrapper->gValueGetObject(&item)); + GstElementFactory *factory = m_gstWrapper->gstElementGetFactory(element); + + if (factory) + { + GstElementFactoryListType type = GST_ELEMENT_FACTORY_TYPE_PARSER; + if (mediaSourceType == MediaSourceType::AUDIO) + { + type |= GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO; + } + else if (mediaSourceType == MediaSourceType::VIDEO) + { + type |= GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO; + } + + if (m_gstWrapper->gstElementFactoryListIsType(factory, type)) + { + m_glibWrapper->gValueUnset(&item); + m_gstWrapper->gstIteratorFree(it); + return GST_ELEMENT(m_gstWrapper->gstObjectRef(element)); + } + } + + m_glibWrapper->gValueUnset(&item); + break; + } + case GST_ITERATOR_RESYNC: + m_gstWrapper->gstIteratorResync(it); + break; + case GST_ITERATOR_ERROR: + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + + RIALTO_SERVER_LOG_WARN("Could not find parser"); + + m_glibWrapper->gValueUnset(&item); + m_gstWrapper->gstIteratorFree(it); + + return nullptr; +} + +std::optional +GstGenericPlayer::createAudioAttributes(const std::unique_ptr &source) const +{ + std::optional audioAttributes; + const IMediaPipeline::MediaSourceAudio *kSource = dynamic_cast(source.get()); + if (kSource) + { + firebolt::rialto::AudioConfig audioConfig = kSource->getAudioConfig(); + audioAttributes = + firebolt::rialto::wrappers::AudioAttributesPrivate{"", // param set below. + audioConfig.numberOfChannels, audioConfig.sampleRate, + 0, // used only in one of logs in rdk_gstreamer_utils, no + // need to set this param. + 0, // used only in one of logs in rdk_gstreamer_utils, no + // need to set this param. + audioConfig.codecSpecificConfig.data(), + static_cast( + audioConfig.codecSpecificConfig.size())}; + if (source->getMimeType() == "audio/mp4" || source->getMimeType() == "audio/aac") + { + audioAttributes->m_codecParam = "mp4a"; + } + else if (source->getMimeType() == "audio/x-eac3") + { + audioAttributes->m_codecParam = "ec-3"; + } + else if (source->getMimeType() == "audio/b-wav" || source->getMimeType() == "audio/x-raw") + { + audioAttributes->m_codecParam = "lpcm"; + } + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to cast source"); + } + + return audioAttributes; +} + +bool GstGenericPlayer::setImmediateOutput(const MediaSourceType &mediaSourceType, bool immediateOutputParam) +{ + if (!m_workerThread) + return false; + + m_workerThread->enqueueTask( + m_taskFactory->createSetImmediateOutput(m_context, *this, mediaSourceType, immediateOutputParam)); + return true; +} + +bool GstGenericPlayer::getImmediateOutput(const MediaSourceType &mediaSourceType, bool &immediateOutputRef) +{ + bool returnValue{false}; + GstElement *sink{getSink(mediaSourceType)}; + if (sink) + { + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "immediate-output")) + { + m_glibWrapper->gObjectGet(sink, "immediate-output", &immediateOutputRef, nullptr); + returnValue = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("immediate-output not supported in element %s", GST_ELEMENT_NAME(sink)); + } + m_gstWrapper->gstObjectUnref(sink); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set immediate-output property, sink is NULL"); + } + + return returnValue; +} + +bool GstGenericPlayer::getStats(const MediaSourceType &mediaSourceType, uint64_t &renderedFrames, uint64_t &droppedFrames) +{ + bool returnValue{false}; + GstElement *sink{getSink(mediaSourceType)}; + if (sink) + { + GstStructure *stats{nullptr}; + m_glibWrapper->gObjectGet(sink, "stats", &stats, nullptr); + if (!stats) + { + RIALTO_SERVER_LOG_ERROR("failed to get stats from '%s'", GST_ELEMENT_NAME(sink)); + } + else + { + guint64 renderedFramesTmp; + guint64 droppedFramesTmp; + if (m_gstWrapper->gstStructureGetUint64(stats, "rendered", &renderedFramesTmp) && + m_gstWrapper->gstStructureGetUint64(stats, "dropped", &droppedFramesTmp)) + { + renderedFrames = renderedFramesTmp; + droppedFrames = droppedFramesTmp; + returnValue = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("failed to get 'rendered' or 'dropped' from structure (%s)", + GST_ELEMENT_NAME(sink)); + } + m_gstWrapper->gstStructureFree(stats); + } + m_gstWrapper->gstObjectUnref(sink); + } + + return returnValue; +} + +GstBuffer *GstGenericPlayer::createBuffer(const IMediaPipeline::MediaSegment &mediaSegment) const +{ + GstBuffer *gstBuffer = m_gstWrapper->gstBufferNewAllocate(nullptr, mediaSegment.getDataLength(), nullptr); + m_gstWrapper->gstBufferFill(gstBuffer, 0, mediaSegment.getData(), mediaSegment.getDataLength()); + + if (mediaSegment.isEncrypted()) + { + GstBuffer *keyId = m_gstWrapper->gstBufferNewAllocate(nullptr, mediaSegment.getKeyId().size(), nullptr); + m_gstWrapper->gstBufferFill(keyId, 0, mediaSegment.getKeyId().data(), mediaSegment.getKeyId().size()); + + GstBuffer *initVector = m_gstWrapper->gstBufferNewAllocate(nullptr, mediaSegment.getInitVector().size(), nullptr); + m_gstWrapper->gstBufferFill(initVector, 0, mediaSegment.getInitVector().data(), + mediaSegment.getInitVector().size()); + GstBuffer *subsamples{nullptr}; + if (!mediaSegment.getSubSamples().empty()) + { + auto subsamplesRawSize = mediaSegment.getSubSamples().size() * (sizeof(guint16) + sizeof(guint32)); + guint8 *subsamplesRaw = static_cast(m_glibWrapper->gMalloc(subsamplesRawSize)); + GstByteWriter writer; + m_gstWrapper->gstByteWriterInitWithData(&writer, subsamplesRaw, subsamplesRawSize, FALSE); + + for (const auto &subSample : mediaSegment.getSubSamples()) + { + m_gstWrapper->gstByteWriterPutUint16Be(&writer, subSample.numClearBytes); + m_gstWrapper->gstByteWriterPutUint32Be(&writer, subSample.numEncryptedBytes); + } + subsamples = m_gstWrapper->gstBufferNewWrapped(subsamplesRaw, subsamplesRawSize); + } + + uint32_t crypt = 0; + uint32_t skip = 0; + bool encryptionPatternSet = mediaSegment.getEncryptionPattern(crypt, skip); + + GstRialtoProtectionData data = {mediaSegment.getMediaKeySessionId(), + static_cast(mediaSegment.getSubSamples().size()), + mediaSegment.getInitWithLast15(), + keyId, + initVector, + subsamples, + mediaSegment.getCipherMode(), + crypt, + skip, + encryptionPatternSet, + m_context.decryptionService}; + + if (!m_protectionMetadataWrapper->addProtectionMetadata(gstBuffer, data)) + { + RIALTO_SERVER_LOG_ERROR("Failed to add protection metadata"); + if (keyId) + { + m_gstWrapper->gstBufferUnref(keyId); + } + if (initVector) + { + m_gstWrapper->gstBufferUnref(initVector); + } + if (subsamples) + { + m_gstWrapper->gstBufferUnref(subsamples); + } + } + } + + GST_BUFFER_TIMESTAMP(gstBuffer) = mediaSegment.getTimeStamp(); + GST_BUFFER_DURATION(gstBuffer) = mediaSegment.getDuration(); + return gstBuffer; +} + +void GstGenericPlayer::notifyNeedMediaData(const MediaSourceType mediaSource) +{ + auto elem = m_context.streamInfo.find(mediaSource); + if (elem != m_context.streamInfo.end()) + { + StreamInfo &streamInfo = elem->second; + streamInfo.isNeedDataPending = false; + + // Send new NeedMediaData if we still need it + if (m_gstPlayerClient && streamInfo.isDataNeeded) + { + streamInfo.isNeedDataPending = m_gstPlayerClient->notifyNeedMediaData(mediaSource); + } + } + else + { + RIALTO_SERVER_LOG_WARN("Media type %s could not be found", common::convertMediaSourceType(mediaSource)); + } +} + +void GstGenericPlayer::attachData(const firebolt::rialto::MediaSourceType mediaType) +{ + auto elem = m_context.streamInfo.find(mediaType); + if (elem != m_context.streamInfo.end()) + { + StreamInfo &streamInfo = elem->second; + if (streamInfo.buffers.empty() || !streamInfo.isDataNeeded) + { + return; + } + + if (firebolt::rialto::MediaSourceType::SUBTITLE == mediaType) + { + setTextTrackPositionIfRequired(streamInfo.appSrc); + } + else + { + pushSampleIfRequired(streamInfo.appSrc, common::convertMediaSourceType(mediaType)); + } + if (mediaType == firebolt::rialto::MediaSourceType::AUDIO) + { + // This needs to be done before gstAppSrcPushBuffer() is + // called because it can free the memory + m_context.lastAudioSampleTimestamps = static_cast(GST_BUFFER_PTS(streamInfo.buffers.back())); + } + + for (GstBuffer *buffer : streamInfo.buffers) + { + m_gstWrapper->gstAppSrcPushBuffer(GST_APP_SRC(streamInfo.appSrc), buffer); + } + streamInfo.buffers.clear(); + streamInfo.isDataPushed = true; + + const bool kIsSingle = m_context.streamInfo.size() == 1; + bool allOtherStreamsPushed = std::all_of(m_context.streamInfo.begin(), m_context.streamInfo.end(), + [](const auto &entry) { return entry.second.isDataPushed; }); + + if (!m_context.bufferedNotificationSent && (allOtherStreamsPushed || kIsSingle) && m_gstPlayerClient) + { + m_context.bufferedNotificationSent = true; + m_gstPlayerClient->notifyNetworkState(NetworkState::BUFFERED); + RIALTO_SERVER_LOG_MIL("Buffered NetworkState reached"); + } + cancelUnderflow(mediaType); + + const auto eosInfoIt = m_context.endOfStreamInfo.find(mediaType); + if (eosInfoIt != m_context.endOfStreamInfo.end() && eosInfoIt->second == EosState::PENDING) + { + setEos(mediaType); + } + } +} + +void GstGenericPlayer::updateAudioCaps(int32_t rate, int32_t channels, const std::shared_ptr &codecData) +{ + auto elem = m_context.streamInfo.find(firebolt::rialto::MediaSourceType::AUDIO); + if (elem != m_context.streamInfo.end()) + { + StreamInfo &streamInfo = elem->second; + + constexpr int kInvalidRate{0}, kInvalidChannels{0}; + GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(streamInfo.appSrc)); + GstCaps *newCaps = m_gstWrapper->gstCapsCopy(currentCaps); + + if (rate != kInvalidRate) + { + m_gstWrapper->gstCapsSetSimple(newCaps, "rate", G_TYPE_INT, rate, NULL); + } + + if (channels != kInvalidChannels) + { + m_gstWrapper->gstCapsSetSimple(newCaps, "channels", G_TYPE_INT, channels, NULL); + } + + setCodecData(newCaps, codecData); + + if (!m_gstWrapper->gstCapsIsEqual(currentCaps, newCaps)) + { + m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(streamInfo.appSrc), newCaps); + } + + m_gstWrapper->gstCapsUnref(newCaps); + m_gstWrapper->gstCapsUnref(currentCaps); + } +} + +void GstGenericPlayer::updateVideoCaps(int32_t width, int32_t height, Fraction frameRate, + const std::shared_ptr &codecData) +{ + auto elem = m_context.streamInfo.find(firebolt::rialto::MediaSourceType::VIDEO); + if (elem != m_context.streamInfo.end()) + { + StreamInfo &streamInfo = elem->second; + + GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(streamInfo.appSrc)); + GstCaps *newCaps = m_gstWrapper->gstCapsCopy(currentCaps); + + if (width > 0) + { + m_gstWrapper->gstCapsSetSimple(newCaps, "width", G_TYPE_INT, width, NULL); + } + + if (height > 0) + { + m_gstWrapper->gstCapsSetSimple(newCaps, "height", G_TYPE_INT, height, NULL); + } + + if ((kUndefinedSize != frameRate.numerator) && (kUndefinedSize != frameRate.denominator)) + { + m_gstWrapper->gstCapsSetSimple(newCaps, "framerate", GST_TYPE_FRACTION, frameRate.numerator, + frameRate.denominator, NULL); + } + + setCodecData(newCaps, codecData); + + if (!m_gstWrapper->gstCapsIsEqual(currentCaps, newCaps)) + { + m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(streamInfo.appSrc), newCaps); + } + + m_gstWrapper->gstCapsUnref(currentCaps); + m_gstWrapper->gstCapsUnref(newCaps); + } +} + +void GstGenericPlayer::addAudioClippingToBuffer(GstBuffer *buffer, uint64_t clippingStart, uint64_t clippingEnd) const +{ + if (clippingStart || clippingEnd) + { + if (m_gstWrapper->gstBufferAddAudioClippingMeta(buffer, GST_FORMAT_TIME, clippingStart, clippingEnd)) + { + RIALTO_SERVER_LOG_DEBUG("Added audio clipping to buffer %p, start: %" PRIu64 ", end %" PRIu64, buffer, + clippingStart, clippingEnd); + } + else + { + RIALTO_SERVER_LOG_WARN("Failed to add audio clipping to buffer %p, start: %" PRIu64 ", end %" PRIu64, + buffer, clippingStart, clippingEnd); + } + } +} + +bool GstGenericPlayer::setCodecData(GstCaps *caps, const std::shared_ptr &codecData) const +{ + if (codecData && CodecDataType::BUFFER == codecData->type) + { + gpointer memory = m_glibWrapper->gMemdup(codecData->data.data(), codecData->data.size()); + GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, codecData->data.size()); + m_gstWrapper->gstCapsSetSimple(caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr); + m_gstWrapper->gstBufferUnref(buf); + return true; + } + if (codecData && CodecDataType::STRING == codecData->type) + { + std::string codecDataStr(codecData->data.begin(), codecData->data.end()); + m_gstWrapper->gstCapsSetSimple(caps, "codec_data", G_TYPE_STRING, codecDataStr.c_str(), nullptr); + return true; + } + return false; +} + +void GstGenericPlayer::pushSampleIfRequired(GstElement *source, const std::string &typeStr) +{ + auto initialPosition = m_context.initialPositions.find(source); + if (m_context.initialPositions.end() == initialPosition) + { + // Sending initial sample not needed + return; + } + // GstAppSrc does not replace segment, if it's the same as previous one. + // It causes problems with position reporing in amlogic devices, so we need to push + // two segments with different reset time value. + pushAdditionalSegmentIfRequired(source); + + for (const auto &[position, resetTime, appliedRate, stopPosition] : initialPosition->second) + { + GstSeekFlags seekFlag = resetTime ? GST_SEEK_FLAG_FLUSH : GST_SEEK_FLAG_NONE; + RIALTO_SERVER_LOG_DEBUG("Pushing new %s sample...", typeStr.c_str()); + GstSegment *segment{m_gstWrapper->gstSegmentNew()}; + m_gstWrapper->gstSegmentInit(segment, GST_FORMAT_TIME); + if (!m_gstWrapper->gstSegmentDoSeek(segment, m_context.playbackRate, GST_FORMAT_TIME, seekFlag, + GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET, stopPosition, nullptr)) + { + RIALTO_SERVER_LOG_WARN("Segment seek failed."); + m_gstWrapper->gstSegmentFree(segment); + m_context.initialPositions.erase(initialPosition); + return; + } + segment->applied_rate = appliedRate; + RIALTO_SERVER_LOG_MIL("New %s segment: [%" GST_TIME_FORMAT ", %" GST_TIME_FORMAT + "], rate: %f, appliedRate %f, reset_time: %d\n", + typeStr.c_str(), GST_TIME_ARGS(segment->start), GST_TIME_ARGS(segment->stop), + segment->rate, segment->applied_rate, resetTime); + + GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(source)); + // We can't pass buffer in GstSample, because implementation of gst_app_src_push_sample + // uses gst_buffer_copy, which loses RialtoProtectionMeta (that causes problems with EME + // for first frame). + GstSample *sample = m_gstWrapper->gstSampleNew(nullptr, currentCaps, segment, nullptr); + m_gstWrapper->gstAppSrcPushSample(GST_APP_SRC(source), sample); + m_gstWrapper->gstSampleUnref(sample); + m_gstWrapper->gstCapsUnref(currentCaps); + + m_gstWrapper->gstSegmentFree(segment); + } + m_context.currentPosition[source] = initialPosition->second.back(); + m_context.initialPositions.erase(initialPosition); + return; +} + +void GstGenericPlayer::pushAdditionalSegmentIfRequired(GstElement *source) +{ + auto currentPosition = m_context.currentPosition.find(source); + if (m_context.currentPosition.end() == currentPosition) + { + return; + } + auto initialPosition = m_context.initialPositions.find(source); + if (m_context.initialPositions.end() == initialPosition) + { + return; + } + if (initialPosition->second.size() == 1 && initialPosition->second.back().resetTime && + currentPosition->second == initialPosition->second.back()) + { + RIALTO_SERVER_LOG_INFO("Adding additional segment with reset_time = false"); + SegmentData additionalSegment = initialPosition->second.back(); + additionalSegment.resetTime = false; + initialPosition->second.push_back(additionalSegment); + } +} + +void GstGenericPlayer::setTextTrackPositionIfRequired(GstElement *source) +{ + auto initialPosition = m_context.initialPositions.find(source); + if (m_context.initialPositions.end() == initialPosition) + { + // Sending initial sample not needed + return; + } + + RIALTO_SERVER_LOG_MIL("New subtitle position set %" GST_TIME_FORMAT, + GST_TIME_ARGS(initialPosition->second.back().position)); + m_glibWrapper->gObjectSet(m_context.subtitleSink, "position", + static_cast(initialPosition->second.back().position), nullptr); + + m_context.initialPositions.erase(initialPosition); +} + +bool GstGenericPlayer::reattachSource(const std::unique_ptr &source) +{ + if (m_context.streamInfo.find(source->getType()) == m_context.streamInfo.end()) + { + RIALTO_SERVER_LOG_ERROR("Unable to switch source, type does not exist"); + return false; + } + if (source->getMimeType().empty()) + { + RIALTO_SERVER_LOG_WARN("Skip switch audio source. Unknown mime type"); + return false; + } + std::optional audioAttributes{createAudioAttributes(source)}; + if (!audioAttributes) + { + RIALTO_SERVER_LOG_ERROR("Failed to create audio attributes"); + return false; + } + + long long currentDispPts = getPosition(m_context.pipeline); // NOLINT(runtime/int) + GstCaps *caps{createCapsFromMediaSource(m_gstWrapper, m_glibWrapper, source)}; + GstAppSrc *appSrc{GST_APP_SRC(m_context.streamInfo[source->getType()].appSrc)}; + GstCaps *oldCaps = m_gstWrapper->gstAppSrcGetCaps(appSrc); + if ((!oldCaps) || (!m_gstWrapper->gstCapsIsEqual(caps, oldCaps))) + { + RIALTO_SERVER_LOG_DEBUG("Caps not equal. Perform audio track codec channel switch."); + int sampleAttributes{ + 0}; // rdk_gstreamer_utils::performAudioTrackCodecChannelSwitch checks if this param != NULL only. + std::uint32_t status{0}; // must be 0 to make rdk_gstreamer_utils::performAudioTrackCodecChannelSwitch work + unsigned int ui32Delay{0}; // output param + long long audioChangeTargetPts{-1}; // NOLINT(runtime/int) output param. Set audioChangeTargetPts = + // currentDispPts in rdk_gstreamer_utils function stub + unsigned int audioChangeStage{0}; // Output param. Set to AUDCHG_ALIGN in rdk_gstreamer_utils function stub + gchar *oldCapsCStr = m_gstWrapper->gstCapsToString(oldCaps); + std::string oldCapsStr = std::string(oldCapsCStr); + m_glibWrapper->gFree(oldCapsCStr); + bool audioAac{oldCapsStr.find("audio/mpeg") != std::string::npos}; + bool svpEnabled{true}; // assume always true + bool retVal{false}; // Output param. Set to TRUE in rdk_gstreamer_utils function stub + bool result = + m_rdkGstreamerUtilsWrapper + ->performAudioTrackCodecChannelSwitch(&m_context.playbackGroup, &sampleAttributes, &(*audioAttributes), + &status, &ui32Delay, &audioChangeTargetPts, ¤tDispPts, + &audioChangeStage, + &caps, // may fail for amlogic - that implementation changes + // this parameter, it's probably used by Netflix later + &audioAac, svpEnabled, GST_ELEMENT(appSrc), &retVal); + + if (!result || !retVal) + { + RIALTO_SERVER_LOG_WARN("performAudioTrackCodecChannelSwitch failed! Result: %d, retval %d", result, retVal); + } + } + else + { + RIALTO_SERVER_LOG_DEBUG("Skip switching audio source - caps are the same."); + } + + m_context.lastAudioSampleTimestamps = currentDispPts; + if (caps) + m_gstWrapper->gstCapsUnref(caps); + if (oldCaps) + m_gstWrapper->gstCapsUnref(oldCaps); + + return true; +} + +bool GstGenericPlayer::hasSourceType(const MediaSourceType &mediaSourceType) const +{ + return m_context.streamInfo.find(mediaSourceType) != m_context.streamInfo.end(); +} + +void GstGenericPlayer::scheduleNeedMediaData(GstAppSrc *src) +{ + if (m_workerThread) + { + if (m_scheduledNeedDatas.isNeedDataScheduled(src)) + { + return; + } + m_scheduledNeedDatas.setNeedDataScheduled(src); + m_workerThread->enqueueTask(m_taskFactory->createNeedData(m_context, *this, src)); + } +} + +void GstGenericPlayer::scheduleEnoughData(GstAppSrc *src) +{ + if (m_workerThread) + { + clearNeedDataScheduled(src); + m_workerThread->enqueueTask(m_taskFactory->createEnoughData(m_context, src)); + } +} + +void GstGenericPlayer::scheduleAudioUnderflow() +{ + if (m_workerThread) + { + bool underflowEnabled = m_context.isPlaying && !m_context.audioSourceRemoved; + m_workerThread->enqueueTask( + m_taskFactory->createUnderflow(m_context, *this, underflowEnabled, MediaSourceType::AUDIO)); + } +} + +void GstGenericPlayer::scheduleVideoUnderflow() +{ + if (m_workerThread) + { + bool underflowEnabled = m_context.isPlaying; + m_workerThread->enqueueTask( + m_taskFactory->createUnderflow(m_context, *this, underflowEnabled, MediaSourceType::VIDEO)); + } +} + +void GstGenericPlayer::scheduleAllSourcesAttached() +{ + allSourcesAttached(); +} + +void GstGenericPlayer::cancelUnderflow(firebolt::rialto::MediaSourceType mediaSource) +{ + auto elem = m_context.streamInfo.find(mediaSource); + if (elem != m_context.streamInfo.end()) + { + StreamInfo &streamInfo = elem->second; + if (!streamInfo.underflowOccured) + { + return; + } + + RIALTO_SERVER_LOG_DEBUG("Cancelling %s underflow", common::convertMediaSourceType(mediaSource)); + streamInfo.underflowOccured = false; + } +} + +void GstGenericPlayer::play() +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createPlay(*this)); + } +} + +void GstGenericPlayer::pause() +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createPause(m_context, *this)); + } +} + +void GstGenericPlayer::stop() +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createStop(m_context, *this)); + } +} + +bool GstGenericPlayer::changePipelineState(GstState newState) +{ + if (!m_context.pipeline) + { + RIALTO_SERVER_LOG_ERROR("Change state failed - pipeline is nullptr"); + if (m_gstPlayerClient) + m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); + return false; + } + if (m_gstWrapper->gstElementSetState(m_context.pipeline, newState) == GST_STATE_CHANGE_FAILURE) + { + RIALTO_SERVER_LOG_ERROR("Change state failed - Gstreamer returned an error"); + if (m_gstPlayerClient) + m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); + return false; + } + return true; +} + +int64_t GstGenericPlayer::getPosition(GstElement *element) +{ + if (!element) + { + RIALTO_SERVER_LOG_WARN("Element is null"); + return -1; + } + + if (m_flushWatcher->isFlushOngoing()) + { + RIALTO_SERVER_LOG_WARN("Can't get position while flush is ongoing"); + return -1; + } + + m_gstWrapper->gstStateLock(element); + + const auto kElementState{m_gstWrapper->gstElementGetState(element)}; + const auto kStateChangeReturn{m_gstWrapper->gstElementGetStateReturn(element)}; + const auto kNextState{m_gstWrapper->gstElementGetStateNext(element)}; + if (kElementState < GST_STATE_PAUSED || + (kStateChangeReturn == GST_STATE_CHANGE_ASYNC && kNextState == GST_STATE_PAUSED)) + { + RIALTO_SERVER_LOG_WARN("Element is prerolling or in invalid state - state: %s, return: %s, next: %s", + m_gstWrapper->gstElementStateGetName(kElementState), + m_gstWrapper->gstElementStateChangeReturnGetName(kStateChangeReturn), + m_gstWrapper->gstElementStateGetName(kNextState)); + + m_gstWrapper->gstStateUnlock(element); + return -1; + } + m_gstWrapper->gstStateUnlock(element); + + gint64 position = -1; + if (!m_gstWrapper->gstElementQueryPosition(m_context.pipeline, GST_FORMAT_TIME, &position)) + { + RIALTO_SERVER_LOG_WARN("Failed to query position"); + return -1; + } + + return position; +} + +void GstGenericPlayer::setVideoGeometry(int x, int y, int width, int height) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask( + m_taskFactory->createSetVideoGeometry(m_context, *this, Rectangle{x, y, width, height})); + } +} + +void GstGenericPlayer::setEos(const firebolt::rialto::MediaSourceType &type) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createEos(m_context, *this, type)); + } +} + +bool GstGenericPlayer::setVideoSinkRectangle() +{ + bool result = false; + GstElement *videoSink{getSink(MediaSourceType::VIDEO)}; + if (videoSink) + { + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(videoSink), "rectangle")) + { + std::string rect = + std::to_string(m_context.pendingGeometry.x) + ',' + std::to_string(m_context.pendingGeometry.y) + ',' + + std::to_string(m_context.pendingGeometry.width) + ',' + std::to_string(m_context.pendingGeometry.height); + m_glibWrapper->gObjectSet(videoSink, "rectangle", rect.c_str(), nullptr); + m_context.pendingGeometry.clear(); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set the video rectangle"); + } + m_gstWrapper->gstObjectUnref(videoSink); + } + + return result; +} + +bool GstGenericPlayer::setImmediateOutput() +{ + bool result{false}; + if (m_context.pendingImmediateOutputForVideo.has_value()) + { + GstElement *sink{getSink(MediaSourceType::VIDEO)}; + if (sink) + { + bool immediateOutput{m_context.pendingImmediateOutputForVideo.value()}; + RIALTO_SERVER_LOG_DEBUG("Set immediate-output to %s", immediateOutput ? "TRUE" : "FALSE"); + + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "immediate-output")) + { + gboolean immediateOutputGboolean{immediateOutput ? TRUE : FALSE}; + m_glibWrapper->gObjectSet(sink, "immediate-output", immediateOutputGboolean, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set immediate-output property on sink '%s'", GST_ELEMENT_NAME(sink)); + } + m_context.pendingImmediateOutputForVideo.reset(); + m_gstWrapper->gstObjectUnref(sink); + } + else + { + RIALTO_SERVER_LOG_DEBUG("Pending an immediate-output, sink is NULL"); + } + } + return result; +} + +bool GstGenericPlayer::setShowVideoWindow() +{ + if (!m_context.pendingShowVideoWindow.has_value()) + { + RIALTO_SERVER_LOG_WARN("No show video window value to be set. Aborting..."); + return false; + } + + GstElement *videoSink{getSink(MediaSourceType::VIDEO)}; + if (!videoSink) + { + RIALTO_SERVER_LOG_DEBUG("Setting show video window queued. Video sink is NULL"); + return false; + } + bool result{false}; + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(videoSink), "show-video-window")) + { + m_glibWrapper->gObjectSet(videoSink, "show-video-window", m_context.pendingShowVideoWindow.value(), nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Setting show video window failed. Property does not exist"); + } + m_context.pendingShowVideoWindow.reset(); + m_gstWrapper->gstObjectUnref(GST_OBJECT(videoSink)); + return result; +} + +bool GstGenericPlayer::setLowLatency() +{ + bool result{false}; + if (m_context.pendingLowLatency.has_value()) + { + GstElement *sink{getSink(MediaSourceType::AUDIO)}; + if (sink) + { + bool lowLatency{m_context.pendingLowLatency.value()}; + RIALTO_SERVER_LOG_DEBUG("Set low-latency to %s", lowLatency ? "TRUE" : "FALSE"); + + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "low-latency")) + { + gboolean lowLatencyGboolean{lowLatency ? TRUE : FALSE}; + m_glibWrapper->gObjectSet(sink, "low-latency", lowLatencyGboolean, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set low-latency property on sink '%s'", GST_ELEMENT_NAME(sink)); + } + m_context.pendingLowLatency.reset(); + m_gstWrapper->gstObjectUnref(sink); + } + else + { + RIALTO_SERVER_LOG_DEBUG("Pending low-latency, sink is NULL"); + } + } + return result; +} + +bool GstGenericPlayer::setSync() +{ + bool result{false}; + if (m_context.pendingSync.has_value()) + { + GstElement *sink{getSink(MediaSourceType::AUDIO)}; + if (sink) + { + bool sync{m_context.pendingSync.value()}; + RIALTO_SERVER_LOG_DEBUG("Set sync to %s", sync ? "TRUE" : "FALSE"); + + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "sync")) + { + gboolean syncGboolean{sync ? TRUE : FALSE}; + m_glibWrapper->gObjectSet(sink, "sync", syncGboolean, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set sync property on sink '%s'", GST_ELEMENT_NAME(sink)); + } + m_context.pendingSync.reset(); + m_gstWrapper->gstObjectUnref(sink); + } + else + { + RIALTO_SERVER_LOG_DEBUG("Pending sync, sink is NULL"); + } + } + return result; +} + +bool GstGenericPlayer::setSyncOff() +{ + bool result{false}; + if (m_context.pendingSyncOff.has_value()) + { + GstElement *decoder = getDecoder(MediaSourceType::AUDIO); + if (decoder) + { + bool syncOff{m_context.pendingSyncOff.value()}; + RIALTO_SERVER_LOG_DEBUG("Set sync-off to %s", syncOff ? "TRUE" : "FALSE"); + + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "sync-off")) + { + gboolean syncOffGboolean{decoder ? TRUE : FALSE}; + m_glibWrapper->gObjectSet(decoder, "sync-off", syncOffGboolean, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set sync-off property on decoder '%s'", GST_ELEMENT_NAME(decoder)); + } + m_context.pendingSyncOff.reset(); + m_gstWrapper->gstObjectUnref(decoder); + } + else + { + RIALTO_SERVER_LOG_DEBUG("Pending sync-off, decoder is NULL"); + } + } + return result; +} + +bool GstGenericPlayer::setStreamSyncMode(const MediaSourceType &type) +{ + bool result{false}; + int32_t streamSyncMode{0}; + { + std::unique_lock lock{m_context.propertyMutex}; + if (m_context.pendingStreamSyncMode.find(type) == m_context.pendingStreamSyncMode.end()) + { + return false; + } + streamSyncMode = m_context.pendingStreamSyncMode[type]; + } + if (MediaSourceType::AUDIO == type) + { + GstElement *decoder = getDecoder(MediaSourceType::AUDIO); + if (!decoder) + { + RIALTO_SERVER_LOG_DEBUG("Pending stream-sync-mode, decoder is NULL"); + return false; + } + + RIALTO_SERVER_LOG_DEBUG("Set stream-sync-mode to %d", streamSyncMode); + + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "stream-sync-mode")) + { + gint streamSyncModeGint{static_cast(streamSyncMode)}; + m_glibWrapper->gObjectSet(decoder, "stream-sync-mode", streamSyncModeGint, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set stream-sync-mode property on decoder '%s'", GST_ELEMENT_NAME(decoder)); + } + m_gstWrapper->gstObjectUnref(decoder); + std::unique_lock lock{m_context.propertyMutex}; + m_context.pendingStreamSyncMode.erase(type); + } + else if (MediaSourceType::VIDEO == type) + { + GstElement *parser = getParser(MediaSourceType::VIDEO); + if (!parser) + { + RIALTO_SERVER_LOG_DEBUG("Pending syncmode-streaming, parser is NULL"); + return false; + } + + gboolean streamSyncModeBoolean{static_cast(streamSyncMode)}; + RIALTO_SERVER_LOG_DEBUG("Set syncmode-streaming to %d", streamSyncMode); + + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(parser), "syncmode-streaming")) + { + m_glibWrapper->gObjectSet(parser, "syncmode-streaming", streamSyncModeBoolean, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set syncmode-streaming property on parser '%s'", GST_ELEMENT_NAME(parser)); + } + m_gstWrapper->gstObjectUnref(parser); + std::unique_lock lock{m_context.propertyMutex}; + m_context.pendingStreamSyncMode.erase(type); + } + return result; +} + +bool GstGenericPlayer::setRenderFrame() +{ + bool result{false}; + if (m_context.pendingRenderFrame) + { + static const std::string kStepOnPrerollPropertyName = "frame-step-on-preroll"; + GstElement *sink{getSink(MediaSourceType::VIDEO)}; + if (sink) + { + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), kStepOnPrerollPropertyName.c_str())) + { + RIALTO_SERVER_LOG_INFO("Rendering preroll"); + + m_glibWrapper->gObjectSet(sink, kStepOnPrerollPropertyName.c_str(), 1, nullptr); + m_gstWrapper->gstElementSendEvent(sink, m_gstWrapper->gstEventNewStep(GST_FORMAT_BUFFERS, 1, 1.0, true, + false)); + m_glibWrapper->gObjectSet(sink, kStepOnPrerollPropertyName.c_str(), 0, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Video sink doesn't have property `%s`", kStepOnPrerollPropertyName.c_str()); + } + m_gstWrapper->gstObjectUnref(sink); + m_context.pendingRenderFrame = false; + } + else + { + RIALTO_SERVER_LOG_DEBUG("Pending render frame, sink is NULL"); + } + } + return result; +} + +bool GstGenericPlayer::setBufferingLimit() +{ + bool result{false}; + guint bufferingLimit{0}; + { + std::unique_lock lock{m_context.propertyMutex}; + if (!m_context.pendingBufferingLimit.has_value()) + { + return false; + } + bufferingLimit = static_cast(m_context.pendingBufferingLimit.value()); + } + + GstElement *decoder{getDecoder(MediaSourceType::AUDIO)}; + if (decoder) + { + RIALTO_SERVER_LOG_DEBUG("Set limit-buffering-ms to %u", bufferingLimit); + + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "limit-buffering-ms")) + { + m_glibWrapper->gObjectSet(decoder, "limit-buffering-ms", bufferingLimit, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set limit-buffering-ms property on decoder '%s'", + GST_ELEMENT_NAME(decoder)); + } + m_gstWrapper->gstObjectUnref(decoder); + std::unique_lock lock{m_context.propertyMutex}; + m_context.pendingBufferingLimit.reset(); + } + else + { + RIALTO_SERVER_LOG_DEBUG("Pending limit-buffering-ms, decoder is NULL"); + } + return result; +} + +bool GstGenericPlayer::setUseBuffering() +{ + std::unique_lock lock{m_context.propertyMutex}; + if (m_context.pendingUseBuffering.has_value()) + { + if (m_context.playbackGroup.m_curAudioDecodeBin) + { + gboolean useBufferingGboolean{m_context.pendingUseBuffering.value() ? TRUE : FALSE}; + RIALTO_SERVER_LOG_DEBUG("Set use-buffering to %d", useBufferingGboolean); + m_glibWrapper->gObjectSet(m_context.playbackGroup.m_curAudioDecodeBin, "use-buffering", + useBufferingGboolean, nullptr); + m_context.pendingUseBuffering.reset(); + return true; + } + else + { + RIALTO_SERVER_LOG_DEBUG("Pending use-buffering, decodebin is NULL"); + } + } + return false; +} + +bool GstGenericPlayer::setWesterossinkSecondaryVideo() +{ + bool result = false; + GstElementFactory *factory = m_gstWrapper->gstElementFactoryFind("westerossink"); + if (factory) + { + GstElement *videoSink = m_gstWrapper->gstElementFactoryCreate(factory, nullptr); + if (videoSink) + { + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(videoSink), "res-usage")) + { + m_glibWrapper->gObjectSet(videoSink, "res-usage", 0x0u, nullptr); + m_glibWrapper->gObjectSet(m_context.pipeline, "video-sink", videoSink, nullptr); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to set the westerossink res-usage"); + m_gstWrapper->gstObjectUnref(GST_OBJECT(videoSink)); + } + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to create the westerossink"); + } + + m_gstWrapper->gstObjectUnref(GST_OBJECT(factory)); + } + else + { + // No westeros sink + result = true; + } + + return result; +} + +bool GstGenericPlayer::setErmContext() +{ + bool result = false; + GstContext *context = m_gstWrapper->gstContextNew("erm", false); + if (context) + { + GstStructure *contextStructure = m_gstWrapper->gstContextWritableStructure(context); + if (contextStructure) + { + m_gstWrapper->gstStructureSet(contextStructure, "res-usage", G_TYPE_UINT, 0x0u, nullptr); + m_gstWrapper->gstElementSetContext(GST_ELEMENT(m_context.pipeline), context); + result = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to create the erm structure"); + } + m_gstWrapper->gstContextUnref(context); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to create the erm context"); + } + + return result; +} + +void GstGenericPlayer::startPositionReportingAndCheckAudioUnderflowTimer() +{ + if (m_positionReportingAndCheckAudioUnderflowTimer && m_positionReportingAndCheckAudioUnderflowTimer->isActive()) + { + return; + } + + m_positionReportingAndCheckAudioUnderflowTimer = m_timerFactory->createTimer( + kPositionReportTimerMs, + [this]() + { + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createReportPosition(m_context, *this)); + m_workerThread->enqueueTask(m_taskFactory->createCheckAudioUnderflow(m_context, *this)); + } + }, + firebolt::rialto::common::TimerType::PERIODIC); +} + +void GstGenericPlayer::stopPositionReportingAndCheckAudioUnderflowTimer() +{ + if (m_positionReportingAndCheckAudioUnderflowTimer && m_positionReportingAndCheckAudioUnderflowTimer->isActive()) + { + m_positionReportingAndCheckAudioUnderflowTimer->cancel(); + m_positionReportingAndCheckAudioUnderflowTimer.reset(); + } +} + +void GstGenericPlayer::startSubtitleClockResyncTimer() +{ + if (m_subtitleClockResyncTimer && m_subtitleClockResyncTimer->isActive()) + { + return; + } + + m_subtitleClockResyncTimer = m_timerFactory->createTimer( + kSubtitleClockResyncInterval, + [this]() + { + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSynchroniseSubtitleClock(m_context, *this)); + } + }, + firebolt::rialto::common::TimerType::PERIODIC); +} + +void GstGenericPlayer::stopSubtitleClockResyncTimer() +{ + if (m_subtitleClockResyncTimer && m_subtitleClockResyncTimer->isActive()) + { + m_subtitleClockResyncTimer->cancel(); + m_subtitleClockResyncTimer.reset(); + } +} + +void GstGenericPlayer::stopWorkerThread() +{ + if (m_workerThread) + { + m_workerThread->stop(); + } +} + +void GstGenericPlayer::setPendingPlaybackRate() +{ + RIALTO_SERVER_LOG_INFO("Setting pending playback rate"); + setPlaybackRate(m_context.pendingPlaybackRate); +} + +void GstGenericPlayer::renderFrame() +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createRenderFrame(m_context, *this)); + } +} + +void GstGenericPlayer::setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask( + m_taskFactory->createSetVolume(m_context, *this, targetVolume, volumeDuration, easeType)); + } +} + +bool GstGenericPlayer::getVolume(double ¤tVolume) +{ + // We are on main thread here, but m_context.pipeline can be used, because it's modified only in GstGenericPlayer + // constructor and destructor. GstGenericPlayer is created/destructed on main thread, so we won't have a crash here. + if (!m_context.pipeline) + { + return false; + } + + // NOTE: No gstreamer documentation for "fade-volume" could be found at the time this code was written. + // Therefore the author performed several tests on a supported platform (Flex2) to determine the behaviour of this property. + // The code has been written to be backwardly compatible on platforms that don't have this property. + // The observed behaviour was: + // - if the returned fade volume is negative then audio-fade is not active. In this case the usual technique + // to find volume in the pipeline works and is used. + // - if the returned fade volume is positive then audio-fade is active. In this case the returned fade volume + // directly returns the current volume level 0=min to 100=max (and the pipeline's current volume level is + // meaningless and doesn't contribute in this case). + GstElement *sink{getSink(MediaSourceType::AUDIO)}; + if (m_context.audioFadeEnabled && sink && + m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "fade-volume")) + { + gint fadeVolume{-100}; + m_glibWrapper->gObjectGet(sink, "fade-volume", &fadeVolume, NULL); + if (fadeVolume < 0) + { + currentVolume = m_gstWrapper->gstStreamVolumeGetVolume(GST_STREAM_VOLUME(m_context.pipeline), + GST_STREAM_VOLUME_FORMAT_LINEAR); + RIALTO_SERVER_LOG_INFO("Fade volume is negative, using volume from pipeline: %f", currentVolume); + } + else + { + currentVolume = static_cast(fadeVolume) / 100.0; + RIALTO_SERVER_LOG_INFO("Fade volume is supported: %f", currentVolume); + } + } + else + { + currentVolume = m_gstWrapper->gstStreamVolumeGetVolume(GST_STREAM_VOLUME(m_context.pipeline), + GST_STREAM_VOLUME_FORMAT_LINEAR); + RIALTO_SERVER_LOG_INFO("Fade volume is not supported, using volume from pipeline: %f", currentVolume); + } + + if (sink) + m_gstWrapper->gstObjectUnref(sink); + + return true; +} + +void GstGenericPlayer::setMute(const MediaSourceType &mediaSourceType, bool mute) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetMute(m_context, *this, mediaSourceType, mute)); + } +} + +bool GstGenericPlayer::getMute(const MediaSourceType &mediaSourceType, bool &mute) +{ + // We are on main thread here, but m_context.pipeline can be used, because it's modified only in GstGenericPlayer + // constructor and destructor. GstGenericPlayer is created/destructed on main thread, so we won't have a crash here. + if (mediaSourceType == MediaSourceType::SUBTITLE) + { + if (!m_context.subtitleSink) + { + RIALTO_SERVER_LOG_ERROR("There is no subtitle sink"); + return false; + } + gboolean muteValue{FALSE}; + m_glibWrapper->gObjectGet(m_context.subtitleSink, "mute", &muteValue, nullptr); + mute = muteValue; + } + else if (mediaSourceType == MediaSourceType::AUDIO) + { + if (!m_context.pipeline) + { + return false; + } + mute = m_gstWrapper->gstStreamVolumeGetMute(GST_STREAM_VOLUME(m_context.pipeline)); + } + else + { + RIALTO_SERVER_LOG_ERROR("Getting mute for type %s unsupported", common::convertMediaSourceType(mediaSourceType)); + return false; + } + + return true; +} + +bool GstGenericPlayer::isAsync(const MediaSourceType &mediaSourceType) const +{ + GstElement *sink = getSink(mediaSourceType); + if (!sink) + { + RIALTO_SERVER_LOG_WARN("Sink not found for %s", common::convertMediaSourceType(mediaSourceType)); + return true; // Our sinks are async by default + } + gboolean returnValue{TRUE}; + m_glibWrapper->gObjectGet(sink, "async", &returnValue, nullptr); + m_gstWrapper->gstObjectUnref(sink); + return returnValue == TRUE; +} + +void GstGenericPlayer::setTextTrackIdentifier(const std::string &textTrackIdentifier) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetTextTrackIdentifier(m_context, textTrackIdentifier)); + } +} + +bool GstGenericPlayer::getTextTrackIdentifier(std::string &textTrackIdentifier) +{ + if (!m_context.subtitleSink) + { + RIALTO_SERVER_LOG_ERROR("There is no subtitle sink"); + return false; + } + + gchar *identifier = nullptr; + m_glibWrapper->gObjectGet(m_context.subtitleSink, "text-track-identifier", &identifier, nullptr); + + if (identifier) + { + textTrackIdentifier = identifier; + m_glibWrapper->gFree(identifier); + return true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to get text track identifier"); + return false; + } +} + +bool GstGenericPlayer::setLowLatency(bool lowLatency) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetLowLatency(m_context, *this, lowLatency)); + } + return true; +} + +bool GstGenericPlayer::setSync(bool sync) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetSync(m_context, *this, sync)); + } + return true; +} + +bool GstGenericPlayer::getSync(bool &sync) +{ + bool returnValue{false}; + GstElement *sink{getSink(MediaSourceType::AUDIO)}; + if (sink) + { + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "sync")) + { + m_glibWrapper->gObjectGet(sink, "sync", &sync, nullptr); + returnValue = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Sync not supported in sink '%s'", GST_ELEMENT_NAME(sink)); + } + m_gstWrapper->gstObjectUnref(sink); + } + else if (m_context.pendingSync.has_value()) + { + RIALTO_SERVER_LOG_DEBUG("Returning queued value"); + sync = m_context.pendingSync.value(); + returnValue = true; + } + else + { + // We dont know the default setting on the sync, so return failure here + RIALTO_SERVER_LOG_WARN("No audio sink attached or queued value"); + } + + return returnValue; +} + +bool GstGenericPlayer::setSyncOff(bool syncOff) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetSyncOff(m_context, *this, syncOff)); + } + return true; +} + +bool GstGenericPlayer::setStreamSyncMode(const MediaSourceType &mediaSourceType, int32_t streamSyncMode) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask( + m_taskFactory->createSetStreamSyncMode(m_context, *this, mediaSourceType, streamSyncMode)); + } + return true; +} + +bool GstGenericPlayer::getStreamSyncMode(int32_t &streamSyncMode) +{ + bool returnValue{false}; + GstElement *decoder = getDecoder(MediaSourceType::AUDIO); + if (decoder && m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "stream-sync-mode")) + { + m_glibWrapper->gObjectGet(decoder, "stream-sync-mode", &streamSyncMode, nullptr); + returnValue = true; + } + else + { + std::unique_lock lock{m_context.propertyMutex}; + if (m_context.pendingStreamSyncMode.find(MediaSourceType::AUDIO) != m_context.pendingStreamSyncMode.end()) + { + RIALTO_SERVER_LOG_DEBUG("Returning queued value"); + streamSyncMode = m_context.pendingStreamSyncMode[MediaSourceType::AUDIO]; + returnValue = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Stream sync mode not supported in decoder '%s'", + (decoder ? GST_ELEMENT_NAME(decoder) : "null")); + } + } + + if (decoder) + m_gstWrapper->gstObjectUnref(GST_OBJECT(decoder)); + + return returnValue; +} + +void GstGenericPlayer::ping(std::unique_ptr &&heartbeatHandler) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createPing(std::move(heartbeatHandler))); + } +} + +void GstGenericPlayer::flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) +{ + if (m_workerThread) + { + async = isAsync(mediaSourceType); + m_flushWatcher->setFlushing(mediaSourceType, async); + m_workerThread->enqueueTask(m_taskFactory->createFlush(m_context, *this, mediaSourceType, resetTime)); + } +} + +void GstGenericPlayer::setSourcePosition(const MediaSourceType &mediaSourceType, int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetSourcePosition(m_context, *this, mediaSourceType, position, + resetTime, appliedRate, stopPosition)); + } +} + +void GstGenericPlayer::setSubtitleOffset(int64_t position) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetSubtitleOffset(m_context, position)); + } +} + +void GstGenericPlayer::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask( + m_taskFactory->createProcessAudioGap(m_context, position, duration, discontinuityGap, audioAac)); + } +} + +void GstGenericPlayer::setBufferingLimit(uint32_t limitBufferingMs) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetBufferingLimit(m_context, *this, limitBufferingMs)); + } +} + +bool GstGenericPlayer::getBufferingLimit(uint32_t &limitBufferingMs) +{ + bool returnValue{false}; + GstElement *decoder = getDecoder(MediaSourceType::AUDIO); + if (decoder && m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "limit-buffering-ms")) + { + m_glibWrapper->gObjectGet(decoder, "limit-buffering-ms", &limitBufferingMs, nullptr); + returnValue = true; + } + else + { + std::unique_lock lock{m_context.propertyMutex}; + if (m_context.pendingBufferingLimit.has_value()) + { + RIALTO_SERVER_LOG_DEBUG("Returning queued value"); + limitBufferingMs = m_context.pendingBufferingLimit.value(); + returnValue = true; + } + else + { + RIALTO_SERVER_LOG_ERROR("buffering limit not supported in decoder '%s'", + (decoder ? GST_ELEMENT_NAME(decoder) : "null")); + } + } + + if (decoder) + m_gstWrapper->gstObjectUnref(GST_OBJECT(decoder)); + + return returnValue; +} + +void GstGenericPlayer::setUseBuffering(bool useBuffering) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSetUseBuffering(m_context, *this, useBuffering)); + } +} + +bool GstGenericPlayer::getUseBuffering(bool &useBuffering) +{ + if (m_context.playbackGroup.m_curAudioDecodeBin) + { + m_glibWrapper->gObjectGet(m_context.playbackGroup.m_curAudioDecodeBin, "use-buffering", &useBuffering, nullptr); + return true; + } + else + { + std::unique_lock lock{m_context.propertyMutex}; + if (m_context.pendingUseBuffering.has_value()) + { + RIALTO_SERVER_LOG_DEBUG("Returning queued value"); + useBuffering = m_context.pendingUseBuffering.value(); + return true; + } + } + return false; +} + +void GstGenericPlayer::switchSource(const std::unique_ptr &mediaSource) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createSwitchSource(*this, mediaSource)); + } +} + +void GstGenericPlayer::handleBusMessage(GstMessage *message, bool priority) +{ + if (priority) + { + m_workerThread->enqueuePriorityTask( + m_taskFactory->createHandleBusMessage(m_context, *this, message, *m_flushWatcher)); + } + else + { + m_workerThread->enqueueTask(m_taskFactory->createHandleBusMessage(m_context, *this, message, *m_flushWatcher)); + } +} + +void GstGenericPlayer::updatePlaybackGroup(GstElement *typefind, const GstCaps *caps) +{ + m_workerThread->enqueueTask(m_taskFactory->createUpdatePlaybackGroup(m_context, *this, typefind, caps)); +} + +void GstGenericPlayer::addAutoVideoSinkChild(GObject *object) +{ + // Only add children that are sinks + if (GST_OBJECT_FLAG_IS_SET(GST_ELEMENT(object), GST_ELEMENT_FLAG_SINK)) + { + RIALTO_SERVER_LOG_DEBUG("Store AutoVideoSink child sink"); + + if (m_context.autoVideoChildSink && m_context.autoVideoChildSink != GST_ELEMENT(object)) + { + RIALTO_SERVER_LOG_MIL("AutoVideoSink child is been overwritten"); + } + m_context.autoVideoChildSink = GST_ELEMENT(object); + } +} + +void GstGenericPlayer::addAutoAudioSinkChild(GObject *object) +{ + // Only add children that are sinks + if (GST_OBJECT_FLAG_IS_SET(GST_ELEMENT(object), GST_ELEMENT_FLAG_SINK)) + { + RIALTO_SERVER_LOG_DEBUG("Store AutoAudioSink child sink"); + + if (m_context.autoAudioChildSink && m_context.autoAudioChildSink != GST_ELEMENT(object)) + { + RIALTO_SERVER_LOG_MIL("AutoAudioSink child is been overwritten"); + } + m_context.autoAudioChildSink = GST_ELEMENT(object); + } +} + +void GstGenericPlayer::removeAutoVideoSinkChild(GObject *object) +{ + if (GST_OBJECT_FLAG_IS_SET(GST_ELEMENT(object), GST_ELEMENT_FLAG_SINK)) + { + RIALTO_SERVER_LOG_DEBUG("Remove AutoVideoSink child sink"); + + if (m_context.autoVideoChildSink && m_context.autoVideoChildSink != GST_ELEMENT(object)) + { + RIALTO_SERVER_LOG_MIL("AutoVideoSink child sink is not the same as the one stored"); + return; + } + + m_context.autoVideoChildSink = nullptr; + } +} + +void GstGenericPlayer::removeAutoAudioSinkChild(GObject *object) +{ + if (GST_OBJECT_FLAG_IS_SET(GST_ELEMENT(object), GST_ELEMENT_FLAG_SINK)) + { + RIALTO_SERVER_LOG_DEBUG("Remove AutoAudioSink child sink"); + + if (m_context.autoAudioChildSink && m_context.autoAudioChildSink != GST_ELEMENT(object)) + { + RIALTO_SERVER_LOG_MIL("AutoAudioSink child sink is not the same as the one stored"); + return; + } + + m_context.autoAudioChildSink = nullptr; + } +} + +GstElement *GstGenericPlayer::getSinkChildIfAutoVideoSink(GstElement *sink) const +{ + const gchar *kTmpName = m_glibWrapper->gTypeName(G_OBJECT_TYPE(sink)); + if (!kTmpName) + return sink; + + const std::string kElementTypeName{kTmpName}; + if (kElementTypeName == "GstAutoVideoSink") + { + if (!m_context.autoVideoChildSink) + { + RIALTO_SERVER_LOG_WARN("No child sink has been added to the autovideosink"); + } + else + { + return m_context.autoVideoChildSink; + } + } + return sink; +} + +GstElement *GstGenericPlayer::getSinkChildIfAutoAudioSink(GstElement *sink) const +{ + const gchar *kTmpName = m_glibWrapper->gTypeName(G_OBJECT_TYPE(sink)); + if (!kTmpName) + return sink; + + const std::string kElementTypeName{kTmpName}; + if (kElementTypeName == "GstAutoAudioSink") + { + if (!m_context.autoAudioChildSink) + { + RIALTO_SERVER_LOG_WARN("No child sink has been added to the autoaudiosink"); + } + else + { + return m_context.autoAudioChildSink; + } + } + return sink; +} + +void GstGenericPlayer::setPlaybinFlags(bool enableAudio) +{ + unsigned flags = getGstPlayFlag("video") | getGstPlayFlag("native-video") | getGstPlayFlag("text"); + + if (enableAudio) + { + flags |= getGstPlayFlag("audio"); + flags |= shouldEnableNativeAudio() ? getGstPlayFlag("native-audio") : 0; + } + + m_glibWrapper->gObjectSet(m_context.pipeline, "flags", flags, nullptr); +} + +bool GstGenericPlayer::shouldEnableNativeAudio() +{ + GstElementFactory *factory = m_gstWrapper->gstElementFactoryFind("brcmaudiosink"); + if (factory) + { + m_gstWrapper->gstObjectUnref(GST_OBJECT(factory)); + return true; + } + return false; +} + +void GstGenericPlayer::clearNeedDataScheduled(GstAppSrc *src) +{ + m_scheduledNeedDatas.clearNeedDataScheduled(src); +} +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstInitialiser.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstInitialiser.cpp new file mode 100644 index 000000000..087358ee3 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstInitialiser.cpp @@ -0,0 +1,93 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GstInitialiser.h" +#include "GstLogForwarding.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server +{ +GstInitialiser::~GstInitialiser() +{ + if (m_thread.joinable()) + { + m_thread.join(); + } + +#ifdef FREE_MEM_BEFORE_EXIT + if (m_gstWrapper) + { + m_gstWrapper->gstDeinit(); + m_gstWrapper.reset(); + } +#endif +} + +IGstInitialiser &IGstInitialiser::instance() +{ + static GstInitialiser initialiser; + return initialiser; +} + +void GstInitialiser::initialise(int *argc, char ***argv) +{ + if (m_thread.joinable()) + { + RIALTO_SERVER_LOG_WARN("Gstreamer is already initialised, no need to do it twice..."); + return; + } + + m_thread = std::thread( + [=]() + { + std::shared_ptr factory = + firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); + m_gstWrapper = factory->getGstWrapper(); + + if (!m_gstWrapper) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gst wrapper"); + return; + } + + m_gstWrapper->gstInit(argc, argv); + + // remove rialto sinks from the registry + GstPlugin *rialtoPlugin = + m_gstWrapper->gstRegistryFindPlugin(m_gstWrapper->gstRegistryGet(), "rialtosinks"); + if (rialtoPlugin) + { + m_gstWrapper->gstRegistryRemovePlugin(m_gstWrapper->gstRegistryGet(), rialtoPlugin); + m_gstWrapper->gstObjectUnref(rialtoPlugin); + } + + enableGstLogForwarding(); + + std::unique_lock lock{m_mutex}; + m_isInitialised = true; + m_cv.notify_all(); + }); +} + +void GstInitialiser::waitForInitialisation() const +{ + std::unique_lock lock{m_mutex}; + m_cv.wait(lock, [this]() { return m_isInitialised; }); +} +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstLogForwarding.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstLogForwarding.cpp new file mode 100644 index 000000000..8d8f768ec --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstLogForwarding.cpp @@ -0,0 +1,117 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GstLogForwarding.h" +#include "RialtoLogging.h" +#include +#include + +namespace +{ +void gstreamerLogFunction(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, + gint line, GObject *object, GstDebugMessage *message, gpointer data) +{ + std::stringstream ss; + switch (level) + { + case GST_LEVEL_NONE: + case GST_LEVEL_ERROR: + { + ss << "ERR: "; + break; + } + case GST_LEVEL_WARNING: + { + ss << "WRN: "; + break; + } + case GST_LEVEL_FIXME: + { + ss << "FIXME: "; + break; + } + case GST_LEVEL_INFO: + { + ss << "NFO: "; + break; + } + case GST_LEVEL_DEBUG: + { + ss << "DBG: "; + break; + } + case GST_LEVEL_LOG: + { + ss << "LOG: "; + break; + } + case GST_LEVEL_TRACE: + { + ss << "TRACE: "; + break; + } + case GST_LEVEL_MEMDUMP: + { + ss << "MEMDUMP: "; + break; + } + case GST_LEVEL_COUNT: + { + ss << "COUNT: "; + break; + } + default: + { + break; + } + } + ss << "C:" << gst_debug_category_get_name(category) << " M:" << file << " F:" << function << ":" << line; + if (object) + { + if (GST_IS_PAD(object) && GST_OBJECT_NAME(object) && GST_OBJECT_PARENT(object) && + GST_OBJECT_NAME(GST_OBJECT_PARENT(object))) + { + ss << " <" << GST_OBJECT_NAME(GST_OBJECT_PARENT(object)) << ":" << GST_OBJECT_NAME(object) << ">"; + } + else if (GST_IS_OBJECT(object) && GST_OBJECT_NAME(object)) + { + ss << " <" << GST_OBJECT_NAME(object) << ">"; + } + else if (G_IS_OBJECT(object)) + { + ss << " <" << G_OBJECT_TYPE_NAME(object) << "@" << static_cast(object) << ">"; + } + else + { + ss << " <" << static_cast(object) << ">"; + } + } + ss << ": " << gst_debug_message_get(message); + RIALTO_LOG_EXTERNAL("%s", ss.str().c_str()); +} +} // namespace + +namespace firebolt::rialto::server +{ +void enableGstLogForwarding() +{ + gst_debug_remove_log_function(gst_debug_log_default); + gst_debug_add_log_function(gstreamerLogFunction, nullptr, nullptr); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadata.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadata.cpp new file mode 100644 index 000000000..bae8af817 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadata.cpp @@ -0,0 +1,92 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GstProtectionMetadata.h" +#include "RialtoServerLogging.h" +#include +#include + +static gboolean rialto_eme_protection_metadata_init(GstMeta *meta, gpointer params, // NOLINT(build/function_format) + GstBuffer *buffer) +{ + GstRialtoProtectionMetadata *emeta = reinterpret_cast(meta); + const GstRialtoProtectionData *data = static_cast(params); + emeta->data = *data; + + if (emeta->data.decryptionService) + { + emeta->data.decryptionService->incrementSessionIdUsageCounter(emeta->data.keySessionId); + } + + return true; +} + +static gboolean rialto_eme_protection_metadata_free(GstMeta *meta, GstBuffer *buffer) // NOLINT(build/function_format) +{ + GstRialtoProtectionMetadata *protectionMeta = reinterpret_cast(meta); + + if (protectionMeta->data.decryptionService) + { + protectionMeta->data.decryptionService->decrementSessionIdUsageCounter(protectionMeta->data.keySessionId); + } + + if (protectionMeta->data.subsamples) + { + gst_buffer_unref(protectionMeta->data.subsamples); + } + if (protectionMeta->data.iv) + { + gst_buffer_unref(protectionMeta->data.iv); + } + if (protectionMeta->data.key) + { + gst_buffer_unref(protectionMeta->data.key); + } + + return true; +} + +GST_EXPORT GType rialto_eme_protection_metadata_get_type() // NOLINT(build/function_format) +{ + static GType g_type; + static const gchar *api_tags[] = {"rialto", "protection", NULL}; + + if (g_once_init_enter(&g_type)) + { + GType _type = gst_meta_api_type_register("GstRialtoProtectionMetadataAPI", api_tags); + g_once_init_leave(&g_type, _type); + } + return g_type; +} + +const GstMetaInfo *rialto_mse_protection_metadata_get_info() // NOLINT(build/function_format) +{ + static const GstMetaInfo *kMetainfo = NULL; + if (g_once_init_enter(&kMetainfo)) + { + const GstMetaInfo *kGstMeta = + gst_meta_register(GST_RIALTO_PROTECTION_METADATA_GET_TYPE, "GstRialtoProtectionMetadata", + sizeof(GstRialtoProtectionMetadata), + (GstMetaInitFunction)rialto_eme_protection_metadata_init, + (GstMetaFreeFunction)rialto_eme_protection_metadata_free, (GstMetaTransformFunction)NULL); + + g_once_init_leave(&kMetainfo, kGstMeta); + } + return kMetainfo; +} diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadataHelper.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadataHelper.cpp new file mode 100644 index 000000000..b813cb429 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadataHelper.cpp @@ -0,0 +1,77 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GstProtectionMetadataHelper.h" +#include "GstProtectionMetadataHelperFactory.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server +{ +std::shared_ptr IGstProtectionMetadataHelperFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the protection metadata wrapper factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr GstProtectionMetadataHelperFactory::createProtectionMetadataWrapper( + const std::shared_ptr &gstWrapper) const +{ + return std::make_unique(gstWrapper); +} + +GstMeta *GstProtectionMetadataHelper::addProtectionMetadata(GstBuffer *gstBuffer, GstRialtoProtectionData &data) +{ + return m_gstWrapper->gstBufferAddMeta(gstBuffer, GST_RIALTO_PROTECTION_METADATA_INFO, &data); +} + +GstRialtoProtectionData *GstProtectionMetadataHelper::getProtectionMetadataData(GstBuffer *gstBuffer) +{ + GstMeta *meta = m_gstWrapper->gstBufferGetMeta(gstBuffer, GST_RIALTO_PROTECTION_METADATA_GET_TYPE); + if (!meta) + { + return nullptr; + } + + GstRialtoProtectionMetadata *protectionMetadata = reinterpret_cast(meta); + return &protectionMetadata->data; +} + +void GstProtectionMetadataHelper::removeProtectionMetadata(GstBuffer *gstBuffer) +{ + GstMeta *meta = m_gstWrapper->gstBufferGetMeta(gstBuffer, GST_RIALTO_PROTECTION_METADATA_GET_TYPE); + if (meta) + { + if (!m_gstWrapper->gstBufferRemoveMeta(gstBuffer, meta)) + { + RIALTO_SERVER_LOG_ERROR("Failed to remove metadata"); + } + } +} + +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstSrc.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstSrc.cpp new file mode 100644 index 000000000..83e7be57b --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstSrc.cpp @@ -0,0 +1,531 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "GstSrc.h" +#include "GstTextTrackSinkFactory.h" +#include "RialtoServerLogging.h" +#include + +static void gstRialtoSrcUriHandlerInit(gpointer gIface, gpointer ifaceData); + +static GstStaticPadTemplate rialto_src_template = + GST_STATIC_PAD_TEMPLATE("src_%u", GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY(rialto_gst_player_debug); +#define GST_CAT_DEFAULT rialto_gst_player_debug +#define gst_rialto_src_parent_class parent_class +#define RIALTO_SRC_CATEGORY_INIT \ + GST_DEBUG_CATEGORY_INIT(rialto_gst_player_debug, "rialtosrc", 0, "Rialto source element"); +G_DEFINE_TYPE_WITH_CODE(GstRialtoSrc, gst_rialto_src, GST_TYPE_BIN, + G_ADD_PRIVATE(GstRialtoSrc) + G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gstRialtoSrcUriHandlerInit) + RIALTO_SRC_CATEGORY_INIT) + +static void gstRialtoSrcDispose(GObject *object) +{ + GST_CALL_PARENT(G_OBJECT_CLASS, dispose, (object)); +} + +static void gstRialtoSrcFinalize(GObject *object) +{ + GstRialtoSrc *src = GST_RIALTO_SRC(object); + GstRialtoSrcPrivate *priv = src->priv; + g_free(priv->uri); + priv->~GstRialtoSrcPrivate(); + GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); +} + +static void gstRialtoSrcSetProperty(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GST_CALL_PARENT(G_OBJECT_CLASS, set_property, (object, prop_id, value, pspec)); +} + +static void gstRialtoSrcGetProperty(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GST_CALL_PARENT(G_OBJECT_CLASS, get_property, (object, prop_id, value, pspec)); +} + +static GstURIType gstRialtoSrcUriGetType(GType) +{ + return GST_URI_SRC; +} + +const gchar *const *gstRialtoSrcGetProtocols(GType) +{ + static const char *protocols[] = {"rialto", 0}; + return protocols; +} + +static gchar *gstRialtoSrcGetUri(GstURIHandler *handler) +{ + GstRialtoSrc *src = GST_RIALTO_SRC(handler); + gchar *ret; + GST_OBJECT_LOCK(src); + ret = g_strdup(src->priv->uri); + GST_OBJECT_UNLOCK(src); + return ret; +} + +static gboolean gstRialtoSrcSetUri(GstURIHandler *handler, const gchar *uri, GError **error) +{ + GstRialtoSrc *src = GST_RIALTO_SRC(handler); + GstRialtoSrcPrivate *priv = src->priv; + if (GST_STATE(src) >= GST_STATE_PAUSED) + { + GST_ERROR_OBJECT(src, "URI can only be set in states < PAUSED"); + return FALSE; + } + GST_OBJECT_LOCK(src); + g_free(priv->uri); + priv->uri = 0; + if (!uri) + { + GST_OBJECT_UNLOCK(src); + return TRUE; + } + priv->uri = g_strdup(uri); + GST_OBJECT_UNLOCK(src); + return TRUE; +} + +static void gstRialtoSrcUriHandlerInit(gpointer gIface, gpointer) +{ + GstURIHandlerInterface *iface = reinterpret_cast(gIface); + iface->get_type = gstRialtoSrcUriGetType; + iface->get_protocols = gstRialtoSrcGetProtocols; + iface->get_uri = gstRialtoSrcGetUri; + iface->set_uri = gstRialtoSrcSetUri; +} + +static gboolean gstRialtoSrcQueryWithParent(GstPad *pad, GstObject *parent, GstQuery *query) +{ + gboolean result = FALSE; + switch (GST_QUERY_TYPE(query)) + { + default: + { + GstPad *target = gst_ghost_pad_get_target(GST_GHOST_PAD_CAST(pad)); + // Forward the query to the proxy target pad. + if (target) + result = gst_pad_query(target, query); + gst_object_unref(target); + break; + } + } + return result; +} + +void gstRialtoSrcHandleMessage(GstBin *bin, GstMessage *message) +{ + GstRialtoSrc *src = GST_RIALTO_SRC(GST_ELEMENT(bin)); + switch (GST_MESSAGE_TYPE(message)) + { + case GST_MESSAGE_EOS: + { + gboolean emit_eos = TRUE; + GstPad *pad = gst_element_get_static_pad(GST_ELEMENT(GST_MESSAGE_SRC(message)), "src"); + GST_DEBUG_OBJECT(src, "EOS received from %s", GST_MESSAGE_SRC_NAME(message)); + g_object_set_data(G_OBJECT(pad), "is-eos", GINT_TO_POINTER(1)); + gst_object_unref(pad); + for (guint i = 0; i < src->priv->appsrc_count; i++) + { + gchar *name = g_strdup_printf("src_%u", i); + GstPad *src_pad = gst_element_get_static_pad(GST_ELEMENT(src), name); + GstPad *target = gst_ghost_pad_get_target(GST_GHOST_PAD_CAST(src_pad)); + gint is_eos = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(target), "is-eos")); + gst_object_unref(target); + gst_object_unref(src_pad); + g_free(name); + if (!is_eos) + { + emit_eos = FALSE; + break; + } + } + gst_message_unref(message); + if (emit_eos) + { + GST_DEBUG_OBJECT(src, "All appsrc elements are EOS, emitting event now."); + gst_element_send_event(GST_ELEMENT(bin), gst_event_new_eos()); + } + break; + } + default: + GST_BIN_CLASS(parent_class)->handle_message(bin, message); + break; + } +} + +static void gstRialtoSrcDoAsyncStart(GstRialtoSrc *rialtoSrc) +{ + GstRialtoSrcPrivate *privateData = rialtoSrc->priv; + if (privateData->async_done) + { + GST_DEBUG_OBJECT(rialtoSrc, "Rialto src already done"); + return; + } + + GstMessage *message = gst_message_new_async_start(GST_OBJECT(rialtoSrc)); + GstBin *bin = GST_BIN(rialtoSrc); + + privateData->async_start = TRUE; + GST_BIN_CLASS(parent_class)->handle_message(bin, message); +} + +static void gstRialtoSrcDoAsyncDone(GstRialtoSrc *rialtoSrc) +{ + GstRialtoSrcPrivate *privateData = rialtoSrc->priv; + if (!privateData->async_start) + { + GST_DEBUG_OBJECT(rialtoSrc, "Rialto src not started"); + return; + } + + GstMessage *message = gst_message_new_async_done(GST_OBJECT(rialtoSrc), GST_CLOCK_TIME_NONE); + GstBin *bin = GST_BIN(rialtoSrc); + + GST_BIN_CLASS(parent_class)->handle_message(bin, message); + + privateData->async_done = TRUE; + privateData->async_start = FALSE; +} + +static GstStateChangeReturn gstRialtoSrcChangeState(GstElement *element, GstStateChange transition) +{ + GstRialtoSrc *rialtoSrc = GST_RIALTO_SRC(element); + GstRialtoSrcPrivate *privateData = rialtoSrc->priv; + GstStateChangeReturn status = GST_STATE_CHANGE_SUCCESS; + + if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) + { + gstRialtoSrcDoAsyncStart(rialtoSrc); + } + + status = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (G_UNLIKELY(status == GST_STATE_CHANGE_FAILURE)) + { + gstRialtoSrcDoAsyncDone(rialtoSrc); + return status; + } + + switch (transition) + { + case GST_STATE_CHANGE_READY_TO_PAUSED: + { + if (!privateData->async_done) + status = GST_STATE_CHANGE_ASYNC; + break; + } + case GST_STATE_CHANGE_PAUSED_TO_READY: + { + gstRialtoSrcDoAsyncDone(rialtoSrc); + break; + } + default: + break; + } + + return status; +} + +static void gst_rialto_src_init(GstRialtoSrc *src) // NOLINT(build/function_format) +{ + GstRialtoSrcPrivate *priv = reinterpret_cast(gst_rialto_src_get_instance_private(src)); + src->priv = priv; + src->priv->appsrc_count = 0; + src->priv->async_start = FALSE; + src->priv->async_done = FALSE; + g_object_set(GST_BIN(src), "message-forward", TRUE, nullptr); +} + +static void gst_rialto_src_class_init(GstRialtoSrcClass *klass) // NOLINT(build/function_format) +{ + GObjectClass *oklass = G_OBJECT_CLASS(klass); + GstElementClass *eklass = GST_ELEMENT_CLASS(klass); + GstBinClass *bklass = GST_BIN_CLASS(klass); + oklass->dispose = gstRialtoSrcDispose; + oklass->finalize = gstRialtoSrcFinalize; + oklass->set_property = gstRialtoSrcSetProperty; + oklass->get_property = gstRialtoSrcGetProperty; + GstPadTemplate *templ = gst_static_pad_template_get(&rialto_src_template); + gst_element_class_add_pad_template(eklass, templ); + gst_element_class_set_metadata(eklass, "Rialto source element", "Source", + "Handles data incoming from the Rialto player", "POC "); + g_object_class_install_property(oklass, PROP_LOCATION, + g_param_spec_string("location", "location", "Location to read from", 0, + (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + bklass->handle_message = GST_DEBUG_FUNCPTR(gstRialtoSrcHandleMessage); + eklass->change_state = GST_DEBUG_FUNCPTR(gstRialtoSrcChangeState); +} + +namespace firebolt::rialto::server +{ +std::weak_ptr GstSrcFactory::m_factory; +std::weak_ptr GstSrcFactory::m_gstSrc; +std::mutex GstSrcFactory::m_creationMutex; + +std::shared_ptr IGstSrcFactory::getFactory() +{ + std::shared_ptr factory = GstSrcFactory::m_factory.lock(); + + if (!factory) + { + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer src factory, reason: %s", e.what()); + } + + GstSrcFactory::m_factory = factory; + } + + return factory; +} + +std::shared_ptr GstSrcFactory::getGstSrc() +{ + std::lock_guard lock{m_creationMutex}; + + std::shared_ptr gstSrc = GstSrcFactory::m_gstSrc.lock(); + + if (!gstSrc) + { + try + { + gstSrc = std::make_shared(firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(), + firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(), + IGstDecryptorElementFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer src, reason: %s", e.what()); + } + + GstSrcFactory::m_gstSrc = gstSrc; + } + + return gstSrc; +} + +GstSrc::GstSrc(const std::shared_ptr &gstWrapperFactory, + const std::shared_ptr &glibWrapperFactory, + const std::shared_ptr &decryptorFactory) + : m_decryptorFactory(decryptorFactory) +{ + if ((!gstWrapperFactory) || (!(m_gstWrapper = gstWrapperFactory->getGstWrapper()))) + { + throw std::runtime_error("Cannot create GstWrapper"); + } + if ((!glibWrapperFactory) || (!(m_glibWrapper = glibWrapperFactory->getGlibWrapper()))) + { + throw std::runtime_error("Cannot create GlibWrapper"); + } + if (!m_decryptorFactory) + { + throw std::runtime_error("No decryptor factory provided"); + } +} + +void GstSrc::initSrc() +{ + GstElementFactory *src_factory = m_gstWrapper->gstElementFactoryFind("rialtosrc"); + if (!src_factory) + { + m_gstWrapper->gstElementRegister(0, "rialtosrc", GST_RANK_PRIMARY + 100, GST_RIALTO_TYPE_SRC); + } + else + { + m_gstWrapper->gstObjectUnref(src_factory); + src_factory = nullptr; + } +} + +void GstSrc::setDefaultStreamFormatIfNeeded(GstElement *appSrc) +{ + GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(appSrc)); + if (currentCaps) + { + GstStructure *structure = m_gstWrapper->gstCapsGetStructure(currentCaps, 0); + if (structure && (m_gstWrapper->gstStructureHasName(structure, "video/x-h264") || + m_gstWrapper->gstStructureHasName(structure, "video/x-h265"))) + { + bool hasStreamFormat = m_gstWrapper->gstStructureHasField(structure, "stream-format"); + bool hasCodecData = m_gstWrapper->gstStructureHasField(structure, "codec_data"); + + if (!hasStreamFormat && !hasCodecData) + { + GstCaps *newCaps = m_gstWrapper->gstCapsCopy(currentCaps); + if (newCaps) + { + m_gstWrapper->gstCapsSetSimple(newCaps, "stream-format", G_TYPE_STRING, "byte-stream", nullptr); + m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(appSrc), newCaps); + GST_INFO("Added stream-format=byte-stream to caps %" GST_PTR_FORMAT, newCaps); + m_gstWrapper->gstCapsUnref(newCaps); + } + } + } + } + m_gstWrapper->gstCapsUnref(currentCaps); +} + +void GstSrc::setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, + GstAppSrcCallbacks *callbacks, gpointer userData, firebolt::rialto::MediaSourceType type) +{ + // Configure and add appsrc + m_glibWrapper->gObjectSet(streamInfo.appSrc, "block", FALSE, "format", GST_FORMAT_TIME, "stream-type", + GST_APP_STREAM_TYPE_STREAM, "min-percent", 20, "handle-segment-change", TRUE, nullptr); + m_gstWrapper->gstAppSrcSetCallbacks(GST_APP_SRC(streamInfo.appSrc), callbacks, userData, nullptr); + + const std::unordered_map queueSize = + {{firebolt::rialto::MediaSourceType::VIDEO, 8 * 1024 * 1024}, + {firebolt::rialto::MediaSourceType::AUDIO, 512 * 1024}, + {firebolt::rialto::MediaSourceType::SUBTITLE, 256 * 1024}}; + + auto sizeIt = queueSize.find(type); + if (sizeIt != queueSize.end()) + { + m_gstWrapper->gstAppSrcSetMaxBytes(GST_APP_SRC(streamInfo.appSrc), sizeIt->second); + } + else + { + GST_WARNING_OBJECT(source, "Could not find max-bytes value for appsrc"); + } + + m_gstWrapper->gstAppSrcSetStreamType(GST_APP_SRC(streamInfo.appSrc), GST_APP_STREAM_TYPE_SEEKABLE); + + GstRialtoSrc *src = GST_RIALTO_SRC(source); + guint id = src->priv->appsrc_count; + src->priv->appsrc_count++; + gchar *name = m_glibWrapper->gStrdupPrintf("src_%u", id); + m_gstWrapper->gstBinAdd(GST_BIN(source), streamInfo.appSrc); + + GstElement *src_elem = streamInfo.appSrc; + + // Configure and add decryptor + if (streamInfo.hasDrm) + { + gchar *decryptorName = + m_glibWrapper->gStrdupPrintf("rialtodecryptor%s_%u", + (type == firebolt::rialto::MediaSourceType::VIDEO) ? "video" : "audio", id); + GstElement *decryptor = + m_decryptorFactory->createDecryptorElement(decryptorName, decryptionService, m_gstWrapper); + m_glibWrapper->gFree(decryptorName); + if (decryptor) + { + GST_DEBUG_OBJECT(src, "Injecting decryptor element %" GST_PTR_FORMAT, decryptor); + + m_gstWrapper->gstBinAdd(GST_BIN(source), decryptor); + m_gstWrapper->gstElementSyncStateWithParent(decryptor); + m_gstWrapper->gstElementLink(src_elem, decryptor); + src_elem = decryptor; + } + else + { + GST_WARNING_OBJECT(src, "Could not create decryptor element"); + } + + if (type == firebolt::rialto::MediaSourceType::VIDEO) + { + // Configure and add payloader + GstElement *payloader = createPayloader(); + if (payloader) + { + /* + h264secparse and h265secparse have problems with parsing blank caps (with no stream-format nor + codec_data defined). This is a workaround to set the stream-format to byte-stream if needed. + */ + setDefaultStreamFormatIfNeeded(streamInfo.appSrc); + + if (GST_IS_BASE_TRANSFORM(payloader)) + { + m_gstWrapper->gstBaseTransformSetInPlace(GST_BASE_TRANSFORM(payloader), TRUE); + } + m_gstWrapper->gstBinAdd(GST_BIN(source), payloader); + m_gstWrapper->gstElementSyncStateWithParent(payloader); + m_gstWrapper->gstElementLink(src_elem, payloader); + src_elem = payloader; + } + else + { + GST_WARNING_OBJECT(src, "Could not create payloader element"); + } + } + } + + // Configure and add buffer queue + GstElement *queue = m_gstWrapper->gstElementFactoryMake("queue", nullptr); + if (queue) + { + m_glibWrapper->gObjectSet(G_OBJECT(queue), "max-size-buffers", 10, "max-size-bytes", 0, "max-size-time", + (gint64)0, "silent", TRUE, nullptr); + m_gstWrapper->gstBinAdd(GST_BIN(source), queue); + m_gstWrapper->gstElementSyncStateWithParent(queue); + m_gstWrapper->gstElementLink(src_elem, queue); + src_elem = queue; + } + else + { + GST_WARNING_OBJECT(src, "Could not create buffer queue element"); + } + + // Setup pad + GstPad *target = m_gstWrapper->gstElementGetStaticPad(src_elem, "src"); + GstPad *pad = m_gstWrapper->gstGhostPadNew(name, target); + m_gstWrapper->gstPadSetQueryFunction(pad, gstRialtoSrcQueryWithParent); + m_gstWrapper->gstPadSetActive(pad, TRUE); + + m_gstWrapper->gstElementAddPad(source, pad); + GST_OBJECT_FLAG_SET(pad, GST_PAD_FLAG_NEED_PARENT); + + m_gstWrapper->gstElementSyncStateWithParent(streamInfo.appSrc); + + m_glibWrapper->gFree(name); + m_gstWrapper->gstObjectUnref(target); +} + +void GstSrc::allAppSrcsAdded(GstElement *element) +{ + GstRialtoSrc *src = GST_RIALTO_SRC(element); + m_gstWrapper->gstElementNoMorePads(element); + gstRialtoSrcDoAsyncDone(src); +} + +GstElement *GstSrc::createPayloader() +{ + static GstElementFactory *factory = nullptr; + static gsize init = 0; + if (m_glibWrapper->gOnceInitEnter(&init)) + { + factory = m_gstWrapper->gstElementFactoryFind("svppay"); + m_glibWrapper->gOnceInitLeave(&init, 1); + } + if (!factory) + { + GST_WARNING("svppay not found"); + return nullptr; + } + return m_gstWrapper->gstElementFactoryCreate(factory, nullptr); +} + +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstTextTrackSink.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstTextTrackSink.cpp new file mode 100644 index 000000000..a0308e8b3 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstTextTrackSink.cpp @@ -0,0 +1,585 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GstProtectionMetadataHelperFactory.h" +#include "GstRialtoTextTrackSinkPrivate.h" +#include "GstTextTrackSinkFactory.h" +#include "RialtoServerLogging.h" +#include +#include +#include +#include +#include +#include +G_BEGIN_DECLS + +enum +{ + PROP_0, + PROP_MUTE, + PROP_TEXT_TRACK_IDENTIFIER, + PROP_VIDEO_DECODER, + PROP_POSITION, + PROP_OFFSET, + PROP_LAST +}; + +#define GST_RIALTO_TEXT_TRACK_SINK_TYPE (gst_rialto_text_track_sink_get_type()) +#define GST_RIALTO_TEXT_TRACK_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_RIALTO_TEXT_TRACK_SINK_TYPE, GstRialtoTextTrackSink)) +#define GST_RIALTO_TEXT_TRACK_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_RIALTO_TEXT_TRACK_SINK_TYPE, GstRialtoTextTrackSinkClass)) + +typedef struct _GstRialtoTextTrackSink GstRialtoTextTrackSink; +typedef struct _GstRialtoTextTrackSinkClass GstRialtoTextTrackSinkClass; +typedef struct firebolt::rialto::server::GstRialtoTextTrackSinkPrivate GstRialtoTextTrackSinkPrivate; + +GType gst_rialto_text_track_sink_get_type(void); // NOLINT(build/function_format) + +struct _GstRialtoTextTrackSink +{ + GstBaseSink parent; + GstRialtoTextTrackSinkPrivate *priv; +}; + +struct _GstRialtoTextTrackSinkClass +{ + GstBaseSink parentClass; +}; + +G_END_DECLS + +static GstStaticPadTemplate sinkTemplate = + GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS("application/ttml+xml; text/vtt; application/x-subtitle-vtt; text/x-raw; " + "subtitle/x-subtitle-cc")); + +GST_DEBUG_CATEGORY(gst_rialto_text_track_sink_debug_category); +#define GST_CAT_DEFAULT gst_rialto_text_track_sink_debug_category + +#define gst_rialto_text_track_sink_parent_class parent_class +G_DEFINE_TYPE_WITH_PRIVATE(GstRialtoTextTrackSink, gst_rialto_text_track_sink, GST_TYPE_BASE_SINK); + +static void gst_rialto_text_track_sink_finalize(GObject *object); // NOLINT(build/function_format) +static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, // NOLINT(build/function_format) + GstBuffer *buffer); +static gboolean gst_rialto_text_track_sink_set_caps(GstBaseSink *sink, GstCaps *caps); // NOLINT(build/function_format) +static gboolean gst_rialto_text_track_sink_start(GstBaseSink *sink); // NOLINT(build/function_format) +static gboolean gst_rialto_text_track_sink_stop(GstBaseSink *sink); // NOLINT(build/function_format) +static gboolean gst_rialto_text_track_sink_event(GstBaseSink *sink, GstEvent *event); // NOLINT(build/function_format) +static GstStateChangeReturn +gst_rialto_text_track_sink_change_state(GstElement *element, GstStateChange transition); // NOLINT(build/function_format) +static void gst_rialto_text_track_sink_get_property(GObject *object, guint propId, // NOLINT(build/function_format) + GValue *value, GParamSpec *pspec); +static void gst_rialto_text_track_sink_set_property(GObject *object, guint propId, // NOLINT(build/function_format) + const GValue *value, GParamSpec *pspec); +static gboolean gst_rialto_text_track_sink_query(GstElement *element, GstQuery *query); // NOLINT(build/function_format) + +static void gst_rialto_text_track_sink_class_init(GstRialtoTextTrackSinkClass *klass) // NOLINT(build/function_format) +{ + GST_DEBUG_CATEGORY_INIT(gst_rialto_text_track_sink_debug_category, "rialto_text_track_sink", 0, + "TextTrack Sink for Rialto"); + + GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); + GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); + GstBaseSinkClass *baseSinkClass = GST_BASE_SINK_CLASS(klass); + + gobjectClass->finalize = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_finalize); + gobjectClass->get_property = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_get_property); + gobjectClass->set_property = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_set_property); + baseSinkClass->start = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_start); + baseSinkClass->stop = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_stop); + baseSinkClass->render = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_render); + baseSinkClass->set_caps = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_set_caps); + baseSinkClass->event = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_event); + elementClass->change_state = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_change_state); + elementClass->query = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_query); + + g_object_class_install_property(gobjectClass, PROP_MUTE, + g_param_spec_boolean("mute", "Mute", "Mute subtitles", FALSE, G_PARAM_READWRITE)); + + g_object_class_install_property(gobjectClass, PROP_TEXT_TRACK_IDENTIFIER, + g_param_spec_string("text-track-identifier", "Text Track Identifier", + "Identifier of text track", nullptr, + GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_VIDEO_DECODER, + g_param_spec_uint64("video-decoder", "Video Decoder", "Video Decoder", 0, + G_MAXUINT64, 0, GParamFlags(G_PARAM_WRITABLE))); + + g_object_class_install_property(gobjectClass, PROP_POSITION, + g_param_spec_uint64("position", "Position", "Position", 0, G_MAXUINT64, 0, + GParamFlags(G_PARAM_READWRITE))); + + g_object_class_install_property(gobjectClass, PROP_OFFSET, + g_param_spec_uint64("offset", "Offset", "Offset", 0, G_MAXUINT64, 0, + GParamFlags(G_PARAM_WRITABLE))); + + gst_element_class_add_pad_template(elementClass, gst_static_pad_template_get(&sinkTemplate)); + gst_element_class_set_static_metadata(elementClass, "Rialto TextTrack Sink", "Sink/Parser/Subtitle", + "Rialto TextTrack Sink", "SKY"); +} + +static void gst_rialto_text_track_sink_init(GstRialtoTextTrackSink *self) // NOLINT(build/function_format) +{ + GstRialtoTextTrackSinkPrivate *priv = + reinterpret_cast(gst_rialto_text_track_sink_get_instance_private(self)); + + self->priv = new (priv) GstRialtoTextTrackSinkPrivate(); + + gst_base_sink_set_async_enabled(GST_BASE_SINK(self), FALSE); +} + +static void gst_rialto_text_track_sink_finalize(GObject *object) // NOLINT(build/function_format) +{ + GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(object); + GstRialtoTextTrackSinkPrivate *priv = + reinterpret_cast(gst_rialto_text_track_sink_get_instance_private(self)); + + priv->~GstRialtoTextTrackSinkPrivate(); + + GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); +} + +static gboolean gst_rialto_text_track_sink_start(GstBaseSink *sink) // NOLINT(build/function_format) +{ + const char *wayland_display = std::getenv("WAYLAND_DISPLAY"); + if (!wayland_display) + { + GST_ERROR_OBJECT(sink, "Failed to get WAYLAND_DISPLAY env variable"); + return false; + } + + std::string display{wayland_display}; + GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink); + try + { + self->priv->m_textTrackSession = + firebolt::rialto::server::ITextTrackSessionFactory::getFactory().createTextTrackSession(display); + } + catch (const std::exception &e) + { + GST_ERROR_OBJECT(sink, "Failed to create TextTrackSession. Reason '%s'", e.what()); + return false; + } + + GST_INFO_OBJECT(sink, "Successfully started TextTrack sink"); + return true; +} + +static gboolean gst_rialto_text_track_sink_stop(GstBaseSink *sink) // NOLINT(build/function_format) +{ + GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink); + self->priv->m_textTrackSession.reset(); + + GST_INFO_OBJECT(sink, "Successfully stopped TextTrack sink"); + return true; +} + +static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, GstBuffer *buffer) // NOLINT(build/function_format) +{ + GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink); + + GstMapInfo info; + if (gst_buffer_map(buffer, &info, GST_MAP_READ)) + { + std::string data(reinterpret_cast(info.data), info.size); + int64_t displayOffset{0}; + if (GST_BUFFER_OFFSET_NONE != GST_BUFFER_OFFSET(buffer)) + { + displayOffset = static_cast(GST_BUFFER_OFFSET(buffer)); + } + textTrackSink->priv->m_textTrackSession->sendData(data, 0 - displayOffset); + + gst_buffer_unmap(buffer, &info); + } + else + { + GST_ERROR_OBJECT(textTrackSink, "Failed to map buffer"); + return GST_FLOW_ERROR; + } + + return GST_FLOW_OK; +} + +static gboolean gst_rialto_text_track_sink_set_position(GstRialtoTextTrackSink *textTrackSink) // NOLINT(build/function_format) +{ + if (!textTrackSink->priv->m_textTrackSession) + { + GST_ERROR_OBJECT(textTrackSink, "Session is NULL"); + return FALSE; + } + + uint64_t positionWithOffset = textTrackSink->priv->m_position.value_or(0) + textTrackSink->priv->m_offset.value_or(0); + + GST_DEBUG_OBJECT(textTrackSink, + "Setting position to %" GST_TIME_FORMAT " (pts %" GST_TIME_FORMAT ", offset %" GST_TIME_FORMAT ")", + GST_TIME_ARGS(positionWithOffset), GST_TIME_ARGS(textTrackSink->priv->m_position.value_or(0)), + GST_TIME_ARGS(textTrackSink->priv->m_offset.value_or(0))); + + textTrackSink->priv->m_textTrackSession->setPosition(positionWithOffset / GST_MSECOND); + return TRUE; +} + +static gboolean gst_rialto_text_track_sink_set_caps(GstBaseSink *sink, GstCaps *caps) // NOLINT(build/function_format) +{ + GST_INFO_OBJECT(sink, "Setting caps %" GST_PTR_FORMAT, caps); + GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink); + + GstStructure *structure = gst_caps_get_structure(caps, 0); + const gchar *mimeName = gst_structure_get_name(structure); + + if (g_str_has_prefix(mimeName, "text/vtt") || g_str_has_prefix(mimeName, "application/x-subtitle-vtt")) + { + GST_INFO_OBJECT(sink, "Setting session to WebVTT"); + textTrackSink->priv->m_textTrackSession->setSessionWebVTTSelection(); + } + else if (g_str_has_prefix(mimeName, "application/ttml+xml")) + { + GST_INFO_OBJECT(sink, "Setting session to TTML"); + textTrackSink->priv->m_textTrackSession->setSessionTTMLSelection(); + } + else if (g_str_has_prefix(mimeName, "subtitle/x-subtitle-cc")) + { + GST_INFO_OBJECT(sink, "Setting session to CC"); + std::string identifier = "CC1"; + if (textTrackSink->priv->m_textTrackIdentifier.empty()) + { + GST_WARNING_OBJECT(sink, "No text track identifier set, defaulting to %s", identifier.c_str()); + } + else + { + identifier = textTrackSink->priv->m_textTrackIdentifier; + } + textTrackSink->priv->m_textTrackSession->setSessionCCSelection(identifier); + + if (textTrackSink->priv->m_videoDecoderIdentifier) + { + textTrackSink->priv->m_textTrackSession->associateVideoDecoder(textTrackSink->priv->m_videoDecoderIdentifier); + } + } + else + { + GST_ERROR_OBJECT(sink, "Invalid mime name '%s'", mimeName); + return FALSE; + } + + textTrackSink->priv->m_textTrackSession->mute(textTrackSink->priv->m_isMuted); + + std::unique_lock lock{textTrackSink->priv->m_mutex}; + textTrackSink->priv->m_capsSet = true; + bool wasAnyQueued = textTrackSink->priv->m_queuedPosition.has_value() || + textTrackSink->priv->m_queuedOffset.has_value(); + if (textTrackSink->priv->m_queuedPosition.has_value()) + { + textTrackSink->priv->m_position = textTrackSink->priv->m_queuedPosition; + textTrackSink->priv->m_queuedPosition.reset(); + } + if (textTrackSink->priv->m_queuedOffset.has_value()) + { + textTrackSink->priv->m_offset = textTrackSink->priv->m_queuedOffset; + textTrackSink->priv->m_queuedOffset.reset(); + } + if (wasAnyQueued) + { + gst_rialto_text_track_sink_set_position(textTrackSink); + } + + return TRUE; +} + +static gboolean gst_rialto_text_track_sink_event(GstBaseSink *sink, GstEvent *event) // NOLINT(build/function_format) +{ + GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink); + GST_DEBUG_OBJECT(textTrackSink, "handling event %" GST_PTR_FORMAT, event); + + switch (GST_EVENT_TYPE(event)) + { + case GST_EVENT_FLUSH_START: + { + if (!textTrackSink->priv->m_textTrackSession->resetSession(textTrackSink->priv->m_isMuted)) + { + GST_ERROR_OBJECT(textTrackSink, "Failed to reset TextTrack session"); + } + break; + } + case GST_EVENT_FLUSH_STOP: + { + break; + } + case GST_EVENT_CUSTOM_DOWNSTREAM: + case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: + { + if (gst_event_has_name(event, "current-pts")) + { + uint64_t pts = 0; + const GstStructure *structure = gst_event_get_structure(event); + if (structure) + { + if (gst_structure_get_uint64(structure, "pts", &pts)) + { + if (pts == GST_CLOCK_TIME_NONE) + { + GST_ERROR_OBJECT(textTrackSink, "Invalid PTS value"); + return FALSE; + } + + std::unique_lock lock{textTrackSink->priv->m_mutex}; + textTrackSink->priv->m_position = pts; + + gst_rialto_text_track_sink_set_position(textTrackSink); + } + else + { + GST_ERROR_OBJECT(textTrackSink, "Failed to get PTS from structure"); + return FALSE; + } + } + else + { + GST_ERROR_OBJECT(textTrackSink, "Failed to get structure from event"); + return FALSE; + } + } + break; + } + default: + { + break; + } + } + + return GST_BASE_SINK_CLASS(parent_class)->event(sink, event); +} + +static GstStateChangeReturn +gst_rialto_text_track_sink_change_state(GstElement *element, GstStateChange transition) // NOLINT(build/function_format) +{ + GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(element); + + GstState current_state = GST_STATE_TRANSITION_CURRENT(transition); + GstState next_state = GST_STATE_TRANSITION_NEXT(transition); + GST_INFO_OBJECT(textTrackSink, "State change: (%s) -> (%s)", gst_element_state_get_name(current_state), + gst_element_state_get_name(next_state)); + + switch (transition) + { + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + if (!textTrackSink->priv->m_textTrackSession->play()) + { + GST_ERROR_OBJECT(textTrackSink, "Failed to play textTrack session"); + return GST_STATE_CHANGE_FAILURE; + } + break; + } + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + { + if (!textTrackSink->priv->m_textTrackSession->pause()) + { + GST_ERROR_OBJECT(textTrackSink, "Failed to pause textTrack session"); + return GST_STATE_CHANGE_FAILURE; + } + + break; + } + default: + break; + } + + GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) + { + GST_WARNING_OBJECT(textTrackSink, "State change failed"); + return result; + } + + return GST_STATE_CHANGE_SUCCESS; +} + +static void gst_rialto_text_track_sink_get_property(GObject *object, guint propId, // NOLINT(build/function_format) + GValue *value, GParamSpec *pspec) +{ + GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(object); + if (!textTrackSink) + { + GST_ERROR_OBJECT(textTrackSink, "Sink not initalised"); + return; + } + GstRialtoTextTrackSinkPrivate *priv = textTrackSink->priv; + + switch (propId) + { + case PROP_MUTE: + { + g_value_set_boolean(value, priv->m_isMuted.load()); + break; + } + case PROP_TEXT_TRACK_IDENTIFIER: + { + g_value_set_string(value, priv->m_textTrackIdentifier.c_str()); + break; + } + case PROP_POSITION: + { + // Thunder ITextTrack does not provide getPosition API so we are unable to determine current position + g_value_set_uint64(value, GST_CLOCK_TIME_NONE); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } +} + +static void gst_rialto_text_track_sink_set_property(GObject *object, guint propId, // NOLINT(build/function_format) + const GValue *value, GParamSpec *pspec) +{ + GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(object); + if (!textTrackSink) + { + GST_ERROR_OBJECT(textTrackSink, "Sink not initalised"); + return; + } + GstRialtoTextTrackSinkPrivate *priv = textTrackSink->priv; + + switch (propId) + { + case PROP_MUTE: + { + priv->m_isMuted = g_value_get_boolean(value); + if (priv->m_textTrackSession) + { + priv->m_textTrackSession->mute(priv->m_isMuted); + } + break; + } + case PROP_TEXT_TRACK_IDENTIFIER: + { + priv->m_textTrackIdentifier = g_value_get_string(value); + if (priv->m_textTrackSession && priv->m_textTrackSession->isClosedCaptions()) + { + priv->m_textTrackSession->setSessionCCSelection(priv->m_textTrackIdentifier); + } + + break; + } + case PROP_VIDEO_DECODER: + { + priv->m_videoDecoderIdentifier = g_value_get_uint64(value); + if (priv->m_textTrackSession && priv->m_textTrackSession->isClosedCaptions()) + { + priv->m_textTrackSession->associateVideoDecoder(priv->m_videoDecoderIdentifier); + } + + break; + } + case PROP_POSITION: + { + guint64 position = g_value_get_uint64(value); + std::unique_lock lock{priv->m_mutex}; + if (priv->m_textTrackSession && priv->m_capsSet) + { + priv->m_position = position; + gst_rialto_text_track_sink_set_position(textTrackSink); + } + else + { + priv->m_queuedPosition = position; + } + break; + } + case PROP_OFFSET: + { + uint64_t offset = g_value_get_uint64(value); + std::unique_lock lock{priv->m_mutex}; + if (priv->m_textTrackSession && priv->m_capsSet) + { + priv->m_offset = offset; + gst_rialto_text_track_sink_set_position(textTrackSink); + } + else + { + priv->m_queuedOffset = offset; + } + break; + } + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); + break; + } +} + +static gboolean gst_rialto_text_track_sink_query(GstElement *element, GstQuery *query) // NOLINT(build/function_format) +{ + GstRialtoTextTrackSink *sink = GST_RIALTO_TEXT_TRACK_SINK(element); + GST_DEBUG_OBJECT(sink, "handling query '%s'", GST_QUERY_TYPE_NAME(query)); + switch (GST_QUERY_TYPE(query)) + { + case GST_QUERY_POSITION: + { + GstFormat fmt; + gst_query_parse_position(query, &fmt, NULL); + switch (fmt) + { + case GST_FORMAT_TIME: + { + // GST_CLOCK_TIME_NONE has to be returned here, because otherwise whole pipeline returns incorrect position + gst_query_set_position(query, fmt, GST_CLOCK_TIME_NONE); + break; + } + default: + break; + } + return TRUE; + } + default: + break; + } + GstElement *parent = GST_ELEMENT(&sink->parent); + return GST_ELEMENT_CLASS(parent_class)->query(parent, query); +} + +namespace firebolt::rialto::server +{ +std::shared_ptr IGstTextTrackSinkFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the textTrackSink element factory, reason: %s", e.what()); + } + + return factory; +} + +GstElement *GstTextTrackSinkFactory::createGstTextTrackSink() const +{ + GstElement *elem = GST_ELEMENT(g_object_new(GST_RIALTO_TEXT_TRACK_SINK_TYPE, nullptr)); + + return elem; +} + +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstWebAudioPlayer.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstWebAudioPlayer.cpp new file mode 100644 index 000000000..ddb9bd2dd --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/GstWebAudioPlayer.cpp @@ -0,0 +1,473 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "GstWebAudioPlayer.h" +#include "GstDispatcherThread.h" +#include "RialtoServerLogging.h" +#include "WorkerThread.h" +#include "tasks/webAudio/WebAudioPlayerTaskFactory.h" +#include + +namespace +{ +constexpr uint32_t kMaxWriteBufferTimeoutMs{2000}; +} // namespace + +namespace firebolt::rialto::server +{ +std::weak_ptr GstWebAudioPlayerFactory::m_factory; + +std::shared_ptr IGstWebAudioPlayerFactory::getFactory() +{ + std::shared_ptr factory = GstWebAudioPlayerFactory::m_factory.lock(); + + if (!factory) + { + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer player factory, reason: %s", e.what()); + } + + GstWebAudioPlayerFactory::m_factory = factory; + } + + return factory; +} + +std::unique_ptr GstWebAudioPlayerFactory::createGstWebAudioPlayer(IGstWebAudioPlayerClient *client, + const uint32_t priority) +{ + std::unique_ptr gstPlayer; + + try + { + auto gstWrapperFactory = firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); + auto glibWrapperFactory = firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(); + std::shared_ptr gstWrapper; + std::shared_ptr glibWrapper; + if ((!gstWrapperFactory) || (!(gstWrapper = gstWrapperFactory->getGstWrapper()))) + { + throw std::runtime_error("Cannot create GstWrapper"); + } + if ((!glibWrapperFactory) || (!(glibWrapper = glibWrapperFactory->getGlibWrapper()))) + { + throw std::runtime_error("Cannot create GlibWrapper"); + } + gstPlayer = std::make_unique(client, priority, gstWrapper, glibWrapper, + IGstInitialiser::instance(), IGstSrcFactory::getFactory(), + std::make_unique(client, gstWrapper, + glibWrapper), + std::make_unique(), + std::make_unique()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer player, reason: %s", e.what()); + } + + return gstPlayer; +} + +GstWebAudioPlayer::GstWebAudioPlayer(IGstWebAudioPlayerClient *client, const uint32_t priority, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const IGstInitialiser &gstInitialiser, + const std::shared_ptr &gstSrcFactory, + std::unique_ptr taskFactory, + std::unique_ptr workerThreadFactory, + std::unique_ptr gstDispatcherThreadFactory) + : m_gstPlayerClient(client), m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, + m_taskFactory{std::move(taskFactory)} +{ + RIALTO_SERVER_LOG_DEBUG("GstWebAudioPlayer is constructed."); + + gstInitialiser.waitForInitialisation(); + + if ((!gstSrcFactory) || (!(m_context.gstSrc = gstSrcFactory->getGstSrc()))) + { + throw std::runtime_error("Cannot create GstSrc"); + } + + // Ensure that rialtosrc has been initalised + m_context.gstSrc->initSrc(); + + // Start task thread + if ((!workerThreadFactory) || (!(m_workerThread = workerThreadFactory->createWorkerThread()))) + { + throw std::runtime_error("Failed to create the worker thread"); + } + + if (!initWebAudioPipeline(priority)) + { + termWebAudioPipeline(); + resetWorkerThread(); + throw std::runtime_error("Failed to initalise the pipeline"); + } + + if ((!gstDispatcherThreadFactory) || + (!(m_gstDispatcherThread = + gstDispatcherThreadFactory->createGstDispatcherThread(*this, m_context.pipeline, m_gstWrapper)))) + { + termWebAudioPipeline(); + resetWorkerThread(); + throw std::runtime_error("Failed to create the dispatcher thread"); + } +} + +GstWebAudioPlayer::~GstWebAudioPlayer() +{ + RIALTO_SERVER_LOG_DEBUG("GstWebAudioPlayer is destructed."); + + m_gstDispatcherThread.reset(); + + resetWorkerThread(); + + termWebAudioPipeline(); +} + +bool GstWebAudioPlayer::initWebAudioPipeline(const uint32_t priority) +{ + m_context.pipeline = m_gstWrapper->gstPipelineNew(std::string("webaudiopipeline" + std::to_string(priority)).c_str()); + if (!m_context.pipeline) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the webaudiopipeline"); + return false; + } + + RIALTO_SERVER_LOG_MIL("RialtoServer's webaudio pipeline constructed"); + + // Create and initalise appsrc + m_context.source = m_gstWrapper->gstElementFactoryMake("appsrc", "audsrc"); + if (!m_context.source) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the appsrc"); + return false; + } + m_gstWrapper->gstAppSrcSetMaxBytes(GST_APP_SRC(m_context.source), kMaxWebAudioBytes); + m_glibWrapper->gObjectSet(m_context.source, "format", GST_FORMAT_TIME, nullptr); + + // Perform sink specific initalisation + GstPluginFeature *feature = nullptr; + GstRegistry *reg = m_gstWrapper->gstRegistryGet(); + if (!reg) + { + RIALTO_SERVER_LOG_ERROR("Failed get the gst registry"); + return false; + } + + GstElement *sink = nullptr; + if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "amlhalasink"))) + { + // LLama + RIALTO_SERVER_LOG_INFO("Use amlhalasink"); + sink = createAmlhalaSink(); + m_gstWrapper->gstObjectUnref(feature); + } + else if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "rtkaudiosink"))) + { + // XiOne + RIALTO_SERVER_LOG_INFO("Use rtkaudiosink"); + sink = createRtkAudioSink(); + m_gstWrapper->gstObjectUnref(feature); + } + else + { + RIALTO_SERVER_LOG_INFO("Use autoaudiosink"); + sink = createAutoSink(); + } + + if (sink) + { + return linkElementsToSrc(sink); + } + else + { + m_gstWrapper->gstObjectUnref(m_context.source); + m_context.source = nullptr; + } + return false; +} + +GstElement *GstWebAudioPlayer::createAmlhalaSink() +{ + GstElement *sink = m_gstWrapper->gstElementFactoryMake("amlhalasink", "webaudiosink"); + if (!sink) + { + RIALTO_SERVER_LOG_ERROR("Failed create the amlhalasink"); + return nullptr; + } + m_glibWrapper->gObjectSet(G_OBJECT(sink), "direct-mode", FALSE, NULL); + + return sink; +} + +GstElement *GstWebAudioPlayer::createRtkAudioSink() +{ + GstElement *sink = m_gstWrapper->gstElementFactoryMake("rtkaudiosink", "webaudiosink"); + if (!sink) + { + RIALTO_SERVER_LOG_ERROR("Failed create the rtkaudiosink"); + return nullptr; + } + m_glibWrapper->gObjectSet(G_OBJECT(sink), "media-tunnel", FALSE, NULL); + m_glibWrapper->gObjectSet(G_OBJECT(sink), "audio-service", TRUE, NULL); + + return sink; +} + +GstElement *GstWebAudioPlayer::createAutoSink() +{ + GstElement *sink = m_gstWrapper->gstElementFactoryMake("autoaudiosink", "webaudiosink"); + if (!sink) + { + RIALTO_SERVER_LOG_ERROR("Failed create the autoaudiosink"); + return nullptr; + } + + return sink; +} + +// NOTE:- +// This method hands the responsibility for the destruction of both { "sink", "m_context.source" } +// over to the pipeline (or if handover wasn't possible, it will unref) +bool GstWebAudioPlayer::linkElementsToSrc(GstElement *sink) +{ + bool status{true}; + + GstElement *convert{nullptr}; + GstElement *resample{nullptr}; + GstElement *volume{nullptr}; + GstElement *queue{nullptr}; + + convert = m_gstWrapper->gstElementFactoryMake("audioconvert", NULL); + if (!convert) + { + RIALTO_SERVER_LOG_ERROR("Failed create the audioconvert"); + status = false; + } + + if (status) + { + resample = m_gstWrapper->gstElementFactoryMake("audioresample", NULL); + if (!resample) + { + RIALTO_SERVER_LOG_ERROR("Failed create the audioresample"); + status = false; + } + } + + if (status) + { + volume = m_gstWrapper->gstElementFactoryMake("volume", NULL); + if (!volume) + { + RIALTO_SERVER_LOG_ERROR("Failed create the volume"); + status = false; + } + } + if (status) + { + queue = m_gstWrapper->gstElementFactoryMake("queue", NULL); + if (!queue) + { + RIALTO_SERVER_LOG_ERROR("Failed create the queue"); + status = false; + } + else + { + constexpr guint kWebAudioQueueSize{8192}; + m_glibWrapper->gObjectSet(queue, "max-size-bytes", kWebAudioQueueSize, nullptr); + } + } + + std::queue elementsToAdd; + elementsToAdd.push(m_context.source); + if (convert) + elementsToAdd.push(convert); + if (resample) + elementsToAdd.push(resample); + if (volume) + elementsToAdd.push(volume); + if (queue) + elementsToAdd.push(queue); + elementsToAdd.push(sink); + + if (status) + { + // Add elements to the pipeline + GstBin *pipelineBin = GST_BIN(m_context.pipeline); + while (!elementsToAdd.empty()) + { + if (m_gstWrapper->gstBinAdd(pipelineBin, elementsToAdd.front())) + elementsToAdd.pop(); + else + { + RIALTO_SERVER_LOG_ERROR("Failed to add element to the bin"); + status = false; + break; + } + } + } + + if (status) + { + if ((!m_gstWrapper->gstElementLink(m_context.source, convert)) || + (!m_gstWrapper->gstElementLink(convert, resample)) || (!m_gstWrapper->gstElementLink(resample, volume)) || + (!m_gstWrapper->gstElementLink(volume, queue)) || (!m_gstWrapper->gstElementLink(queue, sink))) + { + RIALTO_SERVER_LOG_ERROR("Failed to link elements"); + status = false; + } + m_context.gstVolumeElement = GST_STREAM_VOLUME(volume); + } + + if (!status) + { + // Unref anything that wasn't added to the pipeline + while (!elementsToAdd.empty()) + { + m_gstWrapper->gstObjectUnref(elementsToAdd.front()); + elementsToAdd.pop(); + } + m_context.source = nullptr; + } + + return status; +} + +void GstWebAudioPlayer::termWebAudioPipeline() +{ + if (m_context.pipeline) + { + m_taskFactory->createStop(*this)->execute(); + GstBus *bus = m_gstWrapper->gstPipelineGetBus(GST_PIPELINE(m_context.pipeline)); + if (bus) + { + m_gstWrapper->gstBusSetSyncHandler(bus, nullptr, nullptr, nullptr); + m_gstWrapper->gstObjectUnref(bus); + } + + m_gstWrapper->gstObjectUnref(m_context.pipeline); + } + RIALTO_SERVER_LOG_MIL("RialtoServer's webaudio pipeline terminated."); +} + +void GstWebAudioPlayer::resetWorkerThread() +{ + m_workerThread->enqueueTask(m_taskFactory->createShutdown(*this)); + m_workerThread->join(); + m_workerThread.reset(); +} + +void GstWebAudioPlayer::setCaps(const std::string &audioMimeType, std::weak_ptr config) +{ + m_workerThread->enqueueTask(m_taskFactory->createSetCaps(m_context, audioMimeType, config)); +} + +void GstWebAudioPlayer::play() +{ + m_workerThread->enqueueTask(m_taskFactory->createPlay(*this)); +} + +void GstWebAudioPlayer::pause() +{ + m_workerThread->enqueueTask(m_taskFactory->createPause(*this)); +} + +void GstWebAudioPlayer::setVolume(double volume) +{ + m_workerThread->enqueueTask(m_taskFactory->createSetVolume(m_context, volume)); +} + +bool GstWebAudioPlayer::getVolume(double &volume) +{ + // Must be called on the main thread, otherwise the pipeline can be destroyed during the query. + volume = m_gstWrapper->gstStreamVolumeGetVolume(m_context.gstVolumeElement, GST_STREAM_VOLUME_FORMAT_LINEAR); + return true; +} + +uint32_t GstWebAudioPlayer::writeBuffer(uint8_t *mainPtr, uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength) +{ + // Must block and wait for the data to be written from the shared buffer. + std::unique_lock lock(m_context.writeBufferMutex); + m_workerThread->enqueueTask(m_taskFactory->createWriteBuffer(m_context, mainPtr, mainLength, wrapPtr, wrapLength)); + std::cv_status status = m_context.writeBufferCond.wait_for(lock, std::chrono::milliseconds(kMaxWriteBufferTimeoutMs)); + if (std::cv_status::timeout == status) + { + RIALTO_SERVER_LOG_ERROR("Timed out writing to the gstreamer buffers"); + return 0; + } + else + { + return m_context.lastBytesWritten; + } +} + +void GstWebAudioPlayer::setEos() +{ + m_workerThread->enqueueTask(m_taskFactory->createEos(m_context)); +} + +uint64_t GstWebAudioPlayer::getQueuedBytes() +{ + // Must be called on the main thread, otherwise the pipeline can be destroyed during the query. + return m_gstWrapper->gstAppSrcGetCurrentLevelBytes(GST_APP_SRC(m_context.source)); +} + +bool GstWebAudioPlayer::changePipelineState(GstState newState) +{ + if (m_gstWrapper->gstElementSetState(m_context.pipeline, newState) == GST_STATE_CHANGE_FAILURE) + { + RIALTO_SERVER_LOG_ERROR("Change state failed - Gstreamer returned an error"); + if (m_gstPlayerClient) + m_gstPlayerClient->notifyState(WebAudioPlayerState::FAILURE); + return false; + } + return true; +} + +void GstWebAudioPlayer::stopWorkerThread() +{ + if (m_workerThread) + { + m_workerThread->stop(); + } +} + +void GstWebAudioPlayer::handleBusMessage(GstMessage *message, bool priority) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createHandleBusMessage(m_context, *this, message)); + } +} + +void GstWebAudioPlayer::ping(std::unique_ptr &&heartbeatHandler) +{ + if (m_workerThread) + { + m_workerThread->enqueueTask(m_taskFactory->createPing(std::move(heartbeatHandler))); + } +} + +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/NeedDataMapping.cpp b/middleware/rialto-client/media/server/gstplayer/source/NeedDataMapping.cpp new file mode 100644 index 000000000..05212e946 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/NeedDataMapping.cpp @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "NeedDataMapping.h" + +namespace firebolt::rialto::server +{ +bool NeedDataMapping::isNeedDataScheduled(GstAppSrc *src) const +{ + std::unique_lock lock{m_mutex}; + return m_scheduledNeedDatas.find(src) != m_scheduledNeedDatas.end(); +} + +void NeedDataMapping::setNeedDataScheduled(GstAppSrc *src) +{ + std::unique_lock lock{m_mutex}; + m_scheduledNeedDatas.insert(src); +} + +void NeedDataMapping::clearNeedDataScheduled(GstAppSrc *src) +{ + std::unique_lock lock{m_mutex}; + m_scheduledNeedDatas.erase(src); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/Utils.cpp b/middleware/rialto-client/media/server/gstplayer/source/Utils.cpp new file mode 100644 index 000000000..17f7c3aad --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/Utils.cpp @@ -0,0 +1,183 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Utils.h" +#include "CapsBuilder.h" +#include "GstMimeMapping.h" +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include +#include + +namespace +{ +const char *underflowSignals[]{"buffer-underflow-callback", "vidsink-underflow-callback", "underrun-callback"}; + +bool isType(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element, GstElementFactoryListType type) +{ + if (!element) + { + return false; + } + + GstElementFactory *factory{gstWrapper.gstElementGetFactory(element)}; + if (!factory) + { + return false; + } + return gstWrapper.gstElementFactoryListIsType(factory, type); +} +} // namespace + +namespace firebolt::rialto::server +{ + +bool isVideoDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO); +} + +bool isAudioDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); +} + +bool isVideoParser(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO); +} + +bool isVideoSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO); +} + +bool isAudioSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); +} + +bool isSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK); +} + +bool isDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER); +} + +bool isAudio(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); +} + +bool isVideo(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) +{ + return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO); +} + +std::optional getUnderflowSignalName(const firebolt::rialto::wrappers::IGlibWrapper &glibWrapper, + GstElement *element) +{ + GType type = glibWrapper.gObjectType(element); + guint nsignals{0}; + guint *signals = glibWrapper.gSignalListIds(type, &nsignals); + + for (guint i = 0; i < nsignals; i++) + { + GSignalQuery query; + glibWrapper.gSignalQuery(signals[i], &query); + const auto signalNameIt = std::find_if(std::begin(underflowSignals), std::end(underflowSignals), + [&](const auto *signalName) + { return strcmp(signalName, query.signal_name) == 0; }); + + if (std::end(underflowSignals) != signalNameIt) + { + glibWrapper.gFree(signals); + return std::string(*signalNameIt); + } + } + glibWrapper.gFree(signals); + + return std::nullopt; +} + +GstCaps *createCapsFromMediaSource(const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::unique_ptr &source) +{ + std::unique_ptr capsBuilder; + + firebolt::rialto::SourceConfigType configType = source->getConfigType(); + if (configType == firebolt::rialto::SourceConfigType::AUDIO) + { + const IMediaPipeline::MediaSourceAudio *kSource = dynamic_cast(source.get()); + if (kSource) + { + capsBuilder = std::make_unique(gstWrapper, glibWrapper, *kSource); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to cast to audio source"); + return nullptr; + } + } + else if (configType == firebolt::rialto::SourceConfigType::VIDEO) + { + const IMediaPipeline::MediaSourceVideo *kSource = dynamic_cast(source.get()); + if (kSource) + { + capsBuilder = std::make_unique(gstWrapper, glibWrapper, *kSource); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to cast to video source"); + return nullptr; + } + } + else if (configType == firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION) + { + const IMediaPipeline::MediaSourceVideoDolbyVision *kSource = + dynamic_cast(source.get()); + if (kSource) + { + capsBuilder = std::make_unique(gstWrapper, glibWrapper, *kSource); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to cast to dolby vision source!"); + return nullptr; + } + } + else if (configType == firebolt::rialto::SourceConfigType::SUBTITLE) + { + // subtitle caps is just a simple type, without any extra parameters + return firebolt::rialto::server::createSimpleCapsFromMimeType(gstWrapper, *source.get()); + } + else + { + RIALTO_SERVER_LOG_ERROR("Invalid config type %u", static_cast(configType)); + return nullptr; + } + + return capsBuilder->buildCaps(); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/WorkerThread.cpp b/middleware/rialto-client/media/server/gstplayer/source/WorkerThread.cpp new file mode 100644 index 000000000..0b5177b27 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/WorkerThread.cpp @@ -0,0 +1,125 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WorkerThread.h" +#include "RialtoServerLogging.h" + +namespace +{ + +class FunctionTask : public firebolt::rialto::server::IPlayerTask +{ +public: + explicit FunctionTask(std::function &&callback) : m_callback(std::move(callback)) {} + + ~FunctionTask() override = default; + + void execute() const override { m_callback(); } + +private: + std::function m_callback; +}; + +} // namespace + +namespace firebolt::rialto::server +{ +std::unique_ptr WorkerThreadFactory::createWorkerThread() const +{ + std::unique_ptr workerThread; + try + { + workerThread = std::make_unique(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the worker thread, reason: %s", e.what()); + } + return workerThread; +} + +WorkerThread::WorkerThread() +{ + RIALTO_SERVER_LOG_INFO("Worker thread is starting"); + m_taskThread = std::thread(&WorkerThread::taskHandler, this); +} + +WorkerThread::~WorkerThread() +{ + stop(); + join(); +} + +void WorkerThread::stop() +{ + RIALTO_SERVER_LOG_INFO("Stopping worker thread"); + + auto shutdownTask = [this]() { m_isTaskThreadActive = false; }; + enqueueTask(std::make_unique(std::move(shutdownTask))); +} + +void WorkerThread::join() +{ + if (m_taskThread.joinable()) + { + m_taskThread.join(); + } +} + +void WorkerThread::enqueueTask(std::unique_ptr &&task) +{ + if (task) + { + std::unique_lock lock(m_taskMutex); + m_taskQueue.push_back(std::move(task)); + m_taskCV.notify_one(); + } +} + +void WorkerThread::enqueuePriorityTask(std::unique_ptr &&task) +{ + if (task) + { + std::unique_lock lock(m_taskMutex); + m_taskQueue.push_front(std::move(task)); + m_taskCV.notify_one(); + } +} + +void WorkerThread::taskHandler() +{ + while (m_isTaskThreadActive) + { + std::unique_ptr task = waitForTask(); + task->execute(); + } +} + +std::unique_ptr WorkerThread::waitForTask() +{ + std::unique_lock lock(m_taskMutex); + if (m_taskQueue.empty()) + { + m_taskCV.wait(lock, [this] { return !m_taskQueue.empty(); }); + } + std::unique_ptr task = std::move(m_taskQueue.front()); + m_taskQueue.pop_front(); + return task; +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSamples.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSamples.cpp new file mode 100644 index 000000000..ccc91ca02 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSamples.cpp @@ -0,0 +1,135 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/AttachSamples.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +AttachSamples::AttachSamples(GenericPlayerContext &context, + const std::shared_ptr &gstWrapper, + IGstGenericPlayerPrivate &player, const IMediaPipeline::MediaSegmentVector &mediaSegments) + : m_context{context}, m_gstWrapper{gstWrapper}, m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing AttachSamples"); + for (const auto &mediaSegment : mediaSegments) + { + GstBuffer *gstBuffer = m_player.createBuffer(*mediaSegment); + if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::VIDEO) + { + try + { + IMediaPipeline::MediaSegmentVideo &videoSegment = + dynamic_cast(*mediaSegment); + VideoData videoData = {gstBuffer, videoSegment.getWidth(), videoSegment.getHeight(), + videoSegment.getFrameRate(), videoSegment.getCodecData()}; + m_videoData.push_back(videoData); + } + catch (const std::exception &e) + { + // Catching error, but continuing as best as we can + RIALTO_SERVER_LOG_ERROR("Failed to get the video segment, reason: %s", e.what()); + } + } + else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::AUDIO) + { + try + { + IMediaPipeline::MediaSegmentAudio &audioSegment = + dynamic_cast(*mediaSegment); + AudioData audioData = {gstBuffer, + audioSegment.getSampleRate(), + audioSegment.getNumberOfChannels(), + audioSegment.getCodecData(), + audioSegment.getClippingStart(), + audioSegment.getClippingEnd()}; + m_audioData.push_back(audioData); + } + catch (const std::exception &e) + { + // Catching error, but continuing as best as we can + RIALTO_SERVER_LOG_ERROR("Failed to get the audio segment, reason: %s", e.what()); + } + } + else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::SUBTITLE) + { + m_subtitleData.push_back(gstBuffer); + } + } +} + +AttachSamples::~AttachSamples() +{ + RIALTO_SERVER_LOG_DEBUG("AttachSamples finished"); +} + +void AttachSamples::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing AttachSamples"); + for (AudioData audioData : m_audioData) + { + m_player.updateAudioCaps(audioData.rate, audioData.channels, audioData.codecData); + m_player.addAudioClippingToBuffer(audioData.buffer, audioData.clippingStart, audioData.clippingEnd); + + attachData(firebolt::rialto::MediaSourceType::AUDIO, audioData.buffer); + } + for (VideoData videoData : m_videoData) + { + m_player.updateVideoCaps(videoData.width, videoData.height, videoData.frameRate, videoData.codecData); + + attachData(firebolt::rialto::MediaSourceType::VIDEO, videoData.buffer); + } + for (GstBuffer *buffer : m_subtitleData) + { + attachData(firebolt::rialto::MediaSourceType::SUBTITLE, buffer); + } + + if (!m_audioData.empty()) + { + m_player.notifyNeedMediaData(firebolt::rialto::MediaSourceType::AUDIO); + } + else if (!m_videoData.empty()) + { + m_player.notifyNeedMediaData(firebolt::rialto::MediaSourceType::VIDEO); + } + else if (!m_subtitleData.empty()) + { + m_player.notifyNeedMediaData(firebolt::rialto::MediaSourceType::SUBTITLE); + } +} + +void AttachSamples::attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const +{ + auto elem = m_context.streamInfo.find(mediaType); + if (elem != m_context.streamInfo.end()) + { + elem->second.buffers.push_back(buffer); + m_player.attachData(mediaType); + } + else + { + RIALTO_SERVER_LOG_WARN("Could not find stream info for %s", common::convertMediaSourceType(mediaType)); + m_gstWrapper->gstBufferUnref(buffer); + } +} + +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSource.cpp new file mode 100644 index 000000000..ce8c80521 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSource.cpp @@ -0,0 +1,131 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/AttachSource.h" +#include "GstMimeMapping.h" +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "IMediaPipeline.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" +#include "Utils.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +AttachSource::AttachSource(GenericPlayerContext &context, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr &gstTextTrackSinkFactory, + IGstGenericPlayerPrivate &player, const std::unique_ptr &source) + : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, + m_gstTextTrackSinkFactory{gstTextTrackSinkFactory}, m_player{player}, m_attachedSource{source->copy()} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing AttachSource"); +} + +AttachSource::~AttachSource() +{ + RIALTO_SERVER_LOG_DEBUG("AttachSource finished"); +} + +void AttachSource::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing AttachSource %u", static_cast(m_attachedSource->getType())); + + if (m_attachedSource->getType() == MediaSourceType::UNKNOWN) + { + RIALTO_SERVER_LOG_ERROR("Unknown media source type"); + return; + } + + if (m_context.streamInfo.find(m_attachedSource->getType()) == m_context.streamInfo.end()) + { + addSource(); + } + else if (m_attachedSource->getType() == MediaSourceType::AUDIO && m_context.audioSourceRemoved) + { + reattachAudioSource(); + } + else + { + RIALTO_SERVER_LOG_ERROR("cannot update caps"); + } +} + +void AttachSource::addSource() const +{ + GstCaps *caps = createCapsFromMediaSource(m_gstWrapper, m_glibWrapper, m_attachedSource); + if (!caps) + { + RIALTO_SERVER_LOG_ERROR("Failed to create caps from media source"); + return; + } + gchar *capsStr = m_gstWrapper->gstCapsToString(caps); + GstElement *appSrc = nullptr; + if (m_attachedSource->getType() == MediaSourceType::AUDIO) + { + RIALTO_SERVER_LOG_MIL("Adding Audio appsrc with caps %s", capsStr); + appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "audsrc"); + } + else if (m_attachedSource->getType() == MediaSourceType::VIDEO) + { + RIALTO_SERVER_LOG_MIL("Adding Video appsrc with caps %s", capsStr); + appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "vidsrc"); + } + else if (m_attachedSource->getType() == MediaSourceType::SUBTITLE) + { + RIALTO_SERVER_LOG_MIL("Adding Subtitle appsrc with caps %s", capsStr); + appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "subsrc"); + + if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(m_context.pipeline), "text-sink")) + { + GstElement *elem = m_gstTextTrackSinkFactory->createGstTextTrackSink(); + m_context.subtitleSink = elem; + + m_glibWrapper->gObjectSet(m_context.pipeline, "text-sink", elem, nullptr); + } + } + m_glibWrapper->gFree(capsStr); + + m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(appSrc), caps); + m_context.streamInfo.emplace(m_attachedSource->getType(), StreamInfo{appSrc, m_attachedSource->getHasDrm()}); + + if (caps) + m_gstWrapper->gstCapsUnref(caps); +} + +void AttachSource::reattachAudioSource() const +{ + if (!m_player.reattachSource(m_attachedSource)) + { + RIALTO_SERVER_LOG_ERROR("Reattaching source failed!"); + return; + } + + // Restart audio sink + m_player.setPlaybinFlags(true); + + m_context.streamInfo[m_attachedSource->getType()].isDataNeeded = true; + m_context.audioSourceRemoved = false; + m_player.notifyNeedMediaData(MediaSourceType::AUDIO); + + RIALTO_SERVER_LOG_MIL("Audio source reattached"); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp new file mode 100644 index 000000000..e556c4b62 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp @@ -0,0 +1,65 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/CheckAudioUnderflow.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include "tasks/generic/Underflow.h" +#include + +#include + +namespace firebolt::rialto::server::tasks::generic +{ +CheckAudioUnderflow::CheckAudioUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + IGstGenericPlayerClient *client, + std::shared_ptr gstWrapper) + : m_context{context}, m_player(player), m_gstPlayerClient{client}, m_gstWrapper{gstWrapper} +{ +} + +void CheckAudioUnderflow::execute() const +{ + // TODO(LLDEV-31012) Check if the audio stream is in underflow state. + if (m_context.streamInfo.find(firebolt::rialto::MediaSourceType::AUDIO) != m_context.streamInfo.end()) + { + gint64 position = m_player.getPosition(m_context.pipeline); + if (position == -1) + { + RIALTO_SERVER_LOG_WARN("Getting the position failed"); + return; + } + + constexpr int64_t kAudioUnderflowMarginNs = 350 * 1000000; + if ((position > m_context.lastAudioSampleTimestamps + kAudioUnderflowMarginNs) && + m_gstWrapper->gstElementGetState(m_context.pipeline) == GST_STATE_PLAYING && + m_gstWrapper->gstElementGetPendingState(m_context.pipeline) != GST_STATE_PAUSED) + { + RIALTO_SERVER_LOG_WARN("Audio stream underflow! Position %" PRIu64 ", lastAudioSampleTimestamps: %" PRIu64, + position, m_context.lastAudioSampleTimestamps); + bool underflowEnabled = m_context.isPlaying && !m_context.audioSourceRemoved; + Underflow task(m_context, m_player, m_gstPlayerClient, underflowEnabled, MediaSourceType::AUDIO); + task.execute(); + } + } +} + +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp new file mode 100644 index 000000000..56526fd4f --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp @@ -0,0 +1,112 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/DeepElementAdded.h" +#include "RialtoServerLogging.h" + +namespace +{ +void onHaveType(GstElement *typefind, guint probability, const GstCaps *caps, gpointer data) +{ + firebolt::rialto::server::IGstGenericPlayerPrivate *player = + static_cast(data); + player->updatePlaybackGroup(typefind, caps); +} +} // namespace + +namespace firebolt::rialto::server::tasks::generic +{ +DeepElementAdded::DeepElementAdded(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + GstBin *pipeline, GstBin *bin, GstElement *element) + : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_pipeline{pipeline}, + m_bin{bin}, m_element{element}, m_elementName{nullptr}, m_callbackRegistered{false} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing DeepElementAdded"); + // Signal connection has to happen immediately (we cannot wait for thread switch) + if (m_gstWrapper->gstObjectParent(m_element) == m_gstWrapper->gstObjectCast(m_bin)) + { + m_elementName = m_gstWrapper->gstElementGetName(m_element); + if (m_elementName) + { + RIALTO_SERVER_LOG_DEBUG("Element Name = %s", m_elementName); + if (m_glibWrapper->gStrrstr(m_elementName, "typefind")) + { + RIALTO_SERVER_LOG_DEBUG("Registering onHaveType callback"); + m_glibWrapper->gSignalConnect(G_OBJECT(m_element), "have-type", G_CALLBACK(onHaveType), &m_player); + m_callbackRegistered = true; + } + } + } +} + +DeepElementAdded::~DeepElementAdded() +{ + RIALTO_SERVER_LOG_DEBUG("DeepElementAdded finished"); + m_glibWrapper->gFree(m_elementName); +} + +void DeepElementAdded::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing DeepElementAdded"); + m_context.playbackGroup.m_gstPipeline = GST_ELEMENT(m_pipeline); + + RIALTO_SERVER_LOG_DEBUG("Element = %p Bin = %p Pipeline = %p", m_element, m_bin, m_pipeline); + if (m_callbackRegistered) + { + m_context.playbackGroup.m_curAudioTypefind = m_element; + } + if (m_elementName) + { + if (m_gstWrapper->gstObjectCast(m_bin) == m_gstWrapper->gstObjectCast(m_context.playbackGroup.m_curAudioDecodeBin)) + { + if (m_glibWrapper->gStrrstr(m_elementName, "parse")) + { + RIALTO_SERVER_LOG_DEBUG("curAudioParse = %s", m_elementName); + m_context.playbackGroup.m_curAudioParse = m_element; + } + else if (m_glibWrapper->gStrrstr(m_elementName, "dec")) + { + RIALTO_SERVER_LOG_DEBUG("curAudioDecoder = %s", m_elementName); + m_context.playbackGroup.m_curAudioDecoder = m_element; + } + } + else + { + if (m_glibWrapper->gStrrstr(m_elementName, "audiosink")) + { + GstElement *audioSinkParent = + reinterpret_cast(m_gstWrapper->gstElementGetParent(m_element)); + if (audioSinkParent) + { + gchar *audioSinkParentName = m_gstWrapper->gstElementGetName(audioSinkParent); + RIALTO_SERVER_LOG_DEBUG("audioSinkParentName = %s", audioSinkParentName); + if (audioSinkParentName && m_glibWrapper->gStrrstr(audioSinkParentName, "bin")) + { + RIALTO_SERVER_LOG_DEBUG("curAudioPlaysinkBin = %s", audioSinkParentName); + m_context.playbackGroup.m_curAudioPlaysinkBin = audioSinkParent; + } + m_glibWrapper->gFree(audioSinkParentName); + } + } + } + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/EnoughData.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/EnoughData.cpp new file mode 100644 index 000000000..a25679eb7 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/EnoughData.cpp @@ -0,0 +1,51 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/EnoughData.h" +#include "GenericPlayerContext.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +EnoughData::EnoughData(GenericPlayerContext &context, GstAppSrc *src) : m_context{context}, m_src{src} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing EnoughData"); +} + +EnoughData::~EnoughData() +{ + RIALTO_SERVER_LOG_DEBUG("EnoughData finished"); +} + +void EnoughData::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing EnoughData"); + for (auto &elem : m_context.streamInfo) + { + firebolt::rialto::MediaSourceType sourceType = elem.first; + if (elem.second.appSrc == GST_ELEMENT(m_src)) + { + RIALTO_SERVER_LOG_DEBUG("%s source has enough data", common::convertMediaSourceType(sourceType)); + elem.second.isDataNeeded = false; + break; + } + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Eos.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Eos.cpp new file mode 100644 index 000000000..f45968e05 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Eos.cpp @@ -0,0 +1,77 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Eos.h" +#include "GenericPlayerContext.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Eos::Eos(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::shared_ptr gstWrapper, + const firebolt::rialto::MediaSourceType &type) + : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_type{type} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Eos"); +} + +Eos::~Eos() +{ + RIALTO_SERVER_LOG_DEBUG("Eos finished"); +} + +void Eos::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Eos for %s", common::convertMediaSourceType(m_type)); + + m_player.cancelUnderflow(m_type); + + auto elem = m_context.streamInfo.find(m_type); + if (elem == m_context.streamInfo.end()) + { + RIALTO_SERVER_LOG_WARN("Set eos failed - Stream not found"); + return; + } + + const auto eosInfoIt = m_context.endOfStreamInfo.find(m_type); + if (eosInfoIt != m_context.endOfStreamInfo.end() && eosInfoIt->second == EosState::SET) + { + RIALTO_SERVER_LOG_DEBUG("Eos already set for source %s", common::convertMediaSourceType(m_type)); + return; + } + + StreamInfo &streamInfo = elem->second; + if (!streamInfo.buffers.empty()) + { + RIALTO_SERVER_LOG_INFO("There are pending buffers; delaying sending EOS"); + m_context.endOfStreamInfo[m_type] = EosState::PENDING; + } + else if (m_gstWrapper->gstAppSrcEndOfStream(GST_APP_SRC(elem->second.appSrc)) != GST_FLOW_OK) + { + RIALTO_SERVER_LOG_WARN("Set eos failed - Gstreamer error"); + } + else + { + RIALTO_SERVER_LOG_MIL("Successfully set EOS for source %s", common::convertMediaSourceType(m_type)); + m_context.endOfStreamInfo[m_type] = EosState::SET; + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp new file mode 100644 index 000000000..e487e3740 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp @@ -0,0 +1,127 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/FinishSetupSource.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" +#include +#include + +namespace +{ +/** + * @brief Callback for need-data event from gstreamer. Called by the Gstreamer thread. + * + * @param[in] src : the appsrc element that emitted the signal + * @param[in] length : the amount of bytes needed. + * @param[in] user_data : The data to be passed with the message. + * + */ +void appSrcNeedData(GstAppSrc *src, guint length, gpointer user_data) +{ + firebolt::rialto::server::IGstGenericPlayerPrivate *self = + static_cast(user_data); + self->scheduleNeedMediaData(src); +} + +/** + * @brief Callback for enough-data event from gstreamer. Called by the Gstreamer thread. + * + * @param[in] src : the appsrc element that emitted the signal + * @param[in] user_data : The data to be passed with the message. + * + */ +void appSrcEnoughData(GstAppSrc *src, gpointer user_data) +{ + firebolt::rialto::server::IGstGenericPlayerPrivate *self = + static_cast(user_data); + self->scheduleEnoughData(src); +} + +/** + * @brief Callback for seek-data event from gstreamer. Called by the Gstreamer thread. + * + * @param[in] src : the appsrc element that emitted the signal + * @param[in] offset : the offset to seek to + * @param[in] user_data : The data to be passed with the message. + * + * @retval true if the handling of the message is successful, false otherwise. + */ +gboolean appSrcSeekData(GstAppSrc *src, guint64 offset, gpointer user_data) +{ + appSrcEnoughData(src, user_data); + return TRUE; +} +} // namespace + +namespace firebolt::rialto::server::tasks::generic +{ +FinishSetupSource::FinishSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + IGstGenericPlayerClient *client) + : m_context{context}, m_player{player}, m_gstPlayerClient{client} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing FinishSetupSource"); +} + +FinishSetupSource::~FinishSetupSource() +{ + RIALTO_SERVER_LOG_DEBUG("FinishSetupSource finished"); +} + +void FinishSetupSource::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing FinishSetupSource"); + m_context.wereAllSourcesAttached = true; + + if (!m_context.source) + { + RIALTO_SERVER_LOG_DEBUG("Source is not ready"); + return; + } + + GstAppSrcCallbacks callbacks = {appSrcNeedData, appSrcEnoughData, appSrcSeekData, {nullptr}}; + + for (auto &elem : m_context.streamInfo) + { + firebolt::rialto::MediaSourceType sourceType = elem.first; + if (sourceType == firebolt::rialto::MediaSourceType::UNKNOWN) + { + RIALTO_SERVER_LOG_WARN("Unknown media segment type"); + continue; + } + + StreamInfo &streamInfo = elem.second; + m_context.gstSrc->setupAndAddAppSrc(m_context.decryptionService, m_context.source, streamInfo, &callbacks, + &m_player, sourceType); + m_player.notifyNeedMediaData(sourceType); + } + + m_context.gstSrc->allAppSrcsAdded(m_context.source); + + // Notify GstPlayerClient of Idle state once setup has finished + if (m_gstPlayerClient) + m_gstPlayerClient->notifyPlaybackState(PlaybackState::IDLE); + + m_context.setupSourceFinished = true; + + RIALTO_SERVER_LOG_MIL("All sources attached."); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Flush.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Flush.cpp new file mode 100644 index 000000000..82a61d729 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Flush.cpp @@ -0,0 +1,110 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Flush.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Flush::Flush(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + std::shared_ptr gstWrapper, const MediaSourceType &type, + bool resetTime) + : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_type{type}, + m_resetTime{resetTime} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Flush"); +} + +Flush::~Flush() +{ + RIALTO_SERVER_LOG_DEBUG("Flush finished"); +} + +void Flush::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Flush for %s source", common::convertMediaSourceType(m_type)); + + // Get source first + GstElement *source{nullptr}; + auto sourceElem = m_context.streamInfo.find(m_type); + if (sourceElem != m_context.streamInfo.end()) + { + source = sourceElem->second.appSrc; + } + if (!source) + { + RIALTO_SERVER_LOG_WARN("failed to flush %s - source is NULL", common::convertMediaSourceType(m_type)); + return; + } + + if (m_type == MediaSourceType::UNKNOWN) + { + RIALTO_SERVER_LOG_WARN("Flush failed: Media source type not supported."); + return; + } + + StreamInfo &streamInfo = sourceElem->second; + streamInfo.isDataNeeded = false; + streamInfo.isNeedDataPending = false; + m_player.clearNeedDataScheduled(GST_APP_SRC(source)); + + for (auto &buffer : streamInfo.buffers) + { + m_gstWrapper->gstBufferUnref(buffer); + } + streamInfo.buffers.clear(); + + m_gstPlayerClient->invalidateActiveRequests(m_type); + + if (GST_STATE(m_context.pipeline) >= GST_STATE_PAUSED) + { + m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); + // Flush source + GstEvent *flushStart = m_gstWrapper->gstEventNewFlushStart(); + if (!m_gstWrapper->gstElementSendEvent(source, flushStart)) + { + RIALTO_SERVER_LOG_WARN("failed to send flush-start event for %s", common::convertMediaSourceType(m_type)); + } + + GstEvent *flushStop = m_gstWrapper->gstEventNewFlushStop(m_resetTime); + if (!m_gstWrapper->gstElementSendEvent(source, flushStop)) + { + RIALTO_SERVER_LOG_WARN("failed to send flush-stop event for %s", common::convertMediaSourceType(m_type)); + } + } + else + { + RIALTO_SERVER_LOG_DEBUG("Skip sending flush event for %s - pipeline below paused", + common::convertMediaSourceType(m_type)); + } + + // Reset Eos info + m_context.endOfStreamInfo.erase(m_type); + m_context.eosNotified = false; + + // Notify client, that flush has been finished + m_gstPlayerClient->notifySourceFlushed(m_type); + + // Notify GstGenericPlayer, that flush has been finished + m_player.setSourceFlushed(m_type); + + RIALTO_SERVER_LOG_MIL("%s source flushed.", common::convertMediaSourceType(m_type)); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp new file mode 100644 index 000000000..83101affe --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp @@ -0,0 +1,363 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tasks/generic/GenericPlayerTaskFactory.h" +#include "IMediaPipeline.h" +#include "tasks/generic/AttachSamples.h" +#include "tasks/generic/AttachSource.h" +#include "tasks/generic/CheckAudioUnderflow.h" +#include "tasks/generic/DeepElementAdded.h" +#include "tasks/generic/EnoughData.h" +#include "tasks/generic/Eos.h" +#include "tasks/generic/FinishSetupSource.h" +#include "tasks/generic/Flush.h" +#include "tasks/generic/HandleBusMessage.h" +#include "tasks/generic/NeedData.h" +#include "tasks/generic/Pause.h" +#include "tasks/generic/Ping.h" +#include "tasks/generic/Play.h" +#include "tasks/generic/ProcessAudioGap.h" +#include "tasks/generic/ReadShmDataAndAttachSamples.h" +#include "tasks/generic/RemoveSource.h" +#include "tasks/generic/RenderFrame.h" +#include "tasks/generic/ReportPosition.h" +#include "tasks/generic/SetBufferingLimit.h" +#include "tasks/generic/SetImmediateOutput.h" +#include "tasks/generic/SetLowLatency.h" +#include "tasks/generic/SetMute.h" +#include "tasks/generic/SetPlaybackRate.h" +#include "tasks/generic/SetPosition.h" +#include "tasks/generic/SetSourcePosition.h" +#include "tasks/generic/SetStreamSyncMode.h" +#include "tasks/generic/SetSubtitleOffset.h" +#include "tasks/generic/SetSync.h" +#include "tasks/generic/SetSyncOff.h" +#include "tasks/generic/SetTextTrackIdentifier.h" +#include "tasks/generic/SetUseBuffering.h" +#include "tasks/generic/SetVideoGeometry.h" +#include "tasks/generic/SetVolume.h" +#include "tasks/generic/SetupElement.h" +#include "tasks/generic/SetupSource.h" +#include "tasks/generic/Shutdown.h" +#include "tasks/generic/Stop.h" +#include "tasks/generic/SwitchSource.h" +#include "tasks/generic/SynchroniseSubtitleClock.h" +#include "tasks/generic/Underflow.h" +#include "tasks/generic/UpdatePlaybackGroup.h" + +namespace firebolt::rialto::server +{ +GenericPlayerTaskFactory::GenericPlayerTaskFactory( + IGstGenericPlayerClient *client, const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr &rdkGstreamerUtilsWrapper, + const std::shared_ptr &gstTextTrackSinkFactory) + : m_client{client}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, + m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, m_gstTextTrackSinkFactory{gstTextTrackSinkFactory} +{ +} + +std::unique_ptr +GenericPlayerTaskFactory::createAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const IMediaPipeline::MediaSegmentVector &mediaSegments) const +{ + return std::make_unique(context, m_gstWrapper, player, mediaSegments); +} + +std::unique_ptr +GenericPlayerTaskFactory::createAttachSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::unique_ptr &source) const +{ + return std::make_unique(context, m_gstWrapper, m_glibWrapper, + m_gstTextTrackSinkFactory, player, source); +} + +std::unique_ptr GenericPlayerTaskFactory::createDeepElementAdded(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + GstBin *pipeline, GstBin *bin, + GstElement *element) const +{ + return std::make_unique(context, player, m_gstWrapper, m_glibWrapper, pipeline, + bin, element); +} + +std::unique_ptr GenericPlayerTaskFactory::createEnoughData(GenericPlayerContext &context, GstAppSrc *src) const +{ + return std::make_unique(context, src); +} + +std::unique_ptr GenericPlayerTaskFactory::createEos(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type) const +{ + return std::make_unique(context, player, m_gstWrapper, type); +} + +std::unique_ptr GenericPlayerTaskFactory::createFinishSetupSource(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(context, player, m_client); +} + +std::unique_ptr GenericPlayerTaskFactory::createHandleBusMessage(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + GstMessage *message, + const IFlushWatcher &flushWatcher) const +{ + return std::make_unique(context, player, m_client, m_gstWrapper, m_glibWrapper, + message, flushWatcher); +} + +std::unique_ptr GenericPlayerTaskFactory::createNeedData(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + GstAppSrc *src) const +{ + return std::make_unique(context, player, m_client, src); +} + +std::unique_ptr GenericPlayerTaskFactory::createPause(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(context, player); +} + +std::unique_ptr GenericPlayerTaskFactory::createPlay(IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(player); +} + +std::unique_ptr GenericPlayerTaskFactory::createReadShmDataAndAttachSamples( + GenericPlayerContext &context, IGstGenericPlayerPrivate &player, const std::shared_ptr &dataReader) const +{ + return std::make_unique(context, m_gstWrapper, player, dataReader); +} + +std::unique_ptr +GenericPlayerTaskFactory::createRemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type) const +{ + return std::make_unique(context, player, m_client, m_gstWrapper, type); +} + +std::unique_ptr GenericPlayerTaskFactory::createReportPosition(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(context, m_client, m_gstWrapper, player); +} + +std::unique_ptr GenericPlayerTaskFactory::createCheckAudioUnderflow(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(context, player, m_client, m_gstWrapper); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetPlaybackRate(GenericPlayerContext &context, + double rate) const +{ + return std::make_unique(context, m_gstWrapper, m_glibWrapper, rate); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetPosition(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + std::int64_t position) const +{ + return std::make_unique(context, player, m_client, m_gstWrapper, position); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetupElement(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + GstElement *element) const +{ + return std::make_unique(context, m_gstWrapper, m_glibWrapper, player, element); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetupSource(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + GstElement *source) const +{ + return std::make_unique(context, player, source); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetVideoGeometry(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const Rectangle &rectangle) const +{ + return std::make_unique(context, player, rectangle); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetVolume(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + double targetVolume, uint32_t volumeDuration, + firebolt::rialto::EaseType easeType) const +{ + return std::make_unique(context, player, m_gstWrapper, m_glibWrapper, + m_rdkGstreamerUtilsWrapper, targetVolume, volumeDuration, + easeType); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetMute(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const MediaSourceType &mediaSourceType, + bool mute) const +{ + return std::make_unique(context, player, m_gstWrapper, m_glibWrapper, mediaSourceType, mute); +} + +std::unique_ptr +GenericPlayerTaskFactory::createSetTextTrackIdentifier(GenericPlayerContext &context, + const std::string &textTrackIdentifier) const +{ + return std::make_unique(context, m_glibWrapper, textTrackIdentifier); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetLowLatency(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + bool lowLatency) const +{ + return std::make_unique(context, player, lowLatency); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetSync(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, bool sync) const +{ + return std::make_unique(context, player, sync); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetSyncOff(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + bool syncOff) const +{ + return std::make_unique(context, player, syncOff); +} + +std::unique_ptr +GenericPlayerTaskFactory::createSetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + int32_t streamSyncMode) const +{ + return std::make_unique(context, player, type, streamSyncMode); +} + +std::unique_ptr GenericPlayerTaskFactory::createShutdown(IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(player); +} + +std::unique_ptr GenericPlayerTaskFactory::createStop(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(context, player); +} + +std::unique_ptr GenericPlayerTaskFactory::createUnderflow(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + bool underflowEnabled, + MediaSourceType sourceType) const +{ + return std::make_unique(context, player, m_client, underflowEnabled, sourceType); +} + +std::unique_ptr GenericPlayerTaskFactory::createUpdatePlaybackGroup(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + GstElement *typefind, + const GstCaps *caps) const +{ + return std::make_unique(context, player, m_gstWrapper, m_glibWrapper, typefind, + caps); +} + +std::unique_ptr GenericPlayerTaskFactory::createRenderFrame(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(context, player); +} + +std::unique_ptr GenericPlayerTaskFactory::createPing(std::unique_ptr &&heartbeatHandler) const +{ + return std::make_unique(std::move(heartbeatHandler)); +} + +std::unique_ptr GenericPlayerTaskFactory::createFlush(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + bool resetTime) const +{ + return std::make_unique(context, player, m_client, m_gstWrapper, type, resetTime); +} + +std::unique_ptr +GenericPlayerTaskFactory::createSetSourcePosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, std::int64_t position, + bool resetTime, double appliedRate, uint64_t stopPosition) const +{ + return std::make_unique(context, player, m_client, m_glibWrapper, type, position, + resetTime, appliedRate, stopPosition); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetSubtitleOffset(GenericPlayerContext &context, + std::int64_t position) const +{ + return std::make_unique(context, m_glibWrapper, position); +} + +std::unique_ptr GenericPlayerTaskFactory::createProcessAudioGap(GenericPlayerContext &context, + std::int64_t position, + std::uint32_t duration, + std::int64_t discontinuityGap, + bool audioAac) const +{ + return std::make_unique(context, m_gstWrapper, m_glibWrapper, + m_rdkGstreamerUtilsWrapper, position, duration, + discontinuityGap, audioAac); +} + +std::unique_ptr +GenericPlayerTaskFactory::createSetImmediateOutput(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const firebolt::rialto::MediaSourceType &type, + bool immediateOutput) const +{ + return std::make_unique(context, player, type, immediateOutput); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetBufferingLimit(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + std::uint32_t limit) const +{ + return std::make_unique(context, player, limit); +} + +std::unique_ptr GenericPlayerTaskFactory::createSetUseBuffering(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player, + bool useBuffering) const +{ + return std::make_unique(context, player, useBuffering); +} + +std::unique_ptr +GenericPlayerTaskFactory::createSwitchSource(IGstGenericPlayerPrivate &player, + const std::unique_ptr &source) const +{ + return std::make_unique(player, source); +} + +std::unique_ptr GenericPlayerTaskFactory::createSynchroniseSubtitleClock(GenericPlayerContext &context, + IGstGenericPlayerPrivate &player) const +{ + return std::make_unique(context, player, m_gstWrapper, m_glibWrapper); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp new file mode 100644 index 000000000..3905becb1 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp @@ -0,0 +1,295 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/HandleBusMessage.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +HandleBusMessage::HandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + IGstGenericPlayerClient *client, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + GstMessage *message, const IFlushWatcher &flushWatcher) + : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, + m_glibWrapper{glibWrapper}, m_message{message}, m_flushWatcher{flushWatcher}, + m_isFlushOngoingDuringCreation{flushWatcher.isFlushOngoing()}, + m_isAsyncFlushOngoingDuringCreation{flushWatcher.isAsyncFlushOngoing()} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing HandleBusMessage"); +} + +HandleBusMessage::~HandleBusMessage() +{ + RIALTO_SERVER_LOG_DEBUG("HandleBusMessage finished"); +} + +void HandleBusMessage::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing HandleBusMessage"); + switch (GST_MESSAGE_TYPE(m_message)) + { + case GST_MESSAGE_STATE_CHANGED: + { + if (m_context.pipeline && GST_MESSAGE_SRC(m_message) == GST_OBJECT(m_context.pipeline)) + { + GstState oldState, newState, pending; + m_gstWrapper->gstMessageParseStateChanged(m_message, &oldState, &newState, &pending); + RIALTO_SERVER_LOG_MIL("State changed (old: %s, new: %s, pending: %s)", + m_gstWrapper->gstElementStateGetName(oldState), + m_gstWrapper->gstElementStateGetName(newState), + m_gstWrapper->gstElementStateGetName(pending)); + + if (!m_gstPlayerClient) + { + break; + } + switch (newState) + { + case GST_STATE_NULL: + { + m_gstPlayerClient->notifyPlaybackState(PlaybackState::STOPPED); + break; + } + case GST_STATE_PAUSED: + { + if (pending != GST_STATE_PAUSED) + { + // If async flush was requested before HandleBusMessage task creation (but it was not executed yet) + // or if async flush was created after HandleBusMessage task creation (but before its execution) + // we can't report playback state, because async flush causes state loss - reported state is probably invalid. + if (m_isAsyncFlushOngoingDuringCreation || m_flushWatcher.isAsyncFlushOngoing()) + { + RIALTO_SERVER_LOG_WARN("Skip PAUSED notification - flush is ongoing"); + break; + } + // newState==GST_STATE_PAUSED, pending==GST_STATE_PAUSED state transition is received as a result of + // waiting for preroll after seek. + // Subsequent newState==GST_STATE_PAUSED, pending!=GST_STATE_PAUSED transition will + // indicate that the pipeline is prerolled and it reached GST_STATE_PAUSED state after seek. + m_gstPlayerClient->notifyPlaybackState(PlaybackState::PAUSED); + } + if (m_player.hasSourceType(MediaSourceType::SUBTITLE)) + { + m_player.stopSubtitleClockResyncTimer(); + } + break; + } + case GST_STATE_PLAYING: + { + // If async flush was requested before HandleBusMessage task creation (but it was not executed yet) + // or if async flush was created after HandleBusMessage task creation (but before its execution) + // we can't report playback state, because async flush causes state loss - reported state is probably invalid. + if (m_isAsyncFlushOngoingDuringCreation || m_flushWatcher.isAsyncFlushOngoing()) + { + RIALTO_SERVER_LOG_WARN("Skip PLAYING notification - flush is ongoing"); + break; + } + + m_context.isPlaying = true; + m_gstPlayerClient->notifyPlaybackState(PlaybackState::PLAYING); + + if (m_context.pendingPlaybackRate != kNoPendingPlaybackRate) + { + m_player.setPendingPlaybackRate(); + } + m_player.startPositionReportingAndCheckAudioUnderflowTimer(); + if (m_player.hasSourceType(MediaSourceType::SUBTITLE)) + { + m_player.startSubtitleClockResyncTimer(); + } + break; + } + case GST_STATE_VOID_PENDING: + case GST_STATE_READY: + { + break; + } + } + std::string filename = std::string(m_gstWrapper->gstElementStateGetName(oldState)) + "-" + + std::string(m_gstWrapper->gstElementStateGetName(newState)); + m_gstWrapper->gstDebugBinToDotFileWithTs(GST_BIN(m_context.pipeline), GST_DEBUG_GRAPH_SHOW_ALL, + filename.c_str()); + } + break; + } + case GST_MESSAGE_EOS: + { + // If flush was requested before HandleBusMessage task creation (but it was not executed yet) + // or if flush was created after HandleBusMessage task creation (but before its execution) + // we can't report EOS, because flush clears EOS. + if (m_isFlushOngoingDuringCreation || m_flushWatcher.isFlushOngoing()) + { + RIALTO_SERVER_LOG_WARN("Skip EOS notification - flush is ongoing"); + break; + } + if (m_context.pipeline && GST_MESSAGE_SRC(m_message) == GST_OBJECT(m_context.pipeline)) + { + RIALTO_SERVER_LOG_MIL("End of stream reached."); + if (!m_context.eosNotified && m_gstPlayerClient) + { + m_gstPlayerClient->notifyPlaybackState(PlaybackState::END_OF_STREAM); + m_context.eosNotified = true; + } + } + break; + } + case GST_MESSAGE_QOS: + { + GstFormat format; + gboolean isLive = FALSE; + guint64 runningTime = 0; + guint64 streamTime = 0; + guint64 timestamp = 0; + guint64 duration = 0; + guint64 dropped = 0; + guint64 processed = 0; + + m_gstWrapper->gstMessageParseQos(m_message, &isLive, &runningTime, &streamTime, ×tamp, &duration); + m_gstWrapper->gstMessageParseQosStats(m_message, &format, &processed, &dropped); + + if (GST_FORMAT_BUFFERS == format || GST_FORMAT_DEFAULT == format) + { + RIALTO_SERVER_LOG_INFO("QOS message: runningTime %" G_GUINT64_FORMAT ", streamTime %" G_GUINT64_FORMAT + ", timestamp %" G_GUINT64_FORMAT ", duration %" G_GUINT64_FORMAT + ", format %u, processed %" G_GUINT64_FORMAT ", dropped %" G_GUINT64_FORMAT, + runningTime, streamTime, timestamp, duration, format, processed, dropped); + + if (m_gstPlayerClient) + { + firebolt::rialto::QosInfo qosInfo = {processed, dropped}; + const gchar *klass; + klass = m_gstWrapper->gstElementClassGetMetadata(GST_ELEMENT_GET_CLASS(GST_MESSAGE_SRC(m_message)), + GST_ELEMENT_METADATA_KLASS); + + if (g_strrstr(klass, "Video")) + { + m_gstPlayerClient->notifyQos(firebolt::rialto::MediaSourceType::VIDEO, qosInfo); + } + else if (g_strrstr(klass, "Audio")) + { + m_gstPlayerClient->notifyQos(firebolt::rialto::MediaSourceType::AUDIO, qosInfo); + } + else + { + RIALTO_SERVER_LOG_WARN("Unknown source type for class '%s', ignoring QOS Message", klass); + } + } + } + else + { + RIALTO_SERVER_LOG_WARN("Received a QOS_MESSAGE with unhandled format %s", + m_gstWrapper->gstFormatGetName(format)); + } + break; + } + case GST_MESSAGE_ERROR: + { + GError *err = nullptr; + gchar *debug = nullptr; + m_gstWrapper->gstMessageParseError(m_message, &err, &debug); + + if ((err->domain == GST_STREAM_ERROR) && (allSourcesEos())) + { + RIALTO_SERVER_LOG_WARN("Got stream error from %s. But all streams are ended, so reporting EOS. Error code " + "%d: %s " + "(%s).", + GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), err->code, err->message, debug); + if (!m_context.eosNotified && m_gstPlayerClient) + { + m_gstPlayerClient->notifyPlaybackState(PlaybackState::END_OF_STREAM); + m_context.eosNotified = true; + } + } + else + { + RIALTO_SERVER_LOG_ERROR("Error from %s - %d: %s (%s)", GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), + err->code, err->message, debug); + m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); + } + + m_glibWrapper->gFree(debug); + m_glibWrapper->gErrorFree(err); + break; + } + case GST_MESSAGE_WARNING: + { + PlaybackError rialtoError = PlaybackError::UNKNOWN; + GError *err = nullptr; + gchar *debug = nullptr; + m_gstWrapper->gstMessageParseWarning(m_message, &err, &debug); + + if ((err->domain == GST_STREAM_ERROR) && (err->code == GST_STREAM_ERROR_DECRYPT)) + { + RIALTO_SERVER_LOG_WARN("Decrypt error %s - %d: %s (%s)", GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), + err->code, err->message, debug); + rialtoError = PlaybackError::DECRYPTION; + } + else + { + RIALTO_SERVER_LOG_WARN("Unknown warning, ignoring %s - %d: %s (%s)", + GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), err->code, err->message, debug); + } + + if ((PlaybackError::UNKNOWN != rialtoError) && (m_gstPlayerClient)) + { + const gchar *kName = GST_ELEMENT_NAME(GST_ELEMENT(GST_MESSAGE_SRC(m_message))); + if (g_strrstr(kName, "video")) + { + m_gstPlayerClient->notifyPlaybackError(firebolt::rialto::MediaSourceType::VIDEO, + PlaybackError::DECRYPTION); + } + else if (g_strrstr(kName, "audio")) + { + m_gstPlayerClient->notifyPlaybackError(firebolt::rialto::MediaSourceType::AUDIO, + PlaybackError::DECRYPTION); + } + else + { + RIALTO_SERVER_LOG_WARN("Unknown source type for element '%s', not propagating error", kName); + } + } + + m_glibWrapper->gFree(debug); + m_glibWrapper->gErrorFree(err); + break; + } + default: + break; + } + + m_gstWrapper->gstMessageUnref(m_message); +} + +bool HandleBusMessage::allSourcesEos() const +{ + for (const auto &streamInfo : m_context.streamInfo) + { + const auto eosInfoIt = m_context.endOfStreamInfo.find(streamInfo.first); + if (eosInfoIt == m_context.endOfStreamInfo.end() || eosInfoIt->second != EosState::SET) + { + return false; + } + } + return true; +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/NeedData.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/NeedData.cpp new file mode 100644 index 000000000..5f0a6b5b1 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/NeedData.cpp @@ -0,0 +1,73 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/NeedData.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +NeedData::NeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + GstAppSrc *src) + : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_src{src} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing NeedData"); +} + +NeedData::~NeedData() +{ + RIALTO_SERVER_LOG_DEBUG("NeedData finished"); +} + +void NeedData::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing NeedData"); + + for (auto &elem : m_context.streamInfo) + { + firebolt::rialto::MediaSourceType sourceType = elem.first; + if (elem.second.appSrc == GST_ELEMENT(m_src)) + { + RIALTO_SERVER_LOG_DEBUG("%s source needs data", common::convertMediaSourceType(sourceType)); + + elem.second.isDataNeeded = true; + + if (!elem.second.buffers.empty()) + { + RIALTO_SERVER_LOG_INFO("Attaching cached data for %s", common::convertMediaSourceType(sourceType)); + m_player.attachData(sourceType); + } + + if (m_gstPlayerClient && !elem.second.isNeedDataPending) + { + if (sourceType == MediaSourceType::AUDIO && m_context.audioSourceRemoved) + { + RIALTO_SERVER_LOG_DEBUG("Audio source is removed, no need to request data"); + break; + } + elem.second.isNeedDataPending = m_gstPlayerClient->notifyNeedMediaData(sourceType); + } + break; + } + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Pause.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Pause.cpp new file mode 100644 index 000000000..79c9ad14c --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Pause.cpp @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Pause.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Pause::Pause(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) : m_context{context}, m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Pause"); +} + +Pause::~Pause() +{ + RIALTO_SERVER_LOG_DEBUG("Pause finished"); +} + +void Pause::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Pause"); + m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); + m_player.changePipelineState(GST_STATE_PAUSED); + m_context.isPlaying = false; + RIALTO_SERVER_LOG_MIL("State change to PAUSED requested"); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Ping.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Ping.cpp new file mode 100644 index 000000000..82a042b99 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Ping.cpp @@ -0,0 +1,40 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Ping.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Ping::Ping(std::unique_ptr &&heartbeatHandler) : m_heartbeatHandler{std::move(heartbeatHandler)} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Ping"); +} + +Ping::~Ping() +{ + RIALTO_SERVER_LOG_DEBUG("Ping finished"); + m_heartbeatHandler.reset(); +} + +void Ping::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Ping"); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Play.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Play.cpp new file mode 100644 index 000000000..fc13e3c1e --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Play.cpp @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Play.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Play::Play(IGstGenericPlayerPrivate &player) : m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Play"); +} + +Play::~Play() +{ + RIALTO_SERVER_LOG_DEBUG("Play finished"); +} + +void Play::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Play"); + m_player.changePipelineState(GST_STATE_PLAYING); + RIALTO_SERVER_LOG_MIL("State change to PLAYING requested"); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ProcessAudioGap.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ProcessAudioGap.cpp new file mode 100644 index 000000000..d4b79c451 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ProcessAudioGap.cpp @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ProcessAudioGap.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +ProcessAudioGap::ProcessAudioGap( + GenericPlayerContext &context, const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper, + const std::shared_ptr rdkGstreamerUtilsWrapper, + std::int64_t position, std::uint32_t duration, std::int64_t discontinuityGap, bool audioAac) + : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, + m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, m_position{position}, m_duration{duration}, + m_discontinuityGap{discontinuityGap}, m_audioAac{audioAac} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing ProcessAudioGap"); +} + +ProcessAudioGap::~ProcessAudioGap() +{ + RIALTO_SERVER_LOG_DEBUG("ProcessAudioGap finished"); +} + +void ProcessAudioGap::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing ProcessAudioGap"); + if (!m_context.pipeline) + { + RIALTO_SERVER_LOG_ERROR("Process audio gap failed - pipeline is null"); + return; + } + m_rdkGstreamerUtilsWrapper->processAudioGap(m_context.pipeline, m_position, m_duration, m_discontinuityGap, + m_audioAac); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp new file mode 100644 index 000000000..a01d2e4eb --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp @@ -0,0 +1,125 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/ReadShmDataAndAttachSamples.h" +#include "GenericPlayerContext.h" +#include "IDataReader.h" +#include "IGstGenericPlayerPrivate.h" +#include "IMediaPipeline.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +ReadShmDataAndAttachSamples::ReadShmDataAndAttachSamples( + GenericPlayerContext &context, const std::shared_ptr &gstWrapper, + IGstGenericPlayerPrivate &player, const std::shared_ptr &dataReader) + : m_context{context}, m_gstWrapper{gstWrapper}, m_player{player}, m_dataReader{dataReader} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing ReadShmDataAndAttachSamples"); +} + +ReadShmDataAndAttachSamples::~ReadShmDataAndAttachSamples() +{ + RIALTO_SERVER_LOG_DEBUG("ReadShmDataAndAttachSamples finished"); +} + +void ReadShmDataAndAttachSamples::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing ReadShmDataAndAttachSamples"); + // Read media segments from shared memory + IMediaPipeline::MediaSegmentVector mediaSegments = m_dataReader->readData(); + + for (const auto &mediaSegment : mediaSegments) + { + if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::UNKNOWN) + { + RIALTO_SERVER_LOG_WARN("Unknown media segment type"); + continue; + } + + GstBuffer *gstBuffer = m_player.createBuffer(*mediaSegment); + if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::VIDEO) + { + try + { + IMediaPipeline::MediaSegmentVideo &videoSegment = + dynamic_cast(*mediaSegment); + m_player.updateVideoCaps(videoSegment.getWidth(), videoSegment.getHeight(), videoSegment.getFrameRate(), + videoSegment.getCodecData()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to get the video segment, reason: %s", e.what()); + } + } + else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::AUDIO) + { + try + { + IMediaPipeline::MediaSegmentAudio &audioSegment = + dynamic_cast(*mediaSegment); + m_player.updateAudioCaps(audioSegment.getSampleRate(), audioSegment.getNumberOfChannels(), + audioSegment.getCodecData()); + m_player.addAudioClippingToBuffer(gstBuffer, audioSegment.getClippingStart(), + audioSegment.getClippingEnd()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to get the audio segment, reason: %s", e.what()); + } + } + else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::SUBTITLE) + { + if (mediaSegment->getDisplayOffset()) + { + GST_BUFFER_OFFSET(gstBuffer) = mediaSegment->getDisplayOffset().value(); + } + } + + attachData(mediaSegment->getType(), gstBuffer); + } + // All segments in vector have the same type + if (!mediaSegments.empty()) + { + const auto kMediaType{mediaSegments.front()->getType()}; + const auto kFirstTimestamp{mediaSegments.front()->getTimeStamp()}; + const auto kLastTimestamp{mediaSegments.back()->getTimeStamp()}; + RIALTO_SERVER_LOG_DEBUG("%s data received. First ts: %" GST_TIME_FORMAT " last ts: %" GST_TIME_FORMAT, + common::convertMediaSourceType(kMediaType), GST_TIME_ARGS(kFirstTimestamp), + GST_TIME_ARGS(kLastTimestamp)); + m_player.notifyNeedMediaData(kMediaType); + } +} + +void ReadShmDataAndAttachSamples::attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const +{ + auto elem = m_context.streamInfo.find(mediaType); + if (elem != m_context.streamInfo.end()) + { + elem->second.buffers.push_back(buffer); + m_player.attachData(mediaType); + } + else + { + RIALTO_SERVER_LOG_WARN("Could not find stream info for %s", common::convertMediaSourceType(mediaType)); + m_gstWrapper->gstBufferUnref(buffer); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp new file mode 100644 index 000000000..7d9314df0 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp @@ -0,0 +1,82 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/RemoveSource.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +RemoveSource::RemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + IGstGenericPlayerClient *client, + std::shared_ptr gstWrapper, + const MediaSourceType &type) + : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_type{type} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing RemoveSource"); +} + +RemoveSource::~RemoveSource() +{ + RIALTO_SERVER_LOG_DEBUG("RemoveSource finished"); +} + +void RemoveSource::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing RemoveSource for %s source", common::convertMediaSourceType(m_type)); + if (MediaSourceType::AUDIO != m_type) + { + RIALTO_SERVER_LOG_DEBUG("RemoveSource not supported for type != AUDIO"); + return; + } + m_context.audioSourceRemoved = true; + m_gstPlayerClient->invalidateActiveRequests(m_type); + GstElement *source{nullptr}; + auto sourceElem = m_context.streamInfo.find(m_type); + if (sourceElem != m_context.streamInfo.end()) + { + source = sourceElem->second.appSrc; + } + if (!source) + { + RIALTO_SERVER_LOG_WARN("failed to flush - source is NULL"); + return; + } + sourceElem->second.buffers.clear(); + sourceElem->second.isDataNeeded = false; + sourceElem->second.isNeedDataPending = false; + m_player.clearNeedDataScheduled(GST_APP_SRC(sourceElem->second.appSrc)); + m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); + GstEvent *flushStart = m_gstWrapper->gstEventNewFlushStart(); + if (!m_gstWrapper->gstElementSendEvent(source, flushStart)) + { + RIALTO_SERVER_LOG_WARN("failed to send flush-start event"); + } + GstEvent *flushStop = m_gstWrapper->gstEventNewFlushStop(FALSE); + if (!m_gstWrapper->gstElementSendEvent(source, flushStop)) + { + RIALTO_SERVER_LOG_WARN("failed to send flush-stop event"); + } + + // Turn audio off, removing audio sink from playsink + m_player.setPlaybinFlags(false); + + RIALTO_SERVER_LOG_MIL("%s source removed", common::convertMediaSourceType(m_type)); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RenderFrame.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RenderFrame.cpp new file mode 100644 index 000000000..04b386e8e --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RenderFrame.cpp @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "RenderFrame.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +RenderFrame::RenderFrame(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) + : m_context{context}, m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing RenderFrame"); +} + +RenderFrame::~RenderFrame() +{ + RIALTO_SERVER_LOG_DEBUG("RenderFrame finished"); +} + +void RenderFrame::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing RenderFrame"); + + m_context.pendingRenderFrame = true; + if (m_context.pipeline) + { + m_player.setRenderFrame(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReportPosition.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReportPosition.cpp new file mode 100644 index 000000000..2eb46d7c1 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReportPosition.cpp @@ -0,0 +1,50 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/ReportPosition.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +ReportPosition::ReportPosition(GenericPlayerContext &context, IGstGenericPlayerClient *client, + const std::shared_ptr &gstWrapper, + IGstGenericPlayerPrivate &player) + : m_context{context}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_player{player} +{ +} + +void ReportPosition::execute() const +{ + gint64 position = m_player.getPosition(m_context.pipeline); + if (position == -1) + { + RIALTO_SERVER_LOG_WARN("Getting the position failed"); + return; + } + + if (m_gstPlayerClient) + { + m_gstPlayerClient->notifyPosition(position); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetBufferingLimit.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetBufferingLimit.cpp new file mode 100644 index 000000000..92922aa5a --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetBufferingLimit.cpp @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetBufferingLimit.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetBufferingLimit::SetBufferingLimit(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, std::uint32_t limit) + : m_context{context}, m_player(player), m_limit{limit} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetBufferingLimit"); +} + +SetBufferingLimit::~SetBufferingLimit() +{ + RIALTO_SERVER_LOG_DEBUG("SetBufferingLimit finished"); +} + +void SetBufferingLimit::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetBufferingLimit"); + + m_context.pendingBufferingLimit = m_limit; + if (m_context.pipeline) + { + m_player.setBufferingLimit(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetImmediateOutput.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetImmediateOutput.cpp new file mode 100644 index 000000000..4bb34e834 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetImmediateOutput.cpp @@ -0,0 +1,56 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetImmediateOutput.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetImmediateOutput::SetImmediateOutput(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const MediaSourceType &type, bool immediateOutput) + : m_context{context}, m_player(player), m_type{type}, m_immediateOutput{immediateOutput} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetImmediateOutput"); +} + +SetImmediateOutput::~SetImmediateOutput() +{ + RIALTO_SERVER_LOG_DEBUG("SetImmediateOutput finished"); +} + +void SetImmediateOutput::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetImmediateOutput for %s source", common::convertMediaSourceType(m_type)); + + if (m_type == MediaSourceType::VIDEO) + { + m_context.pendingImmediateOutputForVideo = m_immediateOutput; + } + else + { + RIALTO_SERVER_LOG_ERROR("SetImmediateOutput not currently supported for non-video"); + } + + if (m_context.pipeline) + { + m_player.setImmediateOutput(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetLowLatency.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetLowLatency.cpp new file mode 100644 index 000000000..85764237e --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetLowLatency.cpp @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetLowLatency.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetLowLatency::SetLowLatency(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool lowLatency) + : m_context(context), m_player(player), m_lowLatency{lowLatency} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetLowLatency"); +} + +SetLowLatency::~SetLowLatency() +{ + RIALTO_SERVER_LOG_DEBUG("SetLowLatency finished"); +} + +void SetLowLatency::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetLowLatency"); + + m_context.pendingLowLatency = m_lowLatency; + if (m_context.pipeline) + { + m_player.setLowLatency(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetMute.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetMute.cpp new file mode 100644 index 000000000..36c609b6f --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetMute.cpp @@ -0,0 +1,77 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SetMute.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +SetMute::SetMute(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const MediaSourceType &mediaSourceType, bool mute) + : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, + m_mediaSourceType{mediaSourceType}, m_mute{mute} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetMute"); +} + +SetMute::~SetMute() +{ + RIALTO_SERVER_LOG_DEBUG("SetMute finished"); +} + +void SetMute::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetMute"); + if (m_mediaSourceType == MediaSourceType::SUBTITLE) + { + if (!m_context.subtitleSink) + { + RIALTO_SERVER_LOG_ERROR("There is no subtitle sink"); + return; + } + m_glibWrapper->gObjectSet(m_context.subtitleSink, "mute", m_mute, nullptr); + } + else if (m_mediaSourceType == MediaSourceType::AUDIO) + { + if (!m_context.pipeline) + { + RIALTO_SERVER_LOG_ERROR("Setting mute failed. Pipeline is NULL"); + return; + } + m_gstWrapper->gstStreamVolumeSetMute(GST_STREAM_VOLUME(m_context.pipeline), m_mute); + } + else if (m_mediaSourceType == MediaSourceType::VIDEO) + { + m_context.pendingShowVideoWindow = !m_mute; + m_player.setShowVideoWindow(); + } + else + { + RIALTO_SERVER_LOG_ERROR("Setting mute for type %s unsupported", + common::convertMediaSourceType(m_mediaSourceType)); + return; + } + RIALTO_SERVER_LOG_MIL("%s source %s", common::convertMediaSourceType(m_mediaSourceType), + (m_mute ? "muted" : "unmuted")); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp new file mode 100644 index 000000000..5f0c6de85 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp @@ -0,0 +1,105 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SetPlaybackRate.h" +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include + +namespace +{ +const char kCustomInstantRateChangeEventName[] = "custom-instant-rate-change"; +} // namespace + +namespace firebolt::rialto::server::tasks::generic +{ +SetPlaybackRate::SetPlaybackRate(GenericPlayerContext &context, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, double rate) + : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_rate{rate} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetPlaybackRate"); +} + +SetPlaybackRate::~SetPlaybackRate() +{ + RIALTO_SERVER_LOG_DEBUG("SetPlaybackRate finished"); +} + +void SetPlaybackRate::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetPlaybackRate"); + if (m_context.playbackRate == m_rate) + { + RIALTO_SERVER_LOG_DEBUG("No need to change playback rate - it is already %lf", m_rate); + return; + } + + if (!m_context.pipeline) + { + RIALTO_SERVER_LOG_INFO("Postponing set playback rate to %lf. Pipeline is NULL", m_rate); + m_context.pendingPlaybackRate = m_rate; + return; + } + + if (GST_STATE(m_context.pipeline) < GST_STATE_PLAYING) + { + RIALTO_SERVER_LOG_INFO("Postponing set playback rate to %lf. Pipeline state is below PLAYING", m_rate); + m_context.pendingPlaybackRate = m_rate; + return; + } + m_context.pendingPlaybackRate = kNoPendingPlaybackRate; + + GstElement *audioSink{nullptr}; + gboolean success{FALSE}; + m_glibWrapper->gObjectGet(m_context.pipeline, "audio-sink", &audioSink, nullptr); + if (audioSink && m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(audioSink), "amlhalasink")) + { + GstSegment *segment{m_gstWrapper->gstSegmentNew()}; + m_gstWrapper->gstSegmentInit(segment, GST_FORMAT_TIME); + segment->rate = m_rate; + segment->start = GST_CLOCK_TIME_NONE; + segment->position = GST_CLOCK_TIME_NONE; + success = m_gstWrapper->gstPadSendEvent(GST_BASE_SINK_PAD(audioSink), m_gstWrapper->gstEventNewSegment(segment)); + RIALTO_SERVER_LOG_DEBUG("Sent new segment, success = %s", success ? "true" : "false"); + m_gstWrapper->gstSegmentFree(segment); + } + else + { + GstStructure *structure{ + m_gstWrapper->gstStructureNew(kCustomInstantRateChangeEventName, "rate", G_TYPE_DOUBLE, m_rate, NULL)}; + success = m_gstWrapper->gstElementSendEvent(m_context.pipeline, + m_gstWrapper->gstEventNewCustom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, + structure)); + RIALTO_SERVER_LOG_DEBUG("Sent new event, success = %s", success ? "true" : "false"); + } + + if (success) + { + RIALTO_SERVER_LOG_MIL("Playback rate set to: %lf", m_rate); + m_context.playbackRate = m_rate; + } + + if (audioSink) + { + m_glibWrapper->gObjectUnref(audioSink); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPosition.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPosition.cpp new file mode 100644 index 000000000..0ee4cb320 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPosition.cpp @@ -0,0 +1,106 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SetPosition.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerClient.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include "tasks/generic/NeedData.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetPosition::SetPosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + std::shared_ptr gstWrapper, std::int64_t position) + : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_position{position} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetPosition"); +} + +SetPosition::~SetPosition() +{ + RIALTO_SERVER_LOG_DEBUG("SetPosition finished"); +} + +void SetPosition::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetPosition"); + if (!m_gstPlayerClient) + { + RIALTO_SERVER_LOG_ERROR("Seek failed - GstPlayerClient is NULL"); + return; + } + m_gstPlayerClient->notifyPlaybackState(PlaybackState::SEEKING); + + // Stop sending new NeedMediaData requests + for (auto &elem : m_context.streamInfo) + { + StreamInfo &streamInfo = elem.second; + streamInfo.isDataNeeded = false; + streamInfo.isNeedDataPending = false; + m_player.clearNeedDataScheduled(GST_APP_SRC(streamInfo.appSrc)); + + // Clear buffered samples for player session + for (auto &buffer : streamInfo.buffers) + { + m_gstWrapper->gstBufferUnref(buffer); + } + + streamInfo.buffers.clear(); + } + + // Clear local cache of any active data requests for player session + m_gstPlayerClient->clearActiveRequestsCache(); + m_context.lastAudioSampleTimestamps = m_position; + + if (!m_context.pipeline) + { + RIALTO_SERVER_LOG_ERROR("Seek failed - pipeline is null"); + m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); + return; + } + if (!m_gstWrapper->gstElementSeek(m_context.pipeline, m_context.playbackRate, GST_FORMAT_TIME, + static_cast(GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_SET, m_position, + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) + { + RIALTO_SERVER_LOG_ERROR("Seek failed - gstreamer error"); + m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); + return; + } + + RIALTO_SERVER_LOG_MIL("Pipeline seek to: %" GST_TIME_FORMAT, GST_TIME_ARGS(m_position)); + + // Reset Eos info + m_context.endOfStreamInfo.clear(); + m_context.eosNotified = false; + + m_gstPlayerClient->notifyPlaybackState(PlaybackState::SEEK_DONE); + + // Trigger NeedMediaData for all attached sources + for (const auto &streamInfo : m_context.streamInfo) + { + if (streamInfo.second.appSrc) + { + NeedData task{m_context, m_player, m_gstPlayerClient, GST_APP_SRC(streamInfo.second.appSrc)}; + task.execute(); + } + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSourcePosition.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSourcePosition.cpp new file mode 100644 index 000000000..2e2dffb57 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSourcePosition.cpp @@ -0,0 +1,104 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetSourcePosition.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" +#include "tasks/generic/NeedData.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetSourcePosition::SetSourcePosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + IGstGenericPlayerClient *client, + const std::shared_ptr &glibWrapper, + const MediaSourceType &type, std::int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) + : m_context{context}, m_player(player), m_gstPlayerClient{client}, m_glibWrapper{glibWrapper}, m_type{type}, + m_position{position}, m_resetTime{resetTime}, m_appliedRate{appliedRate}, m_stopPosition{stopPosition} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetSourcePosition"); +} + +SetSourcePosition::~SetSourcePosition() +{ + RIALTO_SERVER_LOG_DEBUG("SetSourcePosition finished"); +} + +void SetSourcePosition::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetSourcePosition for %s source", common::convertMediaSourceType(m_type)); + + if (MediaSourceType::UNKNOWN == m_type) + { + RIALTO_SERVER_LOG_WARN("failed to set source position - source type is unknown"); + return; + } + + // Get source first + GstElement *source{nullptr}; + auto sourceElem = m_context.streamInfo.find(m_type); + if (sourceElem != m_context.streamInfo.end()) + { + source = sourceElem->second.appSrc; + } + if (!source) + { + RIALTO_SERVER_LOG_WARN("failed to set source position - %s source is NULL", + common::convertMediaSourceType(m_type)); + return; + } + + if (MediaSourceType::VIDEO == m_type || MediaSourceType::AUDIO == m_type) + { + m_context.initialPositions[source].emplace_back( + SegmentData{m_position, m_resetTime, m_appliedRate, m_stopPosition}); + } + else if (MediaSourceType::SUBTITLE == m_type) + { + setSubtitlePosition(source); + } + + if (m_context.setupSourceFinished) + { + // Reset Eos info + m_context.endOfStreamInfo.erase(m_type); + m_context.eosNotified = false; + + // Trigger NeedData for source + NeedData task{m_context, m_player, m_gstPlayerClient, GST_APP_SRC(source)}; + task.execute(); + } +} + +void SetSourcePosition::setSubtitlePosition(GstElement *source) const +{ + // in case of subtitles, all data might be already in the sink and we might not get any data anymore, + // so set position here and to not depend on any following buffers + if (m_context.setupSourceFinished) + { + m_glibWrapper->gObjectSet(m_context.subtitleSink, "position", static_cast(m_position), nullptr); + } + else + { + m_context.initialPositions[source].emplace_back( + SegmentData{m_position, m_resetTime, m_appliedRate, m_stopPosition}); + } +} + +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetStreamSyncMode.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetStreamSyncMode.cpp new file mode 100644 index 000000000..7dd79017e --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetStreamSyncMode.cpp @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetStreamSyncMode.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetStreamSyncMode::SetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const MediaSourceType &type, int32_t streamSyncMode) + : m_context(context), m_player(player), m_type{type}, m_streamSyncMode{streamSyncMode} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetStreamSyncMode"); +} + +SetStreamSyncMode::~SetStreamSyncMode() +{ + RIALTO_SERVER_LOG_DEBUG("SetStreamSyncMode finished"); +} + +void SetStreamSyncMode::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetStreamSyncMode"); + + m_context.pendingStreamSyncMode.emplace(m_type, m_streamSyncMode); + if (m_context.pipeline) + { + m_player.setStreamSyncMode(m_type); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSubtitleOffset.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSubtitleOffset.cpp new file mode 100644 index 000000000..9023fff87 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSubtitleOffset.cpp @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetSubtitleOffset.h" +#include "RialtoServerLogging.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +SetSubtitleOffset::SetSubtitleOffset(GenericPlayerContext &context, + const std::shared_ptr &glibWrapper, std::int64_t position) + : m_context{context}, m_glibWrapper{glibWrapper}, m_position{position} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetSubtitleOffset"); +} + +SetSubtitleOffset::~SetSubtitleOffset() +{ + RIALTO_SERVER_LOG_DEBUG("SetSubtitleOffset finished"); +} + +void SetSubtitleOffset::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetSubtitleOffset"); + + if (m_context.subtitleSink) + { + RIALTO_SERVER_LOG_DEBUG("Setting subtitle offset to %" PRId64 " nanoseconds", m_position); + m_glibWrapper->gObjectSet(m_context.subtitleSink, "offset", static_cast(m_position), nullptr); + } + else + { + RIALTO_SERVER_LOG_WARN("Failed to set subtitle offset - subtitle sink is NULL"); + } +} + +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSync.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSync.cpp new file mode 100644 index 000000000..40c0cbf74 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSync.cpp @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetSync.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetSync::SetSync(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool sync) + : m_context(context), m_player(player), m_sync{sync} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetSync"); +} + +SetSync::~SetSync() +{ + RIALTO_SERVER_LOG_DEBUG("SetSync finished"); +} + +void SetSync::execute() const +{ + m_context.pendingSync = m_sync; + if (m_context.pipeline) + { + m_player.setSync(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSyncOff.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSyncOff.cpp new file mode 100644 index 000000000..45cf05107 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSyncOff.cpp @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetSyncOff.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetSyncOff::SetSyncOff(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool syncOff) + : m_context(context), m_player(player), m_syncOff{syncOff} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetSyncOff"); +} + +SetSyncOff::~SetSyncOff() +{ + RIALTO_SERVER_LOG_DEBUG("SetSyncOff finished"); +} + +void SetSyncOff::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetSyncOff"); + + m_context.pendingSyncOff = m_syncOff; + if (m_context.pipeline) + { + m_player.setSyncOff(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetTextTrackIdentifier.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetTextTrackIdentifier.cpp new file mode 100644 index 000000000..e58c93430 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetTextTrackIdentifier.cpp @@ -0,0 +1,51 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SetTextTrackIdentifier.h" +#include "RialtoServerLogging.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +SetTextTrackIdentifier::SetTextTrackIdentifier(GenericPlayerContext &context, + std::shared_ptr glibWrapper, + const std::string &textTrackIdentifier) + : m_context{context}, m_glibWrapper{glibWrapper}, m_textTrackIdentifier{textTrackIdentifier} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetTextTrackIdentifier"); +} + +SetTextTrackIdentifier::~SetTextTrackIdentifier() +{ + RIALTO_SERVER_LOG_DEBUG("SetTextTrackIdentifier finished"); +} + +void SetTextTrackIdentifier::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetTextTrackIdentifier"); + + if (!m_context.subtitleSink) + { + RIALTO_SERVER_LOG_ERROR("There is no subtitle sink"); + return; + } + + m_glibWrapper->gObjectSet(m_context.subtitleSink, "text-track-identifier", m_textTrackIdentifier.c_str(), nullptr); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetUseBuffering.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetUseBuffering.cpp new file mode 100644 index 000000000..21003aad6 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetUseBuffering.cpp @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetUseBuffering.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetUseBuffering::SetUseBuffering(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool useBuffering) + : m_context{context}, m_player(player), m_useBuffering{useBuffering} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetUseBuffering"); +} + +SetUseBuffering::~SetUseBuffering() +{ + RIALTO_SERVER_LOG_DEBUG("SetUseBuffering finished"); +} + +void SetUseBuffering::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetUseBuffering"); + + m_context.pendingUseBuffering = m_useBuffering; + if (m_context.pipeline) + { + m_player.setUseBuffering(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVideoGeometry.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVideoGeometry.cpp new file mode 100644 index 000000000..6e4ae2b92 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVideoGeometry.cpp @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SetVideoGeometry.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetVideoGeometry::SetVideoGeometry(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const Rectangle &rectangle) + : m_context{context}, m_player{player}, m_rectangle{rectangle} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetVideoGeometry"); +} + +SetVideoGeometry::~SetVideoGeometry() +{ + RIALTO_SERVER_LOG_DEBUG("SetVideoGeometry finished"); +} + +void SetVideoGeometry::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetVideoGeometry"); + m_context.pendingGeometry = m_rectangle; + if (m_context.pipeline) + { + m_player.setVideoSinkRectangle(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVolume.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVolume.cpp new file mode 100644 index 000000000..dbe8a9d06 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVolume.cpp @@ -0,0 +1,122 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SetVolume.h" +#include "IRdkGstreamerUtilsWrapper.h" +#include "RialtoServerLogging.h" +#include +#include +#include + +namespace firebolt::rialto::server::tasks::generic +{ +SetVolume::SetVolume(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + std::shared_ptr rdkGstreamerUtilsWrapper, + double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType) + : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, + m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, m_targetVolume{targetVolume}, + m_volumeDuration{volumeDuration}, m_easeType{easeType} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetVolume"); +} + +SetVolume::~SetVolume() +{ + RIALTO_SERVER_LOG_DEBUG("SetVolume finished"); +} + +firebolt::rialto::wrappers::rgu_Ease convertEaseTypeToRguEase(EaseType easeType) +{ + switch (easeType) + { + case EaseType::EASE_LINEAR: + return firebolt::rialto::wrappers::rgu_Ease::EaseLinear; + case EaseType::EASE_IN_CUBIC: + return firebolt::rialto::wrappers::rgu_Ease::EaseInCubic; + case EaseType::EASE_OUT_CUBIC: + return firebolt::rialto::wrappers::rgu_Ease::EaseOutCubic; + default: + RIALTO_SERVER_LOG_ERROR("Unknown EaseType, defaulting to EaseLinear"); + return firebolt::rialto::wrappers::rgu_Ease::EaseLinear; + } +} + +void SetVolume::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetVolume"); + + if (!m_context.pipeline) + { + RIALTO_SERVER_LOG_ERROR("Setting volume failed. Pipeline is NULL"); + return; + } + bool isImmediateVolumeChange = (m_volumeDuration == 0); + GstElement *audioSink = m_player.getSink(firebolt::rialto::MediaSourceType::AUDIO); + + if (isImmediateVolumeChange) + { + RIALTO_SERVER_LOG_DEBUG("Immediate volume change, setting volume directly"); + m_gstWrapper->gstStreamVolumeSetVolume(GST_STREAM_VOLUME(m_context.pipeline), GST_STREAM_VOLUME_FORMAT_LINEAR, + m_targetVolume); + } + else if (audioSink && m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(audioSink), "audio-fade")) + { + gchar fadeStr[32]; + uint32_t scaledTarget = trunc(100 * m_targetVolume); + std::string easeString = "L"; + + switch (m_easeType) + { + default: + case firebolt::rialto::EaseType::EASE_LINEAR: + easeString = "L"; + break; + case firebolt::rialto::EaseType::EASE_IN_CUBIC: + easeString = "I"; + break; + case firebolt::rialto::EaseType::EASE_OUT_CUBIC: + easeString = "O"; + break; + } + + snprintf(reinterpret_cast(fadeStr), sizeof(fadeStr), "%u,%u,%s", scaledTarget, m_volumeDuration, + easeString.c_str()); + RIALTO_SERVER_LOG_DEBUG("Fade String: %s", fadeStr); + + m_glibWrapper->gObjectSet(audioSink, "audio-fade", fadeStr, nullptr); + m_context.audioFadeEnabled = true; + } + else if (m_rdkGstreamerUtilsWrapper->isSocAudioFadeSupported()) + { + RIALTO_SERVER_LOG_DEBUG("SOC audio fading is supported, applying SOC audio fade"); + auto rguEaseType = convertEaseTypeToRguEase(m_easeType); + m_rdkGstreamerUtilsWrapper->doAudioEasingonSoc(m_targetVolume, m_volumeDuration, rguEaseType); + m_context.audioFadeEnabled = true; + } + else + { + RIALTO_SERVER_LOG_WARN("No audio-fade property found in audio sink or SOC"); + } + + if (audioSink) + m_gstWrapper->gstObjectUnref(GST_OBJECT(audioSink)); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupElement.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupElement.cpp new file mode 100644 index 000000000..5139fd220 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupElement.cpp @@ -0,0 +1,325 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SetupElement.h" +#include "GenericPlayerContext.h" +#include "IGlibWrapper.h" +#include "IGstGenericPlayerPrivate.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include "Utils.h" + +namespace +{ +/** + * @brief Callback for audio underflow event from sink. Called by the Gstreamer thread. + * + * @param[in] object : the object that emitted the signal + * @param[in] fifoDepth : the fifo depth (may be 0) + * @param[in] queueDepth : the queue depth (may be NULL) + * @param[in] self : The pointer to IGstGenericPlayerPrivate + * + * @retval true if the handling of the message is successful, false otherwise. + */ +void audioUnderflowCallback(GstElement *object, guint fifoDepth, gpointer queueDepth, gpointer self) +{ + firebolt::rialto::server::IGstGenericPlayerPrivate *player = + static_cast(self); + player->scheduleAudioUnderflow(); +} + +/** + * @brief Callback for video underflow event from sink. Called by the Gstreamer thread. + * + * @param[in] object : the object that emitted the signal + * @param[in] fifoDepth : the fifo depth (may be 0) + * @param[in] queueDepth : the queue depth (may be NULL) + * @param[in] self : The pointer to IGstGenericPlayerPrivate + * + * @retval true if the handling of the message is successful, false otherwise. + */ +void videoUnderflowCallback(GstElement *object, guint fifoDepth, gpointer queueDepth, gpointer self) +{ + firebolt::rialto::server::IGstGenericPlayerPrivate *player = + static_cast(self); + player->scheduleVideoUnderflow(); +} + +/** + * @brief Callback for a autovideosink when a child has been added to the sink. + * + * @param[in] obj : the parent element (autovideosink) + * @param[in] object : the child element + * @param[in] name : the name of the child element + * @param[in] self : The pointer to IGstGenericPlayerPrivate + */ +void autoVideoSinkChildAddedCallback(GstChildProxy *obj, GObject *object, gchar *name, gpointer self) +{ + RIALTO_SERVER_LOG_DEBUG("AutoVideoSink added element %s", name); + firebolt::rialto::server::IGstGenericPlayerPrivate *player = + static_cast(self); + player->addAutoVideoSinkChild(object); +} + +/** + * @brief Callback for a autoaudiosink when a child has been added to the sink. + * + * @param[in] obj : the parent element (autoaudiosink) + * @param[in] object : the child element + * @param[in] name : the name of the child element + * @param[in] self : The pointer to IGstGenericPlayerPrivate + */ +void autoAudioSinkChildAddedCallback(GstChildProxy *obj, GObject *object, gchar *name, gpointer self) +{ + RIALTO_SERVER_LOG_DEBUG("AutoAudioSink added element %s", name); + firebolt::rialto::server::IGstGenericPlayerPrivate *player = + static_cast(self); + player->addAutoAudioSinkChild(object); +} + +/** + * @brief Callback for a autovideosink when a child has been removed from the sink. + * + * @param[in] obj : the parent element (autovideosink) + * @param[in] object : the child element + * @param[in] name : the name of the child element + * @param[in] self : The pointer to IGstGenericPlayerPrivate + */ +void autoVideoSinkChildRemovedCallback(GstChildProxy *obj, GObject *object, gchar *name, gpointer self) +{ + RIALTO_SERVER_LOG_DEBUG("AutoVideoSink removed element %s", name); + firebolt::rialto::server::IGstGenericPlayerPrivate *player = + static_cast(self); + player->removeAutoVideoSinkChild(object); +} + +/** + * @brief Callback for a autoaudiosink when a child has been removed from the sink. + * + * @param[in] obj : the parent element (autoaudiosink) + * @param[in] object : the child element + * @param[in] name : the name of the child element + * @param[in] self : The pointer to IGstGenericPlayerPrivate + */ +void autoAudioSinkChildRemovedCallback(GstChildProxy *obj, GObject *object, gchar *name, gpointer self) +{ + RIALTO_SERVER_LOG_DEBUG("AutoAudioSink removed element %s", name); + firebolt::rialto::server::IGstGenericPlayerPrivate *player = + static_cast(self); + player->removeAutoAudioSinkChild(object); +} +} // namespace + +namespace firebolt::rialto::server::tasks::generic +{ +SetupElement::SetupElement(GenericPlayerContext &context, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + IGstGenericPlayerPrivate &player, GstElement *element) + : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_player{player}, m_element{element} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetupElement"); +} + +SetupElement::~SetupElement() +{ + RIALTO_SERVER_LOG_DEBUG("SetupElement finished"); +} + +void SetupElement::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetupElement"); + + const std::string kElementTypeName = m_glibWrapper->gTypeName(G_OBJECT_TYPE(m_element)); + if (kElementTypeName == "GstAutoVideoSink") + { + // Check and store child sink so we can set underlying properties + m_glibWrapper->gSignalConnect(m_element, "child-added", G_CALLBACK(autoVideoSinkChildAddedCallback), &m_player); + m_glibWrapper->gSignalConnect(m_element, "child-removed", G_CALLBACK(autoVideoSinkChildRemovedCallback), + &m_player); + + // AutoVideoSink sets child before it is setup on the pipeline, so check for children here + GstIterator *sinks = m_gstWrapper->gstBinIterateSinks(GST_BIN(m_element)); + if (sinks && sinks->size > 1) + { + RIALTO_SERVER_LOG_WARN("More than one child sink attached"); + } + + GValue elem = G_VALUE_INIT; + if (m_gstWrapper->gstIteratorNext(sinks, &elem) == GST_ITERATOR_OK) + { + m_player.addAutoVideoSinkChild(G_OBJECT(m_glibWrapper->gValueGetObject(&elem))); + } + m_glibWrapper->gValueUnset(&elem); + + if (sinks) + m_gstWrapper->gstIteratorFree(sinks); + } + else if (kElementTypeName == "GstAutoAudioSink") + { + // Check and store child sink so we can set underlying properties + m_glibWrapper->gSignalConnect(m_element, "child-added", G_CALLBACK(autoAudioSinkChildAddedCallback), &m_player); + m_glibWrapper->gSignalConnect(m_element, "child-removed", G_CALLBACK(autoAudioSinkChildRemovedCallback), + &m_player); + + // AutoAudioSink sets child before it is setup on the pipeline, so check for children here + GstIterator *sinks = m_gstWrapper->gstBinIterateSinks(GST_BIN(m_element)); + if (sinks && sinks->size > 1) + { + RIALTO_SERVER_LOG_WARN("More than one child sink attached"); + } + + GValue elem = G_VALUE_INIT; + if (m_gstWrapper->gstIteratorNext(sinks, &elem) == GST_ITERATOR_OK) + { + m_player.addAutoAudioSinkChild(G_OBJECT(m_glibWrapper->gValueGetObject(&elem))); + } + m_glibWrapper->gValueUnset(&elem); + + if (sinks) + m_gstWrapper->gstIteratorFree(sinks); + } + + if (m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "amlhalasink")) + { + if (m_context.streamInfo.find(MediaSourceType::VIDEO) != m_context.streamInfo.end()) + { + // Wait for video so that the audio aligns at the starting point with timeout of 4000ms. + m_glibWrapper->gObjectSet(m_element, "wait-video", TRUE, "a-wait-timeout", 4000, nullptr); + } + + // Xrun occasionally pauses the underlying sink due to unstable playback, but the rest of the pipeline + // remains in the playing state. This causes problems with the synchronization of gst element and rialto + // ultimately hangs waiting for pipeline termination. + m_glibWrapper->gObjectSet(m_element, "disable-xrun", TRUE, nullptr); + } + else if (m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "brcmaudiosink")) + { + m_glibWrapper->gObjectSet(m_element, "async", TRUE, nullptr); + } + else if (m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "rialtotexttracksink")) + { + // in cannot be set during construction, because playsink overwrites "sync" value of text-sink during setup + m_glibWrapper->gObjectSet(m_element, "sync", FALSE, nullptr); + } + + if (m_context.subtitleSink) + { + if (!m_context.isVideoHandleSet && isVideoDecoder(*m_gstWrapper, m_element)) + { + if (m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "omx") || + m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "westerossink") || + m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "brcmvideodecoder")) + { + uintptr_t videoDecoderHandle = reinterpret_cast(m_element); + m_glibWrapper->gObjectSet(m_context.subtitleSink, "video-decoder", videoDecoderHandle, nullptr); + RIALTO_SERVER_LOG_INFO("Setting video decoder handle for subtitle sink: %zu", videoDecoderHandle); + m_context.isVideoHandleSet = true; + } + } + } + + if (isDecoder(*m_gstWrapper, m_element) || isSink(*m_gstWrapper, m_element)) + { + std::optional underflowSignalName = getUnderflowSignalName(*m_glibWrapper, m_element); + if (underflowSignalName) + { + if (isAudio(*m_gstWrapper, m_element)) + { + RIALTO_SERVER_LOG_INFO("Connecting audio underflow callback for signal: %s", + underflowSignalName.value().c_str()); + m_glibWrapper->gSignalConnect(m_element, underflowSignalName.value().c_str(), + G_CALLBACK(audioUnderflowCallback), &m_player); + } + else if (isVideo(*m_gstWrapper, m_element)) + { + RIALTO_SERVER_LOG_INFO("Connecting video underflow callback for signal: %s", + underflowSignalName.value().c_str()); + m_glibWrapper->gSignalConnect(m_element, underflowSignalName.value().c_str(), + G_CALLBACK(videoUnderflowCallback), &m_player); + } + } + } + + if (isVideoSink(*m_gstWrapper, m_element)) + { + if (!m_context.videoSink) + { + m_gstWrapper->gstObjectRef(m_element); + m_context.videoSink = m_element; + } + if (!m_context.pendingGeometry.empty()) + { + m_player.setVideoSinkRectangle(); + } + if (m_context.pendingImmediateOutputForVideo.has_value()) + { + m_player.setImmediateOutput(); + } + if (m_context.pendingRenderFrame) + { + m_player.setRenderFrame(); + } + if (m_context.pendingShowVideoWindow.has_value()) + { + m_player.setShowVideoWindow(); + } + } + else if (isAudioDecoder(*m_gstWrapper, m_element)) + { + if (m_context.pendingSyncOff.has_value()) + { + m_player.setSyncOff(); + } + if (m_context.pendingStreamSyncMode.find(MediaSourceType::AUDIO) != m_context.pendingStreamSyncMode.end()) + { + m_player.setStreamSyncMode(MediaSourceType::AUDIO); + } + if (m_context.pendingBufferingLimit.has_value()) + { + m_player.setBufferingLimit(); + } + } + else if (isAudioSink(*m_gstWrapper, m_element)) + { + if (m_context.pendingLowLatency.has_value()) + { + m_player.setLowLatency(); + } + if (m_context.pendingSync.has_value()) + { + m_player.setSync(); + } + } + else if (isVideoParser(*m_gstWrapper, m_element)) + { + if (m_context.pendingStreamSyncMode.find(MediaSourceType::VIDEO) != m_context.pendingStreamSyncMode.end()) + { + m_player.setStreamSyncMode(MediaSourceType::VIDEO); + } + } + + if (m_gstWrapper->gstIsBaseParse(m_element)) + { + m_gstWrapper->gstBaseParseSetPtsInterpolation(GST_BASE_PARSE(m_element), FALSE); + } + + m_gstWrapper->gstObjectUnref(m_element); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupSource.cpp new file mode 100644 index 000000000..7bfa9e133 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupSource.cpp @@ -0,0 +1,49 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SetupSource.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SetupSource::SetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstElement *source) + : m_context{context}, m_player{player}, m_source{source} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetupSource"); +} + +SetupSource::~SetupSource() +{ + RIALTO_SERVER_LOG_DEBUG("SetupSource finished"); +} + +void SetupSource::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetupSource"); + m_context.source = m_source; + + if (m_context.wereAllSourcesAttached) + { + RIALTO_SERVER_LOG_DEBUG("Source ready. Schedulling allSourcesAttached"); + m_player.scheduleAllSourcesAttached(); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Shutdown.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Shutdown.cpp new file mode 100644 index 000000000..7619ca3b4 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Shutdown.cpp @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Shutdown.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Shutdown::Shutdown(IGstGenericPlayerPrivate &player) : m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Shutdown"); +} + +Shutdown::~Shutdown() +{ + RIALTO_SERVER_LOG_DEBUG("Shutdown finished"); +} + +void Shutdown::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Shutdown"); + m_player.stopWorkerThread(); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Stop.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Stop.cpp new file mode 100644 index 000000000..8b5936560 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Stop.cpp @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Stop.h" +#include "GenericPlayerContext.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Stop::Stop(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) : m_context{context}, m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Stop"); +} + +Stop::~Stop() +{ + RIALTO_SERVER_LOG_DEBUG("Stop finished"); +} + +void Stop::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Stop"); + m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); + m_player.changePipelineState(GST_STATE_NULL); + for (auto &streamInfo : m_context.streamInfo) + { + streamInfo.second.isDataNeeded = false; + } + RIALTO_SERVER_LOG_MIL("State change to NULL requested"); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp new file mode 100644 index 000000000..3fc48a866 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SwitchSource.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" +#include "Utils.h" + +namespace firebolt::rialto::server::tasks::generic +{ +SwitchSource::SwitchSource(IGstGenericPlayerPrivate &player, const std::unique_ptr &source) + : m_player{player}, m_source{source->copy()} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SwitchSource"); +} + +SwitchSource::~SwitchSource() +{ + RIALTO_SERVER_LOG_DEBUG("SwitchSource finished"); +} + +void SwitchSource::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SwitchSource"); + if (!m_player.reattachSource(m_source)) + { + RIALTO_SERVER_LOG_WARN("Switch audio source failed"); + return; + } + RIALTO_SERVER_LOG_MIL("%s source switched", common::convertMediaSourceType(m_source->getType())); +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SynchroniseSubtitleClock.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SynchroniseSubtitleClock.cpp new file mode 100644 index 000000000..4da52f0ff --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SynchroniseSubtitleClock.cpp @@ -0,0 +1,91 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2025 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/SynchroniseSubtitleClock.h" +#include "IGstGenericPlayerPrivate.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" +#include + +namespace firebolt::rialto::server::tasks::generic +{ +SynchroniseSubtitleClock::SynchroniseSubtitleClock( + GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper) + : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SynchroniseSubtitleClock"); +} + +SynchroniseSubtitleClock::~SynchroniseSubtitleClock() +{ + RIALTO_SERVER_LOG_DEBUG("SynchroniseSubtitleClock finished"); +} + +void SynchroniseSubtitleClock::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SynchroniseSubtitleClock"); + if (m_context.videoSink) + { + gint64 position = 0; + if (m_gstWrapper->gstElementQueryPosition(m_context.videoSink, GST_FORMAT_TIME, &position)) + { + RIALTO_SERVER_LOG_DEBUG("Videosink position: %" PRId64 " ns", position); + } + + auto sourceElem = m_context.streamInfo.find(MediaSourceType::SUBTITLE); + GstElement *source{nullptr}; + + if (sourceElem != m_context.streamInfo.end()) + { + source = sourceElem->second.appSrc; + } + else + { + RIALTO_SERVER_LOG_WARN("subtitle source not found"); + return; + } + + GstStructure *structure = m_gstWrapper->gstStructureNew("current-pts", "pts", G_TYPE_UINT64, position, nullptr); + GstEvent *event = m_gstWrapper->gstEventNewCustom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); + + if (event) + { + if (m_gstWrapper->gstElementSendEvent(source, event)) + { + RIALTO_SERVER_LOG_DEBUG("Sent current-pts event to subtitlesource"); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to send current-pts event to source"); + } + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to create current-pts event"); + } + } + else + { + RIALTO_SERVER_LOG_ERROR("video-sink is NULL"); + } +} + +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Underflow.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Underflow.cpp new file mode 100644 index 000000000..f34ad11c2 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Underflow.cpp @@ -0,0 +1,65 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/Underflow.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server::tasks::generic +{ +Underflow::Underflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, + bool underflowEnabled, MediaSourceType sourceType) + : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_underflowEnabled{underflowEnabled}, + m_sourceType{sourceType} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Underflow"); +} + +Underflow::~Underflow() +{ + RIALTO_SERVER_LOG_DEBUG("Underflow finished"); +} + +void Underflow::execute() const +{ + RIALTO_SERVER_LOG_WARN("Executing Underflow for %s source", common::convertMediaSourceType(m_sourceType)); + if (!m_underflowEnabled) + { + return; + } + + auto elem = m_context.streamInfo.find(m_sourceType); + if (elem != m_context.streamInfo.end()) + { + StreamInfo &streamInfo = elem->second; + if (streamInfo.underflowOccured) + { + return; + } + + streamInfo.underflowOccured = true; + + if (m_gstPlayerClient) + { + m_gstPlayerClient->notifyBufferUnderflow(m_sourceType); + } + } +} + +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp new file mode 100644 index 000000000..0264da6f1 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp @@ -0,0 +1,79 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/generic/UpdatePlaybackGroup.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::generic +{ +UpdatePlaybackGroup::UpdatePlaybackGroup(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + GstElement *typefind, const GstCaps *caps) + : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_typefind{typefind}, + m_caps{caps} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing UpdatePlaybackGroup"); +} + +UpdatePlaybackGroup::~UpdatePlaybackGroup() +{ + RIALTO_SERVER_LOG_DEBUG("UpdatePlaybackGroup finished"); +} + +void UpdatePlaybackGroup::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing UpdatePlaybackGroup"); + if (nullptr == m_caps) + { + RIALTO_SERVER_LOG_DEBUG("Typefind SRC Pad Caps NULL"); + return; + } + gchar *typefindCaps = m_gstWrapper->gstCapsToString(m_caps); + if (typefindCaps) + { + RIALTO_SERVER_LOG_DEBUG("Typefind SRC Pad Strm Parsed Caps %s", typefindCaps); + if (m_glibWrapper->gStrrstr(typefindCaps, "audio/")) + { + GstElement *typeFindParent = reinterpret_cast(m_gstWrapper->gstElementGetParent(m_typefind)); + if (typeFindParent) + { + gchar *elementName = m_gstWrapper->gstElementGetName(typeFindParent); + RIALTO_SERVER_LOG_DEBUG("elementName %s", elementName); + if (elementName && m_glibWrapper->gStrrstr(elementName, "decodebin")) + { + RIALTO_SERVER_LOG_DEBUG("m_context.playbackGroup.curAudioDecodeBin %s", elementName); + m_context.playbackGroup.m_curAudioDecodeBin = typeFindParent; + gchar *typefindName = m_gstWrapper->gstElementGetName(m_typefind); + RIALTO_SERVER_LOG_DEBUG("onTypeFound(): m_context.playbackGroup.curAudioTypefind %s", typefindName); + m_glibWrapper->gFree(typefindName); + m_context.playbackGroup.m_curAudioTypefind = m_typefind; + if (m_context.pendingUseBuffering.has_value()) + { + m_player.setUseBuffering(); + } + } + m_glibWrapper->gFree(elementName); + m_gstWrapper->gstObjectUnref(typeFindParent); + } + } + m_glibWrapper->gFree(typefindCaps); + } +} +} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Eos.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Eos.cpp new file mode 100644 index 000000000..031ed7a8c --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Eos.cpp @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/Eos.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include "WebAudioPlayerContext.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +Eos::Eos(WebAudioPlayerContext &context, std::shared_ptr gstWrapper) + : m_context{context}, m_gstWrapper{gstWrapper} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Eos"); +} + +Eos::~Eos() +{ + RIALTO_SERVER_LOG_DEBUG("Eos finished"); +} + +void Eos::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Eos"); + if (m_gstWrapper->gstAppSrcEndOfStream(GST_APP_SRC(m_context.source)) != GST_FLOW_OK) + { + RIALTO_SERVER_LOG_WARN("Set eos failed - Gstreamer error"); + } + RIALTO_SERVER_LOG_MIL("EOS set for webaudio source"); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp new file mode 100644 index 000000000..d58e0d7c1 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp @@ -0,0 +1,139 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/HandleBusMessage.h" +#include "IGstWebAudioPlayerClient.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include "WebAudioPlayerContext.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +HandleBusMessage::HandleBusMessage(WebAudioPlayerContext &context, IGstWebAudioPlayerPrivate &player, + IGstWebAudioPlayerClient *client, + std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + GstMessage *message) + : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, + m_glibWrapper{glibWrapper}, m_message{message} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing HandleBusMessage"); +} + +HandleBusMessage::~HandleBusMessage() +{ + RIALTO_SERVER_LOG_DEBUG("HandleBusMessage finished"); +} + +void HandleBusMessage::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing HandleBusMessage"); + switch (GST_MESSAGE_TYPE(m_message)) + { + case GST_MESSAGE_STATE_CHANGED: + { + if (m_context.pipeline && GST_MESSAGE_SRC(m_message) == GST_OBJECT(m_context.pipeline)) + { + GstState oldState, newState, pending; + m_gstWrapper->gstMessageParseStateChanged(m_message, &oldState, &newState, &pending); + RIALTO_SERVER_LOG_MIL("State changed (old: %s, new: %s, pending: %s)", + m_gstWrapper->gstElementStateGetName(oldState), + m_gstWrapper->gstElementStateGetName(newState), + m_gstWrapper->gstElementStateGetName(pending)); + + std::string filename = std::string(m_gstWrapper->gstElementStateGetName(oldState)) + "-" + + std::string(m_gstWrapper->gstElementStateGetName(newState)); + m_gstWrapper->gstDebugBinToDotFileWithTs(GST_BIN(m_context.pipeline), GST_DEBUG_GRAPH_SHOW_ALL, + filename.c_str()); + if (!m_gstPlayerClient) + { + break; + } + switch (newState) + { + case GST_STATE_PAUSED: + { + if (pending != GST_STATE_PAUSED) + { + // newState==GST_STATE_PAUSED, pending==GST_STATE_PAUSED state transition is received as a result of + // waiting for preroll after seek. + // Subsequent newState==GST_STATE_PAUSED, pending!=GST_STATE_PAUSED transition will + // indicate that the pipeline is prerolled and it reached GST_STATE_PAUSED state after seek. + m_gstPlayerClient->notifyState(WebAudioPlayerState::PAUSED); + } + break; + } + case GST_STATE_PLAYING: + { + m_gstPlayerClient->notifyState(WebAudioPlayerState::PLAYING); + break; + } + case GST_STATE_READY: + { + m_gstPlayerClient->notifyState(WebAudioPlayerState::IDLE); + break; + } + case GST_STATE_NULL: + case GST_STATE_VOID_PENDING: + default: + break; + } + } + break; + } + case GST_MESSAGE_EOS: + { + if (m_context.pipeline && GST_MESSAGE_SRC(m_message) == GST_OBJECT(m_context.pipeline)) + { + RIALTO_SERVER_LOG_MIL("End of stream reached."); + if (m_gstPlayerClient) + { + m_gstPlayerClient->notifyState(WebAudioPlayerState::END_OF_STREAM); + } + + // Flush the pipeline so that it can be reused + if ((!m_gstWrapper->gstElementSendEvent(m_context.pipeline, m_gstWrapper->gstEventNewFlushStart())) || + (!m_gstWrapper->gstElementSendEvent(m_context.pipeline, m_gstWrapper->gstEventNewFlushStop(TRUE)))) + { + RIALTO_SERVER_LOG_ERROR("Failed to flush the pipeline"); + } + } + break; + } + case GST_MESSAGE_ERROR: + { + GError *err = nullptr; + gchar *debug = nullptr; + m_gstWrapper->gstMessageParseError(m_message, &err, &debug); + + RIALTO_SERVER_LOG_ERROR("Error from %s - %d: %s (%s)", GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), err->code, + err->message, debug); + m_gstPlayerClient->notifyState(WebAudioPlayerState::FAILURE); + + m_glibWrapper->gFree(debug); + m_glibWrapper->gErrorFree(err); + break; + } + default: + break; + } + + m_gstWrapper->gstMessageUnref(m_message); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Pause.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Pause.cpp new file mode 100644 index 000000000..53ff8a5d2 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Pause.cpp @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/Pause.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +Pause::Pause(IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client) + : m_player{player}, m_gstPlayerClient{client} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Pause"); +} + +Pause::~Pause() +{ + RIALTO_SERVER_LOG_DEBUG("Pause finished"); +} + +void Pause::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Pause"); + if (!m_player.changePipelineState(GST_STATE_PAUSED)) + { + RIALTO_SERVER_LOG_ERROR("Failed to pause the web audio player"); + } + RIALTO_SERVER_LOG_MIL("State change to PAUSED requested for webaudio pipeline"); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Ping.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Ping.cpp new file mode 100644 index 000000000..0204c1523 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Ping.cpp @@ -0,0 +1,40 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/Ping.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +Ping::Ping(std::unique_ptr &&heartbeatHandler) : m_heartbeatHandler{std::move(heartbeatHandler)} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Ping"); +} + +Ping::~Ping() +{ + RIALTO_SERVER_LOG_DEBUG("Ping finished"); + m_heartbeatHandler.reset(); +} + +void Ping::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Ping"); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Play.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Play.cpp new file mode 100644 index 000000000..cee4382bf --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Play.cpp @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/Play.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +Play::Play(IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client) + : m_player{player}, m_gstPlayerClient{client} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Play"); +} + +Play::~Play() +{ + RIALTO_SERVER_LOG_DEBUG("Play finished"); +} + +void Play::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Play"); + if (!m_player.changePipelineState(GST_STATE_PLAYING)) + { + RIALTO_SERVER_LOG_ERROR("Failed to play the web audio player"); + } + RIALTO_SERVER_LOG_MIL("State change to PLAYING requested for webaudio pipeline"); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp new file mode 100644 index 000000000..f1e0ff99a --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp @@ -0,0 +1,190 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/SetCaps.h" +#include "IGlibWrapper.h" +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" + +#include +#include +#include + +namespace firebolt::rialto::server::tasks::webaudio +{ +namespace +{ +class WebAudioCapsBuilder +{ +public: + WebAudioCapsBuilder(std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper) + : m_gstWrapper(gstWrapper), m_glibWrapper(glibWrapper) + { + } + virtual ~WebAudioCapsBuilder() = default; + virtual GstCaps *buildCaps() = 0; + +protected: + std::shared_ptr m_gstWrapper; + std::shared_ptr m_glibWrapper; +}; + +class WebAudioPcmCapsBuilder : public WebAudioCapsBuilder +{ +public: + WebAudioPcmCapsBuilder(std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const WebAudioPcmConfig &pcmConfig) + : WebAudioCapsBuilder(gstWrapper, glibWrapper), m_pcmConfig(pcmConfig) + { + } + ~WebAudioPcmCapsBuilder() override = default; + + GstCaps *buildCaps() override + { + GstCaps *caps = m_gstWrapper->gstCapsNewEmptySimple("audio/x-raw"); + addFormat(caps); + m_gstWrapper->gstCapsSetSimple(caps, "channels", G_TYPE_INT, m_pcmConfig.channels, "layout", G_TYPE_STRING, + "interleaved", "rate", G_TYPE_INT, m_pcmConfig.rate, "channel-mask", + GST_TYPE_BITMASK, + m_gstWrapper->gstAudioChannelGetFallbackMask(m_pcmConfig.channels), nullptr); + + return caps; + } + +protected: + void addFormat(GstCaps *caps) + { + std::string format; + + if (m_pcmConfig.isFloat) + { + format += "F"; + } + else if (m_pcmConfig.isSigned) + { + format += "S"; + } + else + { + format += "U"; + } + + format += std::to_string(m_pcmConfig.sampleSize); + + if (m_pcmConfig.isBigEndian) + { + format += "BE"; + } + else + { + format += "LE"; + } + + m_gstWrapper->gstCapsSetSimple(caps, "format", G_TYPE_STRING, format.c_str(), nullptr); + } + + const WebAudioPcmConfig &m_pcmConfig; +}; +}; // namespace + +SetCaps::SetCaps(WebAudioPlayerContext &context, std::shared_ptr gstWrapper, + std::shared_ptr glibWrapper, + const std::string &audioMimeType, std::weak_ptr webAudioConfig) + : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_audioMimeType{audioMimeType} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetCaps"); + + if (m_audioMimeType == "audio/x-raw") + { + std::shared_ptr kConfig = webAudioConfig.lock(); + if (kConfig == nullptr) + { + throw std::runtime_error("Config is null for 'audio/x-raw'"); + } + m_config.pcm = kConfig->pcm; + } +} + +SetCaps::~SetCaps() +{ + RIALTO_SERVER_LOG_DEBUG("SetCaps finished"); +} + +void SetCaps::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing SetCaps"); + + GstCaps *caps = createCapsFromMimeType(); + if (caps) + { + gchar *capsStr = m_gstWrapper->gstCapsToString(caps); + std::string strCaps = capsStr; + m_glibWrapper->gFree(capsStr); + + RIALTO_SERVER_LOG_DEBUG("caps str: '%s'", strCaps.c_str()); + + GstCaps *appsrcCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(m_context.source)); + if ((!appsrcCaps) || (!m_gstWrapper->gstCapsIsEqual(appsrcCaps, caps))) + { + RIALTO_SERVER_LOG_INFO("Updating web audio appsrc caps to '%s'", strCaps.c_str()); + m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(m_context.source), caps); + } + + if (appsrcCaps) + m_gstWrapper->gstCapsUnref(appsrcCaps); + if (caps) + m_gstWrapper->gstCapsUnref(caps); + + setBytesPerSample(); + RIALTO_SERVER_LOG_MIL("New caps set for webaudio source: %s", strCaps.c_str()); + } +} + +GstCaps *SetCaps::createCapsFromMimeType() const +{ + std::unique_ptr capsBuilder; + + if (m_audioMimeType == "audio/x-raw") + { + capsBuilder = std::make_unique(m_gstWrapper, m_glibWrapper, m_config.pcm); + } + else + { + RIALTO_SERVER_LOG_ERROR("Invalid audio mime type %s", m_audioMimeType.c_str()); + return nullptr; + } + + return capsBuilder->buildCaps(); +} + +void SetCaps::setBytesPerSample() const +{ + if (m_audioMimeType == "audio/x-raw") + { + m_context.bytesPerSample = m_config.pcm.channels * (m_config.pcm.sampleSize / CHAR_BIT); + } + else + { + RIALTO_SERVER_LOG_ERROR("Cannot set bytes per sample, invalid audio mime type %s", m_audioMimeType.c_str()); + } +} + +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetVolume.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetVolume.cpp new file mode 100644 index 000000000..857ca3406 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetVolume.cpp @@ -0,0 +1,44 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "RialtoServerLogging.h" +#include "tasks/webAudio/SetVolume.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +SetVolume::SetVolume(WebAudioPlayerContext &context, + std::shared_ptr gstWrapper, double volume) + : m_context{context}, m_gstWrapper{gstWrapper}, m_volume{volume} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing SetVolume"); +} + +SetVolume::~SetVolume() +{ + RIALTO_SERVER_LOG_DEBUG("SetVolume finished"); +} + +void SetVolume::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("WebAudio Executing SetVolume %f", m_volume); + m_gstWrapper->gstStreamVolumeSetVolume(m_context.gstVolumeElement, GST_STREAM_VOLUME_FORMAT_LINEAR, m_volume); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp new file mode 100644 index 000000000..a4275ade0 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/Shutdown.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +Shutdown::Shutdown(IGstWebAudioPlayerPrivate &player) : m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Shutdown"); +} + +Shutdown::~Shutdown() +{ + RIALTO_SERVER_LOG_DEBUG("Shutdown finished"); +} + +void Shutdown::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Shutdown"); + m_player.stopWorkerThread(); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Stop.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Stop.cpp new file mode 100644 index 000000000..7e369eee4 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Stop.cpp @@ -0,0 +1,43 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tasks/webAudio/Stop.h" +#include "IGstWebAudioPlayerPrivate.h" +#include "RialtoServerLogging.h" +#include "WebAudioPlayerContext.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +Stop::Stop(IGstWebAudioPlayerPrivate &player) : m_player{player} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing Stop"); +} + +Stop::~Stop() +{ + RIALTO_SERVER_LOG_DEBUG("Stop finished"); +} + +void Stop::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing Stop"); + m_player.changePipelineState(GST_STATE_NULL); + RIALTO_SERVER_LOG_MIL("State change to NULL requested for webaudio pipeline"); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp new file mode 100644 index 000000000..bdf107efc --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp @@ -0,0 +1,97 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "tasks/webAudio/WebAudioPlayerTaskFactory.h" +#include "tasks/webAudio/Eos.h" +#include "tasks/webAudio/HandleBusMessage.h" +#include "tasks/webAudio/Pause.h" +#include "tasks/webAudio/Ping.h" +#include "tasks/webAudio/Play.h" +#include "tasks/webAudio/SetCaps.h" +#include "tasks/webAudio/SetVolume.h" +#include "tasks/webAudio/Shutdown.h" +#include "tasks/webAudio/Stop.h" +#include "tasks/webAudio/WriteBuffer.h" + +namespace firebolt::rialto::server +{ +WebAudioPlayerTaskFactory::WebAudioPlayerTaskFactory( + IGstWebAudioPlayerClient *client, const std::shared_ptr &gstWrapper, + const std::shared_ptr &glibWrapper) + : m_client{client}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper} +{ +} + +std::unique_ptr WebAudioPlayerTaskFactory::createShutdown(IGstWebAudioPlayerPrivate &player) const +{ + return std::make_unique(player); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createStop(IGstWebAudioPlayerPrivate &player) const +{ + return std::make_unique(player); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createPlay(IGstWebAudioPlayerPrivate &player) const +{ + return std::make_unique(player, m_client); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createPause(IGstWebAudioPlayerPrivate &player) const +{ + return std::make_unique(player, m_client); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createEos(WebAudioPlayerContext &context) const +{ + return std::make_unique(context, m_gstWrapper); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createSetCaps(WebAudioPlayerContext &context, + const std::string &audioMimeType, + std::weak_ptr config) const +{ + return std::make_unique(context, m_gstWrapper, m_glibWrapper, audioMimeType, config); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createSetVolume(WebAudioPlayerContext &context, double volume) const +{ + return std::make_unique(context, m_gstWrapper, volume); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createWriteBuffer(WebAudioPlayerContext &context, + uint8_t *mainPtr, uint32_t mainLength, + uint8_t *wrapPtr, uint32_t wrapLength) const +{ + return std::make_unique(context, m_gstWrapper, mainPtr, mainLength, wrapPtr, + wrapLength); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createHandleBusMessage(WebAudioPlayerContext &context, + IGstWebAudioPlayerPrivate &player, + GstMessage *message) const +{ + return std::make_unique(context, player, m_client, m_gstWrapper, m_glibWrapper, + message); +} + +std::unique_ptr WebAudioPlayerTaskFactory::createPing(std::unique_ptr &&heartbeatHandler) const +{ + return std::make_unique(std::move(heartbeatHandler)); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WriteBuffer.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WriteBuffer.cpp new file mode 100644 index 000000000..f22870400 --- /dev/null +++ b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WriteBuffer.cpp @@ -0,0 +1,108 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "IGstWrapper.h" +#include "RialtoServerLogging.h" +#include "WebAudioPlayerContext.h" +#include "tasks/webAudio/WriteBuffer.h" + +namespace firebolt::rialto::server::tasks::webaudio +{ +WriteBuffer::WriteBuffer(WebAudioPlayerContext &context, + std::shared_ptr gstWrapper, uint8_t *mainPtr, + uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength) + : m_context{context}, m_gstWrapper{gstWrapper}, m_mainPtr{mainPtr}, m_mainLength{mainLength}, m_wrapPtr{wrapPtr}, + m_wrapLength{wrapLength} +{ + RIALTO_SERVER_LOG_DEBUG("Constructing WriteBuffer"); +} + +WriteBuffer::~WriteBuffer() +{ + RIALTO_SERVER_LOG_DEBUG("WriteBuffer finished"); +} + +void WriteBuffer::execute() const +{ + RIALTO_SERVER_LOG_DEBUG("Executing WriteBuffer"); + + uint64_t freeBytes = kMaxWebAudioBytes - m_gstWrapper->gstAppSrcGetCurrentLevelBytes(GST_APP_SRC(m_context.source)); + uint64_t maxBytesToWrite = std::min(freeBytes, m_mainLength + m_wrapLength); + uint64_t bytesToWrite = maxBytesToWrite - (maxBytesToWrite % m_context.bytesPerSample); + uint64_t bytesWritten = 0; + + if (bytesToWrite > 0) + { + GstBuffer *gstBuffer = m_gstWrapper->gstBufferNewAllocate(nullptr, bytesToWrite, nullptr); + if (gstBuffer) + { + if (bytesToWrite == m_mainLength + m_wrapLength) + { + bytesWritten += m_gstWrapper->gstBufferFill(gstBuffer, 0, m_mainPtr, m_mainLength); + if (m_wrapLength > 0) + { + bytesWritten += m_gstWrapper->gstBufferFill(gstBuffer, bytesWritten, m_wrapPtr, m_wrapLength); + } + } + else if (bytesToWrite > m_mainLength) + { + bytesWritten += m_gstWrapper->gstBufferFill(gstBuffer, 0, m_mainPtr, m_mainLength); + bytesWritten += + m_gstWrapper->gstBufferFill(gstBuffer, bytesWritten, m_wrapPtr, bytesToWrite - bytesWritten); + } + else + { + bytesWritten += m_gstWrapper->gstBufferFill(gstBuffer, 0, m_mainPtr, bytesToWrite); + } + + if (bytesWritten != bytesToWrite) + { + RIALTO_SERVER_LOG_WARN("Did not write the correct number of bytes! expected %" PRIu64 + ", actual %" PRIu64, + bytesToWrite, bytesWritten); + } + + if (GST_FLOW_OK != m_gstWrapper->gstAppSrcPushBuffer(GST_APP_SRC(m_context.source), gstBuffer)) + { + RIALTO_SERVER_LOG_ERROR("Failed to push the buffers to the appsrc"); + m_gstWrapper->gstBufferUnref(gstBuffer); + bytesWritten = 0; + } + + RIALTO_SERVER_LOG_INFO("%" PRIu64 "bytes written to gstreamer", bytesWritten); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to create the gst buffer"); + } + } + else + { + RIALTO_SERVER_LOG_INFO("No space in gstreamer buffer to write samples"); + } + + { + std::unique_lock lock(m_context.writeBufferMutex); + m_context.lastBytesWritten = bytesWritten; + } + m_context.writeBufferCond.notify_one(); +} +} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/ipc/CMakeLists.txt b/middleware/rialto-client/media/server/ipc/CMakeLists.txt new file mode 100644 index 000000000..17c5c6001 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/CMakeLists.txt @@ -0,0 +1,82 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Find includes in corresponding build directories +set( CMAKE_INCLUDE_CURRENT_DIR ON ) + +add_library ( + RialtoServerIpc + STATIC + + source/AckSender.cpp + source/ApplicationManagementServer.cpp + source/IpcFactory.cpp + source/MediaPipelineClient.cpp + source/MediaPipelineModuleService.cpp + source/MediaPipelineCapabilitiesModuleService.cpp + source/MediaKeysClient.cpp + source/MediaKeysModuleService.cpp + source/MediaKeysCapabilitiesModuleService.cpp + source/ControlClientServerInternal.cpp + source/ControlModuleService.cpp + source/ServerManagerModuleService.cpp + source/SessionManagementServer.cpp + source/SetLogLevelsService.cpp + source/RialtoCommonModule.cpp + source/WebAudioPlayerClient.cpp + source/WebAudioPlayerModuleService.cpp +) + +set_property (TARGET + RialtoServerIpc + PROPERTY POSITION_INDEPENDENT_CODE ON +) + +target_include_directories ( + RialtoServerIpc + + PUBLIC + interface + + PRIVATE + include + $ + $ + $ + $ + $ + $ + $ + $ + $ +) + +target_link_libraries ( + RialtoServerIpc + + PRIVATE + RialtoIpcServer + RialtoIpcCommon + RialtoPlayerCommon + RialtoServerMain + RialtoServerService + RialtoWrappers + RialtoProtobuf + Threads::Threads +) diff --git a/middleware/rialto-client/media/server/ipc/include/AckSender.h b/middleware/rialto-client/media/server/ipc/include/AckSender.h new file mode 100644 index 000000000..9c8dda6a4 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/AckSender.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_ACK_SENDER_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_ACK_SENDER_H_ + +#include "IAckSender.h" +#include "IIpcServer.h" +#include + +namespace firebolt::rialto::server::ipc +{ +class AckSender : public IAckSender +{ +public: + explicit AckSender(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); + ~AckSender() override = default; + + void send(int id, bool success) const override; + +private: + std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_ACK_SENDER_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/ApplicationManagementServer.h b/middleware/rialto-client/media/server/ipc/include/ApplicationManagementServer.h new file mode 100644 index 000000000..cec825d0b --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/ApplicationManagementServer.h @@ -0,0 +1,62 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_APPLICATION_MANAGEMENT_SERVER_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_APPLICATION_MANAGEMENT_SERVER_H_ + +#include "IApplicationManagementServer.h" +#include "IServerManagerModuleServiceFactory.h" +#include "ISessionServerManager.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class ApplicationManagementServer : public IApplicationManagementServer +{ +public: + ApplicationManagementServer(const std::shared_ptr &serverFactory, + const std::shared_ptr + &serverManagerModuleFactory, + service::ISessionServerManager &sessionServerManager); + ~ApplicationManagementServer() override; + ApplicationManagementServer(const ApplicationManagementServer &) = delete; + ApplicationManagementServer(ApplicationManagementServer &&) = delete; + ApplicationManagementServer &operator=(const ApplicationManagementServer &) = delete; + ApplicationManagementServer &operator=(ApplicationManagementServer &&) = delete; + + bool initialize(int socket) override; + bool sendStateChangedEvent(const common::SessionServerState &state) override; + void start() override; + void stop() override; + +private: + void onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client); + +private: + std::thread m_ipcServerThread; + std::shared_ptr<::firebolt::rialto::ipc::IServer> m_ipcServer; + std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; + std::shared_ptr<::rialto::ServerManagerModule> m_service; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_APPLICATION_MANAGEMENT_SERVER_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/ControlClientServerInternal.h b/middleware/rialto-client/media/server/ipc/include/ControlClientServerInternal.h new file mode 100644 index 000000000..bede10525 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/ControlClientServerInternal.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_CONTROL_CLIENT_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_CONTROL_CLIENT_SERVER_INTERNAL_H_ + +#include "IControlClientServerInternal.h" +#include "IIpcServer.h" +#include + +namespace firebolt::rialto::server::ipc +{ +class ControlClientServerInternal : public IControlClientServerInternal +{ +public: + explicit ControlClientServerInternal(int controlId, + const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); + ~ControlClientServerInternal() override = default; + + void notifyApplicationState(ApplicationState state) override; + void ping(uint32_t id) override; + +private: + const int m_kControlId; + std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_CONTROL_CLIENT_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/ControlModuleService.h b/middleware/rialto-client/media/server/ipc/include/ControlModuleService.h new file mode 100644 index 000000000..8204c2cd5 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/ControlModuleService.h @@ -0,0 +1,69 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_CONTROL_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_CONTROL_MODULE_SERVICE_H_ + +#include "IControlModuleService.h" +#include "IControlService.h" +#include "IPlaybackService.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class ControlModuleServiceFactory : public IControlModuleServiceFactory +{ +public: + ControlModuleServiceFactory() = default; + virtual ~ControlModuleServiceFactory() = default; + + std::shared_ptr create(service::IPlaybackService &playbackService, + service::IControlService &controlService) const override; +}; + +class ControlModuleService : public IControlModuleService +{ +public: + explicit ControlModuleService(service::IPlaybackService &playbackService, service::IControlService &controlService); + ~ControlModuleService() override; + + void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + + void getSharedMemory(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetSharedMemoryRequest *request, + ::firebolt::rialto::GetSharedMemoryResponse *response, + ::google::protobuf::Closure *done) override; + void registerClient(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::RegisterClientRequest *request, + ::firebolt::rialto::RegisterClientResponse *response, ::google::protobuf::Closure *done) override; + void ack(::google::protobuf::RpcController *controller, const ::firebolt::rialto::AckRequest *request, + ::firebolt::rialto::AckResponse *response, ::google::protobuf::Closure *done) override; + +private: + service::IPlaybackService &m_playbackService; + service::IControlService &m_controlService; + std::map, std::set> m_controlIds; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_CONTROL_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IControlModuleService.h b/middleware/rialto-client/media/server/ipc/include/IControlModuleService.h new file mode 100644 index 000000000..fce49275f --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/IControlModuleService.h @@ -0,0 +1,90 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_CONTROL_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_CONTROL_MODULE_SERVICE_H_ + +#include "IControlService.h" +#include "IPlaybackService.h" +#include "controlmodule.pb.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class IControlModuleService; + +/** + * @brief IControlModuleService factory class, returns a concrete implementation of IControlModuleService + */ +class IControlModuleServiceFactory +{ +public: + IControlModuleServiceFactory() = default; + virtual ~IControlModuleServiceFactory() = default; + + /** + * @brief Create a IControlModuleServiceFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a ControlModuleService object. + * + * @retval the control ipc instance or null on error. + */ + virtual std::shared_ptr create(service::IPlaybackService &playbackService, + service::IControlService &controlService) const = 0; +}; + +/** + * @brief The definition of the IControlModuleService interface. + */ +class IControlModuleService : public ::firebolt::rialto::ControlModule, + public std::enable_shared_from_this +{ +public: + IControlModuleService() = default; + virtual ~IControlModuleService() = default; + + IControlModuleService(const IControlModuleService &) = delete; + IControlModuleService(IControlModuleService &&) = delete; + IControlModuleService &operator=(const IControlModuleService &) = delete; + IControlModuleService &operator=(IControlModuleService &&) = delete; + + /** + * @brief Connect to the ipc client. + * + * @param[in] ipcClient : The ipc client to connect to. + */ + virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; + + /** + * @brief Disconnect from the ipc client. + * + * @param[in] ipcClient : The ipc client to disconnect to. + */ + virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; +}; + +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_CONTROL_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IMediaKeysCapabilitiesModuleService.h b/middleware/rialto-client/media/server/ipc/include/IMediaKeysCapabilitiesModuleService.h new file mode 100644 index 000000000..ac1997960 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/IMediaKeysCapabilitiesModuleService.h @@ -0,0 +1,91 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ + +#include "ICdmService.h" +#include "mediakeyscapabilitiesmodule.pb.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class IMediaKeysCapabilitiesModuleService; + +/** + * @brief IMediaKeysCapabilitiesModuleService factory class, returns a concrete implementation of + * IMediaKeysCapabilitiesModuleService + */ +class IMediaKeysCapabilitiesModuleServiceFactory +{ +public: + IMediaKeysCapabilitiesModuleServiceFactory() = default; + virtual ~IMediaKeysCapabilitiesModuleServiceFactory() = default; + + /** + * @brief Create a IMediaKeysCapabilitiesModuleServiceFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a MediaKeysCapabilitiesModuleService object. + * + * @param[in] cdmService : The service for cdm objects. + * + * @retval the rialto controller ipc instance or null on error. + */ + virtual std::shared_ptr create(service::ICdmService &cdmService) const = 0; +}; + +/** + * @brief The definition of the IMediaKeysCapabilitiesModuleService interface. + */ +class IMediaKeysCapabilitiesModuleService : public ::firebolt::rialto::MediaKeysCapabilitiesModule, + public std::enable_shared_from_this +{ +public: + IMediaKeysCapabilitiesModuleService() = default; + virtual ~IMediaKeysCapabilitiesModuleService() = default; + + IMediaKeysCapabilitiesModuleService(const IMediaKeysCapabilitiesModuleService &) = delete; + IMediaKeysCapabilitiesModuleService(IMediaKeysCapabilitiesModuleService &&) = delete; + IMediaKeysCapabilitiesModuleService &operator=(const IMediaKeysCapabilitiesModuleService &) = delete; + IMediaKeysCapabilitiesModuleService &operator=(IMediaKeysCapabilitiesModuleService &&) = delete; + + /** + * @brief Connect to the ipc client. + * + * @param[in] ipcClient : The ipc client to connect to. + */ + virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; + + /** + * @brief Disconnect from the ipc client. + * + * @param[in] ipcClient : The ipc client to disconnect to. + */ + virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; +}; + +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IMediaKeysModuleService.h b/middleware/rialto-client/media/server/ipc/include/IMediaKeysModuleService.h new file mode 100644 index 000000000..ea4d3f8c8 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/IMediaKeysModuleService.h @@ -0,0 +1,90 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_MODULE_SERVICE_H_ + +#include "ICdmService.h" +#include "mediakeysmodule.pb.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class IMediaKeysModuleService; + +/** + * @brief IMediaKeysModuleService factory class, returns a concrete implementation of IMediaKeysModuleService + */ +class IMediaKeysModuleServiceFactory +{ +public: + IMediaKeysModuleServiceFactory() = default; + virtual ~IMediaKeysModuleServiceFactory() = default; + + /** + * @brief Create a IMediaKeysModuleServiceFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a MediaKeysModuleService object. + * + * @param[in] cdmService : The service for cdm objects. + * + * @retval the rialto controller ipc instance or null on error. + */ + virtual std::shared_ptr create(service::ICdmService &cdmService) const = 0; +}; + +/** + * @brief The definition of the IMediaKeysModuleService interface. + */ +class IMediaKeysModuleService : public ::firebolt::rialto::MediaKeysModule, + public std::enable_shared_from_this +{ +public: + IMediaKeysModuleService() = default; + virtual ~IMediaKeysModuleService() = default; + + IMediaKeysModuleService(const IMediaKeysModuleService &) = delete; + IMediaKeysModuleService(IMediaKeysModuleService &&) = delete; + IMediaKeysModuleService &operator=(const IMediaKeysModuleService &) = delete; + IMediaKeysModuleService &operator=(IMediaKeysModuleService &&) = delete; + + /** + * @brief Connect to the ipc client. + * + * @param[in] ipcClient : The ipc client to connect to. + */ + virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; + + /** + * @brief Disconnect from the ipc client. + * + * @param[in] ipcClient : The ipc client to disconnect to. + */ + virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; +}; + +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IMediaPipelineCapabilitiesModuleService.h b/middleware/rialto-client/media/server/ipc/include/IMediaPipelineCapabilitiesModuleService.h new file mode 100644 index 000000000..df597614b --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/IMediaPipelineCapabilitiesModuleService.h @@ -0,0 +1,91 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ + +#include "IMediaPipelineService.h" +#include "mediapipelinecapabilitiesmodule.pb.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class IMediaPipelineCapabilitiesModuleService; + +/** + * @brief IMediaPipelineCapabilitiesModuleService factory class, returns a concrete implementation of + * IMediaPipelineCapabilitiesModuleService + */ +class IMediaPipelineCapabilitiesModuleServiceFactory +{ +public: + IMediaPipelineCapabilitiesModuleServiceFactory() = default; + virtual ~IMediaPipelineCapabilitiesModuleServiceFactory() = default; + + /** + * @brief Create a IMediaPipelineCapabilitiesModuleServiceFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a MediaPipelineCapabilitiesModuleService object. + * + * @param[in] mediaPipelineService : The service for media pipeline objects + */ + virtual std::shared_ptr + create(service::IMediaPipelineService &mediaPipelineService) const = 0; +}; + +/** + * @brief The definition of the IMediaPipelineCapabilitiesModuleService interface. + */ +class IMediaPipelineCapabilitiesModuleService + : public ::firebolt::rialto::MediaPipelineCapabilitiesModule, + public std::enable_shared_from_this +{ +public: + IMediaPipelineCapabilitiesModuleService() = default; + virtual ~IMediaPipelineCapabilitiesModuleService() = default; + + IMediaPipelineCapabilitiesModuleService(const IMediaPipelineCapabilitiesModuleService &) = delete; + IMediaPipelineCapabilitiesModuleService(IMediaPipelineCapabilitiesModuleService &&) = delete; + IMediaPipelineCapabilitiesModuleService &operator=(const IMediaPipelineCapabilitiesModuleService &) = delete; + IMediaPipelineCapabilitiesModuleService &operator=(IMediaPipelineCapabilitiesModuleService &&) = delete; + + /** + * @brief Connect to the ipc client. + * + * @param[in] ipcClient : The ipc client to connect to. + */ + virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; + + /** + * @brief Disconnect from the ipc client. + * + * @param[in] ipcClient : The ipc client to disconnect to. + */ + virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; +}; + +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IMediaPipelineModuleService.h b/middleware/rialto-client/media/server/ipc/include/IMediaPipelineModuleService.h new file mode 100644 index 000000000..a9604a90c --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/IMediaPipelineModuleService.h @@ -0,0 +1,89 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_MODULE_SERVICE_H_ + +#include "IMediaPipelineService.h" +#include "mediapipelinemodule.pb.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class IMediaPipelineModuleService; + +/** + * @brief IMediaPipelineModuleService factory class, returns a concrete implementation of IMediaPipelineModuleService + */ +class IMediaPipelineModuleServiceFactory +{ +public: + IMediaPipelineModuleServiceFactory() = default; + virtual ~IMediaPipelineModuleServiceFactory() = default; + + /** + * @brief Create a IMediaPipelineModuleServiceFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a MediaPipelineModuleService object. + * + * @retval the rialto controller ipc instance or null on error. + */ + virtual std::shared_ptr + create(service::IMediaPipelineService &mediaPipelineService) const = 0; +}; + +/** + * @brief The definition of the IMediaPipelineModuleService interface. + */ +class IMediaPipelineModuleService : public ::firebolt::rialto::MediaPipelineModule, + public std::enable_shared_from_this +{ +public: + IMediaPipelineModuleService() = default; + virtual ~IMediaPipelineModuleService() = default; + + IMediaPipelineModuleService(const IMediaPipelineModuleService &) = delete; + IMediaPipelineModuleService(IMediaPipelineModuleService &&) = delete; + IMediaPipelineModuleService &operator=(const IMediaPipelineModuleService &) = delete; + IMediaPipelineModuleService &operator=(IMediaPipelineModuleService &&) = delete; + + /** + * @brief Connect to the ipc client. + * + * @param[in] ipcClient : The ipc client to connect to. + */ + virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; + + /** + * @brief Disconnect from the ipc client. + * + * @param[in] ipcClient : The ipc client to disconnect to. + */ + virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; +}; + +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IServerManagerModuleServiceFactory.h b/middleware/rialto-client/media/server/ipc/include/IServerManagerModuleServiceFactory.h new file mode 100644 index 000000000..2901a9e2e --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/IServerManagerModuleServiceFactory.h @@ -0,0 +1,56 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_SERVER_MANAGER_MODULE_SERVICE_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_SERVER_MANAGER_MODULE_SERVICE_FACTORY_H_ + +#include "ISessionServerManager.h" +#include "servermanagermodule.pb.h" +#include + +namespace firebolt::rialto::server::ipc +{ +/** + * @brief IServerManagerModuleService factory class, returns a concrete implementation of IServerManagerModuleService + */ +class IServerManagerModuleServiceFactory +{ +public: + IServerManagerModuleServiceFactory() = default; + virtual ~IServerManagerModuleServiceFactory() = default; + + /** + * @brief Create a IServerManagerModuleServiceFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a ServerManagerModule object. + * + * @retval the rialto controller ipc instance or null on error. + */ + virtual std::shared_ptr<::rialto::ServerManagerModule> + create(service::ISessionServerManager &sessionServerManager) const = 0; +}; + +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_SERVER_MANAGER_MODULE_SERVICE_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IWebAudioPlayerModuleService.h b/middleware/rialto-client/media/server/ipc/include/IWebAudioPlayerModuleService.h new file mode 100644 index 000000000..755ed6766 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/IWebAudioPlayerModuleService.h @@ -0,0 +1,89 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ + +#include "IWebAudioPlayerService.h" +#include "webaudioplayermodule.pb.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class IWebAudioPlayerModuleService; + +/** + * @brief IWebAudioPlayerModuleService factory class, returns a concrete implementation of IWebAudioPlayerModuleService + */ +class IWebAudioPlayerModuleServiceFactory +{ +public: + IWebAudioPlayerModuleServiceFactory() = default; + virtual ~IWebAudioPlayerModuleServiceFactory() = default; + + /** + * @brief Create a IWebAudioPlayerModuleServiceFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief Creates a WebAudioPlayerModuleService object. + * + * @retval the web audio player ipc instance or null on error. + */ + virtual std::shared_ptr + create(service::IWebAudioPlayerService &webAudioPlayerService) const = 0; +}; + +/** + * @brief The definition of the IWebAudioPlayerModuleService interface. + */ +class IWebAudioPlayerModuleService : public ::firebolt::rialto::WebAudioPlayerModule, + public std::enable_shared_from_this +{ +public: + IWebAudioPlayerModuleService() = default; + virtual ~IWebAudioPlayerModuleService() = default; + + IWebAudioPlayerModuleService(const IWebAudioPlayerModuleService &) = delete; + IWebAudioPlayerModuleService(IWebAudioPlayerModuleService &&) = delete; + IWebAudioPlayerModuleService &operator=(const IWebAudioPlayerModuleService &) = delete; + IWebAudioPlayerModuleService &operator=(IWebAudioPlayerModuleService &&) = delete; + + /** + * @brief Connect to the ipc client. + * + * @param[in] ipcClient : The ipc client to connect to. + */ + virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; + + /** + * @brief Disconnect from the ipc client. + * + * @param[in] ipcClient : The ipc client to disconnect to. + */ + virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; +}; + +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaKeysCapabilitiesModuleService.h b/middleware/rialto-client/media/server/ipc/include/MediaKeysCapabilitiesModuleService.h new file mode 100644 index 000000000..d88c3c0e5 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/MediaKeysCapabilitiesModuleService.h @@ -0,0 +1,71 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ + +#include "ICdmService.h" +#include "IMediaKeysCapabilitiesModuleService.h" +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class MediaKeysCapabilitiesModuleServiceFactory : public IMediaKeysCapabilitiesModuleServiceFactory +{ +public: + MediaKeysCapabilitiesModuleServiceFactory() = default; + virtual ~MediaKeysCapabilitiesModuleServiceFactory() = default; + + std::shared_ptr create(service::ICdmService &cdmService) const override; +}; + +class MediaKeysCapabilitiesModuleService : public IMediaKeysCapabilitiesModuleService +{ +public: + explicit MediaKeysCapabilitiesModuleService(service::ICdmService &cdmService); + ~MediaKeysCapabilitiesModuleService() override; + + void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + + void getSupportedKeySystems(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetSupportedKeySystemsRequest *request, + ::firebolt::rialto::GetSupportedKeySystemsResponse *response, + ::google::protobuf::Closure *done) override; + void supportsKeySystem(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SupportsKeySystemRequest *request, + ::firebolt::rialto::SupportsKeySystemResponse *response, + ::google::protobuf::Closure *done) override; + void getSupportedKeySystemVersion(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetSupportedKeySystemVersionRequest *request, + ::firebolt::rialto::GetSupportedKeySystemVersionResponse *response, + ::google::protobuf::Closure *done) override; + void isServerCertificateSupported(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::IsServerCertificateSupportedRequest *request, + ::firebolt::rialto::IsServerCertificateSupportedResponse *response, + ::google::protobuf::Closure *done) override; + +private: + service::ICdmService &m_cdmService; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaKeysClient.h b/middleware/rialto-client/media/server/ipc/include/MediaKeysClient.h new file mode 100644 index 000000000..9d9206b08 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/MediaKeysClient.h @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CLIENT_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CLIENT_H_ + +#include "IIpcServer.h" +#include "IMediaKeysClient.h" +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class MediaKeysClient : public IMediaKeysClient +{ +public: + MediaKeysClient(int mediaKeysHandle, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); + ~MediaKeysClient() override; + + void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, + const std::string &url) override; + void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) override; + void onKeyStatusesChanged(int32_t keySessionId, const KeyStatusVector &keyStatuses) override; + +private: + int m_mediaKeysHandle; + std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaKeysModuleService.h b/middleware/rialto-client/media/server/ipc/include/MediaKeysModuleService.h new file mode 100644 index 000000000..738201269 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/MediaKeysModuleService.h @@ -0,0 +1,126 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_MODULE_SERVICE_H_ + +#include "ICdmService.h" +#include "IMediaKeysModuleService.h" +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class MediaKeysModuleServiceFactory : public IMediaKeysModuleServiceFactory +{ +public: + MediaKeysModuleServiceFactory() = default; + virtual ~MediaKeysModuleServiceFactory() = default; + + std::shared_ptr create(service::ICdmService &cdmService) const override; +}; + +class MediaKeysModuleService : public IMediaKeysModuleService +{ +public: + explicit MediaKeysModuleService(service::ICdmService &cdmService); + ~MediaKeysModuleService() override; + + void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + + void createMediaKeys(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CreateMediaKeysRequest *request, + ::firebolt::rialto::CreateMediaKeysResponse *response, + ::google::protobuf::Closure *done) override; + void destroyMediaKeys(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DestroyMediaKeysRequest *request, + ::firebolt::rialto::DestroyMediaKeysResponse *response, + ::google::protobuf::Closure *done) override; + void containsKey(::google::protobuf::RpcController *controller, const ::firebolt::rialto::ContainsKeyRequest *request, + ::firebolt::rialto::ContainsKeyResponse *response, ::google::protobuf::Closure *done) override; + void createKeySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CreateKeySessionRequest *request, + ::firebolt::rialto::CreateKeySessionResponse *response, + ::google::protobuf::Closure *done) override; + void generateRequest(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GenerateRequestRequest *request, + ::firebolt::rialto::GenerateRequestResponse *response, + ::google::protobuf::Closure *done) override; + void loadSession(::google::protobuf::RpcController *controller, const ::firebolt::rialto::LoadSessionRequest *request, + ::firebolt::rialto::LoadSessionResponse *response, ::google::protobuf::Closure *done) override; + void updateSession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::UpdateSessionRequest *request, + ::firebolt::rialto::UpdateSessionResponse *response, ::google::protobuf::Closure *done) override; + void setDrmHeader(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetDrmHeaderRequest *request, + ::firebolt::rialto::SetDrmHeaderResponse *response, ::google::protobuf::Closure *done) override; + void closeKeySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CloseKeySessionRequest *request, + ::firebolt::rialto::CloseKeySessionResponse *response, + ::google::protobuf::Closure *done) override; + void removeKeySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::RemoveKeySessionRequest *request, + ::firebolt::rialto::RemoveKeySessionResponse *response, + ::google::protobuf::Closure *done) override; + void deleteDrmStore(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DeleteDrmStoreRequest *request, + ::firebolt::rialto::DeleteDrmStoreResponse *response, ::google::protobuf::Closure *done) override; + void deleteKeyStore(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DeleteKeyStoreRequest *request, + ::firebolt::rialto::DeleteKeyStoreResponse *response, ::google::protobuf::Closure *done) override; + void getDrmStoreHash(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetDrmStoreHashRequest *request, + ::firebolt::rialto::GetDrmStoreHashResponse *response, + ::google::protobuf::Closure *done) override; + void getKeyStoreHash(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetKeyStoreHashRequest *request, + ::firebolt::rialto::GetKeyStoreHashResponse *response, + ::google::protobuf::Closure *done) override; + void getLdlSessionsLimit(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetLdlSessionsLimitRequest *request, + ::firebolt::rialto::GetLdlSessionsLimitResponse *response, + ::google::protobuf::Closure *done) override; + void getLastDrmError(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetLastDrmErrorRequest *request, + ::firebolt::rialto::GetLastDrmErrorResponse *response, + ::google::protobuf::Closure *done) override; + void getDrmTime(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetDrmTimeRequest *request, + ::firebolt::rialto::GetDrmTimeResponse *response, ::google::protobuf::Closure *done) override; + void getCdmKeySessionId(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetCdmKeySessionIdRequest *request, + ::firebolt::rialto::GetCdmKeySessionIdResponse *response, + ::google::protobuf::Closure *done) override; + void releaseKeySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::ReleaseKeySessionRequest *request, + ::firebolt::rialto::ReleaseKeySessionResponse *response, + ::google::protobuf::Closure *done) override; + void getMetricSystemData(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetMetricSystemDataRequest *request, + ::firebolt::rialto::GetMetricSystemDataResponse *response, + ::google::protobuf::Closure *done) override; + +private: + service::ICdmService &m_cdmService; + std::map, std::set> m_clientMediaKeysHandles; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h b/middleware/rialto-client/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h new file mode 100644 index 000000000..e74f19fcf --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h @@ -0,0 +1,71 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ + +#include "IMediaPipelineCapabilitiesModuleService.h" +#include "IMediaPipelineService.h" +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class MediaPipelineCapabilitiesModuleServiceFactory : public IMediaPipelineCapabilitiesModuleServiceFactory +{ +public: + MediaPipelineCapabilitiesModuleServiceFactory() = default; + virtual ~MediaPipelineCapabilitiesModuleServiceFactory() = default; + + std::shared_ptr + create(service::IMediaPipelineService &mediaPipelineService) const override; +}; + +class MediaPipelineCapabilitiesModuleService : public IMediaPipelineCapabilitiesModuleService +{ +public: + explicit MediaPipelineCapabilitiesModuleService(service::IMediaPipelineService &mediaPipelineService); + ~MediaPipelineCapabilitiesModuleService() override; + + void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + + void getSupportedMimeTypes(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetSupportedMimeTypesRequest *request, + ::firebolt::rialto::GetSupportedMimeTypesResponse *response, + ::google::protobuf::Closure *done) override; + void isMimeTypeSupported(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::IsMimeTypeSupportedRequest *request, + ::firebolt::rialto::IsMimeTypeSupportedResponse *response, + ::google::protobuf::Closure *done) override; + void getSupportedProperties(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetSupportedPropertiesRequest *request, + ::firebolt::rialto::GetSupportedPropertiesResponse *response, + ::google::protobuf::Closure *done) override; + void isVideoMaster(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::IsVideoMasterRequest *request, + ::firebolt::rialto::IsVideoMasterResponse *response, ::google::protobuf::Closure *done) override; + +private: + service::IMediaPipelineService &m_mediaPipelineService; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaPipelineClient.h b/middleware/rialto-client/media/server/ipc/include/MediaPipelineClient.h new file mode 100644 index 000000000..e8514052a --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/MediaPipelineClient.h @@ -0,0 +1,62 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CLIENT_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CLIENT_H_ + +#include "IIpcServer.h" +#include "IMediaPipelineClient.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class MediaPipelineClient : public IMediaPipelineClient +{ +public: + MediaPipelineClient(int sessionId, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); + ~MediaPipelineClient() override; + + void notifyDuration(int64_t duration) override; + void notifyPosition(int64_t position) override; + void notifyNativeSize(uint32_t width, uint32_t height, double aspect) override; + void notifyNetworkState(NetworkState state) override; + void notifyPlaybackState(PlaybackState state) override; + void notifyVideoData(bool hasData) override; + void notifyAudioData(bool hasData) override; + void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, + const std::shared_ptr &shmInfo) override; + void notifyCancelNeedMediaData(int32_t sourceId) override; + void notifyQos(int32_t sourceId, const QosInfo &qosInfo) override; + void notifyBufferUnderflow(int32_t sourceId) override; + void notifyPlaybackError(int32_t sourceId, PlaybackError error) override; + void notifySourceFlushed(int32_t sourceId) override; + +private: + int m_sessionId; + std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; + + // It is possible for a needData to be sent while a source is been attached, + // this causes an issue in client side as they recieve a needData from a source + // id they are unaware of. + std::mutex m_needDataMutex; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaPipelineModuleService.h b/middleware/rialto-client/media/server/ipc/include/MediaPipelineModuleService.h new file mode 100644 index 000000000..86ae1239f --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/MediaPipelineModuleService.h @@ -0,0 +1,169 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_MODULE_SERVICE_H_ + +#include "IMediaPipelineClient.h" +#include "IMediaPipelineModuleService.h" +#include "IMediaPipelineService.h" +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class MediaPipelineModuleServiceFactory : public IMediaPipelineModuleServiceFactory +{ +public: + MediaPipelineModuleServiceFactory() = default; + virtual ~MediaPipelineModuleServiceFactory() = default; + + std::shared_ptr create(service::IMediaPipelineService &mediaPipelineService) const override; +}; + +class MediaPipelineModuleService : public IMediaPipelineModuleService +{ +public: + explicit MediaPipelineModuleService(service::IMediaPipelineService &mediaPipelineService); + ~MediaPipelineModuleService() override; + + void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + + void createSession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CreateSessionRequest *request, + ::firebolt::rialto::CreateSessionResponse *response, ::google::protobuf::Closure *done) override; + void destroySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DestroySessionRequest *request, + ::firebolt::rialto::DestroySessionResponse *response, ::google::protobuf::Closure *done) override; + void load(::google::protobuf::RpcController *controller, const ::firebolt::rialto::LoadRequest *request, + ::firebolt::rialto::LoadResponse *response, ::google::protobuf::Closure *done) override; + void setVideoWindow(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetVideoWindowRequest *request, + ::firebolt::rialto::SetVideoWindowResponse *response, ::google::protobuf::Closure *done) override; + void attachSource(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::AttachSourceRequest *request, + ::firebolt::rialto::AttachSourceResponse *response, ::google::protobuf::Closure *done) override; + void removeSource(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::RemoveSourceRequest *request, + ::firebolt::rialto::RemoveSourceResponse *response, ::google::protobuf::Closure *done) override; + void allSourcesAttached(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::AllSourcesAttachedRequest *request, + ::firebolt::rialto::AllSourcesAttachedResponse *response, + ::google::protobuf::Closure *done) override; + void play(::google::protobuf::RpcController *controller, const ::firebolt::rialto::PlayRequest *request, + ::firebolt::rialto::PlayResponse *response, ::google::protobuf::Closure *done) override; + void pause(::google::protobuf::RpcController *controller, const ::firebolt::rialto::PauseRequest *request, + ::firebolt::rialto::PauseResponse *response, ::google::protobuf::Closure *done) override; + void stop(::google::protobuf::RpcController *controller, const ::firebolt::rialto::StopRequest *request, + ::firebolt::rialto::StopResponse *response, ::google::protobuf::Closure *done) override; + void setPosition(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetPositionRequest *request, + ::firebolt::rialto::SetPositionResponse *response, ::google::protobuf::Closure *done) override; + void haveData(::google::protobuf::RpcController *controller, const ::firebolt::rialto::HaveDataRequest *request, + ::firebolt::rialto::HaveDataResponse *response, ::google::protobuf::Closure *done) override; + void setPlaybackRate(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetPlaybackRateRequest *request, + ::firebolt::rialto::SetPlaybackRateResponse *response, + ::google::protobuf::Closure *done) override; + void getPosition(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetPositionRequest *request, + ::firebolt::rialto::GetPositionResponse *response, ::google::protobuf::Closure *done) override; + void setImmediateOutput(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetImmediateOutputRequest *request, + ::firebolt::rialto::SetImmediateOutputResponse *response, + ::google::protobuf::Closure *done) override; + void getImmediateOutput(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetImmediateOutputRequest *request, + ::firebolt::rialto::GetImmediateOutputResponse *response, + ::google::protobuf::Closure *done) override; + void getStats(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetStatsRequest *request, + ::firebolt::rialto::GetStatsResponse *response, ::google::protobuf::Closure *done) override; + void renderFrame(::google::protobuf::RpcController *controller, const ::firebolt::rialto::RenderFrameRequest *request, + ::firebolt::rialto::RenderFrameResponse *response, ::google::protobuf::Closure *done) override; + void setVolume(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetVolumeRequest *request, + ::firebolt::rialto::SetVolumeResponse *response, ::google::protobuf::Closure *done) override; + void getVolume(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetVolumeRequest *request, + ::firebolt::rialto::GetVolumeResponse *response, ::google::protobuf::Closure *done) override; + void setMute(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetMuteRequest *request, + ::firebolt::rialto::SetMuteResponse *response, ::google::protobuf::Closure *done) override; + void getMute(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetMuteRequest *request, + ::firebolt::rialto::GetMuteResponse *response, ::google::protobuf::Closure *done) override; + void setTextTrackIdentifier(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetTextTrackIdentifierRequest *request, + ::firebolt::rialto::SetTextTrackIdentifierResponse *response, + ::google::protobuf::Closure *done) override; + void getTextTrackIdentifier(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetTextTrackIdentifierRequest *request, + ::firebolt::rialto::GetTextTrackIdentifierResponse *response, + ::google::protobuf::Closure *done) override; + void setLowLatency(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetLowLatencyRequest *request, + ::firebolt::rialto::SetLowLatencyResponse *response, ::google::protobuf::Closure *done) override; + void setSync(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetSyncRequest *request, + ::firebolt::rialto::SetSyncResponse *response, ::google::protobuf::Closure *done) override; + void getSync(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSyncRequest *request, + ::firebolt::rialto::GetSyncResponse *response, ::google::protobuf::Closure *done) override; + void setSyncOff(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetSyncOffRequest *request, + ::firebolt::rialto::SetSyncOffResponse *response, ::google::protobuf::Closure *done) override; + void setStreamSyncMode(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetStreamSyncModeRequest *request, + ::firebolt::rialto::SetStreamSyncModeResponse *response, + ::google::protobuf::Closure *done) override; + void getStreamSyncMode(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetStreamSyncModeRequest *request, + ::firebolt::rialto::GetStreamSyncModeResponse *response, + ::google::protobuf::Closure *done) override; + void flush(::google::protobuf::RpcController *controller, const ::firebolt::rialto::FlushRequest *request, + ::firebolt::rialto::FlushResponse *response, ::google::protobuf::Closure *done) override; + void setSourcePosition(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetSourcePositionRequest *request, + ::firebolt::rialto::SetSourcePositionResponse *response, + ::google::protobuf::Closure *done) override; + void setSubtitleOffset(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetSubtitleOffsetRequest *request, + ::firebolt::rialto::SetSubtitleOffsetResponse *response, + ::google::protobuf::Closure *done) override; + void processAudioGap(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::ProcessAudioGapRequest *request, + ::firebolt::rialto::ProcessAudioGapResponse *response, + ::google::protobuf::Closure *done) override; + void setBufferingLimit(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetBufferingLimitRequest *request, + ::firebolt::rialto::SetBufferingLimitResponse *response, + ::google::protobuf::Closure *done) override; + void getBufferingLimit(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetBufferingLimitRequest *request, + ::firebolt::rialto::GetBufferingLimitResponse *response, + ::google::protobuf::Closure *done) override; + void setUseBuffering(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetUseBufferingRequest *request, + ::firebolt::rialto::SetUseBufferingResponse *response, + ::google::protobuf::Closure *done) override; + void getUseBuffering(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetUseBufferingRequest *request, + ::firebolt::rialto::GetUseBufferingResponse *response, + ::google::protobuf::Closure *done) override; + +private: + service::IMediaPipelineService &m_mediaPipelineService; + std::map, std::set> m_clientSessions; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/RialtoCommonModule.h b/middleware/rialto-client/media/server/ipc/include/RialtoCommonModule.h new file mode 100644 index 000000000..cea726195 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/RialtoCommonModule.h @@ -0,0 +1,31 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_RIALTO_COMMON_MODULE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_RIALTO_COMMON_MODULE_H_ + +#include "MediaCommon.h" +#include "rialtocommon.pb.h" + +namespace firebolt::rialto::server::ipc +{ +firebolt::rialto::MediaSourceType convertMediaSourceType(const firebolt::rialto::ProtoMediaSourceType &mediaSourceType); +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_RIALTO_COMMON_MODULE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/ServerManagerModuleService.h b/middleware/rialto-client/media/server/ipc/include/ServerManagerModuleService.h new file mode 100644 index 000000000..483c2e138 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/ServerManagerModuleService.h @@ -0,0 +1,60 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_SERVER_MANAGER_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_SERVER_MANAGER_MODULE_SERVICE_H_ + +#include "IServerManagerModuleServiceFactory.h" +#include "ISessionServerManager.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class ServerManagerModuleServiceFactory : public IServerManagerModuleServiceFactory +{ +public: + ServerManagerModuleServiceFactory() = default; + virtual ~ServerManagerModuleServiceFactory() = default; + + std::shared_ptr<::rialto::ServerManagerModule> + create(service::ISessionServerManager &sessionServerManager) const override; +}; + +class ServerManagerModuleService : public ::rialto::ServerManagerModule +{ +public: + explicit ServerManagerModuleService(service::ISessionServerManager &sessionServerManager); + ~ServerManagerModuleService() override; + + void setConfiguration(::google::protobuf::RpcController *controller, const ::rialto::SetConfigurationRequest *request, + ::rialto::SetConfigurationResponse *response, ::google::protobuf::Closure *done) override; + void setState(::google::protobuf::RpcController *controller, const ::rialto::SetStateRequest *request, + ::rialto::SetStateResponse *response, ::google::protobuf::Closure *done) override; + void setLogLevels(::google::protobuf::RpcController *controller, const ::rialto::SetLogLevelsRequest *request, + ::rialto::SetLogLevelsResponse *response, ::google::protobuf::Closure *done) override; + void ping(::google::protobuf::RpcController *controller, const ::rialto::PingRequest *request, + ::rialto::PingResponse *response, ::google::protobuf::Closure *done) override; + +private: + service::ISessionServerManager &m_sessionServerManager; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_SERVER_MANAGER_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/SessionManagementServer.h b/middleware/rialto-client/media/server/ipc/include/SessionManagementServer.h new file mode 100644 index 000000000..81510d7a5 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/SessionManagementServer.h @@ -0,0 +1,89 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_SESSION_MANAGEMENT_SERVER_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_SESSION_MANAGEMENT_SERVER_H_ + +#include "IControlModuleService.h" +#include "IControlService.h" +#include "ILinuxWrapper.h" +#include "IMediaKeysCapabilitiesModuleService.h" +#include "IMediaKeysModuleService.h" +#include "IMediaPipelineCapabilitiesModuleService.h" +#include "IMediaPipelineModuleService.h" +#include "IPlaybackService.h" +#include "ISessionManagementServer.h" +#include "IWebAudioPlayerModuleService.h" +#include "SetLogLevelsService.h" +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class SessionManagementServer : public ISessionManagementServer +{ +public: + SessionManagementServer( + const std::shared_ptr &serverFactory, + const std::shared_ptr &mediaPipelineModuleFactory, + const std::shared_ptr &mediaPipelineCapabilitiesModuleFactory, + const std::shared_ptr &mediaKeysModuleFactory, + const std::shared_ptr &mediaKeysCapabilitiesModuleFactory, + const std::shared_ptr &webAudioPlayerModuleFactory, + const std::shared_ptr &controlModuleFactory, + service::IPlaybackService &playbackService, service::ICdmService &cdmService, + service::IControlService &controlService); + ~SessionManagementServer() override; + SessionManagementServer(const SessionManagementServer &) = delete; + SessionManagementServer(SessionManagementServer &&) = delete; + SessionManagementServer &operator=(const SessionManagementServer &) = delete; + SessionManagementServer &operator=(SessionManagementServer &&) = delete; + + bool initialize(const std::string &socketName, unsigned int socketPermissions, const std::string &socketOwner, + const std::string &socketGroup) override; + bool initialize(int32_t socketFd) override; + void start() override; + void stop() override; + void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, + RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) override; + +private: + void onClientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client); + void onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client); + size_t getBufferSizeForPasswordStructureCalls() const; + +private: + std::atomic m_isRunning; + std::thread m_ipcServerThread; + std::shared_ptr<::firebolt::rialto::ipc::IServer> m_ipcServer; + std::shared_ptr m_mediaPipelineModule; + std::shared_ptr m_mediaPipelineCapabilitiesModule; + std::shared_ptr m_mediaKeysModule; + std::shared_ptr m_mediaKeysCapabilitiesModule; + std::shared_ptr m_webAudioPlayerModule; + std::shared_ptr m_controlModule; + SetLogLevelsService m_setLogLevelsService; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_SESSION_MANAGEMENT_SERVER_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/SetLogLevelsService.h b/middleware/rialto-client/media/server/ipc/include/SetLogLevelsService.h new file mode 100644 index 000000000..196f89536 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/SetLogLevelsService.h @@ -0,0 +1,53 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_SET_LOG_LEVELS_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_SET_LOG_LEVELS_SERVICE_H_ + +#include +#include +#include + +#include "IIpcServer.h" +#include "RialtoLogging.h" + +namespace firebolt::rialto::server::ipc +{ +class SetLogLevelsService +{ +public: + SetLogLevelsService() = default; + ~SetLogLevelsService() = default; + SetLogLevelsService(const SetLogLevelsService &) = delete; + SetLogLevelsService(SetLogLevelsService &&) = delete; + SetLogLevelsService &operator=(const SetLogLevelsService &) = delete; + SetLogLevelsService &operator=(SetLogLevelsService &&) = delete; + + void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); + void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); + void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, + RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels); + +private: + std::mutex m_mutex; + std::set> m_connectedClients; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_SET_LOG_LEVELS_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerClient.h b/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerClient.h new file mode 100644 index 000000000..dc01f189a --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerClient.h @@ -0,0 +1,43 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_CLIENT_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_CLIENT_H_ + +#include "IIpcServer.h" +#include "IWebAudioPlayerClient.h" +#include + +namespace firebolt::rialto::server::ipc +{ +class WebAudioPlayerClient : public IWebAudioPlayerClient +{ +public: + WebAudioPlayerClient(int webAudioPlayerHandle, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); + ~WebAudioPlayerClient() override; + + void notifyState(WebAudioPlayerState state) override; + +private: + int m_webAudioPlayerHandle; + std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerModuleService.h b/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerModuleService.h new file mode 100644 index 000000000..a863928ba --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerModuleService.h @@ -0,0 +1,94 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ + +#include "IWebAudioPlayerClient.h" +#include "IWebAudioPlayerModuleService.h" +#include "IWebAudioPlayerService.h" +#include +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class WebAudioPlayerModuleServiceFactory : public IWebAudioPlayerModuleServiceFactory +{ +public: + WebAudioPlayerModuleServiceFactory() = default; + virtual ~WebAudioPlayerModuleServiceFactory() = default; + + std::shared_ptr + create(service::IWebAudioPlayerService &webAudioPlayerService) const override; +}; + +class WebAudioPlayerModuleService : public IWebAudioPlayerModuleService +{ +public: + explicit WebAudioPlayerModuleService(service::IWebAudioPlayerService &webAudioPlayerService); + ~WebAudioPlayerModuleService() override; + + void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; + + void createWebAudioPlayer(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CreateWebAudioPlayerRequest *request, + ::firebolt::rialto::CreateWebAudioPlayerResponse *response, + ::google::protobuf::Closure *done) override; + void destroyWebAudioPlayer(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DestroyWebAudioPlayerRequest *request, + ::firebolt::rialto::DestroyWebAudioPlayerResponse *response, + ::google::protobuf::Closure *done) override; + void play(::google::protobuf::RpcController *controller, const ::firebolt::rialto::WebAudioPlayRequest *request, + ::firebolt::rialto::WebAudioPlayResponse *response, ::google::protobuf::Closure *done) override; + void pause(::google::protobuf::RpcController *controller, const ::firebolt::rialto::WebAudioPauseRequest *request, + ::firebolt::rialto::WebAudioPauseResponse *response, ::google::protobuf::Closure *done) override; + void setEos(::google::protobuf::RpcController *controller, const ::firebolt::rialto::WebAudioSetEosRequest *request, + ::firebolt::rialto::WebAudioSetEosResponse *response, ::google::protobuf::Closure *done) override; + void getBufferAvailable(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioGetBufferAvailableRequest *request, + ::firebolt::rialto::WebAudioGetBufferAvailableResponse *response, + ::google::protobuf::Closure *done) override; + void getBufferDelay(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioGetBufferDelayRequest *request, + ::firebolt::rialto::WebAudioGetBufferDelayResponse *response, + ::google::protobuf::Closure *done) override; + void writeBuffer(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioWriteBufferRequest *request, + ::firebolt::rialto::WebAudioWriteBufferResponse *response, + ::google::protobuf::Closure *done) override; + void getDeviceInfo(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioGetDeviceInfoRequest *request, + ::firebolt::rialto::WebAudioGetDeviceInfoResponse *response, + ::google::protobuf::Closure *done) override; + void setVolume(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioSetVolumeRequest *request, + ::firebolt::rialto::WebAudioSetVolumeResponse *response, ::google::protobuf::Closure *done) override; + void getVolume(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioGetVolumeRequest *request, + ::firebolt::rialto::WebAudioGetVolumeResponse *response, ::google::protobuf::Closure *done) override; + +private: + service::IWebAudioPlayerService &m_webAudioPlayerService; + std::map, std::set> m_clientWebAudioPlayerHandles; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/interface/IApplicationManagementServer.h b/middleware/rialto-client/media/server/ipc/interface/IApplicationManagementServer.h new file mode 100644 index 000000000..781bed0e9 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/interface/IApplicationManagementServer.h @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_APPLICATION_MANAGEMENT_SERVER_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_APPLICATION_MANAGEMENT_SERVER_H_ + +#include "SessionServerCommon.h" +#include + +namespace firebolt::rialto::server::ipc +{ +class IApplicationManagementServer +{ +public: + IApplicationManagementServer() = default; + virtual ~IApplicationManagementServer() = default; + + IApplicationManagementServer(const IApplicationManagementServer &) = delete; + IApplicationManagementServer(IApplicationManagementServer &&) = delete; + IApplicationManagementServer &operator=(const IApplicationManagementServer &) = delete; + IApplicationManagementServer &operator=(IApplicationManagementServer &&) = delete; + + virtual bool initialize(int socket) = 0; + virtual bool sendStateChangedEvent(const common::SessionServerState &state) = 0; + virtual void start() = 0; + virtual void stop() = 0; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_APPLICATION_MANAGEMENT_SERVER_H_ diff --git a/middleware/rialto-client/media/server/ipc/interface/IIpcFactory.h b/middleware/rialto-client/media/server/ipc/interface/IIpcFactory.h new file mode 100644 index 000000000..6473c051e --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/interface/IIpcFactory.h @@ -0,0 +1,47 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_IPC_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_IPC_FACTORY_H_ + +#include "IApplicationManagementServer.h" +#include "ICdmService.h" +#include "IControlService.h" +#include "IPlaybackService.h" +#include "ISessionManagementServer.h" +#include "ISessionServerManager.h" +#include + +namespace firebolt::rialto::server::ipc +{ +class IIpcFactory +{ +public: + IIpcFactory() = default; + virtual ~IIpcFactory() = default; + + virtual std::unique_ptr + createApplicationManagementServer(service::ISessionServerManager &sessionServerManager) const = 0; + virtual std::unique_ptr + createSessionManagementServer(service::IPlaybackService &playbackService, service::ICdmService &cdmService, + service::IControlService &controlService) const = 0; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/ipc/interface/ISessionManagementServer.h b/middleware/rialto-client/media/server/ipc/interface/ISessionManagementServer.h new file mode 100644 index 000000000..0f7b35334 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/interface/ISessionManagementServer.h @@ -0,0 +1,50 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_SESSION_MANAGEMENT_SERVER_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_I_SESSION_MANAGEMENT_SERVER_H_ + +#include "RialtoServerLogging.h" +#include +#include + +namespace firebolt::rialto::server::ipc +{ +class ISessionManagementServer +{ +public: + ISessionManagementServer() = default; + virtual ~ISessionManagementServer() = default; + + ISessionManagementServer(const ISessionManagementServer &) = delete; + ISessionManagementServer(ISessionManagementServer &&) = delete; + ISessionManagementServer &operator=(const ISessionManagementServer &) = delete; + ISessionManagementServer &operator=(ISessionManagementServer &&) = delete; + + virtual bool initialize(const std::string &socketName, unsigned int socketPermissions, + const std::string &socketOwner, const std::string &socketGroup) = 0; + virtual bool initialize(int32_t socketFd) = 0; + virtual void start() = 0; + virtual void stop() = 0; + virtual void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, + RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) = 0; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_I_SESSION_MANAGEMENT_SERVER_H_ diff --git a/middleware/rialto-client/media/server/ipc/interface/IpcFactory.h b/middleware/rialto-client/media/server/ipc/interface/IpcFactory.h new file mode 100644 index 000000000..68beb84f5 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/interface/IpcFactory.h @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_IPC_IPC_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_IPC_IPC_FACTORY_H_ + +#include "IIpcFactory.h" +#include + +namespace firebolt::rialto::server::ipc +{ +class IpcFactory : public IIpcFactory +{ +public: + IpcFactory() = default; + ~IpcFactory() override = default; + IpcFactory(const IpcFactory &) = delete; + IpcFactory(IpcFactory &&) = delete; + IpcFactory &operator=(const IpcFactory &) = delete; + IpcFactory &operator=(IpcFactory &&) = delete; + + std::unique_ptr + createApplicationManagementServer(service::ISessionServerManager &sessionServerManager) const override; + std::unique_ptr + createSessionManagementServer(service::IPlaybackService &playbackService, service::ICdmService &cdmService, + service::IControlService &controlService) const override; +}; +} // namespace firebolt::rialto::server::ipc + +#endif // FIREBOLT_RIALTO_SERVER_IPC_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/ipc/proto/controlmodule.proto b/middleware/rialto-client/media/server/ipc/proto/controlmodule.proto new file mode 120000 index 000000000..6e95f531f --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/proto/controlmodule.proto @@ -0,0 +1 @@ +../../../../proto/controlmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/mediakeyscapabilitiesmodule.proto b/middleware/rialto-client/media/server/ipc/proto/mediakeyscapabilitiesmodule.proto new file mode 120000 index 000000000..e508c1392 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/proto/mediakeyscapabilitiesmodule.proto @@ -0,0 +1 @@ +../../../../proto/mediakeyscapabilitiesmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/mediakeysmodule.proto b/middleware/rialto-client/media/server/ipc/proto/mediakeysmodule.proto new file mode 120000 index 000000000..98b44b620 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/proto/mediakeysmodule.proto @@ -0,0 +1 @@ +../../../../proto/mediakeysmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/mediapipelinecapabilitiesmodule.proto b/middleware/rialto-client/media/server/ipc/proto/mediapipelinecapabilitiesmodule.proto new file mode 120000 index 000000000..7af44cdd7 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/proto/mediapipelinecapabilitiesmodule.proto @@ -0,0 +1 @@ +../../../../proto/mediapipelinecapabilitiesmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/mediapipelinemodule.proto b/middleware/rialto-client/media/server/ipc/proto/mediapipelinemodule.proto new file mode 120000 index 000000000..6f1b4bdbe --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/proto/mediapipelinemodule.proto @@ -0,0 +1 @@ +../../../../proto/mediapipelinemodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/rialtocommon.proto b/middleware/rialto-client/media/server/ipc/proto/rialtocommon.proto new file mode 120000 index 000000000..2c6e7a2bb --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/proto/rialtocommon.proto @@ -0,0 +1 @@ +../../../../proto/rialtocommon.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/servermanagermodule.proto b/middleware/rialto-client/media/server/ipc/proto/servermanagermodule.proto new file mode 120000 index 000000000..bc952e7b5 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/proto/servermanagermodule.proto @@ -0,0 +1 @@ +../../../../proto/servermanagermodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/webaudioplayermodule.proto b/middleware/rialto-client/media/server/ipc/proto/webaudioplayermodule.proto new file mode 120000 index 000000000..4c84680f4 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/proto/webaudioplayermodule.proto @@ -0,0 +1 @@ +../../../../proto/webaudioplayermodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/source/AckSender.cpp b/middleware/rialto-client/media/server/ipc/source/AckSender.cpp new file mode 100644 index 000000000..003fb83f1 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/AckSender.cpp @@ -0,0 +1,38 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "AckSender.h" +#include "RialtoServerLogging.h" +#include "servermanagermodule.pb.h" + +namespace firebolt::rialto::server::ipc +{ +AckSender::AckSender(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) : m_ipcClient{ipcClient} {} + +void AckSender::send(int id, bool success) const +{ + RIALTO_SERVER_LOG_DEBUG("Sending AckEvent with id %d", id); + + auto event = std::make_shared<::rialto::AckEvent>(); + event->set_id(id); + event->set_success(success); + + m_ipcClient->sendEvent(event); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/ApplicationManagementServer.cpp b/middleware/rialto-client/media/server/ipc/source/ApplicationManagementServer.cpp new file mode 100644 index 000000000..8ca47c197 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/ApplicationManagementServer.cpp @@ -0,0 +1,122 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ApplicationManagementServer.h" +#include "IServerManagerModuleServiceFactory.h" +#include "RialtoServerLogging.h" +#include + +namespace +{ +rialto::SessionServerState convertSessionServerState(const firebolt::rialto::common::SessionServerState &state) +{ + switch (state) + { + case firebolt::rialto::common::SessionServerState::UNINITIALIZED: + return rialto::SessionServerState::UNINITIALIZED; + case firebolt::rialto::common::SessionServerState::INACTIVE: + return rialto::SessionServerState::INACTIVE; + case firebolt::rialto::common::SessionServerState::ACTIVE: + return rialto::SessionServerState::ACTIVE; + case firebolt::rialto::common::SessionServerState::NOT_RUNNING: + return rialto::SessionServerState::NOT_RUNNING; + case firebolt::rialto::common::SessionServerState::ERROR: + return rialto::SessionServerState::ERROR; + } + return rialto::SessionServerState::ERROR; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +ApplicationManagementServer::ApplicationManagementServer( + const std::shared_ptr &serverFactory, + const std::shared_ptr &serverManagerModuleFactory, + service::ISessionServerManager &sessionServerManager) + : m_ipcServer{serverFactory->create()}, m_service{serverManagerModuleFactory->create(sessionServerManager)} +{ +} + +ApplicationManagementServer::~ApplicationManagementServer() +{ + stop(); + if (m_ipcServerThread.joinable()) + { + m_ipcServerThread.join(); + } +} + +bool ApplicationManagementServer::initialize(int socket) +{ + RIALTO_SERVER_LOG_INFO("Initializing ApplicationManagementServer, socket: %d", socket); + if (!m_ipcServer) + { + RIALTO_SERVER_LOG_ERROR("Failed to initialize ApplicationManagementServer - Ipc server instance is NULL"); + return false; + } + + m_ipcClient = m_ipcServer->addClient(socket, std::bind(&ApplicationManagementServer::onClientDisconnected, this, + std::placeholders::_1)); + if (!m_ipcClient) + { + RIALTO_SERVER_LOG_ERROR("Failed to initialize ApplicationManagementServer - Client is NULL"); + return false; + } + m_ipcClient->exportService(m_service); + RIALTO_SERVER_LOG_MIL("ApplicationManagementServer initialized"); + return true; +} + +bool ApplicationManagementServer::sendStateChangedEvent(const common::SessionServerState &state) +{ + if (!m_ipcClient->isConnected()) + { + return false; + } + auto stateChangedEvent = std::make_shared<::rialto::StateChangedEvent>(); + stateChangedEvent->set_sessionserverstate(convertSessionServerState(state)); + m_ipcClient->sendEvent(stateChangedEvent); + return true; +} + +void ApplicationManagementServer::start() +{ + m_ipcServerThread = std::thread( + [this]() + { + while (m_ipcServer->process() && m_ipcClient && m_ipcClient->isConnected()) + { + m_ipcServer->wait(-1); + } + }); +} + +void ApplicationManagementServer::stop() +{ + if (m_ipcClient && m_ipcClient->isConnected()) + { + m_ipcClient->disconnect(); + } +} + +void ApplicationManagementServer::onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) +{ + RIALTO_SERVER_LOG_WARN("Rialto Server Manager disconnected"); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/ControlClientServerInternal.cpp b/middleware/rialto-client/media/server/ipc/source/ControlClientServerInternal.cpp new file mode 100644 index 000000000..c7d9741a5 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/ControlClientServerInternal.cpp @@ -0,0 +1,73 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ControlClientServerInternal.h" +#include "RialtoServerLogging.h" +#include "controlmodule.pb.h" +#include + +namespace +{ +firebolt::rialto::ApplicationStateChangeEvent_ApplicationState +convertApplicationState(const firebolt::rialto::ApplicationState &state) +{ + switch (state) + { + case firebolt::rialto::ApplicationState::RUNNING: + return firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_RUNNING; + case firebolt::rialto::ApplicationState::INACTIVE: + return firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_INACTIVE; + case firebolt::rialto::ApplicationState::UNKNOWN: + break; + // do nothing + } + return firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_UNKNOWN; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +ControlClientServerInternal::ControlClientServerInternal(int controlId, + const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) + : m_kControlId{controlId}, m_ipcClient{ipcClient} +{ +} + +void ControlClientServerInternal::notifyApplicationState(ApplicationState state) +{ + RIALTO_SERVER_LOG_DEBUG("Sending ApplicationStateChangeEvent"); + + auto event = std::make_shared(); + event->set_control_handle(m_kControlId); + event->set_application_state(convertApplicationState(state)); + + m_ipcClient->sendEvent(event); +} + +void ControlClientServerInternal::ping(uint32_t id) +{ + RIALTO_SERVER_LOG_DEBUG("Sending PingEvent with id: %d", id); + + auto event = std::make_shared(); + event->set_control_handle(m_kControlId); + event->set_id(id); + + m_ipcClient->sendEvent(event); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/ControlModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/ControlModuleService.cpp new file mode 100644 index 000000000..40f930c40 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/ControlModuleService.cpp @@ -0,0 +1,192 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ControlModuleService.h" +#include "ControlClientServerInternal.h" +#include "IPlaybackService.h" +#include "RialtoServerLogging.h" +#include "SchemaVersion.h" +#include +#include +#include + +namespace +{ +int generateControlId() +{ + static int id{0}; + return id++; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +std::shared_ptr IControlModuleServiceFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the rialto control module service factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr ControlModuleServiceFactory::create(service::IPlaybackService &playbackService, + service::IControlService &controlService) const +{ + std::shared_ptr controlModule; + + try + { + controlModule = std::make_shared(playbackService, controlService); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the rialto control module service, reason: %s", e.what()); + } + + return controlModule; +} + +ControlModuleService::ControlModuleService(service::IPlaybackService &playbackService, + service::IControlService &controlService) + : m_playbackService{playbackService}, m_controlService{controlService} +{ +} + +ControlModuleService::~ControlModuleService() +{ + for (const auto &controlIds : m_controlIds) + { + for (int id : controlIds.second) + { + m_controlService.removeControl(id); + } + } +} + +void ControlModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client Connected!"); + m_controlIds.emplace(ipcClient, std::set()); + ipcClient->exportService(shared_from_this()); +} + +void ControlModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client disconnected!"); + auto controlIdsIter = m_controlIds.find(ipcClient); + if (m_controlIds.end() != controlIdsIter) + { + for (int id : controlIdsIter->second) + { + m_controlService.removeControl(id); + } + m_controlIds.erase(controlIdsIter); + } +} + +void ControlModuleService::getSharedMemory(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetSharedMemoryRequest *request, + ::firebolt::rialto::GetSharedMemoryResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + int32_t fd; + uint32_t size; + if (!m_playbackService.getSharedMemory(fd, size)) + { + RIALTO_SERVER_LOG_ERROR("getSharedMemory failed"); + controller->SetFailed("Operation failed"); + done->Run(); + return; + } + response->set_fd(fd); + response->set_size(size); + done->Run(); +} + +void ControlModuleService::registerClient(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::RegisterClientRequest *request, + ::firebolt::rialto::RegisterClientResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + const auto kCurrentSchemaVersion{common::getCurrentSchemaVersion()}; + if (request->has_client_schema_version()) + { + const firebolt::rialto::common::SchemaVersion kClientSchemaVersion{request->client_schema_version().major(), + request->client_schema_version().minor(), + request->client_schema_version().patch()}; + RIALTO_SERVER_LOG_DEBUG("Server schema version: %s, client schema version: %s", + kCurrentSchemaVersion.str().c_str(), kClientSchemaVersion.str().c_str()); + if (!kCurrentSchemaVersion.isCompatible(kClientSchemaVersion)) + { + RIALTO_SERVER_LOG_ERROR("Server and client schema versions not compatible"); + controller->SetFailed("Server and client schema versions not compatible"); + done->Run(); + return; + } + } + else + { + RIALTO_SERVER_LOG_WARN("Client schema version not present in RegisterClientRequest message"); + } + const int kControlId{generateControlId()}; + auto ipcClient = ipcController->getClient(); + auto controlClient{std::make_shared(kControlId, ipcClient)}; + m_controlService.addControl(kControlId, controlClient); + m_controlIds[ipcClient].insert(kControlId); + response->set_control_handle(kControlId); + response->mutable_server_schema_version()->set_major(kCurrentSchemaVersion.major()); + response->mutable_server_schema_version()->set_minor(kCurrentSchemaVersion.minor()); + response->mutable_server_schema_version()->set_patch(kCurrentSchemaVersion.patch()); + done->Run(); +} + +void ControlModuleService::ack(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::AckRequest *request, ::firebolt::rialto::AckResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_controlService.ack(request->control_handle(), request->id())) + { + RIALTO_SERVER_LOG_ERROR("ack failed"); + controller->SetFailed("Operation failed"); + done->Run(); + return; + } + done->Run(); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/IpcFactory.cpp b/middleware/rialto-client/media/server/ipc/source/IpcFactory.cpp new file mode 100644 index 000000000..0849fe8dd --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/IpcFactory.cpp @@ -0,0 +1,57 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "IpcFactory.h" +#include "ApplicationManagementServer.h" +#include "IControlModuleService.h" +#include "IIpcServer.h" +#include "IMediaKeysCapabilitiesModuleService.h" +#include "IMediaKeysModuleService.h" +#include "IMediaPipelineCapabilitiesModuleService.h" +#include "IMediaPipelineModuleService.h" +#include "IServerManagerModuleServiceFactory.h" +#include "IWebAudioPlayerModuleService.h" +#include "SessionManagementServer.h" + +namespace firebolt::rialto::server::ipc +{ +std::unique_ptr +IpcFactory::createApplicationManagementServer(service::ISessionServerManager &sessionServerManager) const +{ + return std::make_unique< + ApplicationManagementServer>(firebolt::rialto::ipc::IServerFactory::createFactory(), + firebolt::rialto::server::ipc::IServerManagerModuleServiceFactory::createFactory(), + sessionServerManager); +} + +std::unique_ptr +IpcFactory::createSessionManagementServer(service::IPlaybackService &playbackService, service::ICdmService &cdmService, + service::IControlService &controlService) const +{ + return std::make_unique< + SessionManagementServer>(firebolt::rialto::ipc::IServerFactory::createFactory(), + firebolt::rialto::server::ipc::IMediaPipelineModuleServiceFactory::createFactory(), + firebolt::rialto::server::ipc::IMediaPipelineCapabilitiesModuleServiceFactory::createFactory(), + firebolt::rialto::server::ipc::IMediaKeysModuleServiceFactory::createFactory(), + firebolt::rialto::server::ipc::IMediaKeysCapabilitiesModuleServiceFactory::createFactory(), + firebolt::rialto::server::ipc::IWebAudioPlayerModuleServiceFactory::createFactory(), + firebolt::rialto::server::ipc::IControlModuleServiceFactory::createFactory(), + playbackService, cdmService, controlService); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaKeysCapabilitiesModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/MediaKeysCapabilitiesModuleService.cpp new file mode 100644 index 000000000..23eb482aa --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/MediaKeysCapabilitiesModuleService.cpp @@ -0,0 +1,171 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "ICdmService.h" +#include "MediaKeysCapabilitiesModuleService.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::ipc +{ +std::shared_ptr IMediaKeysCapabilitiesModuleServiceFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media keys capabilities module service factory, reason: %s", + e.what()); + } + + return factory; +} + +std::shared_ptr +MediaKeysCapabilitiesModuleServiceFactory::create(service::ICdmService &cdmService) const +{ + std::shared_ptr mediaKeysCapabilitiesModule; + + try + { + mediaKeysCapabilitiesModule = std::make_shared(cdmService); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media keys capabilities module service, reason: %s", e.what()); + } + + return mediaKeysCapabilitiesModule; +} + +MediaKeysCapabilitiesModuleService::MediaKeysCapabilitiesModuleService(service::ICdmService &cdmService) + : m_cdmService{cdmService} +{ +} + +MediaKeysCapabilitiesModuleService::~MediaKeysCapabilitiesModuleService() {} + +void MediaKeysCapabilitiesModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client Connected!"); + ipcClient->exportService(shared_from_this()); +} + +void MediaKeysCapabilitiesModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client disconnected!"); +} + +void MediaKeysCapabilitiesModuleService::getSupportedKeySystems( + ::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSupportedKeySystemsRequest *request, + ::firebolt::rialto::GetSupportedKeySystemsResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + std::vector keySystems = m_cdmService.getSupportedKeySystems(); + + for (auto it = keySystems.begin(); it != keySystems.end(); it++) + { + response->add_key_systems(*it); + } + done->Run(); +} + +void MediaKeysCapabilitiesModuleService::supportsKeySystem(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SupportsKeySystemRequest *request, + ::firebolt::rialto::SupportsKeySystemResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + response->set_is_supported(m_cdmService.supportsKeySystem(request->key_system())); + done->Run(); +} + +void MediaKeysCapabilitiesModuleService::getSupportedKeySystemVersion( + ::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSupportedKeySystemVersionRequest *request, + ::firebolt::rialto::GetSupportedKeySystemVersionResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + std::string version; + bool status = m_cdmService.getSupportedKeySystemVersion(request->key_system(), version); + if (status) + { + response->set_version(version); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to get the key system version"); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaKeysCapabilitiesModuleService::isServerCertificateSupported( + ::google::protobuf::RpcController *controller, const ::firebolt::rialto::IsServerCertificateSupportedRequest *request, + ::firebolt::rialto::IsServerCertificateSupportedResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + response->set_is_supported(m_cdmService.isServerCertificateSupported(request->key_system())); + done->Run(); +} + +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaKeysClient.cpp b/middleware/rialto-client/media/server/ipc/source/MediaKeysClient.cpp new file mode 100644 index 000000000..d45f906fa --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/MediaKeysClient.cpp @@ -0,0 +1,120 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaKeysClient.h" +#include "IIpcServer.h" +#include "RialtoServerLogging.h" +#include "mediakeysmodule.pb.h" + +namespace +{ +firebolt::rialto::KeyStatusesChangedEvent_KeyStatus convertKeyStatus(const firebolt::rialto::KeyStatus &keyStatus) +{ + switch (keyStatus) + { + case firebolt::rialto::KeyStatus::USABLE: + { + return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_USABLE; + } + case firebolt::rialto::KeyStatus::EXPIRED: + { + return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_EXPIRED; + } + case firebolt::rialto::KeyStatus::OUTPUT_RESTRICTED: + { + return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_OUTPUT_RESTRICTED; + } + case firebolt::rialto::KeyStatus::PENDING: + { + return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_PENDING; + } + case firebolt::rialto::KeyStatus::INTERNAL_ERROR: + { + return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_INTERNAL_ERROR; + } + case firebolt::rialto::KeyStatus::RELEASED: + { + return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_RELEASED; + } + } + return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_INTERNAL_ERROR; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +MediaKeysClient::MediaKeysClient(int mediaKeysHandle, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) + : m_mediaKeysHandle{mediaKeysHandle}, m_ipcClient{ipcClient} +{ +} + +MediaKeysClient::~MediaKeysClient() {} + +void MediaKeysClient::onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, + const std::string &url) +{ + RIALTO_SERVER_LOG_DEBUG("Sending LicenseRequestEvent"); + + auto event = std::make_shared(); + for (auto it = licenseRequestMessage.begin(); it != licenseRequestMessage.end(); it++) + { + event->add_license_request_message(*it); + } + event->set_media_keys_handle(m_mediaKeysHandle); + event->set_key_session_id(keySessionId); + event->set_url(url); + + m_ipcClient->sendEvent(event); +} + +void MediaKeysClient::onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) +{ + RIALTO_SERVER_LOG_DEBUG("Sending LicenseRenewalEvent"); + + auto event = std::make_shared(); + for (auto it = licenseRenewalMessage.begin(); it != licenseRenewalMessage.end(); it++) + { + event->add_license_renewal_message(*it); + } + event->set_media_keys_handle(m_mediaKeysHandle); + event->set_key_session_id(keySessionId); + + m_ipcClient->sendEvent(event); +} + +void MediaKeysClient::onKeyStatusesChanged(int32_t keySessionId, const KeyStatusVector &keyStatuses) +{ + RIALTO_SERVER_LOG_DEBUG("Sending KeyStatusesChangedEvent"); + + auto event = std::make_shared(); + for (auto it = keyStatuses.begin(); it != keyStatuses.end(); it++) + { + ::firebolt::rialto::KeyStatusesChangedEvent_KeyStatusPair *keyStatusPair = event->add_key_statuses(); + for (auto it2 = it->first.begin(); it2 != it->first.end(); it2++) + { + keyStatusPair->add_key_id(*it2); + } + keyStatusPair->set_key_status(convertKeyStatus(it->second)); + } + event->set_media_keys_handle(m_mediaKeysHandle); + event->set_key_session_id(keySessionId); + + m_ipcClient->sendEvent(event); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaKeysModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/MediaKeysModuleService.cpp new file mode 100644 index 000000000..4ef3b6aab --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/MediaKeysModuleService.cpp @@ -0,0 +1,498 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaKeysModuleService.h" +#include "ICdmService.h" +#include "MediaKeysClient.h" +#include "RialtoServerLogging.h" +#include +#include +#include + +namespace +{ +int generateHandle() +{ + static int mediaKeysHandle{0}; + return mediaKeysHandle++; +} + +firebolt::rialto::ProtoMediaKeyErrorStatus +convertMediaKeyErrorStatus(const firebolt::rialto::MediaKeyErrorStatus &errorStatus) +{ + switch (errorStatus) + { + case firebolt::rialto::MediaKeyErrorStatus::OK: + { + return firebolt::rialto::ProtoMediaKeyErrorStatus::OK; + } + case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: + { + return firebolt::rialto::ProtoMediaKeyErrorStatus::BAD_SESSION_ID; + } + case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: + { + return firebolt::rialto::ProtoMediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED; + } + case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: + { + return firebolt::rialto::ProtoMediaKeyErrorStatus::BUFFER_TOO_SMALL; + } + case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: + { + return firebolt::rialto::ProtoMediaKeyErrorStatus::NOT_SUPPORTED; + } + case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: + { + return firebolt::rialto::ProtoMediaKeyErrorStatus::INVALID_STATE; + } + case firebolt::rialto::MediaKeyErrorStatus::FAIL: + { + return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; + } + } + return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; +} +firebolt::rialto::KeySessionType +convertKeySessionType(const firebolt::rialto::CreateKeySessionRequest_KeySessionType &protoKeySessionType) +{ + switch (protoKeySessionType) + { + case firebolt::rialto::CreateKeySessionRequest_KeySessionType::CreateKeySessionRequest_KeySessionType_TEMPORARY: + return firebolt::rialto::KeySessionType::TEMPORARY; + case firebolt::rialto::CreateKeySessionRequest_KeySessionType::CreateKeySessionRequest_KeySessionType_PERSISTENT_LICENCE: + return firebolt::rialto::KeySessionType::PERSISTENT_LICENCE; + case firebolt::rialto::CreateKeySessionRequest_KeySessionType::CreateKeySessionRequest_KeySessionType_PERSISTENT_RELEASE_MESSAGE: + return firebolt::rialto::KeySessionType::PERSISTENT_RELEASE_MESSAGE; + default: + return firebolt::rialto::KeySessionType::UNKNOWN; + } +} +firebolt::rialto::InitDataType covertInitDataType(firebolt::rialto::GenerateRequestRequest_InitDataType protoInitDataType) +{ + switch (protoInitDataType) + { + case firebolt::rialto::GenerateRequestRequest_InitDataType::GenerateRequestRequest_InitDataType_CENC: + return firebolt::rialto::InitDataType::CENC; + case firebolt::rialto::GenerateRequestRequest_InitDataType::GenerateRequestRequest_InitDataType_KEY_IDS: + return firebolt::rialto::InitDataType::KEY_IDS; + case firebolt::rialto::GenerateRequestRequest_InitDataType::GenerateRequestRequest_InitDataType_WEBM: + return firebolt::rialto::InitDataType::WEBM; + case firebolt::rialto::GenerateRequestRequest_InitDataType::GenerateRequestRequest_InitDataType_DRMHEADER: + return firebolt::rialto::InitDataType::DRMHEADER; + default: + return firebolt::rialto::InitDataType::UNKNOWN; + } +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +std::shared_ptr IMediaKeysModuleServiceFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media keys module service factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr MediaKeysModuleServiceFactory::create(service::ICdmService &cdmService) const +{ + std::shared_ptr mediaKeysModule; + + try + { + mediaKeysModule = std::make_shared(cdmService); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media keys module service, reason: %s", e.what()); + } + + return mediaKeysModule; +} + +MediaKeysModuleService::MediaKeysModuleService(service::ICdmService &cdmService) : m_cdmService{cdmService} {} + +MediaKeysModuleService::~MediaKeysModuleService() {} + +void MediaKeysModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client Connected!"); + { + m_clientMediaKeysHandles.emplace(ipcClient, std::set()); + } + ipcClient->exportService(shared_from_this()); +} + +void MediaKeysModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client disconnected!"); + std::set mediaKeysHandles; + { + auto handleIter = m_clientMediaKeysHandles.find(ipcClient); + if (handleIter == m_clientMediaKeysHandles.end()) + { + RIALTO_SERVER_LOG_ERROR("unknown client disconnected"); + return; + } + mediaKeysHandles = handleIter->second; // copy to avoid deadlock + m_clientMediaKeysHandles.erase(handleIter); + } + for (const auto &mediaKeysHandle : mediaKeysHandles) + { + m_cdmService.destroyMediaKeys(mediaKeysHandle); + } +} + +void MediaKeysModuleService::createMediaKeys(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CreateMediaKeysRequest *request, + ::firebolt::rialto::CreateMediaKeysResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + int mediaKeysHandle = generateHandle(); + bool mediaKeysCreated = m_cdmService.createMediaKeys(mediaKeysHandle, request->key_system()); + if (mediaKeysCreated) + { + // Assume that IPC library works well and client is present + m_clientMediaKeysHandles[ipcController->getClient()].insert(mediaKeysHandle); + response->set_media_keys_handle(mediaKeysHandle); + } + else + { + RIALTO_SERVER_LOG_ERROR("Create media keys failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaKeysModuleService::destroyMediaKeys(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DestroyMediaKeysRequest *request, + ::firebolt::rialto::DestroyMediaKeysResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + if (!m_cdmService.destroyMediaKeys(request->media_keys_handle())) + { + RIALTO_SERVER_LOG_ERROR("Destroy session failed"); + controller->SetFailed("Operation failed"); + done->Run(); + return; + } + auto handleIter = m_clientMediaKeysHandles.find(ipcController->getClient()); + if (handleIter != m_clientMediaKeysHandles.end()) + { + handleIter->second.erase(request->media_keys_handle()); + } + done->Run(); +} + +void MediaKeysModuleService::containsKey(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::ContainsKeyRequest *request, + ::firebolt::rialto::ContainsKeyResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result = m_cdmService.containsKey(request->media_keys_handle(), request->key_session_id(), + std::vector{request->key_id().begin(), request->key_id().end()}); + response->set_contains_key(result); + done->Run(); +} + +void MediaKeysModuleService::createKeySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CreateKeySessionRequest *request, + ::firebolt::rialto::CreateKeySessionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + int32_t keySessionId; + MediaKeyErrorStatus status = + m_cdmService.createKeySession(request->media_keys_handle(), convertKeySessionType(request->session_type()), + std::make_shared(request->media_keys_handle(), + ipcController->getClient()), + request->is_ldl(), keySessionId); + if (MediaKeyErrorStatus::OK == status) + { + response->set_key_session_id(keySessionId); + } + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::generateRequest(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GenerateRequestRequest *request, + ::firebolt::rialto::GenerateRequestResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.generateRequest(request->media_keys_handle(), request->key_session_id(), + covertInitDataType(request->init_data_type()), + std::vector{request->init_data().begin(), + request->init_data().end()}); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::loadSession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::LoadSessionRequest *request, + ::firebolt::rialto::LoadSessionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.loadSession(request->media_keys_handle(), request->key_session_id()); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::updateSession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::UpdateSessionRequest *request, + ::firebolt::rialto::UpdateSessionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.updateSession(request->media_keys_handle(), request->key_session_id(), + std::vector{request->response_data().begin(), + request->response_data().end()}); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::setDrmHeader(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetDrmHeaderRequest *request, + ::firebolt::rialto::SetDrmHeaderResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.setDrmHeader(request->media_keys_handle(), request->key_session_id(), + std::vector{request->request_data().begin(), + request->request_data().end()}); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::closeKeySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CloseKeySessionRequest *request, + ::firebolt::rialto::CloseKeySessionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.closeKeySession(request->media_keys_handle(), request->key_session_id()); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::removeKeySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::RemoveKeySessionRequest *request, + ::firebolt::rialto::RemoveKeySessionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.removeKeySession(request->media_keys_handle(), request->key_session_id()); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::deleteDrmStore(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DeleteDrmStoreRequest *request, + ::firebolt::rialto::DeleteDrmStoreResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.deleteDrmStore(request->media_keys_handle()); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::deleteKeyStore(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DeleteKeyStoreRequest *request, + ::firebolt::rialto::DeleteKeyStoreResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.deleteKeyStore(request->media_keys_handle()); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::getDrmStoreHash(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetDrmStoreHashRequest *request, + ::firebolt::rialto::GetDrmStoreHashResponse *response, + ::google::protobuf::Closure *done) +{ + std::vector drmStoreHash; + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.getDrmStoreHash(request->media_keys_handle(), drmStoreHash); + response->set_error_status(convertMediaKeyErrorStatus(status)); + for (const auto &item : drmStoreHash) + { + response->add_drm_store_hash(item); + } + done->Run(); +} + +void MediaKeysModuleService::getKeyStoreHash(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetKeyStoreHashRequest *request, + ::firebolt::rialto::GetKeyStoreHashResponse *response, + ::google::protobuf::Closure *done) +{ + std::vector keyStoreHash; + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.getKeyStoreHash(request->media_keys_handle(), keyStoreHash); + response->set_error_status(convertMediaKeyErrorStatus(status)); + for (const auto &item : keyStoreHash) + { + response->add_key_store_hash(item); + } + done->Run(); +} + +void MediaKeysModuleService::getLdlSessionsLimit(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetLdlSessionsLimitRequest *request, + ::firebolt::rialto::GetLdlSessionsLimitResponse *response, + ::google::protobuf::Closure *done) +{ + uint32_t ldlLimit{0}; + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.getLdlSessionsLimit(request->media_keys_handle(), ldlLimit); + response->set_error_status(convertMediaKeyErrorStatus(status)); + response->set_ldl_limit(ldlLimit); + done->Run(); +} + +void MediaKeysModuleService::getLastDrmError(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetLastDrmErrorRequest *request, + ::firebolt::rialto::GetLastDrmErrorResponse *response, + ::google::protobuf::Closure *done) +{ + uint32_t errorCode{0}; + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = + m_cdmService.getLastDrmError(request->media_keys_handle(), request->key_session_id(), errorCode); + response->set_error_status(convertMediaKeyErrorStatus(status)); + response->set_error_code(errorCode); + done->Run(); +} + +void MediaKeysModuleService::getDrmTime(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetDrmTimeRequest *request, + ::firebolt::rialto::GetDrmTimeResponse *response, + ::google::protobuf::Closure *done) +{ + uint64_t drmTime{0}; + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.getDrmTime(request->media_keys_handle(), drmTime); + response->set_error_status(convertMediaKeyErrorStatus(status)); + response->set_drm_time(drmTime); + done->Run(); +} + +void MediaKeysModuleService::getCdmKeySessionId(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetCdmKeySessionIdRequest *request, + ::firebolt::rialto::GetCdmKeySessionIdResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + std::string cdmKeySessionId; + MediaKeyErrorStatus status = + m_cdmService.getCdmKeySessionId(request->media_keys_handle(), request->key_session_id(), cdmKeySessionId); + response->set_error_status(convertMediaKeyErrorStatus(status)); + response->set_cdm_key_session_id(cdmKeySessionId); + done->Run(); +} + +void MediaKeysModuleService::releaseKeySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::ReleaseKeySessionRequest *request, + ::firebolt::rialto::ReleaseKeySessionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.releaseKeySession(request->media_keys_handle(), request->key_session_id()); + response->set_error_status(convertMediaKeyErrorStatus(status)); + done->Run(); +} + +void MediaKeysModuleService::getMetricSystemData(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetMetricSystemDataRequest *request, + ::firebolt::rialto::GetMetricSystemDataResponse *response, + ::google::protobuf::Closure *done) +{ + std::vector buffer; + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status = m_cdmService.getMetricSystemData(request->media_keys_handle(), buffer); + response->set_error_status(convertMediaKeyErrorStatus(status)); + for (const auto &buf : buffer) + { + response->add_buffer(buf); + } + done->Run(); +} + +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp new file mode 100644 index 000000000..dc73b0ee6 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp @@ -0,0 +1,183 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaPipelineCapabilitiesModuleService.h" +#include "RialtoCommonModule.h" +#include "RialtoServerLogging.h" +#include + +namespace firebolt::rialto::server::ipc +{ +std::shared_ptr +IMediaPipelineCapabilitiesModuleServiceFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media player capabilities module service factory, reason: %s", + e.what()); + } + + return factory; +} + +std::shared_ptr +MediaPipelineCapabilitiesModuleServiceFactory::create(service::IMediaPipelineService &mediaPipelineService) const +{ + std::shared_ptr mediaPipelineCapabilitiesModule; + + try + { + mediaPipelineCapabilitiesModule = std::make_shared(mediaPipelineService); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media player module service, reason: %s", e.what()); + } + + return mediaPipelineCapabilitiesModule; +} + +MediaPipelineCapabilitiesModuleService::MediaPipelineCapabilitiesModuleService( + service::IMediaPipelineService &mediaPipelineService) + : m_mediaPipelineService{mediaPipelineService} +{ +} + +MediaPipelineCapabilitiesModuleService::~MediaPipelineCapabilitiesModuleService() {} + +void MediaPipelineCapabilitiesModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client Connected!"); + ipcClient->exportService(shared_from_this()); +} + +void MediaPipelineCapabilitiesModuleService::clientDisconnected( + const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client disconnected!"); +} + +void MediaPipelineCapabilitiesModuleService::getSupportedMimeTypes( + ::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSupportedMimeTypesRequest *request, + ::firebolt::rialto::GetSupportedMimeTypesResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + firebolt::rialto::MediaSourceType sourceType = convertMediaSourceType(request->media_type()); + std::vector supportedMimeTypes = m_mediaPipelineService.getSupportedMimeTypes(sourceType); + + for (std::string &mimeType : supportedMimeTypes) + { + response->add_mime_types(mimeType); + } + + done->Run(); +} + +void MediaPipelineCapabilitiesModuleService::isMimeTypeSupported( + ::google::protobuf::RpcController *controller, const ::firebolt::rialto::IsMimeTypeSupportedRequest *request, + ::firebolt::rialto::IsMimeTypeSupportedResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + bool isSupported = m_mediaPipelineService.isMimeTypeSupported(request->mime_type()); + response->set_is_supported(isSupported); + + done->Run(); +} + +void MediaPipelineCapabilitiesModuleService::getSupportedProperties( + ::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSupportedPropertiesRequest *request, + ::firebolt::rialto::GetSupportedPropertiesResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + firebolt::rialto::MediaSourceType mediaType = convertMediaSourceType(request->media_type()); + std::vector propertiesToSearch{request->property_names().begin(), request->property_names().end()}; + + std::vector supportedProperties{ + m_mediaPipelineService.getSupportedProperties(mediaType, propertiesToSearch)}; + + for (const std::string &property : supportedProperties) + { + response->add_supported_properties(property.c_str()); + } + + done->Run(); +} + +void MediaPipelineCapabilitiesModuleService::isVideoMaster(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::IsVideoMasterRequest *request, + ::firebolt::rialto::IsVideoMasterResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + bool isMaster{false}; + if (!m_mediaPipelineService.isVideoMaster(isMaster)) + { + RIALTO_SERVER_LOG_ERROR("isVideoMaster check failed"); + controller->SetFailed("isVideoMaster check failed"); + done->Run(); + return; + } + + response->set_is_video_master(isMaster); + + done->Run(); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaPipelineClient.cpp b/middleware/rialto-client/media/server/ipc/source/MediaPipelineClient.cpp new file mode 100644 index 000000000..d3542a1e4 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/MediaPipelineClient.cpp @@ -0,0 +1,265 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaPipelineClient.h" +#include "RialtoServerLogging.h" +#include "mediapipelinemodule.pb.h" +#include + +namespace +{ +firebolt::rialto::PlaybackStateChangeEvent_PlaybackState +convertPlaybackState(const firebolt::rialto::PlaybackState &playbackState) +{ + switch (playbackState) + { + case firebolt::rialto::PlaybackState::UNKNOWN: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_UNKNOWN; + } + case firebolt::rialto::PlaybackState::IDLE: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_IDLE; + } + case firebolt::rialto::PlaybackState::PLAYING: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PLAYING; + } + case firebolt::rialto::PlaybackState::PAUSED: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PAUSED; + } + case firebolt::rialto::PlaybackState::SEEKING: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEKING; + } + case firebolt::rialto::PlaybackState::SEEK_DONE: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEK_DONE; + } + case firebolt::rialto::PlaybackState::STOPPED: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_STOPPED; + } + case firebolt::rialto::PlaybackState::END_OF_STREAM: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_END_OF_STREAM; + } + case firebolt::rialto::PlaybackState::FAILURE: + { + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_FAILURE; + } + } + return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_UNKNOWN; +} + +firebolt::rialto::NetworkStateChangeEvent_NetworkState +convertNetworkState(const firebolt::rialto::NetworkState &networkState) +{ + switch (networkState) + { + case firebolt::rialto::NetworkState::UNKNOWN: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_UNKNOWN; + } + case firebolt::rialto::NetworkState::IDLE: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_IDLE; + } + case firebolt::rialto::NetworkState::BUFFERING: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING; + } + case firebolt::rialto::NetworkState::BUFFERING_PROGRESS: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING_PROGRESS; + } + case firebolt::rialto::NetworkState::BUFFERED: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERED; + } + case firebolt::rialto::NetworkState::STALLED: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_STALLED; + } + case firebolt::rialto::NetworkState::FORMAT_ERROR: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_FORMAT_ERROR; + } + case firebolt::rialto::NetworkState::NETWORK_ERROR: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_NETWORK_ERROR; + } + case firebolt::rialto::NetworkState::DECODE_ERROR: + { + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_DECODE_ERROR; + } + } + return firebolt::rialto::NetworkStateChangeEvent_NetworkState_UNKNOWN; +} + +firebolt::rialto::PlaybackErrorEvent_PlaybackError convertPlaybackError(const firebolt::rialto::PlaybackError &playbackError) +{ + switch (playbackError) + { + case firebolt::rialto::PlaybackError::UNKNOWN: + { + return firebolt::rialto::PlaybackErrorEvent_PlaybackError_UNKNOWN; + } + case firebolt::rialto::PlaybackError::DECRYPTION: + { + return firebolt::rialto::PlaybackErrorEvent_PlaybackError_DECRYPTION; + } + } + return firebolt::rialto::PlaybackErrorEvent_PlaybackError_UNKNOWN; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +MediaPipelineClient::MediaPipelineClient(int sessionId, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) + : m_sessionId{sessionId}, m_ipcClient{ipcClient} +{ +} + +MediaPipelineClient::~MediaPipelineClient() {} + +void MediaPipelineClient::notifyDuration(int64_t duration) +{ + RIALTO_SERVER_LOG_WARN("Notify Duration not supported"); +} + +void MediaPipelineClient::notifyPosition(int64_t position) +{ + RIALTO_SERVER_LOG_DEBUG("Sending PositionChangeEvent"); + + auto event = std::make_shared(); + event->set_session_id(m_sessionId); + event->set_position(position); + + m_ipcClient->sendEvent(event); +} + +void MediaPipelineClient::notifyNativeSize(uint32_t width, uint32_t height, double aspect) +{ + RIALTO_SERVER_LOG_WARN("Notify Native Size not supported"); +} + +void MediaPipelineClient::notifyNetworkState(NetworkState state) +{ + RIALTO_SERVER_LOG_DEBUG("Sending NetworkStateChangeEvent"); + + auto event = std::make_shared(); + event->set_session_id(m_sessionId); + event->set_state(convertNetworkState(state)); + + m_ipcClient->sendEvent(event); +} + +void MediaPipelineClient::notifyPlaybackState(PlaybackState state) +{ + RIALTO_SERVER_LOG_DEBUG("Sending PlaybackStateChangeEvent..."); + + auto event = std::make_shared(); + event->set_session_id(m_sessionId); + event->set_state(convertPlaybackState(state)); + + m_ipcClient->sendEvent(event); +} + +void MediaPipelineClient::notifyVideoData(bool hasData) +{ + RIALTO_SERVER_LOG_WARN("Notify Video Data not supported"); +} + +void MediaPipelineClient::notifyAudioData(bool hasData) +{ + RIALTO_SERVER_LOG_WARN("Notify Audio Data not supported"); +} + +void MediaPipelineClient::notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, + const std::shared_ptr &shmInfo) +{ + RIALTO_SERVER_LOG_DEBUG("Sending NeedMediaDataEvent..."); + + auto event = std::make_shared(); + event->set_session_id(m_sessionId); + event->set_source_id(sourceId); + event->set_request_id(needDataRequestId); + event->set_frame_count(frameCount); + event->mutable_shm_info()->set_max_metadata_bytes(shmInfo->maxMetadataBytes); + event->mutable_shm_info()->set_metadata_offset(shmInfo->metadataOffset); + event->mutable_shm_info()->set_media_data_offset(shmInfo->mediaDataOffset); + event->mutable_shm_info()->set_max_media_bytes(shmInfo->maxMediaBytes); + + m_ipcClient->sendEvent(event); +} + +void MediaPipelineClient::notifyCancelNeedMediaData(int32_t sourceId) +{ + RIALTO_SERVER_LOG_WARN("Notify Cancel Need Media Data not supported"); +} + +void MediaPipelineClient::notifyQos(int32_t sourceId, const QosInfo &qosInfo) +{ + RIALTO_SERVER_LOG_DEBUG("Sending QosEvent..."); + + auto event = std::make_shared(); + event->set_session_id(m_sessionId); + event->set_source_id(sourceId); + event->mutable_qos_info()->set_processed(qosInfo.processed); + event->mutable_qos_info()->set_dropped(qosInfo.dropped); + + m_ipcClient->sendEvent(event); +} + +void MediaPipelineClient::notifyBufferUnderflow(int32_t sourceId) +{ + RIALTO_SERVER_LOG_DEBUG("Sending BufferUnderflowEvent..."); + + auto event = std::make_shared(); + event->set_session_id(m_sessionId); + event->set_source_id(sourceId); + + m_ipcClient->sendEvent(event); +} + +void MediaPipelineClient::notifyPlaybackError(int32_t sourceId, PlaybackError error) +{ + RIALTO_SERVER_LOG_DEBUG("Sending notifyPlaybackError..."); + + auto event = std::make_shared(); + event->set_session_id(m_sessionId); + event->set_source_id(sourceId); + event->set_error(convertPlaybackError(error)); + + m_ipcClient->sendEvent(event); +} + +void MediaPipelineClient::notifySourceFlushed(int32_t sourceId) +{ + RIALTO_SERVER_LOG_DEBUG("Sending SourceFlushedEvent..."); + + auto event = std::make_shared(); + event->set_session_id(m_sessionId); + event->set_source_id(sourceId); + + m_ipcClient->sendEvent(event); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaPipelineModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/MediaPipelineModuleService.cpp new file mode 100644 index 000000000..c74a74f1d --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/MediaPipelineModuleService.cpp @@ -0,0 +1,1082 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaPipelineModuleService.h" +#include "IMediaPipelineService.h" +#include "MediaPipelineClient.h" +#include "RialtoCommonModule.h" +#include "RialtoServerLogging.h" +#include +#include +#include +#include + +namespace +{ +int generateSessionId() +{ + static int sessionId{0}; + return sessionId++; +} + +firebolt::rialto::MediaType convertMediaType(const firebolt::rialto::LoadRequest_MediaType &mediaType) +{ + switch (mediaType) + { + case firebolt::rialto::LoadRequest_MediaType::LoadRequest_MediaType_UNKNOWN: + { + return firebolt::rialto::MediaType::UNKNOWN; + } + case firebolt::rialto::LoadRequest_MediaType::LoadRequest_MediaType_MSE: + { + return firebolt::rialto::MediaType::MSE; + } + } + return firebolt::rialto::MediaType::UNKNOWN; +} + +firebolt::rialto::EaseType convertEaseType(const firebolt::rialto::SetVolumeRequest_EaseType &easeType) +{ + switch (easeType) + { + case firebolt::rialto::SetVolumeRequest_EaseType::SetVolumeRequest_EaseType_EASE_LINEAR: + { + return firebolt::rialto::EaseType::EASE_LINEAR; + } + case firebolt::rialto::SetVolumeRequest_EaseType::SetVolumeRequest_EaseType_EASE_IN_CUBIC: + { + return firebolt::rialto::EaseType::EASE_IN_CUBIC; + } + case firebolt::rialto::SetVolumeRequest_EaseType::SetVolumeRequest_EaseType_EASE_OUT_CUBIC: + { + return firebolt::rialto::EaseType::EASE_OUT_CUBIC; + } + } + return firebolt::rialto::EaseType::EASE_LINEAR; +} + +firebolt::rialto::MediaSourceStatus +convertMediaSourceStatus(const firebolt::rialto::HaveDataRequest_MediaSourceStatus &status) +{ + switch (status) + { + case firebolt::rialto::HaveDataRequest_MediaSourceStatus_UNKNOWN: + { + return firebolt::rialto::MediaSourceStatus::ERROR; + } + case firebolt::rialto::HaveDataRequest_MediaSourceStatus_OK: + { + return firebolt::rialto::MediaSourceStatus::OK; + } + case firebolt::rialto::HaveDataRequest_MediaSourceStatus_EOS: + { + return firebolt::rialto::MediaSourceStatus::EOS; + } + case firebolt::rialto::HaveDataRequest_MediaSourceStatus_ERROR: + { + return firebolt::rialto::MediaSourceStatus::ERROR; + } + case firebolt::rialto::HaveDataRequest_MediaSourceStatus_CODEC_CHANGED: + { + return firebolt::rialto::MediaSourceStatus::CODEC_CHANGED; + } + case firebolt::rialto::HaveDataRequest_MediaSourceStatus_NO_AVAILABLE_SAMPLES: + { + return firebolt::rialto::MediaSourceStatus::NO_AVAILABLE_SAMPLES; + } + } + return firebolt::rialto::MediaSourceStatus::ERROR; +} + +firebolt::rialto::SourceConfigType convertConfigType(const firebolt::rialto::AttachSourceRequest_ConfigType &configType) +{ + switch (configType) + { + case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_UNKNOWN: + { + return firebolt::rialto::SourceConfigType::UNKNOWN; + } + case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_AUDIO: + { + return firebolt::rialto::SourceConfigType::AUDIO; + } + case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO: + { + return firebolt::rialto::SourceConfigType::VIDEO; + } + case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO_DOLBY_VISION: + { + return firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION; + } + case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_SUBTITLE: + { + return firebolt::rialto::SourceConfigType::SUBTITLE; + } + } + return firebolt::rialto::SourceConfigType::UNKNOWN; +} + +firebolt::rialto::SegmentAlignment +convertSegmentAlignment(const firebolt::rialto::AttachSourceRequest_SegmentAlignment &alignment) +{ + switch (alignment) + { + case firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_UNDEFINED: + { + return firebolt::rialto::SegmentAlignment::UNDEFINED; + } + case firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_NAL: + { + return firebolt::rialto::SegmentAlignment::NAL; + } + case firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_AU: + { + return firebolt::rialto::SegmentAlignment::AU; + } + } + + return firebolt::rialto::SegmentAlignment::UNDEFINED; +} + +firebolt::rialto::StreamFormat convertStreamFormat(const firebolt::rialto::AttachSourceRequest_StreamFormat &streamFormat) +{ + switch (streamFormat) + { + case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_RAW: + { + return firebolt::rialto::StreamFormat::RAW; + } + case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_AVC: + { + return firebolt::rialto::StreamFormat::AVC; + } + case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_BYTE_STREAM: + { + return firebolt::rialto::StreamFormat::BYTE_STREAM; + } + case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HVC1: + { + return firebolt::rialto::StreamFormat::HVC1; + } + case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HEV1: + { + return firebolt::rialto::StreamFormat::HEV1; + } + default: + return firebolt::rialto::StreamFormat::UNDEFINED; + } +} + +firebolt::rialto::CodecDataType convertCodecDataType(const firebolt::rialto::AttachSourceRequest_CodecData_Type &type) +{ + if (firebolt::rialto::AttachSourceRequest_CodecData_Type_STRING == type) + { + return firebolt::rialto::CodecDataType::STRING; + } + return firebolt::rialto::CodecDataType::BUFFER; +} + +firebolt::rialto::Format convertFormat(const firebolt::rialto::AttachSourceRequest_AudioConfig_Format &format) +{ + static const std::unordered_map + kFormatConversionMap{ + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S8, firebolt::rialto::Format::S8}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U8, firebolt::rialto::Format::U8}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16LE, firebolt::rialto::Format::S16LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16BE, firebolt::rialto::Format::S16BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16LE, firebolt::rialto::Format::U16LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16BE, firebolt::rialto::Format::U16BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32LE, firebolt::rialto::Format::S24_32LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32BE, firebolt::rialto::Format::S24_32BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32LE, firebolt::rialto::Format::U24_32LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32BE, firebolt::rialto::Format::U24_32BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32LE, firebolt::rialto::Format::S32LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32BE, firebolt::rialto::Format::S32BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32LE, firebolt::rialto::Format::U32LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32BE, firebolt::rialto::Format::U32BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24LE, firebolt::rialto::Format::S24LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24BE, firebolt::rialto::Format::S24BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24LE, firebolt::rialto::Format::U24LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24BE, firebolt::rialto::Format::U24BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20LE, firebolt::rialto::Format::S20LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20BE, firebolt::rialto::Format::S20BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20LE, firebolt::rialto::Format::U20LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20BE, firebolt::rialto::Format::U20BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18LE, firebolt::rialto::Format::S18LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18BE, firebolt::rialto::Format::S18BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18LE, firebolt::rialto::Format::U18LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18BE, firebolt::rialto::Format::U18BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32LE, firebolt::rialto::Format::F32LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32BE, firebolt::rialto::Format::F32BE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64LE, firebolt::rialto::Format::F64LE}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64BE, firebolt::rialto::Format::F64BE}}; + const auto kIt = kFormatConversionMap.find(format); + if (kFormatConversionMap.end() != kIt) + { + return kIt->second; + } + return firebolt::rialto::Format::S8; +} + +firebolt::rialto::Layout convertLayout(const firebolt::rialto::AttachSourceRequest_AudioConfig_Layout &layout) +{ + static const std::unordered_map + kLayoutConversionMap{{firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_INTERLEAVED, + firebolt::rialto::Layout::INTERLEAVED}, + {firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_NON_INTERLEAVED, + firebolt::rialto::Layout::NON_INTERLEAVED}}; + const auto kIt = kLayoutConversionMap.find(layout); + if (kLayoutConversionMap.end() != kIt) + { + return kIt->second; + } + return firebolt::rialto::Layout::INTERLEAVED; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +std::shared_ptr IMediaPipelineModuleServiceFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media player module service factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr +MediaPipelineModuleServiceFactory::create(service::IMediaPipelineService &mediaPipelineService) const +{ + std::shared_ptr mediaPipelineModule; + + try + { + mediaPipelineModule = std::make_shared(mediaPipelineService); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media player module service, reason: %s", e.what()); + } + + return mediaPipelineModule; +} + +MediaPipelineModuleService::MediaPipelineModuleService(service::IMediaPipelineService &mediaPipelineService) + : m_mediaPipelineService{mediaPipelineService} +{ +} + +MediaPipelineModuleService::~MediaPipelineModuleService() {} + +void MediaPipelineModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client Connected!"); + { + m_clientSessions.emplace(ipcClient, std::set()); + } + ipcClient->exportService(shared_from_this()); +} + +void MediaPipelineModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client disconnected!"); + std::set sessionIds; + { + auto sessionIter = m_clientSessions.find(ipcClient); + if (sessionIter == m_clientSessions.end()) + { + RIALTO_SERVER_LOG_ERROR("unknown client disconnected"); + return; + } + sessionIds = sessionIter->second; // copy to avoid deadlock + m_clientSessions.erase(sessionIter); + } + for (const auto &sessionId : sessionIds) + { + m_mediaPipelineService.destroySession(sessionId); + } +} + +void MediaPipelineModuleService::createSession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CreateSessionRequest *request, + ::firebolt::rialto::CreateSessionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + int sessionId = generateSessionId(); + bool sessionCreated = + m_mediaPipelineService.createSession(sessionId, + std::make_shared(sessionId, ipcController->getClient()), + request->max_width(), request->max_height()); + if (sessionCreated) + { + // Assume that IPC library works well and client is present + m_clientSessions[ipcController->getClient()].insert(sessionId); + response->set_session_id(sessionId); + } + else + { + RIALTO_SERVER_LOG_ERROR("Create session failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::destroySession(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DestroySessionRequest *request, + ::firebolt::rialto::DestroySessionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + if (!m_mediaPipelineService.destroySession(request->session_id())) + { + RIALTO_SERVER_LOG_ERROR("Destroy session failed"); + controller->SetFailed("Operation failed"); + done->Run(); + return; + } + auto sessionIter = m_clientSessions.find(ipcController->getClient()); + if (sessionIter != m_clientSessions.end()) + { + sessionIter->second.erase(request->session_id()); + } + done->Run(); +} + +void MediaPipelineModuleService::load(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::LoadRequest *request, + ::firebolt::rialto::LoadResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.load(request->session_id(), convertMediaType(request->type()), request->mime_type(), + request->url())) + { + RIALTO_SERVER_LOG_ERROR("Load failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::setVideoWindow(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetVideoWindowRequest *request, + ::firebolt::rialto::SetVideoWindowResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.setVideoWindow(request->session_id(), request->x(), request->y(), request->width(), + request->height())) + { + RIALTO_SERVER_LOG_ERROR("Set Video Window failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::attachSource(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::AttachSourceRequest *request, + ::firebolt::rialto::AttachSourceResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("mime_type: %s", request->mime_type().c_str()); + + std::shared_ptr codecData{}; + if (request->has_codec_data()) + { + auto codecDataProto = request->codec_data(); + codecData = std::make_shared(); + codecData->data = std::vector(codecDataProto.data().begin(), codecDataProto.data().end()); + codecData->type = convertCodecDataType(codecDataProto.type()); + } + std::unique_ptr mediaSource; + firebolt::rialto::SourceConfigType configType = convertConfigType(request->config_type()); + bool hasDrm = request->has_drm(); + + if (configType == firebolt::rialto::SourceConfigType::AUDIO) + { + const auto &kConfig = request->audio_config(); + uint32_t numberofchannels = kConfig.number_of_channels(); + uint32_t sampleRate = kConfig.sample_rate(); + + std::vector codecSpecificConfig; + if (kConfig.has_codec_specific_config()) + { + auto codecSpecificConfigStr = kConfig.codec_specific_config(); + codecSpecificConfig.assign(codecSpecificConfigStr.begin(), codecSpecificConfigStr.end()); + } + std::optional format{std::nullopt}; + if (kConfig.has_format()) + { + format = convertFormat(kConfig.format()); + } + std::optional layout{std::nullopt}; + if (kConfig.has_layout()) + { + layout = convertLayout(kConfig.layout()); + } + std::optional channelMask{std::nullopt}; + if (kConfig.has_channel_mask()) + { + channelMask = kConfig.channel_mask(); + } + std::vector> streamHeaders; + for (int i = 0; i < kConfig.stream_header_size(); ++i) + { + auto streamHeaderStr = kConfig.stream_header(i); + streamHeaders.push_back(std::vector{streamHeaderStr.begin(), streamHeaderStr.end()}); + } + std::optional framed; + if (kConfig.has_framed()) + { + framed = kConfig.framed(); + } + AudioConfig audioConfig{numberofchannels, sampleRate, codecSpecificConfig, format, + layout, channelMask, streamHeaders, framed}; + + mediaSource = + std::make_unique(request->mime_type(), hasDrm, audioConfig, + convertSegmentAlignment(request->segment_alignment()), + convertStreamFormat(request->stream_format()), codecData); + } + else if (configType == firebolt::rialto::SourceConfigType::VIDEO) + { + mediaSource = + std::make_unique(request->mime_type().c_str(), hasDrm, request->width(), + request->height(), + convertSegmentAlignment(request->segment_alignment()), + convertStreamFormat(request->stream_format()), codecData); + } + else if (configType == firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION) + { + mediaSource = + std::make_unique(request->mime_type().c_str(), + request->dolby_vision_profile(), hasDrm, + request->width(), request->height(), + convertSegmentAlignment( + request->segment_alignment()), + convertStreamFormat(request->stream_format()), + codecData); + } + else if (configType == firebolt::rialto::SourceConfigType::SUBTITLE) + { + mediaSource = std::make_unique(request->mime_type().c_str(), + request->text_track_identifier()); + } + else + { + RIALTO_SERVER_LOG_ERROR("Unknown source type"); + controller->SetFailed("Operation failed"); + done->Run(); + return; + } + + if (!request->has_switch_source() || !request->switch_source()) + { + RIALTO_SERVER_LOG_DEBUG("Attaching source"); + if (!m_mediaPipelineService.attachSource(request->session_id(), mediaSource)) + { + RIALTO_SERVER_LOG_ERROR("Attach source failed"); + controller->SetFailed("Operation failed"); + } + } + else + { + RIALTO_SERVER_LOG_DEBUG("Switching source"); + if (!m_mediaPipelineService.switchSource(request->session_id(), mediaSource)) + { + RIALTO_SERVER_LOG_ERROR("Switch source failed"); + controller->SetFailed("Operation failed"); + } + } + response->set_source_id(mediaSource->getId()); + done->Run(); +} + +void MediaPipelineModuleService::removeSource(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::RemoveSourceRequest *request, + ::firebolt::rialto::RemoveSourceResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.removeSource(request->session_id(), request->source_id())) + { + RIALTO_SERVER_LOG_ERROR("Remove source failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::allSourcesAttached(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::AllSourcesAttachedRequest *request, + ::firebolt::rialto::AllSourcesAttachedResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.allSourcesAttached(request->session_id())) + { + RIALTO_SERVER_LOG_ERROR("All sources attached failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::play(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::PlayRequest *request, + ::firebolt::rialto::PlayResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.play(request->session_id())) + { + RIALTO_SERVER_LOG_ERROR("Play failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::pause(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::PauseRequest *request, + ::firebolt::rialto::PauseResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.pause(request->session_id())) + { + RIALTO_SERVER_LOG_ERROR("pause failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::stop(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::StopRequest *request, + ::firebolt::rialto::StopResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.stop(request->session_id())) + { + RIALTO_SERVER_LOG_ERROR("Stop failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::setPosition(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetPositionRequest *request, + ::firebolt::rialto::SetPositionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.setPosition(request->session_id(), request->position())) + { + RIALTO_SERVER_LOG_ERROR("Set Position failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::haveData(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::HaveDataRequest *request, + ::firebolt::rialto::HaveDataResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + firebolt::rialto::MediaSourceStatus status{convertMediaSourceStatus(request->status())}; + if (!m_mediaPipelineService.haveData(request->session_id(), status, request->num_frames(), request->request_id())) + { + RIALTO_SERVER_LOG_ERROR("Have data failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::setPlaybackRate(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetPlaybackRateRequest *request, + ::firebolt::rialto::SetPlaybackRateResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.setPlaybackRate(request->session_id(), request->rate())) + { + RIALTO_SERVER_LOG_ERROR("Set playback rate failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::getPosition(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetPositionRequest *request, + ::firebolt::rialto::GetPositionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + int64_t position{}; + if (!m_mediaPipelineService.getPosition(request->session_id(), position)) + { + RIALTO_SERVER_LOG_ERROR("Get position failed"); + controller->SetFailed("Operation failed"); + } + else + { + response->set_position(position); + } + done->Run(); +} + +void MediaPipelineModuleService::setImmediateOutput(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetImmediateOutputRequest *request, + ::firebolt::rialto::SetImmediateOutputResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.setImmediateOutput(request->session_id(), request->source_id(), + request->immediate_output())) + { + RIALTO_SERVER_LOG_ERROR("Set Immediate Output failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::getImmediateOutput(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetImmediateOutputRequest *request, + ::firebolt::rialto::GetImmediateOutputResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + bool immediateOutputState; + if (!m_mediaPipelineService.getImmediateOutput(request->session_id(), request->source_id(), immediateOutputState)) + { + RIALTO_SERVER_LOG_ERROR("Get Immediate Output failed"); + controller->SetFailed("Operation failed"); + } + else + { + response->set_immediate_output(immediateOutputState); + } + done->Run(); +} + +void MediaPipelineModuleService::getStats(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetStatsRequest *request, + ::firebolt::rialto::GetStatsResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + uint64_t renderedFrames; + uint64_t droppedFrames; + if (!m_mediaPipelineService.getStats(request->session_id(), request->source_id(), renderedFrames, droppedFrames)) + { + RIALTO_SERVER_LOG_ERROR("Get stats failed"); + controller->SetFailed("Operation failed"); + } + else + { + response->set_rendered_frames(renderedFrames); + response->set_dropped_frames(droppedFrames); + } + done->Run(); +} + +void MediaPipelineModuleService::renderFrame(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::RenderFrameRequest *request, + ::firebolt::rialto::RenderFrameResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_mediaPipelineService.renderFrame(request->session_id())) + { + RIALTO_SERVER_LOG_ERROR("Render frame"); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaPipelineModuleService::setVolume(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetVolumeRequest *request, + ::firebolt::rialto::SetVolumeResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_mediaPipelineService.setVolume(request->session_id(), request->volume(), request->volume_duration(), + convertEaseType(request->ease_type()))) + { + RIALTO_SERVER_LOG_ERROR("Set volume failed."); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaPipelineModuleService::getVolume(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetVolumeRequest *request, + ::firebolt::rialto::GetVolumeResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + double volume{}; + + if (!m_mediaPipelineService.getVolume(request->session_id(), volume)) + { + RIALTO_SERVER_LOG_ERROR("Get volume failed."); + controller->SetFailed("Operation failed"); + } + else + { + response->set_volume(volume); + } + + done->Run(); +} + +void MediaPipelineModuleService::setMute(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetMuteRequest *request, + ::firebolt::rialto::SetMuteResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_mediaPipelineService.setMute(request->session_id(), request->source_id(), request->mute())) + { + RIALTO_SERVER_LOG_ERROR("Set mute failed."); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaPipelineModuleService::getMute(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetMuteRequest *request, + ::firebolt::rialto::GetMuteResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + bool mute{}; + + if (!m_mediaPipelineService.getMute(request->session_id(), request->source_id(), mute)) + { + RIALTO_SERVER_LOG_ERROR("Get mute failed."); + controller->SetFailed("Operation failed"); + } + else + { + response->set_mute(mute); + } + + done->Run(); +} + +void MediaPipelineModuleService::setTextTrackIdentifier(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetTextTrackIdentifierRequest *request, + ::firebolt::rialto::SetTextTrackIdentifierResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_mediaPipelineService.setTextTrackIdentifier(request->session_id(), request->text_track_identifier())) + { + RIALTO_SERVER_LOG_ERROR("Set text track identifier failed."); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaPipelineModuleService::getTextTrackIdentifier(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetTextTrackIdentifierRequest *request, + ::firebolt::rialto::GetTextTrackIdentifierResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + std::string textTrackIdentifier{}; + + if (!m_mediaPipelineService.getTextTrackIdentifier(request->session_id(), textTrackIdentifier)) + { + RIALTO_SERVER_LOG_ERROR("Get TextTrackIdentifier failed."); + controller->SetFailed("Operation failed"); + } + else + { + response->set_text_track_identifier(textTrackIdentifier); + } + + done->Run(); +} + +void MediaPipelineModuleService::setLowLatency(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetLowLatencyRequest *request, + ::firebolt::rialto::SetLowLatencyResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_mediaPipelineService.setLowLatency(request->session_id(), request->low_latency())) + { + RIALTO_SERVER_LOG_ERROR("Set low latency failed."); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaPipelineModuleService::setSync(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetSyncRequest *request, + ::firebolt::rialto::SetSyncResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_mediaPipelineService.setSync(request->session_id(), request->sync())) + { + RIALTO_SERVER_LOG_ERROR("Set sync failed."); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaPipelineModuleService::getSync(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetSyncRequest *request, + ::firebolt::rialto::GetSyncResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + bool sync{}; + + if (!m_mediaPipelineService.getSync(request->session_id(), sync)) + { + RIALTO_SERVER_LOG_ERROR("Get sync failed."); + controller->SetFailed("Operation failed"); + } + else + { + response->set_sync(sync); + } + + done->Run(); +} + +void MediaPipelineModuleService::setSyncOff(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetSyncOffRequest *request, + ::firebolt::rialto::SetSyncOffResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_mediaPipelineService.setSyncOff(request->session_id(), request->sync_off())) + { + RIALTO_SERVER_LOG_ERROR("Set sync off failed."); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaPipelineModuleService::setStreamSyncMode(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetStreamSyncModeRequest *request, + ::firebolt::rialto::SetStreamSyncModeResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_mediaPipelineService.setStreamSyncMode(request->session_id(), request->source_id(), + request->stream_sync_mode())) + { + RIALTO_SERVER_LOG_ERROR("Set stream sync mode failed."); + controller->SetFailed("Operation failed"); + } + + done->Run(); +} + +void MediaPipelineModuleService::getStreamSyncMode(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetStreamSyncModeRequest *request, + ::firebolt::rialto::GetStreamSyncModeResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + int32_t streamSyncMode{}; + + if (!m_mediaPipelineService.getStreamSyncMode(request->session_id(), streamSyncMode)) + { + RIALTO_SERVER_LOG_ERROR("Get stream sync mode failed."); + controller->SetFailed("Operation failed"); + } + else + { + response->set_stream_sync_mode(streamSyncMode); + } + + done->Run(); +} + +void MediaPipelineModuleService::flush(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::FlushRequest *request, + ::firebolt::rialto::FlushResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool isAsync{false}; + if (!m_mediaPipelineService.flush(request->session_id(), request->source_id(), request->reset_time(), isAsync)) + { + RIALTO_SERVER_LOG_ERROR("Flush failed."); + controller->SetFailed("Operation failed"); + } + response->set_async(isAsync); + + done->Run(); +} + +void MediaPipelineModuleService::setSourcePosition(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetSourcePositionRequest *request, + ::firebolt::rialto::SetSourcePositionResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.setSourcePosition(request->session_id(), request->source_id(), request->position(), + request->reset_time(), request->applied_rate(), + request->stop_position())) + { + RIALTO_SERVER_LOG_ERROR("Set Source Position failed."); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::setSubtitleOffset(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetSubtitleOffsetRequest *request, + ::firebolt::rialto::SetSubtitleOffsetResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.setSubtitleOffset(request->session_id(), request->source_id(), request->position())) + { + RIALTO_SERVER_LOG_ERROR("Set Subtitle Offset failed."); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::processAudioGap(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::ProcessAudioGapRequest *request, + ::firebolt::rialto::ProcessAudioGapResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.processAudioGap(request->session_id(), request->position(), request->duration(), + request->discontinuity_gap(), request->audio_aac())) + { + RIALTO_SERVER_LOG_ERROR("Process audio gap failed."); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::setBufferingLimit(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetBufferingLimitRequest *request, + ::firebolt::rialto::SetBufferingLimitResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.setBufferingLimit(request->session_id(), request->limit_buffering_ms())) + { + RIALTO_SERVER_LOG_ERROR("Set buffering limit failed."); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::getBufferingLimit(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetBufferingLimitRequest *request, + ::firebolt::rialto::GetBufferingLimitResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + uint32_t bufferingLimit{}; + + if (!m_mediaPipelineService.getBufferingLimit(request->session_id(), bufferingLimit)) + { + RIALTO_SERVER_LOG_ERROR("Get buffering limit failed."); + controller->SetFailed("Operation failed"); + } + else + { + response->set_limit_buffering_ms(bufferingLimit); + } + + done->Run(); +} + +void MediaPipelineModuleService::setUseBuffering(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::SetUseBufferingRequest *request, + ::firebolt::rialto::SetUseBufferingResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_mediaPipelineService.setUseBuffering(request->session_id(), request->use_buffering())) + { + RIALTO_SERVER_LOG_ERROR("Set use buffering failed."); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void MediaPipelineModuleService::getUseBuffering(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::GetUseBufferingRequest *request, + ::firebolt::rialto::GetUseBufferingResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + bool useBuffering{}; + + if (!m_mediaPipelineService.getUseBuffering(request->session_id(), useBuffering)) + { + RIALTO_SERVER_LOG_ERROR("Get use buffering failed."); + controller->SetFailed("Operation failed"); + } + else + { + response->set_use_buffering(useBuffering); + } + + done->Run(); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/RialtoCommonModule.cpp b/middleware/rialto-client/media/server/ipc/source/RialtoCommonModule.cpp new file mode 100644 index 000000000..d06e9bbee --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/RialtoCommonModule.cpp @@ -0,0 +1,48 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "RialtoCommonModule.h" + +namespace firebolt::rialto::server::ipc +{ +firebolt::rialto::MediaSourceType convertMediaSourceType(const firebolt::rialto::ProtoMediaSourceType &mediaSourceType) +{ + switch (mediaSourceType) + { + case firebolt::rialto::ProtoMediaSourceType::UNKNOWN: + { + return firebolt::rialto::MediaSourceType::UNKNOWN; + } + case firebolt::rialto::ProtoMediaSourceType::AUDIO: + { + return firebolt::rialto::MediaSourceType::AUDIO; + } + case firebolt::rialto::ProtoMediaSourceType::VIDEO: + { + return firebolt::rialto::MediaSourceType::VIDEO; + } + case firebolt::rialto::ProtoMediaSourceType::SUBTITLE: + { + return firebolt::rialto::MediaSourceType::SUBTITLE; + } + } + return firebolt::rialto::MediaSourceType::UNKNOWN; +} + +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/ServerManagerModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/ServerManagerModuleService.cpp new file mode 100644 index 000000000..fd33fb6f6 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/ServerManagerModuleService.cpp @@ -0,0 +1,171 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ServerManagerModuleService.h" +#include "AckSender.h" +#include "ISessionServerManager.h" +#include "RialtoServerLogging.h" +#include + +namespace +{ +firebolt::rialto::common::SessionServerState convertSessionServerState(const rialto::SessionServerState &state) +{ + switch (state) + { + case rialto::SessionServerState::UNINITIALIZED: + return firebolt::rialto::common::SessionServerState::UNINITIALIZED; + case rialto::SessionServerState::INACTIVE: + return firebolt::rialto::common::SessionServerState::INACTIVE; + case rialto::SessionServerState::ACTIVE: + return firebolt::rialto::common::SessionServerState::ACTIVE; + case rialto::SessionServerState::NOT_RUNNING: + return firebolt::rialto::common::SessionServerState::NOT_RUNNING; + case rialto::SessionServerState::ERROR: + return firebolt::rialto::common::SessionServerState::ERROR; + } + return firebolt::rialto::common::SessionServerState::ERROR; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +std::shared_ptr IServerManagerModuleServiceFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the server maanger module service factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr<::rialto::ServerManagerModule> +ServerManagerModuleServiceFactory::create(service::ISessionServerManager &sessionServerManager) const +{ + std::shared_ptr<::rialto::ServerManagerModule> serverManagerModule; + try + { + serverManagerModule = std::make_shared(sessionServerManager); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the server manager module service, reason: %s", e.what()); + } + + return serverManagerModule; +} + +ServerManagerModuleService::ServerManagerModuleService(service::ISessionServerManager &sessionServerManager) + : m_sessionServerManager{sessionServerManager} +{ +} + +ServerManagerModuleService::~ServerManagerModuleService() {} + +void ServerManagerModuleService::setConfiguration(::google::protobuf::RpcController *controller, + const ::rialto::SetConfigurationRequest *request, + ::rialto::SetConfigurationResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("SetConfiguration received from ServerManager"); + common::MaxResourceCapabilitites maxResource{request->resources().maxplaybacks(), + request->resources().maxwebaudioplayers()}; + const auto kClientDisplayName = request->has_clientdisplayname() ? request->clientdisplayname() : ""; + bool success{true}; + if (request->has_sessionmanagementsocketfd()) + { + m_sessionServerManager.configureIpc(request->sessionmanagementsocketfd()); + } + else + { + m_sessionServerManager.configureIpc(request->sessionmanagementsocketname(), request->socketpermissions(), + request->socketowner(), request->socketgroup()); + } + success &= m_sessionServerManager.configureServices(convertSessionServerState(request->initialsessionserverstate()), + maxResource, kClientDisplayName, request->appname()); + m_sessionServerManager.setLogLevels(static_cast(request->loglevels().defaultloglevels()), + static_cast(request->loglevels().clientloglevels()), + static_cast(request->loglevels().sessionserverloglevels()), + static_cast(request->loglevels().ipcloglevels()), + static_cast(request->loglevels().servermanagerloglevels()), + static_cast(request->loglevels().commonloglevels())); + if (!success) + { + RIALTO_SERVER_LOG_ERROR("SetConfiguration operation failed"); + controller->SetFailed("SetConfiguration failed"); + } + done->Run(); +} + +void ServerManagerModuleService::setState(::google::protobuf::RpcController *controller, + const ::rialto::SetStateRequest *request, + ::rialto::SetStateResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("SetState received from ServerManager"); + bool success = m_sessionServerManager.setState(convertSessionServerState(request->sessionserverstate())); + if (!success) + { + RIALTO_SERVER_LOG_ERROR("SetState operation failed"); + controller->SetFailed("SetState failed"); + } + done->Run(); +} + +void ServerManagerModuleService::setLogLevels(::google::protobuf::RpcController *controller, + const ::rialto::SetLogLevelsRequest *request, + ::rialto::SetLogLevelsResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("setLogLevels received from ServerManager"); + m_sessionServerManager.setLogLevels(static_cast(request->loglevels().defaultloglevels()), + static_cast(request->loglevels().clientloglevels()), + static_cast(request->loglevels().sessionserverloglevels()), + static_cast(request->loglevels().ipcloglevels()), + static_cast(request->loglevels().servermanagerloglevels()), + static_cast(request->loglevels().commonloglevels())); + done->Run(); +} + +void ServerManagerModuleService::ping(::google::protobuf::RpcController *controller, const ::rialto::PingRequest *request, + ::rialto::PingResponse *response, ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("Ping received from ServerManager"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + bool success = m_sessionServerManager.ping(request->id(), std::make_shared(ipcController->getClient())); + if (!success) + { + RIALTO_SERVER_LOG_ERROR("Ping failed"); + controller->SetFailed("Ping failed"); + } + done->Run(); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/SessionManagementServer.cpp b/middleware/rialto-client/media/server/ipc/source/SessionManagementServer.cpp new file mode 100644 index 000000000..20e5b2b7d --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/SessionManagementServer.cpp @@ -0,0 +1,187 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SessionManagementServer.h" +#include "IControlModuleService.h" +#include "IMediaKeysCapabilitiesModuleService.h" +#include "IMediaKeysModuleService.h" +#include "IMediaPipelineModuleService.h" +#include "IWebAudioPlayerModuleService.h" +#include "LinuxUtils.h" +#include "RialtoServerLogging.h" +#include +#include +#include +#include +#include +#include + +namespace +{ +constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner +constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group +} // namespace +namespace firebolt::rialto::server::ipc +{ +SessionManagementServer::SessionManagementServer( + const std::shared_ptr &ipcFactory, + const std::shared_ptr &mediaPipelineModuleFactory, + const std::shared_ptr &mediaPipelineCapabilitiesModuleFactory, + const std::shared_ptr &mediaKeysModuleFactory, + const std::shared_ptr &mediaKeysCapabilitiesModuleFactory, + const std::shared_ptr &webAudioPlayerModuleFactory, + const std::shared_ptr &controlModuleFactory, service::IPlaybackService &playbackService, + service::ICdmService &cdmService, service::IControlService &controlService) + : m_isRunning{false}, + m_mediaPipelineModule{mediaPipelineModuleFactory->create(playbackService.getMediaPipelineService())}, + m_mediaPipelineCapabilitiesModule{ + mediaPipelineCapabilitiesModuleFactory->create(playbackService.getMediaPipelineService())}, + m_mediaKeysModule{mediaKeysModuleFactory->create(cdmService)}, + m_mediaKeysCapabilitiesModule{mediaKeysCapabilitiesModuleFactory->create(cdmService)}, + m_webAudioPlayerModule{webAudioPlayerModuleFactory->create(playbackService.getWebAudioPlayerService())}, + m_controlModule{controlModuleFactory->create(playbackService, controlService)} +{ + m_ipcServer = ipcFactory->create(); +} + +SessionManagementServer::~SessionManagementServer() +{ + stop(); + if (m_ipcServerThread.joinable()) + { + m_ipcServerThread.join(); + } +} + +size_t SessionManagementServer::getBufferSizeForPasswordStructureCalls() const +{ + // Can return -1 on error + return sysconf(_SC_GETPW_R_SIZE_MAX); +} + +bool SessionManagementServer::initialize(const std::string &socketName, unsigned int socketPermissions, + const std::string &socketOwner, const std::string &socketGroup) +{ + RIALTO_SERVER_LOG_INFO("Initializing Session Management Server. Socket name: '%s'", socketName.c_str()); + if (!m_ipcServer) + { + RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - Ipc server instance is NULL"); + return false; + } + + // add a socket for clients and associate with a streamer object + if (!m_ipcServer->addSocket(socketName, + std::bind(&SessionManagementServer::onClientConnected, this, std::placeholders::_1), + std::bind(&SessionManagementServer::onClientDisconnected, this, std::placeholders::_1))) + { + RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - can't add socket '%s' to the ipc " + "server", + socketName.c_str()); + return false; + } + + common::setFilePermissions(socketName, socketPermissions); + common::setFileOwnership(socketName, socketOwner, socketGroup); + + RIALTO_SERVER_LOG_MIL("Session Management Server initialized"); + + return true; +} + +bool SessionManagementServer::initialize(int32_t socketFd) +{ + RIALTO_SERVER_LOG_INFO("Initializing Session Management Server. Socket fd: %d", socketFd); + if (!m_ipcServer) + { + RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - Ipc server instance is NULL"); + return false; + } + + // add a socket for clients and associate with a streamer object + if (!m_ipcServer->addSocket(socketFd, + std::bind(&SessionManagementServer::onClientConnected, this, std::placeholders::_1), + std::bind(&SessionManagementServer::onClientDisconnected, this, std::placeholders::_1))) + { + RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - can't add socket fd %d to the ipc " + "server", + socketFd); + return false; + } + + RIALTO_SERVER_LOG_MIL("Session Management Server initialized"); + + return true; +} + +void SessionManagementServer::start() +{ + if (m_isRunning.load()) + { + RIALTO_SERVER_LOG_DEBUG("Server is already in running state"); + return; + } + RIALTO_SERVER_LOG_DEBUG("Starting Session Management Server event loop"); + m_isRunning.store(true); + m_ipcServerThread = std::thread( + [this]() + { + constexpr int kPollInterval{100}; + while (m_ipcServer->process() && m_isRunning.load()) + { + m_ipcServer->wait(kPollInterval); + } + RIALTO_SERVER_LOG_MIL("Session Management Server event loop finished."); + }); +} + +void SessionManagementServer::stop() +{ + m_isRunning.store(false); +} + +void SessionManagementServer::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, + RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) +{ + m_setLogLevelsService.setLogLevels(defaultLogLevels, clientLogLevels, ipcLogLevels, commonLogLevels); +} + +void SessionManagementServer::onClientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) +{ + RIALTO_SERVER_LOG_MIL("Client app connected"); + m_controlModule->clientConnected(client); + m_mediaPipelineModule->clientConnected(client); + m_mediaPipelineCapabilitiesModule->clientConnected(client); + m_mediaKeysModule->clientConnected(client); + m_mediaKeysCapabilitiesModule->clientConnected(client); + m_webAudioPlayerModule->clientConnected(client); + m_setLogLevelsService.clientConnected(client); +} + +void SessionManagementServer::onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) +{ + RIALTO_SERVER_LOG_MIL("Client app disconnected"); + m_setLogLevelsService.clientDisconnected(client); + m_mediaKeysCapabilitiesModule->clientDisconnected(client); + m_mediaKeysModule->clientDisconnected(client); + m_mediaPipelineCapabilitiesModule->clientDisconnected(client); + m_mediaPipelineModule->clientDisconnected(client); + m_webAudioPlayerModule->clientDisconnected(client); + m_controlModule->clientDisconnected(client); +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/SetLogLevelsService.cpp b/middleware/rialto-client/media/server/ipc/source/SetLogLevelsService.cpp new file mode 100644 index 000000000..a266ddca0 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/SetLogLevelsService.cpp @@ -0,0 +1,52 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SetLogLevelsService.h" +#include "mediapipelinemodule.pb.h" + +namespace firebolt::rialto::server::ipc +{ +void SetLogLevelsService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + std::lock_guard lock(m_mutex); + m_connectedClients.insert(ipcClient); +} + +void SetLogLevelsService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + std::lock_guard lock(m_mutex); + m_connectedClients.erase(ipcClient); +} + +void SetLogLevelsService::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, + RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) +{ + auto event = std::make_shared(); + event->set_defaultloglevels(static_cast(defaultLogLevels)); + event->set_clientloglevels(static_cast(clientLogLevels)); + event->set_ipcloglevels(static_cast(ipcLogLevels)); + event->set_commonloglevels(static_cast(commonLogLevels)); + + std::lock_guard lock(m_mutex); + for (const auto &client : m_connectedClients) + { + client->sendEvent(event); + } +} +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerClient.cpp b/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerClient.cpp new file mode 100644 index 000000000..234683a7a --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerClient.cpp @@ -0,0 +1,82 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WebAudioPlayerClient.h" +#include "RialtoServerLogging.h" +#include "webaudioplayermodule.pb.h" +#include + +namespace +{ +firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState +convertWebAudioPlayerState(const firebolt::rialto::WebAudioPlayerState &state) +{ + switch (state) + { + case firebolt::rialto::WebAudioPlayerState::UNKNOWN: + { + return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_UNKNOWN; + } + case firebolt::rialto::WebAudioPlayerState::IDLE: + { + return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_IDLE; + } + case firebolt::rialto::WebAudioPlayerState::PLAYING: + { + return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_PLAYING; + } + case firebolt::rialto::WebAudioPlayerState::PAUSED: + { + return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_PAUSED; + } + case firebolt::rialto::WebAudioPlayerState::END_OF_STREAM: + { + return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_END_OF_STREAM; + } + case firebolt::rialto::WebAudioPlayerState::FAILURE: + { + return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_FAILURE; + } + } + return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_UNKNOWN; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +WebAudioPlayerClient::WebAudioPlayerClient(int webAudioPlayerHandle, + const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) + : m_webAudioPlayerHandle{webAudioPlayerHandle}, m_ipcClient{ipcClient} +{ +} + +WebAudioPlayerClient::~WebAudioPlayerClient() {} + +void WebAudioPlayerClient::notifyState(WebAudioPlayerState state) +{ + RIALTO_SERVER_LOG_DEBUG("Sending WebAudioPlayerStateEvent"); + + auto event = std::make_shared(); + event->set_web_audio_player_handle(m_webAudioPlayerHandle); + event->set_state(convertWebAudioPlayerState(state)); + + m_ipcClient->sendEvent(event); +} + +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerModuleService.cpp new file mode 100644 index 000000000..717c08078 --- /dev/null +++ b/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerModuleService.cpp @@ -0,0 +1,346 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WebAudioPlayerModuleService.h" +#include "IWebAudioPlayerService.h" +#include "RialtoServerLogging.h" +#include "WebAudioPlayerClient.h" +#include +#include +#include + +namespace +{ +int generateHandle() +{ + static int webAudioPlayerHandle{0}; + return webAudioPlayerHandle++; +} +} // namespace + +namespace firebolt::rialto::server::ipc +{ +std::shared_ptr IWebAudioPlayerModuleServiceFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player module service factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr +WebAudioPlayerModuleServiceFactory::create(service::IWebAudioPlayerService &webAudioPlayerService) const +{ + std::shared_ptr webAudioPlayerModule; + + try + { + webAudioPlayerModule = std::make_shared(webAudioPlayerService); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player module service, reason: %s", e.what()); + } + + return webAudioPlayerModule; +} + +WebAudioPlayerModuleService::WebAudioPlayerModuleService(service::IWebAudioPlayerService &webAudioPlayerService) + : m_webAudioPlayerService{webAudioPlayerService} +{ +} + +WebAudioPlayerModuleService::~WebAudioPlayerModuleService() {} + +void WebAudioPlayerModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client Connected!"); + { + m_clientWebAudioPlayerHandles.emplace(ipcClient, std::set()); + } + ipcClient->exportService(shared_from_this()); +} + +void WebAudioPlayerModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) +{ + RIALTO_SERVER_LOG_INFO("Client disconnected!"); + std::set webAudioPlayerHandles; + { + auto handleIter = m_clientWebAudioPlayerHandles.find(ipcClient); + if (handleIter == m_clientWebAudioPlayerHandles.end()) + { + RIALTO_SERVER_LOG_ERROR("unknown client disconnected"); + return; + } + webAudioPlayerHandles = handleIter->second; // copy to avoid deadlock + m_clientWebAudioPlayerHandles.erase(handleIter); + } + for (const auto &webAudioPlayerHandle : webAudioPlayerHandles) + { + m_webAudioPlayerService.destroyWebAudioPlayer(webAudioPlayerHandle); + } +} + +void WebAudioPlayerModuleService::createWebAudioPlayer(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::CreateWebAudioPlayerRequest *request, + ::firebolt::rialto::CreateWebAudioPlayerResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + + std::shared_ptr config = std::make_shared(); + if (request->has_config()) + { + if (request->config().has_pcm()) + { + config->pcm.rate = request->config().pcm().rate(); + config->pcm.channels = request->config().pcm().channels(); + config->pcm.sampleSize = request->config().pcm().sample_size(); + config->pcm.isBigEndian = request->config().pcm().is_big_endian(); + config->pcm.isSigned = request->config().pcm().is_signed(); + config->pcm.isFloat = request->config().pcm().is_float(); + } + } + int handle = generateHandle(); + bool webAudioPlayerCreated = + m_webAudioPlayerService.createWebAudioPlayer(handle, + std::make_shared(handle, + ipcController->getClient()), + request->audio_mime_type(), request->priority(), config); + if (webAudioPlayerCreated) + { + // Assume that IPC library works well and client is present + m_clientWebAudioPlayerHandles[ipcController->getClient()].insert(handle); + response->set_web_audio_player_handle(handle); + } + else + { + RIALTO_SERVER_LOG_ERROR("Create web audio player failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void WebAudioPlayerModuleService::destroyWebAudioPlayer(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::DestroyWebAudioPlayerRequest *request, + ::firebolt::rialto::DestroyWebAudioPlayerResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto ipcController = dynamic_cast(controller); + if (!ipcController) + { + RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); + controller->SetFailed("ipc library provided incompatible controller object"); + done->Run(); + return; + } + if (!m_webAudioPlayerService.destroyWebAudioPlayer(request->web_audio_player_handle())) + { + RIALTO_SERVER_LOG_ERROR("Destroy web audio player failed"); + controller->SetFailed("Operation failed"); + done->Run(); + return; + } + auto handleIter = m_clientWebAudioPlayerHandles.find(ipcController->getClient()); + if (handleIter != m_clientWebAudioPlayerHandles.end()) + { + handleIter->second.erase(request->web_audio_player_handle()); + } + done->Run(); +} + +void WebAudioPlayerModuleService::play(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioPlayRequest *request, + ::firebolt::rialto::WebAudioPlayResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_webAudioPlayerService.play(request->web_audio_player_handle())) + { + RIALTO_SERVER_LOG_ERROR("play failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void WebAudioPlayerModuleService::pause(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioPauseRequest *request, + ::firebolt::rialto::WebAudioPauseResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_webAudioPlayerService.pause(request->web_audio_player_handle())) + { + RIALTO_SERVER_LOG_ERROR("pause failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void WebAudioPlayerModuleService::setEos(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioSetEosRequest *request, + ::firebolt::rialto::WebAudioSetEosResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_webAudioPlayerService.setEos(request->web_audio_player_handle())) + { + RIALTO_SERVER_LOG_ERROR("setEos failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void WebAudioPlayerModuleService::getBufferAvailable(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioGetBufferAvailableRequest *request, + ::firebolt::rialto::WebAudioGetBufferAvailableResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + uint32_t availableFrames{}; + std::shared_ptr shmInfo = std::make_shared(); + if (!m_webAudioPlayerService.getBufferAvailable(request->web_audio_player_handle(), availableFrames, shmInfo)) + { + RIALTO_SERVER_LOG_ERROR("getBufferAvailable failed"); + controller->SetFailed("Operation failed"); + } + else + { + response->set_available_frames(availableFrames); + auto responseShmInfo = response->mutable_shm_info(); + responseShmInfo->set_offset_main(shmInfo->offsetMain); + responseShmInfo->set_length_main(shmInfo->lengthMain); + responseShmInfo->set_offset_wrap(shmInfo->offsetWrap); + responseShmInfo->set_length_wrap(shmInfo->lengthWrap); + } + done->Run(); +} + +void WebAudioPlayerModuleService::getBufferDelay(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioGetBufferDelayRequest *request, + ::firebolt::rialto::WebAudioGetBufferDelayResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + uint32_t delayFrames{}; + if (!m_webAudioPlayerService.getBufferDelay(request->web_audio_player_handle(), delayFrames)) + { + RIALTO_SERVER_LOG_ERROR("getBufferDelay failed"); + controller->SetFailed("Operation failed"); + } + else + { + response->set_delay_frames(delayFrames); + } + done->Run(); +} + +void WebAudioPlayerModuleService::writeBuffer(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioWriteBufferRequest *request, + ::firebolt::rialto::WebAudioWriteBufferResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_webAudioPlayerService.writeBuffer(request->web_audio_player_handle(), request->number_of_frames(), nullptr)) + { + RIALTO_SERVER_LOG_ERROR("writeBuffer failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void WebAudioPlayerModuleService::getDeviceInfo(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioGetDeviceInfoRequest *request, + ::firebolt::rialto::WebAudioGetDeviceInfoResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + uint32_t preferredFrames{}; + uint32_t maximumFrames{}; + bool supportDeferredPlay{}; + if (!m_webAudioPlayerService.getDeviceInfo(request->web_audio_player_handle(), preferredFrames, maximumFrames, + supportDeferredPlay)) + { + RIALTO_SERVER_LOG_ERROR("getDeviceInfo failed"); + controller->SetFailed("Operation failed"); + } + else + { + response->set_preferred_frames(preferredFrames); + response->set_maximum_frames(maximumFrames); + response->set_support_deferred_play(supportDeferredPlay); + } + done->Run(); +} + +void WebAudioPlayerModuleService::setVolume(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioSetVolumeRequest *request, + ::firebolt::rialto::WebAudioSetVolumeResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + if (!m_webAudioPlayerService.setVolume(request->web_audio_player_handle(), request->volume())) + { + RIALTO_SERVER_LOG_ERROR("setVolume failed"); + controller->SetFailed("Operation failed"); + } + done->Run(); +} + +void WebAudioPlayerModuleService::getVolume(::google::protobuf::RpcController *controller, + const ::firebolt::rialto::WebAudioGetVolumeRequest *request, + ::firebolt::rialto::WebAudioGetVolumeResponse *response, + ::google::protobuf::Closure *done) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + double volume{}; + if (!m_webAudioPlayerService.getVolume(request->web_audio_player_handle(), volume)) + { + RIALTO_SERVER_LOG_ERROR("getVolume failed"); + controller->SetFailed("Operation failed"); + } + else + { + response->set_volume(volume); + } + done->Run(); +} + +} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/main/CMakeLists.txt b/middleware/rialto-client/media/server/main/CMakeLists.txt new file mode 100644 index 000000000..e21462bb1 --- /dev/null +++ b/middleware/rialto-client/media/server/main/CMakeLists.txt @@ -0,0 +1,97 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +set( CMAKE_CXX_STANDARD 17 ) + +set( CMAKE_CXX_STANDARD_REQUIRED ON ) +include( CheckCXXCompilerFlag ) + +# Find includes in corresponding build directories +set( CMAKE_INCLUDE_CURRENT_DIR ON ) + +add_library( + RialtoServerMain STATIC + + ${PROTO_SRCS} + ${PROTO_HEADERS} + + source/MediaPipelineServerInternal.cpp + source/MediaPipelineCapabilities.cpp + source/ActiveRequests.cpp + source/DataReaderFactory.cpp + source/DataReaderV1.cpp + source/DataReaderV2.cpp + source/NeedMediaData.cpp + source/SharedMemoryBuffer.cpp + source/MediaKeysServerInternal.cpp + source/MediaKeysCapabilities.cpp + source/MediaKeySession.cpp + source/MainThread.cpp + source/WebAudioPlayerServerInternal.cpp + source/ControlServerInternal.cpp + source/HeartbeatProcedure.cpp + source/TextTrackAccessor.cpp + source/TextTrackSession.cpp + ) + +target_include_directories( + RialtoServerMain + + PUBLIC + interface + ${GStreamerApp_INCLUDE_DIRS} + + PRIVATE + include + $ + $ + $ + $ + $ + $ + ) + +set_target_properties( + RialtoServerMain + PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" + + ) + +target_compile_options( + RialtoServerMain + + PRIVATE + ) + +target_link_libraries( + RialtoServerMain + + PRIVATE + RialtoLogging + RialtoServerGstPlayer + RialtoWrappers + RialtoCommon + RialtoProtobuf + Threads::Threads + ) + +install( + TARGETS RialtoServerMain + DESTINATION lib + ) diff --git a/middleware/rialto-client/media/server/main/include/ActiveRequests.h b/middleware/rialto-client/media/server/main/include/ActiveRequests.h new file mode 100644 index 000000000..980758bd6 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/ActiveRequests.h @@ -0,0 +1,85 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_ACTIVE_REQUESTS_H_ +#define FIREBOLT_RIALTO_SERVER_ACTIVE_REQUESTS_H_ + +#include "IActiveRequests.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +class ActiveRequests : public IActiveRequests +{ +public: + class ActiveRequestsData + { + public: + ActiveRequestsData(MediaSourceType type, std::uint32_t maxMediaBytes) + : m_type(type), m_bytesWritten(0), m_maxMediaBytes(maxMediaBytes) + { + } + ~ActiveRequestsData(); + ActiveRequestsData(ActiveRequestsData &&) = default; + ActiveRequestsData &operator=(ActiveRequestsData &&) = default; + + ActiveRequestsData(const ActiveRequestsData &) = delete; + ActiveRequestsData &operator=(const ActiveRequestsData &) = delete; + + AddSegmentStatus addSegment(const std::unique_ptr &segment); + + MediaSourceType getType() const { return m_type; } + const IMediaPipeline::MediaSegmentVector &getSegments() const { return m_segments; } + + private: + MediaSourceType m_type; + std::uint32_t m_bytesWritten; + std::uint32_t m_maxMediaBytes; + IMediaPipeline::MediaSegmentVector m_segments; + }; + + ActiveRequests(); + ~ActiveRequests() override = default; + ActiveRequests(const ActiveRequests &) = delete; + ActiveRequests(ActiveRequests &&) = delete; + ActiveRequests &operator=(const ActiveRequests &) = delete; + ActiveRequests &operator=(ActiveRequests &&) = delete; + + std::uint32_t insert(const MediaSourceType &mediaSourceType, std::uint32_t maxMediaBytes) override; + MediaSourceType getType(std::uint32_t requestId) const override; + void erase(std::uint32_t requestId) override; + void erase(const MediaSourceType &mediaSourceType) override; + void clear() override; + AddSegmentStatus addSegment(std::uint32_t requestId, + const std::unique_ptr &segment) override; + const IMediaPipeline::MediaSegmentVector &getSegments(std::uint32_t requestId) const override; + +private: + mutable std::mutex m_mutex; + std::uint32_t m_currentId; + std::map m_requestMap; + // only used in server-only mode + std::map> m_addedSegments; +}; + +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_ACTIVE_REQUESTS_H_ diff --git a/middleware/rialto-client/media/server/main/include/ControlServerInternal.h b/middleware/rialto-client/media/server/main/include/ControlServerInternal.h new file mode 100644 index 000000000..dc6ca3655 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/ControlServerInternal.h @@ -0,0 +1,63 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_CONTROL_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_CONTROL_SERVER_INTERNAL_H_ + +#include + +#include "IControlServerInternal.h" +#include "IMainThread.h" + +namespace firebolt::rialto::server +{ +class ControlServerInternalFactory : public IControlServerInternalFactory +{ +public: + ControlServerInternalFactory() = default; + ~ControlServerInternalFactory() override = default; + + std::shared_ptr createControl() const override; + std::shared_ptr + createControlServerInternal(int id, const std::shared_ptr &client) const override; +}; + +class ControlServerInternal : public IControlServerInternal +{ +public: + explicit ControlServerInternal(const std::shared_ptr &mainThreadFactory, int id, + const std::shared_ptr &client); + ~ControlServerInternal() override; + + void ack(int32_t id) override; + void setApplicationState(const ApplicationState &state) override; + void ping(std::unique_ptr &&heartbeatHandler) override; + bool registerClient(std::weak_ptr client, ApplicationState &appState) override; + +private: + const int m_controlId; + std::shared_ptr m_client; + ApplicationState m_currentState; + std::shared_ptr m_mainThread; + std::unique_ptr m_heartbeatHandler; + uint32_t m_mainThreadClientId; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_CONTROL_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/include/DataReaderFactory.h b/middleware/rialto-client/media/server/main/include/DataReaderFactory.h new file mode 100644 index 000000000..5ba7f6558 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/DataReaderFactory.h @@ -0,0 +1,38 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_DATA_READER_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_DATA_READER_FACTORY_H_ + +#include "IDataReaderFactory.h" +#include + +namespace firebolt::rialto::server +{ +class DataReaderFactory : public IDataReaderFactory +{ +public: + DataReaderFactory() = default; + ~DataReaderFactory() override = default; + std::shared_ptr createDataReader(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, + std::uint32_t dataOffset, std::uint32_t numFrames) const override; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_DATA_READER_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/main/include/DataReaderV1.h b/middleware/rialto-client/media/server/main/include/DataReaderV1.h new file mode 100644 index 000000000..88a35d895 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/DataReaderV1.h @@ -0,0 +1,88 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_DATA_READERV1_H_ +#define FIREBOLT_RIALTO_SERVER_DATA_READERV1_H_ + +#include "IDataReader.h" +#include "MediaCommon.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class DataReaderV1 : public IDataReader +{ + struct MetadataV1 + { + std::uint32_t offset; /* Offset of first byte of sample in CM buffer */ + std::uint32_t length; /* Number of bytes in sample */ + std::int64_t timePosition; /* Position in stream in nanoseconds */ + std::int64_t sampleDuration; /* Frame/sample duration in nanoseconds */ + std::uint32_t streamId; /* stream id (unique ID for ES, as defined in attachSource()) */ + std::uint32_t extraDataSize; /* extraData size */ + std::uint8_t extraData[32]; /* buffer containing extradata */ + std::uint32_t mediaKeysId; /* Identifier of MediaKeys instance to use for decryption. If 0 use any CDM + containing the MKS ID */ + std::uint32_t mediaKeySessionIdentifierOffset; /* Offset to the location of the MediaKeySessionIdentifier */ + std::uint32_t mediaKeySessionIdentifierLength; /* Length of the MediaKeySessionIdentifier */ + std::uint32_t initVectorOffset; /* Offset to the location of the initialization vector */ + std::uint32_t initVectorLength; /* Length of initialization vector */ + std::uint32_t subSampleInfoOffset; /* Offset to the location of the sub sample info table */ + std::uint32_t subSampleInfoLen; /* Length of sub-sample Info table */ + std::uint32_t initWithLast15; + std::uint32_t extra1; /* Samples per second for audio; Video width in pixels for video */ + std::uint32_t extra2; /* Number of channels for audio; Video height in pixels for video */ + }; + +public: + DataReaderV1(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t metadataOffset, + std::uint32_t numFrames); + ~DataReaderV1() override = default; + + IMediaPipeline::MediaSegmentVector readData() const override; + +private: + std::vector readMetadata() const; + +private: + MediaSourceType m_mediaSourceType; + std::uint8_t *m_buffer; + std::uint32_t m_metadataOffset; + std::uint32_t m_numFrames; + + template std::unique_ptr createSegment(const MetadataV1 &metadata) const + { + std::unique_ptr mediaSegment{std::make_unique(0, metadata.timePosition, + metadata.sampleDuration, + metadata.extra1, metadata.extra2)}; + mediaSegment->setData(metadata.length, m_buffer + metadata.offset); + std::vector extraDataVec; + std::copy(&metadata.extraData[0], &metadata.extraData[metadata.extraDataSize], std::back_inserter(extraDataVec)); + mediaSegment->setExtraData(extraDataVec); + mediaSegment->setEncrypted(false); // temporary, only clear content playback should be supported now + return mediaSegment; + } +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_DATA_READERV1_H_ diff --git a/middleware/rialto-client/media/server/main/include/DataReaderV2.h b/middleware/rialto-client/media/server/main/include/DataReaderV2.h new file mode 100644 index 000000000..6871022f5 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/DataReaderV2.h @@ -0,0 +1,46 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_DATA_READERV2_H_ +#define FIREBOLT_RIALTO_SERVER_DATA_READERV2_H_ + +#include "IDataReader.h" +#include "MediaCommon.h" +#include + +namespace firebolt::rialto::server +{ +class DataReaderV2 : public IDataReader +{ +public: + DataReaderV2(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t dataOffset, + std::uint32_t numFrames); + ~DataReaderV2() override = default; + + IMediaPipeline::MediaSegmentVector readData() const override; + +private: + MediaSourceType m_mediaSourceType; + std::uint8_t *m_buffer; + std::uint32_t m_dataOffset; + std::uint32_t m_numFrames; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_DATA_READERV2_H_ diff --git a/middleware/rialto-client/media/server/main/include/HeartbeatProcedure.h b/middleware/rialto-client/media/server/main/include/HeartbeatProcedure.h new file mode 100644 index 000000000..66da279a8 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/HeartbeatProcedure.h @@ -0,0 +1,70 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_HEARTBEAT_PROCEDURE_H_ +#define FIREBOLT_RIALTO_SERVER_HEARTBEAT_PROCEDURE_H_ + +#include "IHeartbeatProcedure.h" +#include +#include + +namespace firebolt::rialto::server +{ +class HeartbeatProcedureFactory : public IHeartbeatProcedureFactory +{ +public: + HeartbeatProcedureFactory() = default; + ~HeartbeatProcedureFactory() override = default; + std::shared_ptr createHeartbeatProcedure(const std::shared_ptr &ackSender, + std::int32_t pingId) const override; +}; + +class HeartbeatProcedure : public std::enable_shared_from_this, public IHeartbeatProcedure +{ + class HeartbeatHandler : public IHeartbeatHandler + { + public: + HeartbeatHandler(const std::shared_ptr &procedure, std::int32_t pingId); + ~HeartbeatHandler() override; + + void error() override; + std::int32_t id() const override; + + private: + std::shared_ptr m_procedure; + const std::int32_t m_kPingId; + bool m_success; + }; + +public: + HeartbeatProcedure(const std::shared_ptr &ackSender, std::int32_t pingId); + ~HeartbeatProcedure() override; + std::unique_ptr createHandler() override; + +private: + void onFinish(bool success); + +private: + std::shared_ptr m_ackSender; + const std::int32_t m_kPingId; + std::atomic_bool m_success; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_HEARTBEAT_PROCEDURE_H_ diff --git a/middleware/rialto-client/media/server/main/include/IActiveRequests.h b/middleware/rialto-client/media/server/main/include/IActiveRequests.h new file mode 100644 index 000000000..d2e728c36 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/IActiveRequests.h @@ -0,0 +1,52 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_ACTIVE_REQUESTS_H_ +#define FIREBOLT_RIALTO_SERVER_I_ACTIVE_REQUESTS_H_ + +#include "MediaCommon.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IActiveRequests +{ +public: + IActiveRequests() = default; + virtual ~IActiveRequests() = default; + + IActiveRequests(const IActiveRequests &) = delete; + IActiveRequests(IActiveRequests &&) = delete; + IActiveRequests &operator=(const IActiveRequests &) = delete; + IActiveRequests &operator=(IActiveRequests &&) = delete; + + virtual std::uint32_t insert(const MediaSourceType &mediaSourceType, std::uint32_t maxMediaBytes) = 0; + virtual MediaSourceType getType(std::uint32_t requestId) const = 0; + virtual void erase(std::uint32_t requestId) = 0; + virtual void erase(const MediaSourceType &mediaSourceType) = 0; + virtual void clear() = 0; + virtual AddSegmentStatus addSegment(std::uint32_t requestId, + const std::unique_ptr &segment) = 0; + virtual const IMediaPipeline::MediaSegmentVector &getSegments(std::uint32_t requestId) const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_ACTIVE_REQUESTS_H_ diff --git a/middleware/rialto-client/media/server/main/include/IDataReaderFactory.h b/middleware/rialto-client/media/server/main/include/IDataReaderFactory.h new file mode 100644 index 000000000..b4dee55e4 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/IDataReaderFactory.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_DATA_READER_FACTORY_H_ +#define FIREBOLT_RIALTO_SERVER_I_DATA_READER_FACTORY_H_ + +#include "MediaCommon.h" +#include +#include + +namespace firebolt::rialto::server +{ +class IDataReader; +} // namespace firebolt::rialto::server + +namespace firebolt::rialto::server +{ +class IDataReaderFactory +{ +public: + IDataReaderFactory() = default; + virtual ~IDataReaderFactory() = default; + + virtual std::shared_ptr createDataReader(const MediaSourceType &mediaSourceType, std::uint8_t *data, + std::uint32_t dataOffset, std::uint32_t numFrames) const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_DATA_READER_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/main/include/IMediaKeySession.h b/middleware/rialto-client/media/server/main/include/IMediaKeySession.h new file mode 100644 index 000000000..f962f66bb --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/IMediaKeySession.h @@ -0,0 +1,192 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_MEDIA_KEY_SESSION_H_ +#define FIREBOLT_RIALTO_SERVER_I_MEDIA_KEY_SESSION_H_ + +#include "IMediaKeysClient.h" +#include "IOcdmSystem.h" +#include "MediaCommon.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IMediaKeySession; + +/** + * @brief IMediaKeySession factory class, returns a concrete implementation of IMediaKeySession + */ +class IMediaKeySessionFactory +{ +public: + IMediaKeySessionFactory() = default; + virtual ~IMediaKeySessionFactory() = default; + + /** + * @brief Create a IMediaKeySessionFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMediaKeySession factory method, returns a concrete implementation of IMediaKeySession + * + * @param[in] keySystem : The key system for this session. + * @param[in] keySessionId : The key session id for this session. + * @param[in] ocdmSystem : The ocdm system object to create the session on. + * @param[in] sessionType : The session type. + * @param[in] client : Client object for callbacks. + * @param[in] isLDL : Is this an LDL. + * + * @retval the new media keys instance or null on error. + */ + virtual std::unique_ptr + createMediaKeySession(const std::string &keySystem, int32_t keySessionId, + const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, KeySessionType sessionType, + std::weak_ptr client, bool isLDL) const = 0; +}; + +/** + * @brief The definition of the IMediaKeySession interface. + */ +class IMediaKeySession +{ +public: + IMediaKeySession() = default; + virtual ~IMediaKeySession() = default; + + IMediaKeySession(const IMediaKeySession &) = delete; + IMediaKeySession &operator=(const IMediaKeySession &) = delete; + IMediaKeySession(IMediaKeySession &&) = delete; + IMediaKeySession &operator=(IMediaKeySession &&) = delete; + + /** + * @brief Generates a licence request. + * + * @param[in] initDataType : The init data type. + * @param[in] initData : The init data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus generateRequest(InitDataType initDataType, const std::vector &initData) = 0; + + /** + * @brief Loads the existing key session. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus loadSession() = 0; + + /** + * @brief Updates the key session's state. + * + * @param[in] responseData : The license response data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus updateSession(const std::vector &responseData) = 0; + + /** + * @brief Decrypts the buffer. + * + * @param[in] encrypted : Gstreamer buffer containing encrypted data and related meta data. If applicable, + * decrypted data will be stored here after this call returns. + * @param[in] caps : The gst caps of buffer. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus decrypt(GstBuffer *encrypted, GstCaps *caps) = 0; + + /** + * @brief Closes the key session. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus closeKeySession() = 0; + + /** + * @brief Removes the key session. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus removeKeySession() = 0; + + /** + * @brief Get the internal CDM key session ID + * + * @param[out] cdmKeySessionId : The internal CDM key session ID + * + * @retval the return status. + */ + virtual MediaKeyErrorStatus getCdmKeySessionId(std::string &cdmKeySessionId) = 0; + + /** + * @brief Returns true if the Key Session object contains the specified key. + * + * @param[in] keyId : The key id. + * + * @retval true if it contains the key. + */ + virtual bool containsKey(const std::vector &keyId) = 0; + + /** + * @brief Set DRM Header for a key session + * + * This method updates a key session's DRM header. If the session id does + * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned.If the session + * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any + * other errors will result in MediaKeyErrorStatus:FAIL. + * + * @param[in] requestData : The request data. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus setDrmHeader(const std::vector &requestData) = 0; + + /** + * @brief Get the last cdm specific DRM error code + * + * @param[out] errorCode : the error code. + * + * @retval the return status value. + */ + virtual MediaKeyErrorStatus getLastDrmError(uint32_t &errorCode) = 0; + + /** + * @brief Selects the specified keyId for the key session. Playready specific API. + * + * @param[in] keyId : The key id to select. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus selectKeyId(const std::vector &keyId) = 0; + + /** + * @brief Checks, if key system of media key session is playready. + * + * @retval true if key system is playready + */ + virtual bool isPlayreadyKeySystem() const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_MEDIA_KEY_SESSION_H_ diff --git a/middleware/rialto-client/media/server/main/include/INeedMediaDataThread.h b/middleware/rialto-client/media/server/main/include/INeedMediaDataThread.h new file mode 100644 index 000000000..7023cc039 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/INeedMediaDataThread.h @@ -0,0 +1,41 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_NEED_MEDIA_DATA_THREAD_H_ +#define FIREBOLT_RIALTO_SERVER_I_NEED_MEDIA_DATA_THREAD_H_ + +namespace firebolt::rialto::server +{ +class INeedMediaDataThread +{ +public: + INeedMediaDataThread() = default; + virtual ~INeedMediaDataThread() = default; + + INeedMediaDataThread(const INeedMediaDataThread &) = delete; + INeedMediaDataThread(INeedMediaDataThread &&) = delete; + INeedMediaDataThread &operator=(const INeedMediaDataThread &) = delete; + INeedMediaDataThread &operator=(INeedMediaDataThread &&) = delete; + + virtual void queueEvent() = 0; + virtual void stop() = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_NEED_MEDIA_DATA_THREAD_H_ diff --git a/middleware/rialto-client/media/server/main/include/ITextTrackAccessor.h b/middleware/rialto-client/media/server/main/include/ITextTrackAccessor.h new file mode 100644 index 000000000..86ebc846d --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/ITextTrackAccessor.h @@ -0,0 +1,70 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_ACCESSOR_H_ +#define FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_ACCESSOR_H_ + +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class ITextTrackAccessor; + +class ITextTrackAccessorFactory +{ +public: + virtual ~ITextTrackAccessorFactory() = default; + + static ITextTrackAccessorFactory &getFactory(); + virtual std::shared_ptr getTextTrackAccessor() const = 0; +}; + +class ITextTrackAccessor +{ +public: + enum class DataType + { + UNKNOWN, + WebVTT, + TTML, + CC + }; + + ITextTrackAccessor() = default; + virtual ~ITextTrackAccessor() = default; + virtual std::optional openSession(const std::string &displayName) = 0; + virtual bool closeSession(uint32_t sessionId) = 0; + virtual bool resetSession(uint32_t sessionId) = 0; + virtual bool pause(uint32_t sessionId) = 0; + virtual bool play(uint32_t sessionId) = 0; + virtual bool mute(uint32_t sessionId, bool mute) = 0; + virtual bool setPosition(uint32_t sessionId, uint64_t mediaTimestampMs) = 0; + virtual bool sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs = 0) = 0; + virtual bool setSessionWebVTTSelection(uint32_t sessionId) = 0; + virtual bool setSessionTTMLSelection(uint32_t sessionId) = 0; + virtual bool setSessionCCSelection(uint32_t sessionId, const std::string &service) = 0; + virtual bool associateVideoDecoder(uint32_t sessionId, const std::string &videoDecoder) = 0; +}; + +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_ACCESSOR_H_ diff --git a/middleware/rialto-client/media/server/main/include/MainThread.h b/middleware/rialto-client/media/server/main/include/MainThread.h new file mode 100644 index 000000000..9610b1bac --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/MainThread.h @@ -0,0 +1,141 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_MAIN_THREAD_H_ +#define FIREBOLT_RIALTO_SERVER_MAIN_THREAD_H_ + +#include "IMainThread.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IMainThread factory class definition. + */ +class MainThreadFactory : public IMainThreadFactory +{ +public: + MainThreadFactory() = default; + ~MainThreadFactory() override = default; + + std::shared_ptr getMainThread() const override; + +protected: + /** + * @brief Weak pointer to the singleton main thread object. + */ + static std::weak_ptr m_mainThread; + + /** + * @brief Mutex protection for creation of the MainThread object. + */ + static std::mutex m_creationMutex; +}; + +/** + * @brief The definition of the MediaKeys. + */ +class MainThread : public IMainThread +{ +public: + MainThread(); + virtual ~MainThread(); + + int32_t registerClient() override; + void unregisterClient(uint32_t clientId) override; + + void enqueueTask(uint32_t clientId, Task task) override; + void enqueueTaskAndWait(uint32_t clientId, Task task) override; + void enqueuePriorityTaskAndWait(uint32_t clientId, Task task) override; + +private: + /** + * @brief Information of a task. + */ + struct TaskInfo + { + uint32_t clientId; /**< The id of the client creating the task. */ + Task task; /**< The task to execute. */ + std::unique_ptr mutex; /**< Mutex for the task condition variable. */ + std::unique_ptr cv; /**< The condition variable of the task. */ + }; + + /** + * @brief Starts a loop that listens for enqueued tasks. + */ + void mainThreadLoop(); + + /** + * @brief Waits for tasks to enter the queue and returns the next task. + * + * @retval The next task in the queue. + */ + const std::shared_ptr waitForTask(); + + /** + * @brief Whether the main thread is running. + */ + bool m_isMainThreadRunning; + + /** + * @brief The main thread. + */ + std::thread m_thread; + + /** + * @brief A mutex protecting access to the task queue. + */ + std::mutex m_taskQueueMutex; + + /** + * @brief A condition variable used to notify of tasks entering the task queue. + */ + std::condition_variable m_taskQueueCv; + + /** + * @brief The queue of tasks and there infomation. + */ + std::deque> m_taskQueue; + + /** + * @brief The main thread objects client id, for registering new clients. + */ + const uint32_t m_mainThreadClientId; + + /** + * @brief The next client id to be given to a registering client. + */ + std::atomic m_nextClientId; + + /** + * @brief Clients registered on this thread. + */ + std::set m_registeredClients; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_MAIN_THREAD_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaKeySession.h b/middleware/rialto-client/media/server/main/include/MediaKeySession.h new file mode 100644 index 000000000..513cbf9fd --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/MediaKeySession.h @@ -0,0 +1,218 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_KEY_SESSION_H_ +#define FIREBOLT_RIALTO_SERVER_MEDIA_KEY_SESSION_H_ + +#include "IMainThread.h" +#include "IMediaKeySession.h" +#include "IOcdmSessionClient.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IMediaKeySessionFactory factory class definition. + */ +class MediaKeySessionFactory : public IMediaKeySessionFactory +{ +public: + MediaKeySessionFactory() = default; + ~MediaKeySessionFactory() override = default; + + std::unique_ptr createMediaKeySession(const std::string &keySystem, int32_t keySessionId, + const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, + KeySessionType sessionType, + std::weak_ptr client, + bool isLDL) const override; +}; + +/** + * @brief The definition of the MediaKeySession. + */ +class MediaKeySession : public IMediaKeySession, public firebolt::rialto::wrappers::IOcdmSessionClient +{ +public: + /** + * @brief The constructor. + * + * @param[in] keySystem : The key system for this session. + * @param[in] keySessionId : The key session id for this session. + * @param[in] ocdmSystem : The ocdm system object to create the session on. + * @param[in] sessionType : The session type. + * @param[in] client : Client object for callbacks. + * @param[in] isLDL : Is this an LDL. + * @param[in] mainThreadFactory : The main thread factory. + */ + MediaKeySession(const std::string &keySystem, int32_t keySessionId, + const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, KeySessionType sessionType, + std::weak_ptr client, bool isLDL, + const std::shared_ptr &mainThreadFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaKeySession(); + + MediaKeyErrorStatus generateRequest(InitDataType initDataType, const std::vector &initData) override; + + MediaKeyErrorStatus loadSession() override; + + MediaKeyErrorStatus updateSession(const std::vector &responseData) override; + + MediaKeyErrorStatus decrypt(GstBuffer *encrypted, GstCaps *caps) override; + + MediaKeyErrorStatus closeKeySession() override; + + MediaKeyErrorStatus removeKeySession() override; + + MediaKeyErrorStatus getCdmKeySessionId(std::string &cdmKeySessionId) override; + + bool containsKey(const std::vector &keyId) override; + + MediaKeyErrorStatus setDrmHeader(const std::vector &requestData) override; + + MediaKeyErrorStatus getLastDrmError(uint32_t &errorCode) override; + + MediaKeyErrorStatus selectKeyId(const std::vector &keyId) override; + + bool isPlayreadyKeySystem() const override; + + void onProcessChallenge(const char url[], const uint8_t challenge[], const uint16_t challengeLength) override; + + void onKeyUpdated(const uint8_t keyId[], const uint8_t keyIdLength) override; + + void onAllKeysUpdated() override; + + void onError(const char message[]) override; + +private: + /** + * @brief KeySystem type of the MediaKeys. + */ + const std::string m_kKeySystem; + + /** + * @brief The key session id for this session. + */ + const int32_t m_kKeySessionId; + + /** + * @brief The key session type of this session. + */ + const KeySessionType m_kSessionType; + + /** + * @brief The media keys client object. + */ + std::weak_ptr m_mediaKeysClient; + + /** + * @brief The IOcdmSession instance. + */ + std::unique_ptr m_ocdmSession; + + /** + * @brief The mainThread object. + */ + std::shared_ptr m_mainThread; + + /** + * @brief Is the session LDL. + */ + const bool m_kIsLDL; + + /** + * @brief Is the ocdm session constructed. + */ + bool m_isSessionConstructed; + + /** + * @brief Is the ocdm session closed. + */ + bool m_isSessionClosed; + + /** + * @brief Set to true if generateRequest has complete and waiting for license response. + */ + std::atomic m_licenseRequested; + + /** + * @brief Store of the updated key statuses from a onKeyUpdated. + */ + KeyStatusVector m_updatedKeyStatuses; + + /** + * @brief This objects id registered on the main thread + */ + uint32_t m_mainThreadClientId; + + /** + * @brief Currently selected key id (PR specific) + */ + std::vector m_selectedKeyId; + + /** + * @brief Whether a Ocdm call is currently ongoing. + */ + bool m_ongoingOcdmOperation; + + /** + * @brief Whether Ocdm has returned an error via the onError callback. + */ + bool m_ocdmError; + + /** + * @brief Mutex protecting the ocdm error checking. + */ + std::mutex m_ocdmErrorMutex; + + /** + * @brief Drm header to be set once the session is constructed + */ + std::vector m_queuedDrmHeader; + + /** + * @brief Posts a getChallenge task onto the main thread. + * + * The challenge data is retrieved from ocdm and notified on a onLicenseRequest. + */ + void getChallenge(); + + /** + * @brief Initalises the ocdm error data which checks for onError callbacks. + */ + void initOcdmErrorChecking(); + + /** + * @brief Checks if onError has been received. + * + * @param[in] operationStr : Operation name for logging purposes. + * + * @retval True if an error was received. + */ + bool checkForOcdmErrors(const char *operationStr); +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_MEDIA_KEY_SESSION_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaKeysCapabilities.h b/middleware/rialto-client/media/server/main/include/MediaKeysCapabilities.h new file mode 100644 index 000000000..8c0117c66 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/MediaKeysCapabilities.h @@ -0,0 +1,90 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_CAPABILITIES_H_ + +#include "IMediaKeysCapabilities.h" +#include "IOcdm.h" +#include "IOcdmSystem.h" +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief IMediaKeysCapabilities factory class definition. + */ +class MediaKeysCapabilitiesFactory : public IMediaKeysCapabilitiesFactory +{ +public: + MediaKeysCapabilitiesFactory() = default; + ~MediaKeysCapabilitiesFactory() override = default; + + std::shared_ptr getMediaKeysCapabilities() const override; +}; + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::server +{ +/** + * @brief The definition of the MediaKeys. + */ +class MediaKeysCapabilities : public IMediaKeysCapabilities +{ +public: + /** + * @brief The constructor. + * + * @param[in] ocdmFactory : The ocdm factory. + * @param[in] ocdmSystemFactory : The ocdmSystem factory. + */ + MediaKeysCapabilities(std::shared_ptr ocdmFactory, + std::shared_ptr ocdmSystemFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaKeysCapabilities(); + + std::vector getSupportedKeySystems() override; + + bool supportsKeySystem(const std::string &keySystem) override; + + bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) override; + + bool isServerCertificateSupported(const std::string &keySystem) override; + +private: + /** + * @brief The IOcdm instance. + */ + std::shared_ptr m_ocdm; + + /** + * @brief The IOcdmSystem factory. + */ + std::shared_ptr m_ocdmSystemFactory; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaKeysCommon.h b/middleware/rialto-client/media/server/main/include/MediaKeysCommon.h new file mode 100644 index 000000000..70a26a534 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/MediaKeysCommon.h @@ -0,0 +1,49 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_COMMON_H_ +#define FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_COMMON_H_ + +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief Widevine key system string. + */ +const std::string kWidevineKeySystem{"com.widevine.alpha"}; + +/** + * @brief Playready key system string. + */ +const std::string kPlayreadyKeySystem{"com.microsoft.playready"}; + +/** + * @brief Netflix key system string. + */ +const std::string kNetflixKeySystem{"com.netflix.playready"}; + +/** + * @brief Supported key systems. + */ +const std::array kSupportedKeySystems{kWidevineKeySystem, kPlayreadyKeySystem, kNetflixKeySystem}; +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_COMMON_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaKeysServerInternal.h b/middleware/rialto-client/media/server/main/include/MediaKeysServerInternal.h new file mode 100644 index 000000000..327aabc5c --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/MediaKeysServerInternal.h @@ -0,0 +1,312 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_SERVER_INTERNAL_H_ + +#include "IMainThread.h" +#include "IMediaKeySession.h" +#include "IMediaKeysServerInternal.h" +#include "IOcdmSystem.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IMediaKeys factory class definition. + */ +class MediaKeysServerInternalFactory : public IMediaKeysServerInternalFactory +{ +public: + MediaKeysServerInternalFactory() = default; + ~MediaKeysServerInternalFactory() override = default; + + std::unique_ptr createMediaKeys(const std::string &keySystem) const override; + std::unique_ptr createMediaKeysServerInternal(const std::string &keySystem) const override; +}; + +}; // namespace firebolt::rialto::server + +namespace firebolt::rialto::server +{ +/** + * @brief The definition of the MediaKeysServerInternal. + */ +class MediaKeysServerInternal : public IMediaKeysServerInternal +{ +public: + struct MediaKeySessionUsage + { + std::unique_ptr mediaKeySession; + uint32_t bufCounter = 0; + bool shouldBeClosed = false; + bool shouldBeReleased = false; + }; + /** + * @brief The constructor. + * + * @param[in] keySystem : The key system for which to create a Media Keys instance. + * @param[in] mainThreadFactory : The main thread factory. + * @param[in] ocdmSystemFactory : The ocdm system factory. + * @param[in] mediaKeySessionFactory : The media key session factory. + * + */ + MediaKeysServerInternal(const std::string &keySystem, const std::shared_ptr &mainThreadFactory, + std::shared_ptr ocdmSystemFactory, + std::shared_ptr mediaKeySessionFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaKeysServerInternal(); + + MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) override; + + bool containsKey(int32_t keySessionId, const std::vector &keyId) override; + + MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, bool isLDL, + int32_t &keySessionId) override; + + MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) override; + + MediaKeyErrorStatus loadSession(int32_t keySessionId) override; + + MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) override; + + MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) override; + + MediaKeyErrorStatus closeKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus removeKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus deleteDrmStore() override; + + MediaKeyErrorStatus deleteKeyStore() override; + + MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) override; + + MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) override; + + MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) override; + + MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) override; + + MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) override; + + MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) override; + + MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) override; + + MediaKeyErrorStatus decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) override; + + MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) override; + + bool hasSession(int32_t keySessionId) const override; + + bool isPlayreadyKeySystem(int32_t keySessionId) const override; + + void incrementSessionIdUsageCounter(int32_t keySessionId) override; + void decrementSessionIdUsageCounter(int32_t keySessionId) override; + void ping(std::unique_ptr &&heartbeatHandler) override; + +private: + /** + * @brief The mainThread object. + */ + std::shared_ptr m_mainThread; + + /** + * @brief The factory for creating MediaKeySessions. + */ + std::shared_ptr m_mediaKeySessionFactory; + + /** + * @brief The IOcdmSystem instance. + */ + std::shared_ptr m_ocdmSystem; + + /** + * @brief Map containing created sessions. + */ + std::map m_mediaKeySessions; + + /** + * @brief KeySystem type of the MediaKeysServerInternal. + */ + const std::string m_keySystem; + + /** + * @brief This objects id registered on the main thread + */ + uint32_t m_mainThreadClientId; + + /** + * @brief Creates a session internally, only to be called on the main thread. + * + * @param[in] sessionType : The session type. + * @param[in] client : Client object for callbacks + * @param[in] isLDL : Is this an LDL + * @param[out] keySessionId: The key session id + * + * @retval an error status. + */ + MediaKeyErrorStatus createKeySessionInternal(KeySessionType sessionType, std::weak_ptr client, + bool isLDL, int32_t &keySessionId); + + /** + * @brief Generate internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] initDataType : The init data type. + * @param[in] initData : The init data. + * + * @retval an error status. + */ + MediaKeyErrorStatus generateRequestInternal(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData); + + /** + * @brief Load internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id for the session. + * + * @retval an error status. + */ + MediaKeyErrorStatus loadSessionInternal(int32_t keySessionId); + + /** + * @brief Update internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] responseData : The license response data. + * + * @retval an error status. + */ + MediaKeyErrorStatus updateSessionInternal(int32_t keySessionId, const std::vector &responseData); + + /** + * @brief Close a key session internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + MediaKeyErrorStatus closeKeySessionInternal(int32_t keySessionId); + + /** + * @brief Removes a key session internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + MediaKeyErrorStatus removeKeySessionInternal(int32_t keySessionId); + + /** + * @brief Get the key session id internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id for the session. + * @param[out] cdmKeySessionId : The internal CDM key session ID + * + * @retval an error status. + */ + MediaKeyErrorStatus getCdmKeySessionIdInternal(int32_t keySessionId, std::string &cdmKeySessionId); + + /** + * @brief Decrypt internally, only to be called on the main thread. + * + * @param[in] keySessionId : The session id for the session. + * @param[in] encrypted : Gstreamer buffer containing encrypted data and related meta data. If applicable, + * decrypted data will be stored here after this call returns. + * @param[in] caps : The gst caps of buffer. + * + * @retval an error status. + */ + MediaKeyErrorStatus decryptInternal(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps); + + /** + * @brief Selects the specified keyId for the key session internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] keyId : The key id to select. + * + * @retval an error status. + */ + MediaKeyErrorStatus selectKeyIdInternal(int32_t keySessionId, const std::vector &keyId); + + /** + * @brief Returns true if the Key Session object contains the specified key internally, + * only to be called on the main thread. + * + * @param[in] keySessionId : The key session id for the session. + * @param[in] keyId : The key id. + * + * @retval true if it contains the key. + */ + bool containsKeyInternal(int32_t keySessionId, const std::vector &keyId); + + /** + * @brief Set DRM Header for a key session internally, only to be called on the main thread. + * + * @param[in] keySessionId : The session id for the session. + * @param[in] requestData : The request data. + * + * @retval an error status. + */ + MediaKeyErrorStatus setDrmHeaderInternal(int32_t keySessionId, const std::vector &requestData); + + /** + * @brief Get the last cdm specific DRM error code internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id. + * @param[out] errorCode : the error code. + * + * @retval the return status value. + */ + MediaKeyErrorStatus getLastDrmErrorInternal(int32_t keySessionId, uint32_t &errorCode); + + /** + * @brief Checks, if key system of media key session is Playready internally, only to be called on the main thread. + * + * @param[in] keySessionId : The session id for the session. + * + * @retval true if key system is Playready + */ + bool isPlayreadyKeySystemInternal(int32_t keySessionId) const; + + /** + * @brief Releases a key session internally, only to be called on the main thread. + * + * @param[in] keySessionId : The key session id. + * + * @retval an error status. + */ + MediaKeyErrorStatus releaseKeySessionInternal(int32_t keySessionId); + + void incrementSessionIdUsageCounterInternal(int32_t keySessionId); + void decrementSessionIdUsageCounterInternal(int32_t keySessionId); +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaPipelineCapabilities.h b/middleware/rialto-client/media/server/main/include/MediaPipelineCapabilities.h new file mode 100644 index 000000000..e65ac91f7 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/MediaPipelineCapabilities.h @@ -0,0 +1,85 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_CAPABILITIES_H_ +#define FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_CAPABILITIES_H_ + +#include "IGstCapabilities.h" +#include "IMediaPipelineCapabilities.h" +#include +#include +#include + +namespace firebolt::rialto +{ +/** + * @brief IMediaPipelineCapabilities factory class definition. + */ +class MediaPipelineCapabilitiesFactory : public IMediaPipelineCapabilitiesFactory +{ +public: + MediaPipelineCapabilitiesFactory() = default; + ~MediaPipelineCapabilitiesFactory() override = default; + + std::unique_ptr createMediaPipelineCapabilities() const override; +}; + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::server +{ +/** + * @brief The definition of the MediaPipeline. + */ +class MediaPipelineCapabilities : public IMediaPipelineCapabilities +{ +public: + /** + * @brief The constructor. + * + * @param[in] gstCapabilitiesFactory : The gstreamer capabilities factory. + */ + explicit MediaPipelineCapabilities(std::shared_ptr gstCapabilitiesFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaPipelineCapabilities(); + + std::vector getSupportedMimeTypes(MediaSourceType sourceType) override; + bool isMimeTypeSupported(const std::string &mimeType) override; + std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) override; + bool isVideoMaster(bool &isVideoMaster) override; + +private: + /** + * @brief The gstreamer capabilities. + */ + std::unique_ptr m_gstCapabilities; + + /** + * @brief The gstreamer capabilities factory object. + */ + const std::shared_ptr m_kGstCapabilitiesFactory; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaPipelineServerInternal.h b/middleware/rialto-client/media/server/main/include/MediaPipelineServerInternal.h new file mode 100644 index 000000000..7379bad14 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/MediaPipelineServerInternal.h @@ -0,0 +1,720 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_SERVER_INTERNAL_H_ + +#include "DataReaderFactory.h" +#include "IActiveRequests.h" +#include "IGstGenericPlayer.h" +#include "IMainThread.h" +#include "IMediaPipelineServerInternal.h" +#include "ITimer.h" +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IMediaPipelineServerInternal factory class definition. + */ +class MediaPipelineServerInternalFactory : public server::IMediaPipelineServerInternalFactory +{ +public: + MediaPipelineServerInternalFactory() = default; + ~MediaPipelineServerInternalFactory() override = default; + + std::unique_ptr createMediaPipeline(std::weak_ptr client, + const VideoRequirements &videoRequirements) const override; + + std::unique_ptr createMediaPipelineServerInternal( + std::weak_ptr client, const VideoRequirements &videoRequirements, int sessionId, + const std::shared_ptr &shmBuffer, IDecryptionService &decryptionService) const override; + + /** + * @brief Create the generic media player factory object. + * + * @retval the generic media player factory instance or null on error. + */ + static std::shared_ptr createFactory(); +}; + +/** + * @brief The definition of the MediaPipelineServerInternal. + */ +class MediaPipelineServerInternal : public IMediaPipelineServerInternal, public IGstGenericPlayerClient +{ +public: + /** + * @brief The constructor. + * + * @param[in] client : The Rialto media player client. + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. + * @param[in] gstPlayerFactory : The gstreamer player factory. + * @param[in] sessionId : The session id + * @param[in] shmBuffer : The shared memory buffer + * @param[in] mainThreadFactory : The main thread factory. + * @param[in] dataReaderFactory : The data reader factory + * @param[in] activeRequests : The active requests + * @param[in] decryptionService : The decryption service + */ + MediaPipelineServerInternal(std::shared_ptr client, const VideoRequirements &videoRequirements, + const std::shared_ptr &gstPlayerFactory, int sessionId, + const std::shared_ptr &shmBuffer, + const std::shared_ptr &mainThreadFactory, + std::shared_ptr timerFactory, + std::unique_ptr &&dataReaderFactory, + std::unique_ptr &&activeRequests, IDecryptionService &decryptionService); + + /** + * @brief Virtual destructor. + */ + virtual ~MediaPipelineServerInternal(); + + bool load(MediaType type, const std::string &mimeType, const std::string &url) override; + + bool attachSource(const std::unique_ptr &source) override; + + bool removeSource(int32_t id) override; + + bool allSourcesAttached() override; + + bool play() override; + + bool pause() override; + + bool stop() override; + + bool setPlaybackRate(double rate) override; + + bool setPosition(int64_t position) override; + + bool getPosition(int64_t &position) override; + + bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override; + + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override; + + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; + + bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + + bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override; + + bool haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId) override; + + void ping(std::unique_ptr &&heartbeatHandler) override; + + bool renderFrame() override; + + bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override; + + bool getVolume(double ¤tVolume) override; + + bool setMute(std::int32_t sourceId, bool mute) override; + + bool getMute(std::int32_t sourceId, bool &mute) override; + + bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; + + bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; + + bool setLowLatency(bool lowLatency) override; + + bool setSync(bool sync) override; + + bool getSync(bool &sync) override; + + bool setSyncOff(bool syncOff) override; + + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; + + bool getStreamSyncMode(int32_t &streamSyncMode) override; + + bool flush(int32_t sourceId, bool resetTime, bool &async) override; + + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) override; + + bool setSubtitleOffset(int32_t sourceId, int64_t position) override; + + bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; + + bool setBufferingLimit(uint32_t limitBufferingMs) override; + + bool getBufferingLimit(uint32_t &limitBufferingMs) override; + + bool setUseBuffering(bool useBuffering) override; + + bool getUseBuffering(bool &useBuffering) override; + + bool switchSource(const std::unique_ptr &source) override; + + AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; + + std::weak_ptr getClient() override; + + void notifyPlaybackState(PlaybackState state) override; + + bool notifyNeedMediaData(MediaSourceType mediaSourceType) override; + + void notifyPosition(std::int64_t position) override; + + void notifyNetworkState(NetworkState state) override; + + void clearActiveRequestsCache() override; + + void invalidateActiveRequests(const MediaSourceType &type) override; + + void notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo) override; + + void notifyBufferUnderflow(MediaSourceType mediaSourceType) override; + + void notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error) override; + + void notifySourceFlushed(MediaSourceType mediaSourceType) override; + +protected: + /** + * @brief The media player client. + */ + std::shared_ptr m_mediaPipelineClient; + + /** + * @brief The mainThread object. + */ + std::shared_ptr m_mainThread; + + /** + * @brief The gstreamer player factory object. + */ + const std::shared_ptr m_kGstPlayerFactory; + + /** + * @brief The gstreamer player. + */ + std::unique_ptr m_gstPlayer; + + /** + * @brief The video decoder requirements for the MediaPipeline session. + */ + const VideoRequirements m_kVideoRequirements; + + /** + * @brief ID of a session represented by this MediaPipeline + */ + int m_sessionId; + + /** + * @brief Shared memory buffer + */ + std::shared_ptr m_shmBuffer; + + /** + * @brief DataReader factory + */ + std::unique_ptr m_dataReaderFactory; + + /** + * @brief Factory creating timers + */ + std::shared_ptr m_timerFactory; + + /** + * @brief Object containing all active NeedDataRequests + */ + std::unique_ptr m_activeRequests; + + /** + * @brief This objects id registered on the main thread + */ + uint32_t m_mainThreadClientId; + + /** + * @brief Decryption service + */ + IDecryptionService &m_decryptionService; + + /** + * @brief Current playback state + */ + PlaybackState m_currentPlaybackState; + + /** + * @brief Map containing scheduled need media data requests. + */ + std::unordered_map> m_needMediaDataTimers; + + /** + * @brief Currently attached sources + */ + std::map m_attachedSources; + + /** + * @brief Map to keep track of the count of MediaSourceStatus with the value NO_AVAILABLE_SAMPLES for each MediaSource + */ + std::map m_noAvailableSamplesCounter; + + /** + * @brief Flag used to check if allSourcesAttached was already called + */ + bool m_wasAllSourcesAttachedCalled; + + /** + * @brief Flag used to check if low latency is set for video source + */ + bool m_IsLowLatencyVideoPlayer{false}; + + /** + * @brief Flag used to check if low latency is set for audio source + */ + bool m_IsLowLatencyAudioPlayer{false}; + + /** + * @brief Map of flags used to check if Eos has been set on the media type for this playback + */ + std::map m_isMediaTypeEosMap; + + /** + * @brief Mutex to protect gstPlayer access in getPosition method + */ + std::shared_mutex m_getPositionMutex; + + /** + * @brief Load internally, only to be called on the main thread. + * + * @param[in] type : The media type. + * @param[in] mimeType : The MIME type. + * @param[in] url : The URL. + * + * @retval true on success. + */ + bool loadInternal(MediaType type, const std::string &mimeType, const std::string &url); + + /** + * @brief Attach source internally, only to be called on the main thread. + * + * @param[in] source : The source. + * + * @retval true on success. + */ + bool attachSourceInternal(const std::unique_ptr &source); + + /** + * @brief Remove source internally, only to be called on the main thread. + * + * @param[in] id : The source id. + * + * @retval true on success. + */ + bool removeSourceInternal(int32_t id); + + /** + * @brief Notify all sources attached internally, only to be called on the main thread. + * + * @retval true on success. + */ + bool allSourcesAttachedInternal(); + + /** + * @brief Play internally, only to be called on the main thread. + * + * @retval true on success. + */ + bool playInternal(); + + /** + * @brief Pause internally, only to be called on the main thread. + * + * @retval true on success. + */ + bool pauseInternal(); + + /** + * @brief Stop internally, only to be called on the main thread. + * + * @retval true on success. + */ + bool stopInternal(); + + /** + * @brief Set the playback rate internally, only to be called on the main thread. + * + * @param[in] rate : The playback rate. + * + * @retval true on success. + */ + bool setPlaybackRateInternal(double rate); + + /** + * @brief Set the position internally, only to be called on the main thread. + * + * @param[in] position : The playback position in nanoseconds. + * + * @retval true on success. + */ + bool setPositionInternal(int64_t position); + + /** + * @brief Sets the "Immediate Output" property for this source. + * + * This method is asynchronous + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] immediateOutput : The desired immediate output mode on the sink + * + * @retval true on success. + */ + bool setImmediateOutputInternal(int32_t sourceId, bool immediateOutput); + + /** + * @brief Gets the "Immediate Output" property for this source. + * + * This method is sychronous + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[out] immediateOutput : Returns the immediate output mode on the sink + * + * @retval true on success. + */ + bool getImmediateOutputInternal(int32_t sourceId, bool &immediateOutput); + + /** + * @brief Get stats for this source. + * + * This method is sychronous, it returns dropped frames and rendered frames + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[out] renderedFrames : The number of rendered frames + * @param[out] droppedFrames : The number of dropped frames + * + * @retval true on success. + */ + bool getStatsInternal(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames); + + /** + * @brief Set video window internally, only to be called on the main thread. + * + * @param[in] x : The x position in pixels. + * @param[in] y : The y position in pixels. + * @param[in] width : The width in pixels. + * @param[in] height : The height in pixels. + * + * @retval true on success. + */ + bool setVideoWindowInternal(uint32_t x, uint32_t y, uint32_t width, uint32_t height); + + /** + * @brief Have data internally, only to be called on the main thread. + * + * @param[in] status : The status + * @param[in] needDataRequestId : Need data request id + * + * @retval true on success. + */ + bool haveDataInternal(MediaSourceStatus status, uint32_t needDataRequestId); + + /** + * @brief Render frame internally, only to be called on the main thread. + * + * @retval true on success. + */ + bool renderFrameInternal(); + + /** + * @brief Have data internally, only to be called on the main thread. + * + * @param[in] status : The status + * @param[in] numFrames : The number of frames written. + * @param[in] needDataRequestId : Need data request id + * + * @retval true on success. + */ + bool haveDataInternal(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId); + + /** + * @brief Add segment internally, only to be called on the main thread. + * + * @param[in] needDataRequestId : The status + * @param[in] mediaSegment : The data returned. + * + * @retval status of adding segment + */ + AddSegmentStatus addSegmentInternal(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment); + + /** + * @brief Notify need media data internally, only to be called on the main thread. + * + * @param[in] mediaSourceType : The media source type. + */ + bool notifyNeedMediaDataInternal(MediaSourceType mediaSourceType); + + /** + * @brief Schedules resending of NeedMediaData after a short delay. Used when no segments were received in the + * haveData() call to prevent a storm of needData()/haveData() calls, only to be called on the main thread. + * + * @param[in] mediaSourceType : The media source type. + */ + void scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType); + + /** + * @brief Set the target volume level with a transition internally, only to be called on the main thread. + * + * @param[in] targetVolume : Target volume level (0.0 - 1.0) + * @param[in] volumeDuration : Duration of the volume transition in milliseconds + * @param[in] ease_type : Easing type for the volume transition + * + * @retval true on success, false otherwise + */ + bool setVolumeInternal(double targetVolume, uint32_t volumeDuration, EaseType easeType); + + /** + * @brief Get the current volume level internally, only to be called on the main thread. + * Fetches the current volume level for the pipeline. + * + * @param[out] currentVolume : Current volume level (range 0.0 - 1.0) + * + * @retval true on success, false otherwise + */ + bool getVolumeInternal(double ¤tVolume); + + /** + * @brief Set mute internally, only to be called on the main thread. + * + * @param[in] mute Desired mute state, true=muted, false=not muted + * + * @retval true on success false otherwise + */ + bool setMuteInternal(std::int32_t sourceId, bool mute); + + /** + * @brief Get mute internally, only to be called on the main thread. + * + * @param[out] mute Current mute state + * + * @retval true on success false otherwise + */ + bool getMuteInternal(std::int32_t sourceId, bool &mute); + + /** + * @brief Change Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + bool setTextTrackIdentifierInternal(const std::string &textTrackIdentifier); + + /** + * @brief Get Text Track Identifier + * + * @param[in] textTrackIdentifier Text track identifier of subtitle stream + * + * @retval true on success false otherwise + */ + bool getTextTrackIdentifierInternal(std::string &textTrackIdentifier); + + /** + * @brief Set low latency internally, only to be called on the main thread. + * + * @param[in] lowLatency : The low latency value to set. + * + * @retval true on success false otherwise + */ + bool setLowLatencyInternal(bool lowLatency); + + /** + * @brief Set sync internally, only to be called on the main thread. + * + * @param[in] sync : The sync value to set. + * + * @retval true on success false otherwise + */ + bool setSyncInternal(bool sync); + + /** + * @brief Get sync internally, only to be called on the main thread. + * + * @param[out] sync : Current sync value. + * + * @retval true on success false otherwise + */ + bool getSyncInternal(bool &sync); + + /** + * @brief Set sync off internally, only to be called on the main thread. + * + * @param[in] syncOff : The sync off value to set. + * + * @retval true on success false otherwise + */ + bool setSyncOffInternal(bool syncOff); + + /** + * @brief Set stream sync mode internally, only to be called on the main thread. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] streamSyncMode : The stream sync mode value to set. + * + * @retval true on success false otherwise + */ + bool setStreamSyncModeInternal(int32_t sourceId, int32_t streamSyncMode); + + /** + * @brief Get stream sync mode internally, only to be called on the main thread. + * + * @param[out] streamSyncMode : Current stream sync mode value. + * + * @retval true on success false otherwise + */ + bool getStreamSyncModeInternal(int32_t &streamSyncMode); + + /** + * @brief Checks if MediaPipeline threads are not deadlocked internally + * + * @param[out] heartbeatHandler : The heartbeat handler instance + */ + void pingInternal(std::unique_ptr &&heartbeatHandler); + + /** + * @brief Flushes a source. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] resetTime : True if time should be reset + * @param[out] async : True if flushed source is asynchronous (will preroll after flush) + * + * @retval true on success. + */ + bool flushInternal(int32_t sourceId, bool resetTime, bool &async); + + /** + * @brief Set the source position in nanoseconds. + * + * This method sets the start position for a source. + * + * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() + * @param[in] position : The position in nanoseconds. + * @param[in] resetTime : True if time should be reset + * @param[in] appliedRate : The applied rate after seek + * @param[in] stopPosition : The position of last pushed buffer + * + * @retval true on success. + */ + bool setSourcePositionInternal(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition); + + /** + * @brief Set subtitle offset for a subtitle source. + * + * This method is used to set the subtitle offset for a subtitle source. + * + * @param[in] sourceId : The id of the subtitle source + * @param[in] position : The subtitle offset position in nanoseconds + * + * @retval true on success. + */ + bool setSubtitleOffsetInternal(int32_t sourceId, int64_t position); + + /** + * @brief Process audio gap + * + * This method handles audio gap in order to avoid audio pops during transitions. + * + * @param[in] position : Audio pts fade position + * @param[in] duration : Audio pts fade duration + * @param[in] discontinuityGap : Audio discontinuity gap + * @param[in] audioAac : True if audio codec is AAC + * + * @retval true on success. + */ + bool processAudioGapInternal(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac); + + /** + * @brief Set buffering limit + * + * This method enables/disables limit buffering and sets millisecond threshold used. + * Use kInvalidLimitBuffering to disable limit buffering + * + * @param[in] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + bool setBufferingLimitInternal(uint32_t limitBufferingMs); + + /** + * @brief Get buffering limit + * + * This method returns current value of buffering limit in milliseconds + * Method will return kInvalidLimitBuffering limit buffering is disabled + * + * @param[out] limitBufferingMs : buffering limit in ms + * + * @retval true on success. + */ + bool getBufferingLimitInternal(uint32_t &limitBufferingMs); + + /** + * @brief Enables/disables the buffering option + * + * This method enables the buffering option so that BUFFERING messages are + * emitted based on low-/high-percent thresholds. + * + * @param[in] useBuffering : true if buffering option enabled. + * + * @retval true on success. + */ + bool setUseBufferingInternal(bool useBuffering); + + /** + * @brief Checks, if buffering is enabled + * + * This method returns true, if buffering is enabled + * + * @param[out] useBuffering : true if buffering option is enabled. + * + * @retval true on success. + */ + bool getUseBufferingInternal(bool &useBuffering); + + /** + * @brief Switches a source. + * + * @param[in] mediaSource : The media source. + * + */ + bool switchSourceInternal(const std::unique_ptr &source); + + /** + * @brief Returns how long should we wait to send next NeedMediaData + * if rialto client returns NO_AVAILABLE_SAMPLES + * + * @param[in] mediaSourceType : The media source type. + * + * @retval NeedMediaData timeout + */ + std::chrono::milliseconds getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/include/NeedMediaData.h b/middleware/rialto-client/media/server/main/include/NeedMediaData.h new file mode 100644 index 000000000..3345b49f8 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/NeedMediaData.h @@ -0,0 +1,54 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_NEED_MEDIA_DATA_H_ +#define FIREBOLT_RIALTO_SERVER_NEED_MEDIA_DATA_H_ + +#include "IActiveRequests.h" +#include "IMediaPipelineClient.h" +#include "ISharedMemoryBuffer.h" +#include "MediaCommon.h" +#include +#include + +namespace firebolt::rialto::server +{ +class NeedMediaData +{ +public: + NeedMediaData(std::weak_ptr client, IActiveRequests &activeRequests, + const ISharedMemoryBuffer &shmBuffer, int sessionId, MediaSourceType mediaSourceType, + std::int32_t sourceId, PlaybackState currentPlaybackState); + ~NeedMediaData() = default; + + bool send() const; + +private: + std::weak_ptr m_client; + IActiveRequests &m_activeRequests; + MediaSourceType m_mediaSourceType; + std::uint32_t m_frameCount; + std::int32_t m_sourceId; + std::uint32_t m_maxMediaBytes; + std::shared_ptr m_shmInfo; + bool m_isValid; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_NEED_MEDIA_DATA_H_ diff --git a/middleware/rialto-client/media/server/main/include/SharedMemoryBuffer.h b/middleware/rialto-client/media/server/main/include/SharedMemoryBuffer.h new file mode 100644 index 000000000..5f43a6f8d --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/SharedMemoryBuffer.h @@ -0,0 +1,87 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SHARED_MEMORY_BUFFER_H_ +#define FIREBOLT_RIALTO_SERVER_SHARED_MEMORY_BUFFER_H_ + +#include "ISharedMemoryBuffer.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +class SharedMemoryBufferFactory : public ISharedMemoryBufferFactory +{ +public: + ~SharedMemoryBufferFactory() override = default; + std::shared_ptr createSharedMemoryBuffer(unsigned numOfPlaybacks, + unsigned numOfWebAudioPlayers) const override; +}; + +class SharedMemoryBuffer : public ISharedMemoryBuffer +{ +public: + explicit SharedMemoryBuffer(unsigned numOfPlaybacks, unsigned numOfWebAudioPlayers); + ~SharedMemoryBuffer() override; + SharedMemoryBuffer(const SharedMemoryBuffer &) = delete; + SharedMemoryBuffer(SharedMemoryBuffer &&) = delete; + SharedMemoryBuffer &operator=(const SharedMemoryBuffer &) = delete; + SharedMemoryBuffer &operator=(SharedMemoryBuffer &&) = delete; + + bool mapPartition(MediaPlaybackType playbackType, int id) override; + bool unmapPartition(MediaPlaybackType playbackType, int id) override; + + bool clearData(MediaPlaybackType playbackType, int id, const MediaSourceType &mediaSourceType) const override; + + std::uint32_t getDataOffset(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const override; + std::uint32_t getMaxDataLen(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const override; + std::uint8_t *getDataPtr(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const override; + + int getFd() const override; + std::uint32_t getSize() const override; + std::uint8_t *getBuffer() const override; + + struct Partition + { + int id; + std::uint32_t dataBufferAudioLen; + std::uint32_t dataBufferVideoLen; + std::uint32_t dataBufferSubtitleLen; + }; + +private: + size_t calculateBufferSize() const; + bool getDataPtrForPartition(MediaPlaybackType playbackType, int id, std::uint8_t **ptr) const; + const std::vector *getPlaybackTypePartition(MediaPlaybackType playbackType) const; + std::vector *getPlaybackTypePartition(MediaPlaybackType playbackType); + +private: + std::vector m_genericPartitions; + std::vector m_webAudioPartitions; + std::uint32_t m_dataBufferLen; + int m_dataBufferFd; + std::uint8_t *m_dataBuffer; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_SHARED_MEMORY_BUFFER_H_ diff --git a/middleware/rialto-client/media/server/main/include/ShmUtils.h b/middleware/rialto-client/media/server/main/include/ShmUtils.h new file mode 100644 index 000000000..34f722fb6 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/ShmUtils.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SHM_UTILS_H_ +#define FIREBOLT_RIALTO_SERVER_SHM_UTILS_H_ + +#include "ShmCommon.h" +#include + +namespace firebolt::rialto::server +{ +constexpr std::uint32_t kPrerollNumFrames{3}; +constexpr std::uint32_t kMaxFrames{24}; +constexpr std::uint32_t getMaxMetadataBytes() +{ + // The Rialto Server must size the metadata regions to be at least the following size: + // 4 bytes version + max_frames_to_request * (maximum metadata struct size for stream type & + // supported metadata format versions) + + // Metadata V2 contains version only, so maximum metadata size is size of MetadataV1 + std::uint32_t maxMetadataStructSize = common::METADATA_V1_SIZE_PER_FRAME_BYTES; + return common::VERSION_SIZE_BYTES + kMaxFrames * maxMetadataStructSize; +} +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_SHM_UTILS_H_ diff --git a/middleware/rialto-client/media/server/main/include/TextTrackAccessor.h b/middleware/rialto-client/media/server/main/include/TextTrackAccessor.h new file mode 100644 index 000000000..98cce9db5 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/TextTrackAccessor.h @@ -0,0 +1,70 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TEXT_TRACK_ACCESSOR_H_ +#define FIREBOLT_RIALTO_SERVER_TEXT_TRACK_ACCESSOR_H_ + +#include "ITextTrackAccessor.h" +#include "ITextTrackPluginWrapper.h" +#include "ITextTrackWrapper.h" +#include "IThunderWrapper.h" +#include "RialtoServerLogging.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class TextTrackAccessorFactory : public ITextTrackAccessorFactory +{ +public: + std::shared_ptr getTextTrackAccessor() const override; +}; + +class TextTrackAccessor : public ITextTrackAccessor +{ +public: + TextTrackAccessor(const std::shared_ptr &textTrackPluginWrapper, + const std::shared_ptr &thunderWrapper); + ~TextTrackAccessor() override; + std::optional openSession(const std::string &displayName) override; + bool closeSession(uint32_t sessionId) override; + bool resetSession(uint32_t sessionId) override; + bool pause(uint32_t sessionId) override; + bool play(uint32_t sessionId) override; + bool mute(uint32_t sessionId, bool mute) override; + bool setPosition(uint32_t sessionId, uint64_t mediaTimestampMs) override; + bool sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs) override; + bool setSessionWebVTTSelection(uint32_t sessionId) override; + bool setSessionTTMLSelection(uint32_t sessionId) override; + bool setSessionCCSelection(uint32_t sessionId, const std::string &service) override; + bool associateVideoDecoder(uint32_t sessionId, const std::string &videoDecoder) override; + +private: + bool createTextTrackControlInterface(); + + std::shared_ptr m_textTrackPluginWrapper; + std::shared_ptr m_thunderWrapper; + std::shared_ptr m_textTrackWrapper; +}; + +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_TEXT_TRACK_ACCESSOR_H_ diff --git a/middleware/rialto-client/media/server/main/include/TextTrackSession.h b/middleware/rialto-client/media/server/main/include/TextTrackSession.h new file mode 100644 index 000000000..16be2c6e9 --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/TextTrackSession.h @@ -0,0 +1,62 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_TEXT_TRACK_SESSION_H_ +#define FIREBOLT_RIALTO_SERVER_TEXT_TRACK_SESSION_H_ + +#include "ITextTrackAccessor.h" +#include "ITextTrackSession.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +class TextTrackSessionFactory : public ITextTrackSessionFactory +{ +public: + std::unique_ptr createTextTrackSession(const std::string &display) const override; +}; + +class TextTrackSession : public ITextTrackSession +{ +public: + TextTrackSession(const std::string &displayName, const ITextTrackAccessorFactory &textTrackAccessorFactory); + ~TextTrackSession() override; + bool resetSession(bool isMuted) override; + bool pause() override; + bool play() override; + bool mute(bool mute) override; + bool setPosition(uint64_t mediaTimestampMs) override; + bool sendData(const std::string &data, int64_t displayOffsetMs = 0) override; + bool setSessionWebVTTSelection() override; + bool setSessionTTMLSelection() override; + bool setSessionCCSelection(const std::string &service) override; + bool associateVideoDecoder(uint64_t decoderId) override; + bool isClosedCaptions() const override; + +private: + std::shared_ptr m_textTrackAccessor; + ITextTrackAccessor::DataType m_dataType{ITextTrackAccessor::DataType::UNKNOWN}; + uint32_t m_sessionId{0}; + std::optional m_ccService; + std::optional m_videoDecoderId; +}; +} // namespace firebolt::rialto::server +#endif // FIREBOLT_RIALTO_SERVER_TEXT_TRACK_SESSION_H_ diff --git a/middleware/rialto-client/media/server/main/include/WebAudioPlayerServerInternal.h b/middleware/rialto-client/media/server/main/include/WebAudioPlayerServerInternal.h new file mode 100644 index 000000000..c4755966e --- /dev/null +++ b/middleware/rialto-client/media/server/main/include/WebAudioPlayerServerInternal.h @@ -0,0 +1,257 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ + +#include "IGstWebAudioPlayer.h" +#include "IMainThread.h" +#include "ITimer.h" +#include "IWebAudioPlayer.h" +#include "IWebAudioPlayerServerInternal.h" + +#include +#include +#include + +namespace firebolt::rialto::server +{ +/** + * @brief IWebAudioPlayer factory class definition. + */ +class WebAudioPlayerServerInternalFactory : public IWebAudioPlayerServerInternalFactory +{ +public: + WebAudioPlayerServerInternalFactory() = default; + ~WebAudioPlayerServerInternalFactory() override = default; + + std::unique_ptr createWebAudioPlayer(std::weak_ptr client, + const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config) const override; + + std::unique_ptr createWebAudioPlayerServerInternal( + std::weak_ptr client, const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config, const std::shared_ptr &shmBuffer, int handle, + const std::shared_ptr &mainThreadFactory, + const std::shared_ptr &gstPlayerFactory, + std::weak_ptr timerFactory) const override; +}; + +/** + * @brief The definition of the WebAudioPlayerServerInternal. + */ +class WebAudioPlayerServerInternal : public IWebAudioPlayerServerInternal, public IGstWebAudioPlayerClient +{ +public: + /** + * @brief The constructor. + * + * @param[in] client : The Web Audio Player client. + * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM). + * @param[in] priority : Priority value for this pipeline. + * @param[in] config : Additional type dependent configuration data or nullptr. + * @param[in] shmBuffer : The shared memory buffer. + * @param[in] handle : The handle for this WebAudioPlayer. + * @param[in] mainThreadFactory : The main thread factory. + * @param[in] gstPlayerFactory : The gstreamer player factory. + * @param[in] timerFactory : The timer factory. + */ + WebAudioPlayerServerInternal(std::weak_ptr client, const std::string &audioMimeType, + const uint32_t priority, std::weak_ptr config, + const std::shared_ptr &shmBuffer, int handle, + const std::shared_ptr &mainThreadFactory, + const std::shared_ptr &gstPlayerFactory, + std::weak_ptr timerFactory); + + /** + * @brief Virtual destructor. + */ + virtual ~WebAudioPlayerServerInternal(); + + bool play() override; + + bool pause() override; + + bool setEos() override; + + bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) override; + + bool getBufferDelay(uint32_t &delayFrames) override; + + bool writeBuffer(const uint32_t numberOfFrames, void *data) override; + + bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override; + + bool setVolume(double volume) override; + + bool getVolume(double &volume) override; + + std::weak_ptr getClient() override; + + void notifyState(WebAudioPlayerState state) override; + + void ping(std::unique_ptr &&heartbeatHandler) override; + +protected: + /** + * @brief The web audio player client. + */ + std::shared_ptr m_webAudioPlayerClient; + + /** + * @brief Shared memory buffer. + */ + std::shared_ptr m_shmBuffer; + + /** + * @brief The mainThread object. + */ + std::shared_ptr m_mainThread; + + /** + * @brief This objects id registered on the main thread. + */ + uint32_t m_mainThreadClientId; + + /** + * @brief This priority of the WebAudioPlayer object. + */ + const uint32_t m_priority; + + /** + * @brief The gstreamer player. + */ + std::unique_ptr m_gstPlayer; + + /** + * @brief The id of the shared memory partition. + */ + const int m_shmId; + + /** + * @brief Pointer to the start of the shared buffer. + */ + uint8_t *m_shmPtr; + + /** + * @brief Offset of the web audio partition relative to the start of the shared memory. + */ + uint32_t m_partitionOffset; + + /** + * @brief Length of the shared buffer partition. + */ + uint32_t m_maxDataLength; + + /** + * @brief The details of the free space in the shared buffer partition. + */ + WebAudioShmInfo m_availableBuffer; + + /** + * @brief True if a writeBuffer call is expected. + */ + bool m_expectWriteBuffer; + + /** + * @brief Factory for creating timers. + */ + std::shared_ptr m_timerFactory; + + /** + * @brief Timer set to write data to gstreamer. + */ + std::unique_ptr m_writeDataTimer; + + /** + * @brief The bytes per frame for this audio playback. + */ + uint32_t m_bytesPerFrame; + + /** + * @brief Whether EOS has been requested at the end of the buffer. + */ + bool m_isEosRequested; + + /** + * @brief Initalises the WebAudioPlayer. + * + * @param[in] audioMimeType : The audio encoding format. + * @param[in] config : Additional type dependent configuration data or nullptr. + * @param[in] gstPlayerFactory : The gstreamer player factory. + * + * @retval true on success. + */ + bool initWebAudioPlayerInternal(const std::string &audioMimeType, std::weak_ptr config, + const std::shared_ptr &gstPlayerFactory); + + /** + * @brief Initalises the GstWebAudioPlayer. + * + * @param[in] audioMimeType : The audio encoding format. + * @param[in] config : Additional type dependent configuration data or nullptr. + * @param[in] gstPlayerFactory : The gstreamer player factory. + * + * @retval true on success. + */ + bool initGstWebAudioPlayer(const std::string &audioMimeType, std::weak_ptr config, + const std::shared_ptr &gstPlayerFactory); + + /** + * @brief Write audio frames internally, only to be called on the main thread. + * + * @param[in] numberOfFrames : Number of frames of audio in the shared memory. + * + * @retval true on success. + */ + bool writeBufferInternal(const uint32_t numberOfFrames); + + /** + * @brief Write the data that has been stored in the shared memory to gstreamer. + * + * Uses the available buffer variable to calculate the data to pass to gstreamer for writting. + * + * @retval true if all stored data was written to gstreamer. + */ + bool writeStoredBuffers(); + + /** + * @brief Update the available buffer variable with the new bytes written to the shared memory and gstreamer. + * + * @param[in] bytesWrittenToShm : Number of bytes newly written to the shared memory. + * @param[in] bytesWrittenToGst : Number of bytes newly written to gstreamer. + */ + void updateAvailableBuffer(uint32_t bytesWrittenToShm, uint32_t bytesWrittenToGst); + + /** + * @brief Handles the timeout of the write data timer. + */ + void handleWriteDataTimer(); + + /** + * @brief Gets the number of queued frames in the shared memory. + * + * @retval The number of frames queued. + */ + uint32_t getQueuedFramesInShm(); +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IAckSender.h b/middleware/rialto-client/media/server/main/interface/IAckSender.h new file mode 100644 index 000000000..ca0754f8c --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IAckSender.h @@ -0,0 +1,33 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_ACK_SENDER_H_ +#define FIREBOLT_RIALTO_SERVER_I_ACK_SENDER_H_ + +namespace firebolt::rialto::server +{ +class IAckSender +{ +public: + virtual ~IAckSender() = default; + virtual void send(int id, bool success) const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_ACK_SENDER_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IControlClientServerInternal.h b/middleware/rialto-client/media/server/main/interface/IControlClientServerInternal.h new file mode 100644 index 000000000..7f02adcec --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IControlClientServerInternal.h @@ -0,0 +1,64 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_CONTROL_CLIENT_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_I_CONTROL_CLIENT_SERVER_INTERNAL_H_ + +/** + * @file IControlClientServerInternal.h + * + * The definition of the IControlClientServerInternal interface. + * + * This file comprises the definition of the IControlClientServerInternal abstract + * class. This is the API by which a IControl implementation will + * pass notifications to its client. + */ + +#include "IControlClient.h" + +namespace firebolt::rialto::server +{ +/** + * @brief The Rialto control client server internal interface. + * + * This is server internal Rialto control client abstract base class. It should be + * implemented by any object that sends notification about rialto server state to its client + * + */ + +class IControlClientServerInternal : public IControlClient +{ +public: + /** + * @brief Virtual destructor + */ + virtual ~IControlClientServerInternal() = default; + + /** + * @brief Ping notification for checking system health + * The client should perform any health checks then respond with + * a call to ack(id) if system healthy + * + * @param[in] id : Unique id, should be passed to corresponding ack call + */ + virtual void ping(uint32_t id) = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_CONTROL_CLIENT_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IControlServerInternal.h b/middleware/rialto-client/media/server/main/interface/IControlServerInternal.h new file mode 100644 index 000000000..965f7826c --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IControlServerInternal.h @@ -0,0 +1,95 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_CONTROL_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_I_CONTROL_SERVER_INTERNAL_H_ + +/** + * @file IControlServerInternal.h + * + * The definition of the IControlServerInternal interface. + * + * This interface defines the server internal API of Rialto for controlling rialto clients. + */ + +#include "IControl.h" +#include "IControlClientServerInternal.h" +#include "IHeartbeatHandler.h" +#include + +namespace firebolt::rialto::server +{ +class IControlServerInternal; +class IControlServerInternalFactory : public IControlFactory +{ +public: + IControlServerInternalFactory() = default; + ~IControlServerInternalFactory() override = default; + + /** + * @brief Create a IControlServerInternalFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IControlServerInternal factory method, returns a concrete implementation of IControlServerInternal + * + * @param[in] id : Control id + * @param[in] client : Client object for callbacks + * + * @retval the new IControlServerInternal instance or null on error. + */ + virtual std::shared_ptr + createControlServerInternal(int id, const std::shared_ptr &client) const = 0; +}; + +class IControlServerInternal : public IControl +{ +public: + IControlServerInternal() = default; + virtual ~IControlServerInternal() = default; + + /** + * @brief Informs connected rialto client about rialto server state change + * + * @param[in] state: The new application state. + */ + virtual void setApplicationState(const ApplicationState &state) = 0; + + /** + * @brief Acknowledgement of a received ping request + * + * @param[in] id : id received in ping notification + */ + virtual void ack(int32_t id) = 0; + + /** + * @brief Ping notification for checking system health + * The client should perform any health checks then respond with + * a call to ack(id) if system healthy + * + * @param[in] heartbeatHandler : Handler of current heartbeat request + */ + virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_CONTROL_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IDataReader.h b/middleware/rialto-client/media/server/main/interface/IDataReader.h new file mode 100644 index 000000000..44666897d --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IDataReader.h @@ -0,0 +1,35 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_DATA_READER_H_ +#define FIREBOLT_RIALTO_SERVER_I_DATA_READER_H_ + +#include "IMediaPipeline.h" + +namespace firebolt::rialto::server +{ +class IDataReader +{ +public: + virtual ~IDataReader() = default; + virtual IMediaPipeline::MediaSegmentVector readData() const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_DATA_READER_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IDecryptionService.h b/middleware/rialto-client/media/server/main/interface/IDecryptionService.h new file mode 100644 index 000000000..443147b1c --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IDecryptionService.h @@ -0,0 +1,42 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_DECRYPTION_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_I_DECRYPTION_SERVICE_H_ + +#include "MediaCommon.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IDecryptionService +{ +public: + virtual ~IDecryptionService() = default; + virtual MediaKeyErrorStatus decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) = 0; + virtual bool isPlayreadyKeySystem(int32_t keySessionId) = 0; + virtual MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) = 0; + virtual void incrementSessionIdUsageCounter(int32_t keySessionId) = 0; + virtual void decrementSessionIdUsageCounter(int32_t keySessionId) = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_DECRYPTION_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IHeartbeatHandler.h b/middleware/rialto-client/media/server/main/interface/IHeartbeatHandler.h new file mode 100644 index 000000000..08956f8c4 --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IHeartbeatHandler.h @@ -0,0 +1,51 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_HANDLER_H_ +#define FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_HANDLER_H_ + +#include + +/** + * @file IHeartbeatHandler.h + * + * The definition of the IHeartbeatHandler interface. + * + * This interface defines the handler of single ping/ack action. + * + */ + +namespace firebolt::rialto::server +{ +class IHeartbeatHandler +{ +public: + IHeartbeatHandler() = default; + IHeartbeatHandler(const IHeartbeatHandler &) = delete; + IHeartbeatHandler(IHeartbeatHandler &&) = delete; + IHeartbeatHandler &operator=(const IHeartbeatHandler &) = delete; + IHeartbeatHandler &operator=(IHeartbeatHandler &&) = delete; + virtual ~IHeartbeatHandler() = default; + + virtual void error() = 0; + virtual std::int32_t id() const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_HANDLER_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IHeartbeatProcedure.h b/middleware/rialto-client/media/server/main/interface/IHeartbeatProcedure.h new file mode 100644 index 000000000..967feeaf0 --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IHeartbeatProcedure.h @@ -0,0 +1,57 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_PROCEDURE_H_ +#define FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_PROCEDURE_H_ + +/** + * @file IHeartbeatHandler.h + * + * The definition of the IHeartbeatProcedure interface. + * + * This interface defines the ping/ack procedure sent for each client. + * + */ + +#include "IAckSender.h" +#include "IHeartbeatHandler.h" +#include + +namespace firebolt::rialto::server +{ +class IHeartbeatProcedure; +class IHeartbeatProcedureFactory +{ +public: + virtual ~IHeartbeatProcedureFactory() = default; + + static std::unique_ptr createFactory(); + virtual std::shared_ptr createHeartbeatProcedure(const std::shared_ptr &ackSender, + std::int32_t pingId) const = 0; +}; + +class IHeartbeatProcedure +{ +public: + virtual ~IHeartbeatProcedure() = default; + virtual std::unique_ptr createHandler() = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_PROCEDURE_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IMainThread.h b/middleware/rialto-client/media/server/main/interface/IMainThread.h new file mode 100644 index 000000000..530af2864 --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IMainThread.h @@ -0,0 +1,117 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_MAIN_THREAD_H_ +#define FIREBOLT_RIALTO_SERVER_I_MAIN_THREAD_H_ + +#include "IMainThread.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IMainThread; + +/** + * @brief IMainThread factory class, gets the concrete implementation of IMainThread + */ +class IMainThreadFactory +{ +public: + IMainThreadFactory() = default; + virtual ~IMainThreadFactory() = default; + + /** + * @brief Create a IMainThreadFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMainThread factory method, gets a concrete implementation of IMainThread + * + * @retval the main thread instance or null on error. + */ + virtual std::shared_ptr getMainThread() const = 0; +}; + +/** + * @brief The definition of the IMainThread interface. + */ +class IMainThread +{ +public: + using Task = std::function; + + IMainThread() = default; + virtual ~IMainThread() = default; + + IMainThread(const IMainThread &) = delete; + IMainThread(IMainThread &&) = delete; + IMainThread &operator=(const IMainThread &) = delete; + IMainThread &operator=(IMainThread &&) = delete; + + /** + * @brief Register a client on the main thread. + * + * Required by clients who want to enqueue tasks on the main thread. + * + * @retval The registered client id. + */ + virtual int32_t registerClient() = 0; + + /** + * @brief Unregister a client on the main thread. + * + * Should be called on the main thread. + * After been called the client will no longer be able to enqueue tasks. + * + * @param[in] clientId : The id of the registered client. + */ + virtual void unregisterClient(uint32_t clientId) = 0; + + /** + * @brief Enqueue a task on the main thread and return. + * + * @param[in] clientId : The id of the registered client. + * @param[in] task : Task to queue. + */ + virtual void enqueueTask(uint32_t clientId, Task task) = 0; + + /** + * @brief Enqueue a task on the main thread and wait for it to finish before returning. + * + * @param[in] clientId : The id of the registered client. + * @param[in] task : Task to queue. + */ + virtual void enqueueTaskAndWait(uint32_t clientId, Task task) = 0; + + /** + * @brief Enqueue a priority task on the main thread and wait for it to finish before returning. + * + * @param[in] clientId : The id of the registered client. + * @param[in] task : Task to queue. + */ + virtual void enqueuePriorityTaskAndWait(uint32_t clientId, Task task) = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_MAIN_THREAD_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IMediaKeysServerInternal.h b/middleware/rialto-client/media/server/main/interface/IMediaKeysServerInternal.h new file mode 100644 index 000000000..909c9973a --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IMediaKeysServerInternal.h @@ -0,0 +1,136 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_MEDIA_KEYS_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_I_MEDIA_KEYS_SERVER_INTERNAL_H_ + +/** + * @file IMediaKeysServerInternal.h + * + * The definition of the IMediaKeys interface. + * + * This interface defines the server internal API of Rialto for EME decryption of AV content. + */ + +#include "IHeartbeatHandler.h" +#include "IMediaKeys.h" +#include "MediaCommon.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server +{ +class IMediaKeysServerInternal; +/** + * @brief IMediaKeysServerInternal factory class, returns a concrete implementation of IMediaKeysServerInternal + */ +class IMediaKeysServerInternalFactory : public IMediaKeysFactory +{ +public: + IMediaKeysServerInternalFactory() = default; + ~IMediaKeysServerInternalFactory() override = default; + + /** + * @brief Create a IMediaKeysServerInternalFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMediaKeysServerInternal factory method, returns a concrete implementation of IMediaKeysServerInternal + * + * @param[in] keySystem : The key system for which to create a Media Keys instance + * + * @retval the new media keys instance or null on error. + */ + virtual std::unique_ptr createMediaKeysServerInternal(const std::string &keySystem) const = 0; +}; + +/** + * @brief The definition of the IMediaKeysServerInternal interface. + * + * This interface defines the public API of Rialto for EME decryption of AV content + * which should be implemented by Rialto Server. + */ +class IMediaKeysServerInternal : public IMediaKeys +{ +public: + /** + * @brief Decrypts the buffer. + * + * Encryption metadata shall be attached to the encrypted buffer as protection meta prior to this call. + * + * @param[in] keySessionId : The session id for the session. + * @param[in] encrypted : Gstreamer buffer containing encrypted data and related meta data. If applicable, + * decrypted data will be stored here after this call returns. + * @param[in] caps : The gst caps of buffer. + * + * @retval an error status. + */ + virtual MediaKeyErrorStatus decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) = 0; + + /** + * @brief Checks if session with given id is handled by this MediaKeys instance + * + * @param[in] keySessionId : The session id for the session. + * + * @retval true if session is handled by this MediaKeys instance + */ + virtual bool hasSession(int32_t keySessionId) const = 0; + + /** + * @brief Checks, if key system of media key session is Playready. + * + * @param[in] keySessionId : The session id for the session. + * + * @retval true if key system is Playready + */ + virtual bool isPlayreadyKeySystem(int32_t keySessionId) const = 0; + + /** + * @brief Increments number of buffers using keySessionId + * + * @param[in] keySessionId : The session id for the session. + * + */ + + virtual void incrementSessionIdUsageCounter(int32_t keySessionId) = 0; + /** + * @brief Decrements number of buffers using keySessionId + * + * @param[in] keySessionId : The session id for the session. + * + */ + virtual void decrementSessionIdUsageCounter(int32_t keySessionId) = 0; + + /** + * @brief Checks, if MediaKeys main thread is not deadlocked + * + * @param[in] heartbeatHandler : The heartbeat handler instance. + * + */ + virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_MEDIA_KEYS_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IMediaPipelineServerInternal.h b/middleware/rialto-client/media/server/main/interface/IMediaPipelineServerInternal.h new file mode 100644 index 000000000..71b125d8f --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IMediaPipelineServerInternal.h @@ -0,0 +1,112 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_MEDIA_PIPELINE_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_I_MEDIA_PIPELINE_SERVER_INTERNAL_H_ + +/** + * @file IMediaPipelineServerInternal.h + * + * The definition of the IMediaPipelineServerInternal interface. + * + * This interface defines the server internal APIs for playback of AV content. + */ + +#include + +#include +#include +#include + +#include "IDecryptionService.h" +#include "IHeartbeatHandler.h" +#include "IMediaPipeline.h" +#include "ISharedMemoryBuffer.h" +#include + +namespace firebolt::rialto::server +{ +class IMediaPipelineServerInternal; + +/** + * @brief IMediaPipelineServerInternal factory class, returns a concrete implementation of IMediaPipelineServerInternal + */ +class IMediaPipelineServerInternalFactory : public IMediaPipelineFactory +{ +public: + virtual ~IMediaPipelineServerInternalFactory() = default; + + /** + * @brief Create a IMediaPipelineServerInternalFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IMediaPipelineServerInternal factory method, returns a concrete implementation of IMediaPipeline + * + * @param[in] client : The Rialto media player client. + * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session + * @param[in] sessionId : The session id for this MediaPipeline. + * @param[in] shmBuffer : The shared buffer object. + * @param[in] decryptionService : The decryption service object. + * + * @retval the new backend instance or null on error. + */ + virtual std::unique_ptr createMediaPipelineServerInternal( + std::weak_ptr client, const VideoRequirements &videoRequirements, int sessionId, + const std::shared_ptr &shmBuffer, IDecryptionService &decryptionService) const = 0; +}; + +/** + * @brief The definition of the IMediaPipelineServerInternal interface. + * + * This interface defines the internal server APIs for playback of AV content which + * should be implemented by Rialto Server only. + */ +class IMediaPipelineServerInternal : public IMediaPipeline +{ +public: + /** + * @brief Returns data requested using notifyNeedMediaData(). + * + * This is a server only implementation. The data from the client has already been + * writen to the shared memory. + * + * A successful notifyNeedMediaData() request will return at least one frame + * of data but may return less than originally requested. + * + * @param[in] status : The status + * @param[in] numFrames : The number of frames written. + * @param[in] needDataRequestId : Need data request id + */ + virtual bool haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId) = 0; + + /** + * @brief Checks if MediaPipeline threads are not deadlocked + * + * @param[out] heartbeatHandler : The heartbeat handler instance + */ + virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; +}; + +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_MEDIA_PIPELINE_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/ISharedMemoryBuffer.h b/middleware/rialto-client/media/server/main/interface/ISharedMemoryBuffer.h new file mode 100644 index 000000000..fac404126 --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/ISharedMemoryBuffer.h @@ -0,0 +1,152 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_SHARED_MEMORY_BUFFER_H_ +#define FIREBOLT_RIALTO_SERVER_I_SHARED_MEMORY_BUFFER_H_ + +#include +#include + +#include "MediaCommon.h" + +namespace firebolt::rialto::server +{ +class ISharedMemoryBuffer; +class ISharedMemoryBufferFactory +{ +public: + ISharedMemoryBufferFactory() = default; + virtual ~ISharedMemoryBufferFactory() = default; + + static std::unique_ptr createFactory(); + virtual std::shared_ptr createSharedMemoryBuffer(unsigned numOfPlaybacks, + unsigned numOfWebAudioPlayers) const = 0; +}; + +class ISharedMemoryBuffer +{ +public: + ISharedMemoryBuffer() = default; + virtual ~ISharedMemoryBuffer() = default; + + ISharedMemoryBuffer(const ISharedMemoryBuffer &) = delete; + ISharedMemoryBuffer(ISharedMemoryBuffer &&) = delete; + ISharedMemoryBuffer &operator=(const ISharedMemoryBuffer &) = delete; + ISharedMemoryBuffer &operator=(ISharedMemoryBuffer &&) = delete; + + /** + * @brief The type of media playback. + */ + enum class MediaPlaybackType + { + GENERIC, + WEB_AUDIO + }; + + /** + * @brief Maps the partition for playback. + * + * @param[in] playbackType : The type of playback partition. + * @param[in] id : The id for the partition of playbackType. + * + * @retval true on success. + */ + virtual bool mapPartition(MediaPlaybackType playbackType, int id) = 0; + + /** + * @brief Unmaps the partition for playback. + * + * @param[in] playbackType : The type of playback partition. + * @param[in] id : The id for the partition of playbackType. + * + * @retval true on success. + */ + virtual bool unmapPartition(MediaPlaybackType playbackType, int id) = 0; + + /** + * @brief Clears the data in the specified partition. + * + * @param[in] playbackType : The type of playback partition. + * @param[in] id : The id for the partition of playbackType. + * @param[in] mediaSourceType : The type of media source partition. + * + * @retval true on success. + */ + virtual bool clearData(MediaPlaybackType playbackType, int id, const MediaSourceType &mediaSourceType) const = 0; + + /** + * @brief Gets the offset of the specified data partition. + * + * @param[in] playbackType : The type of playback partition. + * @param[in] id : The id for the partition of playbackType. + * @param[in] mediaSourceType : The type of media source partition. + * + * @retval true on success. + */ + virtual std::uint32_t getDataOffset(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const = 0; + + /** + * @brief Gets the maximum length of the specified data partition. + * + * @param[in] playbackType : The type of playback partition. + * @param[in] id : The id for the partition of playbackType. + * @param[in] mediaSourceType : The type of media source partition. + * + * @retval true on success. + */ + virtual std::uint32_t getMaxDataLen(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const = 0; + + /** + * @brief Gets the pointer to the start of the specified data partition. + * + * @param[in] playbackType : The type of playback partition. + * @param[in] id : The id for the partition of playbackType. + * @param[in] mediaSourceType : The type of media source partition. + * + * @retval true on success. + */ + virtual std::uint8_t *getDataPtr(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const = 0; + + /** + * @brief Gets file descriptor of the shared memory. + * + * @retval > -1 on success. + */ + virtual int getFd() const = 0; + + /** + * @brief Gets the allocated size of the shared memory. + * + * @retval > 0 on success. + */ + virtual std::uint32_t getSize() const = 0; + + /** + * @brief Gets the pointer to the shared memory. + * + * @retval None null ptr value on success. + */ + virtual std::uint8_t *getBuffer() const = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_SHARED_MEMORY_BUFFER_H_ diff --git a/middleware/rialto-client/media/server/main/interface/ITextTrackSession.h b/middleware/rialto-client/media/server/main/interface/ITextTrackSession.h new file mode 100644 index 000000000..fe156f811 --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/ITextTrackSession.h @@ -0,0 +1,57 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_SESSION_H_ +#define FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_SESSION_H_ + +#include +#include + +namespace firebolt::rialto::server +{ +class ITextTrackSession; + +class ITextTrackSessionFactory +{ +public: + virtual ~ITextTrackSessionFactory() = default; + static ITextTrackSessionFactory &getFactory(); + virtual std::unique_ptr createTextTrackSession(const std::string &display) const = 0; +}; + +class ITextTrackSession +{ +public: + ITextTrackSession() = default; + virtual ~ITextTrackSession() = default; + + virtual bool resetSession(bool isMuted) = 0; + virtual bool pause() = 0; + virtual bool play() = 0; + virtual bool mute(bool mute) = 0; + virtual bool setPosition(uint64_t mediaTimestampMs) = 0; + virtual bool sendData(const std::string &data, int64_t displayOffsetMs = 0) = 0; + virtual bool setSessionWebVTTSelection() = 0; + virtual bool setSessionTTMLSelection() = 0; + virtual bool setSessionCCSelection(const std::string &service) = 0; + virtual bool associateVideoDecoder(uint64_t decoderId) = 0; + virtual bool isClosedCaptions() const = 0; +}; +} // namespace firebolt::rialto::server +#endif // FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_SESSION_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IWebAudioPlayerServerInternal.h b/middleware/rialto-client/media/server/main/interface/IWebAudioPlayerServerInternal.h new file mode 100644 index 000000000..c604ebce6 --- /dev/null +++ b/middleware/rialto-client/media/server/main/interface/IWebAudioPlayerServerInternal.h @@ -0,0 +1,104 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ +#define FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ + +/** + * @file IWebAudioPlayerServerInternal.h + * + * The definition of the IWebAudioPlayerServerInternal interface. + * + * This interface defines the server internal APIs for playback of AV content. + */ + +#include + +#include +#include +#include + +#include "IDecryptionService.h" +#include "IGstWebAudioPlayer.h" +#include "IHeartbeatHandler.h" +#include "IMainThread.h" +#include "ISharedMemoryBuffer.h" +#include "ITimer.h" +#include "IWebAudioPlayer.h" +#include "MediaCommon.h" + +namespace firebolt::rialto::server +{ +class IWebAudioPlayerServerInternal; +/** + * @brief IWebAudioPlayer factory class, returns a concrete implementation of IWebAudioPlayer for internal server use + */ +class IWebAudioPlayerServerInternalFactory : public IWebAudioPlayerFactory +{ +public: + virtual ~IWebAudioPlayerServerInternalFactory() = default; + + /** + * @brief Create a IWebAudioPlayerServerInternalFactory instance. + * + * @retval the factory instance or null on error. + */ + static std::shared_ptr createFactory(); + + /** + * @brief IWebAudioPlayerServerInternalFactory method, returns a concrete implementation of IWebAudioPlayer for + * internal server use + * + * @param[in] client : The Web Audio Player client + * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM) + * @param[in] priority : Priority value for this pipeline. + * @param[in] config : Additional type dependent configuration data or nullptr + * @param[in] shmBuffer : The shared buffer object. + * @param[in] handle : The handle for this WebAudioPlayer. + * + * @retval the new backend instance or null on error. + */ + virtual std::unique_ptr createWebAudioPlayerServerInternal( + std::weak_ptr client, const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config, const std::shared_ptr &shmBuffer, int handle, + const std::shared_ptr &mainThreadFactory, + const std::shared_ptr &gstPlayerFactory, + std::weak_ptr timerFactory) const = 0; +}; + +/** + * @brief The definition of the IWebAudioPlayerServerInternal interface. + * + * This interface defines the public API of Rialto for mixing PCM audio with + * current audio output. It should be implemented by both Rialto Client & + * Rialto Server. + */ +class IWebAudioPlayerServerInternal : public IWebAudioPlayer +{ +public: + /** + * @brief Checks if WebAudioPlayer threads are not deadlocked + * + * @param[out] heartbeatHandler : The heartbeat handler instance + */ + virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; +}; +}; // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/proto/metadata.proto b/middleware/rialto-client/media/server/main/proto/metadata.proto new file mode 120000 index 000000000..31c2471b2 --- /dev/null +++ b/middleware/rialto-client/media/server/main/proto/metadata.proto @@ -0,0 +1 @@ +../../../../proto/metadata.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/main/source/ActiveRequests.cpp b/middleware/rialto-client/media/server/main/source/ActiveRequests.cpp new file mode 100644 index 000000000..b91cfa67b --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/ActiveRequests.cpp @@ -0,0 +1,126 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ActiveRequests.h" +#include +#include + +namespace firebolt::rialto::server +{ +ActiveRequests::ActiveRequestsData::~ActiveRequestsData() +{ + for (std::unique_ptr &segment : m_segments) + { + delete[] segment->getData(); + } +} + +AddSegmentStatus ActiveRequests::ActiveRequestsData::addSegment(const std::unique_ptr &segment) +{ + if (m_bytesWritten + segment->getDataLength() > m_maxMediaBytes) + return AddSegmentStatus::NO_SPACE; + + std::unique_ptr copiedSegment = segment->copy(); + + uint8_t *data = new uint8_t[segment->getDataLength()]; + std::memcpy(data, segment->getData(), segment->getDataLength()); + + copiedSegment->setData(segment->getDataLength(), data); + m_segments.push_back(std::move(copiedSegment)); + + m_bytesWritten += segment->getDataLength(); + return AddSegmentStatus::OK; +} + +ActiveRequests::ActiveRequests() : m_currentId{0} {} + +std::uint32_t ActiveRequests::insert(const MediaSourceType &mediaSourceType, std::uint32_t maxMediaBytes) +{ + std::unique_lock lock{m_mutex}; + m_requestMap.insert(std::make_pair(m_currentId, ActiveRequestsData(mediaSourceType, maxMediaBytes))); + return m_currentId++; +} + +MediaSourceType ActiveRequests::getType(std::uint32_t requestId) const +{ + std::unique_lock lock{m_mutex}; + auto requestIter{m_requestMap.find(requestId)}; + if (requestIter != m_requestMap.end()) + { + return requestIter->second.getType(); + } + return MediaSourceType::UNKNOWN; +} + +void ActiveRequests::erase(std::uint32_t requestId) +{ + std::unique_lock lock{m_mutex}; + m_requestMap.erase(requestId); +} + +void ActiveRequests::erase(const MediaSourceType &mediaSourceType) +{ + std::unique_lock lock{m_mutex}; + for (auto it = m_requestMap.begin(); it != m_requestMap.end();) + { + if (it->second.getType() == mediaSourceType) + { + it = m_requestMap.erase(it); + } + else + { + ++it; + } + } +} + +void ActiveRequests::clear() +{ + std::unique_lock lock{m_mutex}; + m_requestMap.clear(); +} + +AddSegmentStatus ActiveRequests::addSegment(std::uint32_t requestId, + const std::unique_ptr &segment) +{ + if (nullptr == segment || nullptr == segment->getData()) + { + return AddSegmentStatus::ERROR; + } + + auto requestIter{m_requestMap.find(requestId)}; + if (requestIter != m_requestMap.end()) + { + return requestIter->second.addSegment(segment); + } + + return AddSegmentStatus::ERROR; +} + +const IMediaPipeline::MediaSegmentVector &ActiveRequests::getSegments(std::uint32_t requestId) const +{ + auto requestIter{m_requestMap.find(requestId)}; + if (requestIter != m_requestMap.end()) + { + return requestIter->second.getSegments(); + } + + throw std::runtime_error("No segments for request id " + std::to_string(requestId)); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/ControlServerInternal.cpp b/middleware/rialto-client/media/server/main/source/ControlServerInternal.cpp new file mode 100644 index 000000000..2c746fd6f --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/ControlServerInternal.cpp @@ -0,0 +1,163 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ControlServerInternal.h" +#include "RialtoServerLogging.h" +#include + +namespace +{ +const char *convertApplicationState(const firebolt::rialto::ApplicationState &appState) +{ + switch (appState) + { + case firebolt::rialto::ApplicationState::UNKNOWN: + return "UNKNOWN"; + case firebolt::rialto::ApplicationState::RUNNING: + return "RUNNING"; + case firebolt::rialto::ApplicationState::INACTIVE: + return "INACTIVE"; + } + return "UNKNOWN"; +} +} // namespace + +namespace firebolt::rialto +{ +std::shared_ptr IControlFactory::createFactory() +{ + return server::IControlServerInternalFactory::createFactory(); +} +} // namespace firebolt::rialto + +namespace firebolt::rialto::server +{ +std::shared_ptr IControlServerInternalFactory::createFactory() +try +{ + return std::make_shared(); +} +catch (std::exception &e) +{ + RIALTO_SERVER_LOG_ERROR("ControlServerInternalFactory creation failed"); + return nullptr; +} + +std::shared_ptr ControlServerInternalFactory::createControl() const +{ + RIALTO_SERVER_LOG_ERROR("This function can't be used by rialto server. Please use createControlServerInternal"); + return nullptr; +} + +std::shared_ptr ControlServerInternalFactory::createControlServerInternal( + int id, const std::shared_ptr &client) const +try +{ + return std::make_shared(server::IMainThreadFactory::createFactory(), id, client); +} +catch (const std::exception &e) +{ + RIALTO_SERVER_LOG_ERROR("ControlServerInternal creation failed"); + return nullptr; +} + +ControlServerInternal::ControlServerInternal(const std::shared_ptr &mainThreadFactory, int id, + const std::shared_ptr &client) + : m_controlId{id}, m_client{client}, m_currentState{ApplicationState::UNKNOWN} +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + m_mainThread = mainThreadFactory->getMainThread(); + if (!m_mainThread) + { + throw std::runtime_error("Failed to get the main thread"); + } + m_mainThreadClientId = m_mainThread->registerClient(); +} + +ControlServerInternal::~ControlServerInternal() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + m_mainThread->unregisterClient(m_mainThreadClientId); +} + +void ControlServerInternal::ack(int32_t ackId) +{ + RIALTO_SERVER_LOG_DEBUG("Control with id: %d received ack for ping: %d", m_controlId, ackId); + auto task = [&]() + { + if (!m_heartbeatHandler) + { + RIALTO_SERVER_LOG_WARN("No heartbeatHandler present for control with id: %d", m_controlId); + return; + } + if (m_heartbeatHandler->id() != ackId) + { + RIALTO_SERVER_LOG_WARN("Control with id: %d received ack with wrong id: %d", m_controlId, ackId); + return; + } + m_heartbeatHandler.reset(); + }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +void ControlServerInternal::setApplicationState(const ApplicationState &state) +{ + RIALTO_SERVER_LOG_MIL("Notify rialto client about state changed to: %s", convertApplicationState(state)); + auto task = [&]() + { + m_currentState = state; + if (m_client) + m_client->notifyApplicationState(state); + }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +void ControlServerInternal::ping(std::unique_ptr &&heartbeatHandler) +{ + RIALTO_SERVER_LOG_DEBUG("Control with id: %d will send ping with id: %d", m_controlId, heartbeatHandler->id()); + auto task = [&]() + { + if (m_currentState != ApplicationState::RUNNING) + { + RIALTO_SERVER_LOG_DEBUG("Control with id: %d in INACTIVE state. Ack immediately for ping with id: %d", + m_controlId, heartbeatHandler->id()); + m_heartbeatHandler.reset(); + heartbeatHandler.reset(); + return; + } + if (m_heartbeatHandler) + { + m_heartbeatHandler->error(); + m_heartbeatHandler.reset(); + } + if (m_client) + { + m_client->ping(heartbeatHandler->id()); + m_heartbeatHandler = std::move(heartbeatHandler); + } + }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +bool ControlServerInternal::registerClient(std::weak_ptr client, ApplicationState &appState) +{ + RIALTO_SERVER_LOG_ERROR("Method not implemented"); + return false; +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/DataReaderFactory.cpp b/middleware/rialto-client/media/server/main/source/DataReaderFactory.cpp new file mode 100644 index 000000000..079fe0b6d --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/DataReaderFactory.cpp @@ -0,0 +1,56 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DataReaderFactory.h" +#include "DataReaderV1.h" +#include "DataReaderV2.h" +#include "ShmCommon.h" +#include "ShmUtils.h" + +namespace +{ +uint32_t readLEUint32(const uint8_t *buffer) +{ + uint32_t value = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]; + return value; +} +} // namespace + +namespace firebolt::rialto::server +{ +std::shared_ptr DataReaderFactory::createDataReader(const MediaSourceType &mediaSourceType, + std::uint8_t *buffer, std::uint32_t dataOffset, + std::uint32_t numFrames) const +{ + // Version is always first 4 bytes of data + std::uint8_t *metadata = buffer + dataOffset; + std::uint32_t version = readLEUint32(metadata); + if (1 == version) + { + std::uint32_t metadataOffsetWithoutVersion = dataOffset + common::VERSION_SIZE_BYTES; + return std::make_shared(mediaSourceType, buffer, metadataOffsetWithoutVersion, numFrames); + } + if (2 == version) + { + std::uint32_t v2DataOffset = dataOffset + getMaxMetadataBytes(); + return std::make_shared(mediaSourceType, buffer, v2DataOffset, numFrames); + } + return nullptr; +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/DataReaderV1.cpp b/middleware/rialto-client/media/server/main/source/DataReaderV1.cpp new file mode 100644 index 000000000..9e61080ed --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/DataReaderV1.cpp @@ -0,0 +1,68 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DataReaderV1.h" +#include "RialtoServerLogging.h" +#include "ShmCommon.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server +{ +DataReaderV1::DataReaderV1(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t metadataOffset, + std::uint32_t numFrames) + : m_mediaSourceType{mediaSourceType}, m_buffer{buffer}, m_metadataOffset{metadataOffset}, m_numFrames{numFrames} +{ + RIALTO_SERVER_LOG_DEBUG("Detected Metadata in Version 1. Media source type: %s", + common::convertMediaSourceType(m_mediaSourceType)); + static_assert(sizeof(DataReaderV1::MetadataV1) == common::METADATA_V1_SIZE_PER_FRAME_BYTES, + "Size of firebolt::rialto::server::DataReaderV1::MetadataV1 is not equal to " + "firebolt::rialto::common::METADATA_V1_SIZE_PER_FRAME_BYTES"); +} + +IMediaPipeline::MediaSegmentVector DataReaderV1::readData() const +{ + IMediaPipeline::MediaSegmentVector mediaSegments; + auto metadatas = readMetadata(); + for (const auto &metadata : metadatas) + { + if (m_mediaSourceType == MediaSourceType::AUDIO) + { + mediaSegments.emplace_back(createSegment(metadata)); + } + else if (m_mediaSourceType == MediaSourceType::VIDEO) + { + mediaSegments.emplace_back(createSegment(metadata)); + } + } + return mediaSegments; +} + +std::vector DataReaderV1::readMetadata() const +{ + std::vector result; + std::uint8_t *regionMetadataOffset = m_buffer + m_metadataOffset; + for (std::uint32_t frame = 0; frame < m_numFrames; ++frame) + { + std::uint8_t *frameMetadataOffset = regionMetadataOffset + (frame * common::METADATA_V1_SIZE_PER_FRAME_BYTES); + DataReaderV1::MetadataV1 *metadataPtr = reinterpret_cast(frameMetadataOffset); + result.emplace_back(*metadataPtr); + } + return result; +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/DataReaderV2.cpp b/middleware/rialto-client/media/server/main/source/DataReaderV2.cpp new file mode 100644 index 000000000..eab51c355 --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/DataReaderV2.cpp @@ -0,0 +1,240 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "DataReaderV2.h" +#include "RialtoServerLogging.h" +#include "ShmCommon.h" +#include "TypeConverters.h" +#include "metadata.pb.h" + +namespace +{ +firebolt::rialto::SegmentAlignment +convertSegmentAlignment(const firebolt::rialto::MediaSegmentMetadata_SegmentAlignment &segmentAlignment) +{ + switch (segmentAlignment) + { + case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_UNDEFINED: + { + return firebolt::rialto::SegmentAlignment::UNDEFINED; + } + case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_NAL: + { + return firebolt::rialto::SegmentAlignment::NAL; + } + case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_AU: + { + return firebolt::rialto::SegmentAlignment::AU; + } + } + return firebolt::rialto::SegmentAlignment::UNDEFINED; +} + +firebolt::rialto::CipherMode convertCipherMode(const firebolt::rialto::MediaSegmentMetadata_CipherMode &cipherMode) +{ + switch (cipherMode) + { + case firebolt::rialto::MediaSegmentMetadata_CipherMode_UNKNOWN: + { + return firebolt::rialto::CipherMode::UNKNOWN; + } + case firebolt::rialto::MediaSegmentMetadata_CipherMode_CENC: + { + return firebolt::rialto::CipherMode::CENC; + } + case firebolt::rialto::MediaSegmentMetadata_CipherMode_CBC1: + { + return firebolt::rialto::CipherMode::CBC1; + } + case firebolt::rialto::MediaSegmentMetadata_CipherMode_CENS: + { + return firebolt::rialto::CipherMode::CENS; + } + case firebolt::rialto::MediaSegmentMetadata_CipherMode_CBCS: + { + return firebolt::rialto::CipherMode::CBCS; + } + } + return firebolt::rialto::CipherMode::UNKNOWN; +} + +firebolt::rialto::CodecDataType convertCodecDataType(const firebolt::rialto::MediaSegmentMetadata_CodecData_Type &type) +{ + if (firebolt::rialto::MediaSegmentMetadata_CodecData_Type_STRING == type) + { + return firebolt::rialto::CodecDataType::STRING; + } + return firebolt::rialto::CodecDataType::BUFFER; +} + +std::unique_ptr +createSegment(const firebolt::rialto::MediaSegmentMetadata &metadata, const firebolt::rialto::MediaSourceType &type) +{ + // Create segment + std::unique_ptr segment; + if (type == firebolt::rialto::MediaSourceType::AUDIO) + { + if (!metadata.has_sample_rate() || !metadata.has_channels_num()) + { + RIALTO_SERVER_LOG_ERROR("SampleRate/ChannelsNum not present in audio metadata"); + return nullptr; + } + segment = std::make_unique(metadata.stream_id(), + metadata.time_position(), + metadata.sample_duration(), + metadata.sample_rate(), + metadata.channels_num(), + metadata.clipping_start(), + metadata.clipping_end()); + } + else if (type == firebolt::rialto::MediaSourceType::VIDEO) + { + if (!metadata.has_width() || !metadata.has_height()) + { + RIALTO_SERVER_LOG_ERROR("Width/height not present in video metadata"); + return nullptr; + } + + firebolt::rialto::Fraction frameRate{firebolt::rialto::kUndefinedSize, firebolt::rialto::kUndefinedSize}; + if (metadata.has_frame_rate()) + { + frameRate = {metadata.frame_rate().numerator(), metadata.frame_rate().denominator()}; + } + segment = std::make_unique(metadata.stream_id(), + metadata.time_position(), + metadata.sample_duration(), + metadata.width(), + metadata.height(), frameRate); + } + else if (type == firebolt::rialto::MediaSourceType::SUBTITLE) + { + segment = + std::make_unique(metadata.stream_id(), + firebolt::rialto::MediaSourceType::SUBTITLE, + metadata.time_position(), + metadata.sample_duration()); + } + else + { + RIALTO_SERVER_LOG_ERROR("Unknown segment type"); + return nullptr; + } + + // Read optional data + if (metadata.has_segment_alignment()) + { + segment->setSegmentAlignment(convertSegmentAlignment(metadata.segment_alignment())); + } + if (metadata.has_extra_data()) + { + segment->setExtraData(std::vector(metadata.extra_data().begin(), metadata.extra_data().end())); + } + if (metadata.has_codec_data()) + { + auto codecData = std::make_shared(); + codecData->type = convertCodecDataType(metadata.codec_data().type()); + codecData->data = std::vector(metadata.codec_data().data().begin(), metadata.codec_data().data().end()); + segment->setCodecData(codecData); + } + + // Read encryption data + if (metadata.has_media_key_session_id() || metadata.has_key_id() || metadata.has_init_vector() || + metadata.has_init_with_last_15()) + { + segment->setEncrypted(true); + } + else + { + segment->setEncrypted(false); + } + if (metadata.has_media_key_session_id()) + { + segment->setMediaKeySessionId(metadata.media_key_session_id()); + } + if (metadata.has_key_id()) + { + segment->setKeyId(std::vector(metadata.key_id().begin(), metadata.key_id().end())); + } + if (metadata.has_init_vector()) + { + segment->setInitVector(std::vector(metadata.init_vector().begin(), metadata.init_vector().end())); + } + if (metadata.has_init_with_last_15()) + { + segment->setInitWithLast15(metadata.init_with_last_15()); + } + if (metadata.has_cipher_mode()) + { + segment->setCipherMode(convertCipherMode(metadata.cipher_mode())); + } + if (metadata.has_crypt() && metadata.has_skip()) + { + segment->setEncryptionPattern(metadata.crypt(), metadata.skip()); + } + if (metadata.has_display_offset()) + { + segment->setDisplayOffset(metadata.display_offset()); + } + + for (const auto &info : metadata.sub_sample_info()) + { + segment->addSubSample(info.num_clear_bytes(), info.num_encrypted_bytes()); + } + return segment; +} +} // namespace + +namespace firebolt::rialto::server +{ +DataReaderV2::DataReaderV2(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t dataOffset, + std::uint32_t numFrames) + : m_mediaSourceType{mediaSourceType}, m_buffer{buffer}, m_dataOffset{dataOffset}, m_numFrames{numFrames} +{ + RIALTO_SERVER_LOG_DEBUG("Detected Metadata in Version 2. Media source type: %s", + common::convertMediaSourceType(m_mediaSourceType)); +} + +IMediaPipeline::MediaSegmentVector DataReaderV2::readData() const +{ + IMediaPipeline::MediaSegmentVector mediaSegments; + uint8_t *currentReadPosition{m_buffer + m_dataOffset}; + for (auto i = 0U; i < m_numFrames; ++i) + { + std::uint32_t *metadataSize{reinterpret_cast(currentReadPosition)}; + currentReadPosition += sizeof(uint32_t); + MediaSegmentMetadata metadata; + if (!metadata.ParseFromArray(currentReadPosition, *metadataSize)) + { + RIALTO_SERVER_LOG_ERROR("Metadata parsing failed!"); + return IMediaPipeline::MediaSegmentVector{}; + } + auto newSegment{createSegment(metadata, m_mediaSourceType)}; + if (!newSegment) + { + RIALTO_SERVER_LOG_ERROR("Segment parsing failed!"); + return IMediaPipeline::MediaSegmentVector{}; + } + currentReadPosition += *metadataSize; + newSegment->setData(metadata.length(), currentReadPosition); + currentReadPosition += metadata.length(); + mediaSegments.emplace_back(std::move(newSegment)); + } + return mediaSegments; +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/HeartbeatProcedure.cpp b/middleware/rialto-client/media/server/main/source/HeartbeatProcedure.cpp new file mode 100644 index 000000000..d3955571c --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/HeartbeatProcedure.cpp @@ -0,0 +1,78 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "HeartbeatProcedure.h" + +namespace firebolt::rialto::server +{ +std::unique_ptr IHeartbeatProcedureFactory::createFactory() +{ + return std::make_unique(); +} + +std::shared_ptr +HeartbeatProcedureFactory::createHeartbeatProcedure(const std::shared_ptr &ackSender, std::int32_t pingId) const +{ + return std::make_shared(ackSender, pingId); +} + +HeartbeatProcedure::HeartbeatHandler::HeartbeatHandler(const std::shared_ptr &procedure, + std::int32_t pingId) + : m_procedure{procedure}, m_kPingId{pingId}, m_success{true} +{ +} + +HeartbeatProcedure::HeartbeatHandler::~HeartbeatHandler() +{ + m_procedure->onFinish(m_success); +} + +void HeartbeatProcedure::HeartbeatHandler::error() +{ + m_success = false; +} + +std::int32_t HeartbeatProcedure::HeartbeatHandler::id() const +{ + return m_kPingId; +} + +HeartbeatProcedure::HeartbeatProcedure(const std::shared_ptr &ackSender, std::int32_t pingId) + : m_ackSender{ackSender}, m_kPingId{pingId}, m_success{true} +{ +} + +HeartbeatProcedure::~HeartbeatProcedure() +{ + m_ackSender->send(m_kPingId, m_success); +} + +std::unique_ptr HeartbeatProcedure::createHandler() +{ + return std::make_unique(shared_from_this(), m_kPingId); +} + +void HeartbeatProcedure::onFinish(bool success) +{ + if (!success) + { + m_success = false; + } +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MainThread.cpp b/middleware/rialto-client/media/server/main/source/MainThread.cpp new file mode 100644 index 000000000..83c2a3755 --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/MainThread.cpp @@ -0,0 +1,190 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MainThread.h" +#include "RialtoServerLogging.h" +#include +#include +#include + +namespace firebolt::rialto::server +{ +std::weak_ptr MainThreadFactory::m_mainThread; +std::mutex MainThreadFactory::m_creationMutex; + +std::shared_ptr IMainThreadFactory::createFactory() +{ + std::shared_ptr factory; + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the main thread factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr MainThreadFactory::getMainThread() const +{ + std::lock_guard lock{m_creationMutex}; + + std::shared_ptr mainThread = m_mainThread.lock(); + if (!mainThread) + { + try + { + mainThread = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the main thread, reason: %s", e.what()); + } + + m_mainThread = mainThread; + } + + return mainThread; +} + +MainThread::MainThread() : m_isMainThreadRunning{true}, m_mainThreadClientId{0}, m_nextClientId{1} +{ + RIALTO_SERVER_LOG_DEBUG("MainThread is constructed"); + m_thread = std::thread(std::bind(&MainThread::mainThreadLoop, this)); + + // Register itself + m_registeredClients.insert(m_mainThreadClientId); +} + +MainThread::~MainThread() +{ + RIALTO_SERVER_LOG_DEBUG("MainThread is destructed"); + auto shutdownTask = [this]() { m_isMainThreadRunning = false; }; + enqueueTask(m_mainThreadClientId, shutdownTask); + m_thread.join(); +} + +void MainThread::mainThreadLoop() +{ + while (m_isMainThreadRunning) + { + const std::shared_ptr kTaskInfo = waitForTask(); + if (m_registeredClients.find(kTaskInfo->clientId) != m_registeredClients.end()) + { + kTaskInfo->task(); + } + else + { + RIALTO_SERVER_LOG_WARN("Task ignored, client '%d' not registered", kTaskInfo->clientId); + } + + if (nullptr != kTaskInfo->cv) + { + std::unique_lock lockTask(*(kTaskInfo->mutex)); + kTaskInfo->cv->notify_one(); + } + } +} + +const std::shared_ptr MainThread::waitForTask() +{ + std::unique_lock lock(m_taskQueueMutex); + if (m_taskQueue.empty()) + { + m_taskQueueCv.wait(lock, [this] { return !m_taskQueue.empty(); }); + } + const std::shared_ptr kTaskInfo = m_taskQueue.front(); + m_taskQueue.pop_front(); + return kTaskInfo; +} + +int32_t MainThread::registerClient() +{ + uint32_t clientId = m_nextClientId++; + + auto task = [&, clientId]() + { + RIALTO_SERVER_LOG_INFO("Registering client '%u'", clientId); + m_registeredClients.insert(clientId); + }; + enqueueTask(m_mainThreadClientId, task); + + return clientId; +} + +void MainThread::unregisterClient(uint32_t clientId) +{ + RIALTO_SERVER_LOG_INFO("Unregistering client '%u'", clientId); + m_registeredClients.erase(clientId); +} + +void MainThread::enqueueTask(uint32_t clientId, Task task) +{ + std::shared_ptr newTask = std::make_shared(); + newTask->clientId = clientId; + newTask->task = task; + { + std::unique_lock lock(m_taskQueueMutex); + m_taskQueue.push_back(newTask); + } + m_taskQueueCv.notify_one(); +} + +void MainThread::enqueueTaskAndWait(uint32_t clientId, Task task) +{ + std::shared_ptr newTask = std::make_shared(); + newTask->clientId = clientId; + newTask->task = task; + newTask->mutex = std::make_unique(); + newTask->cv = std::make_unique(); + + { + std::unique_lock lockTask(*(newTask->mutex)); + { + std::unique_lock lockQueue(m_taskQueueMutex); + m_taskQueue.push_back(newTask); + } + m_taskQueueCv.notify_one(); + + newTask->cv->wait(lockTask); + } +} + +void MainThread::enqueuePriorityTaskAndWait(uint32_t clientId, Task task) +{ + std::shared_ptr newTask = std::make_shared(); + newTask->clientId = clientId; + newTask->task = task; + newTask->mutex = std::make_unique(); + newTask->cv = std::make_unique(); + + { + std::unique_lock lockTask(*(newTask->mutex)); + { + std::unique_lock lockQueue(m_taskQueueMutex); + m_taskQueue.push_front(newTask); + } + m_taskQueueCv.notify_one(); + + newTask->cv->wait(lockTask); + } +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaKeySession.cpp b/middleware/rialto-client/media/server/main/source/MediaKeySession.cpp new file mode 100644 index 000000000..e57468e6c --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/MediaKeySession.cpp @@ -0,0 +1,489 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "MediaKeySession.h" +#include "MediaKeysCommon.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server +{ +std::shared_ptr IMediaKeySessionFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media key session factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr MediaKeySessionFactory::createMediaKeySession( + const std::string &keySystem, int32_t keySessionId, const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, + KeySessionType sessionType, std::weak_ptr client, bool isLDL) const +{ + std::unique_ptr mediaKeys; + try + { + mediaKeys = std::make_unique(keySystem, keySessionId, ocdmSystem, sessionType, client, + isLDL, server::IMainThreadFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media key session, reason: %s", e.what()); + } + + return mediaKeys; +} + +MediaKeySession::MediaKeySession(const std::string &keySystem, int32_t keySessionId, + const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, KeySessionType sessionType, + std::weak_ptr client, bool isLDL, + const std::shared_ptr &mainThreadFactory) + : m_kKeySystem(keySystem), m_kKeySessionId(keySessionId), m_kSessionType(sessionType), m_mediaKeysClient(client), + m_kIsLDL(isLDL), m_isSessionConstructed(false), m_isSessionClosed(false), m_licenseRequested(false), + m_ongoingOcdmOperation(false), m_ocdmError(false) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + m_mainThread = mainThreadFactory->getMainThread(); + if (!m_mainThread) + { + throw std::runtime_error("Failed to get the main thread"); + } + m_mainThreadClientId = m_mainThread->registerClient(); + + m_ocdmSession = ocdmSystem.createSession(this); + if (!m_ocdmSession) + { + throw std::runtime_error("Ocdm session could not be created"); + } + RIALTO_SERVER_LOG_MIL("New OCDM session created"); +} + +MediaKeySession::~MediaKeySession() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (m_isSessionConstructed) + { + if (!m_isSessionClosed) + { + if (MediaKeyErrorStatus::OK != closeKeySession()) + { + RIALTO_SERVER_LOG_ERROR("Failed to close the key session"); + } + } + if (MediaKeyErrorStatus::OK != m_ocdmSession->destructSession()) + { + RIALTO_SERVER_LOG_ERROR("Failed to destruct the key session"); + } + } + + m_mainThread->unregisterClient(m_mainThreadClientId); +} + +MediaKeyErrorStatus MediaKeySession::generateRequest(InitDataType initDataType, const std::vector &initData) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + // Set the request flag for the onLicenseRequest callback + m_licenseRequested = true; + + // Only construct session if it hasnt previously been constructed + if (!m_isSessionConstructed) + { + initOcdmErrorChecking(); + + MediaKeyErrorStatus status = + m_ocdmSession->constructSession(m_kSessionType, initDataType, &initData[0], initData.size()); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to construct the key session"); + m_licenseRequested = false; + } + else + { + m_isSessionConstructed = true; + + if (!m_queuedDrmHeader.empty()) + { + RIALTO_SERVER_LOG_DEBUG("Setting queued drm header after session construction"); + setDrmHeader(m_queuedDrmHeader); + m_queuedDrmHeader.clear(); + } + if (isPlayreadyKeySystem()) + { + // Ocdm-playready does not notify onProcessChallenge when complete. + // Fetch the challenge manually. + getChallenge(); + } + } + + if ((checkForOcdmErrors("generateRequest")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; + } + + return MediaKeyErrorStatus::OK; +} + +void MediaKeySession::getChallenge() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto task = [&]() + { + uint32_t challengeSize = 0; + MediaKeyErrorStatus status = m_ocdmSession->getChallengeData(m_kIsLDL, nullptr, &challengeSize); + if (challengeSize == 0) + { + RIALTO_SERVER_LOG_ERROR("Failed to get the challenge data size, no onLicenseRequest will be generated"); + return; + } + std::vector challenge(challengeSize, 0x00); + status = m_ocdmSession->getChallengeData(m_kIsLDL, &challenge[0], &challengeSize); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to get the challenge data, no onLicenseRequest will be generated"); + return; + } + + std::string url; + onProcessChallenge(url.c_str(), &challenge[0], challengeSize); + }; + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +MediaKeyErrorStatus MediaKeySession::loadSession() +{ + initOcdmErrorChecking(); + + MediaKeyErrorStatus status = m_ocdmSession->load(); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to load the key session"); + } + + if ((checkForOcdmErrors("loadSession")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +MediaKeyErrorStatus MediaKeySession::updateSession(const std::vector &responseData) +{ + initOcdmErrorChecking(); + + MediaKeyErrorStatus status; + if (isPlayreadyKeySystem()) + { + status = m_ocdmSession->storeLicenseData(&responseData[0], responseData.size()); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to store the license data for the key session"); + } + } + else + { + status = m_ocdmSession->update(&responseData[0], responseData.size()); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to update the key session"); + } + } + + if ((checkForOcdmErrors("updateSession")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +MediaKeyErrorStatus MediaKeySession::decrypt(GstBuffer *encrypted, GstCaps *caps) +{ + initOcdmErrorChecking(); + + MediaKeyErrorStatus status = m_ocdmSession->decryptBuffer(encrypted, caps); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to decrypt buffer"); + } + + if ((checkForOcdmErrors("decrypt")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +MediaKeyErrorStatus MediaKeySession::closeKeySession() +{ + initOcdmErrorChecking(); + + MediaKeyErrorStatus status; + if (isPlayreadyKeySystem()) + { + if (MediaKeyErrorStatus::OK != m_ocdmSession->cancelChallengeData()) + { + RIALTO_SERVER_LOG_WARN("Failed to cancel the challenge data for the key session"); + } + + if (MediaKeyErrorStatus::OK != m_ocdmSession->cleanDecryptContext()) + { + RIALTO_SERVER_LOG_WARN("Failed to clean the decrypt context for the key session"); + } + status = MediaKeyErrorStatus::OK; + RIALTO_SERVER_LOG_MIL("OCDM session closed"); + } + else + { + status = m_ocdmSession->close(); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to Close the key session"); + } + } + m_isSessionClosed = (MediaKeyErrorStatus::OK == status); + + if ((checkForOcdmErrors("closeKeySession")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +MediaKeyErrorStatus MediaKeySession::removeKeySession() +{ + initOcdmErrorChecking(); + + MediaKeyErrorStatus status = m_ocdmSession->remove(); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to remove the key session"); + } + + if ((checkForOcdmErrors("removeKeySession")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +MediaKeyErrorStatus MediaKeySession::getCdmKeySessionId(std::string &cdmKeySessionId) +{ + initOcdmErrorChecking(); + + MediaKeyErrorStatus status = m_ocdmSession->getCdmKeySessionId(cdmKeySessionId); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to get cdm key session id"); + } + + if ((checkForOcdmErrors("getCdmKeySessionId")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +bool MediaKeySession::containsKey(const std::vector &keyId) +{ + uint32_t result = m_ocdmSession->hasKeyId(keyId.data(), keyId.size()); + + return static_cast(result); +} + +MediaKeyErrorStatus MediaKeySession::setDrmHeader(const std::vector &requestData) +{ + initOcdmErrorChecking(); + + if (!m_isSessionConstructed) + { + RIALTO_SERVER_LOG_INFO("Session not yet constructed, queueing drm header to be set after construction"); + m_queuedDrmHeader = requestData; + return MediaKeyErrorStatus::OK; + } + + MediaKeyErrorStatus status = m_ocdmSession->setDrmHeader(requestData.data(), requestData.size()); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to set drm header"); + } + + if ((checkForOcdmErrors("setDrmHeader")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +MediaKeyErrorStatus MediaKeySession::getLastDrmError(uint32_t &errorCode) +{ + initOcdmErrorChecking(); + + MediaKeyErrorStatus status = m_ocdmSession->getLastDrmError(errorCode); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to get last drm error"); + } + + if ((checkForOcdmErrors("getLastDrmError")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +MediaKeyErrorStatus MediaKeySession::selectKeyId(const std::vector &keyId) +{ + if (m_selectedKeyId == keyId) + { + return MediaKeyErrorStatus::OK; + } + + initOcdmErrorChecking(); + + MediaKeyErrorStatus status = m_ocdmSession->selectKeyId(keyId.size(), keyId.data()); + if (MediaKeyErrorStatus::OK == status) + { + RIALTO_SERVER_LOG_INFO("New keyId selected successfully"); + m_selectedKeyId = keyId; + } + + if ((checkForOcdmErrors("selectKeyId")) && (MediaKeyErrorStatus::OK == status)) + { + status = MediaKeyErrorStatus::FAIL; + } + + return status; +} + +bool MediaKeySession::isPlayreadyKeySystem() const +{ + return m_kKeySystem.find("playready") != std::string::npos; +} + +void MediaKeySession::onProcessChallenge(const char url[], const uint8_t challenge[], const uint16_t challengeLength) +{ + std::string urlStr = url; + std::vector challengeVec = std::vector{challenge, challenge + challengeLength}; + auto task = [&, urlStr, challengeVec]() + { + std::shared_ptr client = m_mediaKeysClient.lock(); + if (client) + { + if (m_licenseRequested) + { + client->onLicenseRequest(m_kKeySessionId, challengeVec, urlStr); + m_licenseRequested = false; + } + else + { + client->onLicenseRenewal(m_kKeySessionId, challengeVec); + } + } + }; + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaKeySession::onKeyUpdated(const uint8_t keyId[], const uint8_t keyIdLength) +{ + std::vector keyIdVec = std::vector{keyId, keyId + keyIdLength}; + auto task = [&, keyIdVec]() + { + std::shared_ptr client = m_mediaKeysClient.lock(); + if (client) + { + KeyStatus status = m_ocdmSession->getStatus(&keyIdVec[0], keyIdVec.size()); + m_updatedKeyStatuses.push_back(std::make_pair(keyIdVec, status)); + } + }; + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaKeySession::onAllKeysUpdated() +{ + auto task = [&]() + { + std::shared_ptr client = m_mediaKeysClient.lock(); + if (client) + { + client->onKeyStatusesChanged(m_kKeySessionId, m_updatedKeyStatuses); + m_updatedKeyStatuses.clear(); + } + }; + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaKeySession::onError(const char message[]) +{ + RIALTO_SERVER_LOG_ERROR("Ocdm returned error: %s", message); + + std::lock_guard lock(m_ocdmErrorMutex); + if (!m_ongoingOcdmOperation) + { + RIALTO_SERVER_LOG_WARN("Received an asycronous OCDM error, ignoring"); + } + else + { + m_ocdmError = true; + } +} + +void MediaKeySession::initOcdmErrorChecking() +{ + std::lock_guard lock(m_ocdmErrorMutex); + m_ongoingOcdmOperation = true; + m_ocdmError = false; +} + +bool MediaKeySession::checkForOcdmErrors(const char *operationStr) +{ + bool error = false; + + std::lock_guard lock(m_ocdmErrorMutex); + if (m_ocdmError) + { + RIALTO_SERVER_LOG_ERROR("MediaKeySession received an onError callback, operation '%s' failed", operationStr); + error = true; + } + m_ongoingOcdmOperation = false; + + return error; +} + +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaKeysCapabilities.cpp b/middleware/rialto-client/media/server/main/source/MediaKeysCapabilities.cpp new file mode 100644 index 000000000..7bdb3836e --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/MediaKeysCapabilities.cpp @@ -0,0 +1,175 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "MediaCommon.h" +#include "MediaKeysCapabilities.h" +#include "MediaKeysCommon.h" +#include "RialtoServerLogging.h" + +namespace +{ +/** + * @brief Coverts MediaKeyErrorStatus to string. + */ +const char *toString(const firebolt::rialto::MediaKeyErrorStatus &status) +{ + switch (status) + { + case firebolt::rialto::MediaKeyErrorStatus::OK: + return "OK"; + case firebolt::rialto::MediaKeyErrorStatus::FAIL: + return "FAIL"; + case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: + return "BAD_SESSION_ID"; + case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: + return "INTERFACE_NOT_IMPLEMENTED"; + case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: + return "BUFFER_TOO_SMALL"; + case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: + return "NOT_SUPPORTED"; + case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: + return "INVALID_STATE"; + } + return "Unknown"; +} +} // namespace + +namespace firebolt::rialto +{ +std::shared_ptr IMediaKeysCapabilitiesFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media keys capabilities factory, reason: %s", e.what()); + } + + return factory; +} + +std::shared_ptr MediaKeysCapabilitiesFactory::getMediaKeysCapabilities() const +{ + std::shared_ptr mediaKeysCapabilities; + try + { + mediaKeysCapabilities = + std::make_shared(wrappers::IOcdmFactory::createFactory(), + wrappers::IOcdmSystemFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media keys capabilities, reason: %s", e.what()); + } + + return mediaKeysCapabilities; +} + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::server +{ +MediaKeysCapabilities::MediaKeysCapabilities(std::shared_ptr ocdmFactory, + std::shared_ptr ocdmSystemFactory) + : m_ocdmSystemFactory{ocdmSystemFactory} +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!ocdmFactory) + { + throw std::runtime_error("ocdmFactory invalid"); + } + + m_ocdm = ocdmFactory->getOcdm(); + if (!m_ocdm) + { + throw std::runtime_error("Ocdm could not be fetched"); + } +} + +MediaKeysCapabilities::~MediaKeysCapabilities() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); +} + +std::vector MediaKeysCapabilities::getSupportedKeySystems() +{ + std::vector supportedKeySystemVector; + for (auto it = kSupportedKeySystems.begin(); it != kSupportedKeySystems.end(); it++) + { + MediaKeyErrorStatus status = m_ocdm->isTypeSupported(*it); + if (MediaKeyErrorStatus::OK == status) + { + supportedKeySystemVector.push_back(*it); + } + } + + return supportedKeySystemVector; +} + +bool MediaKeysCapabilities::supportsKeySystem(const std::string &keySystem) +{ + MediaKeyErrorStatus status = m_ocdm->isTypeSupported(keySystem); + if (MediaKeyErrorStatus::OK != status) + { + return false; + } + return true; +} + +bool MediaKeysCapabilities::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) +{ + std::shared_ptr ocdmSystem = + m_ocdmSystemFactory->createOcdmSystem(keySystem); + if (!ocdmSystem) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the ocdm system object"); + version = ""; + return false; + } + + MediaKeyErrorStatus status = ocdmSystem->getVersion(version); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Ocdm getVersion failed with status %s", toString(status)); + version = ""; + return false; + } + return true; +} + +bool MediaKeysCapabilities::isServerCertificateSupported(const std::string &keySystem) +{ + std::shared_ptr ocdmSystem = + m_ocdmSystemFactory->createOcdmSystem(keySystem); + if (!ocdmSystem) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the ocdm system object"); + return false; + } + return ocdmSystem->supportsServerCertificate(); +} + +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaKeysServerInternal.cpp b/middleware/rialto-client/media/server/main/source/MediaKeysServerInternal.cpp new file mode 100644 index 000000000..11fb88488 --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/MediaKeysServerInternal.cpp @@ -0,0 +1,759 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "MediaKeysServerInternal.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto +{ +const char *mediaKeyErrorStatusToString(const MediaKeyErrorStatus &status) +{ + switch (status) + { + case firebolt::rialto::MediaKeyErrorStatus::OK: + return "OK"; + case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: + return "BAD_SESSION_ID"; + case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: + return "INTERFACE_NOT_IMPLEMENTED"; + case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: + return "BUFFER_TOO_SMALL"; + case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: + return "NOT_SUPPORTED"; + default: + return "FAIL"; + } +} + +std::shared_ptr IMediaKeysFactory::createFactory() +{ + return server::IMediaKeysServerInternalFactory::createFactory(); +} +} // namespace firebolt::rialto + +namespace firebolt::rialto::server +{ +int32_t generateSessionId() +{ + static int32_t keySessionId{0}; + return keySessionId++; +} + +std::shared_ptr IMediaKeysServerInternalFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media keys factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr MediaKeysServerInternalFactory::createMediaKeys(const std::string &keySystem) const +{ + RIALTO_SERVER_LOG_ERROR("This function can't be used by rialto server. Please use createMediaKeysServerInternal"); + return nullptr; +} + +std::unique_ptr +MediaKeysServerInternalFactory::createMediaKeysServerInternal(const std::string &keySystem) const +{ + std::unique_ptr mediaKeys; + try + { + mediaKeys = std::make_unique(keySystem, + server::IMainThreadFactory::createFactory(), + wrappers::IOcdmSystemFactory::createFactory(), + server::IMediaKeySessionFactory::createFactory()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media keys, reason: %s", e.what()); + } + + return mediaKeys; +} +}; // namespace firebolt::rialto::server + +namespace firebolt::rialto::server +{ +MediaKeysServerInternal::MediaKeysServerInternal( + const std::string &keySystem, const std::shared_ptr &mainThreadFactory, + std::shared_ptr ocdmSystemFactory, + std::shared_ptr mediaKeySessionFactory) + : m_mediaKeySessionFactory(mediaKeySessionFactory), m_keySystem(keySystem) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + m_mainThread = mainThreadFactory->getMainThread(); + if (!m_mainThread) + { + throw std::runtime_error("Failed to get the main thread"); + } + m_mainThreadClientId = m_mainThread->registerClient(); + + if (!ocdmSystemFactory) + { + throw std::runtime_error("No ocdmSystemFactory"); + } + + bool result = false; + auto task = [&]() + { + m_ocdmSystem = ocdmSystemFactory->createOcdmSystem(keySystem); + if (!m_ocdmSystem) + { + RIALTO_SERVER_LOG_ERROR("Ocdm system could not be created"); + } + else + { + result = true; + } + }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + if (!result) + { + throw std::runtime_error("MediaKeys construction failed"); + } +} + +MediaKeysServerInternal::~MediaKeysServerInternal() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() + { + m_ocdmSystem.reset(); + + m_mainThread->unregisterClient(m_mainThreadClientId); + }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +MediaKeyErrorStatus MediaKeysServerInternal::selectKeyId(int32_t keySessionId, const std::vector &keyId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = selectKeyIdInternal(keySessionId, keyId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::selectKeyIdInternal(int32_t keySessionId, const std::vector &keyId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->selectKeyId(keyId); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to select key id"); + return status; + } + + return status; +} + +bool MediaKeysServerInternal::containsKey(int32_t keySessionId, const std::vector &keyId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result{false}; + auto task = [&]() { result = containsKeyInternal(keySessionId, keyId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaKeysServerInternal::containsKeyInternal(int32_t keySessionId, const std::vector &keyId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return false; + } + + return sessionIter->second.mediaKeySession->containsKey(keyId); +} + +MediaKeyErrorStatus MediaKeysServerInternal::createKeySession(KeySessionType sessionType, + std::weak_ptr client, bool isLDL, + int32_t &keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = createKeySessionInternal(sessionType, client, isLDL, keySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::createKeySessionInternal(KeySessionType sessionType, + std::weak_ptr client, + bool isLDL, int32_t &keySessionId) +{ + int32_t keySessionIdTemp = generateSessionId(); + std::unique_ptr mediaKeySession = + m_mediaKeySessionFactory->createMediaKeySession(m_keySystem, keySessionIdTemp, *m_ocdmSystem, sessionType, + client, isLDL); + if (!mediaKeySession) + { + RIALTO_SERVER_LOG_ERROR("Failed to create a new media key session"); + return MediaKeyErrorStatus::FAIL; + } + keySessionId = keySessionIdTemp; + m_mediaKeySessions.emplace(std::make_pair(keySessionId, MediaKeySessionUsage{std::move(mediaKeySession)})); + + return MediaKeyErrorStatus::OK; +} + +MediaKeyErrorStatus MediaKeysServerInternal::generateRequest(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = generateRequestInternal(keySessionId, initDataType, initData); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::generateRequestInternal(int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->generateRequest(initDataType, initData); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to generate request for the key session %d", keySessionId); + return status; + } + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::loadSession(int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = loadSessionInternal(keySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::loadSessionInternal(int32_t keySessionId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->loadSession(); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to load the session %d", keySessionId); + return status; + } + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::updateSession(int32_t keySessionId, const std::vector &responseData) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = updateSessionInternal(keySessionId, responseData); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::updateSessionInternal(int32_t keySessionId, + const std::vector &responseData) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->updateSession(responseData); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to update the session %d", keySessionId); + return status; + } + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::setDrmHeader(int32_t keySessionId, const std::vector &requestData) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = setDrmHeaderInternal(keySessionId, requestData); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::setDrmHeaderInternal(int32_t keySessionId, + const std::vector &requestData) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->setDrmHeader(requestData); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to set drm header"); + return status; + } + + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::closeKeySession(int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = closeKeySessionInternal(keySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::closeKeySessionInternal(int32_t keySessionId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + if (sessionIter->second.bufCounter == 0) + { + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->closeKeySession(); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to close the key session %d", keySessionId); + return status; + } + return status; + } + + RIALTO_SERVER_LOG_INFO("Deferring closing of key session %d", keySessionId); + sessionIter->second.shouldBeClosed = true; + return MediaKeyErrorStatus::OK; +} + +MediaKeyErrorStatus MediaKeysServerInternal::removeKeySession(int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = removeKeySessionInternal(keySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::removeKeySessionInternal(int32_t keySessionId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->removeKeySession(); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to remove the key session %d", keySessionId); + return status; + } + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::deleteDrmStore() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = m_ocdmSystem->deleteSecureStore(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::deleteKeyStore() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = m_ocdmSystem->deleteKeyStore(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::getDrmStoreHash(std::vector &drmStoreHash) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + constexpr size_t kHashSize{256}; + drmStoreHash.resize(kHashSize); + MediaKeyErrorStatus status; + auto task = [&]() { status = m_ocdmSystem->getSecureStoreHash(&drmStoreHash[0], kHashSize); }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::getKeyStoreHash(std::vector &keyStoreHash) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + constexpr size_t kHashSize{256}; + keyStoreHash.resize(kHashSize); + MediaKeyErrorStatus status; + auto task = [&]() { status = m_ocdmSystem->getKeyStoreHash(&keyStoreHash[0], kHashSize); }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::getLdlSessionsLimit(uint32_t &ldlLimit) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = m_ocdmSystem->getLdlSessionsLimit(&ldlLimit); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::getLastDrmError(int32_t keySessionId, uint32_t &errorCode) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = getLastDrmErrorInternal(keySessionId, errorCode); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::getLastDrmErrorInternal(int32_t keySessionId, uint32_t &errorCode) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->getLastDrmError(errorCode); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to get last drm error"); + } + + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::getDrmTime(uint64_t &drmTime) +{ + MediaKeyErrorStatus status; + auto task = [&]() { status = m_ocdmSystem->getDrmTime(&drmTime); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = getCdmKeySessionIdInternal(keySessionId, cdmKeySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::releaseKeySession(int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = releaseKeySessionInternal(keySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::releaseKeySessionInternal(int32_t keySessionId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + if (sessionIter->second.bufCounter == 0) + { + m_mediaKeySessions.erase(sessionIter); + return MediaKeyErrorStatus::OK; + } + + RIALTO_SERVER_LOG_INFO("Deferring releasing of key session %d", keySessionId); + sessionIter->second.shouldBeReleased = true; + return MediaKeyErrorStatus::OK; +} + +MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionIdInternal(int32_t keySessionId, std::string &cdmKeySessionId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->getCdmKeySessionId(cdmKeySessionId); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to get cdm key session id"); + return status; + } + + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + MediaKeyErrorStatus status; + auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +MediaKeyErrorStatus MediaKeysServerInternal::decryptInternal(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return MediaKeyErrorStatus::BAD_SESSION_ID; + } + + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->decrypt(encrypted, caps); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to decrypt buffer."); + return status; + } + + return status; +} + +bool MediaKeysServerInternal::hasSession(int32_t keySessionId) const +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = m_mediaKeySessions.find(keySessionId) != m_mediaKeySessions.end(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaKeysServerInternal::isPlayreadyKeySystem(int32_t keySessionId) const +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + bool result; + auto task = [&]() { result = isPlayreadyKeySystemInternal(keySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaKeysServerInternal::isPlayreadyKeySystemInternal(int32_t keySessionId) const +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return false; + } + return sessionIter->second.mediaKeySession->isPlayreadyKeySystem(); +} + +void MediaKeysServerInternal::incrementSessionIdUsageCounter(int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto task = [&]() { incrementSessionIdUsageCounterInternal(keySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +void MediaKeysServerInternal::incrementSessionIdUsageCounterInternal(int32_t keySessionId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return; + } + + sessionIter->second.bufCounter++; +} + +void MediaKeysServerInternal::decrementSessionIdUsageCounter(int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto task = [&]() { decrementSessionIdUsageCounterInternal(keySessionId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +void MediaKeysServerInternal::decrementSessionIdUsageCounterInternal(int32_t keySessionId) +{ + auto sessionIter = m_mediaKeySessions.find(keySessionId); + if (sessionIter == m_mediaKeySessions.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); + return; + } + + if (sessionIter->second.bufCounter > 0) + { + sessionIter->second.bufCounter--; + } + + if (sessionIter->second.bufCounter == 0) + { + if (sessionIter->second.shouldBeClosed) + { + RIALTO_SERVER_LOG_INFO("Deferred closing of mksId %d", keySessionId); + MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->closeKeySession(); + if (MediaKeyErrorStatus::OK != status) + { + RIALTO_SERVER_LOG_ERROR("Failed to close the key session %d", keySessionId); + } + } + if (sessionIter->second.shouldBeReleased) + { + m_mediaKeySessions.erase(sessionIter); + } + } +} + +void MediaKeysServerInternal::ping(std::unique_ptr &&heartbeatHandler) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto task = [&]() { heartbeatHandler.reset(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +MediaKeyErrorStatus MediaKeysServerInternal::getMetricSystemData(std::vector &buffer) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + uint32_t bufferLength{1024}; + const uint32_t kMaxBufferLength{65536}; + MediaKeyErrorStatus status; + buffer.resize(bufferLength); + + for (int attempts = 0; bufferLength <= kMaxBufferLength; ++attempts) + { + auto task = [&]() { status = m_ocdmSystem->getMetricSystemData(bufferLength, buffer); }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + + if (status != MediaKeyErrorStatus::BUFFER_TOO_SMALL) + { + break; + } + + if (bufferLength >= kMaxBufferLength) + { + RIALTO_SERVER_LOG_ERROR("Buffer size %u exceeds the maximum allowed size %u", bufferLength, kMaxBufferLength); + return MediaKeyErrorStatus::BUFFER_TOO_SMALL; + } + + RIALTO_SERVER_LOG_WARN("Buffer is too small, resizing from %u to %u", bufferLength, bufferLength * 2); + bufferLength *= 2; + buffer.resize(bufferLength); + } + + if (status == MediaKeyErrorStatus::OK) + { + // If the buffer remains larger than bufferLength (due to a previous resize), + // the client may have values in the extra space. So this resize would ensure the buffer is trimmed to the correct size. + buffer.resize(bufferLength); + RIALTO_SERVER_LOG_DEBUG("Successfully retrieved metric system data, final buffer length: %u", bufferLength); + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to retrieve metric system data, status: %s, last buffer length tried: %u", + firebolt::rialto::mediaKeyErrorStatusToString(status), bufferLength); + } + return status; +} + +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaPipelineCapabilities.cpp b/middleware/rialto-client/media/server/main/source/MediaPipelineCapabilities.cpp new file mode 100644 index 000000000..3d874d5e2 --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/MediaPipelineCapabilities.cpp @@ -0,0 +1,102 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "MediaPipelineCapabilities.h" +#include "RialtoServerLogging.h" +#include + +namespace firebolt::rialto +{ +std::shared_ptr IMediaPipelineCapabilitiesFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media pipeline capabilities factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr MediaPipelineCapabilitiesFactory::createMediaPipelineCapabilities() const +{ + std::unique_ptr mediaPipelineCapabilities; + try + { + mediaPipelineCapabilities = + std::make_unique(server::IGstCapabilitiesFactory::getFactory()); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media pipeline capabilities, reason: %s", e.what()); + } + + return mediaPipelineCapabilities; +} + +}; // namespace firebolt::rialto + +namespace firebolt::rialto::server +{ +MediaPipelineCapabilities::MediaPipelineCapabilities(std::shared_ptr gstCapabilitiesFactory) + : m_kGstCapabilitiesFactory{gstCapabilitiesFactory} +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + m_gstCapabilities = m_kGstCapabilitiesFactory->createGstCapabilities(); + if (!m_gstCapabilities) + { + throw std::runtime_error("Gstreamer capabilities could not be created"); + } +} + +MediaPipelineCapabilities::~MediaPipelineCapabilities() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); +} + +std::vector MediaPipelineCapabilities::getSupportedMimeTypes(MediaSourceType sourceType) +{ + return m_gstCapabilities->getSupportedMimeTypes(sourceType); +} + +bool MediaPipelineCapabilities::isMimeTypeSupported(const std::string &mimeType) +{ + return m_gstCapabilities->isMimeTypeSupported(mimeType); +} + +std::vector MediaPipelineCapabilities::getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) +{ + return m_gstCapabilities->getSupportedProperties(mediaType, propertyNames); +} + +bool MediaPipelineCapabilities::isVideoMaster(bool &isVideoMaster) +{ + return m_gstCapabilities->isVideoMaster(isVideoMaster); +} + +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaPipelineServerInternal.cpp b/middleware/rialto-client/media/server/main/source/MediaPipelineServerInternal.cpp new file mode 100644 index 000000000..21aa0bbae --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/MediaPipelineServerInternal.cpp @@ -0,0 +1,1620 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ActiveRequests.h" +#include "DataReaderFactory.h" +#include "IDataReader.h" +#include "IRdkGstreamerUtilsWrapper.h" +#include "ISharedMemoryBuffer.h" +#include "MediaPipelineServerInternal.h" +#include "NeedMediaData.h" +#include "RialtoServerLogging.h" +#include "TypeConverters.h" + +namespace +{ +const char *toString(const firebolt::rialto::MediaSourceStatus &status) +{ + switch (status) + { + case firebolt::rialto::MediaSourceStatus::OK: + return "OK"; + case firebolt::rialto::MediaSourceStatus::EOS: + return "EOS"; + case firebolt::rialto::MediaSourceStatus::ERROR: + return "ERROR"; + case firebolt::rialto::MediaSourceStatus::CODEC_CHANGED: + return "CODEC_CHANGED"; + case firebolt::rialto::MediaSourceStatus::NO_AVAILABLE_SAMPLES: + return "NO_AVAILABLE_SAMPLES"; + } + return "Unknown"; +} + +std::int32_t generateSourceId() +{ + static std::int32_t sourceId{1}; + return sourceId++; +} +} // namespace + +namespace firebolt::rialto +{ +std::shared_ptr IMediaPipelineFactory::createFactory() +{ + return server::MediaPipelineServerInternalFactory::createFactory(); +} +}; // namespace firebolt::rialto + +namespace firebolt::rialto::server +{ +std::shared_ptr IMediaPipelineServerInternalFactory::createFactory() +{ + return MediaPipelineServerInternalFactory::createFactory(); +} + +std::shared_ptr MediaPipelineServerInternalFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media player server internal factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr +MediaPipelineServerInternalFactory::createMediaPipeline(std::weak_ptr client, + const VideoRequirements &videoRequirements) const +{ + RIALTO_SERVER_LOG_ERROR( + "This function can't be used by rialto server. Please use createMediaPipelineServerInternal"); + return nullptr; +} + +std::unique_ptr MediaPipelineServerInternalFactory::createMediaPipelineServerInternal( + std::weak_ptr client, const VideoRequirements &videoRequirements, int sessionId, + const std::shared_ptr &shmBuffer, IDecryptionService &decryptionService) const +{ + std::shared_ptr sharedClient = client.lock(); + if (!sharedClient) + { + RIALTO_SERVER_LOG_ERROR("Couldn't create client's shared pointer"); + return nullptr; + } + + std::unique_ptr mediaPipeline; + try + { + mediaPipeline = + std::make_unique(sharedClient, videoRequirements, + server::IGstGenericPlayerFactory::getFactory(), + sessionId, shmBuffer, + server::IMainThreadFactory::createFactory(), + common::ITimerFactory::getFactory(), + std::make_unique(), + std::make_unique(), decryptionService); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the media player server internal, reason: %s", e.what()); + } + + return mediaPipeline; +} + +MediaPipelineServerInternal::MediaPipelineServerInternal( + std::shared_ptr client, const VideoRequirements &videoRequirements, + const std::shared_ptr &gstPlayerFactory, int sessionId, + const std::shared_ptr &shmBuffer, const std::shared_ptr &mainThreadFactory, + std::shared_ptr timerFactory, std::unique_ptr &&dataReaderFactory, + std::unique_ptr &&activeRequests, IDecryptionService &decryptionService) + : m_mediaPipelineClient(client), m_kGstPlayerFactory(gstPlayerFactory), m_kVideoRequirements(videoRequirements), + m_sessionId{sessionId}, m_shmBuffer{shmBuffer}, m_dataReaderFactory{std::move(dataReaderFactory)}, + m_timerFactory{timerFactory}, m_activeRequests{std::move(activeRequests)}, m_decryptionService{decryptionService}, + m_currentPlaybackState{PlaybackState::UNKNOWN}, m_wasAllSourcesAttachedCalled{false} +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + m_mainThread = mainThreadFactory->getMainThread(); + if (!m_mainThread) + { + throw std::runtime_error("Failed to get the main thread"); + } + m_mainThreadClientId = m_mainThread->registerClient(); + + bool result = false; + auto task = [&]() + { + if (!m_shmBuffer->mapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId)) + { + RIALTO_SERVER_LOG_ERROR("Unable to map shm partition"); + } + else + { + result = true; + } + }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + if (!result) + { + throw std::runtime_error("MediaPipelineServerInternal construction failed"); + } +} + +MediaPipelineServerInternal::~MediaPipelineServerInternal() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() + { + for (const auto &timer : m_needMediaDataTimers) + { + if (timer.second && timer.second->isActive()) + { + timer.second->cancel(); + } + } + if (!m_shmBuffer->unmapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId)) + { + RIALTO_SERVER_LOG_ERROR("Unable to unmap shm partition"); + } + + m_shmBuffer.reset(); + m_mainThread->unregisterClient(m_mainThreadClientId); + }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +bool MediaPipelineServerInternal::load(MediaType type, const std::string &mimeType, const std::string &url) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = loadInternal(type, mimeType, url); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::loadInternal(MediaType type, const std::string &mimeType, const std::string &url) +{ + std::unique_lock lock{m_getPositionMutex}; + /* If gstreamer player already created, destroy the old one first */ + if (m_gstPlayer) + { + m_gstPlayer.reset(); + } + + m_gstPlayer = + m_kGstPlayerFactory + ->createGstGenericPlayer(this, m_decryptionService, type, m_kVideoRequirements, + firebolt::rialto::wrappers::IRdkGstreamerUtilsWrapperFactory::getFactory()); + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to load gstreamer player"); + return false; + } + + notifyNetworkState(NetworkState::BUFFERING); + + return true; +} + +bool MediaPipelineServerInternal::attachSource(const std::unique_ptr &source) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = attachSourceInternal(source); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::attachSourceInternal(const std::unique_ptr &source) +{ + source->setId(-1); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Gstreamer player has not been loaded"); + return false; + } + + if (source->getType() == MediaSourceType::UNKNOWN) + { + RIALTO_SERVER_LOG_ERROR("Media source type unknown"); + return false; + } + + m_gstPlayer->attachSource(source); + + const auto kSourceIter = m_attachedSources.find(source->getType()); + if (m_attachedSources.cend() == kSourceIter) + { + source->setId(generateSourceId()); + RIALTO_SERVER_LOG_DEBUG("New ID generated for MediaSourceType: %s: %d", + common::convertMediaSourceType(source->getType()), source->getId()); + m_attachedSources.emplace(source->getType(), source->getId()); + } + else + { + RIALTO_SERVER_LOG_WARN("SourceType '%s' already attached", common::convertMediaSourceType(source->getType())); + return false; + } + + return true; +} + +bool MediaPipelineServerInternal::removeSource(int32_t id) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = removeSourceInternal(id); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::removeSourceInternal(int32_t id) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to remove source - Gstreamer player has not been loaded"); + return false; + } + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [id](const auto &src) { return src.second == id; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to remove source with id %d- Source not found", id); + return false; + } + + m_gstPlayer->removeSource(sourceIter->first); + m_needMediaDataTimers.erase(sourceIter->first); + m_attachedSources.erase(sourceIter); + return true; +} + +bool MediaPipelineServerInternal::allSourcesAttached() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = allSourcesAttachedInternal(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::allSourcesAttachedInternal() +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to notify all sources attached - Gstreamer player has not been loaded"); + return false; + } + + if (m_wasAllSourcesAttachedCalled) + { + RIALTO_SERVER_LOG_WARN("Failed to notify all sources attached - It was already called"); + return false; + } + + m_gstPlayer->allSourcesAttached(); + m_wasAllSourcesAttachedCalled = true; + return true; +} + +bool MediaPipelineServerInternal::play() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = playInternal(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::playInternal() +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to play - Gstreamer player has not been loaded"); + return false; + } + + m_gstPlayer->play(); + return true; +} + +bool MediaPipelineServerInternal::pause() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = pauseInternal(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::pauseInternal() +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to pause - Gstreamer player has not been loaded"); + return false; + } + + m_gstPlayer->pause(); + return true; +} + +bool MediaPipelineServerInternal::stop() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = stopInternal(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::stopInternal() +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to stop - Gstreamer player has not been loaded"); + return false; + } + + m_gstPlayer->stop(); + return true; +} + +bool MediaPipelineServerInternal::setPlaybackRate(double rate) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setPlaybackRateInternal(rate); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setPlaybackRateInternal(double rate) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set playback rate - Gstreamer player has not been loaded"); + return false; + } + + if (0.0 == rate) + { + RIALTO_SERVER_LOG_ERROR("Failed to set playback rate to 0.0 - pause method should be used instead."); + return false; + } + + m_gstPlayer->setPlaybackRate(rate); + return true; +} + +bool MediaPipelineServerInternal::setPosition(int64_t position) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setPositionInternal(position); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setPositionInternal(int64_t position) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set position - Gstreamer player has not been loaded"); + return false; + } + + m_gstPlayer->setPosition(position); + + // Reset Eos on seek + for (auto &isMediaTypeEos : m_isMediaTypeEosMap) + { + isMediaTypeEos.second = false; + } + + return true; +} + +bool MediaPipelineServerInternal::getPosition(int64_t &position) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + std::shared_lock lock{m_getPositionMutex}; + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get position - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->getPosition(position); +} + +bool MediaPipelineServerInternal::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = getStatsInternal(sourceId, renderedFrames, droppedFrames); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getStatsInternal(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get stats - Gstreamer player has not been loaded"); + return false; + } + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to get stats - Source not found"); + return false; + } + return m_gstPlayer->getStats(sourceIter->first, renderedFrames, droppedFrames); +} + +bool MediaPipelineServerInternal::setImmediateOutput(int32_t sourceId, bool immediateOutput) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setImmediateOutputInternal(sourceId, immediateOutput); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setImmediateOutputInternal(int32_t sourceId, bool immediateOutput) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded"); + return false; + } + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed - Source not found"); + return false; + } + + m_IsLowLatencyVideoPlayer = immediateOutput; + return m_gstPlayer->setImmediateOutput(sourceIter->first, immediateOutput); +} + +bool MediaPipelineServerInternal::getImmediateOutput(int32_t sourceId, bool &immediateOutput) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = getImmediateOutputInternal(sourceId, immediateOutput); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getImmediateOutputInternal(int32_t sourceId, bool &immediateOutput) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded"); + return false; + } + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed - Source not found"); + return false; + } + return m_gstPlayer->getImmediateOutput(sourceIter->first, immediateOutput); +} + +bool MediaPipelineServerInternal::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setVideoWindowInternal(x, y, width, height); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setVideoWindowInternal(uint32_t x, uint32_t y, uint32_t width, uint32_t height) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set video window - Gstreamer player has not been loaded"); + return false; + } + + m_gstPlayer->setVideoGeometry(x, y, width, height); + return true; +} + +bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t needDataRequestId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = haveDataInternal(status, needDataRequestId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t needDataRequestId) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded"); + return false; + } + + MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId); + if (MediaSourceType::UNKNOWN == mediaSourceType) + { + RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId); + return true; + } + + unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType]; + if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS) + { + // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS. + + ++counter; + if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES) + { + RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u " + "consecutively for mediaSourceType: %s", + needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType)); + } + else + { + RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status: %s", + common::convertMediaSourceType(mediaSourceType), needDataRequestId, toString(status)); + counter = 0; + } + + m_activeRequests->erase(needDataRequestId); + scheduleNotifyNeedMediaData(mediaSourceType); + return true; + } + else + { + RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status", + common::convertMediaSourceType(mediaSourceType), needDataRequestId); + counter = 0; + } + + try + { + const IMediaPipeline::MediaSegmentVector &kSegments = m_activeRequests->getSegments(needDataRequestId); + m_gstPlayer->attachSamples(kSegments); + } + catch (const std::runtime_error &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to get segments %s", e.what()); + m_activeRequests->erase(needDataRequestId); + return false; + } + + m_activeRequests->erase(needDataRequestId); + if (status == MediaSourceStatus::EOS) + { + m_gstPlayer->setEos(mediaSourceType); + m_isMediaTypeEosMap[mediaSourceType] = true; + } + + return true; +} + +bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = haveDataInternal(status, numFrames, needDataRequestId); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t numFrames, + uint32_t needDataRequestId) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded"); + return false; + } + MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId); + if (MediaSourceType::UNKNOWN == mediaSourceType) + { + RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId); + return true; + } + m_activeRequests->erase(needDataRequestId); + + unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType]; + if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS) + { + // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS. + + ++counter; + if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES) + { + RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u " + "consecutively for mediaSourceType: %s", + needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType)); + } + else + { + RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status", + common::convertMediaSourceType(mediaSourceType), needDataRequestId); + counter = 0; + } + scheduleNotifyNeedMediaData(mediaSourceType); + return true; + } + else + { + RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status", + common::convertMediaSourceType(mediaSourceType), needDataRequestId); + counter = 0; + } + + uint8_t *buffer = m_shmBuffer->getBuffer(); + if (!buffer) + { + RIALTO_SERVER_LOG_ERROR("No buffer available"); + notifyPlaybackState(PlaybackState::FAILURE); + return false; + } + + std::uint32_t regionOffset = 0; + try + { + regionOffset = + m_shmBuffer->getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType); + } + catch (const std::runtime_error &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to get region's buffer offset, reason: %s", e.what()); + notifyPlaybackState(PlaybackState::FAILURE); + return false; + } + + if (0 != numFrames) + { + std::shared_ptr dataReader = + m_dataReaderFactory->createDataReader(mediaSourceType, buffer, regionOffset, numFrames); + if (!dataReader) + { + RIALTO_SERVER_LOG_ERROR("Metadata version not supported for %s request id: %u", + common::convertMediaSourceType(mediaSourceType), needDataRequestId); + notifyPlaybackState(PlaybackState::FAILURE); + return false; + } + m_gstPlayer->attachSamples(dataReader); + } + if (status == MediaSourceStatus::EOS) + { + m_gstPlayer->setEos(mediaSourceType); + m_isMediaTypeEosMap[mediaSourceType] = true; + } + + return true; +} + +void MediaPipelineServerInternal::ping(std::unique_ptr &&heartbeatHandler) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() { pingInternal(std::move(heartbeatHandler)); }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::pingInternal(std::unique_ptr &&heartbeatHandler) +{ + if (!m_gstPlayer) + { + // No need to check GstPlayer worker thread, we reached this function, so main thread is working fine. + heartbeatHandler.reset(); + return; + } + // Check GstPlayer worker thread + m_gstPlayer->ping(std::move(heartbeatHandler)); +} + +bool MediaPipelineServerInternal::renderFrame() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = renderFrameInternal(); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::renderFrameInternal() +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("renderFrame failed - Gstreamer player has not been loaded"); + return false; + } + + m_gstPlayer->renderFrame(); + return true; +} + +bool MediaPipelineServerInternal::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setVolumeInternal(targetVolume, volumeDuration, easeType); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setVolumeInternal(double targetVolume, uint32_t volumeDuration, EaseType easeType) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set volume - Gstreamer player has not been loaded"); + return false; + } + m_gstPlayer->setVolume(targetVolume, volumeDuration, easeType); + return true; +} + +bool MediaPipelineServerInternal::getVolume(double ¤tVolume) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = getVolumeInternal(currentVolume); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getVolumeInternal(double ¤tVolume) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get volume - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->getVolume(currentVolume); +} + +bool MediaPipelineServerInternal::setMute(std::int32_t sourceId, bool mute) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setMuteInternal(sourceId, mute); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setMuteInternal(std::int32_t sourceId, bool mute) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set mute - Gstreamer player has not been loaded"); + return false; + } + + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to set mute - Source with id: %d not found", sourceId); + return false; + } + + m_gstPlayer->setMute(sourceIter->first, mute); + + return true; +} + +bool MediaPipelineServerInternal::getMute(std::int32_t sourceId, bool &mute) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = getMuteInternal(sourceId, mute); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getMuteInternal(std::int32_t sourceId, bool &mute) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded"); + return false; + } + + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to get mute - Source with id: %d not found", sourceId); + return false; + } + + return m_gstPlayer->getMute(sourceIter->first, mute); +} + +bool MediaPipelineServerInternal::setTextTrackIdentifier(const std::string &textTrackIdentifier) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setTextTrackIdentifierInternal(textTrackIdentifier); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setTextTrackIdentifierInternal(const std::string &textTrackIdentifier) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set text track identifier - Gstreamer player has not been loaded"); + return false; + } + + m_gstPlayer->setTextTrackIdentifier(textTrackIdentifier); + + return true; +} + +bool MediaPipelineServerInternal::getTextTrackIdentifier(std::string &textTrackIdentifier) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = getTextTrackIdentifierInternal(textTrackIdentifier); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getTextTrackIdentifierInternal(std::string &textTrackIdentifier) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded"); + return false; + } + + return m_gstPlayer->getTextTrackIdentifier(textTrackIdentifier); +} + +bool MediaPipelineServerInternal::flush(int32_t sourceId, bool resetTime, bool &async) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = flushInternal(sourceId, resetTime, async); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setLowLatency(bool lowLatency) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setLowLatencyInternal(lowLatency); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setLowLatencyInternal(bool lowLatency) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set low latency - Gstreamer player has not been loaded"); + return false; + } + m_IsLowLatencyAudioPlayer = lowLatency; + + return m_gstPlayer->setLowLatency(lowLatency); +} + +bool MediaPipelineServerInternal::setSync(bool sync) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setSyncInternal(sync); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setSyncInternal(bool sync) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set sync - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->setSync(sync); +} + +bool MediaPipelineServerInternal::getSync(bool &sync) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = getSyncInternal(sync); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getSyncInternal(bool &sync) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get sync - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->getSync(sync); +} + +bool MediaPipelineServerInternal::setSyncOff(bool syncOff) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setSyncOffInternal(syncOff); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setSyncOffInternal(bool syncOff) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set sync off - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->setSyncOff(syncOff); +} + +bool MediaPipelineServerInternal::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setStreamSyncModeInternal(sourceId, streamSyncMode); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setStreamSyncModeInternal(int32_t sourceId, int32_t streamSyncMode) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Gstreamer player has not been loaded"); + return false; + } + + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Source with id: %d not found", sourceId); + return false; + } + + return m_gstPlayer->setStreamSyncMode(sourceIter->first, streamSyncMode); +} + +bool MediaPipelineServerInternal::getStreamSyncMode(int32_t &streamSyncMode) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = getStreamSyncModeInternal(streamSyncMode); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getStreamSyncModeInternal(int32_t &streamSyncMode) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get stream sync mode - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->getStreamSyncMode(streamSyncMode); +} + +bool MediaPipelineServerInternal::flushInternal(int32_t sourceId, bool resetTime, bool &async) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to flush - Gstreamer player has not been loaded"); + return false; + } + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to flush - Source with id: %d not found", sourceId); + return false; + } + + m_gstPlayer->flush(sourceIter->first, resetTime, async); + + // Reset Eos on flush + auto it = m_isMediaTypeEosMap.find(sourceIter->first); + if (it != m_isMediaTypeEosMap.end() && it->second) + { + it->second = false; + } + + return true; +} + +bool MediaPipelineServerInternal::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setSourcePositionInternal(sourceId, position, resetTime, appliedRate, stopPosition); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setSourcePositionInternal(int32_t sourceId, int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set source position - Gstreamer player has not been loaded"); + return false; + } + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to set source position - Source with id: %d not found", sourceId); + return false; + } + + m_gstPlayer->setSourcePosition(sourceIter->first, position, resetTime, appliedRate, stopPosition); + + // Reset Eos on seek + auto it = m_isMediaTypeEosMap.find(sourceIter->first); + if (it != m_isMediaTypeEosMap.end() && it->second) + { + it->second = false; + } + + return true; +} + +bool MediaPipelineServerInternal::setSubtitleOffset(int32_t sourceId, int64_t position) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = setSubtitleOffsetInternal(sourceId, position); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setSubtitleOffsetInternal(int32_t sourceId, int64_t position) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Gstreamer player has not been loaded"); + return false; + } + auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), + [sourceId](const auto &src) { return src.second == sourceId; }); + if (sourceIter == m_attachedSources.end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Source with id: %d not found", sourceId); + return false; + } + + m_gstPlayer->setSubtitleOffset(position); + return true; +} + +bool MediaPipelineServerInternal::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, + bool audioAac) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result; + auto task = [&]() { result = processAudioGapInternal(position, duration, discontinuityGap, audioAac); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::processAudioGapInternal(int64_t position, uint32_t duration, int64_t discontinuityGap, + bool audioAac) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to process audio gap - Gstreamer player has not been loaded"); + return false; + } + m_gstPlayer->processAudioGap(position, duration, discontinuityGap, audioAac); + return true; +} + +bool MediaPipelineServerInternal::setBufferingLimit(uint32_t limitBufferingMs) +{ + bool result; + auto task = [&]() { result = setBufferingLimitInternal(limitBufferingMs); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setBufferingLimitInternal(uint32_t limitBufferingMs) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set buffering limit - Gstreamer player has not been loaded"); + return false; + } + m_gstPlayer->setBufferingLimit(limitBufferingMs); + return true; +} + +bool MediaPipelineServerInternal::getBufferingLimit(uint32_t &limitBufferingMs) +{ + bool result; + auto task = [&]() { result = getBufferingLimitInternal(limitBufferingMs); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getBufferingLimitInternal(uint32_t &limitBufferingMs) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get buffering limit - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->getBufferingLimit(limitBufferingMs); +} + +bool MediaPipelineServerInternal::setUseBuffering(bool useBuffering) +{ + bool result; + auto task = [&]() { result = setUseBufferingInternal(useBuffering); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::setUseBufferingInternal(bool useBuffering) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to set use buffering - Gstreamer player has not been loaded"); + return false; + } + m_gstPlayer->setUseBuffering(useBuffering); + return true; +} + +bool MediaPipelineServerInternal::getUseBuffering(bool &useBuffering) +{ + bool result; + auto task = [&]() { result = getUseBufferingInternal(useBuffering); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::getUseBufferingInternal(bool &useBuffering) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to get use buffering - Gstreamer player has not been loaded"); + return false; + } + return m_gstPlayer->getUseBuffering(useBuffering); +} + +bool MediaPipelineServerInternal::switchSource(const std::unique_ptr &source) +{ + bool result; + auto task = [&]() { result = switchSourceInternal(source); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return result; +} + +bool MediaPipelineServerInternal::switchSourceInternal(const std::unique_ptr &source) +{ + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to switch source - Gstreamer player has not been loaded"); + return false; + } + m_gstPlayer->switchSource(source); + return true; +} + +AddSegmentStatus MediaPipelineServerInternal::addSegment(uint32_t needDataRequestId, + const std::unique_ptr &mediaSegment) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + AddSegmentStatus status{AddSegmentStatus::ERROR}; + auto task = [&]() { status = addSegmentInternal(needDataRequestId, mediaSegment); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +AddSegmentStatus MediaPipelineServerInternal::addSegmentInternal(uint32_t needDataRequestId, + const std::unique_ptr &mediaSegment) +{ + AddSegmentStatus status = m_activeRequests->addSegment(needDataRequestId, mediaSegment); + if (status != AddSegmentStatus::OK) + { + RIALTO_SERVER_LOG_ERROR("Failed to add segment for request id: %u", needDataRequestId); + } + + return status; +} + +std::weak_ptr MediaPipelineServerInternal::getClient() +{ + return m_mediaPipelineClient; +} + +void MediaPipelineServerInternal::notifyPlaybackState(PlaybackState state) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (m_mediaPipelineClient) + { + m_mediaPipelineClient->notifyPlaybackState(state); + } + auto task = [&, state]() { m_currentPlaybackState = state; }; + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +bool MediaPipelineServerInternal::notifyNeedMediaData(MediaSourceType mediaSourceType) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + // the task won't execute for a disconnected client therefore + // set a default value of true which will help to stop any further + // action being taken + bool result{true}; + + auto task = [&]() { result = notifyNeedMediaDataInternal(mediaSourceType); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + + return result; +} + +bool MediaPipelineServerInternal::notifyNeedMediaDataInternal(MediaSourceType mediaSourceType) +{ + m_needMediaDataTimers.erase(mediaSourceType); + m_shmBuffer->clearData(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType); + const auto kSourceIter = m_attachedSources.find(mediaSourceType); + + if (m_attachedSources.cend() == kSourceIter) + { + RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s - sourceId not found", + common::convertMediaSourceType(mediaSourceType)); + return false; + } + auto it = m_isMediaTypeEosMap.find(mediaSourceType); + if (it != m_isMediaTypeEosMap.end() && it->second) + { + RIALTO_SERVER_LOG_INFO("EOS, NeedMediaData not needed for %s", common::convertMediaSourceType(mediaSourceType)); + return false; + } + NeedMediaData event{m_mediaPipelineClient, *m_activeRequests, *m_shmBuffer, m_sessionId, + mediaSourceType, kSourceIter->second, m_currentPlaybackState}; + if (!event.send()) + { + RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s", + common::convertMediaSourceType(mediaSourceType)); + return false; + } + + RIALTO_SERVER_LOG_DEBUG("%s NeedMediaData sent.", common::convertMediaSourceType(mediaSourceType)); + + return true; +} + +void MediaPipelineServerInternal::notifyPosition(std::int64_t position) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, position]() + { + if (m_mediaPipelineClient) + { + m_mediaPipelineClient->notifyPosition(position); + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::notifyNetworkState(NetworkState state) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, state]() + { + if (m_mediaPipelineClient) + { + m_mediaPipelineClient->notifyNetworkState(state); + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::clearActiveRequestsCache() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() { m_activeRequests->clear(); }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::invalidateActiveRequests(const MediaSourceType &type) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, type]() { m_activeRequests->erase(type); }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, mediaSourceType, qosInfo]() + { + if (m_mediaPipelineClient) + { + const auto kSourceIter = m_attachedSources.find(mediaSourceType); + if (m_attachedSources.cend() == kSourceIter) + { + RIALTO_SERVER_LOG_WARN("Qos notification failed - sourceId not found for %s", + common::convertMediaSourceType(mediaSourceType)); + return; + } + m_mediaPipelineClient->notifyQos(kSourceIter->second, qosInfo); + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::notifyBufferUnderflow(MediaSourceType mediaSourceType) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, mediaSourceType]() + { + if (m_mediaPipelineClient) + { + const auto kSourceIter = m_attachedSources.find(mediaSourceType); + if (m_attachedSources.cend() == kSourceIter) + { + RIALTO_SERVER_LOG_WARN("Buffer underflow notification failed - sourceId not found for %s", + common::convertMediaSourceType(mediaSourceType)); + return; + } + m_mediaPipelineClient->notifyBufferUnderflow(kSourceIter->second); + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, mediaSourceType, error]() + { + if (m_mediaPipelineClient) + { + const auto kSourceIter = m_attachedSources.find(mediaSourceType); + if (m_attachedSources.cend() == kSourceIter) + { + RIALTO_SERVER_LOG_WARN("Playback error notification failed - sourceId not found for %s", + common::convertMediaSourceType(mediaSourceType)); + return; + } + m_mediaPipelineClient->notifyPlaybackError(kSourceIter->second, error); + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::notifySourceFlushed(MediaSourceType mediaSourceType) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, mediaSourceType]() + { + if (m_mediaPipelineClient) + { + const auto kSourceIter = m_attachedSources.find(mediaSourceType); + if (m_attachedSources.cend() == kSourceIter) + { + RIALTO_SERVER_LOG_WARN("Source flushed notification failed - sourceId not found for: %s", + common::convertMediaSourceType(mediaSourceType)); + return; + } + m_mediaPipelineClient->notifySourceFlushed(kSourceIter->second); + RIALTO_SERVER_LOG_DEBUG("%s source flushed", common::convertMediaSourceType(mediaSourceType)); + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +void MediaPipelineServerInternal::scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + auto timer = m_needMediaDataTimers.find(mediaSourceType); + if (m_needMediaDataTimers.end() != timer && timer->second && timer->second->isActive()) + { + RIALTO_SERVER_LOG_DEBUG("Skip scheduling need media data for %s - it is already scheduled", + common::convertMediaSourceType(mediaSourceType)); + return; + } + + m_needMediaDataTimers[mediaSourceType] = + m_timerFactory + ->createTimer(getNeedMediaDataTimeout(mediaSourceType), + [this, mediaSourceType]() + { + m_mainThread + ->enqueueTask(m_mainThreadClientId, + [this, mediaSourceType]() + { + m_needMediaDataTimers.erase(mediaSourceType); + if (!notifyNeedMediaDataInternal(mediaSourceType)) + { + RIALTO_SERVER_LOG_WARN("Scheduled Need media data sending " + "failed for: %s. Scheduling again...", + common::convertMediaSourceType( + mediaSourceType)); + scheduleNotifyNeedMediaData(mediaSourceType); + } + }); + }); +} + +std::chrono::milliseconds MediaPipelineServerInternal::getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const +{ + constexpr std::chrono::milliseconds kDefaultNeedMediaDataResendTimeMs{15}; + constexpr std::chrono::milliseconds kNeedMediaDataResendTimeMsForLowLatency{5}; + if ((mediaSourceType == MediaSourceType::VIDEO && m_IsLowLatencyVideoPlayer) || + (mediaSourceType == MediaSourceType::AUDIO && m_IsLowLatencyAudioPlayer)) + { + return kNeedMediaDataResendTimeMsForLowLatency; + } + return kDefaultNeedMediaDataResendTimeMs; +} +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/NeedMediaData.cpp b/middleware/rialto-client/media/server/main/source/NeedMediaData.cpp new file mode 100644 index 000000000..19a00b7a7 --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/NeedMediaData.cpp @@ -0,0 +1,81 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "NeedMediaData.h" +#include "IActiveRequests.h" +#include "IMediaPipelineClient.h" +#include "ISharedMemoryBuffer.h" +#include "RialtoServerLogging.h" +#include "ShmUtils.h" +#include "TypeConverters.h" + +namespace firebolt::rialto::server +{ +NeedMediaData::NeedMediaData(std::weak_ptr client, IActiveRequests &activeRequests, + const ISharedMemoryBuffer &shmBuffer, int sessionId, MediaSourceType mediaSourceType, + std::int32_t sourceId, PlaybackState currentPlaybackState) + : m_client{client}, m_activeRequests{activeRequests}, m_mediaSourceType{mediaSourceType}, m_frameCount{kMaxFrames}, + m_sourceId{sourceId} +{ + if (PlaybackState::PLAYING != currentPlaybackState) + { + RIALTO_SERVER_LOG_DEBUG("Pipeline in prerolling state. Sending smaller frame count for %s", + common::convertMediaSourceType(m_mediaSourceType)); + m_frameCount = kPrerollNumFrames; + } + if (MediaSourceType::AUDIO != mediaSourceType && MediaSourceType::VIDEO != mediaSourceType && + MediaSourceType::SUBTITLE != mediaSourceType) + { + RIALTO_SERVER_LOG_ERROR("Unable to initialize NeedMediaData - unknown mediaSourceType: %s", + common::convertMediaSourceType(m_mediaSourceType)); + m_isValid = false; + return; + } + try + { + m_maxMediaBytes = + shmBuffer.getMaxDataLen(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, sessionId, mediaSourceType) - + getMaxMetadataBytes(); + auto metadataOffset = + shmBuffer.getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, sessionId, mediaSourceType); + auto mediadataOffset = metadataOffset + getMaxMetadataBytes(); + m_shmInfo = std::make_shared( + MediaPlayerShmInfo{getMaxMetadataBytes(), metadataOffset, mediadataOffset, m_maxMediaBytes}); + m_isValid = true; + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Unable to construct NeedMediaData message for %s - %s", + common::convertMediaSourceType(m_mediaSourceType), e.what()); + m_isValid = false; + } +} + +bool NeedMediaData::send() const +{ + auto client = m_client.lock(); + if (client && m_isValid) + { + client->notifyNeedMediaData(m_sourceId, m_frameCount, + m_activeRequests.insert(m_mediaSourceType, m_maxMediaBytes), m_shmInfo); + return true; + } + return false; +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/SharedMemoryBuffer.cpp b/middleware/rialto-client/media/server/main/source/SharedMemoryBuffer.cpp new file mode 100644 index 000000000..75805b751 --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/SharedMemoryBuffer.cpp @@ -0,0 +1,453 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "RialtoServerLogging.h" +#include "SharedMemoryBuffer.h" +#include "TypeConverters.h" + +#if !defined(SYS_memfd_create) +#if defined(__NR_memfd_create) +#define SYS_memfd_create __NR_memfd_create +#elif defined(__arm__) +#define SYS_memfd_create 385 +#endif +#endif + +#if !defined(MFD_CLOEXEC) +#define MFD_CLOEXEC 0x0001U +#endif + +#if !defined(MFD_ALLOW_SEALING) +#define MFD_ALLOW_SEALING 0x0002U +#endif + +#if !defined(F_ADD_SEALS) +#if !defined(F_LINUX_SPECIFIC_BASE) +#define F_LINUX_SPECIFIC_BASE 1024 +#endif +#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) +#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) + +#define F_SEAL_SEAL 0x0001 +#define F_SEAL_SHRINK 0x0002 +#define F_SEAL_GROW 0x0004 +#define F_SEAL_WRITE 0x0008 +#endif + +namespace +{ +const char *kMemoryBufferName{"rialto_avbuf"}; +constexpr int kNoIdAssigned{-1}; +constexpr uint32_t kVideoRegionSize = 7 * 1024 * 1024; // 7MB +constexpr uint32_t kAudioRegionSize = 1 * 1024 * 1024; // 1MB +constexpr uint32_t kSubtitleRegionSize = 256 * 1024; // 256kB +constexpr uint32_t kWebAudioRegionSize = 10 * 1024; // 10KB + +std::vector +calculatePartitionSize(firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType playbackType, int num) +{ + if (firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::GENERIC == playbackType) + { + // As (for now) resolution of playback (for example HD or UHD) is not known, partitions have the same size. + firebolt::rialto::server::SharedMemoryBuffer::Partition singlePlaybackDataBuffer{kNoIdAssigned, kAudioRegionSize, + kVideoRegionSize, + kSubtitleRegionSize}; + return std::vector(num, singlePlaybackDataBuffer); + } + else if (firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO == playbackType) + { + firebolt::rialto::server::SharedMemoryBuffer::Partition webAudioDataBuffer{kNoIdAssigned, kWebAudioRegionSize, 0}; + return std::vector(num, webAudioDataBuffer); + } + else + { + return std::vector(); + } +} + +const char *toString(const firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType &type) +{ + switch (type) + { + case firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::GENERIC: + { + return "GENERIC"; + } + case firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO: + { + return "WEB_AUDIO"; + } + } + return "UNKNOWN"; +} +} // namespace + +namespace firebolt::rialto::server +{ +std::unique_ptr ISharedMemoryBufferFactory::createFactory() +{ + return std::make_unique(); +} + +std::shared_ptr +SharedMemoryBufferFactory::createSharedMemoryBuffer(unsigned numOfPlaybacks, unsigned numOfWebAudioPlayers) const +{ + return std::make_shared(numOfPlaybacks, numOfWebAudioPlayers); +} + +SharedMemoryBuffer::SharedMemoryBuffer(unsigned numOfPlaybacks, unsigned numOfWebAudioPlayers) + : m_genericPartitions{calculatePartitionSize(MediaPlaybackType::GENERIC, numOfPlaybacks)}, + m_webAudioPartitions{calculatePartitionSize(MediaPlaybackType::WEB_AUDIO, numOfWebAudioPlayers)}, + m_dataBufferLen{0}, m_dataBufferFd{-1}, m_dataBuffer{nullptr} +{ + int fd = syscall(SYS_memfd_create, kMemoryBufferName, MFD_CLOEXEC | MFD_ALLOW_SEALING); + if (fd < 0) + { + RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to create memory buffer"); + } + else + { + const size_t kBufferSize{calculateBufferSize()}; + if (ftruncate(fd, static_cast(kBufferSize)) == -1) + { + RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to resize memfd"); + } + else if (fcntl(fd, F_ADD_SEALS, (F_SEAL_SEAL | F_SEAL_GROW | F_SEAL_SHRINK)) == -1) + { + RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to seal memfd"); + } + else + { + void *addr = mmap(nullptr, kBufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (addr != MAP_FAILED) + { + m_dataBufferLen = kBufferSize; + m_dataBufferFd = fd; + m_dataBuffer = reinterpret_cast(addr); + RIALTO_SERVER_LOG_INFO("Shared Memory Buffer size: %d, ptr: %p", m_dataBufferLen, m_dataBuffer); + } + } + + if (m_dataBufferFd == -1) + { + if (close(fd) != 0) + RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to close fd"); + } + } + + if (m_dataBufferFd == -1) + { + RIALTO_SERVER_LOG_ERROR("Shared Memory Buffer initialization failed"); + throw std::runtime_error("Shared Memory Buffer initialization failed"); + } +} + +SharedMemoryBuffer::~SharedMemoryBuffer() +{ + RIALTO_SERVER_LOG_INFO("Destroying Shared Memory Buffer"); + if (m_dataBufferFd != -1) + { + if (munmap(m_dataBuffer, m_dataBufferLen) != 0) + RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to unmap buffer"); + if (close(m_dataBufferFd) != 0) + RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to close data buffer fd"); + + m_dataBufferLen = 0; + m_dataBufferFd = -1; + m_dataBuffer = nullptr; + } +} + +bool SharedMemoryBuffer::mapPartition(MediaPlaybackType playbackType, int id) +{ + std::vector *partitions = getPlaybackTypePartition(playbackType); + if (!partitions) + { + RIALTO_SERVER_LOG_ERROR("Cannot map the partition for playback type %s with id: %d", toString(playbackType), id); + return false; + } + + auto partition = std::find_if(partitions->begin(), partitions->end(), [id](const auto &p) { return p.id == id; }); + if (partition != partitions->end()) + { + RIALTO_SERVER_LOG_DEBUG("Skip to map shm partition for id: %d. - partition already assigned", id); + return true; + } + auto freePartition = + std::find_if(partitions->begin(), partitions->end(), [](const auto &p) { return p.id == kNoIdAssigned; }); + if (freePartition == partitions->end()) + { + RIALTO_SERVER_LOG_ERROR("Failed to map Shm partition for id: %d. No free partition available.", id); + return false; + } + freePartition->id = id; + return true; +} + +bool SharedMemoryBuffer::unmapPartition(MediaPlaybackType playbackType, int id) +{ + std::vector *partitions = getPlaybackTypePartition(playbackType); + if (!partitions) + { + RIALTO_SERVER_LOG_ERROR("Cannot unmap the partition for playback type %s with id: %d", toString(playbackType), + id); + return false; + } + + auto partition = std::find_if(partitions->begin(), partitions->end(), [id](const auto &p) { return p.id == id; }); + if (partition == partitions->end()) + { + RIALTO_SERVER_LOG_WARN("Failed to unmap Shm partition for id: %d. - partition could not be found", id); + return false; + } + partition->id = kNoIdAssigned; + return true; +} + +bool SharedMemoryBuffer::clearData(MediaPlaybackType playbackType, int id, const MediaSourceType &mediaSourceType) const +{ + const std::vector *kPartitions = getPlaybackTypePartition(playbackType); + if (!kPartitions) + { + RIALTO_SERVER_LOG_ERROR("Cannot clear the %s data for playback type %s with id: %d", + common::convertMediaSourceType(mediaSourceType), toString(playbackType), id); + return false; + } + + auto partition = std::find_if(kPartitions->begin(), kPartitions->end(), [id](const auto &p) { return p.id == id; }); + if (partition == kPartitions->end()) + { + RIALTO_SERVER_LOG_WARN("Failed to clear %s data for playback type %s with id: %d. - partition could not be " + "found", + common::convertMediaSourceType(mediaSourceType), toString(playbackType), id); + return false; + } + std::uint8_t *partitionDataPtr = nullptr; + if (!getDataPtrForPartition(playbackType, id, &partitionDataPtr)) + { + RIALTO_SERVER_LOG_ERROR("Failed to clear %s data for playback type %s with id: %d. - could not get partition " + "data " + "ptr", + common::convertMediaSourceType(mediaSourceType), toString(playbackType), id); + return false; + } + + if (MediaSourceType::VIDEO == mediaSourceType) + { + std::uint8_t *videoData = partitionDataPtr; + memset(videoData, 0x00, partition->dataBufferVideoLen); + return true; + } + if (MediaSourceType::AUDIO == mediaSourceType) + { + std::uint8_t *audioData = partitionDataPtr + partition->dataBufferVideoLen; + memset(audioData, 0x00, partition->dataBufferAudioLen); + return true; + } + if (MediaSourceType::SUBTITLE == mediaSourceType) + { + std::uint8_t *subtitleoData = partitionDataPtr + partition->dataBufferVideoLen + partition->dataBufferAudioLen; + memset(subtitleoData, 0x00, partition->dataBufferSubtitleLen); + return true; + } + + return false; +} + +std::uint32_t SharedMemoryBuffer::getDataOffset(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const +{ + std::uint8_t *buffer = getDataPtr(playbackType, id, mediaSourceType); + if (!buffer) + { + throw std::runtime_error("Buffer not found for playback type " + std::string(toString(playbackType)) + + " with id: " + std::to_string(id)); + } + return buffer - m_dataBuffer; +} + +std::uint32_t SharedMemoryBuffer::getMaxDataLen(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const +{ + const std::vector *kPartitions = getPlaybackTypePartition(playbackType); + if (!kPartitions) + { + RIALTO_SERVER_LOG_ERROR("Cannot get the max data length for playback type %s with id: %d type: %s", + toString(playbackType), id, common::convertMediaSourceType(mediaSourceType)); + return false; + } + + auto partition = std::find_if(kPartitions->begin(), kPartitions->end(), [id](const auto &p) { return p.id == id; }); + if (partition == kPartitions->end()) + { + RIALTO_SERVER_LOG_WARN("Failed to get buffer length for playback type %s with id: %d. type: %s- partition " + "could not be " + "found", + toString(playbackType), id, common::convertMediaSourceType(mediaSourceType)); + return 0; + } + + if (MediaSourceType::VIDEO == mediaSourceType) + { + return partition->dataBufferVideoLen; + } + if (MediaSourceType::AUDIO == mediaSourceType) + { + return partition->dataBufferAudioLen; + } + if (MediaSourceType::SUBTITLE == mediaSourceType) + { + return partition->dataBufferSubtitleLen; + } + + return 0; +} + +std::uint8_t *SharedMemoryBuffer::getDataPtr(MediaPlaybackType playbackType, int id, + const MediaSourceType &mediaSourceType) const +{ + const std::vector *kPartitions = getPlaybackTypePartition(playbackType); + if (!kPartitions) + { + RIALTO_SERVER_LOG_ERROR("Cannot get the buffer offset for playback type %s with id: %d, type: %s", + toString(playbackType), id, common::convertMediaSourceType(mediaSourceType)); + return nullptr; + } + + auto partition = std::find_if(kPartitions->begin(), kPartitions->end(), [id](const auto &p) { return p.id == id; }); + if (partition == kPartitions->end()) + { + RIALTO_SERVER_LOG_WARN("Failed to get buffer offset for playback type %s with id: %d, type: %s. - partition " + "could not be " + "found", + toString(playbackType), id, common::convertMediaSourceType(mediaSourceType)); + return nullptr; + } + std::uint8_t *partitionDataPtr = nullptr; + if (!getDataPtrForPartition(playbackType, id, &partitionDataPtr)) + { + RIALTO_SERVER_LOG_ERROR("Failed to get buffer offset for playback type %s with id: %d. - could not get " + "partition data ptr", + toString(playbackType), id); + return nullptr; + } + + if ((MediaSourceType::VIDEO == mediaSourceType) && (0 != partition->dataBufferVideoLen)) + { + return partitionDataPtr; + } + if ((MediaSourceType::AUDIO == mediaSourceType) && (0 != partition->dataBufferAudioLen)) + { + return partitionDataPtr + partition->dataBufferVideoLen; + } + if ((MediaSourceType::SUBTITLE == mediaSourceType) && (0 != partition->dataBufferSubtitleLen)) + { + return partitionDataPtr + partition->dataBufferVideoLen + partition->dataBufferAudioLen; + } + + return nullptr; +} + +int SharedMemoryBuffer::getFd() const +{ + return m_dataBufferFd; +} + +std::uint32_t SharedMemoryBuffer::getSize() const +{ + return m_dataBufferLen; +} + +std::uint8_t *SharedMemoryBuffer::getBuffer() const +{ + return m_dataBuffer; +} + +size_t SharedMemoryBuffer::calculateBufferSize() const +{ + size_t genericSum = + std::accumulate(m_genericPartitions.begin(), m_genericPartitions.end(), 0, [](size_t sum, const Partition &p) + { return sum + p.dataBufferAudioLen + p.dataBufferVideoLen + p.dataBufferSubtitleLen; }); + size_t webAudioSum = std::accumulate(m_webAudioPartitions.begin(), m_webAudioPartitions.end(), 0, + [](size_t sum, const Partition &p) + { return sum + p.dataBufferAudioLen + p.dataBufferVideoLen; }); + return genericSum + webAudioSum; +} + +bool SharedMemoryBuffer::getDataPtrForPartition(MediaPlaybackType playbackType, int id, std::uint8_t **ptr) const +{ + std::uint8_t *result = m_dataBuffer; + + for (const auto &partition : m_genericPartitions) + { + if ((MediaPlaybackType::GENERIC == playbackType) && (partition.id == id)) + { + *ptr = result; + return true; + } + result += (partition.dataBufferVideoLen + partition.dataBufferAudioLen + partition.dataBufferSubtitleLen); + } + + for (const auto &partition : m_webAudioPartitions) + { + if ((MediaPlaybackType::WEB_AUDIO == playbackType) && (partition.id == id)) + { + *ptr = result; + return true; + } + result += (partition.dataBufferVideoLen + partition.dataBufferAudioLen + partition.dataBufferSubtitleLen); + } + + RIALTO_SERVER_LOG_ERROR("Could not find the data ptr for playback type %s with id: %d", toString(playbackType), id); + return false; +} +const std::vector * +SharedMemoryBuffer::getPlaybackTypePartition(MediaPlaybackType playbackType) const +{ + if (firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::GENERIC == playbackType) + { + return &m_genericPartitions; + } + else if (firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO == playbackType) + { + return &m_webAudioPartitions; + } + else + { + RIALTO_SERVER_LOG_ERROR("Invalid playback type"); + return nullptr; + } +} + +std::vector *SharedMemoryBuffer::getPlaybackTypePartition(MediaPlaybackType playbackType) +{ + return const_cast *>( + const_cast(this)->getPlaybackTypePartition(playbackType)); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/TextTrackAccessor.cpp b/middleware/rialto-client/media/server/main/source/TextTrackAccessor.cpp new file mode 100644 index 000000000..a04b8c9c5 --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/TextTrackAccessor.cpp @@ -0,0 +1,310 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "TextTrackAccessor.h" + +#include +#include +#include + +namespace firebolt::rialto::server +{ +ITextTrackAccessorFactory &ITextTrackAccessorFactory::getFactory() +{ + static TextTrackAccessorFactory factory; + return factory; +} + +std::shared_ptr TextTrackAccessorFactory::getTextTrackAccessor() const +try +{ + static std::shared_ptr textTrackAccessor{ + std::make_shared(firebolt::rialto::wrappers::ITextTrackPluginWrapperFactory::getFactory() + ->getTextTrackPluginWrapper(), + firebolt::rialto::wrappers::IThunderWrapperFactory::getFactory() + ->getThunderWrapper())}; + + return textTrackAccessor; +} +catch (const std::exception &e) +{ + return nullptr; +} + +TextTrackAccessor::TextTrackAccessor( + const std::shared_ptr &textTrackPluginWrapper, + const std::shared_ptr &thunderWrapper) + : m_textTrackPluginWrapper{textTrackPluginWrapper}, m_thunderWrapper{thunderWrapper} +{ + if (!createTextTrackControlInterface()) + { + RIALTO_SERVER_LOG_ERROR("Failed to create TextTrack interfaces"); + throw std::runtime_error("Failed to create TextTrack interfaces"); + } +} + +TextTrackAccessor::~TextTrackAccessor() {} + +std::optional TextTrackAccessor::openSession(const std::string &displayName) +{ + uint32_t sessionId = {}; + uint32_t result = m_textTrackWrapper->openSession(displayName, sessionId); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_MIL("TextTrack session %u created with display '%s'", sessionId, displayName.c_str()); + return sessionId; + } + + RIALTO_SERVER_LOG_ERROR("Failed to create TextTrack session with display '%s'; error '%s'", displayName.c_str(), + m_thunderWrapper->errorToString(result)); + return std::nullopt; +} + +bool TextTrackAccessor::closeSession(uint32_t sessionId) +{ + uint32_t result = m_textTrackWrapper->closeSession(sessionId); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_MIL("TextTrack session %u closed", sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to close TextTrack session %u; error %s", sessionId, + m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::pause(uint32_t sessionId) +{ + uint32_t result = m_textTrackWrapper->pauseSession(sessionId); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_INFO("TextTrack session %u paused", sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to pause TextTrack session %u; error %s", sessionId, + m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::play(uint32_t sessionId) +{ + uint32_t result = m_textTrackWrapper->resumeSession(sessionId); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_INFO("TextTrack session %u resumed", sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to resume TextTrack session %u; error %s", sessionId, + m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::mute(uint32_t sessionId, bool mute) +{ + if (mute) + { + uint32_t result = m_textTrackWrapper->muteSession(sessionId); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_INFO("TextTrack session %u muted", sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to mute TextTrack session %u; error %s", sessionId, + m_thunderWrapper->errorToString(result)); + } + else + { + uint32_t result = m_textTrackWrapper->unmuteSession(sessionId); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_INFO("TextTrack session %u unmuted", sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to unmute TextTrack session %u; error %s", sessionId, + m_thunderWrapper->errorToString(result)); + } + + return false; +} + +bool TextTrackAccessor::setPosition(uint32_t sessionId, uint64_t mediaTimestampMs) +{ + uint32_t result = m_textTrackWrapper->sendSessionTimestamp(sessionId, mediaTimestampMs); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_INFO("TextTrack session %u set position to %" PRIu64, sessionId, mediaTimestampMs); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to set position of TextTrack session %u to %" PRIu64 "; error %s", sessionId, + mediaTimestampMs, m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs) +{ + firebolt::rialto::wrappers::ITextTrackWrapper::DataType wrapperDataType{}; + if (datatype == DataType::WebVTT) + { + wrapperDataType = firebolt::rialto::wrappers::ITextTrackWrapper::DataType::WEBVTT; + } + else if (datatype == DataType::TTML) + { + wrapperDataType = firebolt::rialto::wrappers::ITextTrackWrapper::DataType::TTML; + } + else if (datatype == DataType::CC) + { + RIALTO_SERVER_LOG_WARN("Data received for ClosedCaptions. It should not happen."); + return false; + } + else + { + RIALTO_SERVER_LOG_ERROR("Unknown data type"); + return false; + } + + const uint32_t result = m_textTrackWrapper->sendSessionData(sessionId, wrapperDataType, displayOffsetMs, data); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_DEBUG("Sending data to TextTrack session %u was successful; size %zu", sessionId, data.size()); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to send data to TextTrack session %u; error %s", sessionId, + m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::createTextTrackControlInterface() +{ + if (!m_textTrackPluginWrapper) + { + RIALTO_SERVER_LOG_ERROR("TextTrackPlugin is null!"); + return false; + } + + uint32_t openResult = m_textTrackPluginWrapper->open(); + + if (m_thunderWrapper->isSuccessful(openResult)) + { + if (m_textTrackPluginWrapper->isOperational()) + { + m_textTrackWrapper = m_textTrackPluginWrapper->interface(); + if (m_textTrackWrapper) + { + RIALTO_SERVER_LOG_INFO("Created TextTrack interface"); + return true; + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to create TextTrack interface"); + } + } + else + { + RIALTO_SERVER_LOG_ERROR("TextTrack plugin is NOT operational"); + } + } + else + { + RIALTO_SERVER_LOG_ERROR("Failed to open TextTrack plugin; error '%s'", + m_thunderWrapper->errorToString(openResult)); + } + + return false; +} + +bool TextTrackAccessor::setSessionWebVTTSelection(uint32_t sessionId) +{ + uint32_t result = m_textTrackWrapper->setSessionWebVTTSelection(sessionId); + + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_INFO("Setting WebVTT selection for session %u was successful", sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to set WebVTT selection for session %u; error %s", sessionId, + m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::setSessionTTMLSelection(uint32_t sessionId) +{ + uint32_t result = m_textTrackWrapper->setSessionTTMLSelection(sessionId); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_INFO("Setting TTML selection for session %u was successful", sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to set TTML selection for session %u; error %s", sessionId, + m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::setSessionCCSelection(uint32_t sessionId, const std::string &service) +{ + uint32_t result = m_textTrackWrapper->setSessionClosedCaptionsService(sessionId, service); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_INFO("Setting CC selection service '%s' for session %u was successful", service.c_str(), + sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to set CC selection service '%s' for session %u; error %s", service.c_str(), + sessionId, m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::resetSession(uint32_t sessionId) +{ + uint32_t result = m_textTrackWrapper->resetSession(sessionId); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_MIL("Resseting session %u was successful", sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to reset session %u; error %s", sessionId, m_thunderWrapper->errorToString(result)); + return false; +} + +bool TextTrackAccessor::associateVideoDecoder(uint32_t sessionId, const std::string &videoDecoder) +{ + uint32_t result = m_textTrackWrapper->associateVideoDecoder(sessionId, videoDecoder); + if (m_thunderWrapper->isSuccessful(result)) + { + RIALTO_SERVER_LOG_MIL("Associating video decoder '%s' with session %u was successful", videoDecoder.c_str(), + sessionId); + return true; + } + + RIALTO_SERVER_LOG_ERROR("Failed to associate video decoder '%s' with session %u; error %s", videoDecoder.c_str(), + sessionId, m_thunderWrapper->errorToString(result)); + return false; +} + +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/TextTrackSession.cpp b/middleware/rialto-client/media/server/main/source/TextTrackSession.cpp new file mode 100644 index 000000000..fe0f45d46 --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/TextTrackSession.cpp @@ -0,0 +1,165 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "TextTrackSession.h" +#include "ITextTrackAccessor.h" +#include "RialtoServerLogging.h" +#include + +namespace firebolt::rialto::server +{ +ITextTrackSessionFactory &ITextTrackSessionFactory::getFactory() +{ + static TextTrackSessionFactory factory; + return factory; +} + +std::unique_ptr TextTrackSessionFactory::createTextTrackSession(const std::string &display) const +{ + return std::make_unique(display, ITextTrackAccessorFactory::getFactory()); +} + +TextTrackSession::TextTrackSession(const std::string &displayName, + const ITextTrackAccessorFactory &textTrackAccessorFactory) +{ + m_textTrackAccessor = textTrackAccessorFactory.getTextTrackAccessor(); + if (!m_textTrackAccessor) + { + RIALTO_SERVER_LOG_ERROR("Failed to get TextTrackAccessor"); + throw std::runtime_error("Failed to get TextTrackAccessor"); + } + + std::optional sessionId = m_textTrackAccessor->openSession(displayName); + if (!sessionId) + { + RIALTO_SERVER_LOG_ERROR("Failed to create TextTrack session"); + throw std::runtime_error("Failed to create TextTrack session"); + } + + m_sessionId = sessionId.value(); +} + +TextTrackSession::~TextTrackSession() +{ + m_textTrackAccessor->closeSession(m_sessionId); +} + +bool TextTrackSession::resetSession(bool isMuted) +{ + // There is no direct way to clear TextTrack's data. The only option is to reset the session, but that also resets + // the data type and mute values + if (!m_textTrackAccessor->resetSession(m_sessionId)) + { + return false; + } + + bool wasDataTypeSelected = false; + if (m_dataType == ITextTrackAccessor::DataType::WebVTT) + { + wasDataTypeSelected = setSessionWebVTTSelection(); + } + else if (m_dataType == ITextTrackAccessor::DataType::TTML) + { + wasDataTypeSelected = setSessionTTMLSelection(); + } + else if (m_dataType == ITextTrackAccessor::DataType::CC) + { + if (m_ccService.has_value()) + { + wasDataTypeSelected = setSessionCCSelection(m_ccService.value()); + if (m_videoDecoderId.has_value()) + { + wasDataTypeSelected = associateVideoDecoder(m_videoDecoderId.value()); + } + } + else + { + RIALTO_SERVER_LOG_ERROR("CC service not set"); + return false; + } + } + + if (!wasDataTypeSelected) + { + return false; + } + + // changing the data type resets the mute value in TextTrack to its default (false), so we need to set mute + // after selecting the data type + return mute(isMuted); +} + +bool TextTrackSession::pause() +{ + return m_textTrackAccessor->pause(m_sessionId); +} + +bool TextTrackSession::play() +{ + return m_textTrackAccessor->play(m_sessionId); +} + +bool TextTrackSession::mute(bool mute) +{ + return m_textTrackAccessor->mute(m_sessionId, mute); +} + +bool TextTrackSession::setPosition(uint64_t mediaTimestampMs) +{ + return m_textTrackAccessor->setPosition(m_sessionId, mediaTimestampMs); +} + +bool TextTrackSession::sendData(const std::string &data, int64_t displayOffsetMs) +{ + return m_textTrackAccessor->sendData(m_sessionId, data, m_dataType, displayOffsetMs); +} + +bool TextTrackSession::setSessionWebVTTSelection() +{ + m_dataType = ITextTrackAccessor::DataType::WebVTT; + m_ccService = std::optional(); + return m_textTrackAccessor->setSessionWebVTTSelection(m_sessionId); +} + +bool TextTrackSession::setSessionTTMLSelection() +{ + m_dataType = ITextTrackAccessor::DataType::TTML; + m_ccService = std::optional(); + return m_textTrackAccessor->setSessionTTMLSelection(m_sessionId); +} + +bool TextTrackSession::setSessionCCSelection(const std::string &service) +{ + m_dataType = ITextTrackAccessor::DataType::CC; + m_ccService = service; + return m_textTrackAccessor->setSessionCCSelection(m_sessionId, service); +} + +bool TextTrackSession::associateVideoDecoder(uint64_t decoderId) +{ + m_videoDecoderId = decoderId; + std::string decoderIdStr = std::to_string(decoderId); + return m_textTrackAccessor->associateVideoDecoder(m_sessionId, decoderIdStr); +} + +bool TextTrackSession::isClosedCaptions() const +{ + return m_dataType == ITextTrackAccessor::DataType::CC; +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/WebAudioPlayerServerInternal.cpp b/middleware/rialto-client/media/server/main/source/WebAudioPlayerServerInternal.cpp new file mode 100644 index 000000000..ae383012d --- /dev/null +++ b/middleware/rialto-client/media/server/main/source/WebAudioPlayerServerInternal.cpp @@ -0,0 +1,577 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "RialtoServerLogging.h" +#include "WebAudioPlayerServerInternal.h" + +namespace +{ +constexpr uint32_t kPreferredFrames{640}; +constexpr std::chrono::milliseconds kWriteDataTimeMs{100}; +} // namespace + +namespace firebolt::rialto +{ +std::shared_ptr IWebAudioPlayerFactory::createFactory() +{ + return server::IWebAudioPlayerServerInternalFactory::createFactory(); +} +}; // namespace firebolt::rialto + +namespace firebolt::rialto::server +{ +std::shared_ptr IWebAudioPlayerServerInternalFactory::createFactory() +{ + std::shared_ptr factory; + + try + { + factory = std::make_shared(); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player factory, reason: %s", e.what()); + } + + return factory; +} + +std::unique_ptr +WebAudioPlayerServerInternalFactory::createWebAudioPlayer(std::weak_ptr client, + const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config) const +{ + RIALTO_SERVER_LOG_ERROR( + "This function can't be used by rialto server. Please use createWebAudioPlayerServerInternal"); + return nullptr; +} + +std::unique_ptr WebAudioPlayerServerInternalFactory::createWebAudioPlayerServerInternal( + std::weak_ptr client, const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config, const std::shared_ptr &shmBuffer, int handle, + const std::shared_ptr &mainThreadFactory, + const std::shared_ptr &gstPlayerFactory, + std::weak_ptr timerFactory) const +{ + std::unique_ptr webAudioPlayer; + try + { + webAudioPlayer = std::make_unique(client, audioMimeType, priority, config, + shmBuffer, handle, mainThreadFactory, + gstPlayerFactory, timerFactory); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player, reason: %s", e.what()); + } + + return webAudioPlayer; +} + +WebAudioPlayerServerInternal::WebAudioPlayerServerInternal( + std::weak_ptr client, const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr webAudioConfig, const std::shared_ptr &shmBuffer, + int handle, const std::shared_ptr &mainThreadFactory, + const std::shared_ptr &gstPlayerFactory, std::weak_ptr timerFactory) + : m_webAudioPlayerClient(client), m_shmBuffer{shmBuffer}, m_priority{priority}, m_shmId{handle}, m_shmPtr{nullptr}, + m_partitionOffset{0}, m_maxDataLength{0}, m_availableBuffer{}, m_expectWriteBuffer{false}, + m_timerFactory{timerFactory}, m_bytesPerFrame{0}, m_isEosRequested{false} +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (audioMimeType == "audio/x-raw") + { + std::shared_ptr kConfig = webAudioConfig.lock(); + if (kConfig == nullptr) + { + throw std::runtime_error("Config is null for 'audio/x-raw'"); + } + m_bytesPerFrame = kConfig->pcm.channels * (kConfig->pcm.sampleSize / CHAR_BIT); + if (m_bytesPerFrame == 0) + { + throw std::runtime_error("Bytes per frame cannot be 0, channels " + std::to_string(kConfig->pcm.channels) + + ", sampleSize " + std::to_string(kConfig->pcm.sampleSize)); + } + } + else + { + throw std::runtime_error("Mimetype '" + audioMimeType + "' not supported"); + } + + m_mainThread = mainThreadFactory->getMainThread(); + if (!m_mainThread) + { + throw std::runtime_error("Failed to get the main thread"); + } + m_mainThreadClientId = m_mainThread->registerClient(); + + bool result = false; + auto task = [&]() { result = initWebAudioPlayerInternal(audioMimeType, webAudioConfig, gstPlayerFactory); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + if (!result) + { + throw std::runtime_error("WebAudioPlayerServerInternal construction failed"); + } +} + +bool WebAudioPlayerServerInternal::initWebAudioPlayerInternal( + const std::string &audioMimeType, std::weak_ptr config, + const std::shared_ptr &gstPlayerFactory) +{ + if (!m_shmBuffer->mapPartition(ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO, m_shmId)) + { + RIALTO_SERVER_LOG_ERROR("Unable to map shm partition"); + return false; + } + + if (!(m_shmPtr = m_shmBuffer->getBuffer())) + { + RIALTO_SERVER_LOG_ERROR("Failed to get the data pointer for the shared memory"); + return false; + } + + try + { + m_partitionOffset = m_shmBuffer->getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO, m_shmId, + MediaSourceType::AUDIO); + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("Failed to get the data pointer of the partition"); + return false; + } + + if (!(m_maxDataLength = m_shmBuffer->getMaxDataLen(ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO, m_shmId, + MediaSourceType::AUDIO))) + { + RIALTO_SERVER_LOG_ERROR("Failed to get the length of the partition"); + return false; + } + + if (!initGstWebAudioPlayer(audioMimeType, config, gstPlayerFactory)) + { + RIALTO_SERVER_LOG_ERROR("Failed to initalise the GstPlayer"); + return false; + } + + // Set the available bytes + m_availableBuffer.lengthMain = m_maxDataLength; + m_availableBuffer.offsetMain = m_partitionOffset; + m_availableBuffer.offsetWrap = m_partitionOffset; + + return true; +} + +WebAudioPlayerServerInternal::~WebAudioPlayerServerInternal() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() + { + if (m_writeDataTimer && (m_writeDataTimer->isActive())) + { + m_writeDataTimer->cancel(); + } + + if (!m_shmBuffer->unmapPartition(ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO, m_shmId)) + { + RIALTO_SERVER_LOG_ERROR("Unable to unmap shm partition"); + } + + m_shmBuffer.reset(); + m_mainThread->unregisterClient(m_mainThreadClientId); + }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} + +bool WebAudioPlayerServerInternal::play() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() { m_gstPlayer->play(); }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); + + return true; +} + +bool WebAudioPlayerServerInternal::pause() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() { m_gstPlayer->pause(); }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); + + return true; +} + +bool WebAudioPlayerServerInternal::setEos() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() + { + if (0 != getQueuedFramesInShm()) + { + m_isEosRequested = true; + } + else + { + m_gstPlayer->setEos(); + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); + + return true; +} + +bool WebAudioPlayerServerInternal::getBufferAvailable(uint32_t &availableFrames, + std::shared_ptr &webAudioShmInfo) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + if (!webAudioShmInfo) + { + RIALTO_SERVER_LOG_ERROR("WebAudioShmInfo is null"); + return false; + } + + auto task = [&]() + { + *webAudioShmInfo = m_availableBuffer; + availableFrames = (m_availableBuffer.lengthMain + m_availableBuffer.lengthWrap) / m_bytesPerFrame; + + // A new getBufferAvailable shall overwrite the previous if writeBuffer is not called inbetween + m_expectWriteBuffer = true; + }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + + return true; +} + +bool WebAudioPlayerServerInternal::getBufferDelay(uint32_t &delayFrames) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool status = false; + auto task = [&]() + { + // Gstreamer returns a uint64, so check the value first + uint64_t queuedFrames = (m_gstPlayer->getQueuedBytes() / m_bytesPerFrame) + getQueuedFramesInShm(); + if (queuedFrames > std::numeric_limits::max()) + { + RIALTO_SERVER_LOG_ERROR("Queued frames are larger than the max uint32_t"); + } + else + { + delayFrames = static_cast(queuedFrames); + status = true; + } + }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + return status; +} + +bool WebAudioPlayerServerInternal::writeBuffer(const uint32_t numberOfFrames, void *data) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result = false; + auto task = [&]() + { + // data can be ignored, the frames should be written to the shared memory + result = writeBufferInternal(numberOfFrames); + }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + + return result; +} + +bool WebAudioPlayerServerInternal::writeBufferInternal(const uint32_t numberOfFrames) +{ + if (!m_expectWriteBuffer) + { + RIALTO_SERVER_LOG_ERROR("No getBufferAvailable to match with this writeBuffer call"); + return false; + } + m_expectWriteBuffer = false; + + // Cancel timer + if (m_writeDataTimer && (m_writeDataTimer->isActive())) + { + m_writeDataTimer->cancel(); + m_writeDataTimer = nullptr; + } + + // Write stored frames first + uint32_t numberOfBytesToWrite = numberOfFrames * m_bytesPerFrame; + if (!writeStoredBuffers()) + { + // Update the available buffer with the new data that will not be written to gst + updateAvailableBuffer(numberOfBytesToWrite, 0); + m_writeDataTimer = + m_timerFactory->createTimer(kWriteDataTimeMs, + std::bind(&WebAudioPlayerServerInternal::handleWriteDataTimer, this)); + return true; + } + + if (0 == numberOfFrames) + { + // No frames to write to gst + return true; + } + + // Write new frames + uint8_t *mainPtr = m_shmPtr + m_availableBuffer.offsetMain; + uint8_t *wrapPtr = m_shmPtr + m_availableBuffer.offsetWrap; + uint32_t mainLength = 0; + uint32_t wrapLength = 0; + if (numberOfBytesToWrite <= m_availableBuffer.lengthMain) + { + mainLength = numberOfBytesToWrite; + } + else + { + mainLength = m_availableBuffer.lengthMain; + wrapLength = numberOfBytesToWrite - mainLength; + } + + uint32_t newBytesWritten = m_gstPlayer->writeBuffer(mainPtr, mainLength, wrapPtr, wrapLength); + updateAvailableBuffer(numberOfBytesToWrite, newBytesWritten); + if (newBytesWritten != numberOfBytesToWrite) + { + m_writeDataTimer = + m_timerFactory->createTimer(kWriteDataTimeMs, + std::bind(&WebAudioPlayerServerInternal::handleWriteDataTimer, this)); + } + + return true; +} + +bool WebAudioPlayerServerInternal::writeStoredBuffers() +{ + uint8_t *mainPtr = nullptr; + uint32_t mainLength = 0; + uint8_t *wrapPtr = nullptr; + uint32_t wrapLength = 0; + + if (m_availableBuffer.lengthWrap + m_availableBuffer.lengthMain == m_maxDataLength) + { + // No data stored + return true; + } + else if (m_availableBuffer.lengthWrap != 0) + { + // Data stored in the shared memory has not wrapped, data only stored in the middle of the shared memory region + uint32_t startOfDataOffset = m_availableBuffer.offsetWrap + m_availableBuffer.lengthWrap; + mainPtr = m_shmPtr + startOfDataOffset; + mainLength = m_availableBuffer.offsetMain - startOfDataOffset; + } + else + { + // Data stored in the shared memory has wrapped, data stored at the end and start of the shared memory region + uint32_t startOfDataOffset = m_availableBuffer.offsetMain + m_availableBuffer.lengthMain; + mainPtr = m_shmPtr + startOfDataOffset; + mainLength = m_maxDataLength - (startOfDataOffset - m_partitionOffset); + // Wrapped data stored at the start of the shared memory region up to where the availableBuffer starts + wrapPtr = m_shmPtr + m_partitionOffset; + wrapLength = m_availableBuffer.offsetMain - m_partitionOffset; + } + + uint32_t storedBytesWritten = m_gstPlayer->writeBuffer(mainPtr, mainLength, wrapPtr, wrapLength); + + // Update available buffer with the bytes written to gst. + // Bytes written to shm is 0 becuase they have already been handled. + updateAvailableBuffer(0, storedBytesWritten); + + if (storedBytesWritten == mainLength + wrapLength) + { + // All data written to gstreamer + if (m_isEosRequested) + { + m_gstPlayer->setEos(); + m_isEosRequested = false; + } + return true; + } + + return false; +} + +void WebAudioPlayerServerInternal::updateAvailableBuffer(uint32_t bytesWrittenToShm, uint32_t bytesWrittenToGst) +{ + if (bytesWrittenToShm <= m_availableBuffer.lengthMain) + { + // Data written to the shared memory has not wrapped + uint32_t offetRelativeToPartition = m_availableBuffer.offsetMain - m_partitionOffset; + uint32_t storedDataLengthAtEndOfShm = m_maxDataLength - (offetRelativeToPartition + m_availableBuffer.lengthMain); + + m_availableBuffer.offsetMain = m_availableBuffer.offsetMain + bytesWrittenToShm; + if (bytesWrittenToGst <= storedDataLengthAtEndOfShm) + { + // Data written to gst has not wrapped, data written is taken from the main buffer only + m_availableBuffer.lengthMain = m_availableBuffer.lengthMain - bytesWrittenToShm + bytesWrittenToGst; + } + else + { + // Data written to gst has wrapped, data written is taken from the main buffer and wrapped buffer + m_availableBuffer.lengthMain = m_availableBuffer.lengthMain - bytesWrittenToShm + storedDataLengthAtEndOfShm; + m_availableBuffer.lengthWrap = m_availableBuffer.lengthWrap + + (bytesWrittenToGst - storedDataLengthAtEndOfShm); + } + } + else + { + // Data written to the shared memory has wrapped, available buffer should now point to where the wrapped buffer was + uint32_t newDataLengthAtEndOfShm = m_availableBuffer.lengthMain; + + m_availableBuffer.offsetMain = m_availableBuffer.offsetWrap + (bytesWrittenToShm - m_availableBuffer.lengthMain); + uint32_t newOffetRelativeToPartition = m_availableBuffer.offsetMain - m_partitionOffset; + if (bytesWrittenToGst <= m_availableBuffer.lengthMain) + { + // Data written to gstreamer has not wrapped, data written is taken from the main buffer only + m_availableBuffer.lengthMain = (m_availableBuffer.lengthWrap - newOffetRelativeToPartition) + + bytesWrittenToGst; + m_availableBuffer.lengthWrap = 0; + } + else + { + // Data written to gstreamer has wrapped, data written is taken from the main buffer and wrapped buffer + m_availableBuffer.lengthMain = m_maxDataLength - newOffetRelativeToPartition; + m_availableBuffer.lengthWrap = bytesWrittenToGst - newDataLengthAtEndOfShm; + } + } +} + +bool WebAudioPlayerServerInternal::getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, + bool &supportDeferredPlay) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + // Can be called from any thread + maximumFrames = m_maxDataLength / m_bytesPerFrame; + preferredFrames = std::min(kPreferredFrames, maximumFrames); + supportDeferredPlay = true; + + return true; +} + +bool WebAudioPlayerServerInternal::setVolume(double volume) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, volume]() { m_gstPlayer->setVolume(volume); }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); + + return true; +} + +bool WebAudioPlayerServerInternal::getVolume(double &volume) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + bool result = false; + auto task = [&]() { result = m_gstPlayer->getVolume(volume); }; + + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); + + return result; +} + +std::weak_ptr WebAudioPlayerServerInternal::getClient() +{ + return m_webAudioPlayerClient; +} + +void WebAudioPlayerServerInternal::notifyState(WebAudioPlayerState state) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&, state]() + { + if (m_webAudioPlayerClient) + { + m_webAudioPlayerClient->notifyState(state); + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +bool WebAudioPlayerServerInternal::initGstWebAudioPlayer(const std::string &audioMimeType, + std::weak_ptr config, + const std::shared_ptr &gstPlayerFactory) +{ + m_gstPlayer = gstPlayerFactory->createGstWebAudioPlayer(this, m_priority); + if (!m_gstPlayer) + { + RIALTO_SERVER_LOG_ERROR("Failed to load gstreamer player"); + return false; + } + + m_gstPlayer->setCaps(audioMimeType, config); + + return true; +} + +void WebAudioPlayerServerInternal::handleWriteDataTimer() +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() + { + if (!writeStoredBuffers()) + { + // Not all data was written to gstreamer, restart the timer + m_writeDataTimer = + m_timerFactory->createTimer(kWriteDataTimeMs, + std::bind(&WebAudioPlayerServerInternal::handleWriteDataTimer, this)); + } + else + { + m_writeDataTimer = nullptr; + } + }; + + m_mainThread->enqueueTask(m_mainThreadClientId, task); +} + +uint32_t WebAudioPlayerServerInternal::getQueuedFramesInShm() +{ + return (m_maxDataLength - (m_availableBuffer.lengthMain + m_availableBuffer.lengthWrap)) / m_bytesPerFrame; +} + +void WebAudioPlayerServerInternal::ping(std::unique_ptr &&heartbeatHandler) +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); + + auto task = [&]() { m_gstPlayer->ping(std::move(heartbeatHandler)); }; + m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); +} +}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/service/CMakeLists.txt b/middleware/rialto-client/media/server/service/CMakeLists.txt new file mode 100644 index 000000000..bfd31be96 --- /dev/null +++ b/middleware/rialto-client/media/server/service/CMakeLists.txt @@ -0,0 +1,59 @@ +# +# If not stated otherwise in this file or this component's LICENSE file the +# following copyright and licenses apply: +# +# Copyright 2022 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Find includes in corresponding build directories +set( CMAKE_INCLUDE_CURRENT_DIR ON ) +add_library ( + RialtoServerService STATIC + + source/ApplicationSessionServer.cpp + source/PlaybackService.cpp + source/CdmService.cpp + source/ControlService.cpp + source/SessionServerManager.cpp + source/MediaPipelineService.cpp + source/WebAudioPlayerService.cpp +) +set_target_properties ( + RialtoServerService + PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" POSITION_INDEPENDENT_CODE ON +) +target_include_directories ( + RialtoServerService + + PUBLIC + include + + PRIVATE + $ + $ + $ + $ + $ + $ + ${GStreamerApp_INCLUDE_DIRS} +) +target_link_libraries ( + RialtoServerService + + PRIVATE + RialtoLogging + RialtoServerMain + RialtoServerIpc +) diff --git a/middleware/rialto-client/media/server/service/include/IApplicationSessionServer.h b/middleware/rialto-client/media/server/service/include/IApplicationSessionServer.h new file mode 100644 index 000000000..875d2e940 --- /dev/null +++ b/middleware/rialto-client/media/server/service/include/IApplicationSessionServer.h @@ -0,0 +1,45 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_I_APPLICATION_SESSION_SERVER_H_ +#define FIREBOLT_RIALTO_SERVER_I_APPLICATION_SESSION_SERVER_H_ + +#include + +namespace firebolt::rialto::server +{ +class IApplicationSessionServer; +class IApplicationSessionServerFactory +{ +public: + virtual ~IApplicationSessionServerFactory() = default; + static std::unique_ptr getFactory(); + virtual std::unique_ptr createApplicationSessionServer() const = 0; +}; + +class IApplicationSessionServer +{ +public: + virtual ~IApplicationSessionServer() = default; + virtual bool init(int argc, char *argv[]) = 0; + virtual void startService() = 0; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_I_APPLICATION_SESSION_SERVER_H_ diff --git a/middleware/rialto-client/media/server/service/include/ICdmService.h b/middleware/rialto-client/media/server/service/include/ICdmService.h new file mode 100644 index 000000000..cd0a491f7 --- /dev/null +++ b/middleware/rialto-client/media/server/service/include/ICdmService.h @@ -0,0 +1,84 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_CDM_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_I_CDM_SERVICE_H_ + +#include "IHeartbeatProcedure.h" +#include "IMediaKeysCapabilities.h" +#include "IMediaKeysServerInternal.h" +#include "MediaCommon.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class ICdmService +{ +public: + ICdmService() = default; + virtual ~ICdmService() = default; + + ICdmService(const ICdmService &) = delete; + ICdmService(ICdmService &&) = delete; + ICdmService &operator=(const ICdmService &) = delete; + ICdmService &operator=(ICdmService &&) = delete; + + virtual bool switchToActive() = 0; + virtual void switchToInactive() = 0; + + virtual bool createMediaKeys(int mediaKeysHandle, std::string keySystem) = 0; + virtual bool destroyMediaKeys(int mediaKeysHandle) = 0; + virtual MediaKeyErrorStatus createKeySession(int mediaKeysHandle, KeySessionType sessionType, + const std::shared_ptr &client, bool isLDL, + int32_t &keySessionId) = 0; + virtual MediaKeyErrorStatus generateRequest(int mediaKeysHandle, int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) = 0; + virtual MediaKeyErrorStatus loadSession(int mediaKeysHandle, int32_t keySessionId) = 0; + virtual MediaKeyErrorStatus updateSession(int mediaKeysHandle, int32_t keySessionId, + const std::vector &responseData) = 0; + virtual MediaKeyErrorStatus closeKeySession(int mediaKeysHandle, int32_t keySessionId) = 0; + virtual MediaKeyErrorStatus removeKeySession(int mediaKeysHandle, int32_t keySessionId) = 0; + virtual MediaKeyErrorStatus getCdmKeySessionId(int mediaKeysHandle, int32_t keySessionId, + std::string &cdmKeySessionId) = 0; + virtual bool containsKey(int mediaKeysHandle, int32_t keySessionId, const std::vector &keyId) = 0; + virtual MediaKeyErrorStatus setDrmHeader(int mediaKeysHandle, int32_t keySessionId, + const std::vector &requestData) = 0; + virtual MediaKeyErrorStatus deleteDrmStore(int mediaKeysHandle) = 0; + virtual MediaKeyErrorStatus deleteKeyStore(int mediaKeysHandle) = 0; + virtual MediaKeyErrorStatus getDrmStoreHash(int mediaKeysHandle, std::vector &drmStoreHash) = 0; + virtual MediaKeyErrorStatus getKeyStoreHash(int mediaKeysHandle, std::vector &keyStoreHash) = 0; + virtual MediaKeyErrorStatus getLdlSessionsLimit(int mediaKeysHandle, uint32_t &ldlLimit) = 0; + virtual MediaKeyErrorStatus getLastDrmError(int mediaKeysHandle, int32_t keySessionId, uint32_t &errorCode) = 0; + virtual MediaKeyErrorStatus getDrmTime(int mediaKeysHandle, uint64_t &drmTime) = 0; + virtual MediaKeyErrorStatus releaseKeySession(int mediaKeysHandle, int32_t keySessionId) = 0; + virtual MediaKeyErrorStatus getMetricSystemData(int mediaKeysHandle, std::vector &buffer) = 0; + + virtual std::vector getSupportedKeySystems() = 0; + virtual bool supportsKeySystem(const std::string &keySystem) = 0; + virtual bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) = 0; + virtual bool isServerCertificateSupported(const std::string &keySystem) = 0; + + virtual void ping(const std::shared_ptr &heartbeatProcedure) = 0; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_CDM_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/include/IControlService.h b/middleware/rialto-client/media/server/service/include/IControlService.h new file mode 100644 index 000000000..705885123 --- /dev/null +++ b/middleware/rialto-client/media/server/service/include/IControlService.h @@ -0,0 +1,50 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_CONTROL_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_I_CONTROL_SERVICE_H_ + +#include "ControlCommon.h" +#include "IControlClientServerInternal.h" +#include "IHeartbeatProcedure.h" +#include +#include + +namespace firebolt::rialto::server::service +{ +class IControlService +{ +public: + IControlService() = default; + virtual ~IControlService() = default; + + IControlService(const IControlService &) = delete; + IControlService(IControlService &&) = delete; + IControlService &operator=(const IControlService &) = delete; + IControlService &operator=(IControlService &&) = delete; + + virtual void addControl(int controlId, const std::shared_ptr &client) = 0; + virtual void removeControl(int controlId) = 0; + virtual bool ack(int controlId, std::uint32_t id) = 0; + virtual void setApplicationState(const ApplicationState &state) = 0; + virtual bool ping(const std::shared_ptr &heartbeatProcedure) = 0; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_CONTROL_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/include/IMediaPipelineService.h b/middleware/rialto-client/media/server/service/include/IMediaPipelineService.h new file mode 100644 index 000000000..2c456f1b7 --- /dev/null +++ b/middleware/rialto-client/media/server/service/include/IMediaPipelineService.h @@ -0,0 +1,97 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_MEDIA_PIPELINE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_I_MEDIA_PIPELINE_SERVICE_H_ + +#include "IHeartbeatProcedure.h" +#include "IMediaPipeline.h" +#include "MediaCommon.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class IMediaPipelineService +{ +public: + IMediaPipelineService() = default; + virtual ~IMediaPipelineService() = default; + + IMediaPipelineService(const IMediaPipelineService &) = delete; + IMediaPipelineService(IMediaPipelineService &&) = delete; + IMediaPipelineService &operator=(const IMediaPipelineService &) = delete; + IMediaPipelineService &operator=(IMediaPipelineService &&) = delete; + + virtual bool createSession(int sessionId, const std::shared_ptr &mediaPipelineClient, + std::uint32_t maxWidth, std::uint32_t maxHeight) = 0; + virtual bool destroySession(int sessionId) = 0; + virtual bool load(int sessionId, MediaType type, const std::string &mimeType, const std::string &url) = 0; + virtual bool attachSource(int sessionId, const std::unique_ptr &source) = 0; + virtual bool removeSource(int sessionId, std::int32_t sourceId) = 0; + virtual bool allSourcesAttached(int sessionId) = 0; + virtual bool play(int sessionId) = 0; + virtual bool pause(int sessionId) = 0; + virtual bool stop(int sessionId) = 0; + virtual bool setPlaybackRate(int sessionId, double rate) = 0; + virtual bool setPosition(int sessionId, std::int64_t position) = 0; + virtual bool getPosition(int sessionId, std::int64_t &position) = 0; + virtual bool setImmediateOutput(int sessionId, int32_t sourceId, bool immediateOutput) = 0; + virtual bool getImmediateOutput(int sessionId, int32_t sourceId, bool &immediateOutput) = 0; + virtual bool getStats(int sessionId, int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; + virtual bool setVideoWindow(int sessionId, std::uint32_t x, std::uint32_t y, std::uint32_t width, + std::uint32_t height) = 0; + virtual bool haveData(int sessionId, MediaSourceStatus status, std::uint32_t numFrames, + std::uint32_t needDataRequestId) = 0; + virtual bool renderFrame(int sessionId) = 0; + virtual bool setVolume(int sessionId, double targetVolume, uint32_t volumeDuration, EaseType easeType) = 0; + virtual bool getVolume(int sessionId, double &volume) = 0; + virtual bool setMute(int sessionId, std::int32_t sourceId, bool mute) = 0; + virtual bool getMute(int sessionId, std::int32_t sourceId, bool &mute) = 0; + virtual bool setTextTrackIdentifier(int sessionId, const std::string &textTrackIdentifier) = 0; + virtual bool getTextTrackIdentifier(int sessionId, std::string &textTrackIdentifier) = 0; + virtual bool setLowLatency(int sessionId, bool lowLatency) = 0; + virtual bool setSync(int sessionId, bool sync) = 0; + virtual bool getSync(int sessionId, bool &sync) = 0; + virtual bool setSyncOff(int sessionId, bool syncOff) = 0; + virtual bool setStreamSyncMode(int sessionId, int32_t sourceId, int32_t streamSyncMode) = 0; + virtual bool getStreamSyncMode(int sessionId, int32_t &streamSyncMode) = 0; + virtual bool flush(int sessionId, std::int32_t sourceId, bool resetTime, bool &isAsync) = 0; + virtual bool setSourcePosition(int sessionId, int32_t sourceId, int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) = 0; + virtual bool setSubtitleOffset(int sessionId, int32_t sourceId, int64_t position) = 0; + virtual bool processAudioGap(int sessionId, int64_t position, uint32_t duration, int64_t discontinuityGap, + bool audioAac) = 0; + virtual bool setBufferingLimit(int sessionId, uint32_t limitBufferingMs) = 0; + virtual bool getBufferingLimit(int sessionId, uint32_t &limitBufferingMs) = 0; + virtual bool setUseBuffering(int sessionId, bool useBuffering) = 0; + virtual bool getUseBuffering(int sessionId, bool &useBuffering) = 0; + virtual std::vector getSupportedMimeTypes(MediaSourceType type) = 0; + virtual bool isMimeTypeSupported(const std::string &mimeType) = 0; + virtual std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) = 0; + virtual void ping(const std::shared_ptr &heartbeatProcedure) = 0; + virtual bool switchSource(int sessionId, const std::unique_ptr &source) = 0; + virtual bool isVideoMaster(bool &isVideoMaster) = 0; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_MEDIA_PIPELINE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/include/IPlaybackService.h b/middleware/rialto-client/media/server/service/include/IPlaybackService.h new file mode 100644 index 000000000..98b99fecc --- /dev/null +++ b/middleware/rialto-client/media/server/service/include/IPlaybackService.h @@ -0,0 +1,63 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_PLAYBACK_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_I_PLAYBACK_SERVICE_H_ + +#include "IMediaPipelineService.h" +#include "ISharedMemoryBuffer.h" +#include "IWebAudioPlayerService.h" +#include "MediaCommon.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class IPlaybackService +{ +public: + IPlaybackService() = default; + virtual ~IPlaybackService() = default; + + IPlaybackService(const IPlaybackService &) = delete; + IPlaybackService(IPlaybackService &&) = delete; + IPlaybackService &operator=(const IPlaybackService &) = delete; + IPlaybackService &operator=(IPlaybackService &&) = delete; + + virtual bool switchToActive() = 0; + virtual void switchToInactive() = 0; + virtual void setMaxPlaybacks(int maxPlaybacks) = 0; + virtual void setMaxWebAudioPlayers(int maxWebAudio) = 0; + virtual void setClientDisplayName(const std::string &clientDisplayName) const = 0; + virtual void setResourceManagerAppName(const std::string &appName) const = 0; + + virtual bool isActive() const = 0; + virtual bool getSharedMemory(int32_t &fd, uint32_t &size) const = 0; + virtual int getMaxPlaybacks() const = 0; + virtual int getMaxWebAudioPlayers() const = 0; + virtual std::shared_ptr getShmBuffer() const = 0; + virtual IMediaPipelineService &getMediaPipelineService() const = 0; + virtual IWebAudioPlayerService &getWebAudioPlayerService() const = 0; + virtual void ping(const std::shared_ptr &heartbeatProcedure) const = 0; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_PLAYBACK_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/include/ISessionServerManager.h b/middleware/rialto-client/media/server/service/include/ISessionServerManager.h new file mode 100644 index 000000000..9f3e4beb3 --- /dev/null +++ b/middleware/rialto-client/media/server/service/include/ISessionServerManager.h @@ -0,0 +1,58 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_SESSION_SERVER_MANAGER_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_I_SESSION_SERVER_MANAGER_H_ + +#include "IAckSender.h" +#include "RialtoLogging.h" +#include "SessionServerCommon.h" +#include +#include + +namespace firebolt::rialto::server::service +{ +class ISessionServerManager +{ +public: + ISessionServerManager() = default; + virtual ~ISessionServerManager() = default; + + ISessionServerManager(const ISessionServerManager &) = delete; + ISessionServerManager(ISessionServerManager &&) = delete; + ISessionServerManager &operator=(const ISessionServerManager &) = delete; + ISessionServerManager &operator=(ISessionServerManager &&) = delete; + + virtual bool initialize(int argc, char *argv[]) = 0; + virtual void startService() = 0; + virtual bool configureIpc(const std::string &socketName, unsigned int socketPermissions, + const std::string &socketOwner, const std::string &socketGroup) = 0; + virtual bool configureIpc(int32_t socketFd) = 0; + virtual bool configureServices(const common::SessionServerState &state, + const common::MaxResourceCapabilitites &maxResource, + const std::string &clientDisplayName, const std::string &appName) = 0; + virtual bool setState(const common::SessionServerState &state) = 0; + virtual void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, + RIALTO_DEBUG_LEVEL sessionServerLogLevels, RIALTO_DEBUG_LEVEL ipcLogLevels, + RIALTO_DEBUG_LEVEL serverManagerLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) = 0; + virtual bool ping(std::int32_t id, const std::shared_ptr &ackSender) = 0; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_SESSION_SERVER_MANAGER_H_ diff --git a/middleware/rialto-client/media/server/service/include/IWebAudioPlayerService.h b/middleware/rialto-client/media/server/service/include/IWebAudioPlayerService.h new file mode 100644 index 000000000..133d4c5d7 --- /dev/null +++ b/middleware/rialto-client/media/server/service/include/IWebAudioPlayerService.h @@ -0,0 +1,63 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_WEB_AUDIO_PLAYER_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_I_WEB_AUDIO_PLAYER_SERVICE_H_ + +#include "IHeartbeatProcedure.h" +#include "IWebAudioPlayerClient.h" +#include "MediaCommon.h" +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class IWebAudioPlayerService +{ +public: + IWebAudioPlayerService() = default; + virtual ~IWebAudioPlayerService() = default; + + IWebAudioPlayerService(const IWebAudioPlayerService &) = delete; + IWebAudioPlayerService(IWebAudioPlayerService &&) = delete; + IWebAudioPlayerService &operator=(const IWebAudioPlayerService &) = delete; + IWebAudioPlayerService &operator=(IWebAudioPlayerService &&) = delete; + + virtual bool createWebAudioPlayer(int handle, const std::shared_ptr &webAudioPlayerClient, + const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config) = 0; + virtual bool destroyWebAudioPlayer(int handle) = 0; + virtual bool play(int handle) = 0; + virtual bool pause(int handle) = 0; + virtual bool setEos(int handle) = 0; + virtual bool getBufferAvailable(int handle, uint32_t &availableFrames, + std::shared_ptr &webAudioShmInfo) = 0; + virtual bool getBufferDelay(int handle, uint32_t &delayFrames) = 0; + virtual bool writeBuffer(int handle, const uint32_t numberOfFrames, void *data) = 0; + virtual bool getDeviceInfo(int handle, uint32_t &preferredFrames, uint32_t &maximumFrames, + bool &supportDeferredPlay) = 0; + virtual bool setVolume(int handle, double volume) = 0; + virtual bool getVolume(int handle, double &volume) = 0; + virtual void ping(const std::shared_ptr &heartbeatProcedure) = 0; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_WEB_AUDIO_PLAYER_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.cpp b/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.cpp new file mode 100644 index 000000000..b3de0f8cb --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.cpp @@ -0,0 +1,43 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ApplicationSessionServer.h" + +namespace firebolt::rialto::server +{ +std::unique_ptr IApplicationSessionServerFactory::getFactory() +{ + return std::make_unique(); +} + +std::unique_ptr ApplicationSessionServerFactory::createApplicationSessionServer() const +{ + return std::make_unique(); +} + +bool ApplicationSessionServer::init(int argc, char *argv[]) +{ + return m_serviceManager.initialize(argc, argv); +} + +void ApplicationSessionServer::startService() +{ + m_serviceManager.startService(); +} +} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.h b/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.h new file mode 100644 index 000000000..f9c02020a --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.h @@ -0,0 +1,77 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_APPLICATION_SESSION_SERVER_H_ +#define FIREBOLT_RIALTO_SERVER_APPLICATION_SESSION_SERVER_H_ + +#include "CdmService.h" +#include "ControlService.h" +#include "IApplicationSessionServer.h" +#include "IControlServerInternal.h" +#include "IHeartbeatProcedure.h" +#include "IMediaKeysCapabilities.h" +#include "IMediaKeysServerInternal.h" +#include "IMediaPipelineCapabilities.h" +#include "IMediaPipelineServerInternal.h" +#include "ISharedMemoryBuffer.h" +#include "IWebAudioPlayerServerInternal.h" +#include "IpcFactory.h" +#include "PlaybackService.h" +#include "SessionServerManager.h" +#include + +namespace firebolt::rialto::server +{ +class ApplicationSessionServerFactory : public IApplicationSessionServerFactory +{ +public: + ApplicationSessionServerFactory() = default; + ~ApplicationSessionServerFactory() override = default; + + std::unique_ptr createApplicationSessionServer() const override; +}; + +class ApplicationSessionServer : public IApplicationSessionServer +{ +public: + ApplicationSessionServer() = default; + ~ApplicationSessionServer() override = default; + + bool init(int argc, char *argv[]) override; + void startService() override; + +private: + firebolt::rialto::server::ipc::IpcFactory m_ipcFactory; + firebolt::rialto::server::service::ControlService m_controlService{ + firebolt::rialto::server::IControlServerInternalFactory::createFactory()}; + firebolt::rialto::server::service::CdmService + m_cdmService{firebolt::rialto::server::IMediaKeysServerInternalFactory::createFactory(), + firebolt::rialto::IMediaKeysCapabilitiesFactory::createFactory()}; + firebolt::rialto::server::service::PlaybackService + m_playbackService{firebolt::rialto::server::IMediaPipelineServerInternalFactory::createFactory(), + firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory(), + firebolt::rialto::server::IWebAudioPlayerServerInternalFactory::createFactory(), + firebolt::rialto::server::ISharedMemoryBufferFactory::createFactory(), m_cdmService}; + firebolt::rialto::server::service::SessionServerManager + m_serviceManager{m_ipcFactory, m_playbackService, m_cdmService, m_controlService, + firebolt::rialto::server::IHeartbeatProcedureFactory::createFactory()}; +}; +} // namespace firebolt::rialto::server + +#endif // FIREBOLT_RIALTO_SERVER_APPLICATION_SESSION_SERVER_H_ diff --git a/middleware/rialto-client/media/server/service/source/CdmService.cpp b/middleware/rialto-client/media/server/service/source/CdmService.cpp new file mode 100644 index 000000000..faba4a3fc --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/CdmService.cpp @@ -0,0 +1,561 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "CdmService.h" +#include "RialtoServerLogging.h" + +namespace firebolt::rialto::server::service +{ +CdmService::CdmService(std::shared_ptr &&mediaKeysFactory, + std::shared_ptr &&mediaKeysCapabilitiesFactory) + : m_mediaKeysFactory{mediaKeysFactory}, m_mediaKeysCapabilitiesFactory{mediaKeysCapabilitiesFactory}, + m_isActive{false} +{ + RIALTO_SERVER_LOG_DEBUG("CdmService is constructed"); +} + +CdmService::~CdmService() +{ + RIALTO_SERVER_LOG_DEBUG("CdmService is destructed"); +} + +bool CdmService::switchToActive() +{ + RIALTO_SERVER_LOG_INFO("Switching SessionServer to Active state."); + m_isActive = true; + return true; +} + +void CdmService::switchToInactive() +{ + RIALTO_SERVER_LOG_INFO("Switching SessionServer to Inactive state. Cleaning resources..."); + m_isActive = false; + + { + std::lock_guard lock{m_mediaKeysMutex}; + m_mediaKeys.clear(); + } +} + +bool CdmService::createMediaKeys(int mediaKeysHandle, std::string keySystem) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to create new media keys handle: %d", mediaKeysHandle); + if (!m_isActive) + { + RIALTO_SERVER_LOG_ERROR("Skip to create media keys handle: %d - Session Server in Inactive state", + mediaKeysHandle); + return false; + } + + { + std::lock_guard lock{m_mediaKeysMutex}; + if (m_mediaKeys.find(mediaKeysHandle) != m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d already exists", mediaKeysHandle); + return false; + } + m_mediaKeys.emplace(std::make_pair(mediaKeysHandle, m_mediaKeysFactory->createMediaKeysServerInternal(keySystem))); + if (!m_mediaKeys.at(mediaKeysHandle)) + { + RIALTO_SERVER_LOG_ERROR("Could not create MediaKeys for media keys handle: %d", mediaKeysHandle); + m_mediaKeys.erase(mediaKeysHandle); + return false; + } + } + + RIALTO_SERVER_LOG_INFO("New media keys handle: %d created", mediaKeysHandle); + return true; +} + +bool CdmService::destroyMediaKeys(int mediaKeysHandle) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to destroy media keys handle: %d", mediaKeysHandle); + + { + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return false; + } + m_mediaKeys.erase(mediaKeysIter); + } + + RIALTO_SERVER_LOG_INFO("Media keys handle: %d destroyed", mediaKeysHandle); + return true; +} + +MediaKeyErrorStatus CdmService::createKeySession(int mediaKeysHandle, KeySessionType sessionType, + const std::shared_ptr &client, bool isLDL, + int32_t &keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to create key session: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + + MediaKeyErrorStatus status = mediaKeysIter->second->createKeySession(sessionType, client, isLDL, keySessionId); + if (MediaKeyErrorStatus::OK == status) + { + if (m_mediaKeysClients.find(keySessionId) != m_mediaKeysClients.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys client for key session: %d already exists", keySessionId); + static_cast(removeKeySessionInternal(mediaKeysHandle, keySessionId)); + return MediaKeyErrorStatus::FAIL; + } + m_mediaKeysClients.emplace(std::make_pair(keySessionId, client)); + } + + return status; +} + +MediaKeyErrorStatus CdmService::generateRequest(int mediaKeysHandle, int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to generate request: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->generateRequest(keySessionId, initDataType, initData); +} + +MediaKeyErrorStatus CdmService::loadSession(int mediaKeysHandle, int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to load session: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->loadSession(keySessionId); +} + +MediaKeyErrorStatus CdmService::updateSession(int mediaKeysHandle, int32_t keySessionId, + const std::vector &responseData) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to update session: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->updateSession(keySessionId, responseData); +} + +MediaKeyErrorStatus CdmService::closeKeySession(int mediaKeysHandle, int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to close key session: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->closeKeySession(keySessionId); +} + +MediaKeyErrorStatus CdmService::removeKeySession(int mediaKeysHandle, int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to remove key session: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + return removeKeySessionInternal(mediaKeysHandle, keySessionId); +} + +MediaKeyErrorStatus CdmService::removeKeySessionInternal(int mediaKeysHandle, int32_t keySessionId) +{ + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + + MediaKeyErrorStatus status = mediaKeysIter->second->removeKeySession(keySessionId); + if (MediaKeyErrorStatus::OK == status) + { + auto mediaKeysClientsIter = m_mediaKeysClients.find(keySessionId); + if (mediaKeysClientsIter != m_mediaKeysClients.end()) + { + m_mediaKeysClients.erase(mediaKeysClientsIter); + } + } + + return status; +} + +MediaKeyErrorStatus CdmService::getCdmKeySessionId(int mediaKeysHandle, int32_t keySessionId, std::string &cdmKeySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to get cdm key session id: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + + MediaKeyErrorStatus status = mediaKeysIter->second->getCdmKeySessionId(keySessionId, cdmKeySessionId); + return status; +} + +bool CdmService::containsKey(int mediaKeysHandle, int32_t keySessionId, const std::vector &keyId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to check if key is present: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return false; + } + + return mediaKeysIter->second->containsKey(keySessionId, keyId); +} + +MediaKeyErrorStatus CdmService::setDrmHeader(int mediaKeysHandle, int32_t keySessionId, + const std::vector &requestData) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to set drm header: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + + return mediaKeysIter->second->setDrmHeader(keySessionId, requestData); +} + +MediaKeyErrorStatus CdmService::deleteDrmStore(int mediaKeysHandle) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to delete drm store: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->deleteDrmStore(); +} + +MediaKeyErrorStatus CdmService::deleteKeyStore(int mediaKeysHandle) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to delete key store: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + + return mediaKeysIter->second->deleteKeyStore(); +} + +MediaKeyErrorStatus CdmService::getDrmStoreHash(int mediaKeysHandle, std::vector &drmStoreHash) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to get drm store hash: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->getDrmStoreHash(drmStoreHash); +} + +MediaKeyErrorStatus CdmService::getKeyStoreHash(int mediaKeysHandle, std::vector &keyStoreHash) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to get key store hash: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->getKeyStoreHash(keyStoreHash); +} + +MediaKeyErrorStatus CdmService::getLdlSessionsLimit(int mediaKeysHandle, uint32_t &ldlLimit) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to get ldl sessions limit: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->getLdlSessionsLimit(ldlLimit); +} + +MediaKeyErrorStatus CdmService::getLastDrmError(int mediaKeysHandle, int32_t keySessionId, uint32_t &errorCode) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to get last drm error: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->getLastDrmError(keySessionId, errorCode); +} + +MediaKeyErrorStatus CdmService::getDrmTime(int mediaKeysHandle, uint64_t &drmTime) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to get drm time: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->getDrmTime(drmTime); +} + +MediaKeyErrorStatus CdmService::releaseKeySession(int mediaKeysHandle, int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to release key session: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->releaseKeySession(keySessionId); +} + +std::vector CdmService::getSupportedKeySystems() +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to getSupportedKeySystems"); + + if (!m_isActive) + { + RIALTO_SERVER_LOG_ERROR("Skip to get supported key systems: Session Server in Inactive state"); + return {}; + } + + auto mediaKeysCapabilities = m_mediaKeysCapabilitiesFactory->getMediaKeysCapabilities(); + if (!mediaKeysCapabilities) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the mediaKeysCapabilities object"); + return {}; + } + return mediaKeysCapabilities->getSupportedKeySystems(); +} + +bool CdmService::supportsKeySystem(const std::string &keySystem) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to supportsKeySystem"); + + if (!m_isActive) + { + RIALTO_SERVER_LOG_ERROR("Skip to get supported key systems: Session Server in Inactive state"); + return false; + } + + auto mediaKeysCapabilities = m_mediaKeysCapabilitiesFactory->getMediaKeysCapabilities(); + if (!mediaKeysCapabilities) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the mediaKeysCapabilities object"); + return false; + } + return mediaKeysCapabilities->supportsKeySystem(keySystem); +} + +bool CdmService::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to getSupportedKeySystemVersion"); + + if (!m_isActive) + { + RIALTO_SERVER_LOG_ERROR("Skip to get supported key systems: Session Server in Inactive state"); + return false; + } + + auto mediaKeysCapabilities = m_mediaKeysCapabilitiesFactory->getMediaKeysCapabilities(); + if (!mediaKeysCapabilities) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the mediaKeysCapabilities object"); + return false; + } + return mediaKeysCapabilities->getSupportedKeySystemVersion(keySystem, version); +} + +bool CdmService::isServerCertificateSupported(const std::string &keySystem) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to isServerCertificateSupported"); + + if (!m_isActive) + { + RIALTO_SERVER_LOG_ERROR("Skip to check if server cert is supported: Session Server in Inactive state"); + return false; + } + + auto mediaKeysCapabilities = m_mediaKeysCapabilitiesFactory->getMediaKeysCapabilities(); + if (!mediaKeysCapabilities) + { + RIALTO_SERVER_LOG_ERROR("Failed to create the mediaKeysCapabilities object"); + return false; + } + return mediaKeysCapabilities->isServerCertificateSupported(keySystem); +} + +MediaKeyErrorStatus CdmService::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to decrypt, key session id: %d", keySessionId); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), + [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->decrypt(keySessionId, encrypted, caps); +} + +bool CdmService::isPlayreadyKeySystem(int32_t keySessionId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to check if key system is Playready, key session id: %d", keySessionId); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), + [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); + return false; + } + return mediaKeysIter->second->isPlayreadyKeySystem(keySessionId); +} + +MediaKeyErrorStatus CdmService::selectKeyId(int32_t keySessionId, const std::vector &keyId) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to select key id, key session id: %d", keySessionId); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), + [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->selectKeyId(keySessionId, keyId); +} + +void CdmService::incrementSessionIdUsageCounter(int32_t keySessionId) +{ + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), + [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); + return; + } + + mediaKeysIter->second->incrementSessionIdUsageCounter(keySessionId); +} + +void CdmService::decrementSessionIdUsageCounter(int32_t keySessionId) +{ + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), + [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); + return; + } + + mediaKeysIter->second->decrementSessionIdUsageCounter(keySessionId); +} + +void CdmService::ping(const std::shared_ptr &heartbeatProcedure) +{ + std::lock_guard lock{m_mediaKeysMutex}; + for (const auto &mediaKeyPair : m_mediaKeys) + { + auto &mediaKeys = mediaKeyPair.second; + mediaKeys->ping(heartbeatProcedure->createHandler()); + } +} + +MediaKeyErrorStatus CdmService::getMetricSystemData(int mediaKeysHandle, std::vector &buffer) +{ + RIALTO_SERVER_LOG_DEBUG("CdmService requested to get metric system data: %d", mediaKeysHandle); + + std::lock_guard lock{m_mediaKeysMutex}; + auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); + if (mediaKeysIter == m_mediaKeys.end()) + { + RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); + return MediaKeyErrorStatus::FAIL; + } + return mediaKeysIter->second->getMetricSystemData(buffer); +} +} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/CdmService.h b/middleware/rialto-client/media/server/service/source/CdmService.h new file mode 100644 index 000000000..32abdc216 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/CdmService.h @@ -0,0 +1,95 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_CDM_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_CDM_SERVICE_H_ + +#include "ICdmService.h" +#include "IDecryptionService.h" +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class CdmService : public ICdmService, public IDecryptionService +{ +public: + CdmService(std::shared_ptr &&mediaKeysFactory, + std::shared_ptr &&mediaKeysCapabilitiesFactory); + virtual ~CdmService(); + + bool switchToActive() override; + void switchToInactive() override; + + bool createMediaKeys(int mediaKeysHandle, std::string keySystem) override; + bool destroyMediaKeys(int mediaKeysHandle) override; + MediaKeyErrorStatus createKeySession(int mediaKeysHandle, KeySessionType sessionType, + const std::shared_ptr &client, bool isLDL, + int32_t &keySessionId) override; + MediaKeyErrorStatus generateRequest(int mediaKeysHandle, int32_t keySessionId, InitDataType initDataType, + const std::vector &initData) override; + MediaKeyErrorStatus loadSession(int mediaKeysHandle, int32_t keySessionId) override; + MediaKeyErrorStatus updateSession(int mediaKeysHandle, int32_t keySessionId, + const std::vector &responseData) override; + MediaKeyErrorStatus closeKeySession(int mediaKeysHandle, int32_t keySessionId) override; + MediaKeyErrorStatus removeKeySession(int mediaKeysHandle, int32_t keySessionId) override; + MediaKeyErrorStatus getCdmKeySessionId(int mediaKeysHandle, int32_t keySessionId, + std::string &cdmKeySessionId) override; + bool containsKey(int mediaKeysHandle, int32_t keySessionId, const std::vector &keyId) override; + MediaKeyErrorStatus setDrmHeader(int mediaKeysHandle, int32_t keySessionId, + const std::vector &requestData) override; + MediaKeyErrorStatus deleteDrmStore(int mediaKeysHandle) override; + MediaKeyErrorStatus deleteKeyStore(int mediaKeysHandle) override; + MediaKeyErrorStatus getDrmStoreHash(int mediaKeysHandle, std::vector &drmStoreHash) override; + MediaKeyErrorStatus getKeyStoreHash(int mediaKeysHandle, std::vector &keyStoreHash) override; + MediaKeyErrorStatus getLdlSessionsLimit(int mediaKeysHandle, uint32_t &ldlLimit) override; + MediaKeyErrorStatus getLastDrmError(int mediaKeysHandle, int32_t keySessionId, uint32_t &errorCode) override; + MediaKeyErrorStatus getDrmTime(int mediaKeysHandle, uint64_t &drmTime) override; + MediaKeyErrorStatus releaseKeySession(int mediaKeysHandle, int32_t keySessionId) override; + MediaKeyErrorStatus getMetricSystemData(int mediaKeysHandle, std::vector &buffer) override; + + std::vector getSupportedKeySystems() override; + bool supportsKeySystem(const std::string &keySystem) override; + bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) override; + bool isServerCertificateSupported(const std::string &keySystem) override; + MediaKeyErrorStatus decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) override; + bool isPlayreadyKeySystem(int32_t keySessionId) override; + MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) override; + void incrementSessionIdUsageCounter(int32_t keySessionId) override; + void decrementSessionIdUsageCounter(int32_t keySessionId) override; + void ping(const std::shared_ptr &heartbeatProcedure) override; + +private: + std::shared_ptr m_mediaKeysFactory; + std::shared_ptr m_mediaKeysCapabilitiesFactory; + std::atomic m_isActive; + std::map> m_mediaKeys; + std::map> m_mediaKeysClients; + std::mutex m_mediaKeysMutex; + + MediaKeyErrorStatus removeKeySessionInternal(int mediaKeysHandle, int32_t keySessionId); +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_CDM_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/ControlService.cpp b/middleware/rialto-client/media/server/service/source/ControlService.cpp new file mode 100644 index 000000000..1e25eea24 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/ControlService.cpp @@ -0,0 +1,81 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ControlService.h" +#include "IHeartbeatProcedure.h" +#include "RialtoServerLogging.h" +#include + +namespace firebolt::rialto::server::service +{ +ControlService::ControlService(const std::shared_ptr &controlServerInternalFactory) + : m_currentState{ApplicationState::UNKNOWN}, m_controlServerInternalFactory{controlServerInternalFactory} +{ + RIALTO_SERVER_LOG_DEBUG("entry:"); +} + +void ControlService::addControl(int controlId, const std::shared_ptr &client) +{ + RIALTO_SERVER_LOG_INFO("Creating new Control with id: %d", controlId); + auto controlServerInternal{m_controlServerInternalFactory->createControlServerInternal(controlId, client)}; + std::unique_lock lock{m_mutex}; + controlServerInternal->setApplicationState(m_currentState); + m_controls.emplace(controlId, controlServerInternal); +} + +void ControlService::removeControl(int controlId) +{ + RIALTO_SERVER_LOG_INFO("Removing Control with id: %d", controlId); + std::unique_lock lock{m_mutex}; + m_controls.erase(controlId); +} + +bool ControlService::ack(int controlId, std::uint32_t id) +{ + std::unique_lock lock{m_mutex}; + auto controlIter = m_controls.find(controlId); + if (m_controls.end() == controlIter) + { + RIALTO_SERVER_LOG_ERROR("Control with id: %d not found", controlId); + return false; + } + controlIter->second->ack(id); + return true; +} + +void ControlService::setApplicationState(const ApplicationState &state) +{ + std::unique_lock lock{m_mutex}; + m_currentState = state; + for (const auto &control : m_controls) + { + control.second->setApplicationState(state); + } +} + +bool ControlService::ping(const std::shared_ptr &heartbeatProcedure) +{ + std::unique_lock lock{m_mutex}; + for (const auto &control : m_controls) + { + control.second->ping(heartbeatProcedure->createHandler()); + } + return true; +} +} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/ControlService.h b/middleware/rialto-client/media/server/service/source/ControlService.h new file mode 100644 index 000000000..ad5ea7ea8 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/ControlService.h @@ -0,0 +1,51 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2023 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_CONTROL_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_CONTROL_SERVICE_H_ + +#include "IControlServerInternal.h" +#include "IControlService.h" +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class ControlService : public IControlService +{ +public: + explicit ControlService(const std::shared_ptr &controlServerInternalFactory); + ~ControlService() override = default; + + void addControl(int controlId, const std::shared_ptr &client) override; + void removeControl(int controlId) override; + bool ack(int controlId, std::uint32_t id) override; + void setApplicationState(const ApplicationState &state) override; + bool ping(const std::shared_ptr &heartbeatProcedure) override; + +private: + std::mutex m_mutex; + ApplicationState m_currentState; + std::shared_ptr m_controlServerInternalFactory; + std::map> m_controls; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_CONTROL_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/MediaPipelineService.cpp b/middleware/rialto-client/media/server/service/source/MediaPipelineService.cpp new file mode 100644 index 000000000..ad4023747 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/MediaPipelineService.cpp @@ -0,0 +1,671 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MediaPipelineService.h" +#include "IMediaPipelineServerInternal.h" +#include "RialtoServerLogging.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +MediaPipelineService::MediaPipelineService( + IPlaybackService &playbackService, std::shared_ptr &&mediaPipelineFactory, + std::shared_ptr &&mediaPipelineCapabilitiesFactory, + IDecryptionService &decryptionService) + : m_playbackService{playbackService}, m_mediaPipelineFactory{mediaPipelineFactory}, + m_mediaPipelineCapabilities{mediaPipelineCapabilitiesFactory->createMediaPipelineCapabilities()}, + m_decryptionService{decryptionService} +{ + if (!m_mediaPipelineCapabilities) + { + throw std::runtime_error("Could not create Media Pipeline Capabilities"); + } + + RIALTO_SERVER_LOG_DEBUG("MediaPipelineService is constructed"); +} + +MediaPipelineService::~MediaPipelineService() +{ + RIALTO_SERVER_LOG_DEBUG("MediaPipelineService is destructed"); +} + +void MediaPipelineService::clearMediaPipelines() +{ + std::lock_guard lock{m_mediaPipelineMutex}; + m_mediaPipelines.clear(); +} + +bool MediaPipelineService::createSession(int sessionId, const std::shared_ptr &mediaPipelineClient, + std::uint32_t maxWidth, std::uint32_t maxHeight) +{ + RIALTO_SERVER_LOG_DEBUG("MediaPipelineService requested to create new session with id: %d", sessionId); + if (!m_playbackService.isActive()) + { + RIALTO_SERVER_LOG_ERROR("Skip to create session with id: %d - Session Server in Inactive state", sessionId); + return false; + } + + { + std::lock_guard lock{m_mediaPipelineMutex}; + if (m_mediaPipelines.size() == static_cast(m_playbackService.getMaxPlaybacks())) + { + RIALTO_SERVER_LOG_ERROR("Unable to create a session with id: %d. Max session number reached.", sessionId); + return false; + } + if (m_mediaPipelines.find(sessionId) != m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d already exists", sessionId); + return false; + } + auto shmBuffer = m_playbackService.getShmBuffer(); + m_mediaPipelines.emplace( + std::make_pair(sessionId, + m_mediaPipelineFactory->createMediaPipelineServerInternal(mediaPipelineClient, + VideoRequirements{maxWidth, maxHeight}, + sessionId, shmBuffer, + m_decryptionService))); + if (!m_mediaPipelines.at(sessionId)) + { + RIALTO_SERVER_LOG_ERROR("Could not create MediaPipeline for session with id: %d", sessionId); + m_mediaPipelines.erase(sessionId); + return false; + } + } + + RIALTO_SERVER_LOG_INFO("New session with id: %d created", sessionId); + return true; +} + +bool MediaPipelineService::destroySession(int sessionId) +{ + RIALTO_SERVER_LOG_DEBUG("MediaPipelineService requested to destroy session with id: %d", sessionId); + { + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + m_mediaPipelines.erase(mediaPipelineIter); + } + RIALTO_SERVER_LOG_INFO("Session with id: %d destroyed", sessionId); + return true; +} + +bool MediaPipelineService::load(int sessionId, MediaType type, const std::string &mimeType, const std::string &url) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to load session with id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->load(type, mimeType, url); +} + +bool MediaPipelineService::attachSource(int sessionId, const std::unique_ptr &source) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to attach source, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->attachSource(source); +} + +bool MediaPipelineService::removeSource(int sessionId, std::int32_t sourceId) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to remove source, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->removeSource(sourceId); +} + +bool MediaPipelineService::allSourcesAttached(int sessionId) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService notified that all sources were attached, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->allSourcesAttached(); +} + +bool MediaPipelineService::play(int sessionId) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to play, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->play(); +} + +bool MediaPipelineService::pause(int sessionId) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to pause, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->pause(); +} + +bool MediaPipelineService::stop(int sessionId) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to stop, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->stop(); +} + +bool MediaPipelineService::setPlaybackRate(int sessionId, double rate) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to set playback rate, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->setPlaybackRate(rate); +} + +bool MediaPipelineService::setPosition(int sessionId, std::int64_t position) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to set position, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->setPosition(position); +} + +bool MediaPipelineService::getPosition(int sessionId, std::int64_t &position) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to get position, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->getPosition(position); +} + +bool MediaPipelineService::setImmediateOutput(int sessionId, int32_t sourceId, bool immediateOutput) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to setImmediateOutput, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->setImmediateOutput(sourceId, immediateOutput); +} + +bool MediaPipelineService::getImmediateOutput(int sessionId, int32_t sourceId, bool &immediateOutput) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to getImmediateOutput, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->getImmediateOutput(sourceId, immediateOutput); +} + +bool MediaPipelineService::getStats(int sessionId, int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to get stats, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->getStats(sourceId, renderedFrames, droppedFrames); +} + +bool MediaPipelineService::setVideoWindow(int sessionId, std::uint32_t x, std::uint32_t y, std::uint32_t width, + std::uint32_t height) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to set video window, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->setVideoWindow(x, y, width, height); +} + +bool MediaPipelineService::haveData(int sessionId, MediaSourceStatus status, std::uint32_t numFrames, + std::uint32_t needDataRequestId) +{ + RIALTO_SERVER_LOG_DEBUG("New data available, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->haveData(status, numFrames, needDataRequestId); +} + +bool MediaPipelineService::renderFrame(int sessionId) +{ + RIALTO_SERVER_LOG_DEBUG("Render frame requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->renderFrame(); +} +bool MediaPipelineService::setVolume(int sessionId, double targetVolume, uint32_t volumeDuration, EaseType easeType) +{ + RIALTO_SERVER_LOG_DEBUG("Set volume requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->setVolume(targetVolume, volumeDuration, easeType); +} + +bool MediaPipelineService::getVolume(int sessionId, double &volume) +{ + RIALTO_SERVER_LOG_DEBUG("Get volume requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->getVolume(volume); +} + +bool MediaPipelineService::setMute(int sessionId, std::int32_t sourceId, bool mute) +{ + RIALTO_SERVER_LOG_DEBUG("Set mute requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setMute(sourceId, mute); +} + +bool MediaPipelineService::getMute(int sessionId, std::int32_t sourceId, bool &mute) +{ + RIALTO_SERVER_LOG_DEBUG("Get mute requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->getMute(sourceId, mute); +} + +bool MediaPipelineService::setTextTrackIdentifier(int sessionId, const std::string &textTrackIdentifier) +{ + RIALTO_SERVER_LOG_DEBUG("Set text track identifier requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setTextTrackIdentifier(textTrackIdentifier); +} + +bool MediaPipelineService::getTextTrackIdentifier(int sessionId, std::string &textTrackIdentifier) +{ + RIALTO_SERVER_LOG_DEBUG("Get text track identifier requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->getTextTrackIdentifier(textTrackIdentifier); +} + +bool MediaPipelineService::setLowLatency(int sessionId, bool lowLatency) +{ + RIALTO_SERVER_LOG_DEBUG("Set low latency requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setLowLatency(lowLatency); +} + +bool MediaPipelineService::setSync(int sessionId, bool sync) +{ + RIALTO_SERVER_LOG_DEBUG("Set sync requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setSync(sync); +} + +bool MediaPipelineService::getSync(int sessionId, bool &sync) +{ + RIALTO_SERVER_LOG_DEBUG("Get sync requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->getSync(sync); +} + +bool MediaPipelineService::setSyncOff(int sessionId, bool syncOff) +{ + RIALTO_SERVER_LOG_DEBUG("Set sync off requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setSyncOff(syncOff); +} + +bool MediaPipelineService::setStreamSyncMode(int sessionId, int32_t sourceId, int32_t streamSyncMode) +{ + RIALTO_SERVER_LOG_DEBUG("Set stream sync mode requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setStreamSyncMode(sourceId, streamSyncMode); +} + +bool MediaPipelineService::getStreamSyncMode(int sessionId, int32_t &streamSyncMode) +{ + RIALTO_SERVER_LOG_DEBUG("Get stream sync mode requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->getStreamSyncMode(streamSyncMode); +} + +bool MediaPipelineService::flush(int sessionId, std::int32_t sourceId, bool resetTime, bool &isAsync) +{ + RIALTO_SERVER_LOG_DEBUG("Flush requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->flush(sourceId, resetTime, isAsync); +} + +bool MediaPipelineService::setSourcePosition(int sessionId, int32_t sourceId, int64_t position, bool resetTime, + double appliedRate, uint64_t stopPosition) +{ + RIALTO_SERVER_LOG_DEBUG("Set Source Position requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition); +} + +bool MediaPipelineService::setSubtitleOffset(int sessionId, int32_t sourceId, int64_t position) +{ + RIALTO_SERVER_LOG_DEBUG("Set Subtitle Offset requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setSubtitleOffset(sourceId, position); +} + +bool MediaPipelineService::processAudioGap(int sessionId, int64_t position, uint32_t duration, int64_t discontinuityGap, + bool audioAac) +{ + RIALTO_SERVER_LOG_DEBUG("Process Audio Gap requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->processAudioGap(position, duration, discontinuityGap, audioAac); +} + +bool MediaPipelineService::setBufferingLimit(int sessionId, uint32_t limitBufferingMs) +{ + RIALTO_SERVER_LOG_DEBUG("Set buffering limit requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setBufferingLimit(limitBufferingMs); +} + +bool MediaPipelineService::getBufferingLimit(int sessionId, uint32_t &limitBufferingMs) +{ + RIALTO_SERVER_LOG_DEBUG("Get buffering limit requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->getBufferingLimit(limitBufferingMs); +} + +bool MediaPipelineService::setUseBuffering(int sessionId, bool useBuffering) +{ + RIALTO_SERVER_LOG_DEBUG("Set use buffering requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->setUseBuffering(useBuffering); +} + +bool MediaPipelineService::getUseBuffering(int sessionId, bool &useBuffering) +{ + RIALTO_SERVER_LOG_DEBUG("Get use buffering requested, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); + return false; + } + return mediaPipelineIter->second->getUseBuffering(useBuffering); +} + +bool MediaPipelineService::switchSource(int sessionId, const std::unique_ptr &source) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to switch source, session id: %d", sessionId); + + std::lock_guard lock{m_mediaPipelineMutex}; + auto mediaPipelineIter = m_mediaPipelines.find(sessionId); + if (mediaPipelineIter == m_mediaPipelines.end()) + { + RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); + return false; + } + return mediaPipelineIter->second->switchSource(source); +} + +bool MediaPipelineService::isVideoMaster(bool &isVideoMaster) +{ + RIALTO_SERVER_LOG_INFO("MediaPipelineService requested check if video is master"); + + return m_mediaPipelineCapabilities->isVideoMaster(isVideoMaster); +} + +std::vector MediaPipelineService::getSupportedMimeTypes(MediaSourceType type) +{ + return m_mediaPipelineCapabilities->getSupportedMimeTypes(type); +} + +bool MediaPipelineService::isMimeTypeSupported(const std::string &mimeType) +{ + return m_mediaPipelineCapabilities->isMimeTypeSupported(mimeType); +} + +std::vector MediaPipelineService::getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) +{ + return m_mediaPipelineCapabilities->getSupportedProperties(mediaType, propertyNames); +} + +void MediaPipelineService::ping(const std::shared_ptr &heartbeatProcedure) +{ + RIALTO_SERVER_LOG_DEBUG("Ping requested"); + std::lock_guard lock{m_mediaPipelineMutex}; + for (const auto &mediaPipelinePair : m_mediaPipelines) + { + auto &mediaPipeline = mediaPipelinePair.second; + mediaPipeline->ping(heartbeatProcedure->createHandler()); + } +} + +} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/MediaPipelineService.h b/middleware/rialto-client/media/server/service/source/MediaPipelineService.h new file mode 100644 index 000000000..da925551f --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/MediaPipelineService.h @@ -0,0 +1,118 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_MEDIA_PIPELINE_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_MEDIA_PIPELINE_SERVICE_H_ + +#include "IDecryptionService.h" +#include "IMediaPipelineCapabilities.h" +#include "IMediaPipelineServerInternal.h" +#include "IMediaPipelineService.h" +#include "IPlaybackService.h" +#include "ISharedMemoryBuffer.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class MediaPipelineService : public IMediaPipelineService +{ +public: + MediaPipelineService(IPlaybackService &playbackService, + std::shared_ptr &&mediaPipelineFactory, + std::shared_ptr &&mediaPipelineCapabilitiesFactory, + IDecryptionService &decryptionService); + ~MediaPipelineService() override; + MediaPipelineService(const MediaPipelineService &) = delete; + MediaPipelineService(MediaPipelineService &&) = delete; + MediaPipelineService &operator=(const MediaPipelineService &) = delete; + MediaPipelineService &operator=(MediaPipelineService &&) = delete; + + bool createSession(int sessionId, const std::shared_ptr &mediaPipelineClient, + std::uint32_t maxWidth, std::uint32_t maxHeight) override; + bool destroySession(int sessionId) override; + bool load(int sessionId, MediaType type, const std::string &mimeType, const std::string &url) override; + bool attachSource(int sessionId, const std::unique_ptr &source) override; + bool removeSource(int sessionId, std::int32_t sourceId) override; + bool allSourcesAttached(int sessionId) override; + bool play(int sessionId) override; + bool pause(int sessionId) override; + bool stop(int sessionId) override; + bool setPlaybackRate(int sessionId, double rate) override; + bool setPosition(int sessionId, std::int64_t position) override; + bool getPosition(int sessionId, std::int64_t &position) override; + bool setImmediateOutput(int sessionId, int32_t sourceId, bool immediateOutput) override; + bool getImmediateOutput(int sessionId, int32_t sourceId, bool &immediateOutput) override; + bool getStats(int sessionId, int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; + bool setVideoWindow(int sessionId, std::uint32_t x, std::uint32_t y, std::uint32_t width, + std::uint32_t height) override; + bool haveData(int sessionId, MediaSourceStatus status, std::uint32_t numFrames, + std::uint32_t needDataRequestId) override; + bool renderFrame(int sessionId) override; + bool setVolume(int sessionId, double targetVolume, uint32_t volumeDuration, EaseType easeType) override; + bool getVolume(int sessionId, double &volume) override; + bool setMute(int sessionId, std::int32_t sourceId, bool mute) override; + bool getMute(int sessionId, std::int32_t sourceId, bool &mute) override; + bool setTextTrackIdentifier(int sessionId, const std::string &textTrackIdentifier) override; + bool getTextTrackIdentifier(int sessionId, std::string &textTrackIdentifier) override; + bool setLowLatency(int sessionId, bool lowLatency) override; + bool setSync(int sessionId, bool sync) override; + bool getSync(int sessionId, bool &sync) override; + bool setSyncOff(int sessionId, bool syncOff) override; + bool setStreamSyncMode(int sessionId, int32_t sourceId, int32_t streamSyncMode) override; + bool getStreamSyncMode(int sessionId, int32_t &streamSyncMode) override; + bool flush(int sessionId, std::int32_t sourceId, bool resetTime, bool &isAsync) override; + bool setSourcePosition(int sessionId, int32_t sourceId, int64_t position, bool resetTime, double appliedRate, + uint64_t stopPosition) override; + bool setSubtitleOffset(int sessionId, int32_t sourceId, int64_t position) override; + bool processAudioGap(int sessionId, int64_t position, uint32_t duration, int64_t discontinuityGap, + bool audioAac) override; + bool setBufferingLimit(int sessionId, uint32_t limitBufferingMs) override; + bool getBufferingLimit(int sessionId, uint32_t &limitBufferingMs) override; + bool setUseBuffering(int sessionId, bool useBuffering) override; + bool getUseBuffering(int sessionId, bool &useBuffering) override; + bool switchSource(int sessionId, const std::unique_ptr &source) override; + bool isVideoMaster(bool &isVideoMaster) override; + std::vector getSupportedMimeTypes(MediaSourceType type) override; + bool isMimeTypeSupported(const std::string &mimeType) override; + std::vector getSupportedProperties(MediaSourceType mediaType, + const std::vector &propertyNames) override; + void ping(const std::shared_ptr &heartbeatProcedure) override; + + void clearMediaPipelines(); + +private: + IPlaybackService &m_playbackService; + std::shared_ptr m_mediaPipelineFactory; + std::shared_ptr m_mediaPipelineCapabilities; + IDecryptionService &m_decryptionService; + std::map> m_mediaPipelines; + std::mutex m_mediaPipelineMutex; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_MEDIA_PIPELINE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/PlaybackService.cpp b/middleware/rialto-client/media/server/service/source/PlaybackService.cpp new file mode 100644 index 000000000..121e85730 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/PlaybackService.cpp @@ -0,0 +1,155 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "PlaybackService.h" +#include "IMediaPipelineServerInternal.h" +#include "IWebAudioPlayerServerInternal.h" +#include "RialtoServerLogging.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +PlaybackService::PlaybackService(std::shared_ptr &&mediaPipelineFactory, + std::shared_ptr &&mediaPipelineCapabilitiesFactory, + std::shared_ptr &&webAudioPlayerFactory, + std::unique_ptr &&shmBufferFactory, + IDecryptionService &decryptionService) + : m_shmBufferFactory{std::move(shmBufferFactory)}, m_isActive{false}, m_maxPlaybacks{0}, m_maxWebAudioPlayers{0}, + m_mediaPipelineService{std::make_unique(*this, std::move(mediaPipelineFactory), + std::move(mediaPipelineCapabilitiesFactory), + decryptionService)}, + m_webAudioPlayerService{std::make_unique(*this, std::move(webAudioPlayerFactory))} +{ + RIALTO_SERVER_LOG_DEBUG("PlaybackService is constructed"); +} + +PlaybackService::~PlaybackService() +{ + RIALTO_SERVER_LOG_DEBUG("PlaybackService is destructed"); +} + +bool PlaybackService::switchToActive() +{ + try + { + RIALTO_SERVER_LOG_INFO("Switching SessionServer to Active state."); + m_shmBuffer = m_shmBufferFactory->createSharedMemoryBuffer(m_maxPlaybacks, m_maxWebAudioPlayers); + m_isActive = true; + return true; + } + catch (const std::exception &e) + { + RIALTO_SERVER_LOG_ERROR("SessionServer failed to switch to active: %s", e.what()); + m_isActive = false; + return false; + } +} + +void PlaybackService::switchToInactive() +{ + RIALTO_SERVER_LOG_INFO("Switching SessionServer to Inactive state. Cleaning resources..."); + m_isActive = false; + m_mediaPipelineService->clearMediaPipelines(); + m_webAudioPlayerService->clearWebAudioPlayers(); + m_shmBuffer.reset(); +} + +void PlaybackService::setMaxPlaybacks(int maxPlaybacks) +{ + // Method called during initialization only (before setting any state), no need to execute it on a task thread. + m_maxPlaybacks = maxPlaybacks; +} + +void PlaybackService::setMaxWebAudioPlayers(int maxWebAudio) +{ + // Method called during initialization only (before setting any state), no need to execute it on a task thread. + m_maxWebAudioPlayers = maxWebAudio; +} + +void PlaybackService::setClientDisplayName(const std::string &clientDisplayName) const +{ + // Method called during initialization only (before setting any state), no need to execute it on a task thread. + if (!clientDisplayName.empty()) + { + setenv("WAYLAND_DISPLAY", clientDisplayName.c_str(), 1); + } +} + +void PlaybackService::setResourceManagerAppName(const std::string &appName) const +{ + // Method called during initialization only (before setting any state), no need to execute it on a task thread. + if (!appName.empty()) + { + setenv("ESSRMGR_APPID", appName.c_str(), 1); + } +} + +bool PlaybackService::getSharedMemory(int32_t &fd, uint32_t &size) const +{ + auto shmBuffer = m_shmBuffer; + + if (!shmBuffer) + { + return false; + } + fd = shmBuffer->getFd(); + size = shmBuffer->getSize(); + return true; +} + +bool PlaybackService::isActive() const +{ + return m_isActive; +} + +int PlaybackService::getMaxPlaybacks() const +{ + return m_maxPlaybacks; +} + +int PlaybackService::getMaxWebAudioPlayers() const +{ + return m_maxWebAudioPlayers; +} + +std::shared_ptr PlaybackService::getShmBuffer() const +{ + return m_shmBuffer; +} + +IMediaPipelineService &PlaybackService::getMediaPipelineService() const +{ + return *m_mediaPipelineService; +} + +IWebAudioPlayerService &PlaybackService::getWebAudioPlayerService() const +{ + return *m_webAudioPlayerService; +} + +void PlaybackService::ping(const std::shared_ptr &heartbeatProcedure) const +{ + m_mediaPipelineService->ping(heartbeatProcedure); + m_webAudioPlayerService->ping(heartbeatProcedure); +} +} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/PlaybackService.h b/middleware/rialto-client/media/server/service/source/PlaybackService.h new file mode 100644 index 000000000..16d63cc44 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/PlaybackService.h @@ -0,0 +1,86 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_PLAYBACK_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_PLAYBACK_SERVICE_H_ + +#include "IDecryptionService.h" +#include "IHeartbeatProcedure.h" +#include "IMediaPipelineCapabilities.h" +#include "IMediaPipelineServerInternal.h" +#include "IPlaybackService.h" +#include "ISharedMemoryBuffer.h" +#include "IWebAudioPlayerServerInternal.h" +#include "MediaPipelineService.h" +#include "WebAudioPlayerService.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class PlaybackService : public IPlaybackService +{ +public: + PlaybackService(std::shared_ptr &&mediaPipelineFactory, + std::shared_ptr &&mediaPipelineCapabilitiesFactory, + std::shared_ptr &&webAudioPlayerFactory, + std::unique_ptr &&shmBufferFactory, + IDecryptionService &decryptionService); + ~PlaybackService() override; + PlaybackService(const PlaybackService &) = delete; + PlaybackService(PlaybackService &&) = delete; + PlaybackService &operator=(const PlaybackService &) = delete; + PlaybackService &operator=(PlaybackService &&) = delete; + + bool switchToActive() override; + void switchToInactive() override; + void setMaxPlaybacks(int maxPlaybacks) override; + void setMaxWebAudioPlayers(int maxWebAudio) override; + void setClientDisplayName(const std::string &clientDisplayName) const override; + void setResourceManagerAppName(const std::string &clientDisplayName) const override; + + bool isActive() const override; + bool getSharedMemory(int32_t &fd, uint32_t &size) const override; + int getMaxPlaybacks() const override; + int getMaxWebAudioPlayers() const override; + std::shared_ptr getShmBuffer() const override; + IMediaPipelineService &getMediaPipelineService() const override; + IWebAudioPlayerService &getWebAudioPlayerService() const override; + void ping(const std::shared_ptr &heartbeatProcedure) const override; + +private: + std::unique_ptr m_shmBufferFactory; + std::atomic m_isActive; + std::atomic m_maxPlaybacks; + std::atomic m_maxWebAudioPlayers; + std::shared_ptr m_shmBuffer; + std::unique_ptr m_mediaPipelineService; + std::unique_ptr m_webAudioPlayerService; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_PLAYBACK_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/SessionServerManager.cpp b/middleware/rialto-client/media/server/service/source/SessionServerManager.cpp new file mode 100644 index 000000000..d05bbfcd4 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/SessionServerManager.cpp @@ -0,0 +1,282 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SessionServerManager.h" +#include "IApplicationManagementServer.h" +#include "IIpcFactory.h" +#include "ISessionManagementServer.h" +#include "RialtoServerLogging.h" + +#include +#include +#include + +namespace +{ +inline bool isNumber(const std::string &text) +{ + return std::find_if(text.begin(), text.end(), [](const auto &letter) { return !std::isdigit(letter); }) == text.end(); +} +} // namespace + +namespace firebolt::rialto::server::service +{ +SessionServerManager::SessionServerManager(const ipc::IIpcFactory &ipcFactory, IPlaybackService &playbackService, + ICdmService &cdmService, IControlService &controlService, + std::unique_ptr &&heartbeatProcedureFactory) + : m_playbackService{playbackService}, m_cdmService{cdmService}, m_controlService{controlService}, + m_heartbeatProcedureFactory{std::move(heartbeatProcedureFactory)}, + m_applicationManagementServer{ipcFactory.createApplicationManagementServer(*this)}, + m_sessionManagementServer{ipcFactory.createSessionManagementServer(playbackService, cdmService, controlService)}, + m_isServiceRunning{true}, m_currentState{common::SessionServerState::UNINITIALIZED} +{ + RIALTO_SERVER_LOG_INFO("Starting Rialto Server Service"); +} + +SessionServerManager::~SessionServerManager() +{ + RIALTO_SERVER_LOG_INFO("Stopping Rialto Server Service"); + + // The following reset() will ensure that the thread ApplicationManagementServer::m_ipcServerThread + // isn't currently calling any methods within this class (while it is being destructed) + // Particularly, the mentioned thread is responsible for calling the method + // SessionServerManager::switchToNotRunning() which then triggers a call to this destuctor + // after it calls stopService() + m_applicationManagementServer.reset(); + + stopService(); +} + +bool SessionServerManager::initialize(int argc, char *argv[]) +try +{ + if (argc != 2) + { + RIALTO_SERVER_LOG_ERROR("Wrong number of arguments. Rialto Server Service will close now."); + return false; + } + std::string socketStr{argv[1]}; + if (!isNumber(socketStr)) + { + RIALTO_SERVER_LOG_ERROR("Rialto App Management socket is not a number."); + return false; + } + if (!m_applicationManagementServer->initialize(std::stoi(socketStr))) + { + RIALTO_SERVER_LOG_ERROR("Initialization of Application Management server failed."); + return false; + } + m_applicationManagementServer->start(); + return m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::UNINITIALIZED); +} +catch (const std::exception &e) +{ + RIALTO_SERVER_LOG_ERROR("Exception caught during service initialization: %s", e.what()); + return false; +} + +void SessionServerManager::startService() +{ + std::unique_lock lock{m_serviceMutex}; + m_serviceCv.wait(lock, [this]() { return !m_isServiceRunning; }); +} + +void SessionServerManager::stopService() +{ + std::unique_lock lock{m_serviceMutex}; + if (m_isServiceRunning) + { + m_isServiceRunning = false; + m_serviceCv.notify_one(); + } +} + +bool SessionServerManager::configureIpc(const std::string &socketName, unsigned int socketPermissions, + const std::string &socketOwner, const std::string &socketGroup) +{ + if (!m_sessionManagementServer->initialize(socketName, socketPermissions, socketOwner, socketGroup)) + { + RIALTO_SERVER_LOG_ERROR("configureIpc failed - SessionManagementServer failed to initialize"); + return false; + } + return true; +} + +bool SessionServerManager::configureIpc(int32_t socketFd) +{ + if (!m_sessionManagementServer->initialize(socketFd)) + { + RIALTO_SERVER_LOG_ERROR("configureIpc failed - SessionManagementServer failed to initialize"); + return false; + } + return true; +} + +bool SessionServerManager::configureServices(const common::SessionServerState &state, + const common::MaxResourceCapabilitites &maxResource, + const std::string &clientDisplayName, const std::string &appName) +{ + m_sessionManagementServer->start(); + m_playbackService.setMaxPlaybacks(maxResource.maxPlaybacks); + m_playbackService.setMaxWebAudioPlayers(maxResource.maxWebAudioPlayers); + m_playbackService.setClientDisplayName(clientDisplayName); + m_playbackService.setResourceManagerAppName(appName); + return setState(state); +} + +bool SessionServerManager::setState(const common::SessionServerState &state) +{ + switch (state) + { + case common::SessionServerState::ACTIVE: + { + return switchToActive(); + } + case common::SessionServerState::INACTIVE: + { + return switchToInactive(); + } + case common::SessionServerState::NOT_RUNNING: + { + return switchToNotRunning(); + } + default: + { + RIALTO_SERVER_LOG_ERROR("SetState failed - unsupported state"); + m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::ERROR); + } + } + return false; +} + +void SessionServerManager::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, + RIALTO_DEBUG_LEVEL sessionServerLogLevels, RIALTO_DEBUG_LEVEL ipcLogLevels, + RIALTO_DEBUG_LEVEL serverManagerLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) +{ + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_DEFAULT, defaultLogLevels); + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_CLIENT, clientLogLevels); + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_SERVER, sessionServerLogLevels); + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, ipcLogLevels); + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_SERVER_MANAGER, serverManagerLogLevels); + firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_COMMON, commonLogLevels); + m_sessionManagementServer->setLogLevels(defaultLogLevels, clientLogLevels, ipcLogLevels, commonLogLevels); +} + +bool SessionServerManager::ping(std::int32_t id, const std::shared_ptr &ackSender) +{ + auto heartbeatProcedure{m_heartbeatProcedureFactory->createHeartbeatProcedure(ackSender, id)}; + + // Check all rialto server internal threads + m_cdmService.ping(heartbeatProcedure); + m_playbackService.ping(heartbeatProcedure); + + // Check all Rialto Clients + return m_controlService.ping(heartbeatProcedure); +} + +bool SessionServerManager::switchToActive() +{ + if (m_currentState.load() == common::SessionServerState::ACTIVE) + { + RIALTO_SERVER_LOG_DEBUG("Session server already in Active state."); + return true; + } + if (!m_playbackService.switchToActive()) + { + RIALTO_SERVER_LOG_ERROR("Player service failed to switch to active state"); + return false; + } + if (!m_cdmService.switchToActive()) + { + RIALTO_SERVER_LOG_ERROR("Cdm service failed to switch to active state"); + m_playbackService.switchToInactive(); + return false; + } + if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::ACTIVE)) + { + m_controlService.setApplicationState(ApplicationState::RUNNING); + m_currentState.store(common::SessionServerState::ACTIVE); + RIALTO_SERVER_LOG_MIL("RialtoServer state is ACTIVE now"); + return true; + } + m_playbackService.switchToInactive(); + m_cdmService.switchToInactive(); + return false; +} + +bool SessionServerManager::switchToInactive() +{ + if (m_currentState.load() == common::SessionServerState::INACTIVE) + { + RIALTO_SERVER_LOG_DEBUG("Session server already in Inactive state."); + return true; + } + m_playbackService.switchToInactive(); + m_cdmService.switchToInactive(); + if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::INACTIVE)) + { + m_controlService.setApplicationState(ApplicationState::INACTIVE); + m_currentState.store(common::SessionServerState::INACTIVE); + RIALTO_SERVER_LOG_MIL("RialtoServer state is INACTIVE now"); + return true; + } + if (m_currentState.load() == common::SessionServerState::ACTIVE) + { + if (!m_playbackService.switchToActive()) + { + RIALTO_SERVER_LOG_WARN("Player service failed to switch to active state"); + } + if (!m_cdmService.switchToActive()) + { + RIALTO_SERVER_LOG_WARN("Cdm service failed to switch to active state"); + } + } + return false; +} + +bool SessionServerManager::switchToNotRunning() +{ + RIALTO_SERVER_LOG_MIL("RialtoServer state switch to NOT_RUNNING requested"); + if (m_currentState.load() == common::SessionServerState::NOT_RUNNING) + { + RIALTO_SERVER_LOG_DEBUG("Session server already in NotRunning state."); + return true; + } + // Free resources before sending notification to ServerManager + m_playbackService.switchToInactive(); + m_cdmService.switchToInactive(); + m_controlService.setApplicationState(ApplicationState::UNKNOWN); + + bool result{true}; + if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::NOT_RUNNING)) + { + m_currentState.store(common::SessionServerState::NOT_RUNNING); + } + else + { + result = false; + } + + // stopService() needs to be the last command of this method. + // It triggers destruction of SessionServerManager and therefore + // some member variables may not be valid after this command + stopService(); // This HAS TO BE LAST (see above) + return result; +} +} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/SessionServerManager.h b/middleware/rialto-client/media/server/service/source/SessionServerManager.h new file mode 100644 index 000000000..899475e8c --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/SessionServerManager.h @@ -0,0 +1,84 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_SESSION_SERVER_MANAGER_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_SESSION_SERVER_MANAGER_H_ + +#include "IApplicationManagementServer.h" +#include "ICdmService.h" +#include "IControlService.h" +#include "IHeartbeatProcedure.h" +#include "IIpcFactory.h" +#include "IPlaybackService.h" +#include "ISessionManagementServer.h" +#include "ISessionServerManager.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class SessionServerManager : public ISessionServerManager +{ +public: + SessionServerManager(const ipc::IIpcFactory &ipcFactory, IPlaybackService &playbackService, ICdmService &cdmService, + IControlService &controlService, + std::unique_ptr &&heartbeatProcedureFactory); + ~SessionServerManager() override; + SessionServerManager(const SessionServerManager &) = delete; + SessionServerManager(SessionServerManager &&) = delete; + SessionServerManager &operator=(const SessionServerManager &) = delete; + SessionServerManager &operator=(SessionServerManager &&) = delete; + + bool initialize(int argc, char *argv[]) override; + void startService() override; + bool configureIpc(const std::string &socketName, unsigned int socketPermissions, const std::string &socketOwner, + const std::string &socketGroup) override; + bool configureIpc(int32_t socketFd) override; + bool configureServices(const common::SessionServerState &state, const common::MaxResourceCapabilitites &maxResource, + const std::string &clientDisplayName, const std::string &appName) override; + bool setState(const common::SessionServerState &state) override; + void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, + RIALTO_DEBUG_LEVEL sessionServerLogLevels, RIALTO_DEBUG_LEVEL ipcLogLevels, + RIALTO_DEBUG_LEVEL serverManagerLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) override; + bool ping(std::int32_t id, const std::shared_ptr &ackSender) override; + +private: + bool switchToActive(); + bool switchToInactive(); + bool switchToNotRunning(); + void stopService(); + +private: + IPlaybackService &m_playbackService; + ICdmService &m_cdmService; + IControlService &m_controlService; + std::unique_ptr m_heartbeatProcedureFactory; + std::unique_ptr m_applicationManagementServer; + std::unique_ptr m_sessionManagementServer; + std::mutex m_serviceMutex; + std::condition_variable m_serviceCv; + bool m_isServiceRunning; + std::atomic m_currentState; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_SESSION_SERVER_MANAGER_H_ diff --git a/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.cpp b/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.cpp new file mode 100644 index 000000000..5e15aef01 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.cpp @@ -0,0 +1,254 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "WebAudioPlayerService.h" +#include "IGstWebAudioPlayer.h" +#include "IMainThread.h" +#include "ITimer.h" +#include "IWebAudioPlayer.h" +#include "IWebAudioPlayerServerInternal.h" +#include "RialtoServerLogging.h" +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +WebAudioPlayerService::WebAudioPlayerService(IPlaybackService &playbackService, + std::shared_ptr &&webAudioPlayerFactory) + : m_playbackService{playbackService}, m_webAudioPlayerFactory{webAudioPlayerFactory} +{ + RIALTO_SERVER_LOG_DEBUG("WebAudioPlayerService is constructed"); +} + +WebAudioPlayerService::~WebAudioPlayerService() +{ + RIALTO_SERVER_LOG_DEBUG("WebAudioPlayerService is destructed"); +} + +void WebAudioPlayerService::clearWebAudioPlayers() +{ + std::lock_guard lock{m_webAudioPlayerMutex}; + m_webAudioPlayers.clear(); +} + +bool WebAudioPlayerService::createWebAudioPlayer(int handle, + const std::shared_ptr &webAudioPlayerClient, + const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config) +{ + RIALTO_SERVER_LOG_DEBUG("WebAudioPlayerService requested to create new WebAudioPlayer with id: %d", handle); + if (!m_playbackService.isActive()) + { + RIALTO_SERVER_LOG_ERROR("Skip create WebAudioPlayer with id: %d - Session Server in Inactive state", handle); + return false; + } + + { + std::lock_guard lock{m_webAudioPlayerMutex}; + if (m_webAudioPlayers.size() == static_cast(m_playbackService.getMaxWebAudioPlayers())) + { + RIALTO_SERVER_LOG_ERROR("Unable to create WebAudioPlayer with id: %d. Max instance number reached.", handle); + return false; + } + if (m_webAudioPlayers.find(handle) != m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d already exists", handle); + return false; + } + auto shmBuffer = m_playbackService.getShmBuffer(); + + m_webAudioPlayers.emplace( + std::make_pair(handle, m_webAudioPlayerFactory + ->createWebAudioPlayerServerInternal(webAudioPlayerClient, audioMimeType, + priority, config, shmBuffer, handle, + IMainThreadFactory::createFactory(), + IGstWebAudioPlayerFactory::getFactory(), + common::ITimerFactory::getFactory()))); + if (!m_webAudioPlayers.at(handle)) + { + RIALTO_SERVER_LOG_ERROR("Could not create WebAudioPlayer for handle: %d", handle); + m_webAudioPlayers.erase(handle); + return false; + } + } + + RIALTO_SERVER_LOG_INFO("New WebAudioPlayer: %d created", handle); + return true; +} + +bool WebAudioPlayerService::destroyWebAudioPlayer(int handle) +{ + RIALTO_SERVER_LOG_DEBUG("WebAudioPlayerService requested to destroy WebAudioPlayer with handle: %d", handle); + { + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + m_webAudioPlayers.erase(webAudioPlayerIter); + } + RIALTO_SERVER_LOG_INFO("WebAudioPlayer: %d destroyed", handle); + return true; +} + +bool WebAudioPlayerService::play(int handle) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to play WebAudioPlayer with handle: %d", handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->play(); +} + +bool WebAudioPlayerService::pause(int handle) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to pause WebAudioPlayer with handle: %d", handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->pause(); +} + +bool WebAudioPlayerService::setEos(int handle) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to setEos WebAudioPlayer with handle: %d", handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->setEos(); +} + +bool WebAudioPlayerService::getBufferAvailable(int handle, uint32_t &availableFrames, + std::shared_ptr &webAudioShmInfo) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to getBufferAvailable WebAudioPlayer with handle: %d", + handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->getBufferAvailable(availableFrames, webAudioShmInfo); +} + +bool WebAudioPlayerService::getBufferDelay(int handle, uint32_t &delayFrames) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to getBufferDelay WebAudioPlayer with handle: %d", handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->getBufferDelay(delayFrames); +} + +bool WebAudioPlayerService::writeBuffer(int handle, const uint32_t numberOfFrames, void *data) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to writeBuffer WebAudioPlayer with handle: %d", handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->writeBuffer(numberOfFrames, data); +} + +bool WebAudioPlayerService::getDeviceInfo(int handle, uint32_t &preferredFrames, uint32_t &maximumFrames, + bool &supportDeferredPlay) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to getDeviceInfo WebAudioPlayer with handle: %d", handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay); +} + +bool WebAudioPlayerService::setVolume(int handle, double volume) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to setVolume WebAudioPlayer with handle: %d", handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->setVolume(volume); +} + +bool WebAudioPlayerService::getVolume(int handle, double &volume) +{ + RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to getVolume WebAudioPlayer with handle: %d", handle); + + std::lock_guard lock{m_webAudioPlayerMutex}; + auto webAudioPlayerIter = m_webAudioPlayers.find(handle); + if (webAudioPlayerIter == m_webAudioPlayers.end()) + { + RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); + return false; + } + return webAudioPlayerIter->second->getVolume(volume); +} + +void WebAudioPlayerService::ping(const std::shared_ptr &heartbeatProcedure) +{ + RIALTO_SERVER_LOG_DEBUG("Ping requested"); + std::lock_guard lock{m_webAudioPlayerMutex}; + for (const auto &webAudioPlayersPair : m_webAudioPlayers) + { + auto &webAudioPlayer = webAudioPlayersPair.second; + webAudioPlayer->ping(heartbeatProcedure->createHandler()); + } +} +} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.h b/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.h new file mode 100644 index 000000000..04b2c5511 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.h @@ -0,0 +1,76 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_WEB_AUDIO_PLAYER_SERVICE_H_ +#define FIREBOLT_RIALTO_SERVER_SERVICE_WEB_AUDIO_PLAYER_SERVICE_H_ + +#include "IPlaybackService.h" +#include "IWebAudioPlayerServerInternal.h" +#include "IWebAudioPlayerService.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace firebolt::rialto::server::service +{ +class WebAudioPlayerService : public IWebAudioPlayerService +{ +public: + WebAudioPlayerService(IPlaybackService &playbackService, + std::shared_ptr &&webAudioPlayerFactory); + ~WebAudioPlayerService() override; + WebAudioPlayerService(const WebAudioPlayerService &) = delete; + WebAudioPlayerService(WebAudioPlayerService &&) = delete; + WebAudioPlayerService &operator=(const WebAudioPlayerService &) = delete; + WebAudioPlayerService &operator=(WebAudioPlayerService &&) = delete; + + bool createWebAudioPlayer(int handle, const std::shared_ptr &webAudioPlayerClient, + const std::string &audioMimeType, const uint32_t priority, + std::weak_ptr config) override; + bool destroyWebAudioPlayer(int handle) override; + bool play(int handle) override; + bool pause(int handle) override; + bool setEos(int handle) override; + bool getBufferAvailable(int handle, uint32_t &availableFrames, + std::shared_ptr &webAudioShmInfo) override; + bool getBufferDelay(int handle, uint32_t &delayFrames) override; + bool writeBuffer(int handle, const uint32_t numberOfFrames, void *data) override; + bool getDeviceInfo(int handle, uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override; + bool setVolume(int handle, double volume) override; + bool getVolume(int handle, double &volume) override; + void ping(const std::shared_ptr &heartbeatProcedure) override; + + void clearWebAudioPlayers(); + +private: + IPlaybackService &m_playbackService; + std::shared_ptr m_webAudioPlayerFactory; + std::map> m_webAudioPlayers; + std::mutex m_webAudioPlayerMutex; +}; +} // namespace firebolt::rialto::server::service + +#endif // FIREBOLT_RIALTO_SERVER_SERVICE_WEB_AUDIO_PLAYER_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/main.cpp b/middleware/rialto-client/media/server/service/source/main.cpp new file mode 100644 index 000000000..4442a7764 --- /dev/null +++ b/middleware/rialto-client/media/server/service/source/main.cpp @@ -0,0 +1,67 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2022 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "IApplicationSessionServer.h" +#include "IGstInitialiser.h" +#include "RialtoServerLogging.h" + +// NOLINT(build/filename_format) + +int main(int argc, char *argv[]) +{ + const char kSrcRev[] = SRCREV; + const char kTags[] = TAGS; + + if (std::strlen(kSrcRev) > 0) + { + if (std::strlen(kTags) > 0) + { + RIALTO_SERVER_LOG_MIL("Release Tag(s): %s (Commit ID: %s)", kTags, kSrcRev); + } + else + { + RIALTO_SERVER_LOG_MIL("Release Tag(s): No Release Tags! (Commit ID: %s)", kSrcRev); + } + } + else + { + RIALTO_SERVER_LOG_WARN("Failed to get git commit ID!"); + } + + firebolt::rialto::server::IGstInitialiser::instance().initialise(&argc, &argv); + + auto appSessionServer = + firebolt::rialto::server::IApplicationSessionServerFactory::getFactory()->createApplicationSessionServer(); + + if (!appSessionServer->init(argc, argv)) + { + return EXIT_FAILURE; + } + appSessionServer->startService(); + +#ifdef FREE_MEM_BEFORE_EXIT + RIALTO_SERVER_LOG_INFO("Calling ShutdownProtobufLibrary"); + google::protobuf::ShutdownProtobufLibrary(); +#endif + + return EXIT_SUCCESS; +} diff --git a/middleware/rialto-ocdm/include/ActiveSessions.h b/middleware/rialto-ocdm/include/ActiveSessions.h index cf7918bc5..5b87087cd 100644 --- a/middleware/rialto-ocdm/include/ActiveSessions.h +++ b/middleware/rialto-ocdm/include/ActiveSessions.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2022 Sky UK + * Copyright 2022 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/CdmBackend.h b/middleware/rialto-ocdm/include/CdmBackend.h index c56504782..e8f8f9949 100644 --- a/middleware/rialto-ocdm/include/CdmBackend.h +++ b/middleware/rialto-ocdm/include/CdmBackend.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/ICdmBackend.h b/middleware/rialto-ocdm/include/ICdmBackend.h index d78d09c09..d0ce7668c 100644 --- a/middleware/rialto-ocdm/include/ICdmBackend.h +++ b/middleware/rialto-ocdm/include/ICdmBackend.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/IMessageDispatcher.h b/middleware/rialto-ocdm/include/IMessageDispatcher.h index 6a8e36aa8..9dceccde4 100644 --- a/middleware/rialto-ocdm/include/IMessageDispatcher.h +++ b/middleware/rialto-ocdm/include/IMessageDispatcher.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/Logger.h b/middleware/rialto-ocdm/include/Logger.h index cd2e2945f..51b45466c 100644 --- a/middleware/rialto-ocdm/include/Logger.h +++ b/middleware/rialto-ocdm/include/Logger.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h b/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h index baf3706fd..fe7184eac 100644 --- a/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h +++ b/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/MessageDispatcher.h b/middleware/rialto-ocdm/include/MessageDispatcher.h index 4802ecd14..dc051c634 100644 --- a/middleware/rialto-ocdm/include/MessageDispatcher.h +++ b/middleware/rialto-ocdm/include/MessageDispatcher.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/OpenCDMSession.h b/middleware/rialto-ocdm/include/OpenCDMSession.h index dba49ab48..a681ed4e0 100644 --- a/middleware/rialto-ocdm/include/OpenCDMSession.h +++ b/middleware/rialto-ocdm/include/OpenCDMSession.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2022 Sky UK + * Copyright 2022 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,7 @@ #include #include -#include +#include #include #include #include diff --git a/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h b/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h index c0f699df1..f3c862d40 100644 --- a/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h +++ b/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/OpenCDMSystem.h b/middleware/rialto-ocdm/include/OpenCDMSystem.h index 9efc00a05..e9726d635 100644 --- a/middleware/rialto-ocdm/include/OpenCDMSystem.h +++ b/middleware/rialto-ocdm/include/OpenCDMSystem.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2022 Sky UK + * Copyright 2022 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h b/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h index 63d1cc88a..ce447fdc2 100644 --- a/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h +++ b/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h b/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h index 73126a95f..5352e6331 100644 --- a/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h +++ b/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2024 Sky UK + * Copyright 2024 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/ActiveSessions.cpp b/middleware/rialto-ocdm/source/ActiveSessions.cpp index c1df51192..297ed20c9 100644 --- a/middleware/rialto-ocdm/source/ActiveSessions.cpp +++ b/middleware/rialto-ocdm/source/ActiveSessions.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2022 Sky UK + * Copyright 2022 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/CPPLINT.cfg b/middleware/rialto-ocdm/source/CPPLINT.cfg index 8e1289432..781dc1c70 100644 --- a/middleware/rialto-ocdm/source/CPPLINT.cfg +++ b/middleware/rialto-ocdm/source/CPPLINT.cfg @@ -2,7 +2,7 @@ # If not stated otherwise in this file or this component's LICENSE file the # following copyright and licenses apply: # -# Copyright 2023 Sky UK +# Copyright 2023 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/CdmBackend.cpp b/middleware/rialto-ocdm/source/CdmBackend.cpp index d230f1722..01b6605ad 100644 --- a/middleware/rialto-ocdm/source/CdmBackend.cpp +++ b/middleware/rialto-ocdm/source/CdmBackend.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/Logger.cpp b/middleware/rialto-ocdm/source/Logger.cpp index 6d46b1e5b..f49dde108 100644 --- a/middleware/rialto-ocdm/source/Logger.cpp +++ b/middleware/rialto-ocdm/source/Logger.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp b/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp index f0dd064d3..2fbe82dda 100644 --- a/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp +++ b/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/MessageDispatcher.cpp b/middleware/rialto-ocdm/source/MessageDispatcher.cpp index ef78fcb4b..2c3069ea6 100644 --- a/middleware/rialto-ocdm/source/MessageDispatcher.cpp +++ b/middleware/rialto-ocdm/source/MessageDispatcher.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp b/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp index b25af717f..ae4124a61 100644 --- a/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp +++ b/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2022 Sky UK + * Copyright 2022 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp b/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp index ef447490d..801a52418 100644 --- a/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp +++ b/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2023 Sky UK + * Copyright 2023 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp b/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp index c657d49ec..c6a02a204 100644 --- a/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp +++ b/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2024 Sky UK + * Copyright 2024 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/open_cdm.cpp b/middleware/rialto-ocdm/source/open_cdm.cpp index ed7566798..f2422796b 100644 --- a/middleware/rialto-ocdm/source/open_cdm.cpp +++ b/middleware/rialto-ocdm/source/open_cdm.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2022 Sky UK + * Copyright 2022 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/open_cdm_adapter.cpp b/middleware/rialto-ocdm/source/open_cdm_adapter.cpp index 0b694b2fe..7916467a1 100644 --- a/middleware/rialto-ocdm/source/open_cdm_adapter.cpp +++ b/middleware/rialto-ocdm/source/open_cdm_adapter.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2022 Sky UK + * Copyright 2022 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/middleware/rialto-ocdm/source/open_cdm_ext.cpp b/middleware/rialto-ocdm/source/open_cdm_ext.cpp index 7539a43e3..f59d6a87d 100644 --- a/middleware/rialto-ocdm/source/open_cdm_ext.cpp +++ b/middleware/rialto-ocdm/source/open_cdm_ext.cpp @@ -2,7 +2,7 @@ * If not stated otherwise in this file or this component's LICENSE file the * following copyright and licenses apply: * - * Copyright 2022 Sky UK + * Copyright 2022 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 8aa0c53c3c976274c3a5db71802a95ddc1c7aee6 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Wed, 26 Nov 2025 12:41:36 -0500 Subject: [PATCH 09/21] TEST - DO NOT MERGE Signed-off-by: ryadav698 --- CMakeLists.txt | 106 +- .../rialto-client/common/CMakeLists.txt | 58 - .../common/include/EventThread.h | 68 - .../rialto-client/common/include/Timer.h | 72 - .../common/interface/IEventThread.h | 104 - .../rialto-client/common/interface/ITimer.h | 93 - .../common/interface/LinuxUtils.h | 31 - .../common/interface/RialtoCommonLogging.h | 44 - .../common/public/CMakeLists.txt | 51 - .../public/include/SessionServerCommon.in | 112 - .../common/source/EventThread.cpp | 122 - .../common/source/LinuxUtils.cpp | 107 - .../rialto-client/common/source/Timer.cpp | 96 - middleware/rialto-client/ipc/CMakeLists.txt | 54 - middleware/rialto-client/ipc/README.md | 52 - .../rialto-client/ipc/client/CMakeLists.txt | 56 - .../ipc/client/include/IBlockingClosure.h | 82 - .../ipc/client/include/IIpcChannel.h | 170 -- .../client/include/IIpcControllerFactory.h | 52 - .../ipc/client/source/BlockingClosure.cpp | 113 - .../ipc/client/source/BlockingClosure.h | 68 - .../ipc/client/source/IpcChannelImpl.cpp | 1207 --------- .../ipc/client/source/IpcChannelImpl.h | 147 -- .../client/source/IpcClientControllerImpl.cpp | 146 -- .../client/source/IpcClientControllerImpl.h | 130 - .../ipc/client/source/IpcControllerFactory.h | 41 - .../rialto-client/ipc/common/CMakeLists.txt | 59 - .../ipc/common/include/INamedSocket.h | 52 - .../common/proto/rialtoipc-transport.proto | 1 - .../ipc/common/proto/rialtoipc.proto | 1 - .../ipc/common/source/FileDescriptor.cpp | 126 - .../ipc/common/source/FileDescriptor.h | 66 - .../ipc/common/source/IpcLogging.h | 44 - .../ipc/common/source/NamedSocket.cpp | 313 --- .../ipc/common/source/NamedSocket.h | 63 - .../ipc/common/source/SimpleBufferPool.cpp | 106 - .../ipc/common/source/SimpleBufferPool.h | 66 - .../rialto-client/ipc/examples/CMakeLists.txt | 113 - .../ipc/examples/ExampleClient.cpp | 194 -- .../ipc/examples/ExampleServer.cpp | 124 - .../ipc/examples/ExampleSocketPair.cpp | 198 -- .../rialto-client/ipc/examples/example.proto | 74 - .../rialto-client/ipc/server/CMakeLists.txt | 59 - .../ipc/server/include/IIpcController.h | 132 - .../ipc/server/include/IIpcServer.h | 231 -- .../ipc/server/include/IIpcServerFactory.h | 52 - .../ipc/server/source/IpcClientImpl.cpp | 79 - .../ipc/server/source/IpcClientImpl.h | 68 - .../server/source/IpcServerControllerImpl.cpp | 56 - .../server/source/IpcServerControllerImpl.h | 84 - .../ipc/server/source/IpcServerImpl.cpp | 1417 ---------- .../ipc/server/source/IpcServerImpl.h | 159 -- .../rialto-client/logging/CMakeLists.txt | 53 - .../logging/include/RialtoLogging.h | 235 -- .../logging/source/EnvVariableParser.cpp | 223 -- .../logging/source/EnvVariableParser.h | 57 - .../logging/source/LogFileHandle.cpp | 60 - .../logging/source/LogFileHandle.h | 46 - .../logging/source/RialtoLogging.cpp | 413 --- middleware/rialto-client/media/CMakeLists.txt | 31 - .../rialto-client/media/client/CMakeLists.txt | 22 - .../media/client/common/CMakeLists.txt | 35 - .../common/include/RialtoClientLogging.h | 44 - .../media/client/ipc/CMakeLists.txt | 70 - .../media/client/ipc/include/ControlIpc.h | 118 - .../client/ipc/include/IConnectionObserver.h | 35 - .../media/client/ipc/include/IIpcClient.h | 120 - .../media/client/ipc/include/IpcClient.h | 117 - .../media/client/ipc/include/IpcModule.h | 125 - .../ipc/include/MediaKeysCapabilitiesIpc.h | 96 - .../media/client/ipc/include/MediaKeysIpc.h | 183 -- .../include/MediaPipelineCapabilitiesIpc.h | 117 - .../client/ipc/include/MediaPipelineIpc.h | 300 --- .../client/ipc/include/RialtoCommonIpc.h | 31 - .../client/ipc/include/WebAudioPlayerIpc.h | 119 - .../media/client/ipc/interface/IControlIpc.h | 93 - .../IMediaKeysCapabilitiesIpcFactory.h | 62 - .../ipc/interface/IMediaKeysIpcFactory.h | 68 - .../IMediaPipelineCapabilitiesIpcFactory.h | 62 - .../client/ipc/interface/IMediaPipelineIpc.h | 458 ---- .../ipc/interface/IMediaPipelineIpcClient.h | 121 - .../client/ipc/interface/IWebAudioPlayerIpc.h | 170 -- .../ipc/interface/IWebAudioPlayerIpcClient.h | 58 - .../client/ipc/proto/controlmodule.proto | 1 - .../proto/mediakeyscapabilitiesmodule.proto | 1 - .../client/ipc/proto/mediakeysmodule.proto | 1 - .../mediapipelinecapabilitiesmodule.proto | 1 - .../ipc/proto/mediapipelinemodule.proto | 1 - .../media/client/ipc/proto/rialtocommon.proto | 1 - .../ipc/proto/webaudioplayermodule.proto | 1 - .../media/client/ipc/source/ControlIpc.cpp | 265 -- .../media/client/ipc/source/IpcClient.cpp | 219 -- .../media/client/ipc/source/IpcModule.cpp | 136 - .../ipc/source/MediaKeysCapabilitiesIpc.cpp | 216 -- .../media/client/ipc/source/MediaKeysIpc.cpp | 936 ------- .../source/MediaPipelineCapabilitiesIpc.cpp | 208 -- .../client/ipc/source/MediaPipelineIpc.cpp | 1910 -------------- .../client/ipc/source/RialtoCommonIpc.cpp | 44 - .../client/ipc/source/WebAudioPlayerIpc.cpp | 513 ---- .../media/client/main/CMakeLists.txt | 95 - .../client/main/include/AttachedSources.h | 58 - .../client/main/include/ClientController.h | 116 - .../client/main/include/ClientLogControl.h | 87 - .../media/client/main/include/Control.h | 86 - .../client/main/include/IClientController.h | 110 - .../client/main/include/ISharedMemoryHandle.h | 41 - .../media/client/main/include/KeyIdMap.h | 53 - .../media/client/main/include/MediaKeys.h | 132 - .../main/include/MediaKeysCapabilities.h | 93 - .../media/client/main/include/MediaPipeline.h | 336 --- .../main/include/MediaPipelineCapabilities.h | 116 - .../client/main/include/MediaPipelineProxy.h | 186 -- .../client/main/include/SharedMemoryHandle.h | 53 - .../client/main/include/WebAudioPlayer.h | 165 -- .../client/main/include/WebAudioPlayerProxy.h | 75 - .../client/main/source/AttachedSources.cpp | 68 - .../client/main/source/ClientController.cpp | 281 -- .../client/main/source/ClientLogControl.cpp | 143 -- .../media/client/main/source/Control.cpp | 86 - .../media/client/main/source/KeyIdMap.cpp | 64 - .../media/client/main/source/MediaKeys.cpp | 244 -- .../main/source/MediaKeysCapabilities.cpp | 123 - .../client/main/source/MediaPipeline.cpp | 901 ------- .../main/source/MediaPipelineCapabilities.cpp | 111 - .../client/main/source/SharedMemoryHandle.cpp | 76 - .../client/main/source/WebAudioPlayer.cpp | 280 -- .../rialto-client/media/common/CMakeLists.txt | 77 - .../media/common/include/ByteWriter.h | 102 - .../common/include/MediaFrameWriterFactory.h | 44 - .../media/common/include/MediaFrameWriterV1.h | 147 -- .../media/common/include/MediaFrameWriterV2.h | 111 - .../common/interface/IMediaFrameWriter.h | 99 - .../media/common/interface/SchemaVersion.h | 51 - .../media/common/interface/ShmCommon.h | 43 - .../media/common/interface/TypeConverters.h | 32 - .../media/common/proto/metadata.proto | 1 - .../media/common/source/ByteWriter.cpp | 76 - .../common/source/MediaFrameWriterFactory.cpp | 83 - .../common/source/MediaFrameWriterV1.cpp | 157 -- .../common/source/MediaFrameWriterV2.cpp | 215 -- .../media/common/source/SchemaVersion.cpp | 71 - .../media/common/source/TypeConverters.cpp | 91 - .../rialto-client/media/public/CMakeLists.txt | 58 - .../media/public/include/ControlCommon.h | 46 - .../media/public/include/IClientLogControl.h | 103 - .../media/public/include/IClientLogHandler.h | 84 - .../media/public/include/IControl.h | 99 - .../media/public/include/IControlClient.h | 61 - .../media/public/include/IMediaKeys.h | 306 --- .../public/include/IMediaKeysCapabilities.h | 122 - .../media/public/include/IMediaKeysClient.h | 83 - .../media/public/include/IMediaPipeline.h | 1542 ----------- .../include/IMediaPipelineCapabilities.h | 123 - .../public/include/IMediaPipelineClient.h | 222 -- .../media/public/include/IWebAudioPlayer.h | 216 -- .../public/include/IWebAudioPlayerClient.h | 68 - .../media/public/include/MediaCommon.h | 470 ---- .../rialto-client/media/server/CMakeLists.txt | 77 - .../media/server/common/CMakeLists.txt | 35 - .../common/include/RialtoServerLogging.h | 44 - .../media/server/gstplayer/CMakeLists.txt | 147 -- .../server/gstplayer/include/CapsBuilder.h | 99 - .../server/gstplayer/include/FlushWatcher.h | 45 - .../gstplayer/include/GenericPlayerContext.h | 271 -- .../gstplayer/include/GstCapabilities.h | 167 -- .../include/GstDecryptorElementFactory.h | 44 - .../gstplayer/include/GstDecryptorPrivate.h | 107 - .../gstplayer/include/GstDispatcherThread.h | 78 - .../gstplayer/include/GstGenericPlayer.h | 425 --- .../server/gstplayer/include/GstInitialiser.h | 50 - .../gstplayer/include/GstLogForwarding.h | 28 - .../server/gstplayer/include/GstMimeMapping.h | 123 - .../gstplayer/include/GstProtectionMetadata.h | 58 - .../include/GstProtectionMetadataHelper.h | 49 - .../GstProtectionMetadataHelperFactory.h | 43 - .../include/GstRialtoTextTrackSinkPrivate.h | 47 - .../media/server/gstplayer/include/GstSrc.h | 162 -- .../include/GstTextTrackSinkFactory.h | 42 - .../gstplayer/include/GstWebAudioPlayer.h | 190 -- .../server/gstplayer/include/IFlushWatcher.h | 38 - .../include/IGstDecryptorElementFactory.h | 61 - .../gstplayer/include/IGstDispatcherThread.h | 55 - .../include/IGstDispatcherThreadClient.h | 47 - .../include/IGstGenericPlayerPrivate.h | 323 --- .../include/IGstProtectionMetadataHelper.h | 38 - .../IGstProtectionMetadataHelperFactory.h | 58 - .../media/server/gstplayer/include/IGstSrc.h | 123 - .../include/IGstTextTrackSinkFactory.h | 56 - .../include/IGstWebAudioPlayerPrivate.h | 54 - .../server/gstplayer/include/IWorkerThread.h | 66 - .../gstplayer/include/NeedDataMapping.h | 48 - .../media/server/gstplayer/include/Utils.h | 48 - .../gstplayer/include/WebAudioPlayerContext.h | 81 - .../server/gstplayer/include/WorkerThread.h | 91 - .../include/tasks/IGenericPlayerTaskFactory.h | 550 ---- .../gstplayer/include/tasks/IPlayerTask.h | 39 - .../tasks/IWebAudioPlayerTaskFactory.h | 148 -- .../include/tasks/generic/AttachSamples.h | 72 - .../include/tasks/generic/AttachSource.h | 61 - .../tasks/generic/CheckAudioUnderflow.h | 48 - .../include/tasks/generic/DeepElementAdded.h | 56 - .../include/tasks/generic/EnoughData.h | 46 - .../gstplayer/include/tasks/generic/Eos.h | 49 - .../include/tasks/generic/FinishSetupSource.h | 44 - .../gstplayer/include/tasks/generic/Flush.h | 51 - .../tasks/generic/GenericPlayerTaskFactory.h | 145 -- .../include/tasks/generic/HandleBusMessage.h | 60 - .../include/tasks/generic/NeedData.h | 47 - .../gstplayer/include/tasks/generic/Pause.h | 42 - .../gstplayer/include/tasks/generic/Ping.h | 41 - .../gstplayer/include/tasks/generic/Play.h | 40 - .../include/tasks/generic/ProcessAudioGap.h | 56 - .../generic/ReadShmDataAndAttachSamples.h | 50 - .../include/tasks/generic/RemoveSource.h | 49 - .../include/tasks/generic/RenderFrame.h | 42 - .../include/tasks/generic/ReportPosition.h | 49 - .../include/tasks/generic/SetBufferingLimit.h | 45 - .../tasks/generic/SetImmediateOutput.h | 49 - .../include/tasks/generic/SetLowLatency.h | 43 - .../gstplayer/include/tasks/generic/SetMute.h | 52 - .../include/tasks/generic/SetPlaybackRate.h | 47 - .../include/tasks/generic/SetPosition.h | 50 - .../include/tasks/generic/SetSourcePosition.h | 58 - .../include/tasks/generic/SetStreamSyncMode.h | 45 - .../include/tasks/generic/SetSubtitleOffset.h | 47 - .../gstplayer/include/tasks/generic/SetSync.h | 45 - .../include/tasks/generic/SetSyncOff.h | 43 - .../tasks/generic/SetTextTrackIdentifier.h | 48 - .../include/tasks/generic/SetUseBuffering.h | 44 - .../include/tasks/generic/SetVideoGeometry.h | 43 - .../include/tasks/generic/SetVolume.h | 55 - .../include/tasks/generic/SetupElement.h | 51 - .../include/tasks/generic/SetupSource.h | 44 - .../include/tasks/generic/Shutdown.h | 45 - .../gstplayer/include/tasks/generic/Stop.h | 42 - .../include/tasks/generic/SwitchSource.h | 49 - .../tasks/generic/SynchroniseSubtitleClock.h | 50 - .../include/tasks/generic/Underflow.h | 48 - .../tasks/generic/UpdatePlaybackGroup.h | 53 - .../gstplayer/include/tasks/webAudio/Eos.h | 45 - .../include/tasks/webAudio/HandleBusMessage.h | 53 - .../gstplayer/include/tasks/webAudio/Pause.h | 42 - .../gstplayer/include/tasks/webAudio/Ping.h | 41 - .../gstplayer/include/tasks/webAudio/Play.h | 42 - .../include/tasks/webAudio/SetCaps.h | 53 - .../include/tasks/webAudio/SetVolume.h | 45 - .../include/tasks/webAudio/Shutdown.h | 45 - .../gstplayer/include/tasks/webAudio/Stop.h | 40 - .../webAudio/WebAudioPlayerTaskFactory.h | 61 - .../include/tasks/webAudio/WriteBuffer.h | 50 - .../gstplayer/interface/IGstCapabilities.h | 105 - .../gstplayer/interface/IGstGenericPlayer.h | 460 ---- .../interface/IGstGenericPlayerClient.h | 175 -- .../gstplayer/interface/IGstInitialiser.h | 42 - .../gstplayer/interface/IGstWebAudioPlayer.h | 154 -- .../interface/IGstWebAudioPlayerClient.h | 70 - .../server/gstplayer/source/CapsBuilder.cpp | 262 -- .../server/gstplayer/source/FlushWatcher.cpp | 52 - .../gstplayer/source/GstCapabilities.cpp | 464 ---- .../server/gstplayer/source/GstDecryptor.cpp | 372 --- .../gstplayer/source/GstDispatcherThread.cpp | 124 - .../gstplayer/source/GstGenericPlayer.cpp | 2270 ----------------- .../gstplayer/source/GstInitialiser.cpp | 93 - .../gstplayer/source/GstLogForwarding.cpp | 117 - .../source/GstProtectionMetadata.cpp | 92 - .../source/GstProtectionMetadataHelper.cpp | 77 - .../media/server/gstplayer/source/GstSrc.cpp | 531 ---- .../gstplayer/source/GstTextTrackSink.cpp | 585 ----- .../gstplayer/source/GstWebAudioPlayer.cpp | 473 ---- .../gstplayer/source/NeedDataMapping.cpp | 41 - .../media/server/gstplayer/source/Utils.cpp | 183 -- .../server/gstplayer/source/WorkerThread.cpp | 125 - .../source/tasks/generic/AttachSamples.cpp | 135 - .../source/tasks/generic/AttachSource.cpp | 131 - .../tasks/generic/CheckAudioUnderflow.cpp | 65 - .../source/tasks/generic/DeepElementAdded.cpp | 112 - .../source/tasks/generic/EnoughData.cpp | 51 - .../gstplayer/source/tasks/generic/Eos.cpp | 77 - .../tasks/generic/FinishSetupSource.cpp | 127 - .../gstplayer/source/tasks/generic/Flush.cpp | 110 - .../generic/GenericPlayerTaskFactory.cpp | 363 --- .../source/tasks/generic/HandleBusMessage.cpp | 295 --- .../source/tasks/generic/NeedData.cpp | 73 - .../gstplayer/source/tasks/generic/Pause.cpp | 44 - .../gstplayer/source/tasks/generic/Ping.cpp | 40 - .../gstplayer/source/tasks/generic/Play.cpp | 42 - .../source/tasks/generic/ProcessAudioGap.cpp | 53 - .../generic/ReadShmDataAndAttachSamples.cpp | 125 - .../source/tasks/generic/RemoveSource.cpp | 82 - .../source/tasks/generic/RenderFrame.cpp | 46 - .../source/tasks/generic/ReportPosition.cpp | 50 - .../tasks/generic/SetBufferingLimit.cpp | 47 - .../tasks/generic/SetImmediateOutput.cpp | 56 - .../source/tasks/generic/SetLowLatency.cpp | 46 - .../source/tasks/generic/SetMute.cpp | 77 - .../source/tasks/generic/SetPlaybackRate.cpp | 105 - .../source/tasks/generic/SetPosition.cpp | 106 - .../tasks/generic/SetSourcePosition.cpp | 104 - .../tasks/generic/SetStreamSyncMode.cpp | 47 - .../tasks/generic/SetSubtitleOffset.cpp | 53 - .../source/tasks/generic/SetSync.cpp | 44 - .../source/tasks/generic/SetSyncOff.cpp | 46 - .../tasks/generic/SetTextTrackIdentifier.cpp | 51 - .../source/tasks/generic/SetUseBuffering.cpp | 47 - .../source/tasks/generic/SetVideoGeometry.cpp | 47 - .../source/tasks/generic/SetVolume.cpp | 122 - .../source/tasks/generic/SetupElement.cpp | 325 --- .../source/tasks/generic/SetupSource.cpp | 49 - .../source/tasks/generic/Shutdown.cpp | 41 - .../gstplayer/source/tasks/generic/Stop.cpp | 48 - .../source/tasks/generic/SwitchSource.cpp | 48 - .../generic/SynchroniseSubtitleClock.cpp | 91 - .../source/tasks/generic/Underflow.cpp | 65 - .../tasks/generic/UpdatePlaybackGroup.cpp | 79 - .../gstplayer/source/tasks/webAudio/Eos.cpp | 47 - .../tasks/webAudio/HandleBusMessage.cpp | 139 - .../gstplayer/source/tasks/webAudio/Pause.cpp | 46 - .../gstplayer/source/tasks/webAudio/Ping.cpp | 40 - .../gstplayer/source/tasks/webAudio/Play.cpp | 46 - .../source/tasks/webAudio/SetCaps.cpp | 190 -- .../source/tasks/webAudio/SetVolume.cpp | 44 - .../source/tasks/webAudio/Shutdown.cpp | 41 - .../gstplayer/source/tasks/webAudio/Stop.cpp | 43 - .../webAudio/WebAudioPlayerTaskFactory.cpp | 97 - .../source/tasks/webAudio/WriteBuffer.cpp | 108 - .../media/server/ipc/CMakeLists.txt | 82 - .../media/server/ipc/include/AckSender.h | 42 - .../ipc/include/ApplicationManagementServer.h | 62 - .../ipc/include/ControlClientServerInternal.h | 45 - .../server/ipc/include/ControlModuleService.h | 69 - .../ipc/include/IControlModuleService.h | 90 - .../IMediaKeysCapabilitiesModuleService.h | 91 - .../ipc/include/IMediaKeysModuleService.h | 90 - .../IMediaPipelineCapabilitiesModuleService.h | 91 - .../ipc/include/IMediaPipelineModuleService.h | 89 - .../IServerManagerModuleServiceFactory.h | 56 - .../include/IWebAudioPlayerModuleService.h | 89 - .../MediaKeysCapabilitiesModuleService.h | 71 - .../server/ipc/include/MediaKeysClient.h | 48 - .../ipc/include/MediaKeysModuleService.h | 126 - .../MediaPipelineCapabilitiesModuleService.h | 71 - .../server/ipc/include/MediaPipelineClient.h | 62 - .../ipc/include/MediaPipelineModuleService.h | 169 -- .../server/ipc/include/RialtoCommonModule.h | 31 - .../ipc/include/ServerManagerModuleService.h | 60 - .../ipc/include/SessionManagementServer.h | 89 - .../server/ipc/include/SetLogLevelsService.h | 53 - .../server/ipc/include/WebAudioPlayerClient.h | 43 - .../ipc/include/WebAudioPlayerModuleService.h | 94 - .../interface/IApplicationManagementServer.h | 46 - .../media/server/ipc/interface/IIpcFactory.h | 47 - .../ipc/interface/ISessionManagementServer.h | 50 - .../media/server/ipc/interface/IpcFactory.h | 46 - .../server/ipc/proto/controlmodule.proto | 1 - .../proto/mediakeyscapabilitiesmodule.proto | 1 - .../server/ipc/proto/mediakeysmodule.proto | 1 - .../mediapipelinecapabilitiesmodule.proto | 1 - .../ipc/proto/mediapipelinemodule.proto | 1 - .../media/server/ipc/proto/rialtocommon.proto | 1 - .../ipc/proto/servermanagermodule.proto | 1 - .../ipc/proto/webaudioplayermodule.proto | 1 - .../media/server/ipc/source/AckSender.cpp | 38 - .../source/ApplicationManagementServer.cpp | 122 - .../source/ControlClientServerInternal.cpp | 73 - .../ipc/source/ControlModuleService.cpp | 192 -- .../media/server/ipc/source/IpcFactory.cpp | 57 - .../MediaKeysCapabilitiesModuleService.cpp | 171 -- .../server/ipc/source/MediaKeysClient.cpp | 120 - .../ipc/source/MediaKeysModuleService.cpp | 498 ---- ...MediaPipelineCapabilitiesModuleService.cpp | 183 -- .../server/ipc/source/MediaPipelineClient.cpp | 265 -- .../ipc/source/MediaPipelineModuleService.cpp | 1082 -------- .../server/ipc/source/RialtoCommonModule.cpp | 48 - .../ipc/source/ServerManagerModuleService.cpp | 171 -- .../ipc/source/SessionManagementServer.cpp | 187 -- .../server/ipc/source/SetLogLevelsService.cpp | 52 - .../ipc/source/WebAudioPlayerClient.cpp | 82 - .../source/WebAudioPlayerModuleService.cpp | 346 --- .../media/server/main/CMakeLists.txt | 97 - .../server/main/include/ActiveRequests.h | 85 - .../main/include/ControlServerInternal.h | 63 - .../server/main/include/DataReaderFactory.h | 38 - .../media/server/main/include/DataReaderV1.h | 88 - .../media/server/main/include/DataReaderV2.h | 46 - .../server/main/include/HeartbeatProcedure.h | 70 - .../server/main/include/IActiveRequests.h | 52 - .../server/main/include/IDataReaderFactory.h | 45 - .../server/main/include/IMediaKeySession.h | 192 -- .../main/include/INeedMediaDataThread.h | 41 - .../server/main/include/ITextTrackAccessor.h | 70 - .../media/server/main/include/MainThread.h | 141 - .../server/main/include/MediaKeySession.h | 218 -- .../main/include/MediaKeysCapabilities.h | 90 - .../server/main/include/MediaKeysCommon.h | 49 - .../main/include/MediaKeysServerInternal.h | 312 --- .../main/include/MediaPipelineCapabilities.h | 85 - .../include/MediaPipelineServerInternal.h | 720 ------ .../media/server/main/include/NeedMediaData.h | 54 - .../server/main/include/SharedMemoryBuffer.h | 87 - .../media/server/main/include/ShmUtils.h | 42 - .../server/main/include/TextTrackAccessor.h | 70 - .../server/main/include/TextTrackSession.h | 62 - .../include/WebAudioPlayerServerInternal.h | 257 -- .../media/server/main/interface/IAckSender.h | 33 - .../interface/IControlClientServerInternal.h | 64 - .../main/interface/IControlServerInternal.h | 95 - .../media/server/main/interface/IDataReader.h | 35 - .../main/interface/IDecryptionService.h | 42 - .../server/main/interface/IHeartbeatHandler.h | 51 - .../main/interface/IHeartbeatProcedure.h | 57 - .../media/server/main/interface/IMainThread.h | 117 - .../main/interface/IMediaKeysServerInternal.h | 136 - .../interface/IMediaPipelineServerInternal.h | 112 - .../main/interface/ISharedMemoryBuffer.h | 152 -- .../server/main/interface/ITextTrackSession.h | 57 - .../interface/IWebAudioPlayerServerInternal.h | 104 - .../media/server/main/proto/metadata.proto | 1 - .../server/main/source/ActiveRequests.cpp | 126 - .../main/source/ControlServerInternal.cpp | 163 -- .../server/main/source/DataReaderFactory.cpp | 56 - .../media/server/main/source/DataReaderV1.cpp | 68 - .../media/server/main/source/DataReaderV2.cpp | 240 -- .../server/main/source/HeartbeatProcedure.cpp | 78 - .../media/server/main/source/MainThread.cpp | 190 -- .../server/main/source/MediaKeySession.cpp | 489 ---- .../main/source/MediaKeysCapabilities.cpp | 175 -- .../main/source/MediaKeysServerInternal.cpp | 759 ------ .../main/source/MediaPipelineCapabilities.cpp | 102 - .../source/MediaPipelineServerInternal.cpp | 1620 ------------ .../server/main/source/NeedMediaData.cpp | 81 - .../server/main/source/SharedMemoryBuffer.cpp | 453 ---- .../server/main/source/TextTrackAccessor.cpp | 310 --- .../server/main/source/TextTrackSession.cpp | 165 -- .../source/WebAudioPlayerServerInternal.cpp | 577 ----- .../media/server/service/CMakeLists.txt | 59 - .../include/IApplicationSessionServer.h | 45 - .../server/service/include/ICdmService.h | 84 - .../server/service/include/IControlService.h | 50 - .../service/include/IMediaPipelineService.h | 97 - .../server/service/include/IPlaybackService.h | 63 - .../service/include/ISessionServerManager.h | 58 - .../service/include/IWebAudioPlayerService.h | 63 - .../source/ApplicationSessionServer.cpp | 43 - .../service/source/ApplicationSessionServer.h | 77 - .../server/service/source/CdmService.cpp | 561 ---- .../media/server/service/source/CdmService.h | 95 - .../server/service/source/ControlService.cpp | 81 - .../server/service/source/ControlService.h | 51 - .../service/source/MediaPipelineService.cpp | 671 ----- .../service/source/MediaPipelineService.h | 118 - .../server/service/source/PlaybackService.cpp | 155 -- .../server/service/source/PlaybackService.h | 86 - .../service/source/SessionServerManager.cpp | 282 -- .../service/source/SessionServerManager.h | 84 - .../service/source/WebAudioPlayerService.cpp | 254 -- .../service/source/WebAudioPlayerService.h | 76 - .../media/server/service/source/main.cpp | 67 - .../rialto-gstreamer/source/BufferParser.cpp | 207 -- .../rialto-gstreamer/source/BufferParser.h | 76 - .../rialto-gstreamer/source/CMakeLists.txt | 96 - .../rialto-gstreamer/source/Constants.h | 35 - .../rialto-gstreamer/source/ControlBackend.h | 97 - .../source/ControlBackendInterface.h | 32 - .../source/GStreamerEMEUtils.cpp | 211 -- .../source/GStreamerEMEUtils.h | 46 - .../source/GStreamerMSEMediaPlayerClient.cpp | 1280 ---------- .../source/GStreamerMSEMediaPlayerClient.h | 355 --- .../source/GStreamerMSEUtils.cpp | 223 -- .../source/GStreamerMSEUtils.h | 38 - .../source/GStreamerUtils.cpp | 88 - .../rialto-gstreamer/source/GStreamerUtils.h | 56 - .../source/GStreamerWebAudioPlayerClient.cpp | 481 ---- .../source/GStreamerWebAudioPlayerClient.h | 243 -- .../source/GstreamerCatLog.cpp | 22 - .../rialto-gstreamer/source/GstreamerCatLog.h | 31 - .../rialto-gstreamer/source/IMessageQueue.h | 52 - .../source/IPlaybackDelegate.h | 90 - .../source/IPullModePlaybackDelegate.h | 41 - middleware/rialto-gstreamer/source/ITimer.h | 88 - .../source/LogToGstHandler.cpp | 112 - .../rialto-gstreamer/source/LogToGstHandler.h | 35 - .../source/MediaPlayerClientBackend.h | 188 -- .../MediaPlayerClientBackendInterface.h | 76 - .../source/MediaPlayerManager.cpp | 178 -- .../source/MediaPlayerManager.h | 56 - .../rialto-gstreamer/source/MessageQueue.cpp | 187 -- .../rialto-gstreamer/source/MessageQueue.h | 92 - .../source/PullModeAudioPlaybackDelegate.cpp | 715 ------ .../source/PullModeAudioPlaybackDelegate.h | 66 - .../source/PullModePlaybackDelegate.cpp | 962 ------- .../source/PullModePlaybackDelegate.h | 104 - .../PullModeSubtitlePlaybackDelegate.cpp | 305 --- .../source/PullModeSubtitlePlaybackDelegate.h | 50 - .../source/PullModeVideoPlaybackDelegate.cpp | 386 --- .../source/PullModeVideoPlaybackDelegate.h | 57 - .../source/PushModeAudioPlaybackDelegate.cpp | 365 --- .../source/PushModeAudioPlaybackDelegate.h | 59 - .../source/RialtoGSteamerPlugin.cpp | 83 - .../source/RialtoGStreamerMSEAudioSink.cpp | 374 --- .../source/RialtoGStreamerMSEAudioSink.h | 52 - .../source/RialtoGStreamerMSEBaseSink.cpp | 331 --- .../source/RialtoGStreamerMSEBaseSink.h | 73 - .../RialtoGStreamerMSEBaseSinkPrivate.h | 54 - .../source/RialtoGStreamerMSESubtitleSink.cpp | 191 -- .../source/RialtoGStreamerMSESubtitleSink.h | 53 - .../source/RialtoGStreamerMSEVideoSink.cpp | 291 --- .../source/RialtoGStreamerMSEVideoSink.h | 52 - .../source/RialtoGStreamerWebAudioSink.cpp | 297 --- .../source/RialtoGStreamerWebAudioSink.h | 59 - middleware/rialto-gstreamer/source/Timer.cpp | 97 - middleware/rialto-gstreamer/source/Timer.h | 70 - .../source/WebAudioClientBackend.h | 73 - .../source/WebAudioClientBackendInterface.h | 43 - .../rialto-ocdm/include/ActiveSessions.h | 55 - middleware/rialto-ocdm/include/CdmBackend.h | 80 - middleware/rialto-ocdm/include/ICdmBackend.h | 59 - .../rialto-ocdm/include/IMessageDispatcher.h | 39 - middleware/rialto-ocdm/include/Logger.h | 87 - .../include/MediaKeysCapabilitiesBackend.h | 47 - .../rialto-ocdm/include/MessageDispatcher.h | 63 - .../rialto-ocdm/include/OpenCDMSession.h | 68 - .../include/OpenCDMSessionPrivate.h | 104 - .../rialto-ocdm/include/OpenCDMSystem.h | 52 - .../include/OpenCDMSystemPrivate.h | 66 - .../RialtoGStreamerEMEProtectionMetadata.h | 47 - .../rialto-ocdm/source/ActiveSessions.cpp | 68 - middleware/rialto-ocdm/source/CPPLINT.cfg | 21 - middleware/rialto-ocdm/source/CdmBackend.cpp | 286 --- middleware/rialto-ocdm/source/Logger.cpp | 227 -- .../source/MediaKeysCapabilitiesBackend.cpp | 85 - .../rialto-ocdm/source/MessageDispatcher.cpp | 77 - .../source/OpenCDMSessionPrivate.cpp | 554 ---- .../source/OpenCDMSystemPrivate.cpp | 136 - .../rialto-ocdm/source/RialtoFactoryStubs.cpp | 72 - .../RialtoGStreamerEMEProtectionMetadata.cpp | 87 - middleware/rialto-ocdm/source/open_cdm.cpp | 453 ---- .../rialto-ocdm/source/open_cdm_adapter.cpp | 70 - .../rialto-ocdm/source/open_cdm_ext.cpp | 285 --- .../media/public/include/ControlCommon.h | 44 - .../media/public/include/IClientLogControl.h | 101 - .../media/public/include/IClientLogHandler.h | 82 - rialto-master/media/public/include/IControl.h | 97 - .../media/public/include/IControlClient.h | 59 - .../media/public/include/IMediaKeys.h | 304 --- .../public/include/IMediaKeysCapabilities.h | 120 - .../media/public/include/IMediaKeysClient.h | 81 - .../media/public/include/IMediaPipeline.h | 1530 ----------- .../include/IMediaPipelineCapabilities.h | 121 - .../public/include/IMediaPipelineClient.h | 220 -- .../media/public/include/IWebAudioPlayer.h | 214 -- .../public/include/IWebAudioPlayerClient.h | 66 - .../media/public/include/MediaCommon.h | 468 ---- test/gstTestHarness/rialto-gst-pipeline.cpp | 122 +- test/gstTestHarness/rialto-gst-pipeline.h | 106 +- 554 files changed, 160 insertions(+), 78622 deletions(-) delete mode 100644 middleware/rialto-client/common/CMakeLists.txt delete mode 100644 middleware/rialto-client/common/include/EventThread.h delete mode 100644 middleware/rialto-client/common/include/Timer.h delete mode 100644 middleware/rialto-client/common/interface/IEventThread.h delete mode 100644 middleware/rialto-client/common/interface/ITimer.h delete mode 100644 middleware/rialto-client/common/interface/LinuxUtils.h delete mode 100644 middleware/rialto-client/common/interface/RialtoCommonLogging.h delete mode 100644 middleware/rialto-client/common/public/CMakeLists.txt delete mode 100644 middleware/rialto-client/common/public/include/SessionServerCommon.in delete mode 100644 middleware/rialto-client/common/source/EventThread.cpp delete mode 100644 middleware/rialto-client/common/source/LinuxUtils.cpp delete mode 100644 middleware/rialto-client/common/source/Timer.cpp delete mode 100644 middleware/rialto-client/ipc/CMakeLists.txt delete mode 100644 middleware/rialto-client/ipc/README.md delete mode 100644 middleware/rialto-client/ipc/client/CMakeLists.txt delete mode 100644 middleware/rialto-client/ipc/client/include/IBlockingClosure.h delete mode 100644 middleware/rialto-client/ipc/client/include/IIpcChannel.h delete mode 100644 middleware/rialto-client/ipc/client/include/IIpcControllerFactory.h delete mode 100644 middleware/rialto-client/ipc/client/source/BlockingClosure.cpp delete mode 100644 middleware/rialto-client/ipc/client/source/BlockingClosure.h delete mode 100644 middleware/rialto-client/ipc/client/source/IpcChannelImpl.cpp delete mode 100644 middleware/rialto-client/ipc/client/source/IpcChannelImpl.h delete mode 100644 middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.cpp delete mode 100644 middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.h delete mode 100644 middleware/rialto-client/ipc/client/source/IpcControllerFactory.h delete mode 100644 middleware/rialto-client/ipc/common/CMakeLists.txt delete mode 100644 middleware/rialto-client/ipc/common/include/INamedSocket.h delete mode 120000 middleware/rialto-client/ipc/common/proto/rialtoipc-transport.proto delete mode 120000 middleware/rialto-client/ipc/common/proto/rialtoipc.proto delete mode 100644 middleware/rialto-client/ipc/common/source/FileDescriptor.cpp delete mode 100644 middleware/rialto-client/ipc/common/source/FileDescriptor.h delete mode 100644 middleware/rialto-client/ipc/common/source/IpcLogging.h delete mode 100644 middleware/rialto-client/ipc/common/source/NamedSocket.cpp delete mode 100644 middleware/rialto-client/ipc/common/source/NamedSocket.h delete mode 100644 middleware/rialto-client/ipc/common/source/SimpleBufferPool.cpp delete mode 100644 middleware/rialto-client/ipc/common/source/SimpleBufferPool.h delete mode 100644 middleware/rialto-client/ipc/examples/CMakeLists.txt delete mode 100644 middleware/rialto-client/ipc/examples/ExampleClient.cpp delete mode 100644 middleware/rialto-client/ipc/examples/ExampleServer.cpp delete mode 100644 middleware/rialto-client/ipc/examples/ExampleSocketPair.cpp delete mode 100644 middleware/rialto-client/ipc/examples/example.proto delete mode 100644 middleware/rialto-client/ipc/server/CMakeLists.txt delete mode 100644 middleware/rialto-client/ipc/server/include/IIpcController.h delete mode 100644 middleware/rialto-client/ipc/server/include/IIpcServer.h delete mode 100644 middleware/rialto-client/ipc/server/include/IIpcServerFactory.h delete mode 100644 middleware/rialto-client/ipc/server/source/IpcClientImpl.cpp delete mode 100644 middleware/rialto-client/ipc/server/source/IpcClientImpl.h delete mode 100644 middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.cpp delete mode 100644 middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.h delete mode 100644 middleware/rialto-client/ipc/server/source/IpcServerImpl.cpp delete mode 100644 middleware/rialto-client/ipc/server/source/IpcServerImpl.h delete mode 100644 middleware/rialto-client/logging/CMakeLists.txt delete mode 100644 middleware/rialto-client/logging/include/RialtoLogging.h delete mode 100644 middleware/rialto-client/logging/source/EnvVariableParser.cpp delete mode 100644 middleware/rialto-client/logging/source/EnvVariableParser.h delete mode 100644 middleware/rialto-client/logging/source/LogFileHandle.cpp delete mode 100644 middleware/rialto-client/logging/source/LogFileHandle.h delete mode 100644 middleware/rialto-client/logging/source/RialtoLogging.cpp delete mode 100644 middleware/rialto-client/media/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/client/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/client/common/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/client/common/include/RialtoClientLogging.h delete mode 100644 middleware/rialto-client/media/client/ipc/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/client/ipc/include/ControlIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/IConnectionObserver.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/IIpcClient.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/IpcClient.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/IpcModule.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/MediaKeysCapabilitiesIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/MediaKeysIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/MediaPipelineIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/RialtoCommonIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/include/WebAudioPlayerIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/interface/IControlIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaKeysCapabilitiesIpcFactory.h delete mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaKeysIpcFactory.h delete mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaPipelineCapabilitiesIpcFactory.h delete mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpcClient.h delete mode 100644 middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpc.h delete mode 100644 middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpcClient.h delete mode 120000 middleware/rialto-client/media/client/ipc/proto/controlmodule.proto delete mode 120000 middleware/rialto-client/media/client/ipc/proto/mediakeyscapabilitiesmodule.proto delete mode 120000 middleware/rialto-client/media/client/ipc/proto/mediakeysmodule.proto delete mode 120000 middleware/rialto-client/media/client/ipc/proto/mediapipelinecapabilitiesmodule.proto delete mode 120000 middleware/rialto-client/media/client/ipc/proto/mediapipelinemodule.proto delete mode 120000 middleware/rialto-client/media/client/ipc/proto/rialtocommon.proto delete mode 120000 middleware/rialto-client/media/client/ipc/proto/webaudioplayermodule.proto delete mode 100644 middleware/rialto-client/media/client/ipc/source/ControlIpc.cpp delete mode 100644 middleware/rialto-client/media/client/ipc/source/IpcClient.cpp delete mode 100644 middleware/rialto-client/media/client/ipc/source/IpcModule.cpp delete mode 100644 middleware/rialto-client/media/client/ipc/source/MediaKeysCapabilitiesIpc.cpp delete mode 100644 middleware/rialto-client/media/client/ipc/source/MediaKeysIpc.cpp delete mode 100644 middleware/rialto-client/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp delete mode 100644 middleware/rialto-client/media/client/ipc/source/MediaPipelineIpc.cpp delete mode 100644 middleware/rialto-client/media/client/ipc/source/RialtoCommonIpc.cpp delete mode 100644 middleware/rialto-client/media/client/ipc/source/WebAudioPlayerIpc.cpp delete mode 100644 middleware/rialto-client/media/client/main/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/client/main/include/AttachedSources.h delete mode 100644 middleware/rialto-client/media/client/main/include/ClientController.h delete mode 100644 middleware/rialto-client/media/client/main/include/ClientLogControl.h delete mode 100644 middleware/rialto-client/media/client/main/include/Control.h delete mode 100644 middleware/rialto-client/media/client/main/include/IClientController.h delete mode 100644 middleware/rialto-client/media/client/main/include/ISharedMemoryHandle.h delete mode 100644 middleware/rialto-client/media/client/main/include/KeyIdMap.h delete mode 100644 middleware/rialto-client/media/client/main/include/MediaKeys.h delete mode 100644 middleware/rialto-client/media/client/main/include/MediaKeysCapabilities.h delete mode 100644 middleware/rialto-client/media/client/main/include/MediaPipeline.h delete mode 100644 middleware/rialto-client/media/client/main/include/MediaPipelineCapabilities.h delete mode 100644 middleware/rialto-client/media/client/main/include/MediaPipelineProxy.h delete mode 100644 middleware/rialto-client/media/client/main/include/SharedMemoryHandle.h delete mode 100644 middleware/rialto-client/media/client/main/include/WebAudioPlayer.h delete mode 100644 middleware/rialto-client/media/client/main/include/WebAudioPlayerProxy.h delete mode 100644 middleware/rialto-client/media/client/main/source/AttachedSources.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/ClientController.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/ClientLogControl.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/Control.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/KeyIdMap.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/MediaKeys.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/MediaKeysCapabilities.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/MediaPipeline.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/MediaPipelineCapabilities.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/SharedMemoryHandle.cpp delete mode 100644 middleware/rialto-client/media/client/main/source/WebAudioPlayer.cpp delete mode 100644 middleware/rialto-client/media/common/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/common/include/ByteWriter.h delete mode 100644 middleware/rialto-client/media/common/include/MediaFrameWriterFactory.h delete mode 100644 middleware/rialto-client/media/common/include/MediaFrameWriterV1.h delete mode 100644 middleware/rialto-client/media/common/include/MediaFrameWriterV2.h delete mode 100644 middleware/rialto-client/media/common/interface/IMediaFrameWriter.h delete mode 100644 middleware/rialto-client/media/common/interface/SchemaVersion.h delete mode 100644 middleware/rialto-client/media/common/interface/ShmCommon.h delete mode 100644 middleware/rialto-client/media/common/interface/TypeConverters.h delete mode 120000 middleware/rialto-client/media/common/proto/metadata.proto delete mode 100644 middleware/rialto-client/media/common/source/ByteWriter.cpp delete mode 100644 middleware/rialto-client/media/common/source/MediaFrameWriterFactory.cpp delete mode 100644 middleware/rialto-client/media/common/source/MediaFrameWriterV1.cpp delete mode 100644 middleware/rialto-client/media/common/source/MediaFrameWriterV2.cpp delete mode 100644 middleware/rialto-client/media/common/source/SchemaVersion.cpp delete mode 100644 middleware/rialto-client/media/common/source/TypeConverters.cpp delete mode 100644 middleware/rialto-client/media/public/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/public/include/ControlCommon.h delete mode 100644 middleware/rialto-client/media/public/include/IClientLogControl.h delete mode 100644 middleware/rialto-client/media/public/include/IClientLogHandler.h delete mode 100644 middleware/rialto-client/media/public/include/IControl.h delete mode 100644 middleware/rialto-client/media/public/include/IControlClient.h delete mode 100644 middleware/rialto-client/media/public/include/IMediaKeys.h delete mode 100644 middleware/rialto-client/media/public/include/IMediaKeysCapabilities.h delete mode 100644 middleware/rialto-client/media/public/include/IMediaKeysClient.h delete mode 100644 middleware/rialto-client/media/public/include/IMediaPipeline.h delete mode 100644 middleware/rialto-client/media/public/include/IMediaPipelineCapabilities.h delete mode 100644 middleware/rialto-client/media/public/include/IMediaPipelineClient.h delete mode 100644 middleware/rialto-client/media/public/include/IWebAudioPlayer.h delete mode 100644 middleware/rialto-client/media/public/include/IWebAudioPlayerClient.h delete mode 100644 middleware/rialto-client/media/public/include/MediaCommon.h delete mode 100644 middleware/rialto-client/media/server/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/server/common/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/server/common/include/RialtoServerLogging.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/CapsBuilder.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/FlushWatcher.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GenericPlayerContext.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstCapabilities.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstDecryptorElementFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstDecryptorPrivate.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstDispatcherThread.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstGenericPlayer.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstInitialiser.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstLogForwarding.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstMimeMapping.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadata.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelper.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelperFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstRialtoTextTrackSinkPrivate.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstSrc.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstTextTrackSinkFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/GstWebAudioPlayer.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IFlushWatcher.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstDecryptorElementFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThread.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThreadClient.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstGenericPlayerPrivate.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelper.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelperFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstSrc.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstTextTrackSinkFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/IWorkerThread.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/NeedDataMapping.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/Utils.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/WebAudioPlayerContext.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/WorkerThread.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/IPlayerTask.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSamples.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSource.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/CheckAudioUnderflow.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/DeepElementAdded.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/EnoughData.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Eos.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/FinishSetupSource.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Flush.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/NeedData.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Pause.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Ping.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Play.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ProcessAudioGap.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReadShmDataAndAttachSamples.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RemoveSource.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RenderFrame.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReportPosition.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetBufferingLimit.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetImmediateOutput.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetLowLatency.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetMute.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPlaybackRate.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPosition.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSourcePosition.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetStreamSyncMode.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSubtitleOffset.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSync.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSyncOff.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetTextTrackIdentifier.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetUseBuffering.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVideoGeometry.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVolume.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupElement.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupSource.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Shutdown.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Stop.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SwitchSource.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SynchroniseSubtitleClock.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Underflow.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/generic/UpdatePlaybackGroup.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Eos.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/HandleBusMessage.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Pause.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Ping.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Play.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetCaps.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetVolume.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Shutdown.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Stop.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WriteBuffer.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstCapabilities.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayer.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayerClient.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstInitialiser.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayer.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayerClient.h delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/CapsBuilder.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/FlushWatcher.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstCapabilities.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstDecryptor.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstDispatcherThread.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstGenericPlayer.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstInitialiser.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstLogForwarding.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadata.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadataHelper.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstSrc.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstTextTrackSink.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/GstWebAudioPlayer.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/NeedDataMapping.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/Utils.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/WorkerThread.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSamples.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSource.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/EnoughData.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Eos.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Flush.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/NeedData.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Pause.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Ping.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Play.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ProcessAudioGap.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RenderFrame.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReportPosition.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetBufferingLimit.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetImmediateOutput.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetLowLatency.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetMute.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPosition.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSourcePosition.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetStreamSyncMode.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSubtitleOffset.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSync.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSyncOff.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetTextTrackIdentifier.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetUseBuffering.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVideoGeometry.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVolume.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupElement.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupSource.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Shutdown.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Stop.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SynchroniseSubtitleClock.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Underflow.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Eos.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Pause.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Ping.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Play.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetVolume.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Stop.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp delete mode 100644 middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WriteBuffer.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/server/ipc/include/AckSender.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/ApplicationManagementServer.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/ControlClientServerInternal.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/ControlModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/IControlModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/IMediaKeysCapabilitiesModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/IMediaKeysModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/IMediaPipelineCapabilitiesModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/IMediaPipelineModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/IServerManagerModuleServiceFactory.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/IWebAudioPlayerModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/MediaKeysCapabilitiesModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/MediaKeysClient.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/MediaKeysModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/MediaPipelineClient.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/MediaPipelineModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/RialtoCommonModule.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/ServerManagerModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/SessionManagementServer.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/SetLogLevelsService.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/WebAudioPlayerClient.h delete mode 100644 middleware/rialto-client/media/server/ipc/include/WebAudioPlayerModuleService.h delete mode 100644 middleware/rialto-client/media/server/ipc/interface/IApplicationManagementServer.h delete mode 100644 middleware/rialto-client/media/server/ipc/interface/IIpcFactory.h delete mode 100644 middleware/rialto-client/media/server/ipc/interface/ISessionManagementServer.h delete mode 100644 middleware/rialto-client/media/server/ipc/interface/IpcFactory.h delete mode 120000 middleware/rialto-client/media/server/ipc/proto/controlmodule.proto delete mode 120000 middleware/rialto-client/media/server/ipc/proto/mediakeyscapabilitiesmodule.proto delete mode 120000 middleware/rialto-client/media/server/ipc/proto/mediakeysmodule.proto delete mode 120000 middleware/rialto-client/media/server/ipc/proto/mediapipelinecapabilitiesmodule.proto delete mode 120000 middleware/rialto-client/media/server/ipc/proto/mediapipelinemodule.proto delete mode 120000 middleware/rialto-client/media/server/ipc/proto/rialtocommon.proto delete mode 120000 middleware/rialto-client/media/server/ipc/proto/servermanagermodule.proto delete mode 120000 middleware/rialto-client/media/server/ipc/proto/webaudioplayermodule.proto delete mode 100644 middleware/rialto-client/media/server/ipc/source/AckSender.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/ApplicationManagementServer.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/ControlClientServerInternal.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/ControlModuleService.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/IpcFactory.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/MediaKeysCapabilitiesModuleService.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/MediaKeysClient.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/MediaKeysModuleService.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/MediaPipelineClient.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/MediaPipelineModuleService.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/RialtoCommonModule.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/ServerManagerModuleService.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/SessionManagementServer.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/SetLogLevelsService.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/WebAudioPlayerClient.cpp delete mode 100644 middleware/rialto-client/media/server/ipc/source/WebAudioPlayerModuleService.cpp delete mode 100644 middleware/rialto-client/media/server/main/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/server/main/include/ActiveRequests.h delete mode 100644 middleware/rialto-client/media/server/main/include/ControlServerInternal.h delete mode 100644 middleware/rialto-client/media/server/main/include/DataReaderFactory.h delete mode 100644 middleware/rialto-client/media/server/main/include/DataReaderV1.h delete mode 100644 middleware/rialto-client/media/server/main/include/DataReaderV2.h delete mode 100644 middleware/rialto-client/media/server/main/include/HeartbeatProcedure.h delete mode 100644 middleware/rialto-client/media/server/main/include/IActiveRequests.h delete mode 100644 middleware/rialto-client/media/server/main/include/IDataReaderFactory.h delete mode 100644 middleware/rialto-client/media/server/main/include/IMediaKeySession.h delete mode 100644 middleware/rialto-client/media/server/main/include/INeedMediaDataThread.h delete mode 100644 middleware/rialto-client/media/server/main/include/ITextTrackAccessor.h delete mode 100644 middleware/rialto-client/media/server/main/include/MainThread.h delete mode 100644 middleware/rialto-client/media/server/main/include/MediaKeySession.h delete mode 100644 middleware/rialto-client/media/server/main/include/MediaKeysCapabilities.h delete mode 100644 middleware/rialto-client/media/server/main/include/MediaKeysCommon.h delete mode 100644 middleware/rialto-client/media/server/main/include/MediaKeysServerInternal.h delete mode 100644 middleware/rialto-client/media/server/main/include/MediaPipelineCapabilities.h delete mode 100644 middleware/rialto-client/media/server/main/include/MediaPipelineServerInternal.h delete mode 100644 middleware/rialto-client/media/server/main/include/NeedMediaData.h delete mode 100644 middleware/rialto-client/media/server/main/include/SharedMemoryBuffer.h delete mode 100644 middleware/rialto-client/media/server/main/include/ShmUtils.h delete mode 100644 middleware/rialto-client/media/server/main/include/TextTrackAccessor.h delete mode 100644 middleware/rialto-client/media/server/main/include/TextTrackSession.h delete mode 100644 middleware/rialto-client/media/server/main/include/WebAudioPlayerServerInternal.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IAckSender.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IControlClientServerInternal.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IControlServerInternal.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IDataReader.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IDecryptionService.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IHeartbeatHandler.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IHeartbeatProcedure.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IMainThread.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IMediaKeysServerInternal.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IMediaPipelineServerInternal.h delete mode 100644 middleware/rialto-client/media/server/main/interface/ISharedMemoryBuffer.h delete mode 100644 middleware/rialto-client/media/server/main/interface/ITextTrackSession.h delete mode 100644 middleware/rialto-client/media/server/main/interface/IWebAudioPlayerServerInternal.h delete mode 120000 middleware/rialto-client/media/server/main/proto/metadata.proto delete mode 100644 middleware/rialto-client/media/server/main/source/ActiveRequests.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/ControlServerInternal.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/DataReaderFactory.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/DataReaderV1.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/DataReaderV2.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/HeartbeatProcedure.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/MainThread.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/MediaKeySession.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/MediaKeysCapabilities.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/MediaKeysServerInternal.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/MediaPipelineCapabilities.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/MediaPipelineServerInternal.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/NeedMediaData.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/SharedMemoryBuffer.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/TextTrackAccessor.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/TextTrackSession.cpp delete mode 100644 middleware/rialto-client/media/server/main/source/WebAudioPlayerServerInternal.cpp delete mode 100644 middleware/rialto-client/media/server/service/CMakeLists.txt delete mode 100644 middleware/rialto-client/media/server/service/include/IApplicationSessionServer.h delete mode 100644 middleware/rialto-client/media/server/service/include/ICdmService.h delete mode 100644 middleware/rialto-client/media/server/service/include/IControlService.h delete mode 100644 middleware/rialto-client/media/server/service/include/IMediaPipelineService.h delete mode 100644 middleware/rialto-client/media/server/service/include/IPlaybackService.h delete mode 100644 middleware/rialto-client/media/server/service/include/ISessionServerManager.h delete mode 100644 middleware/rialto-client/media/server/service/include/IWebAudioPlayerService.h delete mode 100644 middleware/rialto-client/media/server/service/source/ApplicationSessionServer.cpp delete mode 100644 middleware/rialto-client/media/server/service/source/ApplicationSessionServer.h delete mode 100644 middleware/rialto-client/media/server/service/source/CdmService.cpp delete mode 100644 middleware/rialto-client/media/server/service/source/CdmService.h delete mode 100644 middleware/rialto-client/media/server/service/source/ControlService.cpp delete mode 100644 middleware/rialto-client/media/server/service/source/ControlService.h delete mode 100644 middleware/rialto-client/media/server/service/source/MediaPipelineService.cpp delete mode 100644 middleware/rialto-client/media/server/service/source/MediaPipelineService.h delete mode 100644 middleware/rialto-client/media/server/service/source/PlaybackService.cpp delete mode 100644 middleware/rialto-client/media/server/service/source/PlaybackService.h delete mode 100644 middleware/rialto-client/media/server/service/source/SessionServerManager.cpp delete mode 100644 middleware/rialto-client/media/server/service/source/SessionServerManager.h delete mode 100644 middleware/rialto-client/media/server/service/source/WebAudioPlayerService.cpp delete mode 100644 middleware/rialto-client/media/server/service/source/WebAudioPlayerService.h delete mode 100644 middleware/rialto-client/media/server/service/source/main.cpp delete mode 100644 middleware/rialto-gstreamer/source/BufferParser.cpp delete mode 100644 middleware/rialto-gstreamer/source/BufferParser.h delete mode 100644 middleware/rialto-gstreamer/source/CMakeLists.txt delete mode 100644 middleware/rialto-gstreamer/source/Constants.h delete mode 100644 middleware/rialto-gstreamer/source/ControlBackend.h delete mode 100644 middleware/rialto-gstreamer/source/ControlBackendInterface.h delete mode 100644 middleware/rialto-gstreamer/source/GStreamerEMEUtils.cpp delete mode 100644 middleware/rialto-gstreamer/source/GStreamerEMEUtils.h delete mode 100644 middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.cpp delete mode 100644 middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.h delete mode 100644 middleware/rialto-gstreamer/source/GStreamerMSEUtils.cpp delete mode 100644 middleware/rialto-gstreamer/source/GStreamerMSEUtils.h delete mode 100644 middleware/rialto-gstreamer/source/GStreamerUtils.cpp delete mode 100644 middleware/rialto-gstreamer/source/GStreamerUtils.h delete mode 100644 middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.cpp delete mode 100644 middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.h delete mode 100644 middleware/rialto-gstreamer/source/GstreamerCatLog.cpp delete mode 100644 middleware/rialto-gstreamer/source/GstreamerCatLog.h delete mode 100644 middleware/rialto-gstreamer/source/IMessageQueue.h delete mode 100644 middleware/rialto-gstreamer/source/IPlaybackDelegate.h delete mode 100644 middleware/rialto-gstreamer/source/IPullModePlaybackDelegate.h delete mode 100644 middleware/rialto-gstreamer/source/ITimer.h delete mode 100644 middleware/rialto-gstreamer/source/LogToGstHandler.cpp delete mode 100644 middleware/rialto-gstreamer/source/LogToGstHandler.h delete mode 100644 middleware/rialto-gstreamer/source/MediaPlayerClientBackend.h delete mode 100644 middleware/rialto-gstreamer/source/MediaPlayerClientBackendInterface.h delete mode 100644 middleware/rialto-gstreamer/source/MediaPlayerManager.cpp delete mode 100644 middleware/rialto-gstreamer/source/MediaPlayerManager.h delete mode 100644 middleware/rialto-gstreamer/source/MessageQueue.cpp delete mode 100644 middleware/rialto-gstreamer/source/MessageQueue.h delete mode 100644 middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.cpp delete mode 100644 middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.h delete mode 100644 middleware/rialto-gstreamer/source/PullModePlaybackDelegate.cpp delete mode 100644 middleware/rialto-gstreamer/source/PullModePlaybackDelegate.h delete mode 100644 middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.cpp delete mode 100644 middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.h delete mode 100644 middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.cpp delete mode 100644 middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.h delete mode 100644 middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.cpp delete mode 100644 middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.h delete mode 100644 middleware/rialto-gstreamer/source/RialtoGSteamerPlugin.cpp delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.cpp delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.h delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.cpp delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.h delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSinkPrivate.h delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.cpp delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.h delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.cpp delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.h delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.cpp delete mode 100644 middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.h delete mode 100644 middleware/rialto-gstreamer/source/Timer.cpp delete mode 100644 middleware/rialto-gstreamer/source/Timer.h delete mode 100644 middleware/rialto-gstreamer/source/WebAudioClientBackend.h delete mode 100644 middleware/rialto-gstreamer/source/WebAudioClientBackendInterface.h delete mode 100644 middleware/rialto-ocdm/include/ActiveSessions.h delete mode 100644 middleware/rialto-ocdm/include/CdmBackend.h delete mode 100644 middleware/rialto-ocdm/include/ICdmBackend.h delete mode 100644 middleware/rialto-ocdm/include/IMessageDispatcher.h delete mode 100644 middleware/rialto-ocdm/include/Logger.h delete mode 100644 middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h delete mode 100644 middleware/rialto-ocdm/include/MessageDispatcher.h delete mode 100644 middleware/rialto-ocdm/include/OpenCDMSession.h delete mode 100644 middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h delete mode 100644 middleware/rialto-ocdm/include/OpenCDMSystem.h delete mode 100644 middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h delete mode 100644 middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h delete mode 100644 middleware/rialto-ocdm/source/ActiveSessions.cpp delete mode 100644 middleware/rialto-ocdm/source/CPPLINT.cfg delete mode 100644 middleware/rialto-ocdm/source/CdmBackend.cpp delete mode 100644 middleware/rialto-ocdm/source/Logger.cpp delete mode 100644 middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp delete mode 100644 middleware/rialto-ocdm/source/MessageDispatcher.cpp delete mode 100644 middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp delete mode 100644 middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp delete mode 100644 middleware/rialto-ocdm/source/RialtoFactoryStubs.cpp delete mode 100644 middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp delete mode 100644 middleware/rialto-ocdm/source/open_cdm.cpp delete mode 100644 middleware/rialto-ocdm/source/open_cdm_adapter.cpp delete mode 100644 middleware/rialto-ocdm/source/open_cdm_ext.cpp delete mode 100644 rialto-master/media/public/include/ControlCommon.h delete mode 100644 rialto-master/media/public/include/IClientLogControl.h delete mode 100644 rialto-master/media/public/include/IClientLogHandler.h delete mode 100644 rialto-master/media/public/include/IControl.h delete mode 100644 rialto-master/media/public/include/IControlClient.h delete mode 100644 rialto-master/media/public/include/IMediaKeys.h delete mode 100644 rialto-master/media/public/include/IMediaKeysCapabilities.h delete mode 100644 rialto-master/media/public/include/IMediaKeysClient.h delete mode 100644 rialto-master/media/public/include/IMediaPipeline.h delete mode 100644 rialto-master/media/public/include/IMediaPipelineCapabilities.h delete mode 100644 rialto-master/media/public/include/IMediaPipelineClient.h delete mode 100644 rialto-master/media/public/include/IWebAudioPlayer.h delete mode 100644 rialto-master/media/public/include/IWebAudioPlayerClient.h delete mode 100644 rialto-master/media/public/include/MediaCommon.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a2d511324..b4e13dcaa 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,28 +129,6 @@ if(CMAKE_PLATFORM_UBUNTU OR CMAKE_SYSTEM_NAME STREQUAL Darwin) endif(CMAKE_SYSTEM_NAME STREQUAL Darwin) endif() -# include_directories(${CMAKE_CURRENT_SOURCE_DIR}/rialto-master/media/public/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/public/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/common/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/common/interface) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/logging/interface) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/client/main/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/client/ipc/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/client/ipc/interface) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/media/client/common/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/common/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/common/interface) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/ipc/client/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/ipc/client/source) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/ipc/common/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-client/ipc/common/source) - - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-gstreamer/source) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-gstreamer/source) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/rialto-ocdm/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/middleware/test/utests/ocdm/) - include_directories(${GSTREAMER_INCLUDE_DIRS}) include_directories(${CURL_INCLUDE_DIRS}) include_directories(${GSTREAMERBASE_INCLUDE_DIRS}) @@ -485,56 +463,59 @@ set(GSTTESTHARNESS_SOURCES test/gstTestHarness/mp4demux.hpp ) -file(GLOB RIALTO_GST_CPP_FILES middleware/rialto-gstreamer/source/*.cpp) +find_path( RIALTO_INCLUDE_DIR NAMES IMediaPipeline.h PATH_SUFFIXES rialto) -file(GLOB RIALTO_CLIENT_MAIN_CPP_FILES middleware/rialto-client/media/client/main/source/*.cpp) -file(GLOB RIALTO_CLIENT_IPC_CPP_FILES middleware/rialto-client/media/client/ipc/source/*.cpp) -file(GLOB RIALTO_CLIENT_LOGGING_CPP_FILES middleware/rialto-client/logging/source/*.cpp) -file(GLOB RIALTO_CLIENT_LOGGING_CPP_FILES middleware/rialto-client/common/source/*.cpp) -file(GLOB RIALTO_CLIENT_LOGGING_CPP_FILES middleware/rialto-client/ipc/client/source/*.cpp) -file(GLOB RIALTO_CLIENT_LOGGING_CPP_FILES middleware/rialto-client/ipc/common/source/*.cpp) +# find_path(RIALTO_GSTREAMER_INCLUDE_DIR +# NAMES client/GStreamerMSEMediaPlayerClient.h +# PATH_SUFFIXES rialto-gstreamer +# ) -file(GLOB RIALTO_OCDM_CPP_FILES middleware/rialto-ocdm/source/*.cpp) -file(GLOB RIALTO_GST_H_FILES middleware/rialto-gstreamer/source/*.h) +find_library( RIALTO_LIBRARY NAMES libRialtoClient.so RialtoClient ) -message("TEST START") -message(${RIALTO_GST_CPP_FILES}) -message(${RIALTO_GST_H_FILES}) -list(APPEND GSTTESTHARNESS_SOURCES ${RIALTO_GST_CPP_FILES} ${RIALTO_OCDM_CPP_FILES} ${RIALTO_CLIENT_MAIN_CPP_FILES} ${RIALTO_CLIENT_IPC_CPP_FILES} ${RIALTO_CLIENT_LOGGING_CPP_FILES} ${RIALTO_GST_H_FILES}) +# find_library(RIALTO_SERVER_MANAGER +# NAMES RialtoServerManager libRialtoServerManager.so +# ) -add_executable(gstTestHarness ${GSTTESTHARNESS_SOURCES}) -target_link_libraries(gstTestHarness ${GSTTESTHARNESS_DEPENDS} "-lreadline") -install(TARGETS gstTestHarness - DESTINATION bin -) -# XCode schema target -xcode_define_schema(gstTestHarness) +# find_library(RIALTO_OCDM +# NAMES ocdmRialto libocdmRialto.so +# ) -set(RIALTO_TEST_DEPENDS - ${OS_LD_FLAGS} - ${CMAKE_THREAD_LIBS_INIT} - ${GSTREAMER_LINK_LIBRARIES} - ${GSTREAMERBASE_LINK_LIBRARIES} - ${LIBDASH_LIBRARIES} - ${CURL_LINK_LIBRARIES} -) -set(RIALTO_TEST_SOURCES - test/gstTestHarness/rialto-api-test.cpp - test/gstTestHarness/rialto-gst-pipeline.cpp - test/gstTestHarness/rialto-gst-pipeline.h - test/gstTestHarness/mp4demux.hpp +include( FindPackageHandleStandardArgs ) + +# find_package_handle_standard_args( RIALTO DEFAULT_MSG +# RIALTO_LIBRARY RIALTO_INCLUDE_DIR RIALTO_SERVER_MANAGER RIALTO_OCDM ) + +find_package_handle_standard_args( RIALTO DEFAULT_MSG + RIALTO_LIBRARY RIALTO_INCLUDE_DIR ) + +mark_as_advanced( + RIALTO_INCLUDE_DIR + RIALTO_LIBRARY + RIALTO_GSTREAMER_INCLUDE_DIR ) -file(GLOB RIALTO_CPP_FILES middleware/rialto-gstreamer/source/*.cpp) -list(APPEND RIALTO_TEST_SOURCES ${RIALTO_CPP_FILES}) -add_executable(rialtoTest ${RIALTO_TEST_SOURCES}) -target_link_libraries(rialtoTest ${RIALTO_TEST_DEPENDS} "-lreadline") -install(TARGETS rialtoTest - DESTINATION bin +if( RIALTO_FOUND ) + set( RIALTO_LIBRARIES ${RIALTO_LIBRARY} ) + set(RIALTO_INCLUDE_DIRS + ${RIALTO_INCLUDE_DIR} + ${RIALTO_GSTREAMER_INCLUDE_DIR} ) +endif() + +if( RIALTO_FOUND AND NOT TARGET Rialto::RialtoClient ) + add_library( Rialto::RialtoClient SHARED IMPORTED ) + set_target_properties( Rialto::RialtoClient PROPERTIES + IMPORTED_LOCATION "${RIALTO_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${RIALTO_INCLUDE_DIR}" ) +endif() + +add_executable(gstTestHarness ${GSTTESTHARNESS_SOURCES}) +target_link_libraries(gstTestHarness ${GSTTESTHARNESS_DEPENDS} "-lreadline" Rialto::RialtoClient) + +install(TARGETS gstTestHarness DESTINATION bin) # XCode schema target -xcode_define_schema(rialtoTest) +xcode_define_schema(gstTestHarness) #TODO: Decide which are the actual public headers install(FILES @@ -561,7 +542,6 @@ install(FILES DESTINATION include ) - if (UTEST_ENABLED) add_subdirectory(test/utests EXCLUDE_FROM_ALL) endif() diff --git a/middleware/rialto-client/common/CMakeLists.txt b/middleware/rialto-client/common/CMakeLists.txt deleted file mode 100644 index 42d7a115f..000000000 --- a/middleware/rialto-client/common/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 Sky UK -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -add_subdirectory(public) - -add_library( - RialtoCommon - STATIC - - source/EventThread.cpp - source/LinuxUtils.cpp - source/Timer.cpp - ) - -set_property ( - TARGET - RialtoCommon - PROPERTY POSITION_INDEPENDENT_CODE ON -) - -target_include_directories( - RialtoCommon - - PUBLIC - interface - $ - - PRIVATE - include - ) - -target_link_libraries ( - RialtoCommon - - PRIVATE - RialtoLogging - ) diff --git a/middleware/rialto-client/common/include/EventThread.h b/middleware/rialto-client/common/include/EventThread.h deleted file mode 100644 index 64cc89010..000000000 --- a/middleware/rialto-client/common/include/EventThread.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_EVENT_THREAD_H_ -#define FIREBOLT_RIALTO_COMMON_EVENT_THREAD_H_ - -#include "IEventThread.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::common -{ -class EventThreadFactory : public IEventThreadFactory -{ -public: - std::unique_ptr createEventThread(std::string threadName) const override; -}; - -class EventThread : public IEventThread -{ -public: - explicit EventThread(std::string threadName = std::string()); - ~EventThread(); - - void flush() override; - -private: - void addImpl(std::function &&func) override; - - void threadExecutor(); - -private: - const std::string m_kThreadName; - - std::list> m_funcs; - std::mutex m_lock; - std::condition_variable m_cond; - - std::atomic m_shutdown; - std::thread m_thread; -}; - -}; // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_EVENT_THREAD_H_ diff --git a/middleware/rialto-client/common/include/Timer.h b/middleware/rialto-client/common/include/Timer.h deleted file mode 100644 index 7393c9a61..000000000 --- a/middleware/rialto-client/common/include/Timer.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_TIMER_H_ -#define FIREBOLT_RIALTO_COMMON_TIMER_H_ - -#include "ITimer.h" - -#include -#include -#include -#include -#include - -namespace firebolt::rialto::common -{ -/** - * @brief ITimerFactory factory class definition. - */ -class TimerFactory : public ITimerFactory -{ -public: - /** - * @brief Weak pointer to the singleton factory object. - */ - static std::weak_ptr m_factory; - - std::unique_ptr createTimer(const std::chrono::milliseconds &timeout, const std::function &callback, - TimerType timerType = TimerType::ONE_SHOT) const override; -}; - -class Timer : public ITimer -{ -public: - Timer(const std::chrono::milliseconds &timeout, const std::function &callback, - TimerType timerType = TimerType::ONE_SHOT); - ~Timer(); - Timer(const Timer &) = delete; - Timer(Timer &&) = delete; - Timer &operator=(const Timer &) = delete; - Timer &operator=(Timer &&) = delete; - - void cancel() override; - bool isActive() const override; - -private: - std::atomic m_active; - std::chrono::milliseconds m_timeout; - std::function m_callback; - mutable std::mutex m_mutex; - std::thread m_thread; - std::condition_variable m_cv; -}; -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_TIMER_H_ diff --git a/middleware/rialto-client/common/interface/IEventThread.h b/middleware/rialto-client/common/interface/IEventThread.h deleted file mode 100644 index 4c9932e8c..000000000 --- a/middleware/rialto-client/common/interface/IEventThread.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_I_EVENT_THREAD_H_ -#define FIREBOLT_RIALTO_COMMON_I_EVENT_THREAD_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::common -{ -class IEventThread; - -/** - * @brief IEventThreadFactory factory class, returns a concrete implementation of IEventThread - */ -class IEventThreadFactory -{ -public: - IEventThreadFactory() = default; - virtual ~IEventThreadFactory() = default; - - /** - * @brief Creates a IEventThreadFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates an IEventThread object. - * - * @param[in] threadName : The name of the thread - * - * @retval the new event thread instance or null on error. - */ - virtual std::unique_ptr createEventThread(std::string threadName = std::string()) const = 0; -}; - -class IEventThread -{ -public: - IEventThread() = default; - virtual ~IEventThread() = default; - - IEventThread(const IEventThread &) = delete; - IEventThread &operator=(const IEventThread &) = delete; - IEventThread(IEventThread &&) = delete; - IEventThread &operator=(IEventThread &&) = delete; - - /** - * @brief Flush any waiting events. - */ - virtual void flush() = 0; - - /** - * @brief Add the event handler function. - * - * @param[in] func : Function to call on event. - */ - template inline void add(Function &&func) { this->addImpl(std::forward(func)); } - - /** - * @brief Add the event handler function with arguments. - * - * @param[in] func : Function to call on event. - * @param[in] args : Arguments to pass into the function. - */ - template inline void add(Function &&func, Args &&...args) - { - this->addImpl(std::bind(std::forward(func), std::forward(args)...)); - } - -private: - virtual void addImpl(std::function &&func) = 0; -}; - -}; // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_I_EVENT_THREAD_H_ diff --git a/middleware/rialto-client/common/interface/ITimer.h b/middleware/rialto-client/common/interface/ITimer.h deleted file mode 100644 index 710a3ed32..000000000 --- a/middleware/rialto-client/common/interface/ITimer.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_I_TIMER_H_ -#define FIREBOLT_RIALTO_COMMON_I_TIMER_H_ - -#include -#include -#include - -namespace firebolt::rialto::common -{ -class ITimer; - -enum class TimerType -{ - ONE_SHOT, - PERIODIC -}; - -/** - * @brief ITimerFactory factory class, returns a concrete implementation of ITimer - */ -class ITimerFactory -{ -public: - ITimerFactory() = default; - virtual ~ITimerFactory() = default; - - /** - * @brief Gets the ITimerFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Creates an ITimer object. - * - * @param[in] timeout : Timeout after which callback will be called - * @param[in] callback : Function which is called after timeout - * @param[in] timerType : Type of timer - * - * @retval the new timer instance or null on error. - */ - virtual std::unique_ptr createTimer(const std::chrono::milliseconds &timeout, - const std::function &callback, - TimerType timerType = TimerType::ONE_SHOT) const = 0; -}; - -class ITimer -{ -public: - ITimer() = default; - virtual ~ITimer() = default; - - ITimer(const ITimer &) = delete; - ITimer &operator=(const ITimer &) = delete; - ITimer(ITimer &&) = delete; - ITimer &operator=(ITimer &&) = delete; - - /** - * @brief Cancels the timer - */ - virtual void cancel() = 0; - - /** - * @brief Checks if timer is active - * - * @retval true if timer is active, false otherwise - */ - virtual bool isActive() const = 0; -}; - -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_I_TIMER_H_ diff --git a/middleware/rialto-client/common/interface/LinuxUtils.h b/middleware/rialto-client/common/interface/LinuxUtils.h deleted file mode 100644 index b6c22ade8..000000000 --- a/middleware/rialto-client/common/interface/LinuxUtils.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_LINUX_UTILS_H_ -#define FIREBOLT_RIALTO_COMMON_LINUX_UTILS_H_ - -#include - -namespace firebolt::rialto::common -{ -bool setFilePermissions(const std::string &filePath, unsigned int filePermissions); -bool setFileOwnership(const std::string &filePath, const std::string &fileOwner, const std::string &fileGroup); -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_LINUX_UTILS_H_ diff --git a/middleware/rialto-client/common/interface/RialtoCommonLogging.h b/middleware/rialto-client/common/interface/RialtoCommonLogging.h deleted file mode 100644 index 76b2a1ce2..000000000 --- a/middleware/rialto-client/common/interface/RialtoCommonLogging.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef RIALTO_COMMON_LOGGING_H_ -#define RIALTO_COMMON_LOGGING_H_ - -#include "RialtoLogging.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define RIALTO_COMMON_LOG_FATAL(fmt, args...) RIALTO_LOG_FATAL(RIALTO_COMPONENT_COMMON, fmt, ##args) -#define RIALTO_COMMON_LOG_SYS_FATAL(err, fmt, args...) RIALTO_LOG_SYS_FATAL(RIALTO_COMPONENT_COMMON, err, fmt, ##args) -#define RIALTO_COMMON_LOG_ERROR(fmt, args...) RIALTO_LOG_ERROR(RIALTO_COMPONENT_COMMON, fmt, ##args) -#define RIALTO_COMMON_LOG_SYS_ERROR(err, fmt, args...) RIALTO_LOG_SYS_ERROR(RIALTO_COMPONENT_COMMON, err, fmt, ##args) -#define RIALTO_COMMON_LOG_WARN(fmt, args...) RIALTO_LOG_WARN(RIALTO_COMPONENT_COMMON, fmt, ##args) -#define RIALTO_COMMON_LOG_SYS_WARN(err, fmt, args...) RIALTO_LOG_SYS_WARN(RIALTO_COMPONENT_COMMON, err, fmt, ##args) -#define RIALTO_COMMON_LOG_MIL(fmt, args...) RIALTO_LOG_MIL(RIALTO_COMPONENT_COMMON, fmt, ##args) -#define RIALTO_COMMON_LOG_INFO(fmt, args...) RIALTO_LOG_INFO(RIALTO_COMPONENT_COMMON, fmt, ##args) -#define RIALTO_COMMON_LOG_DEBUG(fmt, args...) RIALTO_LOG_DEBUG(RIALTO_COMPONENT_COMMON, fmt, ##args) - -#ifdef __cplusplus -} -#endif - -#endif // RIALTO_COMMON_LOGGING_H_ diff --git a/middleware/rialto-client/common/public/CMakeLists.txt b/middleware/rialto-client/common/public/CMakeLists.txt deleted file mode 100644 index 019ffe843..000000000 --- a/middleware/rialto-client/common/public/CMakeLists.txt +++ /dev/null @@ -1,51 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2023 Sky UK -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -configure_file( - include/SessionServerCommon.in - include/SessionServerCommon.h - @ONLY ) - -add_library( - RialtoCommonPublic - INTERFACE - ) - -target_include_directories( - RialtoCommonPublic - - INTERFACE - ${CMAKE_BINARY_DIR}/common/public/include - ) - -if( NOT CMAKE_BUILD_TYPE STREQUAL "UnitTests" ) - include( GNUInstallDirs ) - set (LIB_RIALTO_COMMON_PUBLIC_HEADERS - ${CMAKE_BINARY_DIR}/common/public/include/SessionServerCommon.h - ) - install ( - FILES ${LIB_RIALTO_COMMON_PUBLIC_HEADERS} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rialto - ) -endif() diff --git a/middleware/rialto-client/common/public/include/SessionServerCommon.in b/middleware/rialto-client/common/public/include/SessionServerCommon.in deleted file mode 100644 index 1658a93bc..000000000 --- a/middleware/rialto-client/common/public/include/SessionServerCommon.in +++ /dev/null @@ -1,112 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_SESSION_SERVER_COMMON_H_ -#define FIREBOLT_RIALTO_COMMON_SESSION_SERVER_COMMON_H_ - -#include -#include -#include -#include - -namespace firebolt::rialto::common -{ -/** - * @brief Represents all possible states of session server. - * - * Session Servers can be in one of four states, Not Running (session server not loaded or running), - * Active (session server loaded, running and able to stream AV, Inactive (session server loaded but unable - * to stream AV) and Uninitialized (session server loaded, waiting for initialization data). Error is used, - * when something went wrong (for example connection failed) - * - */ -enum class SessionServerState -{ - UNINITIALIZED, - INACTIVE, - ACTIVE, - NOT_RUNNING, - ERROR -}; - -/** - * @brief The max resource capabilities of the platform. - */ -struct MaxResourceCapabilitites -{ - int maxPlaybacks; - int maxWebAudioPlayers; -}; - -/** - * @brief Configuration data for an application - */ -struct AppConfig -{ - std::string clientIpcSocketName; /**< Socket name that Rialto client should connect to */ - /* - * @note Socket name can take the following forms: - * - Empty string, in which case Rialto server will automatically allocate the socket name, e.g. "/tmp/rialto-12" - * - Full path, such as "/foo/bar", in which case Rialto will use this name for the socket - * - Socket name, such as "bar", in which case Rialto will create the named socket in the default dir, e.g. - * "/tmp/bar" In all cases the name can be retrieved with getAppConnectionInfo() - */ - std::string clientDisplayName; /**< Socket name that Rialto client should connect to */ -}; - -/** - * @brief Available permissions - */ -constexpr unsigned int kRead{4}; -constexpr unsigned int kWrite{2}; -constexpr unsigned int kExecute{1}; - -/** - * @brief Socket permissions and ownership - */ -struct SocketPermissions -{ - unsigned int ownerPermissions{@SOCKET_PERMISSIONS_OWNER@}; - unsigned int groupPermissions{@SOCKET_PERMISSIONS_GROUP@}; - unsigned int otherPermissions{@SOCKET_PERMISSIONS_OTHER@}; - std::string owner{@SOCKET_OWNER@}; - std::string group{@SOCKET_GROUP@}; -}; - -/** - * @brief Configuration data for server manager - */ -struct ServerManagerConfig -{ - std::list sessionServerEnvVars{@ENVIRONMENT_VARIABLES@}; - /* List of environment variables, that need to be passed to RialtoSessionServer */ - unsigned numOfPreloadedServers{@NUM_OF_PRELOADED_SERVERS@}; /* Number of preloaded servers */ - std::string sessionServerPath{@SESSION_SERVER_PATH@}; /* Location of Rialto Session Server binary */ - std::chrono::milliseconds sessionServerStartupTimeout{@STARTUP_TIMEOUT_MS@}; - /* Custom session server startup timeout. If 0 - timeout disabled. */ - std::chrono::seconds healthcheckInterval{@HEALTHCHECK_INTERVAL_S@}; - /* Defines how often healthcheck messages will be sent */ - SocketPermissions sessionManagementSocketPermissions{}; /* Defines permissions of session management socket */ - unsigned numOfFailedPingsBeforeRecovery{@NUM_OF_PINGS_BEFORE_RECOVERY@}; - /* Defines how many pings have to fail before recovery action will be taken */ -}; - -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_SESSION_SERVER_COMMON_H_ diff --git a/middleware/rialto-client/common/source/EventThread.cpp b/middleware/rialto-client/common/source/EventThread.cpp deleted file mode 100644 index 1ad60188b..000000000 --- a/middleware/rialto-client/common/source/EventThread.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "EventThread.h" -#include "RialtoCommonLogging.h" - -#include -#include -#include - -namespace firebolt::rialto::common -{ -std::shared_ptr IEventThreadFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_COMMON_LOG_ERROR("Failed to create the event thread factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr EventThreadFactory::createEventThread(std::string threadName) const -{ - return std::make_unique(threadName); -} - -EventThread::EventThread(std::string threadName) : m_kThreadName(std::move(threadName)), m_shutdown(false) -{ - m_thread = std::thread(&EventThread::threadExecutor, this); -} - -EventThread::~EventThread() -{ - std::unique_lock locker(m_lock); - - m_shutdown = true; - - m_cond.notify_all(); - - locker.unlock(); - - if (m_thread.joinable()) - m_thread.join(); -} - -void EventThread::threadExecutor() -{ - if (!m_kThreadName.empty()) - { - pthread_setname_np(pthread_self(), m_kThreadName.c_str()); - } - - std::unique_lock locker(m_lock); - - while (true) - { - while (!m_shutdown && m_funcs.empty()) - m_cond.wait(locker); - - if (m_shutdown) - break; - - std::function func = std::move(m_funcs.front()); - m_funcs.pop_front(); - - m_lock.unlock(); - - if (func) - func(); - - m_lock.lock(); - } -} - -void EventThread::flush() -{ - sem_t semaphore; - sem_init(&semaphore, 0, 0); - - // add a simple function to release the semaphore in the context of the event thread - addImpl( - [sem = &semaphore]() - { - if (sem_post(sem) != 0) - RIALTO_COMMON_LOG_SYS_ERROR(errno, "failed to signal semaphore"); - }); - - // wait for the above call to unblock the semaphore - TEMP_FAILURE_RETRY(sem_wait(&semaphore)); -} - -void EventThread::addImpl(std::function &&func) -{ - std::lock_guard locker(m_lock); - m_funcs.emplace_back(std::move(func)); - m_cond.notify_all(); -} - -}; // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/common/source/LinuxUtils.cpp b/middleware/rialto-client/common/source/LinuxUtils.cpp deleted file mode 100644 index b8906830a..000000000 --- a/middleware/rialto-client/common/source/LinuxUtils.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "LinuxUtils.h" -#include "RialtoCommonLogging.h" -#include -#include -#include -#include - -namespace -{ -constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner -constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group - -uid_t getFileOwnerId(const std::string &fileOwner) -{ - uid_t ownerId = kNoOwnerChange; - const size_t kBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (!fileOwner.empty() && kBufferSize > 0) - { - errno = 0; - passwd passwordStruct{}; - passwd *passwordResult = nullptr; - char buffer[kBufferSize]; - int result = getpwnam_r(fileOwner.c_str(), &passwordStruct, buffer, kBufferSize, &passwordResult); - if (result == 0 && passwordResult) - { - ownerId = passwordResult->pw_uid; - } - else - { - RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to determine ownerId for '%s'", fileOwner.c_str()); - } - } - return ownerId; -} - -gid_t getFileGroupId(const std::string &fileGroup) -{ - gid_t groupId = kNoGroupChange; - const size_t kBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (!fileGroup.empty() && kBufferSize > 0) - { - errno = 0; - group groupStruct{}; - group *groupResult = nullptr; - char buffer[kBufferSize]; - int result = getgrnam_r(fileGroup.c_str(), &groupStruct, buffer, kBufferSize, &groupResult); - if (result == 0 && groupResult) - { - groupId = groupResult->gr_gid; - } - else - { - RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to determine groupId for '%s'", fileGroup.c_str()); - } - } - return groupId; -} -} // namespace - -namespace firebolt::rialto::common -{ -bool setFilePermissions(const std::string &filePath, unsigned int filePermissions) -{ - errno = 0; - if (chmod(filePath.c_str(), filePermissions) != 0) - { - RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to change the permissions on %s", filePath.c_str()); - return false; - } - return true; -} - -bool setFileOwnership(const std::string &filePath, const std::string &fileOwner, const std::string &fileGroup) -{ - uid_t ownerId = getFileOwnerId(fileOwner); - gid_t groupId = getFileGroupId(fileGroup); - - if (ownerId != kNoOwnerChange || groupId != kNoGroupChange) - { - errno = 0; - if (chown(filePath.c_str(), ownerId, groupId) != 0) - { - RIALTO_COMMON_LOG_SYS_WARN(errno, "Failed to change the owner/group for %s", filePath.c_str()); - } - } - return true; -} -} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/common/source/Timer.cpp b/middleware/rialto-client/common/source/Timer.cpp deleted file mode 100644 index ae109a692..000000000 --- a/middleware/rialto-client/common/source/Timer.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Timer.h" -#include "RialtoCommonLogging.h" - -namespace firebolt::rialto::common -{ -std::weak_ptr TimerFactory::m_factory; - -std::shared_ptr ITimerFactory::getFactory() -{ - std::shared_ptr factory = TimerFactory::m_factory.lock(); - - if (!factory) - { - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_COMMON_LOG_ERROR("Failed to create the timer factory, reason: %s", e.what()); - } - - TimerFactory::m_factory = factory; - } - - return factory; -} - -std::unique_ptr TimerFactory::createTimer(const std::chrono::milliseconds &timeout, - const std::function &callback, TimerType timerType) const -{ - return std::make_unique(timeout, callback, timerType); -} - -Timer::Timer(const std::chrono::milliseconds &timeout, const std::function &callback, TimerType timerType) - : m_active{true}, m_timeout{timeout}, m_callback{callback} -{ - m_thread = std::thread( - [this, timerType]() - { - do - { - std::unique_lock lock{m_mutex}; - if (!m_cv.wait_for(lock, m_timeout, [this]() { return !m_active; })) - { - if (m_active && m_callback) - { - lock.unlock(); - m_callback(); - } - } - } while (timerType == TimerType::PERIODIC && m_active); - m_active = false; - }); -} - -Timer::~Timer() -{ - cancel(); -} - -void Timer::cancel() -{ - m_active = false; - - if (std::this_thread::get_id() != m_thread.get_id() && m_thread.joinable()) - { - m_cv.notify_one(); - m_thread.join(); - } -} - -bool Timer::isActive() const -{ - return m_active; -} -} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/ipc/CMakeLists.txt b/middleware/rialto-client/ipc/CMakeLists.txt deleted file mode 100644 index 62e168ef8..000000000 --- a/middleware/rialto-client/ipc/CMakeLists.txt +++ /dev/null @@ -1,54 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 Sky UK -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -cmake_minimum_required( VERSION 3.10 ) -project( RialtoIpc ) - -# The following is to check if building this component from this CMakeLists.txt file -# or if it is part of a bigger project -get_directory_property( HAS_PARENT PARENT_DIRECTORY ) -if( NOT HAS_PARENT ) - - set( PROTOC_PATH "" CACHE STRING "Optional path to the host protobuf compiler (protoc) tool" ) - if( PROTOC_PATH ) - add_executable( protobuf::protoc IMPORTED ) - set_target_properties( protobuf::protoc PROPERTIES IMPORTED_LOCATION "${PROTOC_PATH}" ) - endif() - - # Requires protobuf libraries - find_package( Protobuf REQUIRED ) - - # Add the logging component (static library) - add_subdirectory( "${CMAKE_CURRENT_LIST_DIR}/../rialtoLogging" "${CMAKE_CURRENT_BINARY_DIR}/rialtoLogging" ) - -endif() - -# We require C++14 -set( CMAKE_CXX_STANDARD 17 ) -set( CMAKE_CXX_STANDARD_REQUIRED ON ) - -# Build all components with -fPIC as ultimates -set( CMAKE_POSITION_INDEPENDENT_CODE ON ) - -# Sub-components -add_subdirectory( common ) -add_subdirectory( client ) -add_subdirectory( server ) -add_subdirectory( examples EXCLUDE_FROM_ALL ) - diff --git a/middleware/rialto-client/ipc/README.md b/middleware/rialto-client/ipc/README.md deleted file mode 100644 index deafe2738..000000000 --- a/middleware/rialto-client/ipc/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# RialtoIpc Library - -This library is used to implement a client channel and server for the Google [protobuf][1] [RPC interface][2]. -In addition, it adds extensions to support sending asynchronous events and passing unix file descriptors in RPC -calls and events. - -The 'library' is actually three libraries, a client side and server side library and a 'common' library that -contains shared code between server and client. The reason for this is to allow a process to be both a client -and server without having symbol clash. - -All transfers are over local unix domain sockets. - -### Dependencies -The only dependency is [protobuf][1], minimum version is 3.6. - -### Server-side Library -* A single server instance can create multiple listening unix domain sockets. -* The server allows for registering zero or more services (protobuf defined service) for a client connection. -* The server can receive RPC method calls and response with a reply or error message. -* The server can send single protobuf messages, these are asynchronous events. - -### Client-side Library -* Clients can make RPC calls using stub c++ code generated by protobuf compiler. -* Clients can register to receive events from the server. -* Clients cannot send events to the server. - -### Both Client and Server Libraries -* Neither library contains any internal threads, each must be driven by an external event loop. - - -## Questions - -### What is Protobuf ? -Protobuf is a host compiler tool and library for taking .proto (text) files describing the format of a message or -service and generating code to serialise and deserialise the messages to / from binary data. It is used in this -library to generate c++ stub code for implementing RPC services. - -### Why not use gRPC ? -[gRPC][3] is built on top of protobuf but also provides the client library code to implement transport across various -different protocols (unix sockets, http, websockets, etc), in this sense it provides the same RPC support. However -since it is more generic it lacks some specific things needed by Rialto: -* Client management - the ability to associate a call with a specific client and get the client details (ie. pid or uid). -* File descriptor passing - it has no support for sending or receiving file descriptors. -* Sending asynchronous events - it doesn't have support for sending asynchronous events, although it does have a concept - of a stream of messages which possibly could be adapted. - - - - -[1]: https://developers.google.com/protocol-buffers -[2]: https://developers.google.com/protocol-buffers/docs/proto#services -[3]: https://grpc.io diff --git a/middleware/rialto-client/ipc/client/CMakeLists.txt b/middleware/rialto-client/ipc/client/CMakeLists.txt deleted file mode 100644 index 8334f8d91..000000000 --- a/middleware/rialto-client/ipc/client/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 Sky UK -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -add_library( - RialtoIpcClient - STATIC - - source/IpcChannelImpl.cpp - source/IpcClientControllerImpl.cpp - source/BlockingClosure.cpp - - ) - -target_include_directories( - RialtoIpcClient - - PUBLIC - include - $ - - PRIVATE - $ - - ) - -set_property( - TARGET RialtoIpcClient - PROPERTY POSITION_INDEPENDENT_CODE ON - - ) - -target_link_libraries( - RialtoIpcClient - - PRIVATE - RialtoIpcCommon - RialtoLogging - protobuf::libprotobuf - - ) diff --git a/middleware/rialto-client/ipc/client/include/IBlockingClosure.h b/middleware/rialto-client/ipc/client/include/IBlockingClosure.h deleted file mode 100644 index fa66c9f6e..000000000 --- a/middleware/rialto-client/ipc/client/include/IBlockingClosure.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_I_BLOCKING_CLOSURE_H_ -#define FIREBOLT_RIALTO_IPC_I_BLOCKING_CLOSURE_H_ - -#include "IIpcChannel.h" -#include - -namespace firebolt::rialto::ipc -{ -class IBlockingClosure; - -class IBlockingClosureFactory -{ -public: - IBlockingClosureFactory() = default; - virtual ~IBlockingClosureFactory() = default; - - /** - * @brief Create a IBlockingClosureFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a polling IBlockingClosure object. - * Pump the event loop from within the wait() method. - * - * @param[in] ipcChannel : The ipc channel to wait on. - * - * @retval the protobuf controller instance or null on error. - */ - virtual std::shared_ptr - createBlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel) = 0; - - /** - * @brief Creates a semaphore IBlockingClosure object. - * Do not pump the event loop from within the wait() method. - * - * @retval the protobuf controller instance or null on error. - */ - virtual std::shared_ptr createBlockingClosureSemaphore() = 0; -}; - -class IBlockingClosure : public google::protobuf::Closure -{ -public: - IBlockingClosure() = default; - virtual ~IBlockingClosure() = default; - - IBlockingClosure(const IBlockingClosure &) = delete; - IBlockingClosure &operator=(const IBlockingClosure &) = delete; - IBlockingClosure(IBlockingClosure &&) = delete; - IBlockingClosure &operator=(IBlockingClosure &&) = delete; - - /** - * @brief Wait for the response. - */ - virtual void wait() = 0; -}; - -}; // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_I_BLOCKING_CLOSURE_H_ diff --git a/middleware/rialto-client/ipc/client/include/IIpcChannel.h b/middleware/rialto-client/ipc/client/include/IIpcChannel.h deleted file mode 100644 index aa79e41c4..000000000 --- a/middleware/rialto-client/ipc/client/include/IIpcChannel.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_I_IPC_CHANNEL_H_ -#define FIREBOLT_RIALTO_IPC_I_IPC_CHANNEL_H_ - -#include - -#include -#include -#include -#include - -namespace firebolt::rialto::ipc -{ -class IChannel; - -/** - * @brief IChannel factory class, returns a new connected IChannel object - */ -class IChannelFactory -{ -public: - IChannelFactory() = default; - virtual ~IChannelFactory() = default; - - /** - * @brief Create a IChannelFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Create a connected IChannel object. - * - * \threadsafe - * - * @param[in] socketPath : The path of the socket to connect. - * - * @retval the connected ipc channel instance or null on error. - */ - virtual std::shared_ptr createChannel(const std::string &socketPath) = 0; - - /** - * @brief Create a connected IChannel object. - * - * \threadsafe - * - * Creates an IPC channel around the supplied socket fd. - * The call takes ownership of the fd and it will close it when the channel is - * destructed. The exception to this is if the call fails, in which case the - * caller should close the socket themselves. - * - * @param[in] sockFd : The fd of the connected socket. - * - * @retval the connected ipc channel instance or null on error. - */ - virtual std::shared_ptr createChannel(int sockFd) = 0; -}; - -class IChannel : public google::protobuf::RpcChannel -{ -public: - IChannel() = default; - virtual ~IChannel() = default; - - IChannel(const IChannel &) = delete; - IChannel &operator=(const IChannel &) = delete; - IChannel(IChannel &&) = delete; - IChannel &operator=(IChannel &&) = delete; - - /** - * @brief Disconnect the IPC channel from the socket. - * - * \threadsafe - */ - virtual void disconnect() = 0; - - /** - * @brief Query whether the IPC channel is connected. - * - * \threadsafe - * - * @retval true if connected, false otherwise. - */ - virtual bool isConnected() const = 0; - - /** - * @brief Get the epoll file descriptor. - * - * \threadsafe - * - * @retval >= 0 on success, -1 otherwise. - */ - virtual int fd() const = 0; - - /** - * @brief Waits for any I/O to occur on the socket or timeout from a method call. - * - * The call will block for a maximum of timeoutMSecs, to make the call wait - * indefinitely pass -1. - * - * @param[in] timeoutMSecs : The time to wait for I/O. - * - * @retval false if there was an error or the channel was disconnected, true otherwise - */ - inline bool wait() { return this->wait(-1); } - virtual bool wait(int timeoutMSecs) = 0; - - /** - * @brief Processes at most one event on the channel, this may be a socket message or - * a method call timeout. - * - * \threadsafe - * - * @retval false if there was an error or the channel was disconnected, true otherwise - */ - virtual bool process() = 0; - - /** - * @brief Subscribe for event message. - * - * @param[in] handler : The handler to be called when the event is triggered. - * - * @retval the tag of the subscribed event, -1 on error. - */ - template inline int subscribe(std::function &message)> handler) - { - if (!handler) - return -1; - - return this->subscribeImpl(Message::default_instance().GetTypeName(), Message::default_instance().GetDescriptor(), - [handler_ = std::move(handler)](const std::shared_ptr &msg) - { handler_(std::dynamic_pointer_cast(msg)); }); - } - - /** - * @brief Unsubscribe event. - * - * @param[in] eventTag : The tag of the event to unsubscribe too. - * - * @retval true on success. - */ - virtual bool unsubscribe(int eventTag) = 0; - -private: - virtual int subscribeImpl(const std::string &eventName, const google::protobuf::Descriptor *descriptor, - std::function &msg)> &&handler) = 0; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_I_IPC_CHANNEL_H_ diff --git a/middleware/rialto-client/ipc/client/include/IIpcControllerFactory.h b/middleware/rialto-client/ipc/client/include/IIpcControllerFactory.h deleted file mode 100644 index 4329534b5..000000000 --- a/middleware/rialto-client/ipc/client/include/IIpcControllerFactory.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_FACTORY_H_ -#define FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_FACTORY_H_ - -#include - -#include - -namespace firebolt::rialto::ipc -{ -class IControllerFactory -{ -public: - IControllerFactory() = default; - virtual ~IControllerFactory() = default; - - /** - * @brief Create a IControllerFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a RpcController object. - * - * @retval the protobuf controller instance or null on error. - */ - virtual std::shared_ptr create() = 0; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_FACTORY_H_ diff --git a/middleware/rialto-client/ipc/client/source/BlockingClosure.cpp b/middleware/rialto-client/ipc/client/source/BlockingClosure.cpp deleted file mode 100644 index 4663f6892..000000000 --- a/middleware/rialto-client/ipc/client/source/BlockingClosure.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "BlockingClosure.h" -#include "IpcLogging.h" - -#include -#include -#include - -namespace firebolt::rialto::ipc -{ -std::shared_ptr IBlockingClosureFactory::createFactory() -{ - std::shared_ptr factory; - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Failed to create the blocking closure factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr -BlockingClosureFactory::createBlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel) -{ - std::shared_ptr blockingClosure; - try - { - blockingClosure = std::make_shared(ipcChannel); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Failed to create the blocking closure, reason: %s", e.what()); - } - - return blockingClosure; -} - -std::shared_ptr BlockingClosureFactory::createBlockingClosureSemaphore() -{ - std::shared_ptr blockingClosure; - try - { - blockingClosure = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Failed to create the blocking closure, reason: %s", e.what()); - } - - return blockingClosure; -} - -BlockingClosurePoll::BlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel) - : m_kChannel(std::move(ipcChannel)), m_done(false) -{ -} - -void BlockingClosurePoll::Run() // NOLINT(build/function_format) -{ - m_done = true; -} - -void BlockingClosurePoll::wait() -{ - while (m_kChannel->process() && !m_done) - { - m_kChannel->wait(-1); - } -} - -BlockingClosureSemaphore::BlockingClosureSemaphore() : m_sem{{0}} -{ - sem_init(&m_sem, 0, 0); -} - -BlockingClosureSemaphore::~BlockingClosureSemaphore() -{ - sem_destroy(&m_sem); -} - -void BlockingClosureSemaphore::Run() // NOLINT(build/function_format) -{ - if (sem_post(&m_sem) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to signal semaphore"); -} - -void BlockingClosureSemaphore::wait() -{ - TEMP_FAILURE_RETRY(sem_wait(&m_sem)); -} -}; // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/client/source/BlockingClosure.h b/middleware/rialto-client/ipc/client/source/BlockingClosure.h deleted file mode 100644 index d5c84b782..000000000 --- a/middleware/rialto-client/ipc/client/source/BlockingClosure.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_BLOCKING_CLOSURE_H_ -#define FIREBOLT_RIALTO_IPC_BLOCKING_CLOSURE_H_ - -#include "IBlockingClosure.h" -#include -#include - -namespace firebolt::rialto::ipc -{ -class BlockingClosureFactory : public IBlockingClosureFactory -{ -public: - BlockingClosureFactory() = default; - ~BlockingClosureFactory() override = default; - - std::shared_ptr - createBlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel) override; - std::shared_ptr createBlockingClosureSemaphore() override; -}; - -class BlockingClosurePoll final : public IBlockingClosure -{ -public: - explicit BlockingClosurePoll(std::shared_ptr<::firebolt::rialto::ipc::IChannel> ipcChannel); - ~BlockingClosurePoll() final = default; - - void Run() final; - void wait() final; - -private: - const std::shared_ptr<::firebolt::rialto::ipc::IChannel> m_kChannel; - bool m_done; -}; - -class BlockingClosureSemaphore final : public IBlockingClosure -{ -public: - BlockingClosureSemaphore(); - ~BlockingClosureSemaphore() final; - - void Run() final; - void wait() final; - -private: - sem_t m_sem; -}; -}; // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_BLOCKING_CLOSURE_H_ diff --git a/middleware/rialto-client/ipc/client/source/IpcChannelImpl.cpp b/middleware/rialto-client/ipc/client/source/IpcChannelImpl.cpp deleted file mode 100644 index 85c6fea52..000000000 --- a/middleware/rialto-client/ipc/client/source/IpcChannelImpl.cpp +++ /dev/null @@ -1,1207 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "IpcChannelImpl.h" -#include "IpcLogging.h" -#include "rialtoipc.pb.h" - -#if !defined(SCM_MAX_FD) -#define SCM_MAX_FD 255 -#endif - -namespace -{ -constexpr size_t kMaxMessageSize{128 * 1024}; -const std::chrono::milliseconds kDefaultIpcTimeout{3000}; - -std::chrono::milliseconds getIpcTimeout() -{ - const char *kCustomTimeout = getenv("RIALTO_CLIENT_IPC_TIMEOUT"); - std::chrono::milliseconds timeout{kDefaultIpcTimeout}; - if (kCustomTimeout) - { - try - { - timeout = std::chrono::milliseconds{std::stoull(kCustomTimeout)}; - RIALTO_IPC_LOG_INFO("Using custom Ipc timeout: %sms", kCustomTimeout); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Custom Ipc timeout invalid, ignoring: %s", kCustomTimeout); - } - } - return timeout; -} -} // namespace - -namespace firebolt::rialto::ipc -{ - -std::shared_ptr IChannelFactory::createFactory() -{ - std::shared_ptr factory; - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Failed to create the ipc channel factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr ChannelFactory::createChannel(int sockFd) -{ - std::shared_ptr channel; - try - { - channel = std::make_shared(sockFd); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Failed to create the ipc channel with socketFd %d, reason: %s", sockFd, e.what()); - } - - return channel; -} - -std::shared_ptr ChannelFactory::createChannel(const std::string &socketPath) -{ - std::shared_ptr channel; - try - { - channel = std::make_shared(socketPath); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Failed to create the ipc channel with socketPath %s, reason: %s", socketPath.c_str(), - e.what()); - } - - return channel; -} - -ChannelImpl::ChannelImpl(int sock) - : m_sock(-1), m_epollFd(-1), m_timerFd(-1), m_eventFd(-1), m_serialCounter(1), m_timeout(getIpcTimeout()), - m_eventTagCounter(1) -{ - if (!attachSocket(sock)) - { - throw std::runtime_error("Failed attach the socket"); - } - if (!initChannel()) - { - termChannel(); - throw std::runtime_error("Failed to initalise the channel"); - } - if (!isConnectedInternal()) - { - termChannel(); - throw std::runtime_error("Channel not connected"); - } -} - -ChannelImpl::ChannelImpl(const std::string &socketPath) - : m_sock(-1), m_epollFd(-1), m_timerFd(-1), m_eventFd(-1), m_serialCounter(1), m_timeout(getIpcTimeout()), - m_eventTagCounter(1) -{ - if (!createConnectedSocket(socketPath)) - { - throw std::runtime_error("Failed connect socket"); - } - if (!initChannel()) - { - termChannel(); - throw std::runtime_error("Failed to initalise the channel"); - } - if (!isConnectedInternal()) - { - termChannel(); - throw std::runtime_error("Channel not connected"); - } -} - -ChannelImpl::~ChannelImpl() -{ - termChannel(); -} - -bool ChannelImpl::createConnectedSocket(const std::string &socketPath) -{ - int sock = socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (sock < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to create socket"); - return false; - } - - struct sockaddr_un addr = {0}; - memset(&addr, 0x00, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); - - if (::connect(sock, reinterpret_cast(&addr), sizeof(addr)) == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to connect to %s", socketPath.c_str()); - close(sock); - return false; - } - - m_sock = sock; - - return true; -} - -bool ChannelImpl::attachSocket(int sockFd) -{ - // sanity check the supplied socket is of the right type - struct sockaddr addr; - socklen_t len = sizeof(addr); - if ((getsockname(sockFd, &addr, &len) < 0) || (len < sizeof(sa_family_t))) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get name of supplied socket"); - return false; - } - if (addr.sa_family != AF_UNIX) - { - RIALTO_IPC_LOG_ERROR("supplied client socket is not a unix domain socket"); - return false; - } - - int type = 0; - len = sizeof(type); - if ((getsockopt(sockFd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) || (len != sizeof(type))) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get type of supplied socket"); - return false; - } - if (type != SOCK_SEQPACKET) - { - RIALTO_IPC_LOG_ERROR("supplied client socket is not of type SOCK_SEQPACKET"); - return false; - } - - // set the O_NONBLOCKING flag on the socket - int flags = fcntl(sockFd, F_GETFL); - if ((flags < 0) || (fcntl(sockFd, F_SETFL, flags | O_NONBLOCK) < 0)) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to set socket to non-blocking mode"); - return false; - } - - m_sock = sockFd; - - return true; -} - -bool ChannelImpl::initChannel() -{ - // create epoll so can listen for timeouts as well as socket messages - m_epollFd = epoll_create1(EPOLL_CLOEXEC); - if (m_epollFd < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll failed"); - return false; - } - - // add the socket to epoll - epoll_event sockEvent = {.events = EPOLLIN, .data = {.fd = m_sock}}; - if (epoll_ctl(m_epollFd, EPOLL_CTL_ADD, m_sock, &sockEvent) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add eventfd"); - return false; - } - - m_timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); - if (m_timerFd < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "timerfd_create failed"); - return false; - } - - // add the timer event to epoll - epoll_event timerEvent = {.events = EPOLLIN, .data = {.fd = m_timerFd}}; - if (epoll_ctl(m_epollFd, EPOLL_CTL_ADD, m_timerFd, &timerEvent) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add eventfd"); - return false; - } - - // and lastly the eventfd to wake the poll loop - m_eventFd = eventfd(0, EFD_CLOEXEC); - if (m_eventFd < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "eventfd create failed"); - return false; - } - - // add the timer event to epoll - epoll_event wakeEvent = {.events = EPOLLIN, .data = {.fd = m_eventFd}}; - if (epoll_ctl(m_epollFd, EPOLL_CTL_ADD, m_eventFd, &wakeEvent) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add eventfd"); - return false; - } - - return true; -} - -void ChannelImpl::termChannel() -{ - // close the socket and the epoll and timer fds - if (m_sock >= 0) - disconnectNoLock(); - if ((m_epollFd >= 0) && (close(m_epollFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "closing epoll fd failed"); - if ((m_timerFd >= 0) && (close(m_timerFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "closing timer fd failed"); - if ((m_eventFd >= 0) && (close(m_eventFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "closing event fd failed"); - - // if any method calls are still outstanding then complete them with errors now - for (auto &entry : m_methodCalls) - { - completeWithError(&entry.second, "Channel destructed"); - } - - m_methodCalls.clear(); -} - -void ChannelImpl::disconnect() -{ - // disconnect from the socket - { - std::lock_guard locker(m_lock); - - if (m_sock < 0) - return; - - disconnectNoLock(); - } - - // wake the wait(...) call so client code is blocked there it is woken - if (m_eventFd >= 0) - { - uint64_t wakeup = 1; - if (TEMP_FAILURE_RETRY(write(m_eventFd, &wakeup, sizeof(wakeup))) != sizeof(wakeup)) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to write to wake event fd"); - } - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - - */ -void ChannelImpl::disconnectNoLock() -{ - if (m_sock < 0) - { - RIALTO_IPC_LOG_WARN("not connected\n"); - return; - } - - // remove the socket from epoll - if (epoll_ctl(m_epollFd, EPOLL_CTL_DEL, m_sock, nullptr) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to remove socket"); - } - - // shutdown and close the socket - if (shutdown(m_sock, SHUT_RDWR) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "shutdown error"); - } - if (close(m_sock) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "close error"); - } - - m_sock = -1; -} - -bool ChannelImpl::isConnected() const -{ - return isConnectedInternal(); -} - -bool ChannelImpl::isConnectedInternal() const -{ - std::lock_guard locker(m_lock); - return (m_sock >= 0); -} - -int ChannelImpl::fd() const -{ - return m_epollFd; -} - -bool ChannelImpl::wait(int timeoutMSecs) -{ - if ((m_epollFd < 0) || !isConnected()) - { - return false; - } - - // wait for any event (with timeout) - struct pollfd fds[2]; - fds[0].fd = m_epollFd; - fds[0].events = POLLIN; - - int rc = TEMP_FAILURE_RETRY(poll(fds, 1, timeoutMSecs)); - if (rc < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "poll failed?"); - return false; - } - - return isConnected(); -} - -bool ChannelImpl::process() -{ - if (!isConnected()) - return false; - - struct epoll_event events[3]; - int rc = TEMP_FAILURE_RETRY(epoll_wait(m_epollFd, events, 3, 0)); - if (rc < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_wait failed"); - return false; - } - - enum - { - HaveSocketEvent = 0x1, - HaveTimeoutEvent = 0x2, - HaveWakeEvent = 0x4 - }; - unsigned eventsMask = 0; - for (int i = 0; i < rc; i++) - { - if (events[i].data.fd == m_sock) - eventsMask |= HaveSocketEvent; - else if (events[i].data.fd == m_timerFd) - eventsMask |= HaveTimeoutEvent; - else if (events[i].data.fd == m_eventFd) - eventsMask |= HaveWakeEvent; - } - - if ((eventsMask & HaveSocketEvent) && !processSocketEvent()) - { - std::map callsToDelete; - { - std::lock_guard locker(m_lock); - callsToDelete = m_methodCalls; - m_methodCalls.clear(); - } - - for (auto &entry : callsToDelete) - { - completeWithError(&entry.second, "Socket down"); - } - return false; - } - - if (eventsMask & HaveTimeoutEvent) - processTimeoutEvent(); - - if (eventsMask & HaveWakeEvent) - processWakeEvent(); - - return isConnected(); -} - -bool ChannelImpl::unsubscribe(int eventTag) -{ - std::lock_guard locker(m_eventsLock); - bool success = false; - - auto it = std::find_if(m_eventHandlers.begin(), m_eventHandlers.end(), - [&](const auto &item) { return item.second.id == eventTag; }); - if (m_eventHandlers.end() != it) - { - m_eventHandlers.erase(it); - success = true; - } - - return success; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - - */ -bool ChannelImpl::processSocketEvent() -{ - static std::mutex bufLock; - std::lock_guard bufLocker(bufLock); - - static std::vector dataBuf(kMaxMessageSize); - static std::vector ctrlBuf(CMSG_SPACE(SCM_MAX_FD * sizeof(int))); - - // read all messages from the client socket, we break out if the socket is closed - // or EWOULDBLOCK is returned on a read (ie. no more messages to read) - while (true) - { - struct msghdr msg = {nullptr}; - struct iovec io = {.iov_base = dataBuf.data(), .iov_len = dataBuf.size()}; - - bzero(&msg, sizeof(msg)); - msg.msg_iov = &io; - msg.msg_iovlen = 1; - msg.msg_control = ctrlBuf.data(); - msg.msg_controllen = ctrlBuf.size(); - - // read one message - ssize_t rd = TEMP_FAILURE_RETRY(recvmsg(m_sock, &msg, MSG_CMSG_CLOEXEC)); - if (rd < 0) - { - if (errno != EWOULDBLOCK) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "error reading client socket"); - - std::lock_guard locker(m_lock); - disconnectNoLock(); - return false; - } - - break; - } - else if (rd == 0) - { - // server closed connection, and we've read all data - RIALTO_IPC_LOG_INFO("socket remote end closed, disconnecting channel"); - - std::lock_guard locker(m_lock); - disconnectNoLock(); - return false; - } - else if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) - { - RIALTO_IPC_LOG_WARN("received truncated message from server, discarding"); - - // make sure to close all the fds, otherwise we'll leak them, this - // will read the fds and return in a vector, which will then be - // destroyed, closing all the fds - readMessageFds(&msg, 16); - } - else - { - // if there is control data then assume fd(s) have been passed - std::vector fds; - if (msg.msg_controllen > 0) - { - fds = readMessageFds(&msg, 32); - } - - // process the message from the server - processServerMessage(dataBuf.data(), rd, &fds); - } - } - - return true; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Called from process() to check if the timerfd has expired and if so cancel - the any outstanding method calls that have now timed-out. - - */ -void ChannelImpl::processTimeoutEvent() -{ - // read the timerfd to clear any expirations - uint64_t expirations; - ssize_t rd = TEMP_FAILURE_RETRY(read(m_timerFd, &expirations, sizeof(expirations))); - if (rd < 0) - { - if (errno != EWOULDBLOCK) - RIALTO_IPC_LOG_SYS_ERROR(errno, "error reading timerfd"); - return; - } - - // check if any method call has no expired - std::unique_lock locker(m_lock); - - // stores the timed-out method calls - std::vector timedOuts; - - // remove the method calls that have expired - const auto kNow = std::chrono::steady_clock::now(); - auto it = m_methodCalls.begin(); - while (it != m_methodCalls.end()) - { - if (kNow >= it->second.timeoutDeadline) - { - timedOuts.emplace_back(it->second); - it = m_methodCalls.erase(it); - } - else - { - ++it; - } - } - - // if we still have method calls available, then re-calculate the timer for the next timeout - if (!m_methodCalls.empty()) - { - updateTimeoutTimer(); - } - - // drop the lock and now terminate the timed out method calls - locker.unlock(); - - for (auto &call : timedOuts) - { - completeWithError(&call, "Timed out"); - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Called from process() when the eventfd was used to wake the event loop. All - the function does is read the eventfd to clear it's value. - - */ -void ChannelImpl::processWakeEvent() -{ - uint64_t ignore; - if (TEMP_FAILURE_RETRY(read(m_eventFd, &ignore, sizeof(ignore))) != sizeof(ignore)) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "Failed to read wake eventfd to clear it"); - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Updates the timerfd to the time of the next method call timeout. If method - calls are pending then the timer is disabled. - - This should be called whenever a new method is called or a method has - completed. - - \note Must be called while holding the m_lock mutex. - - */ -void ChannelImpl::updateTimeoutTimer() -{ - struct itimerspec ts = {{0}}; - - // if no method calls then just disarm the timer - if (!m_methodCalls.empty()) - { - // otherwise, find the next soonest timeout - std::chrono::steady_clock::time_point nextTimeout = std::chrono::steady_clock::time_point::max(); - auto nextTimeoutCall = - std::min_element(m_methodCalls.begin(), m_methodCalls.end(), [](const auto &elem, const auto ¤tMin) - { return elem.second.timeoutDeadline < currentMin.second.timeoutDeadline; }); - if (nextTimeoutCall != m_methodCalls.end()) - { - nextTimeout = nextTimeoutCall->second.timeoutDeadline; - } - - // set the timerfd to the next duration - const std::chrono::microseconds kDuration = - std::chrono::duration_cast(nextTimeout - std::chrono::steady_clock::now()); - if (kDuration <= std::chrono::microseconds::zero()) - { - ts.it_value.tv_nsec = 1000; - } - else - { - ts.it_value.tv_sec = static_cast(std::chrono::duration_cast(kDuration).count()); - ts.it_value.tv_nsec = static_cast((kDuration.count() % 1000000) * 1000); - } - - RIALTO_IPC_LOG_DEBUG("next timeout in %" PRId64 "us - %ld.%09lds", kDuration.count(), ts.it_value.tv_sec, - ts.it_value.tv_nsec); - } - - // write the timeout value - if (timerfd_settime(m_timerFd, 0, &ts, nullptr) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to write to timerfd"); - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Processes a single message from the server, it may be a method call response - or an event. - - - */ -void ChannelImpl::processServerMessage(const uint8_t *data, size_t dataLen, std::vector *fds) -{ - // parse the message - transport::MessageFromServer message; - if (!message.ParseFromArray(data, static_cast(dataLen))) - { - RIALTO_IPC_LOG_ERROR("invalid message from server"); - return; - } - - // check if an event or a reply to a request - if (message.has_reply()) - { - processReplyFromServer(message.reply(), fds); - } - else if (message.has_error()) - { - processErrorFromServer(message.error()); - } - else if (message.has_event()) - { - processEventFromServer(message.event(), fds); - } - else - { - RIALTO_IPC_LOG_ERROR("message from server is missing reply or event type"); - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - - */ -void ChannelImpl::processReplyFromServer(const transport::MethodCallReply &reply, std::vector *fds) -{ - RIALTO_IPC_LOG_DEBUG("processing reply from server"); - - std::unique_lock locker(m_lock); - - // find the original request - const uint64_t kSerialId = reply.reply_id(); - auto it = m_methodCalls.find(kSerialId); - if (it == m_methodCalls.end()) - { - RIALTO_IPC_LOG_ERROR("failed to find request for received reply with id %" PRIu64 "", reply.reply_id()); - return; - } - - // take the method call and remove from the map of outstanding calls - MethodCall methodCall = it->second; - m_methodCalls.erase(it); - - // update the timeout timer now a method call has been processed - updateTimeoutTimer(); - - // can now drop the lock - locker.unlock(); - - // this is an actual reply so try and read it - if (!methodCall.response->ParseFromString(reply.reply_message())) - { - RIALTO_IPC_LOG_ERROR("failed to parse method reply from server"); - completeWithError(&methodCall, "Failed to parse reply message"); - } - else if (!addReplyFileDescriptors(methodCall.response, fds)) - { - RIALTO_IPC_LOG_ERROR("mismatch of file descriptors to the reply"); - completeWithError(&methodCall, "Mismatched file descriptors in message"); - } - else if (methodCall.closure) - { - RIALTO_IPC_LOG_DEBUG("reply{ serial %" PRIu64 " } - %s { %s }", kSerialId, - methodCall.response->GetTypeName().c_str(), methodCall.response->ShortDebugString().c_str()); - - complete(&methodCall); - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - - */ -void ChannelImpl::processErrorFromServer(const transport::MethodCallError &error) -{ - RIALTO_IPC_LOG_DEBUG("processing error from server"); - - std::unique_lock locker(m_lock); - - // find the original request - const uint64_t kSerialId = error.reply_id(); - auto it = m_methodCalls.find(kSerialId); - if (it == m_methodCalls.end()) - { - RIALTO_IPC_LOG_ERROR("failed to find request for received reply with id %" PRIu64 "", error.reply_id()); - return; - } - - // take the method call and remove from the map of outstanding calls - MethodCall methodCall = it->second; - m_methodCalls.erase(it); - - // update the timeout timer now a method call has been processed - updateTimeoutTimer(); - - // can now drop the lock - locker.unlock(); - - RIALTO_IPC_LOG_DEBUG("error{ serial %" PRIu64 " } - %s", kSerialId, error.error_reason().c_str()); - - // complete the call with an error - completeWithError(&methodCall, error.error_reason()); -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - - */ -void ChannelImpl::processEventFromServer(const transport::EventFromServer &event, std::vector *fds) -{ - RIALTO_IPC_LOG_DEBUG("processing event from server"); - - const std::string &kEventName = event.event_name(); - - std::lock_guard locker(m_eventsLock); - - auto range = m_eventHandlers.equal_range(kEventName); - if (range.first == range.second) - { - RIALTO_IPC_LOG_WARN("no handler for event %s", kEventName.c_str()); - return; - } - - const google::protobuf::Descriptor *kDescriptor = range.first->second.descriptor; - - const google::protobuf::Message *kPrototype = - google::protobuf::MessageFactory::generated_factory()->GetPrototype(kDescriptor); - if (!kPrototype) - { - RIALTO_IPC_LOG_ERROR("failed to create prototype for event %s", kEventName.c_str()); - return; - } - - std::shared_ptr message(kPrototype->New()); - if (!message) - { - RIALTO_IPC_LOG_ERROR("failed to create mutable message from prototype"); - return; - } - - if (!message->ParseFromString(event.message())) - { - RIALTO_IPC_LOG_ERROR("failed to parse message for event %s", kEventName.c_str()); - } - else if (!addReplyFileDescriptors(message.get(), fds)) - { - RIALTO_IPC_LOG_ERROR("mismatch of file descriptors to the reply"); - } - else - { - RIALTO_IPC_LOG_DEBUG("event{ %s } - %s { %s }", kEventName.c_str(), message->GetTypeName().c_str(), - message->ShortDebugString().c_str()); - - for (auto it = range.first; it != range.second; ++it) - { - it->second.handler(message); - } - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - \static - - Reads all the file descriptors from a unix domain socket received \a msg. - It returns the file descriptors as a vector of FileDescriptor objects, - these objects safely store the fd and close them when they're destructed. - - The \a limit specifies the maximum number of fds to store, if more were - sent then they are automatically closed and not returned in the vector. - - */ -std::vector ChannelImpl::readMessageFds(const struct msghdr *msg, size_t limit) -{ - std::vector fds; - - for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != nullptr; - cmsg = CMSG_NXTHDR(const_cast(msg), cmsg)) - { - if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) - { - const unsigned kFdsLength = cmsg->cmsg_len - CMSG_LEN(0); - if ((kFdsLength < sizeof(int)) || ((kFdsLength % sizeof(int)) != 0)) - { - RIALTO_IPC_LOG_ERROR("invalid fd array size"); - } - else - { - const size_t n = kFdsLength / sizeof(int); - RIALTO_IPC_LOG_DEBUG("received %zu fds", n); - - fds.reserve(std::min(limit, n)); - - const int *kFds = reinterpret_cast(CMSG_DATA(cmsg)); - for (size_t i = 0; i < n; i++) - { - RIALTO_IPC_LOG_DEBUG("received fd %d", kFds[i]); - - if (fds.size() >= limit) - { - RIALTO_IPC_LOG_ERROR( - "received to many file descriptors, exceeding max per message, closing left overs"); - } - else - { - firebolt::rialto::ipc::FileDescriptor fileDescriptor(kFds[i]); - if (!fileDescriptor.isValid()) - { - RIALTO_IPC_LOG_ERROR("received invalid fd (couldn't dup)"); - } - else - { - fds.emplace_back(std::move(fileDescriptor)); - } - } - - if (close(kFds[i]) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close received fd"); - } - } - } - } - - return fds; -} - -// ----------------------------------------------------------------------------- -/*! - \static - \internal - - Places the received file descriptors into the protobuf message. - - It works by iterating over the fields in the message, finding ones that are - marked as 'field_is_fd' and then replacing the received integer value with - an actual file descriptor. - - */ -bool ChannelImpl::addReplyFileDescriptors(google::protobuf::Message *reply, - std::vector *fds) -{ - auto fdIterator = fds->begin(); - - const google::protobuf::Descriptor *kDescriptor = reply->GetDescriptor(); - const google::protobuf::Reflection *kReflection = nullptr; - - const int n = kDescriptor->field_count(); - for (int i = 0; i < n; i++) - { - auto fieldDescriptor = kDescriptor->field(i); - if (fieldDescriptor->options().HasExtension(::firebolt::rialto::ipc::field_is_fd) && - fieldDescriptor->options().GetExtension(::firebolt::rialto::ipc::field_is_fd)) - { - if (fieldDescriptor->type() != google::protobuf::FieldDescriptor::TYPE_INT32) - { - RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but not an int32 type"); - return false; - } - - if (!kReflection) - { - kReflection = reply->GetReflection(); - } - - if (kReflection->HasField(*reply, fieldDescriptor)) - { - if (fdIterator == fds->end()) - { - RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but none or too few were supplied"); - return false; - } - - kReflection->SetInt32(reply, fieldDescriptor, fdIterator->fd()); - ++fdIterator; - } - } - } - - if (fdIterator != fds->end()) - { - RIALTO_IPC_LOG_ERROR("received too many file descriptors in the message"); - return false; - } - - // we now need to release all the fds stored in the vector, otherwise they - // will be closed when the vector is destroyed. From now onwards it is the - // caller's responsibility to close the fds in the returned protobuf message - // object - for (firebolt::rialto::ipc::FileDescriptor &fd : *fds) - { - fd.release(); - } - - return true; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - \static - - - */ -void ChannelImpl::complete(MethodCall *call) -{ - if (call->closure) - { - call->closure->Run(); - call->closure = nullptr; - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - \static - - - */ -void ChannelImpl::completeWithError(MethodCall *call, std::string reason) -{ - RIALTO_IPC_LOG_DEBUG("completing method call with error '%s'", reason.c_str()); - - if (call->controller) - { - call->controller->setMethodCallFailed(std::move(reason)); - call->controller = nullptr; - } - - if (call->closure) - { - call->closure->Run(); - call->closure = nullptr; - } -} - -// ----------------------------------------------------------------------------- -/*! - \static - - Iterates through the message and finds any file descriptor type fields, if - found it adds the fds to the returned vector. - - */ -std::vector ChannelImpl::getMessageFds(const google::protobuf::Message &message) -{ - std::vector fds; - - auto descriptor = message.GetDescriptor(); - const int n = descriptor->field_count(); - for (int i = 0; i < n; i++) - { - auto fieldDescriptor = descriptor->field(i); - if (fieldDescriptor->options().HasExtension(::firebolt::rialto::ipc::field_is_fd) && - fieldDescriptor->options().GetExtension(::firebolt::rialto::ipc::field_is_fd)) - { - if (fieldDescriptor->type() != google::protobuf::FieldDescriptor::TYPE_INT32) - { - RIALTO_IPC_LOG_ERROR("field '%s' is marked as containing an fd but not an int32 type", - fieldDescriptor->full_name().c_str()); - } - else - { - auto reflection = message.GetReflection(); - int fileDescriptor = reflection->GetInt32(message, fieldDescriptor); - fds.emplace_back(fileDescriptor); - } - } - } - - return fds; -} - -// ----------------------------------------------------------------------------- -/*! - \overload - - \quote - Call the given method of the remote service. The signature of this - procedure looks the same as Service::CallMethod(), but the requirements - are less strict in one important way: the request and response objects - need not be of any specific class as long as their descriptors are - method->input_type() and method->output_type(). - - */ -void ChannelImpl::CallMethod(const google::protobuf::MethodDescriptor *method, // NOLINT(build/function_format) - google::protobuf::RpcController *controller, const google::protobuf::Message *request, - google::protobuf::Message *response, google::protobuf::Closure *done) -{ - MethodCall methodCall{std::chrono::steady_clock::now() + m_timeout, - dynamic_cast(controller), response, done}; - - // - const uint64_t kSerialId = m_serialCounter++; - - // create the transport request - transport::MessageToServer message; - transport::MethodCall *call = message.mutable_call(); - call->set_serial_id(kSerialId); - call->set_service_name(method->service()->full_name()); - call->set_method_name(method->name()); - - // copy in the actual message data - std::string reqString = request->SerializeAsString(); - call->set_request_message(std::move(reqString)); - - const size_t kRequiredDataLen = message.ByteSizeLong(); - if (kRequiredDataLen > kMaxMessageSize) - { - RIALTO_IPC_LOG_ERROR("method call to big to send (%zu, max %zu", kRequiredDataLen, kMaxMessageSize); - completeWithError(&methodCall, "Method call to big"); - return; - } - - // extract the fds from the message - const std::vector kFds = getMessageFds(*request); - const size_t kRequiredCtrlLen = kFds.empty() ? 0 : CMSG_SPACE(sizeof(int) * kFds.size()); - - // build the socket message to send - auto msgBuf = - m_sendBufPool.allocateShared(sizeof(msghdr) + sizeof(iovec) + kRequiredCtrlLen + kRequiredDataLen); - - auto *header = reinterpret_cast(msgBuf.get()); - bzero(header, sizeof(msghdr)); - - auto *ctrl = reinterpret_cast(msgBuf.get() + sizeof(msghdr)); - header->msg_control = ctrl; - header->msg_controllen = kRequiredCtrlLen; - - auto *iov = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen); - header->msg_iov = iov; - header->msg_iovlen = 1; - - auto *data = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen + sizeof(iovec)); - iov->iov_base = data; - iov->iov_len = kRequiredDataLen; - - // copy in the data - message.SerializeWithCachedSizesToArray(data); - - // next check if the request is sending any fd's - if (!kFds.empty()) - { - struct cmsghdr *cmsg = CMSG_FIRSTHDR(header); - if (!cmsg) - { - RIALTO_IPC_LOG_ERROR("odd, failed to get the first cmsg header"); - completeWithError(&methodCall, "Internal error"); - return; - } - - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int) * kFds.size()); - memcpy(CMSG_DATA(cmsg), kFds.data(), sizeof(int) * kFds.size()); - header->msg_controllen = cmsg->cmsg_len; - } - - // check if the method is expecting a reply - const bool kNoReplyExpected = method->options().HasExtension(::firebolt::rialto::ipc::no_reply) && - method->options().GetExtension(::firebolt::rialto::ipc::no_reply); - - // finally, send the message - std::unique_lock locker(m_lock); - - if (m_sock < 0) - { - locker.unlock(); - completeWithError(&methodCall, "Not connected"); - } - else if (sendmsg(m_sock, header, MSG_NOSIGNAL) != static_cast(kRequiredDataLen)) - { - locker.unlock(); - completeWithError(&methodCall, "Failed to send message"); - } - else - { - RIALTO_IPC_LOG_DEBUG("call{ serial %" PRIu64 " } - %s.%s { %s }", kSerialId, call->service_name().c_str(), - call->method_name().c_str(), request->ShortDebugString().c_str()); - - if (kNoReplyExpected) - { - // no reply from server is expected, however if the caller supplied - // a closure (it shouldn't) we should still call it now to indicate - // the method call has been made - if (done) - done->Run(); - } - else - { - // add the message to the queue so we pick-up the reply - m_methodCalls.emplace(kSerialId, methodCall); - - // update the single timeout timer - updateTimeoutTimer(); - } - } -} - -int ChannelImpl::subscribeImpl(const std::string &kEventName, const google::protobuf::Descriptor *descriptor, - EventHandler &&handler) -{ - std::lock_guard locker(m_eventsLock); - - const int kTag = m_eventTagCounter++; - m_eventHandlers.emplace(kEventName, Event{kTag, descriptor, std::move(handler)}); - - return kTag; -} -}; // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/client/source/IpcChannelImpl.h b/middleware/rialto-client/ipc/client/source/IpcChannelImpl.h deleted file mode 100644 index a19cfdce9..000000000 --- a/middleware/rialto-client/ipc/client/source/IpcChannelImpl.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_IPC_CHANNEL_IMPL_H_ -#define FIREBOLT_RIALTO_IPC_IPC_CHANNEL_IMPL_H_ - -#include "FileDescriptor.h" -#include "IIpcChannel.h" -#include "IpcClientControllerImpl.h" -#include "SimpleBufferPool.h" - -#include "rialtoipc-transport.pb.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace firebolt::rialto::ipc -{ -class ChannelFactory : public IChannelFactory -{ -public: - ChannelFactory() = default; - ~ChannelFactory() override = default; - - std::shared_ptr createChannel(int sockFd) override; - std::shared_ptr createChannel(const std::string &socketPath) override; -}; - -class ChannelImpl final : public IChannel -{ -public: - explicit ChannelImpl(int sockFd); - explicit ChannelImpl(const std::string &socketPath); - ~ChannelImpl() final; - - void disconnect() override; - bool isConnected() const override; - - int fd() const override; - bool wait(int timeoutMSecs) override; - bool process() override; - bool unsubscribe(int eventTag) override; - - void CallMethod(const google::protobuf::MethodDescriptor *method, google::protobuf::RpcController *controller, - const google::protobuf::Message *request, google::protobuf::Message *response, - google::protobuf::Closure *done) override; - - using EventHandler = std::function &msg)>; - - int subscribeImpl(const std::string &name, const google::protobuf::Descriptor *descriptor, - EventHandler &&handler) override; - -private: - void disconnectNoLock(); - - bool processSocketEvent(); - void processTimeoutEvent(); - void processWakeEvent(); - - void processServerMessage(const uint8_t *data, size_t len, std::vector *fds); - void processReplyFromServer(const ::firebolt::rialto::ipc::transport::MethodCallReply &reply, - std::vector *fds); - void processErrorFromServer(const ::firebolt::rialto::ipc::transport::MethodCallError &error); - void processEventFromServer(const ::firebolt::rialto::ipc::transport::EventFromServer &event, - std::vector *fds); - - bool createConnectedSocket(const std::string &socketPath); - bool attachSocket(int sockFd); - bool initChannel(); - void termChannel(); - bool isConnectedInternal() const; // to avoid calling virtual method in constructor - - static std::vector readMessageFds(const struct msghdr *msg, size_t limit); - static std::vector getMessageFds(const google::protobuf::Message &message); - - static bool addReplyFileDescriptors(google::protobuf::Message *reply, std::vector *fds); - - struct MethodCall - { - std::chrono::steady_clock::time_point timeoutDeadline; - ClientControllerImpl *controller = nullptr; - google::protobuf::Message *response = nullptr; - google::protobuf::Closure *closure = nullptr; - }; - - void updateTimeoutTimer(); - - static void complete(MethodCall *call); - static void completeWithError(MethodCall *call, std::string reason); - -private: - int m_sock; - int m_epollFd; - int m_timerFd; - int m_eventFd; - - SimpleBufferPool m_sendBufPool; - - mutable std::mutex m_lock; - std::atomic m_serialCounter; - - const std::chrono::milliseconds m_timeout; - - std::map m_methodCalls; - - std::mutex m_eventsLock; - - int m_eventTagCounter; - - struct Event - { - int id; - const google::protobuf::Descriptor *descriptor; - EventHandler handler; - }; - - std::multimap m_eventHandlers; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_IPC_CHANNEL_IMPL_H_ diff --git a/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.cpp b/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.cpp deleted file mode 100644 index 91d3b27d9..000000000 --- a/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "IpcClientControllerImpl.h" -#include "IpcControllerFactory.h" -#include "IpcLogging.h" -#include -#include - -namespace firebolt::rialto::ipc -{ -std::shared_ptr IControllerFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Failed to create the controller factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr ControllerFactory::create() -{ - return std::make_shared(); -} - -// ----------------------------------------------------------------------------- -/*! - \overload - - \quote - Resets the RpcController to its initial state so that it may be reused in - a new call. Must not be called while an RPC is in progress. - - - */ -void ClientControllerImpl::Reset() // NOLINT(build/function_format) -{ - std::lock_guard locker(m_lock); - m_failed = false; - m_reason.clear(); -} - -// ----------------------------------------------------------------------------- -/*! - \overload - - \quote - After a call has finished, returns true if the call failed. The possible - reasons for failure depend on the RPC implementation. Failed() must not - be called before a call has finished. If Failed() returns true, the - contents of the response message are undefined. - - */ -bool ClientControllerImpl::Failed() const // NOLINT(build/function_format) -{ - std::lock_guard locker(m_lock); - return m_failed; -} - -// ----------------------------------------------------------------------------- -/*! - \overload - - \quote - If Failed() is true, returns a human-readable description of the error. - - */ -std::string ClientControllerImpl::ErrorText() const // NOLINT(build/function_format) -{ - std::lock_guard locker(m_lock); - return m_reason; -} - -// ----------------------------------------------------------------------------- -/*! - \overload - \warning Not implemented - - \quote - Advises the RPC system that the caller desires that the RPC call be - canceled. The RPC system may cancel it immediately, may wait awhile and - then cancel it, or may not even cancel the call at all. If the call is - canceled, the "done" callback will still be called and the RpcController - will indicate that the call failed at that time. - - */ -void ClientControllerImpl::StartCancel() // NOLINT(build/function_format) -{ - RIALTO_IPC_LOG_WARN("Cancel not implemented"); -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Called from RialtoIpcChannelImpl when a method call failed for any reason. - - */ -void ClientControllerImpl::setMethodCallFailed(std::string reason) -{ - std::lock_guard locker(m_lock); - m_failed = true; - m_reason = std::move(reason); -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Called from RialtoIpcChannelImpl when a method call failed for any reason. - - */ -void ClientControllerImpl::setMethodCallFailed(const char *format, va_list ap) -{ - char buf[512]; - vsnprintf(buf, sizeof(buf), format, ap); - - std::lock_guard locker(m_lock); - m_failed = true; - m_reason.assign(buf); -} - -} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.h b/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.h deleted file mode 100644 index 61ce8fcd3..000000000 --- a/middleware/rialto-client/ipc/client/source/IpcClientControllerImpl.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_IPC_CLIENT_CONTROLLER_IMPL_H_ -#define FIREBOLT_RIALTO_IPC_IPC_CLIENT_CONTROLLER_IMPL_H_ - -#include - -#include -#include -#include - -namespace firebolt::rialto::ipc -{ -class ClientControllerImpl final : public google::protobuf::RpcController -{ -public: - ClientControllerImpl() = default; - ~ClientControllerImpl() final = default; - - /** - * Client-side methods - * Calls can only be made from the client side. Calling these apis from server side - * is undefined and could cause crashes. - */ - - /** - * @brief Reset the RpcController. - * - * So that the RpcController can be reused for a new call, sets to the inital state. - */ - void Reset() override; - - /** - * @brief Checks id the previosu call has failed. - * - * The reason for the failure depends on the implementaion of the RPC. Failed should only - * be called after after the call has finished. If this call returns true, the response - * structure returned from the failed call is undefined. - * - * @retval true if previous call failed. - */ - bool Failed() const override; - - /** - * @brief Returns a description of the error if the previous call has failed. - * - * @retval error string. - */ - std::string ErrorText() const override; - - /** - * @brief Starts the cancellation of a RPC call - * - * RPC may cancel the call immediatly, wait and cancel or not cancel at all. If a call is cancelled - * failure will be set for the client and "done" will still be called. - */ - void StartCancel() override; - - /** - * Server-side methods - * Calls can only be made from the server side. Calling these apis from client side - * is undefined and could cause crashes. - */ - - /** - * @brief Causes failure to be returned to the client. - * - * Failed() shall return true. The failure reason can be fetched from the ErrorText(). - * To return machine-readable info on failure, use the method response structure rather than - * SetFailed(). - * - * @param[in] reason : The reason for the falure. - */ - void SetFailed(const std::string &reason) override { (void)reason; } - - /** - * @brief Check if the client had cancelled the RPC. - * - * If true, indicates that the client canceled the RPC, so the server may - * as well give up on replying to it. The server should still call the - * final "done" callback. - * - * @retval true of cancelled, false otherwise. - */ - bool IsCanceled() const override { return false; } - - /** - * @brief Request a notification when RPC is cancelled. - * - * The callback will always be called exactly once. If the RPC completes without - * being canceled, the callback will be called after completion. If the RPC - * has already been canceled when NotifyOnCancel() is called, the callback - * will be called immediately. - * - * @param[in] callback : Callback method on cancelled. - */ - void NotifyOnCancel(google::protobuf::Closure *callback) override { (void)callback; } - -private: - friend class ChannelImpl; - - void setMethodCallFailed(std::string reason); - void setMethodCallFailed(const char *format, va_list ap) __attribute__((format(printf, 2, 0))); - -private: - mutable std::mutex m_lock; - bool m_failed = false; - std::string m_reason; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_IPC_CLIENT_CONTROLLER_IMPL_H_ diff --git a/middleware/rialto-client/ipc/client/source/IpcControllerFactory.h b/middleware/rialto-client/ipc/client/source/IpcControllerFactory.h deleted file mode 100644 index 1555fc458..000000000 --- a/middleware/rialto-client/ipc/client/source/IpcControllerFactory.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_IPC_CONTROLLER_FACTORY_H_ -#define FIREBOLT_RIALTO_IPC_IPC_CONTROLLER_FACTORY_H_ - -#include - -#include "IIpcControllerFactory.h" -#include - -namespace firebolt::rialto::ipc -{ -class ControllerFactory : public IControllerFactory -{ -public: - ControllerFactory() = default; - ~ControllerFactory() = default; - - std::shared_ptr create() override; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_IPC_CONTROLLER_FACTORY_H_ diff --git a/middleware/rialto-client/ipc/common/CMakeLists.txt b/middleware/rialto-client/ipc/common/CMakeLists.txt deleted file mode 100644 index c2adf6395..000000000 --- a/middleware/rialto-client/ipc/common/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 Sky UK -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Find includes in corresponding build directories -set( CMAKE_INCLUDE_CURRENT_DIR ON ) - - -add_library( - RialtoIpcCommon - STATIC - - source/FileDescriptor.cpp - source/SimpleBufferPool.cpp - source/NamedSocket.cpp - - ) - -target_include_directories( - RialtoIpcCommon - - PUBLIC - include - $ - - PRIVATE - source - - ) - - -set_property( - TARGET RialtoIpcCommon - PROPERTY POSITION_INDEPENDENT_CODE ON - - ) - -target_link_libraries( - RialtoIpcCommon - - PRIVATE - RialtoProtobuf - - ) diff --git a/middleware/rialto-client/ipc/common/include/INamedSocket.h b/middleware/rialto-client/ipc/common/include/INamedSocket.h deleted file mode 100644 index 170a50b26..000000000 --- a/middleware/rialto-client/ipc/common/include/INamedSocket.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_I_NAMED_SOCKET_H_ -#define FIREBOLT_RIALTO_IPC_I_NAMED_SOCKET_H_ - -#include -#include - -namespace firebolt::rialto::ipc -{ -class INamedSocket; - -class INamedSocketFactory -{ -public: - virtual ~INamedSocketFactory() = default; - - static INamedSocketFactory &getFactory(); - virtual std::unique_ptr createNamedSocket() const = 0; - virtual std::unique_ptr createNamedSocket(const std::string &socketPath) const = 0; -}; - -class INamedSocket -{ -public: - virtual ~INamedSocket() = default; - virtual int getFd() const = 0; - virtual bool setSocketPermissions(unsigned int socketPermissions) const = 0; - virtual bool setSocketOwnership(const std::string &socketOwner, const std::string &socketGroup) const = 0; - virtual bool blockNewConnections() const = 0; - virtual bool bind(const std::string &socketPath) = 0; -}; -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_I_NAMED_SOCKET_H_ diff --git a/middleware/rialto-client/ipc/common/proto/rialtoipc-transport.proto b/middleware/rialto-client/ipc/common/proto/rialtoipc-transport.proto deleted file mode 120000 index 6225e1f25..000000000 --- a/middleware/rialto-client/ipc/common/proto/rialtoipc-transport.proto +++ /dev/null @@ -1 +0,0 @@ -../../../proto/rialtoipc-transport.proto \ No newline at end of file diff --git a/middleware/rialto-client/ipc/common/proto/rialtoipc.proto b/middleware/rialto-client/ipc/common/proto/rialtoipc.proto deleted file mode 120000 index 274045422..000000000 --- a/middleware/rialto-client/ipc/common/proto/rialtoipc.proto +++ /dev/null @@ -1 +0,0 @@ -../../../proto/rialtoipc.proto \ No newline at end of file diff --git a/middleware/rialto-client/ipc/common/source/FileDescriptor.cpp b/middleware/rialto-client/ipc/common/source/FileDescriptor.cpp deleted file mode 100644 index 88cd67507..000000000 --- a/middleware/rialto-client/ipc/common/source/FileDescriptor.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "FileDescriptor.h" -#include "IpcLogging.h" - -#include -#include -#include - -namespace firebolt::rialto::ipc -{ -FileDescriptor::FileDescriptor() : m_fd(-1) {} - -FileDescriptor::FileDescriptor(int fd) : m_fd(-1) -{ - if (fd >= 0) - { - m_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); - if (m_fd < 0) - RIALTO_IPC_LOG_SYS_WARN(errno, "failed to dup supplied fd"); - } -} - -FileDescriptor::FileDescriptor(const FileDescriptor &other) : m_fd(-1) -{ - if (other.m_fd >= 0) - { - m_fd = fcntl(other.m_fd, F_DUPFD_CLOEXEC, 3); - if (m_fd < 0) - RIALTO_IPC_LOG_SYS_WARN(errno, "failed to dup supplied fd"); - } -} - -FileDescriptor &FileDescriptor::operator=(FileDescriptor &&other) noexcept -{ - if ((m_fd >= 0) && (::close(m_fd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close file descriptor"); - - m_fd = other.m_fd; - other.m_fd = -1; - - return *this; -} - -FileDescriptor &FileDescriptor::operator=(const FileDescriptor &other) -{ - if (this == &other) - return *this; - - if ((m_fd >= 0) && (::close(m_fd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close file descriptor"); - - m_fd = -1; - - if (other.m_fd >= 0) - { - m_fd = fcntl(other.m_fd, F_DUPFD_CLOEXEC, 3); - if (m_fd < 0) - RIALTO_IPC_LOG_SYS_WARN(errno, "failed to dup supplied fd"); - } - - return *this; -} - -FileDescriptor::~FileDescriptor() -{ - reset(); -} - -bool FileDescriptor::isValid() const -{ - return (m_fd >= 0); -} - -int FileDescriptor::fd() const -{ - return m_fd; -} - -void FileDescriptor::reset(int fd) -{ - if ((m_fd >= 0) && (::close(m_fd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close file descriptor"); - - if (fd < 0) - { - m_fd = -1; - } - else - { - m_fd = fcntl(fd, F_DUPFD_CLOEXEC, 3); - if (m_fd < 0) - RIALTO_IPC_LOG_SYS_WARN(errno, "failed to dup supplied fd"); - } -} - -void FileDescriptor::clear() -{ - reset(); -} - -int FileDescriptor::release() -{ - int descriptor = m_fd; - m_fd = -1; - return descriptor; -} - -} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/common/source/FileDescriptor.h b/middleware/rialto-client/ipc/common/source/FileDescriptor.h deleted file mode 100644 index 2d01f81d4..000000000 --- a/middleware/rialto-client/ipc/common/source/FileDescriptor.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_FILE_DESCRIPTOR_H_ -#define FIREBOLT_RIALTO_IPC_FILE_DESCRIPTOR_H_ - -// ----------------------------------------------------------------------------- -/*! - \class FileDescriptor - \brief Light wrapper around a file descriptor so it can be used safely. - - Why do we need this? Because we want to safely pass a file descriptor - around. - - Why not just use an integer? Because although it's obviously fine to pass - an integer around there is no guarantee that the descriptor is still valid - when it's used. This class uses \c dup(2) to ensure that if the object was - created with a valid file descriptor in the first place then it and all copy - constructed objects will have a valid file descriptor. - -*/ - -namespace firebolt::rialto::ipc -{ -class FileDescriptor -{ -public: - FileDescriptor(); - explicit FileDescriptor(int fd); - FileDescriptor(const FileDescriptor &other); - FileDescriptor &operator=(FileDescriptor &&other) noexcept; - FileDescriptor &operator=(const FileDescriptor &other); - ~FileDescriptor(); - -public: - bool isValid() const; - int fd() const; - - void reset(int fd = -1); - void clear(); - - int release(); - -private: - int m_fd; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_FILE_DESCRIPTOR_H_ diff --git a/middleware/rialto-client/ipc/common/source/IpcLogging.h b/middleware/rialto-client/ipc/common/source/IpcLogging.h deleted file mode 100644 index 90c1705a7..000000000 --- a/middleware/rialto-client/ipc/common/source/IpcLogging.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef IPC_LOGGING_H_ -#define IPC_LOGGING_H_ - -#include "RialtoLogging.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define RIALTO_IPC_LOG_FATAL(fmt, args...) RIALTO_LOG_FATAL(RIALTO_COMPONENT_IPC, fmt, ##args) -#define RIALTO_IPC_LOG_SYS_FATAL(err, fmt, args...) RIALTO_LOG_SYS_FATAL(RIALTO_COMPONENT_IPC, err, fmt, ##args) -#define RIALTO_IPC_LOG_ERROR(fmt, args...) RIALTO_LOG_ERROR(RIALTO_COMPONENT_IPC, fmt, ##args) -#define RIALTO_IPC_LOG_SYS_ERROR(err, fmt, args...) RIALTO_LOG_SYS_ERROR(RIALTO_COMPONENT_IPC, err, fmt, ##args) -#define RIALTO_IPC_LOG_WARN(fmt, args...) RIALTO_LOG_WARN(RIALTO_COMPONENT_IPC, fmt, ##args) -#define RIALTO_IPC_LOG_SYS_WARN(err, fmt, args...) RIALTO_LOG_SYS_WARN(RIALTO_COMPONENT_IPC, err, fmt, ##args) -#define RIALTO_IPC_LOG_MIL(fmt, args...) RIALTO_LOG_MIL(RIALTO_COMPONENT_IPC, fmt, ##args) -#define RIALTO_IPC_LOG_INFO(fmt, args...) RIALTO_LOG_INFO(RIALTO_COMPONENT_IPC, fmt, ##args) -#define RIALTO_IPC_LOG_DEBUG(fmt, args...) RIALTO_LOG_DEBUG(RIALTO_COMPONENT_IPC, fmt, ##args) - -#ifdef __cplusplus -} -#endif - -#endif // IPC_LOGGING_H_ diff --git a/middleware/rialto-client/ipc/common/source/NamedSocket.cpp b/middleware/rialto-client/ipc/common/source/NamedSocket.cpp deleted file mode 100644 index f3565aa5b..000000000 --- a/middleware/rialto-client/ipc/common/source/NamedSocket.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "NamedSocket.h" -#include "IpcLogging.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace -{ -constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner -constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group -} // namespace - -namespace firebolt::rialto::ipc -{ -INamedSocketFactory &INamedSocketFactory::getFactory() -{ - static NamedSocketFactory factory; - return factory; -} - -std::unique_ptr NamedSocketFactory::createNamedSocket() const -try -{ - return std::make_unique(); -} -catch (const std::runtime_error &error) -{ - RIALTO_IPC_LOG_ERROR("Failed to create named socket: %s", error.what()); - return nullptr; -} - -std::unique_ptr NamedSocketFactory::createNamedSocket(const std::string &socketPath) const -try -{ - return std::make_unique(socketPath); -} -catch (const std::runtime_error &error) -{ - RIALTO_IPC_LOG_ERROR("Failed to create named socket: %s", error.what()); - return nullptr; -} - -NamedSocket::NamedSocket() -{ - RIALTO_IPC_LOG_MIL("Creating new socket without binding"); - - // Create the socket - m_sockFd = ::socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); - if (m_sockFd == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "socket error"); - throw std::runtime_error("socket error"); - } - - RIALTO_IPC_LOG_MIL("Socket created, fd: %d", m_sockFd); -} - -NamedSocket::NamedSocket(const std::string &socketPath) -{ - RIALTO_IPC_LOG_MIL("Creating named socket with name: %s", socketPath.c_str()); - m_sockPath = socketPath; - - // Create the socket - m_sockFd = ::socket(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0); - if (m_sockFd == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "socket error"); - throw std::runtime_error("socket error"); - } - - // get the socket lock - if (!getSocketLock()) - { - closeListeningSocket(); - throw std::runtime_error("lock error"); - } - - // bind to the given path - struct sockaddr_un addr = {0}; - memset(&addr, 0x00, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); - - if (::bind(m_sockFd, reinterpret_cast(&addr), sizeof(addr)) == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "bind error"); - - closeListeningSocket(); - throw std::runtime_error("bind error"); - } - - RIALTO_IPC_LOG_MIL("Named socket with name: %s created, fd: %d", m_sockPath.c_str(), m_sockFd); -} - -NamedSocket::~NamedSocket() -{ - RIALTO_IPC_LOG_MIL("Close named socket with name: %s, fd: %d", m_sockPath.c_str(), m_sockFd); - closeListeningSocket(); -} - -int NamedSocket::getFd() const -{ - return m_sockFd; -} - -bool NamedSocket::setSocketPermissions(unsigned int socketPermissions) const -{ - errno = 0; - if (chmod(m_sockPath.c_str(), socketPermissions) != 0) - { - RIALTO_IPC_LOG_SYS_WARN(errno, "Failed to change the permissions on the IPC socket"); - return false; - } - return true; -} - -bool NamedSocket::setSocketOwnership(const std::string &socketOwner, const std::string &socketGroup) const -{ - uid_t ownerId = getSocketOwnerId(socketOwner); - gid_t groupId = getSocketGroupId(socketGroup); - - if (ownerId != kNoOwnerChange || groupId != kNoGroupChange) - { - errno = 0; - if (chown(m_sockPath.c_str(), ownerId, groupId) != 0) - { - RIALTO_IPC_LOG_SYS_WARN(errno, "Failed to change the owner/group for the IPC socket"); - } - } - return true; -} - -bool NamedSocket::blockNewConnections() const -{ - if (m_sockPath.empty()) - { - RIALTO_IPC_LOG_DEBUG("No need to block new connections - socket not configured"); - return true; - } - RIALTO_IPC_LOG_INFO("Block new connections for: %s", m_sockPath.c_str()); - if (listen(m_sockFd, 0) == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "blockNewConnections: listen error"); - return false; - } - return true; -} - -bool NamedSocket::bind(const std::string &socketPath) -{ - if (!m_sockPath.empty()) - { - RIALTO_IPC_LOG_DEBUG("no need to bind again"); - return true; - } - RIALTO_IPC_LOG_MIL("Binding socket with fd: %d with name: %s", m_sockFd, socketPath.c_str()); - m_sockPath = socketPath; - - // get the socket lock - if (!getSocketLock()) - { - closeListeningSocket(); - return false; - } - - // bind to the given path - struct sockaddr_un addr = {0}; - memset(&addr, 0x00, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); - - if (::bind(m_sockFd, reinterpret_cast(&addr), sizeof(addr)) == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "bind error"); - - closeListeningSocket(); - return false; - } - - RIALTO_IPC_LOG_MIL("Named socket with fd: %d bound with path: %s", m_sockFd, m_sockPath.c_str()); - - return true; -} - -void NamedSocket::closeListeningSocket() -{ - if (!m_sockPath.empty() && (unlink(m_sockPath.c_str()) != 0) && (errno != ENOENT)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket @ '%s'", m_sockPath.c_str()); - if ((m_sockFd >= 0) && (close(m_sockFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close listening socket"); - - if (!m_lockPath.empty() && (unlink(m_lockPath.c_str()) != 0) && (errno != ENOENT)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket lock file @ '%s'", m_lockPath.c_str()); - if ((m_lockFd >= 0) && (close(m_lockFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close socket lock file"); - - m_sockFd = -1; - m_sockPath.clear(); - - m_lockFd = -1; - m_lockPath.clear(); -} - -bool NamedSocket::getSocketLock() -{ - std::string lockPath = m_sockPath + ".lock"; - int fd = open(lockPath.c_str(), O_CREAT | O_CLOEXEC, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); - if (fd < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to create / open lockfile @ '%s' (check permissions)", lockPath.c_str()); - return false; - } - - if (flock(fd, LOCK_EX | LOCK_NB) < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to lock lockfile @ '%s', maybe another server is running", - lockPath.c_str()); - close(fd); - return false; - } - - struct stat sbuf = {0}; - if (stat(m_sockPath.c_str(), &sbuf) < 0) - { - if (errno != ENOENT) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "did not manage to stat existing socket @ '%s'", m_sockPath.c_str()); - close(fd); - return false; - } - } - else if ((sbuf.st_mode & S_IWUSR) || (sbuf.st_mode & S_IWGRP)) - { - unlink(m_sockPath.c_str()); - } - - m_lockFd = fd; - m_lockPath = std::move(lockPath); - - return true; -} - -uid_t NamedSocket::getSocketOwnerId(const std::string &socketOwner) const -{ - uid_t ownerId = kNoOwnerChange; - const size_t kBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (!socketOwner.empty() && kBufferSize > 0) - { - errno = 0; - passwd passwordStruct{}; - passwd *passwordResult = nullptr; - char buffer[kBufferSize]; - int result = getpwnam_r(socketOwner.c_str(), &passwordStruct, buffer, kBufferSize, &passwordResult); - if (result == 0 && passwordResult) - { - ownerId = passwordResult->pw_uid; - } - else - { - RIALTO_IPC_LOG_SYS_WARN(errno, "Failed to determine ownerId for '%s'", socketOwner.c_str()); - } - } - return ownerId; -} - -gid_t NamedSocket::getSocketGroupId(const std::string &socketGroup) const -{ - gid_t groupId = kNoGroupChange; - const size_t kBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX); - if (!socketGroup.empty() && kBufferSize > 0) - { - errno = 0; - group groupStruct{}; - group *groupResult = nullptr; - char buffer[kBufferSize]; - int result = getgrnam_r(socketGroup.c_str(), &groupStruct, buffer, kBufferSize, &groupResult); - if (result == 0 && groupResult) - { - groupId = groupResult->gr_gid; - } - else - { - RIALTO_IPC_LOG_SYS_WARN(errno, "Failed to determine groupId for '%s'", socketGroup.c_str()); - } - } - return groupId; -} -} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/common/source/NamedSocket.h b/middleware/rialto-client/ipc/common/source/NamedSocket.h deleted file mode 100644 index 8ce2dca5a..000000000 --- a/middleware/rialto-client/ipc/common/source/NamedSocket.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_NAMED_SOCKET_H_ -#define FIREBOLT_RIALTO_IPC_NAMED_SOCKET_H_ - -#include "INamedSocket.h" -#include -#include - -namespace firebolt::rialto::ipc -{ -class NamedSocketFactory : public INamedSocketFactory -{ -public: - std::unique_ptr createNamedSocket() const override; - std::unique_ptr createNamedSocket(const std::string &socketPath) const override; -}; - -class NamedSocket : public INamedSocket -{ -public: - NamedSocket(); - explicit NamedSocket(const std::string &socketPath); - ~NamedSocket() override; - - int getFd() const override; - bool setSocketPermissions(unsigned int socketPermissions) const override; - bool setSocketOwnership(const std::string &socketOwner, const std::string &socketGroup) const override; - bool blockNewConnections() const override; - bool bind(const std::string &socketPath) override; - -private: - void closeListeningSocket(); - bool getSocketLock(); - uid_t getSocketOwnerId(const std::string &socketOwner) const; - gid_t getSocketGroupId(const std::string &socketGroup) const; - -private: - int m_sockFd{-1}; - int m_lockFd{-1}; - std::string m_sockPath{}; - std::string m_lockPath{}; -}; -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_NAMED_SOCKET_H_ diff --git a/middleware/rialto-client/ipc/common/source/SimpleBufferPool.cpp b/middleware/rialto-client/ipc/common/source/SimpleBufferPool.cpp deleted file mode 100644 index 9bca47168..000000000 --- a/middleware/rialto-client/ipc/common/source/SimpleBufferPool.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "IpcLogging.h" -#include "SimpleBufferPool.h" - -SimpleBufferPool::SimpleBufferPool() : m_staticBuf(nullptr), m_staticBufSize(0) -{ - // allocate a 64kb 'static' buffer and split it up into smaller individual buffers - m_staticBufSize = 64 * 1024; - m_staticBuf = new uint8_t[m_staticBufSize]; - - uint8_t *p = m_staticBuf; - for (int i = 0; i < 8; i++) - { - m_staticBufMetaData.emplace(p, BufInfo{256, true}); - p += 256; - } - for (int i = 0; i < 6; i++) - { - m_staticBufMetaData.emplace(p, BufInfo{1024, true}); - p += 1024; - } - for (int i = 0; i < 2; i++) - { - m_staticBufMetaData.emplace(p, BufInfo{4096, true}); - p += 4096; - } - for (int i = 0; i < 1; i++) - { - m_staticBufMetaData.emplace(p, BufInfo{16384, true}); - p += 16384; - } - for (int i = 0; i < 1; i++) - { - m_staticBufMetaData.emplace(p, BufInfo{32768, true}); - p += 32768; - } -} - -SimpleBufferPool::~SimpleBufferPool() -{ - delete[] m_staticBuf; -} - -void *SimpleBufferPool::allocateImpl(size_t bytes) -{ - // try and find a free static buffer that is big enough - { - std::lock_guard locker(m_staticBufLock); - - auto entry = std::find_if(m_staticBufMetaData.begin(), m_staticBufMetaData.end(), [&](const auto &metadata) - { return (metadata.second.free && (metadata.second.size >= bytes)); }); - if (m_staticBufMetaData.end() != entry) - { - entry->second.free = false; - return entry->first; - } - } - - // RIALTO_IPC_LOG_DEBUG("no static buffers for alloc of size %zu", bytes); - - // failed, so revert to dynamic allocation - return malloc(bytes); -} - -void SimpleBufferPool::deallocate(void *p) -{ - // if the pointer is not within our static area then assume it was dynamically - // allocated, in which case just free it - if ((p < m_staticBuf) || (p >= (m_staticBuf + m_staticBufSize))) - { - free(p); - return; - } - - std::lock_guard locker(m_staticBufLock); - - // else find the meta-data on the buffer pointer and mark as freed - auto it = m_staticBufMetaData.find(p); - if (it == m_staticBufMetaData.end()) - { - RIALTO_IPC_LOG_FATAL("trying to free an unknown buffer from the pool!"); - return; - } - - it->second.free = true; -} diff --git a/middleware/rialto-client/ipc/common/source/SimpleBufferPool.h b/middleware/rialto-client/ipc/common/source/SimpleBufferPool.h deleted file mode 100644 index ce7d55024..000000000 --- a/middleware/rialto-client/ipc/common/source/SimpleBufferPool.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SIMPLE_BUFFER_POOL_H_ -#define SIMPLE_BUFFER_POOL_H_ - -#include -#include -#include - -class SimpleBufferPool -{ -public: - SimpleBufferPool(); - ~SimpleBufferPool(); - SimpleBufferPool(const SimpleBufferPool &) = delete; - SimpleBufferPool(SimpleBufferPool &&) = delete; - SimpleBufferPool &operator=(const SimpleBufferPool &) = delete; - SimpleBufferPool &operator=(SimpleBufferPool &&) = delete; - - template T *allocate(size_t count) - { - return reinterpret_cast(allocateImpl(count * sizeof(T))); - } - - template std::shared_ptr allocateShared(size_t count) - { - return std::shared_ptr(allocate(count), [this](T *p) { deallocate(p); }); - } - - void deallocate(void *p); - -private: - void *allocateImpl(size_t bytes); - -private: - uint8_t *m_staticBuf; - size_t m_staticBufSize; - - struct BufInfo - { - size_t size; - bool free; - }; - - std::mutex m_staticBufLock; - std::map m_staticBufMetaData; -}; - -#endif // SIMPLE_BUFFER_POOL_H_ diff --git a/middleware/rialto-client/ipc/examples/CMakeLists.txt b/middleware/rialto-client/ipc/examples/CMakeLists.txt deleted file mode 100644 index dc6126a0e..000000000 --- a/middleware/rialto-client/ipc/examples/CMakeLists.txt +++ /dev/null @@ -1,113 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 Sky UK -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Set the example include paths for the protoc compiler -set( Protobuf_IMPORT_DIRS "${CMAKE_CURRENT_LIST_DIR}/../common/proto" ) - -# Run the protoc tool to generate the code -include( FindProtobuf ) -protobuf_generate_cpp( PROTO_SRCS PROTO_HEADERS example.proto ) - -# Get the directory where header was generated -list( GET PROTO_HEADERS 0 FIRST_PROTO_HEADER ) -get_filename_component( PROTO_HEADER_DIR ${FIRST_PROTO_HEADER} DIRECTORY ) - -# Find includes in corresponding build directories -set( CMAKE_INCLUDE_CURRENT_DIR ON ) - - -# Create the example client -add_executable( ExampleClient - - ExampleClient.cpp - ${PROTO_SRCS} - ${PROTO_HEADERS} - - ) - -target_include_directories( ExampleClient - - PRIVATE - ${Protobuf_INCLUDE_DIRS} - - ) - -target_link_libraries( ExampleClient - - PRIVATE - RialtoIpcCommon - RialtoLogging - RialtoIpcClient - protobuf::libprotobuf - - ) - - -# Create the example server -add_executable( ExampleServer - - ExampleServer.cpp - ${PROTO_SRCS} - ${PROTO_HEADERS} - - ) - -target_include_directories( ExampleServer - - PRIVATE - ${Protobuf_INCLUDE_DIRS} - - ) - -target_link_libraries( ExampleServer - - PRIVATE - RialtoIpcCommon - RialtoLogging - RialtoIpcServer - protobuf::libprotobuf - - ) - -# Create the example with socket pair -add_executable( ExampleSocketPair - - ExampleSocketPair.cpp - ${PROTO_SRCS} - ${PROTO_HEADERS} - - ) - -target_include_directories( ExampleSocketPair - - PRIVATE - ${Protobuf_INCLUDE_DIRS} - - ) - -target_link_libraries( ExampleSocketPair - - PRIVATE - RialtoIpcCommon - RialtoLogging - RialtoIpcClient - RialtoIpcServer - protobuf::libprotobuf - - ) diff --git a/middleware/rialto-client/ipc/examples/ExampleClient.cpp b/middleware/rialto-client/ipc/examples/ExampleClient.cpp deleted file mode 100644 index 003f61e24..000000000 --- a/middleware/rialto-client/ipc/examples/ExampleClient.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include "example.pb.h" - -#include - -#include - -// Callback invoked when the given event is received from the server -static void onSomeEvent(const std::shared_ptr<::example::SomeEvent> &event) -{ - printf("received event from server : %s\n", event->DebugString().c_str()); -} - -// Callback called when the RPC call completes with either a valid result or error -static void onComplete(bool *done) -{ - *done = true; -} - -// Example thread to show how you process the ipc channel event loop -static void runChannelEventLoop(const std::shared_ptr &channel) -{ - printf("Starting thread to process ipc channel events\n"); - - while (channel->wait(-1)) - { - if (!channel->process()) - break; - } - - printf("Stopping ipc process thread - channel disconnected\n"); -} - -int main(int argc, char *argv[]) -{ - // verify that the version of the library that we linked against is - // compatible with the version of the headers we compiled against. - GOOGLE_PROTOBUF_VERIFY_VERSION; - - // enable info level debugging - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, - RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_DEFAULT | RIALTO_DEBUG_LEVEL_INFO)); - - // connect to a socket created by the server - auto factory = firebolt::rialto::ipc::IChannelFactory::createFactory(); - auto channel = factory->createChannel("/tmp/rialto.example.socket"); - if (!channel) - { - fprintf(stderr, "Failed to connect to socket '/tmp/rialto.example.socket', is ExampleServer running?\n"); - return EXIT_FAILURE; - } - - // subscribe to an event from the server - channel->subscribe<::example::SomeEvent>(&onSomeEvent); - - // create the stub for rpc calls - ::example::ExampleService::Stub stub(channel.get()); - - // make a basic call and get the result polling on the channel - { - printf("Making RPC call ExampleService.exampleEcho()\n"); - - ::example::RequestEcho request; - ::example::ResponseEcho response; - - // populate the request message - request.set_text("the significant owl hoots in the night"); - - // create a controller which is used to check for any errors or cancel the rpc call - auto controllerFactory = IControllerFactory::createFactory(); - auto controller = controllerFactory->create(); - - // make the rpc call, onComplete will be called when it completes - bool done = false; - stub.exampleEcho(controller.get(), &request, &response, google::protobuf::NewCallback(onComplete, &done)); - - // process the event loop until the RPC call completes - while (channel->process() && !done) - { - channel->wait(-1); - } - - // check if the call failed with an error - if (controller->Failed()) - { - fprintf(stderr, "\texampleEcho IPC call failed with error '%s'\n", controller->ErrorText().c_str()); - } - else - { - printf("\treceived response '%s'\n", response.DebugString().c_str()); - } - } - - // example of spawning a thread to run the event loop - std::thread loop = std::thread(runChannelEventLoop, channel); - - // example making a call with no reply expected - { - printf("Making RPC call ExampleService.exampleWithNoReply()\n"); - - ::example::RequestWithNoReply request; - - // populate the request message - request.set_text("request with no reply expected"); - - // create a controller which is used to check for any errors or cancel the rpc call - auto controllerFactory = IControllerFactory::createFactory(); - auto controller = controllerFactory->create(); - - // make the rpc call, onComplete will be called when it completes - stub.exampleWithNoReply(controller.get(), &request, nullptr, nullptr); - - // check if the call failed - this will only happen if there was an issue sending the request (ie. channel disconnected) - if (controller->Failed()) - { - fprintf(stderr, "\texampleWithNoReply IPC call failed with error '%s'\n", controller->ErrorText().c_str()); - } - else - { - printf("\trequest send\n"); - } - } - - // example making a call sending and receiving file descriptors - { - printf("Making RPC call ExampleService.exampleWithFd()\n"); - - ::example::RequestWithFd request; - ::example::ResponseWithFd response; - - // populate the request message - request.set_fd(STDOUT_FILENO); - request.set_text("some test"); - - // create a controller which is used to check for any errors or cancel the rpc call - auto controllerFactory = IControllerFactory::createFactory(); - auto controller = controllerFactory->create(); - - // make the rpc call, onComplete will be called when it completes - bool done = false; - stub.exampleWithFd(controller.get(), &request, &response, google::protobuf::NewCallback(onComplete, &done)); - - // the complete callback will now be called on the runChannelEventLoop thread, so we just poll on done - // being set to true (this is not truely thread safe but provides a simple example) - while (!done) - { - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - } - - // check if the call failed with an error - if (controller->Failed()) - { - fprintf(stderr, "\texampleWithFd IPC call failed with error '%s'\n", controller->ErrorText().c_str()); - } - else - { - printf("\treceived response '%s'\n", response.DebugString().c_str()); - - // it is the callers responsibility to close the received file descriptor - if (close(response.fd()) != 0) - fprintf(stderr, "\tfailed to close the fd received from the server\n"); - } - } - - // disconnect from the server - channel->disconnect(); - - // this should terminate the processing thread - loop.join(); - - return EXIT_SUCCESS; -} diff --git a/middleware/rialto-client/ipc/examples/ExampleServer.cpp b/middleware/rialto-client/ipc/examples/ExampleServer.cpp deleted file mode 100644 index 839023daa..000000000 --- a/middleware/rialto-client/ipc/examples/ExampleServer.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "example.pb.h" - -#include - -class MyExampleServiceServer : public ::example::ExampleService -{ -public: - void exampleEcho(google::protobuf::RpcController *controller, const ::example::RequestEcho *request, - ::example::ResponseEcho *response, google::protobuf::Closure *done) override - { - // convert received string to upper case and send back - std::string text = request->text(); - std::transform(text.begin(), text.end(), text.begin(), ::toupper); - response->set_text(text); - - printf("ExampleService::exampleEcho({%s}) -> {%s}\n", request->DebugString().c_str(), - response->DebugString().c_str()); - - // if you wanted to report an error you'd do this - // controller->SetFailed("Failed for some reason ..."); - - // complete - done->Run(); - } - - void exampleWithFd(google::protobuf::RpcController *controller, const ::example::RequestWithFd *request, - ::example::ResponseWithFd *response, google::protobuf::Closure *done) override - { - // expecting the request to contain an fd to stdout of the client, so just write a message to the client - int fd = request->fd(); - if (dprintf(fd, "hello from the server\n") < 0) - perror("dprintf failed\n"); - - // reply with our own stdout fd - response->set_fd(STDOUT_FILENO); - - printf("ExampleService::exampleWithFd({%s}) -> {%s}\n", request->DebugString().c_str(), - response->DebugString().c_str()); - - // complete - done->Run(); - } - - void exampleWithNoReply(google::protobuf::RpcController *controller, const ::example::RequestWithNoReply *request, - ::example::EmptyResponse *response, google::protobuf::Closure *done) override - { - fprintf(stderr, "ExampleService::exampleWithNoReply({%s})\n", request->DebugString().c_str()); - - // for 'no reply' calls both the response object and done closure are null - } -}; - -// Example callback for when a client connects -static void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) -{ - printf("Client connected, pid:%d, uid:%d gid:%d\n", client->getClientPid(), client->getClientUserId(), - client->getClientGroupId()); - - // export the example server to the client - client->exportService(std::make_shared()); - - // example of sending an async event to the client - auto someEvent = std::make_shared<::example::SomeEvent>(); - someEvent->set_id(1234); - someEvent->set_text("some event"); - client->sendEvent(someEvent); -} - -// Example callback for a client disconnects -static void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) -{ - printf("Client disconnected, pid:%d, uid:%d gid:%d\n", client->getClientPid(), client->getClientUserId(), - client->getClientGroupId()); -} - -int main(int argc, char *argv[]) -{ - // verify that the version of the library that we linked against is - // compatible with the version of the headers we compiled against. - GOOGLE_PROTOBUF_VERIFY_VERSION; - - // enable info level debugging - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, - RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_DEFAULT | RIALTO_DEBUG_LEVEL_INFO)); - - auto factory = ::firebolt::rialto::ipc::IServerFactory::createFactory(); - auto server = factory->create(); - - // add a listening socket for clients to connect to - server->addSocket("/tmp/rialto.example.socket", &clientConnected, &clientDisconnected); - - // loop processing all event (alternatively you can call server->fd() to get a file descriptor to add to your - // own poll loop and then when woken call server->process()) - while (server->process()) - { - server->wait(-1); - } - - return EXIT_SUCCESS; -} diff --git a/middleware/rialto-client/ipc/examples/ExampleSocketPair.cpp b/middleware/rialto-client/ipc/examples/ExampleSocketPair.cpp deleted file mode 100644 index a210f4ccc..000000000 --- a/middleware/rialto-client/ipc/examples/ExampleSocketPair.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include - -#include "example.pb.h" - -#include -#include -#include - -class MyExampleService : public ::example::ExampleService -{ -public: - void exampleEcho(google::protobuf::RpcController *controller, const ::example::RequestEcho *request, - ::example::ResponseEcho *response, google::protobuf::Closure *done) override - { - // convert received string to upper case and send back - std::string text = request->text(); - std::transform(text.begin(), text.end(), text.begin(), ::toupper); - response->set_text(text); - - printf("[server] ExampleService::exampleEcho({%s}) -> {%s}\n", request->DebugString().c_str(), - response->DebugString().c_str()); - - // if you wanted to report an error you'd do this - // controller->SetFailed("Failed for some reason ..."); - - // complete - done->Run(); - } -}; - -// Callback called when the RPC call completes with either a valid result or error -static void onComplete(bool *done) -{ - *done = true; -} - -// Simple 'main' for the spawned example -static int childProcessMain(int sock) -{ - // create a channel to a socket created by the server - auto factory = firebolt::rialto::ipc::IChannelFactory::createFactory(); - auto channel = factory->createChannel(sock); - if (!channel) - { - fprintf(stderr, "[child] Failed to connect to socket fd '%d'\n", sock); - return EXIT_FAILURE; - } - - // create the stub for rpc calls - ::example::ExampleService::Stub stub(channel.get()); - - // make a basic call and get the result polling on the channel - { - printf("[child] Making IPC call ExampleService.exampleEcho()\n"); - - ::example::RequestEcho request; - ::example::ResponseEcho response; - - // populate the request message - request.set_text("the significant owl hoots in the night"); - - // create a controller which is used to check for any errors or cancel the rpc call - auto controllerFactory = IControllerFactory::createFactory(); - auto controller = controllerFactory->create(); - - // make the rpc call, onComplete will be called when it completes - bool done = false; - stub.exampleEcho(controller.get(), &request, &response, google::protobuf::NewCallback(onComplete, &done)); - - // process the event loop until the RPC call completes - while (channel->process() && !done) - { - channel->wait(-1); - } - - // check if the call failed with an error - if (controller->Failed()) - { - fprintf(stderr, "[child] \texampleEcho IPC call failed with error '%s'\n", controller->ErrorText().c_str()); - } - else - { - printf("[child] \treceived response '%s'\n", response.DebugString().c_str()); - } - } -} - -// Example of spawning a client and giving it the socket to talk back the server on -static pid_t spawnClient(int sock) -{ - // fork and exec the process - pid_t pid = fork(); - if (pid < 0) - { - fprintf(stderr, "fork failed - %s\n", strerror(errno)); - return -1; - } - - if (pid == 0) - { - // within spawned process - int ret = childProcessMain(sock); - _exit(ret); - } - else - { - // still in parent, close the socket - close(sock); - } - - return pid; -} - -// Example callback for a client disconnects -static void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::Client> &client) -{ - printf("Client disconnected, pid:%d, uid:%d gid:%d\n", client->getClientPid(), client->getClientUserId(), - client->getClientGroupId()); -} - -int main(int argc, char *argv[]) -{ - // verify that the version of the library that we linked against is - // compatible with the version of the headers we compiled against. - GOOGLE_PROTOBUF_VERIFY_VERSION; - - // enable info level debugging - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, - RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_DEFAULT | RIALTO_DEBUG_LEVEL_INFO)); - - auto factory = ::firebolt::rialto::ipc::IServerFactory::createFactory(); - auto server = factory->create(); - - // create a socket pair, one for the server and one for the spawned client - int socks[2] = {-1, -1}; - if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, socks) < 0) - { - fprintf(stderr, "socketpair failed - %s\n", strerror(errno)); - return EXIT_FAILURE; - } - - // give one socket to the server - auto client = server->addClient(socks[0], &clientDisconnected); - if (!client) - { - return EXIT_FAILURE; - } - - // export the example service to the client - client->exportService(std::make_shared()); - - // spawn off a client process, giving it the socket fd - pid_t childPid = spawnClient(socks[1]); - if (childPid <= 0) - { - return EXIT_FAILURE; - } - - // loop processing all event (alternatively you can call server->fd() to get a file descriptor to add to your - // own poll loop and then when woken call server->process()) - while (server->process() && client->isConnected()) - { - server->wait(-1); - } - - // ensure we reap the child process - int status; - if (waitpid(childPid, &status, 0) < 0) - { - fprintf(stderr, "waitpid failed - %s\n", strerror(errno)); - } - - return EXIT_SUCCESS; -} diff --git a/middleware/rialto-client/ipc/examples/example.proto b/middleware/rialto-client/ipc/examples/example.proto deleted file mode 100644 index d02c31f13..000000000 --- a/middleware/rialto-client/ipc/examples/example.proto +++ /dev/null @@ -1,74 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -import "google/protobuf/descriptor.proto"; -import "rialtoipc.proto"; - -package example; - -// You need this to generate the rpc service stubs -option cc_generic_services = true; - - -message RequestEcho { - required string text = 1; -} -message ResponseEcho { - required string text = 1; -} - - -message RequestWithFd { - optional string text = 1; - required int32 fd = 2 [(rialto.ipc.field_is_fd) = true]; -} -message ResponseWithFd { - optional string text = 1; - required int32 fd = 2 [(rialto.ipc.field_is_fd) = true]; -} - - -message RequestWithNoReply { - optional string text = 1; -} -message EmptyResponse { -} - - - -message SomeEvent { - required int32 id = 5; - optional string text = 1; -} - -service ExampleService { - - rpc exampleEcho(RequestEcho) returns (ResponseEcho) { - } - - rpc exampleWithFd(RequestWithFd) returns (ResponseWithFd) { - } - - rpc exampleWithNoReply(RequestWithNoReply) returns (EmptyResponse) { - option (rialto.ipc.no_reply) = true; - } - -} diff --git a/middleware/rialto-client/ipc/server/CMakeLists.txt b/middleware/rialto-client/ipc/server/CMakeLists.txt deleted file mode 100644 index dd85f16af..000000000 --- a/middleware/rialto-client/ipc/server/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 Sky UK -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - - -add_library( - RialtoIpcServer - STATIC - - source/IpcClientImpl.cpp - source/IpcServerImpl.cpp - source/IpcServerControllerImpl.cpp - - # $ - - ) - -target_include_directories( - RialtoIpcServer - - PUBLIC - include - $ - - PRIVATE - $ - - ) - -set_property( - TARGET RialtoIpcServer - PROPERTY POSITION_INDEPENDENT_CODE ON - - ) - -target_link_libraries( - RialtoIpcServer - - PRIVATE - RialtoIpcCommon - RialtoLogging - protobuf::libprotobuf - - ) diff --git a/middleware/rialto-client/ipc/server/include/IIpcController.h b/middleware/rialto-client/ipc/server/include/IIpcController.h deleted file mode 100644 index 7064f23b3..000000000 --- a/middleware/rialto-client/ipc/server/include/IIpcController.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_H_ -#define FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_H_ - -#include "IIpcServer.h" -#include - -#include -#include -#include - -namespace firebolt::rialto::ipc -{ -/** - * @brief Controller interface for the protobuf RPC service stubs. - * - * A pointer to this interface will be supplied as the first argument in every - * RPC stub call. It is an extensions of the google::protobuf::RpcController - * interface and provides an additional method to get the client that made the - * RPC call. - */ -class IController : public google::protobuf::RpcController -{ -public: - IController() = default; - virtual ~IController() = default; - - IController(const IController &) = delete; - IController &operator=(const IController &) = delete; - IController(IController &&) = delete; - IController &operator=(IController &&) = delete; - -public: - /** - * Client-side methods - * Calls can only be made from the client side. Calling these apis from server side - * is undefined and could cause crashes. - */ - - /** - * @brief Reset the RpcController. - * - * So that the RpcController can be reused for a new call, sets to the inital state. - */ - void Reset() override = 0; - - /** - * @brief Checks id the previosu call has failed. - * - * The reason for the failure depends on the implementaion of the RPC. Failed should only - * be called after after the call has finished. If this call returns true, the response - * structure returned from the failed call is undefined. - * - * @retval true if previous call failed. - */ - bool Failed() const override = 0; - - /** - * @brief Returns a description of the error if the previous call has failed. - * - * @retval error string. - */ - std::string ErrorText() const override = 0; - - /** - * @brief Starts the cancellation of a RPC call - * - * RPC may cancel the call immediatly, wait and cancel or not cancel at all. If a call is cancelled - * failure will be set for the client and "done" will still be called. - */ - void StartCancel() override = 0; - - /** - * Server-side methods - * Calls can only be made from the server side. Calling these apis from client side - * is undefined and could cause crashes. - */ - - /** - * @brief To be called during a method call. Returns a ptr to the client that made the call. - * - * @retval client that made the call. - */ - virtual std::shared_ptr getClient() const = 0; - - /** - * @brief Causes failure to be returned to the client. - * - * Failed() shall return true. The failure reason can be fetched from the ErrorText(). - * To return machine-readable info on failure, use the method response structure rather than - * SetFailed(). - * - * @param[in] reason : The reason for the falure. - */ - void SetFailed(const std::string &reason) override = 0; - - /** - * @brief Not supported. - * - * @retval false. - */ - bool IsCanceled() const override = 0; - - /** - * @brief Not supported. - * - * @param[in] callback : Callback on closure. - */ - void NotifyOnCancel(google::protobuf::Closure *callback) override = 0; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_I_IPC_CONTROLLER_H_ diff --git a/middleware/rialto-client/ipc/server/include/IIpcServer.h b/middleware/rialto-client/ipc/server/include/IIpcServer.h deleted file mode 100644 index 10a2a8936..000000000 --- a/middleware/rialto-client/ipc/server/include/IIpcServer.h +++ /dev/null @@ -1,231 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_I_IPC_SERVER_H_ -#define FIREBOLT_RIALTO_IPC_I_IPC_SERVER_H_ - -#include -#include - -#include -#include -#include -#include -#include - -namespace firebolt::rialto::ipc -{ -/** - * @brief Interface to object describing a client connected to the server. - * - * An object of this interface is provided in the callbacks for when a client - * connects / disconnects. The interface can be used to query details above - * the client and send it asynchronous events. - */ -class IClient -{ -public: - IClient() = default; - virtual ~IClient() = default; - - IClient(const IClient &) = delete; - IClient &operator=(const IClient &) = delete; - IClient(IClient &&) = delete; - IClient &operator=(IClient &&) = delete; - -public: - /** - * @brief Gets the pid of the client that created the connection. - * - * \threadsafe - * - * @retval the pid. - */ - virtual pid_t getClientPid() const = 0; - - /** - * @brief Gets the userIdof the client that created the connection. - * - * \threadsafe - * - * @retval the userId. - */ - virtual uid_t getClientUserId() const = 0; - - /** - * @brief Gets the groupId of the client that created the connection. - * - * \threadsafe - * - * @retval the groupId. - */ - virtual gid_t getClientGroupId() const = 0; - - /** - * @brief Tells the server to disconnect the client. - * - * \threadsafe - * - * Typically you'd call this in the clientConnected method if you didn't want to accept the - * client's connection. - */ - virtual void disconnect() = 0; - - /** - * @brief Adds a service implementation for the client. - * - * \threadsafe - * - * After this the client will be able to call methods on the service. - * - * @param[in] service : service to export. - */ - virtual void exportService(const std::shared_ptr &service) = 0; - - /** - * @brief Sends a message out to the client connection. - * - * \threadsafe - * - * This method is thread safe - * and may be called from any context; internally it will queue the message - * on the client's message queue and the server process will send it - * - * @param[in] message : message to send. - * - * @retval true on success, false otherwise. - */ - virtual bool sendEvent(const std::shared_ptr &message) = 0; - - /** - * @brief The server object. - * - * \threadsafe - * - * It is safe to hold a - * shared_ptr to this object after the client has disconnected, but obviously - * sendEvent will fail and data like pid and userId will be invalid. - * - * @retval true if the client is still conn - */ - virtual bool isConnected() const = 0; -}; - -/** - * @brief The server object. - * - * You must run the server as part of an external event loop implementation, you - * can do that by setting up a loop that calls wait() and then process(). Or - * you can get the fd() and add it to an external poll loop, and when woken call - * process(). - */ -class IServer -{ -public: - IServer() = default; - virtual ~IServer() = default; - - IServer(const IServer &) = delete; - IServer &operator=(const IServer &) = delete; - IServer(IServer &&) = delete; - IServer &operator=(IServer &&) = delete; - - /** - * @brief Creates the listening socket to accept new connections. - * - * \threadsafe - * - * This does not blockwaiting for connections, it just creates the socket and adds to the poll loop. - * - * @retval true on success, false otherwise. - */ - inline bool addSocket(const std::string &socketPath) { return addSocket(socketPath, nullptr, nullptr); } - inline bool addSocket(const std::string &socketPath, - std::function &)> clientConnectedCb) - { - return addSocket(socketPath, std::move(clientConnectedCb), nullptr); - } - virtual bool addSocket(const std::string &socketPath, - std::function &)> clientConnectedCb, - std::function &)> clientDisconnectedCb) = 0; - virtual bool addSocket(int fd, std::function &)> clientConnectedCb, - std::function &)> clientDisconnectedCb) = 0; - - /** - * @brief Create a client. - * - * \threadsafe - * - * Given a file descriptor corresponding to one end of a socket, this function - * will create a client (std::shared_ptr) and add the new client to - * the internal clients list. At that point, the client is initialized and - * ready to run, as if the client had connected to the servers listening socket. - * - * The other end of the socket can be passed to firebolt::rialto::ipc::Channel::connect(int sockFd) - * function to create a client side IPC channel. - * - * When the other end of the socket is closed the clientDisconnectedCb will - * be called. - * - * The socketFd must be a unix domain socket of type SOCK_SEQPACKET, if a different - * socket type then this will fail and return a null std::shared_ptr. - * - * The server will dup the socketFd on success, so the caller can (and should) - * close the socketFd after this call completes if it no longer needs the socket. - * - * @param[in] socketFd : The file descriptor for the socket. - * @param[in] clientDisconnectedCb : Callback to be called on the closing of the socket. - * - * @retval client on success, nullptr otherwise. - */ - inline std::shared_ptr addClient(int socketFd) { return addClient(socketFd, nullptr); } - virtual std::shared_ptr - addClient(int socketFd, std::function &)> clientDisconnectedCb) = 0; - - /** - * @brief Returns an fd that can be added to an external event loop. This is NOT the - * server socket fd. - * - * @retval >= 0 on success, -1 otherwise. - */ - virtual int fd() const = 0; - - /** Waits for any I/O to occur on the socket or timeout from a method call. - * The call will block for a maximum of timeoutMSecs, to make the call wait - * indefinitely pass -1. - * - * @param[in] timeoutMSecs : The time to wait for I/O. - * - * @retval false if there was an error , true otherwise - */ - inline bool wait() { return this->wait(-1); } - virtual bool wait(int timeoutMSecs) = 0; - - /** - * @brief This is the heart of the server, it is where we wait for new incoming - * connections or data from clients, and send data back to clients. - * - * @retval false if there was an error, true otherwise - */ - virtual bool process() = 0; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_I_IPC_SERVER_H_ diff --git a/middleware/rialto-client/ipc/server/include/IIpcServerFactory.h b/middleware/rialto-client/ipc/server/include/IIpcServerFactory.h deleted file mode 100644 index 77f71cbd3..000000000 --- a/middleware/rialto-client/ipc/server/include/IIpcServerFactory.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_I_IPC_SERVER_FACTORY_H_ -#define FIREBOLT_RIALTO_IPC_I_IPC_SERVER_FACTORY_H_ - -#include "IIpcServer.h" - -#include - -namespace firebolt::rialto::ipc -{ -class IServerFactory -{ -public: - IServerFactory() = default; - virtual ~IServerFactory() = default; - - /** - * @brief Create a IServerFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Create a IServer object. - * - * @retval the server instance or null on error. - */ - virtual std::shared_ptr create() = 0; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_I_IPC_SERVER_FACTORY_H_ diff --git a/middleware/rialto-client/ipc/server/source/IpcClientImpl.cpp b/middleware/rialto-client/ipc/server/source/IpcClientImpl.cpp deleted file mode 100644 index dceeeae45..000000000 --- a/middleware/rialto-client/ipc/server/source/IpcClientImpl.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "IpcClientImpl.h" -#include "IpcServerImpl.h" -#include - -namespace firebolt::rialto::ipc -{ -ClientImpl::ClientImpl(const std::shared_ptr &server, uint64_t clientId, const struct ucred &creds) - : m_kServer(server), m_kClientId(clientId), m_kCredentials(creds) -{ -} - -pid_t ClientImpl::getClientPid() const -{ - return m_kCredentials.pid; -} - -uid_t ClientImpl::getClientUserId() const -{ - return m_kCredentials.uid; -} - -gid_t ClientImpl::getClientGroupId() const -{ - return m_kCredentials.gid; -} - -void ClientImpl::disconnect() -{ - auto server = m_kServer.lock(); - if (server) - { - server->disconnectClient(m_kClientId); - } -} - -void ClientImpl::exportService(const std::shared_ptr &service) -{ - auto descriptor = service->GetDescriptor(); - m_services.emplace(descriptor->full_name(), service); -} - -bool ClientImpl::sendEvent(const std::shared_ptr &message) -{ - auto server = m_kServer.lock(); - if (server) - return server->sendEvent(m_kClientId, message); - else - return false; -} - -bool ClientImpl::isConnected() const -{ - auto server = m_kServer.lock(); - if (server) - return server->isClientConnected(m_kClientId); - else - return false; -} - -} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/server/source/IpcClientImpl.h b/middleware/rialto-client/ipc/server/source/IpcClientImpl.h deleted file mode 100644 index 9c44b097c..000000000 --- a/middleware/rialto-client/ipc/server/source/IpcClientImpl.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_IPC_CLIENT_IMPL_H_ -#define FIREBOLT_RIALTO_IPC_IPC_CLIENT_IMPL_H_ - -#include "IIpcServer.h" - -#include - -#include -#include -#include - -namespace firebolt::rialto::ipc -{ -class ServerImpl; - -class ClientImpl final : public IClient -{ -public: - ClientImpl(const std::shared_ptr &server, uint64_t clientId, const struct ucred &creds); - ~ClientImpl() final = default; - -public: - pid_t getClientPid() const override; - uid_t getClientUserId() const override; - gid_t getClientGroupId() const override; - - void disconnect() override; - - void exportService(const std::shared_ptr &service) override; - - bool sendEvent(const std::shared_ptr &message) override; - - bool isConnected() const override; - -protected: - friend class ServerImpl; - inline uint64_t id() const { return m_kClientId; } - -private: - const std::weak_ptr m_kServer; - const uint64_t m_kClientId{}; - const struct ucred m_kCredentials; - - std::map> m_services; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_IPC_CLIENT_IMPL_H_ diff --git a/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.cpp b/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.cpp deleted file mode 100644 index 2c0d100cc..000000000 --- a/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "IpcServerControllerImpl.h" -#include "IpcClientImpl.h" -#include -#include -#include - -namespace firebolt::rialto::ipc -{ -ServerControllerImpl::ServerControllerImpl(std::shared_ptr client, uint64_t serialId) - : m_kClient(std::move(client)), m_kSerialId(serialId) -{ -} - -void ServerControllerImpl::SetFailed(const std::string &reason) // NOLINT(build/function_format) -{ - m_failed = true; - m_failureReason = reason; -} - -bool ServerControllerImpl::IsCanceled() const // NOLINT(build/function_format) -{ - // neither client nor server support cancel - return false; -} - -void ServerControllerImpl::NotifyOnCancel(google::protobuf::Closure *callback) // NOLINT(build/function_format) -{ - // neither client nor server support cancel - (void)callback; -} - -std::shared_ptr ServerControllerImpl::getClient() const -{ - return m_kClient; -} - -} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.h b/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.h deleted file mode 100644 index 22a0e4b80..000000000 --- a/middleware/rialto-client/ipc/server/source/IpcServerControllerImpl.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_IPC_SERVER_CONTROLLER_IMPL_H_ -#define FIREBOLT_RIALTO_IPC_IPC_SERVER_CONTROLLER_IMPL_H_ - -#include "IIpcController.h" -#include "IpcClientImpl.h" -#include -#include - -namespace firebolt::rialto::ipc -{ -/** - * @brief Implementation of the RialtoIpcServerController interface, a pointer to an - * object of this type is supplied in each RPC call handler. - * - * This object is inherited from RialtoIpcServerController interface which in turn - * is inherited from google::protobuf::RpcController, and therefore meets the - * requirements of the protobuf RPC service handler. - * - * It implements the google::protobuf::RpcController::SetFailed(...) method - * which allows the server to return a failure on an RPC call. - * - * It also implements the RialtoIpcController::getClient(...) method which - * allows for returning a pointer to the RialtoIpc client that made the request. - * This is an extension to the google::protobuf::RpcController interface. - * If clients need this API then they are expected to perform a dynamic_cast - * on the controller pointer to a RialtoIpcController pointer. - */ -class ServerControllerImpl final : public IController -{ -public: - ~ServerControllerImpl() final = default; - -public: - /** - * Ignore Client-side methods - */ - void Reset() final {} - bool Failed() const final { return false; } - std::string ErrorText() const final { return std::string(); } - void StartCancel() final {} - -public: - /** - * Server-side methods - */ - void SetFailed(const std::string &reason) final; - bool IsCanceled() const final; - void NotifyOnCancel(google::protobuf::Closure *callback) final; - std::shared_ptr getClient() const final; - -protected: - friend class ServerImpl; - ServerControllerImpl(std::shared_ptr client, uint64_t serialId); - - const std::shared_ptr m_kClient; - const uint64_t m_serialId{}; - const uint64_t m_kSerialId; - - bool m_failed = false; - std::string m_failureReason; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_IPC_SERVER_CONTROLLER_IMPL_H_ diff --git a/middleware/rialto-client/ipc/server/source/IpcServerImpl.cpp b/middleware/rialto-client/ipc/server/source/IpcServerImpl.cpp deleted file mode 100644 index f6cd2da73..000000000 --- a/middleware/rialto-client/ipc/server/source/IpcServerImpl.cpp +++ /dev/null @@ -1,1417 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "IpcServerImpl.h" -#include "IIpcServerFactory.h" -#include "IpcClientImpl.h" -#include "IpcLogging.h" -#include "IpcServerControllerImpl.h" - -#include "rialtoipc.pb.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WAKE_EVENT_ID uint64_t(0) -#define FIRST_LISTENING_SOCKET_ID uint64_t(1) -#define FIRST_CLIENT_ID uint64_t(10000) - -namespace firebolt::rialto::ipc -{ -const size_t ServerImpl::m_kMaxMessageLen = (128 * 1024); - -std::shared_ptr IServerFactory::createFactory() -{ - std::shared_ptr factory; - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_IPC_LOG_ERROR("Failed to create the server factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr ServerFactory::create() -{ - return std::make_shared(); -} - -ServerImpl::ServerImpl() - : m_pollFd(-1), m_wakeEventFd(-1), m_socketIdCounter(FIRST_LISTENING_SOCKET_ID), m_clientIdCounter(FIRST_CLIENT_ID), - m_recvDataBuf{0}, m_recvCtrlBuf{0} -{ - // create the eventfd use to wake the poll loop - m_wakeEventFd = eventfd(0, EFD_CLOEXEC); - if (m_wakeEventFd < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "eventfd failed"); - return; - } - - // create epoll loop - m_pollFd = epoll_create1(EPOLL_CLOEXEC); - if (m_pollFd < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_create1 failed"); - return; - } - - // add the wake event to epoll - epoll_event event = {.events = EPOLLIN, .data = {.u64 = WAKE_EVENT_ID}}; - if (epoll_ctl(m_pollFd, EPOLL_CTL_ADD, m_wakeEventFd, &event) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add eventfd"); - } -} - -ServerImpl::~ServerImpl() -{ - if ((m_pollFd >= 0) && (close(m_pollFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close epoll"); - - if ((m_wakeEventFd >= 0) && (close(m_wakeEventFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close eventfd"); - - for (const auto &entry : m_sockets) - { - const Socket &kSocket = entry.second; - - if (kSocket.isOwned) - { - if (unlink(kSocket.sockPath.c_str()) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket @ '%s'", kSocket.sockPath.c_str()); - if (close(kSocket.sockFd) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close listening socket"); - - if (unlink(kSocket.lockPath.c_str()) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket lock file @ '%s'", kSocket.lockPath.c_str()); - if (close(kSocket.lockFd) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close socket lock file"); - } - } -} - -// ----------------------------------------------------------------------------- -/*! - \static - \internal - - Creates (if required) and takes the file lock associated with the socket - path in the \a socket object. - - */ -bool ServerImpl::getSocketLock(Socket *socket) -{ - std::string lockPath = socket->sockPath + ".lock"; - int fileDescriptor = open(lockPath.c_str(), O_CREAT | O_CLOEXEC, (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)); - if (fileDescriptor < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to create / open lockfile @ '%s' (check permissions)", lockPath.c_str()); - return false; - } - - if (flock(fileDescriptor, LOCK_EX | LOCK_NB) < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to lock lockfile @ '%s', maybe another server is running", - lockPath.c_str()); - close(fileDescriptor); - return false; - } - - struct stat sbuf = {0}; - if (stat(socket->sockPath.c_str(), &sbuf) < 0) - { - if (errno != ENOENT) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "did not manage to stat existing socket @ '%s'", socket->sockPath.c_str()); - close(fileDescriptor); - return false; - } - } - else if ((sbuf.st_mode & S_IWUSR) || (sbuf.st_mode & S_IWGRP)) - { - unlink(socket->sockPath.c_str()); - } - - socket->lockFd = fileDescriptor; - socket->lockPath = std::move(lockPath); - - return true; -} - -// ----------------------------------------------------------------------------- -/*! - \static - \internal - - Closes the file descriptors and the deletes the files stored in the \a socket - object. - - */ -void ServerImpl::closeListeningSocket(Socket *socket) -{ - if (!socket->isOwned) - { - return; - } - - if (!socket->sockPath.empty() && (unlink(socket->sockPath.c_str()) != 0) && (errno != ENOENT)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket @ '%s'", socket->sockPath.c_str()); - if ((socket->sockFd >= 0) && (close(socket->sockFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close listening socket"); - - if (!socket->lockPath.empty() && (unlink(socket->lockPath.c_str()) != 0) && (errno != ENOENT)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket lock file @ '%s'", socket->lockPath.c_str()); - if ((socket->lockFd >= 0) && (close(socket->lockFd) != 0)) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close socket lock file"); - - socket->sockFd = -1; - socket->sockPath.clear(); - - socket->lockFd = -1; - socket->lockPath.clear(); -} - -bool ServerImpl::addSocket(const std::string &socketPath, - std::function &)> clientConnectedCb, - std::function &)> clientDisconnectedCb) -{ - // store the path - Socket socket; - socket.sockPath = socketPath; - - // create the socket - socket.sockFd = ::socket(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); - if (socket.sockFd == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "socket error"); - return false; - } - - // get the socket lock - if (!getSocketLock(&socket)) - { - closeListeningSocket(&socket); - return false; - } - - // bind to the given path - struct sockaddr_un addr = {0}; - memset(&addr, 0x00, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); - - if (bind(socket.sockFd, reinterpret_cast(&addr), sizeof(addr)) == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "bind error"); - - closeListeningSocket(&socket); - return false; - } - - // put in listening mode - if (listen(socket.sockFd, 1) == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "listen error"); - - closeListeningSocket(&socket); - return false; - } - - // create an id for the listening socket - const uint64_t kSocketId = m_socketIdCounter++; - if (kSocketId >= FIRST_CLIENT_ID) - { - // should never happen, we'd run out of file descriptors before - // we hit the 10k limit on listening sockets - RIALTO_IPC_LOG_ERROR("too many listening sockets"); - - closeListeningSocket(&socket); - return false; - } - - // add the socket to epoll - epoll_event event = {.events = EPOLLIN, .data = {.u64 = kSocketId}}; - if (epoll_ctl(m_pollFd, EPOLL_CTL_ADD, socket.sockFd, &event) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add listening socket"); - - closeListeningSocket(&socket); - return false; - } - - // store the client connected / disconnected callbacks - socket.connectedCb = clientConnectedCb; - socket.disconnectedCb = clientDisconnectedCb; - - // add to the internal map - std::lock_guard locker(m_socketsLock); - m_sockets.emplace(kSocketId, std::move(socket)); - - RIALTO_IPC_LOG_INFO("added listening socket '%s' to server", socketPath.c_str()); - - return true; -} - -bool ServerImpl::addSocket(int fd, std::function &)> clientConnectedCb, - std::function &)> clientDisconnectedCb) -{ - // store the path - Socket socket; - socket.isOwned = false; - socket.sockFd = fd; - - // put in listening mode - if (listen(socket.sockFd, 1) == -1) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "listen error"); - return false; - } - - // create an id for the listening socket - const uint64_t kSocketId = m_socketIdCounter++; - if (kSocketId >= FIRST_CLIENT_ID) - { - // should never happen, we'd run out of file descriptors before - // we hit the 10k limit on listening sockets - RIALTO_IPC_LOG_ERROR("too many listening sockets"); - return false; - } - - // add the socket to epoll - epoll_event event = {.events = EPOLLIN, .data = {.u64 = kSocketId}}; - if (epoll_ctl(m_pollFd, EPOLL_CTL_ADD, socket.sockFd, &event) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add listening socket"); - return false; - } - - // store the client connected / disconnected callbacks - socket.connectedCb = clientConnectedCb; - socket.disconnectedCb = clientDisconnectedCb; - - // add to the internal map - std::lock_guard locker(m_socketsLock); - m_sockets.emplace(kSocketId, std::move(socket)); - - RIALTO_IPC_LOG_INFO("added listening socket with fd: %d to server", fd); - - return true; -} - -std::shared_ptr ServerImpl::addClient(int socketFd, - std::function &)> clientDisconnectedCb) -{ - // sanity check the supplied socket is of the right type - struct sockaddr addr; - socklen_t len = sizeof(sockaddr); - if ((getsockname(socketFd, &addr, &len) < 0) || (len < sizeof(sa_family_t))) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get name of supplied socket"); - return nullptr; - } - if (addr.sa_family != AF_UNIX) - { - RIALTO_IPC_LOG_ERROR("supplied client socket is not a unix domain socket"); - return nullptr; - } - - int type = 0; - len = sizeof(type); - if ((getsockopt(socketFd, SOL_SOCKET, SO_TYPE, &type, &len) < 0) || (len != sizeof(type))) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get type of supplied socket"); - return nullptr; - } - if (type != SOCK_SEQPACKET) - { - RIALTO_IPC_LOG_ERROR("supplied client socket is not of type SOCK_SEQPACKET"); - return nullptr; - } - - // dup the socket and set the O_CLOEXEC bit - int duppedFd = fcntl(socketFd, F_DUPFD_CLOEXEC, 3); - if (duppedFd < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get type of supplied socket"); - return nullptr; - } - - // ensure the SOCK_NONBLOCK flag is set - int flags = fcntl(duppedFd, F_GETFL); - if ((flags < 0) || (fcntl(duppedFd, F_SETFL, flags | O_NONBLOCK) < 0)) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to set socket to non-blocking mode"); - close(duppedFd); - return nullptr; - } - - // finally, add the socket to the list of clients - auto client = addClientSocket(duppedFd, "", std::move(clientDisconnectedCb)); - if (!client) - { - close(duppedFd); - } - - return client; -} - -int ServerImpl::fd() const -{ - return m_pollFd; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Writes to the eventfd to wake the event loop. Typically called when requesting - it to shutdown or external code has requested that a client be disconnected. - - */ -void ServerImpl::wakeEventLoop() const -{ - if (m_wakeEventFd < 0) - { - RIALTO_IPC_LOG_ERROR("invalid wake event fd"); - } - else - { - uint64_t value = 1; - if (TEMP_FAILURE_RETRY(::write(m_wakeEventFd, &value, sizeof(value))) != sizeof(value)) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to write to the event fd"); - } - } -} - -bool ServerImpl::wait(int timeoutMSecs) -{ - if (m_pollFd < 0) - { - return false; - } - - // wait for any event (with timeout) - struct pollfd fds[2]; - fds[0].fd = m_pollFd; - fds[0].events = POLLIN; - - int rc = TEMP_FAILURE_RETRY(poll(fds, 1, timeoutMSecs)); - if (rc < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "poll failed?"); - return false; - } - - return true; -} - -bool ServerImpl::process() -{ - if (m_pollFd < 0) - { - RIALTO_IPC_LOG_ERROR("missing epoll"); - return false; - } - - // read up to 32 events - const int kMaxEvents = 32; - struct epoll_event events[kMaxEvents]; - - int rc = TEMP_FAILURE_RETRY(epoll_wait(m_pollFd, events, kMaxEvents, 0)); - if (rc < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_wait failed"); - return false; - } - - // process the events (maybe 0 if timed out) - for (int i = 0; i < rc; i++) - { - const struct epoll_event &kEvent = events[i]; - - // check if a wake event, in which case just clear the eventfd - if (kEvent.data.u64 == WAKE_EVENT_ID) - { - uint64_t ignore; - if (TEMP_FAILURE_RETRY(::read(m_wakeEventFd, &ignore, sizeof(ignore))) != sizeof(ignore)) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to read wake eventfd"); - } - } - - // check for events on the listening socket - else if (kEvent.data.u64 < FIRST_CLIENT_ID) - { - if (kEvent.events & EPOLLIN) - processNewConnection(kEvent.data.u64); - if (kEvent.events & EPOLLERR) - RIALTO_IPC_LOG_ERROR("error occurred on listening socket"); - } - - // otherwise, the event must have come from a socket - else - { - processClientSocket(kEvent.data.u64, kEvent.events); - } - } - - // if we have client sockets that are condemned then we need to shut down - // and close them as well as remove from epoll - std::unique_lock locker(m_clientsLock); - if (!m_condemnedClients.empty()) - { - // take a copy of the set so we can process without the lock held - std::set theCondemned; - m_condemnedClients.swap(theCondemned); - - for (uint64_t clientId : theCondemned) - { - auto it = m_clients.find(clientId); - if (it == m_clients.end()) - { - RIALTO_IPC_LOG_ERROR("failed to find condemned client"); - continue; - } - - ClientDetails details = it->second; - - // remove from the list of clients - m_clients.erase(it); - - // drop the lock while closing the connection and removing from epoll - locker.unlock(); - - // remove the socket from epoll and close it - if (details.sock >= 0) - { - if (epoll_ctl(m_pollFd, EPOLL_CTL_DEL, details.sock, nullptr) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to remove socket from epoll"); - - if (shutdown(details.sock, SHUT_RDWR) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to shutdown socket"); - if (close(details.sock) != 0) - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close socket"); - } - - // let the installed handler know a client has disconnected - if (details.disconnectedCb) - details.disconnectedCb(details.client); - - // ensure client object is destructed without the client lock held - details.client.reset(); - - // re-take the lock for the next client - locker.lock(); - } - } - - return true; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Adds the \a socketFd to the internal list of client sockets. This is called - when a new connection is accepted on a listening socket, or when a client - fd is added via ServerImpl::addClient(...). - - Returns a nullptr if failed to add the socket. - - */ -std::shared_ptr ServerImpl::addClientSocket(int socketFd, const std::string &listeningSocketPath, - std::function &)> disconnectedCb) -{ - // get the client credentials - struct ucred clientCreds = {0}; - socklen_t clientCredsLen = sizeof(clientCreds); - - if ((getsockopt(socketFd, SOL_SOCKET, SO_PEERCRED, &clientCreds, &clientCredsLen) < 0) || - (clientCredsLen != sizeof(clientCreds))) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to get client's details"); - return nullptr; - } - - // create a new unique client id for the connection - const uint64_t kClientId = m_clientIdCounter++; - - // add the new socket to the poll loop - epoll_event event = {.events = EPOLLIN, .data = {.u64 = kClientId}}; - if (epoll_ctl(m_pollFd, EPOLL_CTL_ADD, socketFd, &event) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "epoll_ctl failed to add client socket"); - return nullptr; - } - - // create initial client object for the socket - auto client = std::make_shared(shared_from_this(), kClientId, clientCreds); - - // and the details for the internal list - ClientDetails clientDetails; - clientDetails.sock = socketFd; - clientDetails.disconnectedCb = std::move(disconnectedCb); - clientDetails.client = client; - - // add to the set of clients - { - std::lock_guard locker(m_clientsLock); - m_clients.emplace(kClientId, clientDetails); - } - - RIALTO_IPC_LOG_INFO("new client connected - giving id %" PRIu64, kClientId); - - return client; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Called when an event occurs on the listening socket. The code first accepts - the connection and retrieves the client details, it then calls the installed - handler to determine if we should drop this connection or not. - - - */ -void ServerImpl::processNewConnection(uint64_t socketId) -{ - RIALTO_IPC_LOG_DEBUG("processing new connection"); - - std::unique_lock socketLocker(m_socketsLock); - - // find matching socket object - auto it = m_sockets.find(socketId); - if (it == m_sockets.end()) - { - RIALTO_IPC_LOG_ERROR("failed to find listening socket with id %" PRIu64, socketId); - return; - } - - const Socket &kSocket = it->second; - - // accept the connection from the client - struct sockaddr clientAddr = {0}; - socklen_t clientAddrLen = sizeof(clientAddr); - - int clientSock = accept4(kSocket.sockFd, &clientAddr, &clientAddrLen, SOCK_NONBLOCK | SOCK_CLOEXEC); - if (clientSock < 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to accept client connection"); - return; - } - - const std::string kSockPath = kSocket.sockPath; - std::function &)> connectedCb = kSocket.connectedCb; - std::function &)> disconnectedCb = kSocket.disconnectedCb; - - socketLocker.unlock(); - - // attempt to add the socket to the client list - auto client = addClientSocket(clientSock, kSockPath, std::move(disconnectedCb)); - if (!client) - { - close(clientSock); - return; - } - - // notify the handler that a new connection has been made - if (connectedCb) - { - // tell the handler we have a new client - connectedCb(client); - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - \static - - Reads all the file descriptors from a message. It returns the file descriptors - as a vector of FileDescriptor objects, these objects safely store the fd and - close them when they're destructed. - - */ -static std::vector readMessageFds(const struct msghdr *msg, size_t limit) -{ - std::vector fds; - - for (struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg); cmsg != nullptr; - cmsg = CMSG_NXTHDR(const_cast(msg), cmsg)) - { - if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SCM_RIGHTS)) - { - const unsigned kFdsLength = cmsg->cmsg_len - CMSG_LEN(0); - if ((kFdsLength < sizeof(int)) || ((kFdsLength % sizeof(int)) != 0)) - { - RIALTO_IPC_LOG_ERROR("invalid fd array size"); - } - else - { - const size_t n = kFdsLength / sizeof(int); - RIALTO_IPC_LOG_DEBUG("received %zu fds", n); - - fds.reserve(std::min(limit, n)); - - const int *kFds = reinterpret_cast(CMSG_DATA(cmsg)); - for (size_t i = 0; i < n; i++) - { - RIALTO_IPC_LOG_DEBUG("received fd %d", kFds[i]); - - if (fds.size() >= limit) - { - RIALTO_IPC_LOG_ERROR("received to many file descriptors, " - "exceeding max per message, closing left overs"); - } - else - { - FileDescriptor fd(kFds[i]); - if (!fd.isValid()) - { - RIALTO_IPC_LOG_ERROR("received invalid fd (couldn't dup)"); - } - else - { - fds.emplace_back(std::move(fd)); - } - } - - if (close(kFds[i]) != 0) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to close received fd"); - } - } - } - } - } - - return fds; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Processes an event from a client socket. - - */ -void ServerImpl::processClientSocket(uint64_t clientId, unsigned events) -{ - // take the lock while accessing the client list - std::unique_lock locker(m_clientsLock); - - auto it = m_clients.find(clientId); - if (it == m_clients.end()) - { - // should never happen - RIALTO_IPC_LOG_ERROR("received an event from a socket with no matching client"); - return; - } - - // check if the client is marked for closure, if so then just ignore the data - if (m_condemnedClients.count(clientId) != 0) - { - return; - } - - // get the socket that corresponds to the client connection - const int kSockFd = it->second.sock; - - // get the client object - std::shared_ptr clientObj = it->second.client; - - // can safely release the lock now we have the clientId and client object - locker.unlock(); - - // if there was an error disconnect the socket - if (events & EPOLLERR) - { - RIALTO_IPC_LOG_ERROR("error detected on client socket - disconnecting client"); - disconnectClient(clientId); - return; - } - - if (events & EPOLLIN) - { - // read all messages from the client socket, we break out if the socket is closed - // or EWOULDBLOCK is returned on a read (ie. no more messages to read) - while (true) - { - struct msghdr msg = {nullptr}; - struct iovec io = {.iov_base = m_recvDataBuf, .iov_len = sizeof(m_recvDataBuf)}; - - bzero(&msg, sizeof(msg)); - msg.msg_iov = &io; - msg.msg_iovlen = 1; - msg.msg_control = m_recvCtrlBuf; - msg.msg_controllen = sizeof(m_recvCtrlBuf); - - // read one message - ssize_t rd = TEMP_FAILURE_RETRY(recvmsg(kSockFd, &msg, MSG_CMSG_CLOEXEC)); - if (rd < 0) - { - if (errno != EWOULDBLOCK) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "error reading client socket"); - disconnectClient(clientId); - } - - break; - } - else if (rd == 0) - { - // client closed connection, and we've read all data, add to the condemned set - // so is cleaned up once all the events are processed - disconnectClient(clientId); - - break; - } - else if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) - { - RIALTO_IPC_LOG_WARN("received message from client %" PRIu64 " truncated, discarding", clientId); - - // make sure to close all the fds, otherwise we'll leak them - readMessageFds(&msg, 16); - } - else - { - // if there is control data then assume fd(s) have been passed - if (msg.msg_controllen > 0) - { - processClientMessage(clientObj, m_recvDataBuf, rd, readMessageFds(&msg, 16)); - } - else - { - processClientMessage(clientObj, m_recvDataBuf, rd); - } - } - } - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Places the received file descriptors into the request message. - - It works by iterating over the fields in the message, finding ones that are - marked as 'field_is_fd' and then replacing the received integer value with - an actual file descriptor. - - */ -static bool addRequestFileDescriptors(google::protobuf::Message *request, const std::vector &requestFds) -{ - auto fdIterator = requestFds.begin(); - - const google::protobuf::Descriptor *kDescriptor = request->GetDescriptor(); - const google::protobuf::Reflection *kReflection = nullptr; - - const int n = kDescriptor->field_count(); - for (int i = 0; i < n; i++) - { - auto fieldDescriptor = kDescriptor->field(i); - if (fieldDescriptor->options().HasExtension(field_is_fd) && fieldDescriptor->options().GetExtension(field_is_fd)) - { - if (fieldDescriptor->type() != google::protobuf::FieldDescriptor::TYPE_INT32) - { - RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but not an int32 type"); - return false; - } - - if (!kReflection) - { - kReflection = request->GetReflection(); - } - - if (kReflection->HasField(*request, fieldDescriptor)) - { - if (fdIterator == requestFds.end()) - { - RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but one was supplied"); - return false; - } - - kReflection->SetInt32(request, fieldDescriptor, fdIterator->fd()); - ++fdIterator; - } - } - } - - if (fdIterator != requestFds.end()) - { - RIALTO_IPC_LOG_ERROR("received too many file descriptors in the message"); - return false; - } - - return true; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Processes a message received on a client socket. - - */ -void ServerImpl::processClientMessage(const std::shared_ptr &client, const uint8_t *data, size_t dataLen, - const std::vector &fds) -{ - RIALTO_IPC_LOG_DEBUG("processing client message of size %zu bytes (%zu fds) from client %" PRId64, dataLen, - fds.size(), client->id()); - - // parse the message - transport::MessageToServer message; - if (!message.ParseFromArray(data, static_cast(dataLen))) - { - RIALTO_IPC_LOG_ERROR("invalid request"); - return; - } - - if (message.has_call()) - { - processMethodCall(client, message.call(), fds); - } - else - { - RIALTO_IPC_LOG_WARN("received unknown message type from client"); - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Processes a method call requst from a client. - - */ -void ServerImpl::processMethodCall(const std::shared_ptr &client, const transport::MethodCall &call, - const std::vector &fds) -{ - // try and find the service with the given name - const std::string &kServiceName = call.service_name(); - auto it = client->m_services.find(kServiceName); - if (it == client->m_services.end()) - { - RIALTO_IPC_LOG_ERROR("unknown service request '%s'", kServiceName.c_str()); - - sendErrorReply(client, call.serial_id(), "Unknown service '%s'", kServiceName.c_str()); - return; - } - - std::shared_ptr service = it->second; - - // try and find the method - const std::string &kMethodName = call.method_name(); - const google::protobuf::MethodDescriptor *kMethod = service->GetDescriptor()->FindMethodByName(kMethodName); - if (!kMethod) - { - RIALTO_IPC_LOG_ERROR("no method with name '%s'", kMethodName.c_str()); - - sendErrorReply(client, call.serial_id(), "Unknown method '%s'", kMethodName.c_str()); - return; - } - - // check if the method is expecting a reply - const bool kNoReply = kMethod->options().HasExtension(no_reply) && kMethod->options().GetExtension(no_reply); - - // parse the request data - google::protobuf::Message *requestMessage = service->GetRequestPrototype(kMethod).New(); - if (!requestMessage->ParseFromString(call.request_message())) - { - RIALTO_IPC_LOG_ERROR("failed to parse method from array"); - } - else if (!addRequestFileDescriptors(requestMessage, fds)) - { - RIALTO_IPC_LOG_ERROR("mismatch of file descriptors to the request"); - } - else - { - RIALTO_IPC_LOG_DEBUG("call{ serial %" PRIu64 " } - %s.%s { %s }", call.serial_id(), kServiceName.c_str(), - kMethodName.c_str(), requestMessage->ShortDebugString().c_str()); - - auto *controller = new ServerControllerImpl(client, call.serial_id()); - - if (kNoReply) - { - // we should not send a reply for this call, so call the code to handle the - // request, but no need to pass a controller, response or closure object - static google::protobuf::internal::FunctionClosure0 nullClosure(&google::protobuf::DoNothing, false); - service->CallMethod(kMethod, controller, requestMessage, nullptr, &nullClosure); - - delete controller; - } - else - { - // create a response - google::protobuf::Message *responseMessage = service->GetResponsePrototype(kMethod).New(); - - // this is finally where we call the service implementation to process the request - service->CallMethod(kMethod, controller, requestMessage, responseMessage, - google::protobuf::NewCallback(this, &ServerImpl::handleResponse, controller, - responseMessage)); - } - } - - delete requestMessage; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - \threadsafe - - Sends a message to the given client if still connected. - - */ -void ServerImpl::sendReply(uint64_t clientId, const std::shared_ptr &msg) -{ - // now take the lock (so the socket is not closed beneath us) and send the reply - std::lock_guard locker(m_clientsLock); - - auto it = m_clients.find(clientId); - if (it == m_clients.end()) - { - RIALTO_IPC_LOG_WARN("socket removed before error reply could be sent"); - } - else if (it->second.sock < 0) - { - RIALTO_IPC_LOG_WARN("socket closed before error reply could be sent"); - } - else if (!msg) - { - RIALTO_IPC_LOG_WARN("invalid msg to send on socket, ignoring"); - } - else if (TEMP_FAILURE_RETRY(sendmsg(it->second.sock, msg.get(), MSG_NOSIGNAL)) != - static_cast(msg->msg_iov->iov_len)) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to send the complete error reply message"); - } -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Sends an error back to the client with a reason string in \a format. - - */ -void ServerImpl::sendErrorReply(const std::shared_ptr &client, uint64_t serialId, const char *format, ...) -{ - // construct the error string - va_list ap; - va_start(ap, format); - char reason[512]; - vsnprintf(reason, sizeof(reason), format, ap); - va_end(ap); - - // construct the reply message - auto msg = populateErrorReply(client, serialId, reason); - - // and send it - sendReply(client->id(), msg); -} - -// ----------------------------------------------------------------------------- -/*! - \internal - \threadsafe - - Called once the service handler code has processed the request and - completed it. This may be called from a different thread if the service - implementation decided to off-load the request to a processing thread. - - */ -void ServerImpl::handleResponse(ServerControllerImpl *controller, google::protobuf::Message *response) -{ - if (!controller || !controller->m_kClient) - { - RIALTO_IPC_LOG_ERROR("missing controller or attached client"); - return; - } - - const std::shared_ptr kClient = controller->m_kClient; - const uint64_t kClientId = kClient->id(); - - std::shared_ptr message; - if (!controller->m_failed) - { - message = populateReply(kClient, controller->m_kSerialId, response); - } - else - { - message = populateErrorReply(kClient, controller->m_kSerialId, controller->m_failureReason); - } - - // no longer need the controller or the response objects - delete response; - delete controller; - - // send the reply message to the given client - sendReply(kClientId, message); -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Gets all the file descriptors that are stored in the \a response message - and returns them as a vector of ints. - - It works by iterating over the fields in the message, finding ones that are - marked as 'field_is_fd' and inserting the fd value into control part of the - message. The actual integer sent in the data part of the message is set to - -1. - - */ -static std::vector getResponseFileDescriptors(google::protobuf::Message *response) -{ - std::vector fds; - - // process any file descriptors from the response message - const google::protobuf::Descriptor *kDescriptor = response->GetDescriptor(); - const google::protobuf::Reflection *kReflection = nullptr; - - const int n = kDescriptor->field_count(); - for (int i = 0; i < n; i++) - { - auto fieldDescriptor = kDescriptor->field(i); - if (fieldDescriptor->options().HasExtension(field_is_fd) && fieldDescriptor->options().GetExtension(field_is_fd)) - { - if (fieldDescriptor->type() != google::protobuf::FieldDescriptor::TYPE_INT32) - { - RIALTO_IPC_LOG_ERROR("field is marked as containing an fd but not an int32 type"); - return {}; - } - - if (!kReflection) - { - kReflection = response->GetReflection(); - } - - if (kReflection->HasField(*response, fieldDescriptor)) - { - fds.push_back(kReflection->GetInt32(*response, fieldDescriptor)); - kReflection->SetInt32(response, fieldDescriptor, -1); - } - } - } - - return fds; -} - -// ----------------------------------------------------------------------------- -/*! - \internal - \static - - Populates tha socket message buffer with the reply data for the RPC request. - - */ -std::shared_ptr ServerImpl::populateReply(const std::shared_ptr &client, uint64_t serialId, - google::protobuf::Message *response) -{ - // create the base reply - transport::MessageFromServer message; - transport::MethodCallReply *reply = message.mutable_reply(); - if (!reply) - { - RIALTO_IPC_LOG_ERROR("failed to create mutable reply object"); - return nullptr; - } - - // convert the message response to a data string - std::string respString = response->SerializeAsString(); - - // wrap in a transport response and send that - reply->set_reply_id(serialId); - reply->set_reply_message(std::move(respString)); - - // next need to check if the response message has any file descriptors in - // it that need to be attached - const std::vector kFds = getResponseFileDescriptors(response); - const size_t kRequiredCtrlLen = kFds.empty() ? 0 : CMSG_SPACE(sizeof(int) * kFds.size()); - - // calculate the size of the reply - const size_t kRequiredDataLen = message.ByteSizeLong(); - if (kRequiredDataLen > m_kMaxMessageLen) - { - RIALTO_IPC_LOG_ERROR("reply exceeds maximum message limit (%zu, max %zu)", kRequiredDataLen, m_kMaxMessageLen); - - // error message is too big, replace with a generic error - return populateErrorReply(client, serialId, "Internal error - reply message to large"); - } - - // build the socket message to send - auto msgBuf = - m_sendBufPool.allocateShared(sizeof(msghdr) + sizeof(iovec) + kRequiredCtrlLen + kRequiredDataLen); - - auto *header = reinterpret_cast(msgBuf.get()); - bzero(header, sizeof(msghdr)); - - auto *ctrl = reinterpret_cast(msgBuf.get() + sizeof(msghdr)); - header->msg_control = ctrl; - header->msg_controllen = kRequiredCtrlLen; - - auto *iov = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen); - header->msg_iov = iov; - header->msg_iovlen = 1; - - auto *data = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen + sizeof(iovec)); - iov->iov_base = data; - iov->iov_len = kRequiredDataLen; - - // copy in the data - message.SerializeWithCachedSizesToArray(data); - - // add the fds - if (!kFds.empty()) - { - struct cmsghdr *cmsg = CMSG_FIRSTHDR(header); - if (!cmsg) - { - RIALTO_IPC_LOG_ERROR("odd, failed to get the first cmsg header"); - return nullptr; - } - - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int) * kFds.size()); - memcpy(CMSG_DATA(cmsg), kFds.data(), sizeof(int) * kFds.size()); - header->msg_controllen = cmsg->cmsg_len; - } - - RIALTO_IPC_LOG_DEBUG("reply{ serial %" PRIu64 " } - { %s }", serialId, response->ShortDebugString().c_str()); - - // std::reinterpret_pointer_cast is only implemented in C++17 and newer, so for - // now do it manually - return std::shared_ptr(msgBuf, reinterpret_cast(msgBuf.get())); -} - -// ----------------------------------------------------------------------------- -/*! - \internal - - Populates tha socket message buffer with a reply error message. - - */ -std::shared_ptr ServerImpl::populateErrorReply(const std::shared_ptr &client, - uint64_t serialId, const std::string &reason) -{ - // create the base reply - transport::MessageFromServer message; - transport::MethodCallError *error = message.mutable_error(); - error->set_reply_id(serialId); - error->set_error_reason(reason); - - // check the message will fit - size_t replySize = message.ByteSizeLong(); - if (replySize > m_kMaxMessageLen) - { - RIALTO_IPC_LOG_ERROR("error reply exceeds max message size"); - - // error message is to big, replace with a generic error - error->set_error_reason("Error message truncated"); - replySize = message.ByteSizeLong(); - } - - RIALTO_IPC_LOG_DEBUG("error{ serial %" PRIu64 " } - \"%s\"", serialId, reason.c_str()); - - // construct the message to send on the socket - auto msgBuf = m_sendBufPool.allocateShared(sizeof(msghdr) + sizeof(iovec) + replySize); - - auto *header = reinterpret_cast(msgBuf.get()); - bzero(header, sizeof(msghdr)); - - auto *iov = reinterpret_cast(msgBuf.get() + sizeof(msghdr)); - header->msg_iov = iov; - header->msg_iovlen = 1; - - auto *data = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + sizeof(iovec)); - iov->iov_base = data; - iov->iov_len = replySize; - - // serialise the reply to the message buffer - message.SerializeWithCachedSizesToArray(data); - - // std::reinterpret_pointer_cast is only implemented in C++17 and newer, so for - // now do it manually - return std::shared_ptr(msgBuf, reinterpret_cast(msgBuf.get())); -} - -// ----------------------------------------------------------------------------- -/*! - \threadsafe - - Returns \c true if the client with \a clientId is currently connected to - the server. - - */ -bool ServerImpl::isClientConnected(uint64_t clientId) const -{ - std::unique_lock locker(m_clientsLock); - return (m_clients.count(clientId) > 0); -} - -// ----------------------------------------------------------------------------- -/*! - \threadsafe - - May be called internally when there is an error on the socket, or externally - (possibly from a different thread) if the handler or service code decides to - close the client connection. - - */ -void ServerImpl::disconnectClient(uint64_t clientId) -{ - std::unique_lock locker(m_clientsLock); - m_condemnedClients.insert(clientId); - locker.unlock(); - - wakeEventLoop(); -} - -// ----------------------------------------------------------------------------- -/*! - \threadsafe - - Called via the IAVBusClient interface when an async event should be sent. - - This may be called from any thread, or from within the rpc message handler. - - The \a clientId is the client to send the event to. - - */ -bool ServerImpl::sendEvent(uint64_t clientId, const std::shared_ptr &eventMessage) -{ - // gets the file descriptors from the event message - const std::vector kFds = getResponseFileDescriptors(eventMessage.get()); - const size_t kRequiredCtrlLen = kFds.empty() ? 0 : CMSG_SPACE(sizeof(int) * kFds.size()); - - // create the base reply - transport::MessageFromServer message; - transport::EventFromServer *event = message.mutable_event(); - if (!event) - { - RIALTO_IPC_LOG_ERROR("failed to create mutable event object"); - return false; - } - - event->set_event_name(eventMessage->GetTypeName()); - - // convert the event to a data string - std::string respString = eventMessage->SerializeAsString(); - - // wrap in a transport response and send that - event->set_message(std::move(respString)); - - // check the reply will fit - size_t requiredDataLen = message.ByteSizeLong(); - if (requiredDataLen > m_kMaxMessageLen) - { - RIALTO_IPC_LOG_ERROR("event message to big to fit in buffer (size %zu, max size %zu)", requiredDataLen, - m_kMaxMessageLen); - return false; - } - - // build the socket message to send - auto msgBuf = - m_sendBufPool.allocateShared(sizeof(msghdr) + sizeof(iovec) + kRequiredCtrlLen + requiredDataLen); - - auto *header = reinterpret_cast(msgBuf.get()); - bzero(header, sizeof(msghdr)); - - auto *ctrl = reinterpret_cast(msgBuf.get() + sizeof(msghdr)); - header->msg_control = ctrl; - header->msg_controllen = kRequiredCtrlLen; - - auto *iov = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen); - header->msg_iov = iov; - header->msg_iovlen = 1; - - auto *data = reinterpret_cast(msgBuf.get() + sizeof(msghdr) + kRequiredCtrlLen + sizeof(iovec)); - iov->iov_base = data; - iov->iov_len = requiredDataLen; - - // copy in the data - message.SerializeWithCachedSizesToArray(data); - - // add the fds - if (!kFds.empty()) - { - struct cmsghdr *cmsg = CMSG_FIRSTHDR(header); - if (!cmsg) - { - RIALTO_IPC_LOG_ERROR("odd, failed to get the first cmsg header"); - return false; - } - - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - cmsg->cmsg_len = CMSG_LEN(sizeof(int) * kFds.size()); - memcpy(CMSG_DATA(cmsg), kFds.data(), sizeof(int) * kFds.size()); - header->msg_controllen = cmsg->cmsg_len; - } - - // finally, take the lock (so the socket is not closed beneath us) and send the reply - std::unique_lock locker(m_clientsLock); - - auto it = m_clients.find(clientId); - if (it == m_clients.end() || it->second.sock < 0) - { - RIALTO_IPC_LOG_WARN("socket closed before event could be sent"); - return false; - } - else if (TEMP_FAILURE_RETRY(sendmsg(it->second.sock, header, MSG_NOSIGNAL)) != static_cast(requiredDataLen)) - { - RIALTO_IPC_LOG_SYS_ERROR(errno, "failed to send the complete event message"); - return false; - } - - locker.unlock(); - - RIALTO_IPC_LOG_DEBUG("event{ %s } - { %s }", eventMessage->GetTypeName().c_str(), - eventMessage->ShortDebugString().c_str()); - - return true; -} -} // namespace firebolt::rialto::ipc diff --git a/middleware/rialto-client/ipc/server/source/IpcServerImpl.h b/middleware/rialto-client/ipc/server/source/IpcServerImpl.h deleted file mode 100644 index 591f2a80b..000000000 --- a/middleware/rialto-client/ipc/server/source/IpcServerImpl.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_IPC_IPC_SERVER_IMPL_H_ -#define FIREBOLT_RIALTO_IPC_IPC_SERVER_IMPL_H_ - -#include "FileDescriptor.h" -#include "IIpcServer.h" -#include "IIpcServerFactory.h" -#include "IpcServerControllerImpl.h" -#include "SimpleBufferPool.h" - -#include "rialtoipc-transport.pb.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(SCM_MAX_FD) -#define SCM_MAX_FD 255 -#endif - -namespace firebolt::rialto::ipc -{ -class ClientImpl; - -class ServerFactory : public IServerFactory -{ -public: - ServerFactory() = default; - ~ServerFactory() override = default; - - std::shared_ptr create() override; -}; - -class ServerImpl final : public ::firebolt::rialto::ipc::IServer, public std::enable_shared_from_this -{ -public: - explicit ServerImpl(); - ~ServerImpl() final; - -public: - bool addSocket(const std::string &socketPath, std::function &)> clientConnectedCb, - std::function &)> clientDisconnectedCb) override; - bool addSocket(int fd, std::function &)> clientConnectedCb, - std::function &)> clientDisconnectedCb) override; - - std::shared_ptr - addClient(int socketFd, std::function &)> clientDisconnectedCb) override; - - int fd() const override; - bool wait(int timeoutMSecs) override; - bool process() override; - -protected: - friend class ClientImpl; - bool sendEvent(uint64_t clientId, const std::shared_ptr &message); - bool isClientConnected(uint64_t clientId) const; - void disconnectClient(uint64_t clientId); - -private: - struct Socket; - static bool getSocketLock(Socket *socket); - static void closeListeningSocket(Socket *socket); - - void wakeEventLoop() const; - - void processNewConnection(uint64_t socketId); - - void processClientSocket(uint64_t clientId, unsigned events); - void processClientMessage(const std::shared_ptr &client, const uint8_t *data, size_t dataLen, - const std::vector &fds = {}); - - void processMethodCall(const std::shared_ptr &client, const transport::MethodCall &call, - const std::vector &fds); - - std::shared_ptr addClientSocket(int socketFd, const std::string &listeningSocketPath, - std::function &)> disconnectedCb); - - void sendReply(uint64_t clientId, const std::shared_ptr &msg); - - void sendErrorReply(const std::shared_ptr &client, uint64_t serialId, const char *format, ...) - __attribute__((format(printf, 4, 5))); - - void handleResponse(ServerControllerImpl *controller, google::protobuf::Message *response); - - std::shared_ptr populateReply(const std::shared_ptr &client, uint64_t serialId, - google::protobuf::Message *response); - std::shared_ptr populateErrorReply(const std::shared_ptr &client, uint64_t serialId, - const std::string &reason); - -private: - static const size_t m_kMaxMessageLen; - - int m_pollFd; - int m_wakeEventFd; - - std::atomic m_socketIdCounter; - std::atomic m_clientIdCounter; - - struct Socket - { - int sockFd = -1; - int lockFd = -1; - std::string sockPath; - std::string lockPath; - std::function &)> connectedCb; - std::function &)> disconnectedCb; - bool isOwned = true; - }; - - std::mutex m_socketsLock; - std::map m_sockets; - - struct ClientDetails - { - int sock = -1; - std::shared_ptr client; - std::function &)> disconnectedCb; - }; - - mutable std::mutex m_clientsLock; - - std::map m_clients; - std::set m_condemnedClients; - - uint8_t m_recvDataBuf[128 * 1024]; - uint8_t m_recvCtrlBuf[SCM_MAX_FD * sizeof(int)]; - - SimpleBufferPool m_sendBufPool; -}; - -} // namespace firebolt::rialto::ipc - -#endif // FIREBOLT_RIALTO_IPC_IPC_SERVER_IMPL_H_ diff --git a/middleware/rialto-client/logging/CMakeLists.txt b/middleware/rialto-client/logging/CMakeLists.txt deleted file mode 100644 index 2c0751238..000000000 --- a/middleware/rialto-client/logging/CMakeLists.txt +++ /dev/null @@ -1,53 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2025 Sky UK -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set(RialtoLogging_HEADERS - include/RialtoLogging.h - ) - -set(RialtoLogging_SOURCES - source/EnvVariableParser.cpp - source/EnvVariableParser.h - source/LogFileHandle.cpp - source/LogFileHandle.h - source/RialtoLogging.cpp - ) - -set(RialtoLogging_INCLUDES - "${CMAKE_CURRENT_SOURCE_DIR}/include" - ) - -add_library(RialtoLogging STATIC ${RialtoLogging_HEADERS} ${RialtoLogging_SOURCES}) -target_include_directories(RialtoLogging PUBLIC "$") -set_target_properties(RialtoLogging PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) -set_target_properties(RialtoLogging PROPERTIES POSITION_INDEPENDENT_CODE ON) - -find_package(EthanLog) -if (EthanLog_FOUND AND RIALTO_ENABLE_ETHAN_LOG) - message(STATUS "EthanLog is enabled") - add_library(RialtoEthanLog STATIC ${RialtoLogging_HEADERS} ${RialtoLogging_SOURCES}) - target_include_directories(RialtoEthanLog PUBLIC "$") - target_compile_definitions(RialtoEthanLog PRIVATE USE_ETHANLOG) - target_link_libraries(RialtoEthanLog PUBLIC EthanLog::EthanLog) - set_target_properties(RialtoEthanLog PROPERTIES CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON CXX_EXTENSIONS OFF) - set_target_properties(RialtoEthanLog PROPERTIES POSITION_INDEPENDENT_CODE ON) -else () - message(STATUS "EthanLog is disabled") - add_library(RialtoEthanLog ALIAS RialtoLogging) -endif () diff --git a/middleware/rialto-client/logging/include/RialtoLogging.h b/middleware/rialto-client/logging/include/RialtoLogging.h deleted file mode 100644 index ca97a228a..000000000 --- a/middleware/rialto-client/logging/include/RialtoLogging.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_LOGGING_RIALTO_LOGGING_H_ -#define FIREBOLT_RIALTO_LOGGING_RIALTO_LOGGING_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include -#include - - /** - * Defined log levels used to set the required output logs for the component - */ - enum RIALTO_DEBUG_LEVEL - { - RIALTO_DEBUG_LEVEL_FATAL = (1u << 0), - RIALTO_DEBUG_LEVEL_ERROR = (1u << 1), - RIALTO_DEBUG_LEVEL_WARNING = (1u << 2), - RIALTO_DEBUG_LEVEL_MILESTONE = (1u << 3), - RIALTO_DEBUG_LEVEL_INFO = (1u << 4), - RIALTO_DEBUG_LEVEL_DEBUG = (1u << 5), - RIALTO_DEBUG_LEVEL_EXTERNAL = - (1u << 6), // Level controlled by an external variable, like e.g. GST_DEBUG. Keep it as last level. - - RIALTO_DEBUG_LEVEL_DEFAULT = (RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING | - RIALTO_DEBUG_LEVEL_MILESTONE) - }; - - /** - * Possible components for logging. - */ - enum RIALTO_COMPONENT - { - RIALTO_COMPONENT_DEFAULT = 0u, - RIALTO_COMPONENT_CLIENT, - RIALTO_COMPONENT_SERVER, - RIALTO_COMPONENT_IPC, - RIALTO_COMPONENT_SERVER_MANAGER, - RIALTO_COMPONENT_COMMON, - RIALTO_COMPONENT_EXTERNAL, // External component, like e.g. GStreamer. Keep it as last component. - RIALTO_COMPONENT_LAST, - }; - - /** - * Utility functions used by the logging macros to produce the log output - */ - extern void rialtoLogVPrintf(enum RIALTO_COMPONENT component, enum RIALTO_DEBUG_LEVEL level, const char *file, - const char *func, int line, const char *fmt, va_list ap) - __attribute__((format(printf, 6, 0))); - extern void rialtoLogPrintf(enum RIALTO_COMPONENT component, enum RIALTO_DEBUG_LEVEL level, const char *file, - const char *func, int line, const char *fmt, ...) __attribute__((format(printf, 6, 7))); - extern void rialtoLogSysPrintf(enum RIALTO_COMPONENT component, int err, enum RIALTO_DEBUG_LEVEL level, - const char *file, const char *func, int line, const char *fmt, ...) - __attribute__((format(printf, 7, 8))); - - /** - * Macros to be used for logging - */ - -#ifdef RIALTO_LOG_FATAL_ENABLED -#define RIALTO_LOG_FATAL(component, fmt, args...) \ - do \ - { \ - rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_FATAL, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) - -#define RIALTO_LOG_SYS_FATAL(component, err, fmt, args...) \ - do \ - { \ - rialtoLogSysPrintf(component, err, RIALTO_DEBUG_LEVEL_FATAL, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) -#else -#define RIALTO_LOG_FATAL(component, fmt, args...) -#define RIALTO_LOG_SYS_FATAL(component, err, fmt, args...) -#endif - -#ifdef RIALTO_LOG_ERROR_ENABLED -#define RIALTO_LOG_ERROR(component, fmt, args...) \ - do \ - { \ - rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_ERROR, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) - -#define RIALTO_LOG_SYS_ERROR(component, err, fmt, args...) \ - do \ - { \ - rialtoLogSysPrintf(component, err, RIALTO_DEBUG_LEVEL_ERROR, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) -#else -#define RIALTO_LOG_ERROR(component, fmt, args...) -#define RIALTO_LOG_SYS_ERROR(component, err, fmt, args...) -#endif - -#ifdef RIALTO_LOG_WARN_ENABLED -#define RIALTO_LOG_WARN(component, fmt, args...) \ - do \ - { \ - rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_WARNING, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) -#define RIALTO_LOG_SYS_WARN(component, err, fmt, args...) \ - do \ - { \ - rialtoLogSysPrintf(component, err, RIALTO_DEBUG_LEVEL_WARNING, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) -#else -#define RIALTO_LOG_WARN(component, fmt, args...) -#define RIALTO_LOG_SYS_WARN(component, err, fmt, args...) -#endif - -#ifdef RIALTO_LOG_MIL_ENABLED -#define RIALTO_LOG_MIL(component, fmt, args...) \ - do \ - { \ - rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_MILESTONE, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) -#else -#define RIALTO_LOG_MIL(component, fmt, args...) -#endif - -#ifdef RIALTO_LOG_INFO_ENABLED -#define RIALTO_LOG_INFO(component, fmt, args...) \ - do \ - { \ - rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_INFO, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) -#else -#define RIALTO_LOG_INFO(component, fmt, args...) -#endif - -#ifdef RIALTO_LOG_DEBUG_ENABLED -#define RIALTO_LOG_DEBUG(component, fmt, args...) \ - do \ - { \ - rialtoLogPrintf(component, RIALTO_DEBUG_LEVEL_DEBUG, __FILE__, __FUNCTION__, __LINE__, fmt, ##args); \ - } while (false) -#else -#define RIALTO_LOG_DEBUG(component, fmt, args...) -#endif - -#define RIALTO_LOG_EXTERNAL(fmt, args...) \ - do \ - { \ - rialtoLogPrintf(RIALTO_COMPONENT_EXTERNAL, RIALTO_DEBUG_LEVEL_EXTERNAL, __FILE__, __FUNCTION__, __LINE__, fmt, \ - ##args); \ - } while (false) - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -#include - -namespace firebolt::rialto::logging -{ -/** - * Error Return Status. - */ -enum RialtoLoggingStatus : uint32_t -{ - RIALTO_LOGGING_STATUS_OK = 0u, - RIALTO_LOGGING_STATUS_ERROR, -}; - -/** - * @brief Set the logging levels required. - * - * See RIALTO_DEBUG_LEVEL_* for possible log levels. Multiple log levels can be set - * at once, for example: (RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR). - * Setting new log levels shall completely overwrite the previous log level set. - * @retval RIALTO_LOGGING_STATUS_OK on success. Note that if setLogHandler() has been - * called (for this component) with ignoreLogLevels==true then this will return - * RIALTO_LOGGING_STATUS_ERROR - * - * @param[in] logLevels : The levels of logging to set. - * @param[in] component : The component to set the log levels on. - */ -RialtoLoggingStatus setLogLevels(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL logLevels); - -/** - * @brief Get current logging levels. - * - * See RIALTO_DEBUG_LEVEL_* for possible log levels. - * If setLogHandler() has been called with ignoreLogLevels==true then this will return RIALTO_DEBUG_LEVEL_EXTERNAL - * - * @param[in] component : The component to get the log levels from. - */ -RIALTO_DEBUG_LEVEL getLogLevels(RIALTO_COMPONENT component); - -/** - * @brief Set the log handler used to process the logs. - * - * After requesting a logHandler then it can be cancelled by - * calling setLogHandler again with the handler passed as a nullptr - * - * @param[in] handler : The log handler. - * @param[in] component : The component to set the log handler on. - */ -using LogHandler = std::function; -RialtoLoggingStatus setLogHandler(RIALTO_COMPONENT component, LogHandler handler, bool ignoreLogLevels); - -/** - * @brief Checks if rialto logs to console. - * - * @retval: Returns true, if rialto is logging to console - */ -bool isConsoleLoggingEnabled(); - -} // namespace firebolt::rialto::logging - -#endif // defined(__cplusplus) - -#endif // FIREBOLT_RIALTO_LOGGING_RIALTO_LOGGING_H_ diff --git a/middleware/rialto-client/logging/source/EnvVariableParser.cpp b/middleware/rialto-client/logging/source/EnvVariableParser.cpp deleted file mode 100644 index 5ef89d89c..000000000 --- a/middleware/rialto-client/logging/source/EnvVariableParser.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "EnvVariableParser.h" -#include "LogFileHandle.h" -#include -#include -#include -#include - -namespace -{ -std::string getRialtoDebug() -{ - const char *kDebugVar = getenv("RIALTO_DEBUG"); - if (kDebugVar) - { - return std::string(kDebugVar); - } - return ""; -} - -std::string getRialtoConsoleLog() -{ - const char *kDebugVar = getenv("RIALTO_CONSOLE_LOG"); - if (kDebugVar) - { - return std::string(kDebugVar); - } - return ""; -} - -std::string getRialtoLogPath() -{ - const char *kLogPathEnvVar = getenv("RIALTO_LOG_PATH"); - if (kLogPathEnvVar) - { - return std::string(kLogPathEnvVar); - } - return ""; -} - -inline bool isNumber(const std::string &str) -{ - return std::find_if(str.begin(), str.end(), [](unsigned char c) { return !std::isdigit(c); }) == str.end(); -} - -std::vector split(std::string s, const std::string &delimiter) -{ - std::vector result; - size_t pos = 0; - while ((pos = s.find(delimiter)) != std::string::npos) - { - result.push_back(s.substr(0, pos)); - s.erase(0, pos + delimiter.length()); - } - result.push_back(s); - return result; -} - -std::map parseEnvVar(const std::string &envVar) -{ - std::map flagValues; - auto componentsWithLevels{split(envVar, ";")}; - for (const auto &item : componentsWithLevels) - { - auto componentWithLevel{split(item, ":")}; - if (componentWithLevel.size() != 2 || !isNumber(componentWithLevel[1])) - continue; - flagValues[componentWithLevel[0]] = std::stoi(componentWithLevel[1]); - } - return flagValues; -} - -RIALTO_DEBUG_LEVEL levelFromNumber(int level) -{ - switch (level) - { - case 0: - return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL); - case 1: - return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR); - case 2: - return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING); - case 3: - return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING | - RIALTO_DEBUG_LEVEL_MILESTONE); - case 4: - return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING | - RIALTO_DEBUG_LEVEL_MILESTONE | RIALTO_DEBUG_LEVEL_INFO); - case 5: - return RIALTO_DEBUG_LEVEL(RIALTO_DEBUG_LEVEL_FATAL | RIALTO_DEBUG_LEVEL_ERROR | RIALTO_DEBUG_LEVEL_WARNING | - RIALTO_DEBUG_LEVEL_MILESTONE | RIALTO_DEBUG_LEVEL_INFO | RIALTO_DEBUG_LEVEL_DEBUG); - } - return RIALTO_DEBUG_LEVEL_DEFAULT; -} - -RIALTO_COMPONENT componentFromStr(const std::string &component) -{ - if ("client" == component) - { - return RIALTO_COMPONENT_CLIENT; - } - if ("sessionserver" == component) - { - return RIALTO_COMPONENT_SERVER; - } - if ("ipc" == component) - { - return RIALTO_COMPONENT_IPC; - } - if ("servermanager" == component) - { - return RIALTO_COMPONENT_SERVER_MANAGER; - } - if ("common" == component) - { - return RIALTO_COMPONENT_COMMON; - } - return RIALTO_COMPONENT_LAST; -} -} // namespace - -namespace firebolt::rialto::logging -{ -EnvVariableParser::EnvVariableParser() - : m_debugLevels{{RIALTO_COMPONENT_CLIENT, RIALTO_DEBUG_LEVEL_DEFAULT}, - {RIALTO_COMPONENT_SERVER, RIALTO_DEBUG_LEVEL_DEFAULT}, - {RIALTO_COMPONENT_IPC, RIALTO_DEBUG_LEVEL_DEFAULT}, - {RIALTO_COMPONENT_SERVER_MANAGER, RIALTO_DEBUG_LEVEL_DEFAULT}, - {RIALTO_COMPONENT_COMMON, RIALTO_DEBUG_LEVEL_DEFAULT}}, - m_logToConsole{false}, m_logFilePath{getRialtoLogPath()} -{ - configureRialtoDebug(); - configureRialtoConsoleLog(); - configureFileLogging(); -} - -void EnvVariableParser::configureRialtoDebug() -{ - std::string debugFlagEnvVar = getRialtoDebug(); - if (debugFlagEnvVar.empty()) - return; - if (isNumber(debugFlagEnvVar)) - { - int level = std::stoi(debugFlagEnvVar); - for (auto &elem : m_debugLevels) - elem.second = levelFromNumber(level); - return; - } - auto flagValues{parseEnvVar(debugFlagEnvVar)}; - auto defaultFlagIter = flagValues.find("*"); - if (defaultFlagIter != flagValues.end()) - { - for (auto &elem : m_debugLevels) - elem.second = levelFromNumber(defaultFlagIter->second); - flagValues.erase(defaultFlagIter); - } - for (const auto &value : flagValues) - { - auto currentLevelIter = m_debugLevels.find(componentFromStr(value.first)); - if (currentLevelIter != m_debugLevels.end()) - { - currentLevelIter->second = levelFromNumber(value.second); - } - } -} - -void EnvVariableParser::configureRialtoConsoleLog() -{ - std::string debugFlagEnvVar = getRialtoConsoleLog(); - if (debugFlagEnvVar == "1") - { - m_logToConsole = true; - } -} - -void EnvVariableParser::configureFileLogging() -{ - if (isFileLoggingEnabled()) - { - LogFileHandle::instance().init(m_logFilePath); - } -} - -RIALTO_DEBUG_LEVEL EnvVariableParser::getLevel(const RIALTO_COMPONENT &component) const -{ - if (RIALTO_COMPONENT_EXTERNAL == component) - { - return RIALTO_DEBUG_LEVEL_EXTERNAL; - } - auto levelIter = m_debugLevels.find(component); - if (levelIter == m_debugLevels.end()) - return RIALTO_DEBUG_LEVEL_DEFAULT; - return levelIter->second; -} - -bool EnvVariableParser::isConsoleLoggingEnabled() const -{ - return m_logToConsole; -} - -bool EnvVariableParser::isFileLoggingEnabled() const -{ - return !m_logFilePath.empty(); -} -} // namespace firebolt::rialto::logging diff --git a/middleware/rialto-client/logging/source/EnvVariableParser.h b/middleware/rialto-client/logging/source/EnvVariableParser.h deleted file mode 100644 index 82e8fee50..000000000 --- a/middleware/rialto-client/logging/source/EnvVariableParser.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_LOGGING_ENV_VARIABLE_PARSER_H_ -#define FIREBOLT_RIALTO_LOGGING_ENV_VARIABLE_PARSER_H_ -#ifdef __cplusplus - -#include "RialtoLogging.h" -#include -#include - -namespace firebolt::rialto::logging -{ -class EnvVariableParser -{ -public: - EnvVariableParser(); - ~EnvVariableParser() = default; - EnvVariableParser(const EnvVariableParser &) = delete; - EnvVariableParser(EnvVariableParser &&) = delete; - EnvVariableParser &operator=(const EnvVariableParser &) = delete; - EnvVariableParser &operator=(EnvVariableParser &&) = delete; - - RIALTO_DEBUG_LEVEL getLevel(const RIALTO_COMPONENT &component) const; - bool isConsoleLoggingEnabled() const; - bool isFileLoggingEnabled() const; - -private: - void configureRialtoDebug(); - void configureRialtoConsoleLog(); - void configureFileLogging(); - -private: - std::map m_debugLevels; - bool m_logToConsole; - std::string m_logFilePath; -}; -} // namespace firebolt::rialto::logging - -#endif // defined(__cplusplus) -#endif // FIREBOLT_RIALTO_LOGGING_ENV_VARIABLE_PARSER_H_ diff --git a/middleware/rialto-client/logging/source/LogFileHandle.cpp b/middleware/rialto-client/logging/source/LogFileHandle.cpp deleted file mode 100644 index 0b6b7bf1d..000000000 --- a/middleware/rialto-client/logging/source/LogFileHandle.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "LogFileHandle.h" - -#include -#include - -namespace firebolt::rialto::logging -{ -LogFileHandle &LogFileHandle::instance() -{ - static LogFileHandle handle; - return handle; -} - -void LogFileHandle::init(const std::string &path) -{ - if (-1 == m_fd) - { - m_fd = open(path.c_str(), O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC, 0664); - } -} - -int LogFileHandle::fd() const -{ - return m_fd; -} - -bool LogFileHandle::isOpen() const -{ - return m_fd != -1; -} - -LogFileHandle::LogFileHandle() : m_fd{-1} {} - -LogFileHandle::~LogFileHandle() -{ - if (-1 != m_fd) - { - close(m_fd); - } -} -} // namespace firebolt::rialto::logging diff --git a/middleware/rialto-client/logging/source/LogFileHandle.h b/middleware/rialto-client/logging/source/LogFileHandle.h deleted file mode 100644 index e71deac29..000000000 --- a/middleware/rialto-client/logging/source/LogFileHandle.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_LOGGING_LOG_FILE_HANDLE_H_ -#define FIREBOLT_RIALTO_LOGGING_LOG_FILE_HANDLE_H_ -#ifdef __cplusplus - -#include - -namespace firebolt::rialto::logging -{ -class LogFileHandle -{ -public: - static LogFileHandle &instance(); - void init(const std::string &path); - int fd() const; - bool isOpen() const; - -private: - LogFileHandle(); - ~LogFileHandle(); - -private: - int m_fd; -}; -} // namespace firebolt::rialto::logging - -#endif // defined(__cplusplus) -#endif // FIREBOLT_RIALTO_LOGGING_LOG_FILE_HANDLE_H_ diff --git a/middleware/rialto-client/logging/source/RialtoLogging.cpp b/middleware/rialto-client/logging/source/RialtoLogging.cpp deleted file mode 100644 index 099599a69..000000000 --- a/middleware/rialto-client/logging/source/RialtoLogging.cpp +++ /dev/null @@ -1,413 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 Sky UK - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "EnvVariableParser.h" -#include "LogFileHandle.h" -#include "RialtoLogging.h" - -#ifdef USE_ETHANLOG - -#include - -#define SYSTEM_LOG_FATAL(filename, function, line, ...) ethanlog(ETHAN_LOG_FATAL, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_ERROR(filename, function, line, ...) ethanlog(ETHAN_LOG_ERROR, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_WARN(filename, function, line, ...) \ - ethanlog(ETHAN_LOG_WARNING, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_MIL(filename, function, line, ...) \ - ethanlog(ETHAN_LOG_MILESTONE, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_INFO(filename, function, line, ...) ethanlog(ETHAN_LOG_INFO, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_DEBUG(filename, function, line, ...) ethanlog(ETHAN_LOG_DEBUG, filename, function, line, __VA_ARGS__) - -#else - -#include - -#define SYSTEM_LOG_FATAL(filename, function, line, ...) syslog(LOG_CRIT, __VA_ARGS__) -#define SYSTEM_LOG_ERROR(filename, function, line, ...) syslog(LOG_ERR, __VA_ARGS__) -#define SYSTEM_LOG_WARN(filename, function, line, ...) syslog(LOG_WARNING, __VA_ARGS__) -#define SYSTEM_LOG_MIL(filename, function, line, ...) syslog(LOG_NOTICE, __VA_ARGS__) -#define SYSTEM_LOG_INFO(filename, function, line, ...) syslog(LOG_INFO, __VA_ARGS__) -#define SYSTEM_LOG_DEBUG(filename, function, line, ...) syslog(LOG_DEBUG, __VA_ARGS__) - -#endif - -namespace -{ -/** - * Log levels for each component. By default will print all fatals, errors, warnings & milestones. - */ -std::atomic g_rialtoLogLevels[RIALTO_COMPONENT_LAST] = {}; - -/** - * Default Log levels defined by RIALTO_DEBUG environment variable - */ -const firebolt::rialto::logging::EnvVariableParser g_envVariableParser; - -/** - * Log handler for each component. By default will use journaldLogHandler. - */ -void fdLogHandler(int fd, RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, - const char *function, const char *message, size_t messageLen); -void journaldLogHandler(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, - const char *function, const char *message, size_t messageLen); - -firebolt::rialto::logging::LogHandler g_logHandler[RIALTO_COMPONENT_LAST] = {}; -bool g_ignoreLogLevels[RIALTO_COMPONENT_LAST] = {}; -std::mutex g_logHandlerMutex; - -std::string componentToString(RIALTO_COMPONENT component); -std::string levelToString(RIALTO_DEBUG_LEVEL level); - -std::string componentToString(RIALTO_COMPONENT component) -{ - switch (component) - { - case RIALTO_COMPONENT_DEFAULT: - return "DEF"; - break; - case RIALTO_COMPONENT_CLIENT: - return "CLI"; - break; - case RIALTO_COMPONENT_SERVER: - return "SRV"; - break; - case RIALTO_COMPONENT_IPC: - return "IPC"; - break; - case RIALTO_COMPONENT_SERVER_MANAGER: - return "SMG"; - break; - case RIALTO_COMPONENT_COMMON: - return "COM"; - break; - case RIALTO_COMPONENT_EXTERNAL: - return "EXT"; - break; - default: - return "UNK"; - break; - } -} - -std::string levelToString(RIALTO_DEBUG_LEVEL level) -{ - switch (level) - { - case RIALTO_DEBUG_LEVEL_FATAL: - return "FTL"; - break; - case RIALTO_DEBUG_LEVEL_ERROR: - return "ERR"; - break; - case RIALTO_DEBUG_LEVEL_WARNING: - return "WRN"; - break; - case RIALTO_DEBUG_LEVEL_MILESTONE: - return "MIL"; - break; - case RIALTO_DEBUG_LEVEL_INFO: - return "NFO"; - break; - case RIALTO_DEBUG_LEVEL_DEBUG: - return "DBG"; - break; - case RIALTO_DEBUG_LEVEL_EXTERNAL: - return "EXT"; - break; - default: - return ":"; - break; - } -} - -/** - * File descriptor logging function for the library. - */ -void fdLogHandler(int fd, RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, - const char *function, const char *message, size_t messageLen) -{ - timespec ts = {0, 0}; - clock_gettime(CLOCK_MONOTONIC, &ts); - struct iovec iov[6]; - char tbuf[32]; - - iov[0].iov_base = tbuf; - iov[0].iov_len = snprintf(tbuf, sizeof(tbuf), "%.010lu.%.06lu ", ts.tv_sec, ts.tv_nsec / 1000); - iov[0].iov_len = std::min(iov[0].iov_len, sizeof(tbuf)); - - char lbuf[8]; - iov[1].iov_base = reinterpret_cast(lbuf); - iov[1].iov_len = - std::min(static_cast(snprintf(lbuf, sizeof(lbuf), "%s: ", levelToString(level).c_str())), sizeof(lbuf)); - - char cbuf[8]; - iov[2].iov_base = reinterpret_cast(cbuf); - iov[2].iov_len = - std::min(static_cast(snprintf(cbuf, sizeof(cbuf), "%s: ", componentToString(component).c_str())), - sizeof(cbuf)); - - static thread_local pid_t threadId = 0; - if (threadId <= 0) - threadId = syscall(SYS_gettid); - char fbuf[180]; - iov[3].iov_base = reinterpret_cast(fbuf); - - if (RIALTO_DEBUG_LEVEL_EXTERNAL == level) - { - iov[3].iov_len = snprintf(fbuf, sizeof(fbuf), "< T:%d >", threadId); - } - else if (!file || !function || (line <= 0)) - { - iov[3].iov_len = snprintf(fbuf, sizeof(fbuf), "< T:%d M:? F:? L:? > ", threadId); - } - else - { - iov[3].iov_len = - snprintf(fbuf, sizeof(fbuf), "< T:%d M:%.*s F:%.*s L:%d > ", threadId, 64, file, 64, function, line); - } - iov[3].iov_len = std::min(iov[3].iov_len, sizeof(fbuf)); - iov[4].iov_base = const_cast(reinterpret_cast(message)); - iov[4].iov_len = messageLen; - iov[5].iov_base = const_cast(reinterpret_cast("\n")); - iov[5].iov_len = 1; - // TODO(RIALTO-38): consider using standard write(2) and handle EINTR properly. - std::ignore = writev(fd, iov, 6); -} -/** - * Journald logging function for the library. - */ -void journaldLogHandler(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, - const char *function, const char *message, size_t messageLen) -{ - static thread_local pid_t threadId = 0; - if (threadId <= 0) - threadId = syscall(SYS_gettid); - char fbuf[180]; - if (RIALTO_DEBUG_LEVEL_EXTERNAL == level) - { - snprintf(fbuf, sizeof(fbuf), "%s: %s: < T:%d >", levelToString(level).c_str(), - componentToString(component).c_str(), threadId); - } - else if (!file || !function || (line <= 0)) - { - snprintf(fbuf, sizeof(fbuf), "%s: %s: < T:%d M:? F:? L:? >", levelToString(level).c_str(), - componentToString(component).c_str(), threadId); - } - else - { - snprintf(fbuf, sizeof(fbuf), "%s: %s: < T:%d M:%.*s F:%.*s L:%d >", levelToString(level).c_str(), - componentToString(component).c_str(), threadId, 64, file, 64, function, line); - } - - switch (level) - { - case RIALTO_DEBUG_LEVEL_FATAL: - SYSTEM_LOG_FATAL(file, function, line, "%s %s", fbuf, message); - break; - case RIALTO_DEBUG_LEVEL_ERROR: - SYSTEM_LOG_ERROR(file, function, line, "%s %s", fbuf, message); - break; - case RIALTO_DEBUG_LEVEL_WARNING: - SYSTEM_LOG_WARN(file, function, line, "%s %s", fbuf, message); - break; - case RIALTO_DEBUG_LEVEL_MILESTONE: - SYSTEM_LOG_MIL(file, function, line, "%s %s", fbuf, message); - break; - case RIALTO_DEBUG_LEVEL_INFO: - SYSTEM_LOG_INFO(file, function, line, "%s %s", fbuf, message); - break; - case RIALTO_DEBUG_LEVEL_DEBUG: - SYSTEM_LOG_DEBUG(file, function, line, "%s %s", fbuf, message); - break; - case RIALTO_DEBUG_LEVEL_EXTERNAL: - SYSTEM_LOG_INFO(file, function, line, "%s %s", fbuf, message); - break; - default: - break; - } -} - -void rialtoLog(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, const char *func, int line, - const char *fmt, va_list ap, const char *append) -{ - /* Must be valid component */ - if (component >= RIALTO_COMPONENT_LAST) - return; - - /* If log levels have not been set, set to Default */ - if (!g_rialtoLogLevels[component]) - g_rialtoLogLevels[component] = g_envVariableParser.getLevel(component); - - if (!(level & g_rialtoLogLevels[component]) && !g_ignoreLogLevels[component]) - return; - char mbuf[512]; - int len; - len = vsnprintf(mbuf, sizeof(mbuf), fmt, ap); - if (len < 1) - return; - if (len > static_cast(sizeof(mbuf) - 1)) - len = sizeof(mbuf) - 1; - if (mbuf[len - 1] == '\n') - len--; - mbuf[len] = '\0'; - if (append && (len < static_cast(sizeof(mbuf) - 1))) - { - size_t extra = std::min(strlen(append), (sizeof(mbuf) - len - 1)); - memcpy(mbuf + len, append, extra); - len += static_cast(extra); - mbuf[len] = '\0'; - } - const char *kFname = nullptr; - if (file) - { - if ((kFname = strrchr(file, '/')) == nullptr) - kFname = file; - else - kFname++; - } - - const auto &kLogFileHandle = firebolt::rialto::logging::LogFileHandle::instance(); - /* If log handler had not been set, use default */ - firebolt::rialto::logging::LogHandler logHandler = g_logHandler[component]; // local copy for thread safety - if (logHandler) - { - logHandler(level, kFname, line, func, mbuf, len); - } - else if (g_envVariableParser.isFileLoggingEnabled() && kLogFileHandle.isOpen()) - { - fdLogHandler(kLogFileHandle.fd(), component, level, kFname, line, func, mbuf, len); - } - else if (g_envVariableParser.isConsoleLoggingEnabled()) - { - fdLogHandler(STDERR_FILENO, component, level, kFname, line, func, mbuf, len); - } - else - { - journaldLogHandler(component, level, kFname, line, func, mbuf, len); - } -} - -} // namespace - -void rialtoLogVPrintf(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, const char *func, - int line, const char *fmt, va_list ap) -{ - rialtoLog(component, level, file, func, line, fmt, ap, nullptr); -} - -void rialtoLogPrintf(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, const char *func, int line, - const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - rialtoLog(component, level, file, func, line, fmt, ap, nullptr); - va_end(ap); -} - -void rialtoLogSysPrintf(RIALTO_COMPONENT component, int err, RIALTO_DEBUG_LEVEL level, const char *file, - const char *func, int line, const char *fmt, ...) -{ - va_list ap; - const char *kErrmsg{nullptr}; - char appendbuf[96]; - const char *kAppend = nullptr; -#if defined(__linux__) - char errbuf[64]; - kErrmsg = strerror_r(err, errbuf, sizeof(errbuf)); -#elif defined(__APPLE__) - char errbuf[64]; - if (strerror_r(err, errbuf, sizeof(errbuf)) != 0) - kErrmsg = "Unknown error"; - else - kErrmsg = errbuf; -#endif - if (kErrmsg) - { - snprintf(appendbuf, sizeof(appendbuf), " (%d - %s)", err, kErrmsg); - appendbuf[sizeof(appendbuf) - 1] = '\0'; - kAppend = appendbuf; - } - va_start(ap, fmt); - rialtoLog(component, level, file, func, line, fmt, ap, kAppend); - va_end(ap); -} - -namespace firebolt::rialto::logging -{ -RialtoLoggingStatus setLogLevels(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL logLevels) -{ - RialtoLoggingStatus status = RIALTO_LOGGING_STATUS_ERROR; - if (component < RIALTO_COMPONENT_LAST && !g_ignoreLogLevels[component]) - { - g_rialtoLogLevels[component] = logLevels; - status = RIALTO_LOGGING_STATUS_OK; - } - - return status; -} - -RIALTO_DEBUG_LEVEL getLogLevels(RIALTO_COMPONENT component) -{ - if (component < RIALTO_COMPONENT_LAST) - { - if (g_ignoreLogLevels[component]) - return RIALTO_DEBUG_LEVEL_EXTERNAL; - - if (!g_rialtoLogLevels[component]) - g_rialtoLogLevels[component] = g_envVariableParser.getLevel(component); - return g_rialtoLogLevels[component]; - } - return RIALTO_DEBUG_LEVEL_DEFAULT; -} - -RialtoLoggingStatus setLogHandler(RIALTO_COMPONENT component, LogHandler handler, bool ignoreLogLevels) -{ - RialtoLoggingStatus status = RIALTO_LOGGING_STATUS_ERROR; - if (component < RIALTO_COMPONENT_LAST) - { - std::unique_lock lock{g_logHandlerMutex}; - - g_logHandler[component] = std::move(handler); - - // Ignoring log levels is only an option if we're registering - // a non-null log handler - g_ignoreLogLevels[component] = (g_logHandler[component]) ? ignoreLogLevels : false; - - status = RIALTO_LOGGING_STATUS_OK; - } - - return status; -} - -bool isConsoleLoggingEnabled() -{ - return g_envVariableParser.isConsoleLoggingEnabled(); -} - -} // namespace firebolt::rialto::logging diff --git a/middleware/rialto-client/media/CMakeLists.txt b/middleware/rialto-client/media/CMakeLists.txt deleted file mode 100644 index 31389dcea..000000000 --- a/middleware/rialto-client/media/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -add_subdirectory(public) -add_subdirectory(common) -add_subdirectory(client) - -if( ENABLE_SERVER ) - add_subdirectory(server) -endif() diff --git a/middleware/rialto-client/media/client/CMakeLists.txt b/middleware/rialto-client/media/client/CMakeLists.txt deleted file mode 100644 index cc906105c..000000000 --- a/middleware/rialto-client/media/client/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -add_subdirectory(main) -add_subdirectory(ipc) -add_subdirectory(common) diff --git a/middleware/rialto-client/media/client/common/CMakeLists.txt b/middleware/rialto-client/media/client/common/CMakeLists.txt deleted file mode 100644 index 7664f6a17..000000000 --- a/middleware/rialto-client/media/client/common/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -add_library( - RialtoClientCommon - INTERFACE - ) - -target_include_directories( - RialtoClientCommon - - INTERFACE - include - ) diff --git a/middleware/rialto-client/media/client/common/include/RialtoClientLogging.h b/middleware/rialto-client/media/client/common/include/RialtoClientLogging.h deleted file mode 100644 index 0bdb87d57..000000000 --- a/middleware/rialto-client/media/client/common/include/RialtoClientLogging.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef RIALTO_CLIENT_LOGGING_H_ -#define RIALTO_CLIENT_LOGGING_H_ - -#include "RialtoLogging.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define RIALTO_CLIENT_LOG_FATAL(fmt, args...) RIALTO_LOG_FATAL(RIALTO_COMPONENT_CLIENT, fmt, ##args) -#define RIALTO_CLIENT_LOG_SYS_FATAL(err, fmt, args...) RIALTO_LOG_SYS_FATAL(RIALTO_COMPONENT_CLIENT, err, fmt, ##args) -#define RIALTO_CLIENT_LOG_ERROR(fmt, args...) RIALTO_LOG_ERROR(RIALTO_COMPONENT_CLIENT, fmt, ##args) -#define RIALTO_CLIENT_LOG_SYS_ERROR(err, fmt, args...) RIALTO_LOG_SYS_ERROR(RIALTO_COMPONENT_CLIENT, err, fmt, ##args) -#define RIALTO_CLIENT_LOG_WARN(fmt, args...) RIALTO_LOG_WARN(RIALTO_COMPONENT_CLIENT, fmt, ##args) -#define RIALTO_CLIENT_LOG_SYS_WARN(err, fmt, args...) RIALTO_LOG_SYS_WARN(RIALTO_COMPONENT_CLIENT, err, fmt, ##args) -#define RIALTO_CLIENT_LOG_MIL(fmt, args...) RIALTO_LOG_MIL(RIALTO_COMPONENT_CLIENT, fmt, ##args) -#define RIALTO_CLIENT_LOG_INFO(fmt, args...) RIALTO_LOG_INFO(RIALTO_COMPONENT_CLIENT, fmt, ##args) -#define RIALTO_CLIENT_LOG_DEBUG(fmt, args...) RIALTO_LOG_DEBUG(RIALTO_COMPONENT_CLIENT, fmt, ##args) - -#ifdef __cplusplus -} -#endif - -#endif // RIALTO_CLIENT_LOGGING_H_ diff --git a/middleware/rialto-client/media/client/ipc/CMakeLists.txt b/middleware/rialto-client/media/client/ipc/CMakeLists.txt deleted file mode 100644 index 8df436d3a..000000000 --- a/middleware/rialto-client/media/client/ipc/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Find includes in corresponding build directories -set( CMAKE_INCLUDE_CURRENT_DIR ON ) - -add_library ( - RialtoClientIpcImpl - STATIC - - source/IpcClient.cpp - source/IpcModule.cpp - source/MediaPipelineIpc.cpp - source/MediaPipelineCapabilitiesIpc.cpp - source/ControlIpc.cpp - source/MediaKeysIpc.cpp - source/MediaKeysCapabilitiesIpc.cpp - source/RialtoCommonIpc.cpp - source/WebAudioPlayerIpc.cpp -) - -set_property ( - TARGET - RialtoClientIpcImpl - PROPERTY POSITION_INDEPENDENT_CODE ON -) - -target_include_directories ( - RialtoClientIpcImpl - - PUBLIC - interface - - PRIVATE - include - $ - $ - $ - $ - $ - $ -) - -target_link_libraries ( - RialtoClientIpcImpl - - PRIVATE - RialtoIpcClient - RialtoIpcCommon - RialtoCommon - RialtoPlayerCommon - RialtoEthanLog - RialtoProtobuf -) diff --git a/middleware/rialto-client/media/client/ipc/include/ControlIpc.h b/middleware/rialto-client/media/client/ipc/include/ControlIpc.h deleted file mode 100644 index 01093dd9b..000000000 --- a/middleware/rialto-client/media/client/ipc/include/ControlIpc.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_CONTROL_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_CONTROL_IPC_H_ - -#include "IConnectionObserver.h" -#include "IControlClient.h" -#include "IControlIpc.h" -#include "IEventThread.h" -#include "IpcModule.h" -#include - -#include "controlmodule.pb.h" - -namespace firebolt::rialto::client -{ -class ControlIpc; - -/** - * @brief IControlIpc factory class definition. - */ -class ControlIpcFactory : public IControlIpcFactory -{ -public: - ControlIpcFactory() = default; - ~ControlIpcFactory() override = default; - - std::shared_ptr createControlIpc(IControlClient *controlClient) override; - - /** - * @brief Create the generic control factory object. - * - * @retval the generic control factory instance or null on error. - */ - static std::shared_ptr createFactory(); -}; - -/** - * @brief The definition of the ControlIpc. - */ -class ControlIpc : public IControlIpc, public IpcModule, public IConnectionObserver -{ -public: - /** - * @brief The constructor. - */ - ControlIpc(IControlClient *controlClient, IIpcClient &ipcClient, - const std::shared_ptr &eventThreadFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~ControlIpc(); - - bool getSharedMemory(int32_t &fd, uint32_t &size) override; - bool registerClient() override; - -private: - bool createRpcStubs(const std::shared_ptr &ipcChannel) override; - bool subscribeToEvents(const std::shared_ptr &ipcChannel) override; - void onConnectionBroken() override; - - /** - * @brief Handler for a application state update from the server. - * - * @param[in] event : The app state changed event structure. - */ - void onApplicationStateUpdated(const std::shared_ptr &event); - - /** - * @brief Handler for a ping from the server. - * - * @param[in] event : The ping event structure. - */ - void onPing(const std::shared_ptr &event); - -private: - /** - * @brief Control client for handling messages from server - */ - IControlClient *m_controlClient; - - /** - * @brief The control handle for the current instance. - */ - std::atomic m_controlHandle; - - /** - * @brief Thread for handling media player events from the server. - */ - std::unique_ptr m_eventThread; - - /** - * @brief RPC stubs for the Control APIs. - */ - std::shared_ptr<::firebolt::rialto::ControlModule_Stub> m_controlStub; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_CONTROL_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/IConnectionObserver.h b/middleware/rialto-client/media/client/ipc/include/IConnectionObserver.h deleted file mode 100644 index 2857707fb..000000000 --- a/middleware/rialto-client/media/client/ipc/include/IConnectionObserver.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_CONNECTION_OBSERVER_H_ -#define FIREBOLT_RIALTO_CLIENT_I_CONNECTION_OBSERVER_H_ - -#include "ControlCommon.h" - -namespace firebolt::rialto::client -{ -class IConnectionObserver -{ -public: - virtual ~IConnectionObserver() = default; - virtual void onConnectionBroken() = 0; -}; -} // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_CONNECTION_OBSERVER_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/IIpcClient.h b/middleware/rialto-client/media/client/ipc/include/IIpcClient.h deleted file mode 100644 index 8455d4a6d..000000000 --- a/middleware/rialto-client/media/client/ipc/include/IIpcClient.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_IPC_CLIENT_H_ -#define FIREBOLT_RIALTO_CLIENT_I_IPC_CLIENT_H_ - -#include -#include -#include -#include - -#include -#include -#include - -#include "IConnectionObserver.h" - -namespace firebolt::rialto::client -{ -class IIpcClient; - -/** - * @brief IIpcClient accessor class definition. - */ -class IIpcClientAccessor -{ -public: - virtual ~IIpcClientAccessor() = default; - IIpcClientAccessor(const IIpcClientAccessor &) = delete; - IIpcClientAccessor &operator=(const IIpcClientAccessor &) = delete; - IIpcClientAccessor(IIpcClientAccessor &&) = delete; - IIpcClientAccessor &operator=(IIpcClientAccessor &&) = delete; - - /** - * @brief Get a IControlIpcAccessor instance. - * - * @retval the accessor instance - */ - static IIpcClientAccessor &instance(); - - /** - * @brief Get IpcClient object. - * - * @retval the reference to IpcClient singleton object - */ - virtual IIpcClient &getIpcClient() const = 0; - -protected: - IIpcClientAccessor() = default; -}; - -/** - * @brief The definition of the IIpcClient interface. - * - * This interface defines the control ipc APIs that are used to communicate with the Rialto server. - */ -class IIpcClient -{ -public: - IIpcClient() = default; - virtual ~IIpcClient() = default; - - IIpcClient(const IIpcClient &) = delete; - IIpcClient &operator=(const IIpcClient &) = delete; - IIpcClient(IIpcClient &&) = delete; - IIpcClient &operator=(IIpcClient &&) = delete; - - /** - * @brief Gets a weak ptr to the Ipc channel created by the IpcClient. - * - * @retval the ipc channel weak ptr. - */ - virtual std::weak_ptr getChannel() const = 0; - - /** - * @brief Create the blocking closure to be passed to the RPC stubs. - * - * @retval the blocking closure or null on error. - */ - virtual std::shared_ptr createBlockingClosure() = 0; - - /** - * @brief Create the rpc controller to be passed to the RPC stubs. - * - * @retval the rpc controller or null on error. - */ - virtual std::shared_ptr createRpcController() = 0; - - /** - * @brief Reconnect channel. - * - * @retval true on success. - */ - virtual bool reconnect() = 0; - - /** - * @brief Registers new connection observer. - */ - virtual void registerConnectionObserver(const std::weak_ptr &observer) = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_IPC_CLIENT_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/IpcClient.h b/middleware/rialto-client/media/client/ipc/include/IpcClient.h deleted file mode 100644 index d6a8da658..000000000 --- a/middleware/rialto-client/media/client/ipc/include/IpcClient.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_IPC_CLIENT_H_ -#define FIREBOLT_RIALTO_CLIENT_IPC_CLIENT_H_ - -#include "IIpcClient.h" -#include -#include - -namespace firebolt::rialto::client -{ -class IpcClientAccessor : public IIpcClientAccessor -{ -public: - ~IpcClientAccessor() override = default; - IIpcClient &getIpcClient() const override; -}; - -/** - * @brief The definition of the IpcClient. - */ -class IpcClient : public IIpcClient -{ -public: - /** - * @brief The constructor. - */ - IpcClient(const std::shared_ptr &ipcChannelFactory, - const std::shared_ptr &ipcControllerFactory, - const std::shared_ptr &blockingClosureFactory); - - /** - * @brief Virtual destructor. - */ - ~IpcClient() override; - - std::weak_ptr getChannel() const override; - - std::shared_ptr createBlockingClosure() override; - - std::shared_ptr createRpcController() override; - - bool reconnect() override; - - void registerConnectionObserver(const std::weak_ptr &observer) override; - -protected: - /** - * @brief The ipc thread. - */ - std::thread m_ipcThread; - - /** - * @brief The connected ipc communication channel. - */ - std::shared_ptr m_ipcChannel; - - /** - * @brief Factory for creating the ipc controllers. - */ - std::shared_ptr m_ipcControllerFactory; - - /** - * @brief Factory for creating a connected ipc channel. - */ - std::shared_ptr m_ipcChannelFactory; - - /** - * @brief Factory for creating a blocking closure. - */ - std::shared_ptr m_blockingClosureFactory; - - /** - * @brief Whether disconnection of ipc has been requested by the client and is ongoing. - */ - std::atomic m_disconnecting; - - /** - * @brief Current connection status observer - */ - std::weak_ptr m_connectionObserver; - - /** - * @brief The processing loop for the ipc thread. - */ - void processIpcThread(); - - /** - * @brief Establish connection between Rialto Server and Rialto Client - */ - bool connect(); - - /** - * @brief Close connection between Rialto Server and Rialto Client - */ - bool disconnect(); -}; -} // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_IPC_CLIENT_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/IpcModule.h b/middleware/rialto-client/media/client/ipc/include/IpcModule.h deleted file mode 100644 index 5af617089..000000000 --- a/middleware/rialto-client/media/client/ipc/include/IpcModule.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_IPC_MODULE_H_ -#define FIREBOLT_RIALTO_CLIENT_IPC_MODULE_H_ - -#include "IIpcClient.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::client -{ -/** - * @brief The implementation of a IpcModule. - * - * This class defines common Ipc APIs for Ipc modules. - */ -class IpcModule -{ -public: - /** - * @brief The constructor. - * - * @param[in] ipcClient : The ipc client - */ - explicit IpcModule(IIpcClient &ipcClient); - - /** - * @brief Virtual destructor. - */ - virtual ~IpcModule(); - -protected: - /** - * @brief The ipc client singleton object. - */ - IIpcClient &m_ipc; - - /** - * @brief The ipc communication channel. - */ - std::weak_ptr m_ipcChannel; - - /** - * @brief Subscribed event tags. - */ - std::vector m_eventTags; - - /** - * @brief Create the Rpc stubs for the derived object. - * - * @param[in] ipcChannel : The ipc channel - * - * @retval true if the rpc stubs are created successfully, false otherwise. - */ - virtual bool createRpcStubs(const std::shared_ptr &ipcChannel) = 0; - - /** - * @brief Subscribes to the Ipc events for the derived object. - * - * @param[in] ipcChannel : The ipc channel - * - * @retval true if the events are subscribed successfully, false otherwise. - */ - virtual bool subscribeToEvents(const std::shared_ptr &ipcChannel) = 0; - - /** - * @brief Unsubscribes to all Ipc events. - * - * @param[in] ipcChannel : The ipc channel - * - * @retval true if the events are unsubscribed successfully, false otherwise. - */ - bool unsubscribeFromAllEvents(const std::shared_ptr &ipcChannel); - - /** - * @brief Attach the connected ipc client channel to the MediaKeysIpc object. - * - * @retval true if the channel attached successfully, false otherwise. - */ - bool attachChannel(); - - /** - * @brief Detach the ipc client channel from the MediaKeysIpc object. - */ - void detachChannel(); - - /** - * @brief If the channel is disconnected, this method will reattach the channel. - * - * @retval true if channel now connected, false otherwise. - */ - bool reattachChannelIfRequired(); - -private: - /** - * @brief Get connected IPC Channel - * - * @retval Ipc Channel if connected, nullptr otherwise - */ - std::shared_ptr getConnectedChannel(); -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_IPC_MODULE_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/MediaKeysCapabilitiesIpc.h b/middleware/rialto-client/media/client/ipc/include/MediaKeysCapabilitiesIpc.h deleted file mode 100644 index 93ef65e44..000000000 --- a/middleware/rialto-client/media/client/ipc/include/MediaKeysCapabilitiesIpc.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_IPC_H_ - -#include "IEventThread.h" -#include "IMediaKeysCapabilitiesIpcFactory.h" -#include "IpcModule.h" -#include -#include -#include -#include - -#include "mediakeyscapabilitiesmodule.pb.h" - -namespace firebolt::rialto::client -{ -/** - * @brief IMediaKeysCapabilitiesIpc factory class definition. - */ -class MediaKeysCapabilitiesIpcFactory : public IMediaKeysCapabilitiesIpcFactory -{ -public: - MediaKeysCapabilitiesIpcFactory() = default; - ~MediaKeysCapabilitiesIpcFactory() override = default; - - /** - * @brief Weak pointer to the singleton object. - */ - static std::weak_ptr m_mediaKeysCapabilitiesIpc; - - /** - * @brief Mutex protection for creation of the MediaKeysCapabilitiesIpc object. - */ - static std::mutex m_creationMutex; - - std::shared_ptr getMediaKeysCapabilitiesIpc() const override; -}; - -/** - * @brief The definition of the MediaKeysCapabilitiesIpc. - */ -class MediaKeysCapabilitiesIpc : public IMediaKeysCapabilities, public IpcModule -{ -public: - /** - * @brief The constructor. - * - * @param[in] ipcClient : The ipc client - */ - explicit MediaKeysCapabilitiesIpc(IIpcClient &ipcClientFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaKeysCapabilitiesIpc(); - - std::vector getSupportedKeySystems() override; - - bool supportsKeySystem(const std::string &keySystem) override; - - bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) override; - - bool isServerCertificateSupported(const std::string &keySystem) override; - -private: - /** - * @brief The ipc protobuf media keys capabilities stub. - */ - std::unique_ptr<::firebolt::rialto::MediaKeysCapabilitiesModule_Stub> m_mediaKeysCapabilitiesStub; - - bool createRpcStubs(const std::shared_ptr &ipcChannel) override; - - bool subscribeToEvents(const std::shared_ptr &ipcChannel) override { return true; } -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/MediaKeysIpc.h b/middleware/rialto-client/media/client/ipc/include/MediaKeysIpc.h deleted file mode 100644 index 0ecf5c744..000000000 --- a/middleware/rialto-client/media/client/ipc/include/MediaKeysIpc.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_IPC_H_ - -#include "IEventThread.h" -#include "IMediaKeysClient.h" -#include "IMediaKeysIpcFactory.h" -#include "IpcModule.h" -#include -#include -#include - -#include "mediakeysmodule.pb.h" - -namespace firebolt::rialto::client -{ -/** - * @brief IMediaKeysIpc factory class definition. - */ -class MediaKeysIpcFactory : public IMediaKeysIpcFactory -{ -public: - MediaKeysIpcFactory() = default; - ~MediaKeysIpcFactory() override = default; - - std::unique_ptr createMediaKeysIpc(const std::string &keySystem) const override; -}; - -/** - * @brief The definition of the MediaKeysIpc. - */ -class MediaKeysIpc : public IMediaKeys, public IpcModule -{ -public: - /** - * @brief The constructor. - * - * @param[in] keySystem : The key system for which to create a Media Keys Ipc instance - * @param[in] ipcClient : The ipc client - * @param[in] eventThreadFactory : The event thread factory - */ - MediaKeysIpc(const std::string &keySystem, IIpcClient &ipcClient, - const std::shared_ptr &eventThreadFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaKeysIpc(); - - MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) override; - - bool containsKey(int32_t keySessionId, const std::vector &keyId) override; - - MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, bool isLDL, - int32_t &keySessionId) override; - - MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) override; - - MediaKeyErrorStatus loadSession(int32_t keySessionId) override; - - MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) override; - - MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) override; - - MediaKeyErrorStatus closeKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus removeKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus deleteDrmStore() override; - - MediaKeyErrorStatus deleteKeyStore() override; - - MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) override; - - MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) override; - - MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) override; - - MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) override; - - MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) override; - - MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) override; - - MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) override; - -private: - /** - * @brief The ipc protobuf media keys stub. - */ - std::unique_ptr<::firebolt::rialto::MediaKeysModule_Stub> m_mediaKeysStub; - - /** - * @brief The media key handle for the current session. - */ - std::atomic m_mediaKeysHandle; - - /** - * @brief Thread for handling media player events from the server. - */ - std::unique_ptr m_eventThread; - - /** - * @brief The media keys client ipc. - */ - std::weak_ptr m_mediaKeysIpcClient; - - bool createRpcStubs(const std::shared_ptr &ipcChannel) override; - - bool subscribeToEvents(const std::shared_ptr &ipcChannel) override; - - /** - * @brief Handler for a license request from the server. - * - * @param[in] event : The license request event structure. - */ - void onLicenseRequest(const std::shared_ptr &event); - - /** - * @brief Handler for a license renewal from the server. - * - * @param[in] event : The license renewal event structure. - */ - void onLicenseRenewal(const std::shared_ptr &event); - - /** - * @brief Handler for a key statues change from the server. - * - * @param[in] event : The key statues change event structure. - */ - void onKeyStatusesChanged(const std::shared_ptr &event); - - /** - * @brief Create a new media keys instance. - * - * @retval true on success, false otherwise. - */ - bool createMediaKeys(const std::string &keySystem); - - /** - * @brief Destroy the current media keys instance. - */ - void destroyMediaKeys(); - - /** - * @brief Checks the Ipc controller and ProtoMediaKeyErrorStatus for failures and return the MediaKeyErrorStatus. - * - * @param[in] methodName : The name of the ipc method. - * @param[in] controller : The rpc controller object. - * @param[in] status : The protobuf response status. - * - * @retval The MediaKeyErrorStatus to return. - */ - MediaKeyErrorStatus - getMediaKeyErrorStatusFromResponse(const std::string methodName, - const std::shared_ptr &controller, - ProtoMediaKeyErrorStatus status); -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h b/middleware/rialto-client/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h deleted file mode 100644 index 0078aa340..000000000 --- a/middleware/rialto-client/media/client/ipc/include/MediaPipelineCapabilitiesIpc.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_IPC_H_ - -#include "IMediaPipelineCapabilitiesIpcFactory.h" -#include "IpcModule.h" -#include -#include -#include - -#include "mediapipelinecapabilitiesmodule.pb.h" - -namespace firebolt::rialto::client -{ -/** - * @brief IMediaPipelineCapabilitiesIpc factory class definition. - */ -class MediaPipelineCapabilitiesIpcFactory : public IMediaPipelineCapabilitiesIpcFactory -{ -public: - MediaPipelineCapabilitiesIpcFactory() = default; - ~MediaPipelineCapabilitiesIpcFactory() override = default; - - std::unique_ptr createMediaPipelineCapabilitiesIpc() const override; -}; - -/** - * @brief The definition of the MediaPipelineCapabilitiesIpc. - */ -class MediaPipelineCapabilitiesIpc : public IMediaPipelineCapabilities, public IpcModule -{ -public: - /** - * @brief The constructor. - * - * @param[in] ipcClient : The ipc client - */ - explicit MediaPipelineCapabilitiesIpc(IIpcClient &ipcClient); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaPipelineCapabilitiesIpc(); - - /** - * @brief Returns the MSE mime types supported by Rialto for \a sourceType - * - * @param[in] sourceType : source type - * - * @retval The supported mime types. - */ - std::vector getSupportedMimeTypes(MediaSourceType sourceType) override; - - /** - * @brief Indicates if the specified mime type is supported. - * - * This method should be called to ensure that the specified mime - * type is supported by Rialto. - * - * @param[in] mimeType : The mime type to check. - * - * @retval true if supported. - */ - bool isMimeTypeSupported(const std::string &mimeType) override; - - /** - * @brief Check sinks and decoders for supported properties - * - * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched - * @param[in] propertyNames : A vector of property names to look for - * - * @retval Returns the subset of propertyNames that are supported by the mediaType - */ - std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) override; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - bool isVideoMaster(bool &isVideoMaster) override; - -private: - /** - * @brief The ipc protobuf media Pipeline capabilities stub. - */ - std::unique_ptr<::firebolt::rialto::MediaPipelineCapabilitiesModule_Stub> m_mediaPipelineCapabilitiesStub; - - bool createRpcStubs(const std::shared_ptr &ipcChannel) override; - - bool subscribeToEvents(const std::shared_ptr &ipcChannel) override { return true; } -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/MediaPipelineIpc.h b/middleware/rialto-client/media/client/ipc/include/MediaPipelineIpc.h deleted file mode 100644 index a398159d7..000000000 --- a/middleware/rialto-client/media/client/ipc/include/MediaPipelineIpc.h +++ /dev/null @@ -1,300 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_IPC_H_ - -#include "IEventThread.h" -#include "IMediaPipelineIpc.h" -#include "IpcModule.h" -#include -#include -#include - -#include "mediapipelinemodule.pb.h" - -namespace firebolt::rialto::client -{ -/** - * @brief IMediaPipelineIpc factory class definition. - */ -class MediaPipelineIpcFactory : public IMediaPipelineIpcFactory -{ -public: - /** - * @brief Weak pointer to the singleton factory object. - */ - static std::weak_ptr m_factory; - - std::unique_ptr createMediaPipelineIpc(IMediaPipelineIpcClient *client, - const VideoRequirements &videoRequirements, - std::weak_ptr ipcClient) override; -}; - -/** - * @brief The definition of the MediaPipelineIpc. - */ -class MediaPipelineIpc : public IMediaPipelineIpc, public IpcModule -{ -public: - /** - * @brief The constructor. - * - * @param[in] client : The Rialto ipc media player client. - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. - * @param[in] ipcClient : The ipc client - * @param[in] eventThreadFactory : The event thread factory - */ - MediaPipelineIpc(IMediaPipelineIpcClient *client, const VideoRequirements &videoRequirements, IIpcClient &ipcClient, - const std::shared_ptr &eventThreadFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaPipelineIpc(); - - bool attachSource(const std::unique_ptr &source, int32_t &sourceId) override; - - bool removeSource(int32_t sourceId) override; - - bool allSourcesAttached() override; - - bool load(MediaType type, const std::string &mimeType, const std::string &url) override; - - bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; - - bool play() override; - - bool pause() override; - - bool stop() override; - - bool haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t requestId) override; - - bool setPosition(int64_t position) override; - - bool getPosition(int64_t &position) override; - - bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override; - - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override; - - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; - - bool setPlaybackRate(double rate) override; - - bool renderFrame() override; - - bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override; - - bool getVolume(double &volume) override; - - bool setMute(int32_t sourceId, bool mute) override; - - bool getMute(int32_t sourceId, bool &mute) override; - - bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; - - bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; - - bool setLowLatency(bool lowLatency) override; - - bool setSync(bool sync) override; - - bool getSync(bool &sync) override; - - bool setSyncOff(bool syncOff) override; - - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; - - bool getStreamSyncMode(int32_t &streamSyncMode) override; - - bool flush(int32_t sourceId, bool resetTime, bool &async) override; - - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) override; - - bool setSubtitleOffset(int32_t sourceId, int64_t position) override; - - bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; - - bool setBufferingLimit(uint32_t limitBufferingMs) override; - - bool getBufferingLimit(uint32_t &limitBufferingMs) override; - - bool setUseBuffering(bool useBuffering) override; - - bool getUseBuffering(bool &useBuffering) override; - - bool switchSource(const std::unique_ptr &source) override; - -private: - /** - * @brief The media player client ipc. - */ - IMediaPipelineIpcClient *m_mediaPipelineIpcClient; - - /** - * @brief The ipc protobuf media player stub. - */ - std::unique_ptr<::firebolt::rialto::MediaPipelineModule_Stub> m_mediaPipelineStub; - - /** - * @brief The session id of the current session. - */ - // onPlaybackStateUpdated() can be called before createSession() therefore - // initialise m_sessionId to -1 which is an invalid session_id - std::atomic m_sessionId{-1}; - - /** - * @brief Thread for handling media player events from the server. - */ - std::unique_ptr m_eventThread; - - bool createRpcStubs(const std::shared_ptr &ipcChannel) override; - - bool subscribeToEvents(const std::shared_ptr &ipcChannel) override; - - /** - * @brief Handler for a playback state update from the server. - * - * @param[in] event : The player state changed event structure. - */ - void onPlaybackStateUpdated(const std::shared_ptr &event); - - /** - * @brief Handler for a playback position update from the server. - * - * @param[in] event : The playback position changed event structure. - */ - void onPositionUpdated(const std::shared_ptr &event); - - /** - * @brief Handler for a network state update from the server. - * - * @param[in] event : The player state changed event structure. - */ - void onNetworkStateUpdated(const std::shared_ptr &event); - - /** - * @brief Handler for a need data request from the server. - * - * @param[in] event : The need data event structure. - */ - void onNeedMediaData(const std::shared_ptr &event); - - /** - * @brief Handler for a QOS update from the server. - * - * @param[in] event : The qos event structure. - */ - void onQos(const std::shared_ptr &event); - - /** - * @brief Handler for a buffer underflow notification from the server. - * - * @param[in] event : The buffer underflow event structure. - */ - void onBufferUnderflow(const std::shared_ptr &event); - - /** - * @brief Handler for a playback error notification from the server. - * - * @param[in] event : The playback error event structure. - */ - void onPlaybackError(const std::shared_ptr &event); - - /** - * @brief Handler for a source flushed notification from the server. - * - * @param[in] event : The source flushed event structure. - */ - void onSourceFlushed(const std::shared_ptr &event); - - /** - * @brief Create a new player session. - * - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. - * - * @retval true on success, false otherwise. - */ - bool createSession(const VideoRequirements &videoRequirements); - - /** - * @brief Destroy the current player session. - */ - void destroySession(); - - /** - * @brief Converts the MediaType enum to protobuf LoadRequest MediaType. - */ - firebolt::rialto::LoadRequest_MediaType convertLoadRequestMediaType(MediaType mediaType) const; - - /** - * @brief Converts the MediaSourceStatus enum to protobuf HaveDataRequest MediaSourceStatus. - */ - firebolt::rialto::HaveDataRequest_MediaSourceStatus - convertHaveDataRequestMediaSourceStatus(MediaSourceStatus status) const; - - /** - * @brief Converts the SegmentAlignment enum to protobuf AttachSourceRequest SegmentAlignment. - */ - firebolt::rialto::AttachSourceRequest_SegmentAlignment - convertSegmentAlignment(const firebolt::rialto::SegmentAlignment &alignment) const; - - /** - * @brief Converts the StreamFormat enum to protobuf AttachSourceRequest StreamFormat. - */ - firebolt::rialto::AttachSourceRequest_StreamFormat - convertStreamFormat(const firebolt::rialto::StreamFormat &streamFormat) const; - - firebolt::rialto::AttachSourceRequest_ConfigType - convertConfigType(const firebolt::rialto::SourceConfigType &configType) const; - - /** - * @brief Converts the CodecDataType enum to protobuf AttachSourceRequest CodecDataType. - */ - firebolt::rialto::AttachSourceRequest_CodecData_Type - convertCodecDataType(const firebolt::rialto::CodecDataType &codecDataType) const; - - /** - * @brief Converts the Format enum to protobuf AttachSourceRequest Format. - */ - firebolt::rialto::AttachSourceRequest_AudioConfig_Format convertFormat(const firebolt::rialto::Format &format) const; - - /** - * @brief Converts the Layout enum to protobuf AttachSourceRequest Layout. - */ - firebolt::rialto::AttachSourceRequest_AudioConfig_Layout convertLayout(const firebolt::rialto::Layout &layout) const; - - /** - * @brief Converts the EaseType enum to protobuf SetVolumeRequest EaseType. - */ - firebolt::rialto::SetVolumeRequest_EaseType convertEaseType(const firebolt::rialto::EaseType &easeType) const; - - /** - * @brief Sets AttachSourceRequest parameters based on given MediaSource - */ - bool buildAttachSourceRequest(firebolt::rialto::AttachSourceRequest &request, - const std::unique_ptr &source) const; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/RialtoCommonIpc.h b/middleware/rialto-client/media/client/ipc/include/RialtoCommonIpc.h deleted file mode 100644 index 44044d38d..000000000 --- a/middleware/rialto-client/media/client/ipc/include/RialtoCommonIpc.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_RIALTO_COMMON_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_RIALTO_COMMON_IPC_H_ - -#include "MediaCommon.h" -#include "rialtocommon.pb.h" - -namespace firebolt::rialto::client -{ -firebolt::rialto::ProtoMediaSourceType convertProtoMediaSourceType(MediaSourceType mediaSourceType); -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_RIALTO_COMMON_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/include/WebAudioPlayerIpc.h b/middleware/rialto-client/media/client/ipc/include/WebAudioPlayerIpc.h deleted file mode 100644 index beb364777..000000000 --- a/middleware/rialto-client/media/client/ipc/include/WebAudioPlayerIpc.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_IPC_H_ - -#include "IEventThread.h" -#include "IWebAudioPlayerIpc.h" -#include "IpcModule.h" -#include -#include -#include - -#include "webaudioplayermodule.pb.h" - -namespace firebolt::rialto::client -{ -/** - * @brief IWebAudioPlayerIpc factory class definition. - */ -class WebAudioPlayerIpcFactory : public IWebAudioPlayerIpcFactory -{ -public: - std::unique_ptr - createWebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config, std::weak_ptr ipcClient) override; -}; - -/** - * @brief The definition of the WebAudioPlayerIpc. - */ -class WebAudioPlayerIpc : public IWebAudioPlayerIpc, public IpcModule -{ -public: - /** - * @brief The constructor. - * - * @param[in] client : The Rialto ipc web audio player client. - * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM) - * @param[in] priority : Priority value for this pipeline. - * @param[in] config : Additional type dependent configuration data or nullptr - * @param[in] ipcClient : The ipc client - * @param[in] eventThreadFactory : The event thread factory - */ - WebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config, IIpcClient &ipcClient, - const std::shared_ptr &eventThreadFactory); - - virtual ~WebAudioPlayerIpc(); - - bool play() override; - - bool pause() override; - - bool setEos() override; - - bool getBufferAvailable(uint32_t &availableFrames, const std::shared_ptr &webAudioShmInfo) override; - - bool getBufferDelay(uint32_t &delayFrames) override; - - bool writeBuffer(const uint32_t numberOfFrames) override; - - bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override; - - bool setVolume(double volume) override; - - bool getVolume(double &volume) override; - -private: - bool createWebAudioPlayer(const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config); - - void destroyWebAudioPlayer(); - - bool createRpcStubs(const std::shared_ptr &ipcChannel) override; - - bool subscribeToEvents(const std::shared_ptr &ipcChannel) override; - - void onPlaybackStateUpdated(const std::shared_ptr &event); - /** - * @brief The web audio player client ipc. - */ - IWebAudioPlayerIpcClient *m_webAudioPlayerIpcClient; - - /** - * @brief The ipc protobuf web audio player stub. - */ - std::unique_ptr<::firebolt::rialto::WebAudioPlayerModule_Stub> m_webAudioPlayerStub; - - /** - * @brief Thread for handling web audio player events from the server. - */ - std::unique_ptr m_eventThread; - - /** - * @brief Handle to an IPC connection to the server. - */ - int32_t m_webAudioPlayerHandle; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IControlIpc.h b/middleware/rialto-client/media/client/ipc/interface/IControlIpc.h deleted file mode 100644 index a68a285a9..000000000 --- a/middleware/rialto-client/media/client/ipc/interface/IControlIpc.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_CONTROL_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_I_CONTROL_IPC_H_ - -#include "IControlClient.h" -#include - -#include -#include - -namespace firebolt::rialto::client -{ -class IControlIpc; - -/** - * @brief IControlIpc factory class, returns a singlton of IControlIpc - */ -class IControlIpcFactory -{ -public: - IControlIpcFactory() = default; - virtual ~IControlIpcFactory() = default; - - /** - * @brief Create a IControlIpcFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Gets the IControlIpc singleton object. - * - * @retval the rialto controller ipc instance or null on error. - */ - virtual std::shared_ptr createControlIpc(IControlClient *controlClient) = 0; -}; - -/** - * @brief The definition of the IControlIpc interface. - * - * This interface defines the rialto control ipc APIs that are used to communicate with the Rialto server. - */ -class IControlIpc -{ -public: - IControlIpc() = default; - virtual ~IControlIpc() = default; - - IControlIpc(const IControlIpc &) = delete; - IControlIpc &operator=(const IControlIpc &) = delete; - IControlIpc(IControlIpc &&) = delete; - IControlIpc &operator=(IControlIpc &&) = delete; - - /** - * @brief Gets shared memory information to map. - * - * @param[in] fd : The file descriptor of the shared memory region. - * @param[in] size : The size of the shared memory region. - * - * @retval true success, false otherwise. - */ - virtual bool getSharedMemory(int32_t &fd, uint32_t &size) = 0; - - /** - * @brief Register new client - * - * @retval true success, false otherwise. - */ - virtual bool registerClient() = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_CONTROL_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaKeysCapabilitiesIpcFactory.h b/middleware/rialto-client/media/client/ipc/interface/IMediaKeysCapabilitiesIpcFactory.h deleted file mode 100644 index bff31562e..000000000 --- a/middleware/rialto-client/media/client/ipc/interface/IMediaKeysCapabilitiesIpcFactory.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_CAPABILITIES_IPC_FACTORY_H_ -#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_CAPABILITIES_IPC_FACTORY_H_ - -/** - * @file IMediaKeysCapabilities.h - * - * The definition of the IMediaKeysCapabilities interface. - */ - -#include "IMediaKeysCapabilities.h" -#include -#include -#include - -namespace firebolt::rialto::client -{ -/** - * @brief IMediaKeysCapabilities factory class, for getting the IMediaKeysCapabilities singleton object for ipc. - */ -class IMediaKeysCapabilitiesIpcFactory -{ -public: - IMediaKeysCapabilitiesIpcFactory() = default; - virtual ~IMediaKeysCapabilitiesIpcFactory() = default; - - /** - * @brief Gets the IMediaKeysCapabilitiesIpcFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Gets the IMediaKeysCapabilities singleton object for ipc. - * - * @retval the MediaKeysCapabilities for ipc instance or null on error. - */ - virtual std::shared_ptr getMediaKeysCapabilitiesIpc() const = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_CAPABILITIES_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaKeysIpcFactory.h b/middleware/rialto-client/media/client/ipc/interface/IMediaKeysIpcFactory.h deleted file mode 100644 index 7b8a3ee33..000000000 --- a/middleware/rialto-client/media/client/ipc/interface/IMediaKeysIpcFactory.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_IPC_FACTORY_H_ -#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_IPC_FACTORY_H_ - -/** - * @file IMediaKeys.h - * - * The definition of the IMediaKeys interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content. - */ - -#include -#include -#include - -#include "IMediaKeys.h" -#include "MediaCommon.h" - -namespace firebolt::rialto::client -{ -/** - * @brief IMediaKeys factory class, returns a concrete implementation of IMediaKeys for Ipc - */ -class IMediaKeysIpcFactory -{ -public: - IMediaKeysIpcFactory() = default; - virtual ~IMediaKeysIpcFactory() = default; - - /** - * @brief Create a IMediaKeysIpcFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMediaKeys factory method, returns a concrete implementation of IMediaKeys for Ipc - * - * @param[in] keySystem : The key system for which to create a Media Keys instance - * - * @retval the new media keys for ipc instance or null on error. - */ - virtual std::unique_ptr createMediaKeysIpc(const std::string &keySystem) const = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_KEYS_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineCapabilitiesIpcFactory.h b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineCapabilitiesIpcFactory.h deleted file mode 100644 index cec92eba6..000000000 --- a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineCapabilitiesIpcFactory.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_CAPABILITIES_IPC_FACTORY_H_ -#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_CAPABILITIES_IPC_FACTORY_H_ - -/** - * @file IMediaPipelineCapabilities.h - * - * The definition of the IMediaPipelineCapabilities interface. - */ - -#include "IMediaPipelineCapabilities.h" -#include -#include -#include - -namespace firebolt::rialto::client -{ -/** - * @brief IMediaPipelineCapabilities factory class, for getting the IMediaPipelineCapabilities singleton object for ipc. - */ -class IMediaPipelineCapabilitiesIpcFactory -{ -public: - IMediaPipelineCapabilitiesIpcFactory() = default; - virtual ~IMediaPipelineCapabilitiesIpcFactory() = default; - - /** - * @brief Gets the IMediaPipelineCapabilitiesIpcFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Gets the IMediaPipelineCapabilities singleton object for ipc. - * - * @retval the MediaPipelineCapabilities for ipc instance or null on error. - */ - virtual std::unique_ptr createMediaPipelineCapabilitiesIpc() const = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_CAPABILITIES_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpc.h b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpc.h deleted file mode 100644 index 6a727e551..000000000 --- a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpc.h +++ /dev/null @@ -1,458 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_H_ - -#include - -#include -#include - -#include "IMediaPipeline.h" -#include "IMediaPipelineIpcClient.h" -#include "MediaCommon.h" - -namespace firebolt::rialto::client -{ -class IMediaPipelineIpc; -class IIpcClient; - -/** - * @brief IMediaPipelineIpc factory class, returns a concrete implementation of IMediaPipelineIpc - */ -class IMediaPipelineIpcFactory -{ -public: - IMediaPipelineIpcFactory() = default; - virtual ~IMediaPipelineIpcFactory() = default; - - /** - * @brief Gets the IMediaPipelineIpcFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Creates a IMediaPipelineIpc object. - * - * @param[in] client : The Rialto ipc media player client. - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. - * - * @retval the new media player ipc instance or null on error. - */ - virtual std::unique_ptr createMediaPipelineIpc(IMediaPipelineIpcClient *client, - const VideoRequirements &videoRequirements, - std::weak_ptr ipcClient = {}) = 0; -}; - -/** - * @brief The definition of the IMediaPipelineIpc interface. - * - * This interface defines the media player ipc APIs that are used to communicate with the Rialto server. - */ -class IMediaPipelineIpc -{ -public: - IMediaPipelineIpc() = default; - virtual ~IMediaPipelineIpc() = default; - - IMediaPipelineIpc(const IMediaPipelineIpc &) = delete; - IMediaPipelineIpc &operator=(const IMediaPipelineIpc &) = delete; - IMediaPipelineIpc(IMediaPipelineIpc &&) = delete; - IMediaPipelineIpc &operator=(IMediaPipelineIpc &&) = delete; - - /** - * @brief Request to attach the source to the server backend. - * - * @param[in] source : The source. - * @param[out] sourceId : The unique id of the media source. - * - * @retval true on success. - */ - virtual bool attachSource(const std::unique_ptr &source, int32_t &sourceId) = 0; - - /** - * @brief Request to remove the source to the server backend. - * - * @param[in] sourceId : The unique id of the media source. - * - * @retval true on success. - */ - virtual bool removeSource(int32_t sourceId) = 0; - - virtual bool allSourcesAttached() = 0; - - /** - * @brief Request to load the media pipeline. - * - * @param[in] type : The media type. - * @param[in] mimeType : The MIME type. - * @param[in] url : The URL. - * - * @retval true on success. - */ - virtual bool load(MediaType type, const std::string &mimeType, const std::string &url) = 0; - - /** - * @brief Request to set the coordinates of the video window. - * - * @param[in] x : The x position in pixels. - * @param[in] y : The y position in pixels. - * @param[in] width : The width in pixels. - * @param[in] height : The height in pixels. - * - * @retval true on success. - */ - virtual bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; - - /** - * @brief Request play on the playback session. - * - * @retval true on success. - */ - virtual bool play() = 0; - - /** - * @brief Request pause on the playback session. - * - * @retval true on success. - */ - virtual bool pause() = 0; - - /** - * @brief Request stop on the playback session. - * - * @retval true on success. - */ - virtual bool stop() = 0; - - /** - * @brief Notify server that the data has been written to the shared memory. - * - * @param[in] status : The status. - * @param[in] requestId : The Need data request id. - * - * @retval true on success. - */ - virtual bool haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t requestId) = 0; - - /** - * @brief Request new playback position. - * - * @param[in] position : The playback position in nanoseconds. - * - * @retval true on success. - */ - virtual bool setPosition(int64_t position) = 0; - - /** - * @brief Get the playback position in nanoseconds. - * - * This method is sychronous, it returns current playback position - * - * @param[out] position : The playback position in nanoseconds - * - * @retval true on success. - */ - virtual bool getPosition(int64_t &position) = 0; - - /** - * @brief Sets the "Immediate Output" property for this source. - * - * This method is asynchronous - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] immediateOutput : The desired immediate output mode on the sink - * - * @retval true on success. - */ - virtual bool setImmediateOutput(int32_t sourceId, bool immediateOutput) = 0; - - /** - * @brief Gets the "Immediate Output" property for this source. - * - * This method is sychronous - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[out] immediateOutput : Returns the immediate output mode of the sink - * - * @retval true on success. - */ - virtual bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) = 0; - - /** - * @brief Get stats for this source. - * - * This method is sychronous, it returns dropped frames and rendered frames - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[out] droppedFrames : The number of dropped frames - * @param[out] renderedFrames : The number of rendered frames - * - * @retval true on success. - */ - virtual bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; - - /** - * @brief Request new playback rate. - * - * @param[in] rate : The playback rate. - * - * @retval true on success. - */ - virtual bool setPlaybackRate(double rate) = 0; - - /** - * @brief Requests to render a prerolled frame - */ - virtual bool renderFrame() = 0; - - /** - * @brief Set level and transition of audio attenuation. - * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume) - * - * @param[in] targetVolume : Target volume level (0.0 - 1.0) - * @param[in] volumeDuration : Duration of the volume transition in milliseconds - * @param[in] ease_type : Easing type for the volume transition - * - * @retval true on success false otherwise - */ - virtual bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) = 0; - - /** - * @brief Get current audio level. Fetches the current volume level for the pipeline. - * - * @param[out] volume Current volume level (range 0.0 - 1.0) - * - * @retval true on success false otherwise - */ - virtual bool getVolume(double &volume) = 0; - - /** - * @brief Set mute status of pipeline. - * - * Change mute status of media source - * - * @param[in] sourceId Source, which mute status should be changed - * @param[in] mute Desired mute state, true=muted, false=not muted - * - * @retval true on success false otherwise - */ - virtual bool setMute(int32_t sourceId, bool mute) = 0; - - /** - * @brief Get current mute status of the media source - * - * @param[in] sourceId Source, which mute status should be fetched - * @param[out] mute Current mute state - * - * @retval true on success false otherwise - */ - virtual bool getMute(int32_t sourceId, bool &mute) = 0; - - /** - * @brief Change Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - virtual bool setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; - - /** - * @brief Get Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; - - /** - * @brief Set low latency property on the pipeline. Default false. - * - * @param[in] lowLatency : The low latency value to set. - * - * @retval true on success false otherwise - */ - virtual bool setLowLatency(bool lowLatency) = 0; - - /** - * @brief Set sync property on the pipeline. Default false. - * - * @param[in] sync : The sync value to set. - * - * @retval true on success false otherwise - */ - virtual bool setSync(bool sync) = 0; - - /** - * @brief Get sync property on the pipeline. - * - * @param[out] sync : Current sync value. - * - * @retval true on success false otherwise - */ - virtual bool getSync(bool &sync) = 0; - - /** - * @brief Set sync off property on the pipeline. Default false. - * - * @param[in] syncOff : The sync off value to set. - * - * @retval true on success false otherwise - */ - virtual bool setSyncOff(bool syncOff) = 0; - - /** - * @brief Set stream sync mode property on the pipeline. Default 0. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] streamSyncMode : The stream sync mode value to set. - * - * @retval true on success false otherwise - */ - virtual bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) = 0; - - /** - * @brief Get stream sync mode property on the pipeline. - * - * @param[out] streamSyncMode : Current stream sync mode value. - * - * @retval true on success false otherwise - */ - virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; - - /** - * @brief Flushes a source. - * - * This method is called by Rialto Client to flush out all queued data for a media source stream. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] resetTime : True if time should be reset - * @param[out] async : True if flushed source is asynchronous (will preroll after flush) - * - * @retval true on success. - */ - virtual bool flush(int32_t sourceId, bool resetTime, bool &async) = 0; - - /** - * @brief Set the source position in nanoseconds. - * - * This method sets the start position for a source. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] position : The position in nanoseconds. - * @param[in] resetTime : True if time should be reset - * @param[in] appliedRate : The applied rate after seek - * @param[in] stopPosition : The position of last pushed buffer - * - * @retval true on success. - */ - virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) = 0; - - /** - * @brief Set the subtitle offset in nanoseconds. - * - * This method sets the subtitle offset for a subtitle source. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] position : The offset position in nanoseconds. - * - * @retval true on success. - */ - virtual bool setSubtitleOffset(int32_t sourceId, int64_t position) = 0; - - /** - * @brief Process audio gap - * - * This method handles audio gap in order to avoid audio pops during transitions. - * - * @param[in] position : Audio pts fade pts value - * @param[in] duration : Audio pts fade duration - * @param[in] discontinuityGap : Audio discontinuity gap - * @param[in] audioAac : True if audio codec is AAC - * - * @retval true on success. - */ - virtual bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; - - /** - * @brief Set buffering limit - * - * This method enables/disables limit buffering and sets millisecond threshold used. - * Use kInvalidLimitBuffering to disable limit buffering - * - * @param[in] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - virtual bool setBufferingLimit(uint32_t limitBufferingMs) = 0; - - /** - * @brief Get buffering limit - * - * This method returns current value of buffering limit in milliseconds - * Method will return kInvalidLimitBuffering limit buffering is disabled - * - * @param[out] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; - - /** - * @brief Enables/disables the buffering option - * - * This method enables the buffering option so that BUFFERING messages are - * emitted based on low-/high-percent thresholds. - * - * @param[in] useBuffering : true if buffering option enabled. - * - * @retval true on success. - */ - virtual bool setUseBuffering(bool useBuffering) = 0; - - /** - * @brief Check, if buffering is enabled - * - * This method returns true, if buffering is enabled - * - * @param[out] useBuffering : true if buffering option is enabled. - * - * @retval true on success. - */ - virtual bool getUseBuffering(bool &useBuffering) = 0; - - /** - * @brief Request to switch the source to the server backend. - * - * @param[in] source : The source. - * - * @retval true on success. - */ - virtual bool switchSource(const std::unique_ptr &source) = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpcClient.h b/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpcClient.h deleted file mode 100644 index 9e50a3a23..000000000 --- a/middleware/rialto-client/media/client/ipc/interface/IMediaPipelineIpcClient.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_CLIENT_H_ -#define FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_CLIENT_H_ - -#include -#include -#include -#include - -/** - * @file IMediaPipelineIpcClient.h - * - * The definition of the IMediaPipelineIpcClient interface. - */ - -namespace firebolt::rialto::client -{ -/** - * @brief The Rialto media player client ipc interface. - */ -class IMediaPipelineIpcClient -{ -public: - IMediaPipelineIpcClient() = default; - virtual ~IMediaPipelineIpcClient() = default; - - IMediaPipelineIpcClient(const IMediaPipelineIpcClient &) = delete; - IMediaPipelineIpcClient &operator=(const IMediaPipelineIpcClient &) = delete; - IMediaPipelineIpcClient(IMediaPipelineIpcClient &&) = delete; - IMediaPipelineIpcClient &operator=(IMediaPipelineIpcClient &&) = delete; - - /** - * @brief Notifies the rialto client of the playback state. - * - * @param[in] state : The new playback state. - */ - virtual void notifyPlaybackState(PlaybackState state) = 0; - - /** - * @brief Handler for a playback position update from the server. - * - * @param[in] event : The playback position changed event structure. - */ - virtual void notifyPosition(int64_t position) = 0; - - /** - * @brief Notifies the rialto client of the network state. - * - * @param[in] state : The new network state. - */ - virtual void notifyNetworkState(NetworkState state) = 0; - - /** - * @brief Notifies the rialto client of a need data request. - * - * @param[in] sourceId : The source to read data from. - * @param[in] frameCount : The number of frames to read. - * @param[in] requestId : Need data request id. - * @param[in] shmInfo : Information for populating the shared memory (null if not applicable to the client). - */ - virtual void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId, - const std::shared_ptr &shmInfo) = 0; - - /** - * @brief Notifies the rialto client of a Quality Of Service update. - * - * @param[in] sourceId : The id of the source that produced the Qos. - * @param[in] qosInfo : The information provided in the update. - */ - virtual void notifyQos(int32_t sourceId, const QosInfo &qosInfo) = 0; - - /** - * @brief Notifies the client that buffer underflow occurred. - * - * Notification shall be sent whenever a video/audio buffer underflow occurs - * - * @param[in] sourceId : The id of the source that produced the buffer underflow - */ - virtual void notifyBufferUnderflow(int32_t sourceId) = 0; - - /** - * @brief Notifies the client that a non-fatal error has occurred in the player. - * - * PlaybackState remains unchanged when an error occurs. - * - * @param[in] sourceId : The id of the source that produced the error. - * @param[in] error : The type of error that occurred. - */ - virtual void notifyPlaybackError(int32_t sourceId, PlaybackError error) = 0; - - /** - * @brief Notifies the client that the source has been flushed. - * - * Notification shall be sent whenever a flush procedure is finished. - * - * @param[in] sourceId : The id of the source that has been flushed. - */ - virtual void notifySourceFlushed(int32_t sourceId) = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_MEDIA_PIPELINE_IPC_CLIENT_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpc.h b/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpc.h deleted file mode 100644 index a8bc997cd..000000000 --- a/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpc.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_H_ -#define FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_H_ - -#include - -#include -#include - -#include -#include - -#include "IWebAudioPlayerIpcClient.h" - -namespace firebolt::rialto::client -{ -class IWebAudioPlayerIpc; -class IIpcClient; - -/** - * @brief IWebAudioPlayerIpc factory class, returns a concrete implementation of IWebAudioPlayerIpc - */ -class IWebAudioPlayerIpcFactory -{ -public: - IWebAudioPlayerIpcFactory() = default; - virtual ~IWebAudioPlayerIpcFactory() = default; - - /** - * @brief Gets the IWebAudioPlayerIpcFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Creates a IWebAudioPlayerIpc object. - * - * @param[in] client : The Rialto ipc web audio player client. - * - * @retval the new web audio player ipc instance or null on error. - */ - virtual std::unique_ptr - createWebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config, std::weak_ptr ipcClient = {}) = 0; -}; - -/** - * @brief The definition of the IWebAudioPlayerIpc interface. - * - * This interface defines the web audio player ipc APIs that are used to communicate with the Rialto server. - */ -class IWebAudioPlayerIpc -{ -public: - IWebAudioPlayerIpc() = default; - virtual ~IWebAudioPlayerIpc() = default; - - IWebAudioPlayerIpc(const IWebAudioPlayerIpc &) = delete; - IWebAudioPlayerIpc &operator=(const IWebAudioPlayerIpc &) = delete; - IWebAudioPlayerIpc(IWebAudioPlayerIpc &&) = delete; - IWebAudioPlayerIpc &operator=(IWebAudioPlayerIpc &&) = delete; - - /** - * @brief Play the web audio. - * - * @retval true on success. - */ - virtual bool play() = 0; - - /** - * @brief Pause the web audio. - * - * @retval true on success. - */ - virtual bool pause() = 0; - - /** - * @brief Notify EOS. - * - * @retval true on success. - */ - virtual bool setEos() = 0; - - /** - * @brief Get the available frames. - * - * @param[out] availableFrames : Number of frames available to be written. - * @param[out] webAudioShmInfo : Location in shm to write the data. - * - * @retval true on success. - */ - virtual bool getBufferAvailable(uint32_t &availableFrames, - const std::shared_ptr &webAudioShmInfo) = 0; - - /** - * @brief Get the delay frames. - * - * Gets the frame delay of the playback from Rialto. Frame delay is the number - * of frames left to play by the server. - * - * @param[out] delayFrames : Number of frames to be played. - * - * @retval true on success. - */ - virtual bool getBufferDelay(uint32_t &delayFrames) = 0; - - /** - * @brief Write audio frames - * - * Sends a buffer of audio data for playback - * - * @param[in] numberOfFrames : Number of frames written to shared memory. - * - * @retval true on success. - */ - virtual bool writeBuffer(const uint32_t numberOfFrames) = 0; - - /** - * @brief Get device information. - * - * @param[out] preferredFrames : preferred number of frames to be commited. - * @param[out] maximumFrames : Maximum number of frames that can be commited. - * @param[out] supportDeferredPlay : Whether defered play is supported. - * - * @retval true on success. - */ - virtual bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) = 0; - - /** - * - * @brief Set level and transition of audio attenuation - * - * @param[in] volume : Target volume level (0.0 - 1.0) - * - * @retval true on success false otherwise - */ - virtual bool setVolume(double volume) = 0; - - /** - * @brief Get current audio level - * - * @param[out] volume : Current volume level (range 0.0 - 1.0) - * - * @retval true on success false otherwise - */ - virtual bool getVolume(double &volume) = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_H_ diff --git a/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpcClient.h b/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpcClient.h deleted file mode 100644 index 370207cbd..000000000 --- a/middleware/rialto-client/media/client/ipc/interface/IWebAudioPlayerIpcClient.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_CLIENT_H_ -#define FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_CLIENT_H_ - -#include - -/** - * @file IWebAudioPlayerIpcClient.h - * - * The definition of the IWebAudioPlayerIpcClient interface. - */ - -namespace firebolt::rialto::client -{ -/** - * @brief The Rialto web audio player client ipc interface. - */ -class IWebAudioPlayerIpcClient -{ -public: - IWebAudioPlayerIpcClient() = default; - virtual ~IWebAudioPlayerIpcClient() = default; - - IWebAudioPlayerIpcClient(const IWebAudioPlayerIpcClient &) = delete; - IWebAudioPlayerIpcClient &operator=(const IWebAudioPlayerIpcClient &) = delete; - IWebAudioPlayerIpcClient(IWebAudioPlayerIpcClient &&) = delete; - IWebAudioPlayerIpcClient &operator=(IWebAudioPlayerIpcClient &&) = delete; - - /** - * @brief Notifies the client of the playback state. - * @param[in] state : The new playback state. - * - * @retval true on success. - */ - virtual void notifyState(WebAudioPlayerState state) = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_WEB_AUDIO_PLAYER_IPC_CLIENT_H_ diff --git a/middleware/rialto-client/media/client/ipc/proto/controlmodule.proto b/middleware/rialto-client/media/client/ipc/proto/controlmodule.proto deleted file mode 120000 index 6e95f531f..000000000 --- a/middleware/rialto-client/media/client/ipc/proto/controlmodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/controlmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/mediakeyscapabilitiesmodule.proto b/middleware/rialto-client/media/client/ipc/proto/mediakeyscapabilitiesmodule.proto deleted file mode 120000 index e508c1392..000000000 --- a/middleware/rialto-client/media/client/ipc/proto/mediakeyscapabilitiesmodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/mediakeyscapabilitiesmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/mediakeysmodule.proto b/middleware/rialto-client/media/client/ipc/proto/mediakeysmodule.proto deleted file mode 120000 index 98b44b620..000000000 --- a/middleware/rialto-client/media/client/ipc/proto/mediakeysmodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/mediakeysmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/mediapipelinecapabilitiesmodule.proto b/middleware/rialto-client/media/client/ipc/proto/mediapipelinecapabilitiesmodule.proto deleted file mode 120000 index 7af44cdd7..000000000 --- a/middleware/rialto-client/media/client/ipc/proto/mediapipelinecapabilitiesmodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/mediapipelinecapabilitiesmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/mediapipelinemodule.proto b/middleware/rialto-client/media/client/ipc/proto/mediapipelinemodule.proto deleted file mode 120000 index 6f1b4bdbe..000000000 --- a/middleware/rialto-client/media/client/ipc/proto/mediapipelinemodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/mediapipelinemodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/rialtocommon.proto b/middleware/rialto-client/media/client/ipc/proto/rialtocommon.proto deleted file mode 120000 index 2c6e7a2bb..000000000 --- a/middleware/rialto-client/media/client/ipc/proto/rialtocommon.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/rialtocommon.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/proto/webaudioplayermodule.proto b/middleware/rialto-client/media/client/ipc/proto/webaudioplayermodule.proto deleted file mode 120000 index 4c84680f4..000000000 --- a/middleware/rialto-client/media/client/ipc/proto/webaudioplayermodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/webaudioplayermodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/client/ipc/source/ControlIpc.cpp b/middleware/rialto-client/media/client/ipc/source/ControlIpc.cpp deleted file mode 100644 index 5b277d154..000000000 --- a/middleware/rialto-client/media/client/ipc/source/ControlIpc.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ControlIpc.h" -#include "RialtoClientLogging.h" -#include "SchemaVersion.h" - -namespace -{ -firebolt::rialto::ApplicationState -convertApplicationState(const firebolt::rialto::ApplicationStateChangeEvent_ApplicationState &state) -{ - switch (state) - { - case firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_RUNNING: - return firebolt::rialto::ApplicationState::RUNNING; - case firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_INACTIVE: - return firebolt::rialto::ApplicationState::INACTIVE; - case firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_UNKNOWN: - break; - } - return firebolt::rialto::ApplicationState::UNKNOWN; -} -} // namespace - -namespace firebolt::rialto::client -{ -std::shared_ptr IControlIpcFactory::createFactory() -{ - return ControlIpcFactory::createFactory(); -} - -std::shared_ptr ControlIpcFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the rialto control ipc factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr ControlIpcFactory::createControlIpc(IControlClient *controlClient) -{ - auto &ipcClient{IIpcClientAccessor::instance().getIpcClient()}; - auto controlIpc{std::make_shared(controlClient, ipcClient, - firebolt::rialto::common::IEventThreadFactory::createFactory())}; - ipcClient.registerConnectionObserver(controlIpc); - return controlIpc; -} - -ControlIpc::ControlIpc(IControlClient *controlClient, IIpcClient &ipcClient, - const std::shared_ptr &eventThreadFactory) - : IpcModule(ipcClient), m_controlClient(controlClient), - m_eventThread(eventThreadFactory->createEventThread("rialto-control-events")) -{ - if (!attachChannel()) - { - throw std::runtime_error("Failed attach to the ipc channel"); - } -} - -ControlIpc::~ControlIpc() -{ - // detach the Ipc channel - detachChannel(); - - // destroy the thread processing async notifications - m_eventThread.reset(); -} - -bool ControlIpc::getSharedMemory(int32_t &fd, uint32_t &size) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - std::shared_ptr<::firebolt::rialto::ControlModule_Stub> controlStub = m_controlStub; - - firebolt::rialto::GetSharedMemoryRequest request; - - firebolt::rialto::GetSharedMemoryResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - controlStub->getSharedMemory(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get the shared memory due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - fd = response.fd(); - size = response.size(); - - return true; -} - -bool ControlIpc::registerClient() -{ - const auto kCurrentSchemaVersion{common::getCurrentSchemaVersion()}; - - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - std::shared_ptr<::firebolt::rialto::ControlModule_Stub> controlStub = m_controlStub; - - firebolt::rialto::RegisterClientRequest request; - firebolt::rialto::RegisterClientResponse response; - firebolt::rialto::SchemaVersion clientSchemaVersion; - request.mutable_client_schema_version()->set_major(kCurrentSchemaVersion.major()); - request.mutable_client_schema_version()->set_minor(kCurrentSchemaVersion.minor()); - request.mutable_client_schema_version()->set_patch(kCurrentSchemaVersion.patch()); - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - controlStub->registerClient(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to register client due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - m_controlHandle = response.control_handle(); - - if (!response.has_server_schema_version()) - { - RIALTO_CLIENT_LOG_WARN("Server proto schema version not known"); - return true; - } - - const common::SchemaVersion kServerSchemaVersion{response.server_schema_version().major(), - response.server_schema_version().minor(), - response.server_schema_version().patch()}; - if (kCurrentSchemaVersion == kServerSchemaVersion) - { - RIALTO_CLIENT_LOG_DEBUG("Server and Client proto schema versions are equal"); - } - else if (kCurrentSchemaVersion.isCompatible(kServerSchemaVersion)) - { - RIALTO_CLIENT_LOG_INFO("Server and Client proto schema versions are compatible. Server schema version: %s, " - "Client schema version: %s", - kServerSchemaVersion.str().c_str(), kCurrentSchemaVersion.str().c_str()); - } - else - { - RIALTO_CLIENT_LOG_ERROR("Server and Client proto schema versions are not compatible. Server schema version: " - "%s, Client schema version: %s", - kServerSchemaVersion.str().c_str(), kCurrentSchemaVersion.str().c_str()); - return false; - } - - return true; -} - -bool ControlIpc::createRpcStubs(const std::shared_ptr &ipcChannel) -{ - m_controlStub = std::make_unique<::firebolt::rialto::ControlModule_Stub>(ipcChannel.get()); - if (!m_controlStub) - { - return false; - } - return true; -} - -bool ControlIpc::subscribeToEvents(const std::shared_ptr &ipcChannel) -{ - if (!ipcChannel) - { - return false; - } - - int eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&ControlIpc::onApplicationStateUpdated, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&ControlIpc::onPing, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - return true; -} - -void ControlIpc::onConnectionBroken() -{ - m_eventThread->add([this]() { m_controlClient->notifyApplicationState(ApplicationState::UNKNOWN); }); -} - -void ControlIpc::onApplicationStateUpdated(const std::shared_ptr &event) -{ - // It's possible, that ApplicationStateChangeEvent comes before RegisterClientResponse, so do not check control_handle() here. - m_controlClient->notifyApplicationState(convertApplicationState(event->application_state())); -} - -void ControlIpc::onPing(const std::shared_ptr &event) -{ - if (m_controlHandle != event->control_handle()) - { - RIALTO_CLIENT_LOG_WARN("PingEvent received with wrong handle"); - return; - } - - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return; - } - firebolt::rialto::AckRequest request; - request.set_control_handle(m_controlHandle); - request.set_id(event->id()); - firebolt::rialto::AckResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_controlStub->ack(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to ack due to '%s'", ipcController->ErrorText().c_str()); - } -} -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/IpcClient.cpp b/middleware/rialto-client/media/client/ipc/source/IpcClient.cpp deleted file mode 100644 index 1e1aa4881..000000000 --- a/middleware/rialto-client/media/client/ipc/source/IpcClient.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "IpcClient.h" -#include "RialtoClientLogging.h" - -namespace firebolt::rialto::client -{ -IIpcClientAccessor &IIpcClientAccessor::instance() -{ - static IpcClientAccessor factory; - return factory; -} - -IIpcClient &IpcClientAccessor::getIpcClient() const -{ - static IpcClient ipcClient{ipc::IChannelFactory::createFactory(), ipc::IControllerFactory::createFactory(), - ipc::IBlockingClosureFactory::createFactory()}; - return ipcClient; -} - -IpcClient::IpcClient(const std::shared_ptr &ipcChannelFactory, - const std::shared_ptr &ipcControllerFactory, - const std::shared_ptr &blockingClosureFactory) - : m_ipcControllerFactory(ipcControllerFactory), m_ipcChannelFactory(ipcChannelFactory), - m_blockingClosureFactory(blockingClosureFactory), m_disconnecting(false) -{ - // For now, always connect the client on construction - if (!connect()) - { - throw std::runtime_error("Could not connect client"); - } -} - -IpcClient::~IpcClient() -{ - if (!disconnect()) - { - RIALTO_CLIENT_LOG_WARN("Could not disconnect client"); - } -} - -bool IpcClient::connect() -{ - if (m_ipcChannel) - { - RIALTO_CLIENT_LOG_INFO("Client already connected"); - return true; - } - - // Verify that the version of the library that we linked against is - // compatible with the version of the headers we compiled against. - GOOGLE_PROTOBUF_VERIFY_VERSION; - - // check if either of following env vars are set to determine the location of the rialto socket - // - RIALTO_SOCKET_PATH should specify the absolute path to the socket to connect to - // - RIALTO_SOCKET_FD should specify the number of a file descriptor of the socket to connect to - const char *kRialtoPath = getenv("RIALTO_SOCKET_PATH"); - const char *kRialtoFd = getenv("RIALTO_SOCKET_FD"); - if (kRialtoFd) - { - char *end = nullptr; - int fd = strtol(kRialtoFd, &end, 10); - if ((errno != 0) || (kRialtoFd == end) || (*end != '\0')) - { - RIALTO_CLIENT_LOG_SYS_ERROR(errno, "Invalid value set in RIALTO_SOCKET_FD env var"); - return false; - } - - m_ipcChannel = m_ipcChannelFactory->createChannel(fd); - } - else if (kRialtoPath) - { - m_ipcChannel = m_ipcChannelFactory->createChannel(kRialtoPath); - } - else - { - RIALTO_CLIENT_LOG_ERROR("No rialto socket specified"); - return false; - } - - // check if the channel was opened - if (!m_ipcChannel) - { - RIALTO_CLIENT_LOG_ERROR("Failed to open a connection to the ipc socket"); - return false; - } - - // spin up the thread that runs the IPC event loop - m_ipcThread = std::thread(&IpcClient::processIpcThread, this); - if (!m_ipcThread.joinable()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create thread for IPC"); - return false; - } - - return true; -} - -bool IpcClient::disconnect() -{ - // Increase reference in case client disconnects from another thread - std::shared_ptr ipcChannel = m_ipcChannel; - if (!ipcChannel) - { - // The ipc channel may have disconnected unexpectedly, join the ipc thread if possible - if (m_ipcThread.joinable()) - m_ipcThread.join(); - - RIALTO_CLIENT_LOG_INFO("Client already disconnect"); - return true; - } - - RIALTO_CLIENT_LOG_INFO("closing IPC channel"); - m_disconnecting = true; - - // disconnect from the server, this should terminate the thread so join that too - ipcChannel->disconnect(); - - if (m_ipcThread.joinable()) - m_ipcThread.join(); - - // destroy the IPC channel - m_ipcChannel.reset(); - - m_disconnecting = false; - - return true; -} - -void IpcClient::processIpcThread() -{ - pthread_setname_np(pthread_self(), "rialto-ipc"); - - RIALTO_CLIENT_LOG_INFO("started ipc thread"); - - while (m_ipcChannel->process()) - { - m_ipcChannel->wait(-1); - } - - if (!m_disconnecting) - { - RIALTO_CLIENT_LOG_ERROR("The ipc channel unexpectedly disconnected, destroying the channel"); - - // Safe to destroy the ipc objects in the ipc thread as the client has already disconnected. - // This ensures the channel is destructed and that all ongoing ipc calls are unblocked. - m_ipcChannel.reset(); - - auto connectionObserver{m_connectionObserver.lock()}; - if (connectionObserver) - { - connectionObserver->onConnectionBroken(); - } - } - - RIALTO_CLIENT_LOG_INFO("exiting ipc thread"); -} - -std::weak_ptr<::firebolt::rialto::ipc::IChannel> IpcClient::getChannel() const -{ - return m_ipcChannel; -} - -std::shared_ptr IpcClient::createBlockingClosure() -{ - // Increase reference in case client disconnects from another thread - std::shared_ptr ipcChannel = m_ipcChannel; - if (!ipcChannel) - { - RIALTO_CLIENT_LOG_ERROR("ipc channel not connected"); - return nullptr; - } - - // check which thread we're being called from, this determines if we pump - // event loop from within the wait() method or not - if (m_ipcThread.get_id() == std::this_thread::get_id()) - return m_blockingClosureFactory->createBlockingClosurePoll(ipcChannel); - else - return m_blockingClosureFactory->createBlockingClosureSemaphore(); -} - -std::shared_ptr IpcClient::createRpcController() -{ - return m_ipcControllerFactory->create(); -} - -bool IpcClient::reconnect() -{ - RIALTO_CLIENT_LOG_INFO("Trying to reconnect channel"); - if (disconnect()) - { - return connect(); - } - return false; -} - -void IpcClient::registerConnectionObserver(const std::weak_ptr &observer) -{ - m_connectionObserver = observer; -} - -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/IpcModule.cpp b/middleware/rialto-client/media/client/ipc/source/IpcModule.cpp deleted file mode 100644 index 11418c640..000000000 --- a/middleware/rialto-client/media/client/ipc/source/IpcModule.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "IpcModule.h" -#include "RialtoClientLogging.h" - -namespace firebolt::rialto::client -{ -IpcModule::IpcModule(IIpcClient &ipcClient) : m_ipc{ipcClient} -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); -} - -IpcModule::~IpcModule() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); -} - -bool IpcModule::unsubscribeFromAllEvents(const std::shared_ptr &ipcChannel) -{ - if (!ipcChannel) - { - return false; - } - - bool result = true; - for (auto it = m_eventTags.begin(); it != m_eventTags.end(); it++) - { - if (!ipcChannel->unsubscribe(*it)) - { - result = false; - } - } - m_eventTags.clear(); - - return result; -} - -bool IpcModule::attachChannel() -{ - // get the channel - std::shared_ptr ipcChannel{getConnectedChannel()}; - - // If not connected, try to recover and reconnect first - if (!ipcChannel) - { - RIALTO_CLIENT_LOG_WARN("Channel not connected. Trying to recover..."); - if (!m_ipc.reconnect()) - { - RIALTO_CLIENT_LOG_ERROR("Reconnection failed."); - return false; - } - - ipcChannel = getConnectedChannel(); - if (!ipcChannel) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get the ipc channel"); - return false; - } - } - - // create the RPC stubs - if (!createRpcStubs(ipcChannel)) - { - RIALTO_CLIENT_LOG_ERROR("Could not create the ipc module stubs"); - return false; - } - - // install listeners - if (!subscribeToEvents(ipcChannel)) - { - RIALTO_CLIENT_LOG_ERROR("Could not subscribe to ipc module events"); - unsubscribeFromAllEvents(ipcChannel); - return false; - } - - m_ipcChannel = ipcChannel; - - return true; -} - -void IpcModule::detachChannel() -{ - // uninstalls listeners - if (!unsubscribeFromAllEvents(m_ipcChannel.lock())) - { - RIALTO_CLIENT_LOG_ERROR("Failed to unsubscribe to some ipc module events, this can lead to core dumps in IPC"); - } - - // remove IPC - m_ipcChannel.reset(); -} - -bool IpcModule::reattachChannelIfRequired() -{ - std::shared_ptr ipcChannel = m_ipcChannel.lock(); - if ((nullptr == ipcChannel) || (!ipcChannel->isConnected())) - { - RIALTO_CLIENT_LOG_INFO("Ipc channel no longer connected, attach new channel"); - detachChannel(); - if (!attachChannel()) - { - RIALTO_CLIENT_LOG_ERROR("Failed attach to the ipc channel"); - return false; - } - } - - return true; -} - -std::shared_ptr IpcModule::getConnectedChannel() -{ - std::shared_ptr ipcChannel = m_ipc.getChannel().lock(); - if (ipcChannel && ipcChannel->isConnected()) - { - return ipcChannel; - } - return nullptr; -} -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/MediaKeysCapabilitiesIpc.cpp b/middleware/rialto-client/media/client/ipc/source/MediaKeysCapabilitiesIpc.cpp deleted file mode 100644 index e5f63a2d0..000000000 --- a/middleware/rialto-client/media/client/ipc/source/MediaKeysCapabilitiesIpc.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaKeysCapabilitiesIpc.h" -#include "RialtoClientLogging.h" - -namespace firebolt::rialto::client -{ -std::weak_ptr MediaKeysCapabilitiesIpcFactory::m_mediaKeysCapabilitiesIpc; -std::mutex MediaKeysCapabilitiesIpcFactory::m_creationMutex; - -std::shared_ptr IMediaKeysCapabilitiesIpcFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys capabilities ipc factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr MediaKeysCapabilitiesIpcFactory::getMediaKeysCapabilitiesIpc() const -{ - std::lock_guard lock{m_creationMutex}; - - std::shared_ptr mediaKeysCapabilitiesIpc = - MediaKeysCapabilitiesIpcFactory::m_mediaKeysCapabilitiesIpc.lock(); - - if (!mediaKeysCapabilitiesIpc) - { - try - { - mediaKeysCapabilitiesIpc = - std::make_shared(IIpcClientAccessor::instance().getIpcClient()); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys capabilities ipc, reason: %s", e.what()); - } - - MediaKeysCapabilitiesIpcFactory::m_mediaKeysCapabilitiesIpc = mediaKeysCapabilitiesIpc; - } - - return mediaKeysCapabilitiesIpc; -} - -MediaKeysCapabilitiesIpc::MediaKeysCapabilitiesIpc(IIpcClient &ipcClient) : IpcModule(ipcClient) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - if (!attachChannel()) - { - throw std::runtime_error("Failed attach to the ipc channel"); - } -} - -MediaKeysCapabilitiesIpc::~MediaKeysCapabilitiesIpc() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - detachChannel(); -} - -bool MediaKeysCapabilitiesIpc::createRpcStubs(const std::shared_ptr &ipcChannel) -{ - m_mediaKeysCapabilitiesStub = - std::make_unique<::firebolt::rialto::MediaKeysCapabilitiesModule_Stub>(ipcChannel.get()); - if (!m_mediaKeysCapabilitiesStub) - { - return false; - } - return true; -} - -std::vector MediaKeysCapabilitiesIpc::getSupportedKeySystems() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return {}; - } - - firebolt::rialto::GetSupportedKeySystemsRequest request; - firebolt::rialto::GetSupportedKeySystemsResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysCapabilitiesStub->getSupportedKeySystems(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get supported key systems due to '%s'", ipcController->ErrorText().c_str()); - return {}; - } - - return std::vector{response.key_systems().begin(), response.key_systems().end()}; -} - -bool MediaKeysCapabilitiesIpc::supportsKeySystem(const std::string &keySystem) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SupportsKeySystemRequest request; - request.set_key_system(keySystem); - - firebolt::rialto::SupportsKeySystemResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysCapabilitiesStub->supportsKeySystem(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to supports key system due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return response.is_supported(); -} - -bool MediaKeysCapabilitiesIpc::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetSupportedKeySystemVersionRequest request; - request.set_key_system(keySystem); - - firebolt::rialto::GetSupportedKeySystemVersionResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysCapabilitiesStub->getSupportedKeySystemVersion(ipcController.get(), &request, &response, - blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get supported key system version due to '%s'", - ipcController->ErrorText().c_str()); - return false; - } - version = response.version(); - - return true; -} - -bool MediaKeysCapabilitiesIpc::isServerCertificateSupported(const std::string &keySystem) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::IsServerCertificateSupportedRequest request; - request.set_key_system(keySystem); - - firebolt::rialto::IsServerCertificateSupportedResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysCapabilitiesStub->isServerCertificateSupported(ipcController.get(), &request, &response, - blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to check if server certificate is supported due to '%s'", - ipcController->ErrorText().c_str()); - return false; - } - - return response.is_supported(); -} - -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/MediaKeysIpc.cpp b/middleware/rialto-client/media/client/ipc/source/MediaKeysIpc.cpp deleted file mode 100644 index 68a8b0e98..000000000 --- a/middleware/rialto-client/media/client/ipc/source/MediaKeysIpc.cpp +++ /dev/null @@ -1,936 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaKeysIpc.h" -#include "RialtoClientLogging.h" - -namespace -{ -firebolt::rialto::MediaKeyErrorStatus -convertMediaKeyErrorStatus(const firebolt::rialto::ProtoMediaKeyErrorStatus &errorStatus) -{ - switch (errorStatus) - { - case firebolt::rialto::ProtoMediaKeyErrorStatus::OK: - { - return firebolt::rialto::MediaKeyErrorStatus::OK; - } - case firebolt::rialto::ProtoMediaKeyErrorStatus::BAD_SESSION_ID: - { - return firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID; - } - case firebolt::rialto::ProtoMediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: - { - return firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED; - } - case firebolt::rialto::ProtoMediaKeyErrorStatus::BUFFER_TOO_SMALL: - { - return firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL; - } - case firebolt::rialto::ProtoMediaKeyErrorStatus::NOT_SUPPORTED: - { - return firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED; - } - case firebolt::rialto::ProtoMediaKeyErrorStatus::INVALID_STATE: - { - return firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE; - } - case firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL: - { - return firebolt::rialto::MediaKeyErrorStatus::FAIL; - } - } - return firebolt::rialto::MediaKeyErrorStatus::FAIL; -} - -firebolt::rialto::KeyStatus convertKeyStatus(const firebolt::rialto::KeyStatusesChangedEvent_KeyStatus &protoKeyStatus) -{ - switch (protoKeyStatus) - { - case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_USABLE: - { - return firebolt::rialto::KeyStatus::USABLE; - } - case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_EXPIRED: - { - return firebolt::rialto::KeyStatus::EXPIRED; - } - case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_OUTPUT_RESTRICTED: - { - return firebolt::rialto::KeyStatus::OUTPUT_RESTRICTED; - } - case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_PENDING: - { - return firebolt::rialto::KeyStatus::PENDING; - } - case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_INTERNAL_ERROR: - { - return firebolt::rialto::KeyStatus::INTERNAL_ERROR; - } - case firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_RELEASED: - { - return firebolt::rialto::KeyStatus::RELEASED; - } - } - return firebolt::rialto::KeyStatus::INTERNAL_ERROR; -} - -const char *toString(const firebolt::rialto::MediaKeyErrorStatus &errorStatus) -{ - switch (errorStatus) - { - case firebolt::rialto::MediaKeyErrorStatus::OK: - { - return "OK"; - } - case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: - { - return "BAD_SESSION_ID"; - } - case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: - { - return "INTERFACE_NOT_IMPLEMENTED"; - } - case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: - { - return "BUFFER_TOO_SMALL"; - } - case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: - { - return "NOT_SUPPORTED"; - } - case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: - { - return "INVALID_STATE"; - } - case firebolt::rialto::MediaKeyErrorStatus::FAIL: - { - return "FAIL"; - } - } - return "UNKNOWN"; -} -} // namespace - -namespace firebolt::rialto::client -{ -std::shared_ptr IMediaKeysIpcFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys ipc factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr MediaKeysIpcFactory::createMediaKeysIpc(const std::string &keySystem) const -{ - std::unique_ptr mediaKeysIpc; - try - { - mediaKeysIpc = - std::make_unique(keySystem, IIpcClientAccessor::instance().getIpcClient(), - firebolt::rialto::common::IEventThreadFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys ipc, reason: %s", e.what()); - } - - return mediaKeysIpc; -} - -MediaKeysIpc::MediaKeysIpc(const std::string &keySystem, IIpcClient &ipcClient, - const std::shared_ptr &eventThreadFactory) - : IpcModule(ipcClient), m_eventThread(eventThreadFactory->createEventThread("rialto-media-keys-events")) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - if (!attachChannel()) - { - throw std::runtime_error("Failed attach to the ipc channel"); - } - - if (!createMediaKeys(keySystem)) - { - detachChannel(); - throw std::runtime_error("Could not create the media keys instance"); - } -} - -MediaKeysIpc::~MediaKeysIpc() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - destroyMediaKeys(); - - detachChannel(); - - m_eventThread.reset(); -} - -bool MediaKeysIpc::createRpcStubs(const std::shared_ptr &ipcChannel) -{ - m_mediaKeysStub = std::make_unique<::firebolt::rialto::MediaKeysModule_Stub>(ipcChannel.get()); - if (!m_mediaKeysStub) - { - return false; - } - return true; -} - -bool MediaKeysIpc::subscribeToEvents(const std::shared_ptr &ipcChannel) -{ - if (!ipcChannel) - { - return false; - } - - int eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaKeysIpc::onLicenseRequest, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaKeysIpc::onLicenseRenewal, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaKeysIpc::onKeyStatusesChanged, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - return true; -} - -bool MediaKeysIpc::createMediaKeys(const std::string &keySystem) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::CreateMediaKeysRequest request; - - request.set_key_system(keySystem); - - firebolt::rialto::CreateMediaKeysResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->createMediaKeys(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to create media keys due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - m_mediaKeysHandle = response.media_keys_handle(); - - return true; -} - -void MediaKeysIpc::destroyMediaKeys() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return; - } - - firebolt::rialto::DestroyMediaKeysRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - - firebolt::rialto::DestroyMediaKeysResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->destroyMediaKeys(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to destroy media keys due to '%s'", ipcController->ErrorText().c_str()); - } -} - -MediaKeyErrorStatus MediaKeysIpc::selectKeyId(int32_t keySessionId, const std::vector &keyId) -{ - RIALTO_CLIENT_LOG_ERROR("Not Implemented"); - return MediaKeyErrorStatus::FAIL; -} - -bool MediaKeysIpc::containsKey(int32_t keySessionId, const std::vector &keyId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::ContainsKeyRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - for (const auto &keyIdItem : keyId) - { - request.add_key_id(keyIdItem); - } - - firebolt::rialto::ContainsKeyResponse response; - // Default return value to false - response.set_contains_key(false); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->containsKey(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("containsKey failed due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return response.contains_key(); -} - -MediaKeyErrorStatus MediaKeysIpc::createKeySession(KeySessionType sessionType, std::weak_ptr client, - bool isLDL, int32_t &keySessionId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - CreateKeySessionRequest_KeySessionType protoSessionType = CreateKeySessionRequest_KeySessionType_UNKNOWN; - switch (sessionType) - { - case KeySessionType::TEMPORARY: - protoSessionType = CreateKeySessionRequest_KeySessionType_TEMPORARY; - break; - case KeySessionType::PERSISTENT_LICENCE: - protoSessionType = CreateKeySessionRequest_KeySessionType_PERSISTENT_LICENCE; - break; - case KeySessionType::PERSISTENT_RELEASE_MESSAGE: - protoSessionType = CreateKeySessionRequest_KeySessionType_PERSISTENT_RELEASE_MESSAGE; - break; - default: - RIALTO_CLIENT_LOG_WARN("Recieved unknown key session type"); - break; - } - - firebolt::rialto::CreateKeySessionRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_session_type(protoSessionType); - request.set_is_ldl(isLDL); - - firebolt::rialto::CreateKeySessionResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->createKeySession(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - MediaKeyErrorStatus status = - getMediaKeyErrorStatusFromResponse("createKeySession", ipcController, response.error_status()); - if (MediaKeyErrorStatus::OK == status) - { - keySessionId = response.key_session_id(); - m_mediaKeysIpcClient = client; - } - - return status; -} - -MediaKeyErrorStatus MediaKeysIpc::generateRequest(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - GenerateRequestRequest_InitDataType protoInitDataType = GenerateRequestRequest_InitDataType_UNKNOWN; - switch (initDataType) - { - case InitDataType::CENC: - protoInitDataType = GenerateRequestRequest_InitDataType_CENC; - break; - case InitDataType::KEY_IDS: - protoInitDataType = GenerateRequestRequest_InitDataType_KEY_IDS; - break; - case InitDataType::WEBM: - protoInitDataType = GenerateRequestRequest_InitDataType_WEBM; - break; - case InitDataType::DRMHEADER: - protoInitDataType = GenerateRequestRequest_InitDataType_DRMHEADER; - break; - default: - RIALTO_CLIENT_LOG_WARN("Recieved unknown init data type"); - break; - } - - firebolt::rialto::GenerateRequestRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - request.set_init_data_type(protoInitDataType); - - for (auto it = initData.begin(); it != initData.end(); it++) - { - request.add_init_data(*it); - } - - firebolt::rialto::GenerateRequestResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->generateRequest(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("generateRequest", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::loadSession(int32_t keySessionId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::LoadSessionRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - - firebolt::rialto::LoadSessionResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->loadSession(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("loadSession", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::updateSession(int32_t keySessionId, const std::vector &responseData) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::UpdateSessionRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - - for (auto it = responseData.begin(); it != responseData.end(); it++) - { - request.add_response_data(*it); - } - - firebolt::rialto::UpdateSessionResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->updateSession(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("updateSession", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::setDrmHeader(int32_t keySessionId, const std::vector &requestData) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::SetDrmHeaderRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - for (const auto &requestDataItem : requestData) - { - request.add_request_data(requestDataItem); - } - - firebolt::rialto::SetDrmHeaderResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->setDrmHeader(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("setDrmHeader", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::closeKeySession(int32_t keySessionId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - // Reset client - m_mediaKeysIpcClient.reset(); - - firebolt::rialto::CloseKeySessionRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - - firebolt::rialto::CloseKeySessionResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->closeKeySession(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("closeKeySession", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::removeKeySession(int32_t keySessionId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::RemoveKeySessionRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - - firebolt::rialto::RemoveKeySessionResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->removeKeySession(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("removeKeySession", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::deleteDrmStore() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::DeleteDrmStoreRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - - firebolt::rialto::DeleteDrmStoreResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->deleteDrmStore(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("deleteDrmStore", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::deleteKeyStore() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::DeleteKeyStoreRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - - firebolt::rialto::DeleteKeyStoreResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->deleteKeyStore(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("deleteKeyStore", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::getDrmStoreHash(std::vector &drmStoreHash) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::GetDrmStoreHashRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - - firebolt::rialto::GetDrmStoreHashResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->getDrmStoreHash(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - if (ProtoMediaKeyErrorStatus::OK == response.error_status()) - { - drmStoreHash = std::vector(response.drm_store_hash().begin(), response.drm_store_hash().end()); - } - - return getMediaKeyErrorStatusFromResponse("getDrmStoreHash", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::getKeyStoreHash(std::vector &keyStoreHash) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::GetKeyStoreHashRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - - firebolt::rialto::GetKeyStoreHashResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->getKeyStoreHash(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - if (ProtoMediaKeyErrorStatus::OK == response.error_status()) - { - keyStoreHash = std::vector(response.key_store_hash().begin(), response.key_store_hash().end()); - } - - return getMediaKeyErrorStatusFromResponse("getKeyStoreHash", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::getLdlSessionsLimit(uint32_t &ldlLimit) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::GetLdlSessionsLimitRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - - firebolt::rialto::GetLdlSessionsLimitResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->getLdlSessionsLimit(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - if (ProtoMediaKeyErrorStatus::OK == response.error_status()) - { - ldlLimit = response.ldl_limit(); - } - - return getMediaKeyErrorStatusFromResponse("getLdlSessionsLimit", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::getLastDrmError(int32_t keySessionId, uint32_t &errorCode) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::GetLastDrmErrorRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - - firebolt::rialto::GetLastDrmErrorResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->getLastDrmError(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - if (ProtoMediaKeyErrorStatus::OK == response.error_status()) - { - errorCode = response.error_code(); - } - - return getMediaKeyErrorStatusFromResponse("getLastDrmError", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::getDrmTime(uint64_t &drmTime) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::GetDrmTimeRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - - firebolt::rialto::GetDrmTimeResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->getDrmTime(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - if (ProtoMediaKeyErrorStatus::OK == response.error_status()) - { - drmTime = response.drm_time(); - } - - return getMediaKeyErrorStatusFromResponse("getDrmTime", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::GetCdmKeySessionIdRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - - firebolt::rialto::GetCdmKeySessionIdResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->getCdmKeySessionId(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - cdmKeySessionId = response.cdm_key_session_id(); - - return getMediaKeyErrorStatusFromResponse("getCdmKeySessionId", ipcController, response.error_status()); -} - -MediaKeyErrorStatus MediaKeysIpc::releaseKeySession(int32_t keySessionId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - // Reset client - m_mediaKeysIpcClient.reset(); - - firebolt::rialto::ReleaseKeySessionRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - request.set_key_session_id(keySessionId); - - firebolt::rialto::ReleaseKeySessionResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->releaseKeySession(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - return getMediaKeyErrorStatusFromResponse("releaseKeySession", ipcController, response.error_status()); -} - -void MediaKeysIpc::onLicenseRequest(const std::shared_ptr &event) -{ - std::shared_ptr mediaKeysIpcClient = m_mediaKeysIpcClient.lock(); - - /* Ignore event if not for this session or no client */ - if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient)) - { - std::vector messageVector = std::vector{event->license_request_message().begin(), - event->license_request_message().end()}; - mediaKeysIpcClient->onLicenseRequest(event->key_session_id(), messageVector, event->url()); - } -} - -void MediaKeysIpc::onLicenseRenewal(const std::shared_ptr &event) -{ - std::shared_ptr mediaKeysIpcClient = m_mediaKeysIpcClient.lock(); - - /* Ignore event if not for this session or no client */ - if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient)) - { - std::vector messageVector = std::vector{event->license_renewal_message().begin(), - event->license_renewal_message().end()}; - mediaKeysIpcClient->onLicenseRenewal(event->key_session_id(), messageVector); - } -} - -void MediaKeysIpc::onKeyStatusesChanged(const std::shared_ptr &event) -{ - std::shared_ptr mediaKeysIpcClient = m_mediaKeysIpcClient.lock(); - - /* Ignore event if not for this session or no client */ - if ((event->media_keys_handle() == m_mediaKeysHandle) && (mediaKeysIpcClient)) - { - KeyStatusVector keyStatuses; - for (auto it = event->key_statuses().begin(); it != event->key_statuses().end(); it++) - { - std::vector keyVector = std::vector{it->key_id().begin(), it->key_id().end()}; - KeyStatus keyStatus = convertKeyStatus(it->key_status()); - keyStatuses.push_back(std::make_pair(keyVector, keyStatus)); - } - mediaKeysIpcClient->onKeyStatusesChanged(event->key_session_id(), keyStatuses); - } -} - -MediaKeyErrorStatus -MediaKeysIpc::getMediaKeyErrorStatusFromResponse(const std::string methodName, - const std::shared_ptr &controller, - ProtoMediaKeyErrorStatus status) -{ - if (controller->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("%s failed due to '%s'", methodName.c_str(), controller->ErrorText().c_str()); - return MediaKeyErrorStatus::FAIL; - } - MediaKeyErrorStatus returnStatus = convertMediaKeyErrorStatus(status); - if (MediaKeyErrorStatus::OK != returnStatus) - { - RIALTO_CLIENT_LOG_ERROR("%s failed due to MediaKeyErrorStatus '%s'", methodName.c_str(), toString(returnStatus)); - return returnStatus; - } - - return returnStatus; -} - -MediaKeyErrorStatus MediaKeysIpc::getMetricSystemData(std::vector &buffer) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return MediaKeyErrorStatus::FAIL; - } - - firebolt::rialto::GetMetricSystemDataRequest request; - request.set_media_keys_handle(m_mediaKeysHandle); - - firebolt::rialto::GetMetricSystemDataResponse response; - // Default error status to FAIL - response.set_error_status(ProtoMediaKeyErrorStatus::FAIL); - - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaKeysStub->getMetricSystemData(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - if (ProtoMediaKeyErrorStatus::OK == response.error_status()) - { - buffer = std::vector(response.buffer().begin(), response.buffer().end()); - } - - return getMediaKeyErrorStatusFromResponse("getMetricSystemData", ipcController, response.error_status()); -} - -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp b/middleware/rialto-client/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp deleted file mode 100644 index e9f7b125a..000000000 --- a/middleware/rialto-client/media/client/ipc/source/MediaPipelineCapabilitiesIpc.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaPipelineCapabilitiesIpc.h" -#include "RialtoClientLogging.h" -#include "RialtoCommonIpc.h" - -namespace firebolt::rialto::client -{ -std::shared_ptr IMediaPipelineCapabilitiesIpcFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media pipeline capabilities ipc factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr MediaPipelineCapabilitiesIpcFactory::createMediaPipelineCapabilitiesIpc() const -{ - std::unique_ptr mediaPipelineCapabilitiesIpc; - - try - { - mediaPipelineCapabilitiesIpc = - std::make_unique(IIpcClientAccessor::instance().getIpcClient()); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media pipeline capabilities ipc, reason: %s", e.what()); - } - - return mediaPipelineCapabilitiesIpc; -} - -MediaPipelineCapabilitiesIpc::MediaPipelineCapabilitiesIpc(IIpcClient &ipcClient) : IpcModule(ipcClient) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - if (!attachChannel()) - { - throw std::runtime_error("Failed attach to the ipc channel"); - } -} - -MediaPipelineCapabilitiesIpc::~MediaPipelineCapabilitiesIpc() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - detachChannel(); -} - -bool MediaPipelineCapabilitiesIpc::createRpcStubs(const std::shared_ptr &ipcChannel) -{ - m_mediaPipelineCapabilitiesStub = - std::make_unique<::firebolt::rialto::MediaPipelineCapabilitiesModule_Stub>(ipcChannel.get()); - if (!m_mediaPipelineCapabilitiesStub) - { - return false; - } - return true; -} - -std::vector MediaPipelineCapabilitiesIpc::getSupportedMimeTypes(MediaSourceType sourceType) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return {}; - } - - firebolt::rialto::GetSupportedMimeTypesRequest request; - request.set_media_type(convertProtoMediaSourceType(sourceType)); - - firebolt::rialto::GetSupportedMimeTypesResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineCapabilitiesStub->getSupportedMimeTypes(ipcController.get(), &request, &response, - blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get supported mime types due to '%s'", ipcController->ErrorText().c_str()); - return {}; - } - - return std::vector{response.mime_types().begin(), response.mime_types().end()}; -} - -bool MediaPipelineCapabilitiesIpc::isMimeTypeSupported(const std::string &mimeType) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::IsMimeTypeSupportedRequest request; - request.set_mime_type(mimeType); - - firebolt::rialto::IsMimeTypeSupportedResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineCapabilitiesStub->isMimeTypeSupported(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to check if mime type '%s' is supported due to '%s'", mimeType.c_str(), - ipcController->ErrorText().c_str()); - return false; - } - - return response.is_supported(); -} - -std::vector MediaPipelineCapabilitiesIpc::getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return {}; - } - - firebolt::rialto::GetSupportedPropertiesRequest request; - request.set_media_type(convertProtoMediaSourceType(mediaType)); - for (const std::string &property : propertyNames) - request.add_property_names(property); - - firebolt::rialto::GetSupportedPropertiesResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineCapabilitiesStub->getSupportedProperties(ipcController.get(), &request, &response, - blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed due to '%s'", ipcController->ErrorText().c_str()); - return std::vector{}; - } - - return std::vector{response.supported_properties().begin(), response.supported_properties().end()}; -} - -bool MediaPipelineCapabilitiesIpc::isVideoMaster(bool &isVideoMaster) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return {}; - } - - firebolt::rialto::IsVideoMasterRequest request; - firebolt::rialto::IsVideoMasterResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineCapabilitiesStub->isVideoMaster(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - isVideoMaster = response.is_video_master(); - - return true; -} -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/MediaPipelineIpc.cpp b/middleware/rialto-client/media/client/ipc/source/MediaPipelineIpc.cpp deleted file mode 100644 index 4ce1930e9..000000000 --- a/middleware/rialto-client/media/client/ipc/source/MediaPipelineIpc.cpp +++ /dev/null @@ -1,1910 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "MediaPipelineIpc.h" -#include "RialtoClientLogging.h" -#include "RialtoCommonIpc.h" -#include "mediapipelinemodule.pb.h" -#include -#include - -namespace firebolt::rialto::client -{ -std::weak_ptr MediaPipelineIpcFactory::m_factory; - -std::shared_ptr IMediaPipelineIpcFactory::getFactory() -{ - std::shared_ptr factory = MediaPipelineIpcFactory::m_factory.lock(); - - if (!factory) - { - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media player ipc factory, reason: %s", e.what()); - } - - MediaPipelineIpcFactory::m_factory = factory; - } - - return factory; -} - -std::unique_ptr MediaPipelineIpcFactory::createMediaPipelineIpc( - IMediaPipelineIpcClient *client, const VideoRequirements &videoRequirements, std::weak_ptr ipcClientParam) -{ - std::unique_ptr mediaPipelineIpc; - try - { - std::shared_ptr ipcClient = ipcClientParam.lock(); - mediaPipelineIpc = - std::make_unique(client, videoRequirements, - ipcClient ? *ipcClient : IIpcClientAccessor::instance().getIpcClient(), - firebolt::rialto::common::IEventThreadFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media player ipc, reason: %s", e.what()); - } - - return mediaPipelineIpc; -} - -MediaPipelineIpc::MediaPipelineIpc(IMediaPipelineIpcClient *client, const VideoRequirements &videoRequirements, - IIpcClient &ipcClient, - const std::shared_ptr &eventThreadFactory) - : IpcModule(ipcClient), m_mediaPipelineIpcClient(client), - m_eventThread(eventThreadFactory->createEventThread("rialto-media-player-events")) -{ - if (!attachChannel()) - { - throw std::runtime_error("Failed attach to the ipc channel"); - } - - // create media player session - if (!createSession(videoRequirements)) - { - detachChannel(); - throw std::runtime_error("Could not create the media player session"); - } -} - -MediaPipelineIpc::~MediaPipelineIpc() -{ - // destroy media player session - destroySession(); - - // detach the Ipc channel - detachChannel(); - - // destroy the thread processing async notifications - m_eventThread.reset(); -} - -bool MediaPipelineIpc::createRpcStubs(const std::shared_ptr &ipcChannel) -{ - m_mediaPipelineStub = std::make_unique<::firebolt::rialto::MediaPipelineModule_Stub>(ipcChannel.get()); - if (!m_mediaPipelineStub) - { - return false; - } - return true; -} - -bool MediaPipelineIpc::subscribeToEvents(const std::shared_ptr &ipcChannel) -{ - if (!ipcChannel) - { - return false; - } - - int eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaPipelineIpc::onPlaybackStateUpdated, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaPipelineIpc::onPositionUpdated, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaPipelineIpc::onNetworkStateUpdated, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaPipelineIpc::onNeedMediaData, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaPipelineIpc::onQos, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaPipelineIpc::onBufferUnderflow, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaPipelineIpc::onPlaybackError, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&MediaPipelineIpc::onSourceFlushed, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - return true; -} - -bool MediaPipelineIpc::load(MediaType type, const std::string &mimeType, const std::string &url) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::LoadRequest request; - - request.set_session_id(m_sessionId); - request.set_type(convertLoadRequestMediaType(type)); - request.set_mime_type(mimeType); - request.set_url(url); - - firebolt::rialto::LoadResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->load(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to load media due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::attachSource(const std::unique_ptr &source, int32_t &sourceId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::AttachSourceRequest request; - - request.set_session_id(m_sessionId); - request.set_switch_source(false); - if (!buildAttachSourceRequest(request, source)) - { - RIALTO_CLIENT_LOG_ERROR("Failed to parse source"); - return false; - } - - firebolt::rialto::AttachSourceResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->attachSource(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to attach source due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - sourceId = response.source_id(); - - return true; -} - -bool MediaPipelineIpc::removeSource(int32_t sourceId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::RemoveSourceRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - - firebolt::rialto::RemoveSourceResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->removeSource(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to remove source due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::allSourcesAttached() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::AllSourcesAttachedRequest request; - request.set_session_id(m_sessionId); - - firebolt::rialto::AllSourcesAttachedResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->allSourcesAttached(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to notify about all sources attached due to '%s'", - ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetVideoWindowRequest request; - - request.set_session_id(m_sessionId); - request.set_x(x); - request.set_y(y); - request.set_width(width); - request.set_height(height); - - firebolt::rialto::SetVideoWindowResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setVideoWindow(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set the video window due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::play() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::PlayRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::PlayResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->play(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to play due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::pause() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::PauseRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::PauseResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->pause(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to pause due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::stop() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::StopRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::StopResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->stop(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to stop due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t requestId) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::HaveDataRequest request; - - request.set_session_id(m_sessionId); - request.set_status(convertHaveDataRequestMediaSourceStatus(status)); - request.set_num_frames(numFrames); - request.set_request_id(requestId); - - firebolt::rialto::HaveDataResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->haveData(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to stop due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::setPosition(int64_t position) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetPositionRequest request; - - request.set_session_id(m_sessionId); - request.set_position(position); - - firebolt::rialto::SetPositionResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setPosition(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set position due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getPosition(int64_t &position) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetPositionRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::GetPositionResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getPosition(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get position due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - position = response.position(); - return true; -} - -bool MediaPipelineIpc::setImmediateOutput(int32_t sourceId, bool immediateOutput) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetImmediateOutputRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - request.set_immediate_output(immediateOutput); - - firebolt::rialto::SetImmediateOutputResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setImmediateOutput(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set immediate-output due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getImmediateOutput(int32_t sourceId, bool &immediateOutput) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetImmediateOutputRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - - firebolt::rialto::GetImmediateOutputResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getImmediateOutput(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get immediate-output due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - else - { - immediateOutput = response.immediate_output(); - } - - return true; -} - -bool MediaPipelineIpc::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetStatsRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - - firebolt::rialto::GetStatsResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getStats(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get stats due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - renderedFrames = response.rendered_frames(); - droppedFrames = response.dropped_frames(); - return true; -} - -bool MediaPipelineIpc::setPlaybackRate(double rate) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetPlaybackRateRequest request; - - request.set_session_id(m_sessionId); - request.set_rate(rate); - - firebolt::rialto::SetPlaybackRateResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setPlaybackRate(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set playback rate due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::renderFrame() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::RenderFrameRequest request; - request.set_session_id(m_sessionId); - - firebolt::rialto::RenderFrameResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->renderFrame(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to render frame due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetVolumeRequest request; - - request.set_session_id(m_sessionId); - request.set_volume(targetVolume); - request.set_volume_duration(volumeDuration); - request.set_ease_type(convertEaseType(easeType)); - - firebolt::rialto::SetVolumeResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setVolume(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set volume due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getVolume(double &volume) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetVolumeRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::GetVolumeResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getVolume(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get volume due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - volume = response.volume(); - - return true; -} - -bool MediaPipelineIpc::setMute(int32_t sourceId, bool mute) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetMuteRequest request; - - request.set_session_id(m_sessionId); - request.set_mute(mute); - request.set_source_id(sourceId); - - firebolt::rialto::SetMuteResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setMute(ipcController.get(), &request, &response, blockingClosure.get()); - - // waiting for call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set mute due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getMute(std::int32_t sourceId, bool &mute) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetMuteRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - - firebolt::rialto::GetMuteResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getMute(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get mute due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - mute = response.mute(); - - return true; -} - -bool MediaPipelineIpc::setTextTrackIdentifier(const std::string &textTrackIdentifier) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetTextTrackIdentifierRequest request; - - request.set_session_id(m_sessionId); - request.set_text_track_identifier(textTrackIdentifier); - - firebolt::rialto::SetTextTrackIdentifierResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setTextTrackIdentifier(ipcController.get(), &request, &response, blockingClosure.get()); - - // waiting for call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set text track identifier due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getTextTrackIdentifier(std::string &textTrackIdentifier) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetTextTrackIdentifierRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::GetTextTrackIdentifierResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getTextTrackIdentifier(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get mute due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - textTrackIdentifier = response.text_track_identifier(); - - return true; -} - -bool MediaPipelineIpc::setLowLatency(bool lowLatency) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetLowLatencyRequest request; - - request.set_session_id(m_sessionId); - request.set_low_latency(lowLatency); - - firebolt::rialto::SetLowLatencyResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setLowLatency(ipcController.get(), &request, &response, blockingClosure.get()); - // waiting for call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set low-latency due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::setSync(bool sync) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetSyncRequest request; - - request.set_session_id(m_sessionId); - request.set_sync(sync); - - firebolt::rialto::SetSyncResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setSync(ipcController.get(), &request, &response, blockingClosure.get()); - - // waiting for call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set sync due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getSync(bool &sync) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetSyncRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::GetSyncResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getSync(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get sync due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - sync = response.sync(); - - return true; -} - -bool MediaPipelineIpc::setSyncOff(bool syncOff) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetSyncOffRequest request; - - request.set_session_id(m_sessionId); - request.set_sync_off(syncOff); - - firebolt::rialto::SetSyncOffResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setSyncOff(ipcController.get(), &request, &response, blockingClosure.get()); - - // waiting for call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set sync-off due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetStreamSyncModeRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - request.set_stream_sync_mode(streamSyncMode); - - firebolt::rialto::SetStreamSyncModeResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setStreamSyncMode(ipcController.get(), &request, &response, blockingClosure.get()); - - // waiting for call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set stream-sync-mode due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getStreamSyncMode(int32_t &streamSyncMode) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetStreamSyncModeRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::GetStreamSyncModeResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getStreamSyncMode(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get stream-sync-mode due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - streamSyncMode = response.stream_sync_mode(); - - return true; -} - -bool MediaPipelineIpc::flush(int32_t sourceId, bool resetTime, bool &async) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::FlushRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - request.set_reset_time(resetTime); - - firebolt::rialto::FlushResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->flush(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to flush due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - // Async is true by default - async = response.has_async() ? response.async() : true; - - return true; -} - -bool MediaPipelineIpc::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetSourcePositionRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - request.set_position(position); - request.set_reset_time(resetTime); - request.set_applied_rate(appliedRate); - request.set_stop_position(stopPosition); - - firebolt::rialto::SetSourcePositionResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setSourcePosition(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set source position due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::setSubtitleOffset(int32_t sourceId, int64_t position) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetSubtitleOffsetRequest request; - - request.set_session_id(m_sessionId); - request.set_source_id(sourceId); - request.set_position(position); - - firebolt::rialto::SetSubtitleOffsetResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setSubtitleOffset(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set subtitle offset due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::ProcessAudioGapRequest request; - - request.set_session_id(m_sessionId); - request.set_position(position); - request.set_duration(duration); - request.set_discontinuity_gap(discontinuityGap); - request.set_audio_aac(audioAac); - - firebolt::rialto::ProcessAudioGapResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->processAudioGap(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to process audio gap due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::setBufferingLimit(uint32_t limitBufferingMs) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetBufferingLimitRequest request; - - request.set_session_id(m_sessionId); - request.set_limit_buffering_ms(limitBufferingMs); - - firebolt::rialto::SetBufferingLimitResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setBufferingLimit(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set buffering limit due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getBufferingLimit(uint32_t &limitBufferingMs) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetBufferingLimitRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::GetBufferingLimitResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getBufferingLimit(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get buffering limit due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - limitBufferingMs = response.limit_buffering_ms(); - - return true; -} - -bool MediaPipelineIpc::setUseBuffering(bool useBuffering) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::SetUseBufferingRequest request; - - request.set_session_id(m_sessionId); - request.set_use_buffering(useBuffering); - - firebolt::rialto::SetUseBufferingResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->setUseBuffering(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to set use buffering due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool MediaPipelineIpc::getUseBuffering(bool &useBuffering) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::GetUseBufferingRequest request; - - request.set_session_id(m_sessionId); - - firebolt::rialto::GetUseBufferingResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->getUseBuffering(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to get use buffering due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - useBuffering = response.use_buffering(); - - return true; -} - -bool MediaPipelineIpc::switchSource(const std::unique_ptr &source) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::AttachSourceRequest request; - - request.set_session_id(m_sessionId); - request.set_switch_source(true); - if (!buildAttachSourceRequest(request, source)) - { - RIALTO_CLIENT_LOG_ERROR("Failed to parse source"); - return false; - } - - firebolt::rialto::AttachSourceResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->attachSource(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to attach source due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -void MediaPipelineIpc::onPlaybackStateUpdated(const std::shared_ptr &event) -{ - /* Ignore event if not for this session */ - if (event->session_id() == m_sessionId) - { - PlaybackState playbackState = PlaybackState::UNKNOWN; - switch (event->state()) - { - case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_IDLE: - playbackState = PlaybackState::IDLE; - break; - case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PLAYING: - playbackState = PlaybackState::PLAYING; - break; - case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PAUSED: - playbackState = PlaybackState::PAUSED; - break; - case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEKING: - playbackState = PlaybackState::SEEKING; - break; - case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEK_DONE: - playbackState = PlaybackState::SEEK_DONE; - break; - case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_STOPPED: - playbackState = PlaybackState::STOPPED; - break; - case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_END_OF_STREAM: - playbackState = PlaybackState::END_OF_STREAM; - break; - case firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_FAILURE: - playbackState = PlaybackState::FAILURE; - break; - default: - RIALTO_CLIENT_LOG_WARN("Received unknown playback state"); - break; - } - - m_mediaPipelineIpcClient->notifyPlaybackState(playbackState); - } -} - -void MediaPipelineIpc::onPositionUpdated(const std::shared_ptr &event) -{ - // Ignore event if not for this session - if (event->session_id() == m_sessionId) - { - int64_t position = event->position(); - m_mediaPipelineIpcClient->notifyPosition(position); - } -} - -void MediaPipelineIpc::onNetworkStateUpdated(const std::shared_ptr &event) -{ - // Ignore event if not for this session - if (event->session_id() == m_sessionId) - { - NetworkState networkState = NetworkState::UNKNOWN; - switch (event->state()) - { - case firebolt::rialto::NetworkStateChangeEvent_NetworkState_IDLE: - networkState = NetworkState::IDLE; - break; - case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING: - networkState = NetworkState::BUFFERING; - break; - case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING_PROGRESS: - networkState = NetworkState::BUFFERING_PROGRESS; - break; - case firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERED: - networkState = NetworkState::BUFFERED; - break; - case firebolt::rialto::NetworkStateChangeEvent_NetworkState_STALLED: - networkState = NetworkState::STALLED; - break; - case firebolt::rialto::NetworkStateChangeEvent_NetworkState_FORMAT_ERROR: - networkState = NetworkState::FORMAT_ERROR; - break; - case firebolt::rialto::NetworkStateChangeEvent_NetworkState_NETWORK_ERROR: - networkState = NetworkState::NETWORK_ERROR; - break; - default: - RIALTO_CLIENT_LOG_WARN("Received unknown network state"); - break; - } - - m_mediaPipelineIpcClient->notifyNetworkState(networkState); - } -} - -void MediaPipelineIpc::onNeedMediaData(const std::shared_ptr &event) -{ - // Ignore event if not for this session - if (event->session_id() == m_sessionId) - { - std::shared_ptr shmInfo; - if (event->has_shm_info()) - { - shmInfo = std::make_shared(); - shmInfo->maxMetadataBytes = event->shm_info().max_metadata_bytes(); - shmInfo->metadataOffset = event->shm_info().metadata_offset(); - shmInfo->mediaDataOffset = event->shm_info().media_data_offset(); - shmInfo->maxMediaBytes = event->shm_info().max_media_bytes(); - } - m_mediaPipelineIpcClient->notifyNeedMediaData(event->source_id(), event->frame_count(), event->request_id(), - shmInfo); - } -} - -void MediaPipelineIpc::onQos(const std::shared_ptr &event) -{ - // Ignore event if not for this session - if (event->session_id() == m_sessionId) - { - QosInfo qosInfo = {event->qos_info().processed(), event->qos_info().dropped()}; - m_mediaPipelineIpcClient->notifyQos(event->source_id(), qosInfo); - } -} - -void MediaPipelineIpc::onBufferUnderflow(const std::shared_ptr &event) -{ - // Ignore event if not for this session - if (event->session_id() == m_sessionId) - { - m_mediaPipelineIpcClient->notifyBufferUnderflow(event->source_id()); - } -} - -void MediaPipelineIpc::onPlaybackError(const std::shared_ptr &event) -{ - // Ignore event if not for this session - if (event->session_id() == m_sessionId) - { - PlaybackError playbackError = PlaybackError::UNKNOWN; - switch (event->error()) - { - case firebolt::rialto::PlaybackErrorEvent_PlaybackError_DECRYPTION: - playbackError = PlaybackError::DECRYPTION; - break; - default: - RIALTO_CLIENT_LOG_WARN("Received unknown playback error"); - break; - } - - m_mediaPipelineIpcClient->notifyPlaybackError(event->source_id(), playbackError); - } -} - -void MediaPipelineIpc::onSourceFlushed(const std::shared_ptr &event) -{ - // Ignore event if not for this session - if (event->session_id() == m_sessionId) - { - m_mediaPipelineIpcClient->notifySourceFlushed(event->source_id()); - } -} - -bool MediaPipelineIpc::createSession(const VideoRequirements &videoRequirements) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::CreateSessionRequest request; - - request.set_max_width(videoRequirements.maxWidth); - request.set_max_height(videoRequirements.maxHeight); - - firebolt::rialto::CreateSessionResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->createSession(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to create session due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - m_sessionId = response.session_id(); - - return true; -} - -void MediaPipelineIpc::destroySession() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return; - } - - firebolt::rialto::DestroySessionRequest request; - request.set_session_id(m_sessionId); - - firebolt::rialto::DestroySessionResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_mediaPipelineStub->destroySession(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("failed to destroy session due to '%s'", ipcController->ErrorText().c_str()); - } -} - -firebolt::rialto::LoadRequest_MediaType MediaPipelineIpc::convertLoadRequestMediaType(MediaType mediaType) const -{ - firebolt::rialto::LoadRequest_MediaType protoMediaType = firebolt::rialto::LoadRequest_MediaType_UNKNOWN; - switch (mediaType) - { - case MediaType::MSE: - protoMediaType = firebolt::rialto::LoadRequest_MediaType_MSE; - break; - default: - break; - } - - return protoMediaType; -} - -firebolt::rialto::HaveDataRequest_MediaSourceStatus -MediaPipelineIpc::convertHaveDataRequestMediaSourceStatus(MediaSourceStatus status) const -{ - firebolt::rialto::HaveDataRequest_MediaSourceStatus protoMediaSourceStatus = - firebolt::rialto::HaveDataRequest_MediaSourceStatus_UNKNOWN; - switch (status) - { - case MediaSourceStatus::OK: - protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_OK; - break; - case MediaSourceStatus::EOS: - protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_EOS; - break; - case MediaSourceStatus::ERROR: - protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_ERROR; - break; - case MediaSourceStatus::CODEC_CHANGED: - protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_CODEC_CHANGED; - break; - case MediaSourceStatus::NO_AVAILABLE_SAMPLES: - protoMediaSourceStatus = firebolt::rialto::HaveDataRequest_MediaSourceStatus_NO_AVAILABLE_SAMPLES; - break; - default: - break; - } - - return protoMediaSourceStatus; -} - -firebolt::rialto::AttachSourceRequest_ConfigType -MediaPipelineIpc::convertConfigType(const firebolt::rialto::SourceConfigType &configType) const -{ - switch (configType) - { - case firebolt::rialto::SourceConfigType::UNKNOWN: - { - return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_UNKNOWN; - } - case firebolt::rialto::SourceConfigType::AUDIO: - { - return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_AUDIO; - } - case firebolt::rialto::SourceConfigType::VIDEO: - { - return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO; - } - case firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION: - { - return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO_DOLBY_VISION; - } - case firebolt::rialto::SourceConfigType::SUBTITLE: - { - return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_SUBTITLE; - } - } - return firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_UNKNOWN; -} - -firebolt::rialto::SetVolumeRequest_EaseType MediaPipelineIpc::convertEaseType(const firebolt::rialto::EaseType &easeType) const -{ - switch (easeType) - { - case firebolt::rialto::EaseType::EASE_LINEAR: - { - return firebolt::rialto::SetVolumeRequest_EaseType_EASE_LINEAR; - } - case firebolt::rialto::EaseType::EASE_IN_CUBIC: - { - return firebolt::rialto::SetVolumeRequest_EaseType_EASE_IN_CUBIC; - } - case firebolt::rialto::EaseType::EASE_OUT_CUBIC: - { - return firebolt::rialto::SetVolumeRequest_EaseType_EASE_OUT_CUBIC; - } - } - return firebolt::rialto::SetVolumeRequest_EaseType_EASE_LINEAR; -} - -firebolt::rialto::AttachSourceRequest_SegmentAlignment -MediaPipelineIpc::convertSegmentAlignment(const firebolt::rialto::SegmentAlignment &alignment) const -{ - switch (alignment) - { - case firebolt::rialto::SegmentAlignment::UNDEFINED: - { - return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_UNDEFINED; - } - case firebolt::rialto::SegmentAlignment::NAL: - { - return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_NAL; - } - case firebolt::rialto::SegmentAlignment::AU: - { - return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_AU; - } - } - return firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_UNDEFINED; -} - -firebolt::rialto::AttachSourceRequest_StreamFormat -MediaPipelineIpc::convertStreamFormat(const firebolt::rialto::StreamFormat &streamFormat) const -{ - switch (streamFormat) - { - case firebolt::rialto::StreamFormat::UNDEFINED: - { - return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_UNDEFINED; - } - case firebolt::rialto::StreamFormat::RAW: - { - return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_RAW; - } - case firebolt::rialto::StreamFormat::AVC: - { - return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_AVC; - } - case firebolt::rialto::StreamFormat::BYTE_STREAM: - { - return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_BYTE_STREAM; - } - case firebolt::rialto::StreamFormat::HVC1: - { - return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HVC1; - } - case firebolt::rialto::StreamFormat::HEV1: - { - return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HEV1; - } - } - return firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_UNDEFINED; -} - -firebolt::rialto::AttachSourceRequest_CodecData_Type -MediaPipelineIpc::convertCodecDataType(const firebolt::rialto::CodecDataType &codecDataType) const -{ - if (firebolt::rialto::CodecDataType::STRING == codecDataType) - { - return firebolt::rialto::AttachSourceRequest_CodecData_Type_STRING; - } - return firebolt::rialto::AttachSourceRequest_CodecData_Type_BUFFER; -} - -firebolt::rialto::AttachSourceRequest_AudioConfig_Format -MediaPipelineIpc::convertFormat(const firebolt::rialto::Format &format) const -{ - static const std::unordered_map - kFormatConversionMap{ - {firebolt::rialto::Format::S8, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S8}, - {firebolt::rialto::Format::U8, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U8}, - {firebolt::rialto::Format::S16LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16LE}, - {firebolt::rialto::Format::S16BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16BE}, - {firebolt::rialto::Format::U16LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16LE}, - {firebolt::rialto::Format::U16BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16BE}, - {firebolt::rialto::Format::S24_32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32LE}, - {firebolt::rialto::Format::S24_32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32BE}, - {firebolt::rialto::Format::U24_32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32LE}, - {firebolt::rialto::Format::U24_32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32BE}, - {firebolt::rialto::Format::S32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32LE}, - {firebolt::rialto::Format::S32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32BE}, - {firebolt::rialto::Format::U32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32LE}, - {firebolt::rialto::Format::U32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32BE}, - {firebolt::rialto::Format::S24LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24LE}, - {firebolt::rialto::Format::S24BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24BE}, - {firebolt::rialto::Format::U24LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24LE}, - {firebolt::rialto::Format::U24BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24BE}, - {firebolt::rialto::Format::S20LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20LE}, - {firebolt::rialto::Format::S20BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20BE}, - {firebolt::rialto::Format::U20LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20LE}, - {firebolt::rialto::Format::U20BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20BE}, - {firebolt::rialto::Format::S18LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18LE}, - {firebolt::rialto::Format::S18BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18BE}, - {firebolt::rialto::Format::U18LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18LE}, - {firebolt::rialto::Format::U18BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18BE}, - {firebolt::rialto::Format::F32LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32LE}, - {firebolt::rialto::Format::F32BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32BE}, - {firebolt::rialto::Format::F64LE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64LE}, - {firebolt::rialto::Format::F64BE, firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64BE}}; - const auto kIt = kFormatConversionMap.find(format); - if (kFormatConversionMap.end() != kIt) - { - return kIt->second; - } - return firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S8; -} - -firebolt::rialto::AttachSourceRequest_AudioConfig_Layout -MediaPipelineIpc::convertLayout(const firebolt::rialto::Layout &layout) const -{ - static const std::unordered_map - kLayoutConversionMap{{firebolt::rialto::Layout::INTERLEAVED, - firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_INTERLEAVED}, - {firebolt::rialto::Layout::NON_INTERLEAVED, - firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_NON_INTERLEAVED}}; - const auto kIt = kLayoutConversionMap.find(layout); - if (kLayoutConversionMap.end() != kIt) - { - return kIt->second; - } - return firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_INTERLEAVED; -} - -bool MediaPipelineIpc::buildAttachSourceRequest(firebolt::rialto::AttachSourceRequest &request, - const std::unique_ptr &source) const -{ - SourceConfigType configType = source->getConfigType(); - request.set_config_type(convertConfigType(configType)); - request.set_mime_type(source->getMimeType()); - request.set_has_drm(source->getHasDrm()); - - if (configType == SourceConfigType::VIDEO_DOLBY_VISION || configType == SourceConfigType::VIDEO || - configType == SourceConfigType::AUDIO) - { - IMediaPipeline::MediaSourceAV *mediaSourceAV = dynamic_cast(source.get()); - if (!mediaSourceAV) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get the audio video source"); - return false; - } - request.set_segment_alignment(convertSegmentAlignment(mediaSourceAV->getSegmentAlignment())); - - if (mediaSourceAV->getCodecData()) - { - request.mutable_codec_data()->set_data(mediaSourceAV->getCodecData()->data.data(), - mediaSourceAV->getCodecData()->data.size()); - request.mutable_codec_data()->set_type(convertCodecDataType(mediaSourceAV->getCodecData()->type)); - } - request.set_stream_format(convertStreamFormat(mediaSourceAV->getStreamFormat())); - - if (configType == SourceConfigType::VIDEO_DOLBY_VISION) - { - IMediaPipeline::MediaSourceVideoDolbyVision *mediaSourceDolby = - dynamic_cast(source.get()); - if (!mediaSourceDolby) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get the video dolby vision media source"); - return false; - } - request.set_width(mediaSourceDolby->getWidth()); - request.set_height(mediaSourceDolby->getHeight()); - request.set_dolby_vision_profile(mediaSourceDolby->getDolbyVisionProfile()); - } - else if (configType == SourceConfigType::VIDEO) - { - IMediaPipeline::MediaSourceVideo *mediaSourceVideo = - dynamic_cast(source.get()); - if (!mediaSourceVideo) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get the video media source"); - return false; - } - request.set_width(mediaSourceVideo->getWidth()); - request.set_height(mediaSourceVideo->getHeight()); - } - else if (configType == SourceConfigType::AUDIO) - { - IMediaPipeline::MediaSourceAudio *mediaSourceAudio = - dynamic_cast(source.get()); - if (!mediaSourceAudio) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get the audio media source"); - return false; - } - request.mutable_audio_config()->set_number_of_channels(mediaSourceAudio->getAudioConfig().numberOfChannels); - request.mutable_audio_config()->set_sample_rate(mediaSourceAudio->getAudioConfig().sampleRate); - if (!mediaSourceAudio->getAudioConfig().codecSpecificConfig.empty()) - { - request.mutable_audio_config() - ->set_codec_specific_config(mediaSourceAudio->getAudioConfig().codecSpecificConfig.data(), - mediaSourceAudio->getAudioConfig().codecSpecificConfig.size()); - } - if (mediaSourceAudio->getAudioConfig().format.has_value()) - { - request.mutable_audio_config()->set_format( - convertFormat(mediaSourceAudio->getAudioConfig().format.value())); - } - if (mediaSourceAudio->getAudioConfig().layout.has_value()) - { - request.mutable_audio_config()->set_layout( - convertLayout(mediaSourceAudio->getAudioConfig().layout.value())); - } - if (mediaSourceAudio->getAudioConfig().channelMask.has_value()) - { - request.mutable_audio_config()->set_channel_mask(mediaSourceAudio->getAudioConfig().channelMask.value()); - } - for (auto &header : mediaSourceAudio->getAudioConfig().streamHeader) - { - request.mutable_audio_config()->add_stream_header(header.data(), header.size()); - } - if (mediaSourceAudio->getAudioConfig().framed.has_value()) - { - request.mutable_audio_config()->set_framed(mediaSourceAudio->getAudioConfig().framed.value()); - } - } - } - else if (configType == SourceConfigType::SUBTITLE) - { - IMediaPipeline::MediaSourceSubtitle *mediaSourceSubtitle = - dynamic_cast(source.get()); - if (!mediaSourceSubtitle) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get the subtitle source"); - return false; - } - request.set_text_track_identifier(mediaSourceSubtitle->getTextTrackIdentifier()); - } - else - { - RIALTO_CLIENT_LOG_ERROR("Unknown source type"); - return false; - } - return true; -} -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/RialtoCommonIpc.cpp b/middleware/rialto-client/media/client/ipc/source/RialtoCommonIpc.cpp deleted file mode 100644 index 911b474d2..000000000 --- a/middleware/rialto-client/media/client/ipc/source/RialtoCommonIpc.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "RialtoCommonIpc.h" - -namespace firebolt::rialto::client -{ -firebolt::rialto::ProtoMediaSourceType convertProtoMediaSourceType(MediaSourceType mediaSourceType) -{ - firebolt::rialto::ProtoMediaSourceType protoMediaSourceType = firebolt::rialto::ProtoMediaSourceType::UNKNOWN; - switch (mediaSourceType) - { - case MediaSourceType::AUDIO: - protoMediaSourceType = firebolt::rialto::ProtoMediaSourceType::AUDIO; - break; - case MediaSourceType::VIDEO: - protoMediaSourceType = firebolt::rialto::ProtoMediaSourceType::VIDEO; - break; - case MediaSourceType::SUBTITLE: - protoMediaSourceType = firebolt::rialto::ProtoMediaSourceType::SUBTITLE; - break; - default: - break; - } - - return protoMediaSourceType; -} -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/ipc/source/WebAudioPlayerIpc.cpp b/middleware/rialto-client/media/client/ipc/source/WebAudioPlayerIpc.cpp deleted file mode 100644 index ad1fa7903..000000000 --- a/middleware/rialto-client/media/client/ipc/source/WebAudioPlayerIpc.cpp +++ /dev/null @@ -1,513 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "WebAudioPlayerIpc.h" -#include "RialtoClientLogging.h" -#include "RialtoCommonIpc.h" -#include "webaudioplayermodule.pb.h" -#include - -namespace firebolt::rialto::client -{ - -std::shared_ptr IWebAudioPlayerIpcFactory::getFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player ipc factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr -WebAudioPlayerIpcFactory::createWebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config, - std::weak_ptr ipcClientParam) -{ - std::unique_ptr webAudioPlayerIpc; - try - { - std::shared_ptr ipcClient = ipcClientParam.lock(); - webAudioPlayerIpc = - std::make_unique(client, audioMimeType, priority, config, - ipcClient ? *ipcClient : IIpcClientAccessor::instance().getIpcClient(), - firebolt::rialto::common::IEventThreadFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player ipc, reason: %s", e.what()); - } - - return webAudioPlayerIpc; -} - -WebAudioPlayerIpc::WebAudioPlayerIpc(IWebAudioPlayerIpcClient *client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config, - IIpcClient &ipcClient, - const std::shared_ptr &eventThreadFactory) - : IpcModule(ipcClient), m_webAudioPlayerIpcClient(client), - m_eventThread(eventThreadFactory->createEventThread("rialto-web-audio-player-events")), m_webAudioPlayerHandle(-1) -{ - if (!attachChannel()) - { - throw std::runtime_error("Failed attach to the ipc channel"); - } - - if (!createWebAudioPlayer(audioMimeType, priority, config)) - { - detachChannel(); - throw std::runtime_error("Could not create the web audio player"); - } -} - -WebAudioPlayerIpc::~WebAudioPlayerIpc() -{ - // destroy web audio player session - destroyWebAudioPlayer(); - - // detach the Ipc channel - detachChannel(); - - // destroy the thread processing async notifications - m_eventThread.reset(); -} - -bool WebAudioPlayerIpc::createRpcStubs(const std::shared_ptr &ipcChannel) -{ - m_webAudioPlayerStub = std::make_unique<::firebolt::rialto::WebAudioPlayerModule_Stub>(ipcChannel.get()); - if (!m_webAudioPlayerStub) - { - return false; - } - return true; -} - -bool WebAudioPlayerIpc::subscribeToEvents(const std::shared_ptr &ipcChannel) -{ - if (!ipcChannel) - { - return false; - } - - int eventTag = ipcChannel->subscribe( - [this](const std::shared_ptr &event) - { m_eventThread->add(&WebAudioPlayerIpc::onPlaybackStateUpdated, this, event); }); - if (eventTag < 0) - return false; - m_eventTags.push_back(eventTag); - - return true; -} - -void WebAudioPlayerIpc::onPlaybackStateUpdated(const std::shared_ptr &event) -{ - if (event->web_audio_player_handle() == m_webAudioPlayerHandle) - { - firebolt::rialto::WebAudioPlayerState playerState = firebolt::rialto::WebAudioPlayerState::UNKNOWN; - switch (event->state()) - { - case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_UNKNOWN: - playerState = firebolt::rialto::WebAudioPlayerState::UNKNOWN; - break; - case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_IDLE: - playerState = firebolt::rialto::WebAudioPlayerState::IDLE; - break; - case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_PLAYING: - playerState = firebolt::rialto::WebAudioPlayerState::PLAYING; - break; - case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_PAUSED: - playerState = firebolt::rialto::WebAudioPlayerState::PAUSED; - break; - case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_END_OF_STREAM: - playerState = firebolt::rialto::WebAudioPlayerState::END_OF_STREAM; - break; - case firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_FAILURE: - playerState = firebolt::rialto::WebAudioPlayerState::FAILURE; - break; - default: - RIALTO_CLIENT_LOG_WARN("Recieved unknown web audio player state"); - break; - } - - m_webAudioPlayerIpcClient->notifyState(playerState); - } -} - -bool WebAudioPlayerIpc::play() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioPlayRequest request; - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioPlayResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->play(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to play due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool WebAudioPlayerIpc::pause() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioPauseRequest request; - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioPauseResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->pause(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to pause due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool WebAudioPlayerIpc::setEos() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioSetEosRequest request; - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioSetEosResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->setEos(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to set eos due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool WebAudioPlayerIpc::getBufferAvailable(uint32_t &availableFrames, - const std::shared_ptr &webAudioShmInfo) -{ - if (!webAudioShmInfo) - { - RIALTO_CLIENT_LOG_ERROR("webAudioShmInfo parameter can't be null!"); - return false; - } - - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioGetBufferAvailableRequest request; - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioGetBufferAvailableResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->getBufferAvailable(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get buffer available due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - availableFrames = response.available_frames(); - webAudioShmInfo->offsetMain = response.shm_info().offset_main(); - webAudioShmInfo->lengthMain = response.shm_info().length_main(); - webAudioShmInfo->offsetWrap = response.shm_info().offset_wrap(); - webAudioShmInfo->lengthWrap = response.shm_info().length_wrap(); - - return true; -} - -bool WebAudioPlayerIpc::getBufferDelay(uint32_t &delayFrames) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioGetBufferDelayRequest request; - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioGetBufferDelayResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->getBufferDelay(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get buffer delay source due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - delayFrames = response.delay_frames(); - - return true; -} - -bool WebAudioPlayerIpc::writeBuffer(const uint32_t numberOfFrames) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioWriteBufferRequest request; - - request.set_number_of_frames(numberOfFrames); - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioWriteBufferResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->writeBuffer(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to write to the buffer due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool WebAudioPlayerIpc::getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioGetDeviceInfoRequest request; - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioGetDeviceInfoResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->getDeviceInfo(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get device info source due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - preferredFrames = response.preferred_frames(); - maximumFrames = response.maximum_frames(); - supportDeferredPlay = response.support_deferred_play(); - - return true; -} - -bool WebAudioPlayerIpc::setVolume(double volume) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioSetVolumeRequest request; - request.set_volume(volume); - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioSetVolumeResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->setVolume(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to set volume due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - return true; -} - -bool WebAudioPlayerIpc::getVolume(double &volume) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::WebAudioGetVolumeRequest request; - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::WebAudioGetVolumeResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->getVolume(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get volume due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - volume = response.volume(); - return true; -} - -bool WebAudioPlayerIpc::createWebAudioPlayer(const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr webAudioConfig) -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return false; - } - - firebolt::rialto::CreateWebAudioPlayerRequest request; - request.set_audio_mime_type(audioMimeType); - request.set_priority(priority); - std::shared_ptr kConfig = webAudioConfig.lock(); - if (kConfig) - { - ::firebolt::rialto::CreateWebAudioPlayerRequest_WebAudioPcmConfig pcm_config; - pcm_config.set_rate(kConfig->pcm.rate); - pcm_config.set_channels(kConfig->pcm.channels); - pcm_config.set_sample_size(kConfig->pcm.sampleSize); - pcm_config.set_is_big_endian(kConfig->pcm.isBigEndian); - pcm_config.set_is_signed(kConfig->pcm.isSigned); - pcm_config.set_is_float(kConfig->pcm.isFloat); - request.mutable_config()->mutable_pcm()->CopyFrom(pcm_config); - } - - firebolt::rialto::CreateWebAudioPlayerResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->createWebAudioPlayer(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create web audio player due to '%s'", ipcController->ErrorText().c_str()); - return false; - } - - m_webAudioPlayerHandle = response.web_audio_player_handle(); - - return true; -} - -void WebAudioPlayerIpc::destroyWebAudioPlayer() -{ - if (!reattachChannelIfRequired()) - { - RIALTO_CLIENT_LOG_ERROR("Reattachment of the ipc channel failed, ipc disconnected"); - return; - } - - firebolt::rialto::DestroyWebAudioPlayerRequest request; - request.set_web_audio_player_handle(m_webAudioPlayerHandle); - - firebolt::rialto::DestroyWebAudioPlayerResponse response; - auto ipcController = m_ipc.createRpcController(); - auto blockingClosure = m_ipc.createBlockingClosure(); - m_webAudioPlayerStub->destroyWebAudioPlayer(ipcController.get(), &request, &response, blockingClosure.get()); - - // wait for the call to complete - blockingClosure->wait(); - - // check the result - if (ipcController->Failed()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to destroy web audio player due to '%s'", ipcController->ErrorText().c_str()); - } -} - -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/CMakeLists.txt b/middleware/rialto-client/media/client/main/CMakeLists.txt deleted file mode 100644 index c0da47d75..000000000 --- a/middleware/rialto-client/media/client/main/CMakeLists.txt +++ /dev/null @@ -1,95 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set(CMAKE_C_STANDARD 99) -set(CMAKE_CXX_STANDARD 17) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCCompilerFlag ) -include( CheckCXXCompilerFlag ) - -set(LIB_RIALTO_CLIENT_SOURCES - source/AttachedSources.cpp - source/ClientController.cpp - source/ClientLogControl.cpp - source/Control.cpp - source/KeyIdMap.cpp - source/MediaKeys.cpp - source/MediaKeysCapabilities.cpp - source/MediaPipeline.cpp - source/MediaPipelineCapabilities.cpp - source/SharedMemoryHandle.cpp - source/WebAudioPlayer.cpp - ) - -add_library( RialtoClient - SHARED - ${LIB_RIALTO_CLIENT_SOURCES} - - ) - -target_compile_options( - RialtoClient - - PUBLIC - -DRIALTO_SERVER_SUPPORTS_DECRYPTION=1 - ) - -target_include_directories( - RialtoClient - - PUBLIC - ${PROJECT_SOURCE_DIR}/include - $ - $ - - PRIVATE - $ - $ - $ - $ - $ - - ) - -set_target_properties( - RialtoClient - PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" - SOVERSION ${PROJECT_VERSION_MAJOR} - VERSION ${CMAKE_PROJECT_VERSION} - ) - -target_link_libraries( - RialtoClient - - PRIVATE - RialtoPlayerCommon - RialtoClientIpcImpl - RialtoCommon - RialtoEthanLog - - Threads::Threads - - ) - -include( GNUInstallDirs ) - -install( TARGETS RialtoClient LIBRARY - DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) diff --git a/middleware/rialto-client/media/client/main/include/AttachedSources.h b/middleware/rialto-client/media/client/main/include/AttachedSources.h deleted file mode 100644 index 43c0f7fc1..000000000 --- a/middleware/rialto-client/media/client/main/include/AttachedSources.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_ATTACHED_SOURCES_H_ -#define FIREBOLT_RIALTO_CLIENT_ATTACHED_SOURCES_H_ - -#include "MediaCommon.h" -#include -#include -#include - -namespace firebolt::rialto::client -{ -class AttachedSources -{ - struct Source - { - MediaSourceType type{MediaSourceType::UNKNOWN}; - bool isFlushing{false}; - }; - -public: - AttachedSources() = default; - ~AttachedSources() = default; - AttachedSources(const AttachedSources &) = delete; - AttachedSources(AttachedSources &&) = delete; - AttachedSources &operator=(const AttachedSources &) = delete; - AttachedSources &operator=(AttachedSources &&) = delete; - - void add(std::uint32_t id, const MediaSourceType &mediaSourceType); - void remove(std::uint32_t id); - MediaSourceType getType(std::uint32_t id) const; - bool isFlushing(std::uint32_t id) const; - void setFlushing(std::uint32_t id, bool flushing); - -private: - mutable std::mutex m_mutex; - std::map m_attachedSources; -}; -} // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_ATTACHED_SOURCES_H_ diff --git a/middleware/rialto-client/media/client/main/include/ClientController.h b/middleware/rialto-client/media/client/main/include/ClientController.h deleted file mode 100644 index 92f495c2b..000000000 --- a/middleware/rialto-client/media/client/main/include/ClientController.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_CLIENT_CONTROLLER_H_ -#define FIREBOLT_RIALTO_CLIENT_CLIENT_CONTROLLER_H_ - -#include -#include -#include -#include - -#include "IClientController.h" -#include "IControlClient.h" -#include "IControlIpc.h" - -namespace firebolt::rialto::client -{ -class ClientControllerAccessor : public IClientControllerAccessor -{ -public: - ~ClientControllerAccessor() override = default; - IClientController &getClientController() const override; -}; - -class ClientController : public IClientController, public IControlClient -{ -public: - explicit ClientController(const std::shared_ptr &ControlIpcFactory); - ~ClientController() override; - - std::shared_ptr getSharedMemoryHandle() override; - bool registerClient(std::weak_ptr client, ApplicationState &appState) override; - bool unregisterClient(std::weak_ptr client) override; - -private: - void notifyApplicationState(ApplicationState state) override; - - /** - * @brief Initalised the shared memory for media playback. - * - * @retval true on success, false otherwise. - */ - bool initSharedMemory(); - - /** - * @brief Terminates the shared memory. - */ - void termSharedMemory(); - - /** - * @brief Coverts a ApplicationState to string. - * - * @param[in] state : The application state. - * - * @retval the application state string, or "" on error. - */ - std::string stateToString(ApplicationState state); - - /** - * @brief Forwards new ApplicationState to subscribed clients - * - * @param[in] state : The new application state. - * - */ - void changeStateAndNotifyClients(ApplicationState state); - -private: - /** - * @brief Mutex protection for class attributes. - */ - std::mutex m_mutex; - - /** - * @brief The current application state - */ - ApplicationState m_currentState; - - /** - * @brief Flag indicating if registerRequest has to be sent to Rialto Server - */ - bool m_registrationRequired; - - /** - * @brief The shared memory buffer handle. - */ - std::shared_ptr m_shmHandle; - - /** - * @brief The rialto control ipc factory. - */ - std::shared_ptr m_controlIpc; - - /** - * @brief List of clients to notify. - */ - std::list> m_clients; -}; -} // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_CLIENT_CONTROLLER_H_ diff --git a/middleware/rialto-client/media/client/main/include/ClientLogControl.h b/middleware/rialto-client/media/client/main/include/ClientLogControl.h deleted file mode 100644 index 7549aac3b..000000000 --- a/middleware/rialto-client/media/client/main/include/ClientLogControl.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_CLIENT_LOG_CONTROL_H_ -#define FIREBOLT_RIALTO_CLIENT_CLIENT_LOG_CONTROL_H_ - -#include -#include -#include -#include - -#include "IClientLogControl.h" -#include "RialtoLogging.h" - -namespace firebolt::rialto::client -{ -/** - * @brief IClientLogControl factory class definition. - */ -class ClientLogControlFactory : public IClientLogControlFactory -{ -public: - ClientLogControlFactory() = default; - ~ClientLogControlFactory() override = default; - - IClientLogControl &createClientLogControl() override; - - /** - * @brief Create the (singleton) object. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); -}; - -/** - * @brief The definition of the Control. - */ -class ClientLogControl : public IClientLogControl -{ -public: - /** - * @brief The constructor. - */ - ClientLogControl(); - - ClientLogControl(const ClientLogControl &) = delete; - ClientLogControl &operator=(const ClientLogControl &) = delete; - - /** - * @brief Virtual destructor. - */ - ~ClientLogControl() override; - - bool registerLogHandler(const std::shared_ptr &handler, bool ignoreLogLevels) override; - -private: - void forwardLog(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, - const char *function, const char *message, std::size_t messageLen); - void cancelLogHandler(); - - /** - * @brief The registered log handler - */ - std::shared_ptr m_logHandler; - std::mutex m_logHandlerMutex; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_CLIENT_LOG_CONTROL_H_ diff --git a/middleware/rialto-client/media/client/main/include/Control.h b/middleware/rialto-client/media/client/main/include/Control.h deleted file mode 100644 index 8ad5e6329..000000000 --- a/middleware/rialto-client/media/client/main/include/Control.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_CONTROL_H_ -#define FIREBOLT_RIALTO_CLIENT_CONTROL_H_ - -#include -#include -#include - -#include "IClientController.h" -#include "IControl.h" -#include "IControlClient.h" -#include "RialtoLogging.h" - -namespace firebolt::rialto::client -{ -/** - * @brief IControl factory class definition. - */ -class ControlFactory : public IControlFactory -{ -public: - ControlFactory() = default; - ~ControlFactory() override = default; - - std::shared_ptr createControl() const override; - /** - * @brief Create the control factory object. - * - * @retval the control factory instance or null on error. - */ - static std::shared_ptr createFactory(); -}; - -/** - * @brief The definition of the Control. - */ -class Control : public IControl -{ -public: - /** - * @brief The constructor. - */ - explicit Control(IClientController &clientController); - - /** - * @brief Virtual destructor. - */ - ~Control() override; - - bool registerClient(std::weak_ptr client, ApplicationState &appState) override; - -private: - /** - * @brief The control clients which have been registered with m_clientController - * and are kept so that they can be unregistered upon destruction of this - * object - */ - std::vector> m_clientsToUnregister; - - /** - * @brief The rialto client controller object. - */ - IClientController &m_clientController; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_CONTROL_H_ diff --git a/middleware/rialto-client/media/client/main/include/IClientController.h b/middleware/rialto-client/media/client/main/include/IClientController.h deleted file mode 100644 index b6402c25e..000000000 --- a/middleware/rialto-client/media/client/main/include/IClientController.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_CLIENT_CONTROLLER_H_ -#define FIREBOLT_RIALTO_CLIENT_I_CLIENT_CONTROLLER_H_ - -#include -#include -#include - -#include "IClientLogHandler.h" -#include "IControlClient.h" -#include "ISharedMemoryHandle.h" - -namespace firebolt::rialto::client -{ -class IClientController; - -/** - * @brief IClientController accessor class definition. - */ -class IClientControllerAccessor -{ -public: - virtual ~IClientControllerAccessor() = default; - IClientControllerAccessor(const IClientControllerAccessor &) = delete; - IClientControllerAccessor &operator=(const IClientControllerAccessor &) = delete; - IClientControllerAccessor(IClientControllerAccessor &&) = delete; - IClientControllerAccessor &operator=(IClientControllerAccessor &&) = delete; - - /** - * @brief Get a IClientControllerAccessor instance. - * - * @retval the accessor instance - */ - static IClientControllerAccessor &instance(); - - /** - * @brief Get ClientController object. - * - * @retval the reference to ClientController singleton object - */ - virtual IClientController &getClientController() const = 0; - -protected: - IClientControllerAccessor() = default; -}; - -/** - * @brief The definition of the IClientController interface. - * - * This interface defines the internal API querying shared memory. - */ -class IClientController -{ -public: - IClientController() = default; - virtual ~IClientController() = default; - - IClientController(const IClientController &) = delete; - IClientController &operator=(const IClientController &) = delete; - IClientController(IClientController &&) = delete; - IClientController &operator=(IClientController &&) = delete; - - /** - * @brief Gets the handle to the mapped shared memory. - * - * @retval shared pointer to shm handle. - */ - virtual std::shared_ptr getSharedMemoryHandle() = 0; - - /** - * @brief Register a client notify when the shared buffer changes. - * - * @param[in] client : Client to register. - * @param[out] appState : Current application state - * - * @retval true on success, false otherwise. - */ - virtual bool registerClient(std::weak_ptr client, ApplicationState &appState) = 0; - - /** - * @brief Unregister a client. - * - * @param[in] client : Client to unregister. - * - * @retval true on success, false otherwise. - */ - virtual bool unregisterClient(std::weak_ptr client) = 0; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_CLIENT_CONTROLLER_H_ diff --git a/middleware/rialto-client/media/client/main/include/ISharedMemoryHandle.h b/middleware/rialto-client/media/client/main/include/ISharedMemoryHandle.h deleted file mode 100644 index 6ff1128df..000000000 --- a/middleware/rialto-client/media/client/main/include/ISharedMemoryHandle.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_I_SHARED_MEMORY_HANDLE_H_ -#define FIREBOLT_RIALTO_CLIENT_I_SHARED_MEMORY_HANDLE_H_ - -#include - -namespace firebolt::rialto::client -{ -class ISharedMemoryHandle -{ -public: - ISharedMemoryHandle() = default; - ISharedMemoryHandle(const ISharedMemoryHandle &) = delete; - ISharedMemoryHandle(ISharedMemoryHandle &&) = delete; - ISharedMemoryHandle &operator=(const ISharedMemoryHandle &) = delete; - ISharedMemoryHandle &operator=(ISharedMemoryHandle &&) = delete; - virtual ~ISharedMemoryHandle() = default; - - virtual std::uint8_t *getShm() const = 0; -}; -} // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_I_SHARED_MEMORY_HANDLE_H_ diff --git a/middleware/rialto-client/media/client/main/include/KeyIdMap.h b/middleware/rialto-client/media/client/main/include/KeyIdMap.h deleted file mode 100644 index 978f7d6ab..000000000 --- a/middleware/rialto-client/media/client/main/include/KeyIdMap.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_KEY_IDMAP_H_ -#define FIREBOLT_RIALTO_CLIENT_KEY_IDMAP_H_ - -#include -#include -#include -#include - -namespace firebolt::rialto::client -{ -class KeyIdMap -{ -public: - static KeyIdMap &instance(); - void addSession(std::int32_t keySessionId); - bool updateKey(std::int32_t keySessionId, const std::vector &keyId); - std::vector get(std::int32_t keySessionId) const; - void erase(std::int32_t keySessionId); - -private: - KeyIdMap() = default; - ~KeyIdMap() = default; - KeyIdMap(const KeyIdMap &) = delete; - KeyIdMap(KeyIdMap &&) = delete; - KeyIdMap &operator=(const KeyIdMap &) = delete; - KeyIdMap &operator=(KeyIdMap &&) = delete; - -private: - mutable std::mutex m_mutex; - std::map> m_keyIdMap; -}; -} // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_KEY_IDMAP_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaKeys.h b/middleware/rialto-client/media/client/main/include/MediaKeys.h deleted file mode 100644 index f5e6bb485..000000000 --- a/middleware/rialto-client/media/client/main/include/MediaKeys.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_H_ -#define FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_H_ - -#include "IMediaKeys.h" -#include "IMediaKeysIpcFactory.h" -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief IMediaKeys factory class definition. - */ -class MediaKeysFactory : public IMediaKeysFactory -{ -public: - MediaKeysFactory() = default; - ~MediaKeysFactory() override = default; - - std::unique_ptr createMediaKeys(const std::string &keySystem) const override; - - /** - * @brief IMediaKeys factory method with factory parameters for mock injection. - * - * @param[in] keySystem : The key system for which to create a Media Keys instance - * @param[in] mediaKeysIpcFactory : This was added for the test environment where a mock object needs to be passed in. - * - * @retval the new media keys instance or null on error. - */ - std::unique_ptr - createMediaKeys(const std::string &keySystem, - std::weak_ptr mediaKeysIpcFactory) const; -}; - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -/** - * @brief The definition of the MediaKeys. - */ -class MediaKeys : public IMediaKeys -{ -public: - /** - * @brief The constructor. - * - * @param[in] keySystem : The key system for which to create a Media Keys instance. - * @param[in] mediaKeysIpcFactory : The media keys ipc factory. - */ - explicit MediaKeys(const std::string &keySystem, const std::shared_ptr &mediaKeysIpcFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaKeys(); - - MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) override; - - bool containsKey(int32_t keySessionId, const std::vector &keyId) override; - - MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, bool isLDL, - int32_t &keySessionId) override; - - MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) override; - - MediaKeyErrorStatus loadSession(int32_t keySessionId) override; - - MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) override; - - MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) override; - - MediaKeyErrorStatus closeKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus removeKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus deleteDrmStore() override; - - MediaKeyErrorStatus deleteKeyStore() override; - - MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) override; - - MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) override; - - MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) override; - - MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) override; - - MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) override; - - MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) override; - - MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) override; - -private: - /** - * @brief The media keys ipc object. - */ - std::unique_ptr m_mediaKeysIpc; - - /** - * @brief The key system. - */ - std::string m_keySystem; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaKeysCapabilities.h b/middleware/rialto-client/media/client/main/include/MediaKeysCapabilities.h deleted file mode 100644 index c1974f606..000000000 --- a/middleware/rialto-client/media/client/main/include/MediaKeysCapabilities.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_H_ - -#include "IMediaKeysCapabilities.h" -#include "IMediaKeysCapabilitiesIpcFactory.h" -#include -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief IMediaKeysCapabilities factory class definition. - */ -class MediaKeysCapabilitiesFactory : public IMediaKeysCapabilitiesFactory -{ -public: - MediaKeysCapabilitiesFactory() = default; - ~MediaKeysCapabilitiesFactory() override = default; - - /** - * @brief Weak pointer to the singleton object. - */ - static std::weak_ptr m_mediaKeysCapabilities; - - /** - * @brief Mutex protection for creation of the MediaKeysCapabilities object. - */ - static std::mutex m_creationMutex; - - std::shared_ptr getMediaKeysCapabilities() const override; -}; - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -/** - * @brief The definition of the MediaKeysCapabilities. - */ -class MediaKeysCapabilities : public IMediaKeysCapabilities -{ -public: - /** - * @brief The constructor. - * - * @param[in] mediaKeysCapabilitiesIpcFactory : The media keys capabilities ipc factory. - */ - explicit MediaKeysCapabilities(const std::shared_ptr &MediaKeysCapabilitiesIpcFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaKeysCapabilities(); - - std::vector getSupportedKeySystems() override; - - bool supportsKeySystem(const std::string &keySystem) override; - - bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) override; - - bool isServerCertificateSupported(const std::string &keySystem) override; - -private: - /** - * @brief The media keys capabilities ipc object. - */ - std::shared_ptr m_mediaKeysCapabilitiesIpc; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_KEYS_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaPipeline.h b/middleware/rialto-client/media/client/main/include/MediaPipeline.h deleted file mode 100644 index b9e97a430..000000000 --- a/middleware/rialto-client/media/client/main/include/MediaPipeline.h +++ /dev/null @@ -1,336 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_MEDIA_PIPELINE_H_ -#define FIREBOLT_RIALTO_MEDIA_PIPELINE_H_ - -#include "AttachedSources.h" -#include "IClientController.h" -#include "IControlClient.h" -#include "IMediaFrameWriter.h" -#include "IMediaPipeline.h" -#include "IMediaPipelineIpc.h" -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief IMediaPipeline factory class definition. - */ -class MediaPipelineFactory : public IMediaPipelineFactory -{ -public: - MediaPipelineFactory() = default; - ~MediaPipelineFactory() override = default; - - std::unique_ptr createMediaPipeline(std::weak_ptr client, - const VideoRequirements &videoRequirements) const override; - - /** - * @brief IMediaPipeline factory method with factory parameters for mock injection. - * - * @param[in] client : The Rialto media player client. - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. - * @param[in] mediaPipelineIpcFactory : This was added for the test environment where a mock object needs to be passed in. - * @param[in] clientController : This was added for the test environment where a mock object needs to be passed in. - * - * @retval the new backend instance or null on error. - */ - std::unique_ptr - createMediaPipeline(std::weak_ptr client, const VideoRequirements &videoRequirements, - std::weak_ptr mediaPipelineIpcFactory, - std::weak_ptr clientController) const; -}; - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -class IMediaPipelineAndIControlClient : public IMediaPipeline, public IControlClient -{ -}; - -/** - * @brief The definition of the MediaPipeline. - */ -class MediaPipeline : public IMediaPipelineAndIControlClient, public IMediaPipelineIpcClient -{ -public: - /** - * @brief The possible states of the MediaPipeline. - */ - enum class State - { - IDLE, /**< The MediaPipeline is idle. */ - BUFFERING, /**< The MediaPipeline is buffering data. */ - PLAYING, /**< The MediaPipeline is playing. */ - SEEKING, /**< The MediaPipeline is seeking position. */ - FAILURE, /**< The MediaPipeline is failed. */ - END_OF_STREAM /**< The MediaPipeline is at the end of stream. */ - }; - - /** - * @brief The constructor. - * - * @param[in] client : The Rialto media player client. - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. - * @param[in] mediaPipelineIpcFactory : The media player ipc factory. - * @param[in] mediaFrameWriterFactory : The media frame writer factory. - * @param[in] clientController : The shared memory manager. - */ - MediaPipeline(std::weak_ptr client, const VideoRequirements &videoRequirements, - const std::shared_ptr &mediaPipelineIpcFactory, - const std::shared_ptr &mediaFrameWriterFactory, - IClientController &clientController); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaPipeline(); - - bool load(MediaType type, const std::string &mimeType, const std::string &url) override; - - bool attachSource(const std::unique_ptr &source) override; - - bool removeSource(int32_t id) override; - - bool allSourcesAttached() override; - - bool play() override; - - bool pause() override; - - bool stop() override; - - bool setPlaybackRate(double rate) override; - - bool setPosition(int64_t position) override; - - bool getPosition(int64_t &position) override; - - bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override; - - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override; - - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; - bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; - - bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override; - - AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; - - std::weak_ptr getClient() override; - - void notifyPlaybackState(PlaybackState state) override; - - void notifyPosition(int64_t position) override; - - void notifyNetworkState(NetworkState state) override; - - void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId, - const std::shared_ptr &shmInfo) override; - - void notifyQos(int32_t sourceId, const QosInfo &qosInfo) override; - - void notifyBufferUnderflow(int32_t sourceId) override; - - void notifyPlaybackError(int32_t sourceId, PlaybackError error) override; - - void notifySourceFlushed(int32_t sourceId) override; - - bool renderFrame() override; - - bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override; - - bool getVolume(double ¤tVolume) override; - - bool setMute(int32_t sourceId, bool mute) override; - - bool getMute(int32_t sourceId, bool &mute) override; - - bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; - - bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; - - bool setLowLatency(bool lowLatency) override; - - bool setSync(bool sync) override; - - bool getSync(bool &sync) override; - - bool setSyncOff(bool syncOff) override; - - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; - - bool getStreamSyncMode(int32_t &streamSyncMode) override; - - bool flush(int32_t sourceId, bool resetTime, bool &async) override; - - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) override; - - bool setSubtitleOffset(int32_t sourceId, int64_t position) override; - - bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; - - bool setBufferingLimit(uint32_t limitBufferingMs) override; - - bool getBufferingLimit(uint32_t &limitBufferingMs) override; - - bool setUseBuffering(bool useBuffering) override; - - bool getUseBuffering(bool &useBuffering) override; - - bool switchSource(const std::unique_ptr &source) override; - - void notifyApplicationState(ApplicationState state) override; - -protected: - /** - * @brief The need data request data. - */ - struct NeedDataRequest - { - int32_t sourceId; /**< The source id. */ - std::shared_ptr shmInfo; /**< The shared memory information. */ - std::unique_ptr frameWriter; /**< The frame writer used to add segments. */ - }; - - /** - * @brief The media player client. - */ - std::weak_ptr m_mediaPipelineClient; - - /** - * @brief The media player ipc object. - */ - std::unique_ptr m_mediaPipelineIpc; - - /** - * @brief The rialto shared memory manager object. - */ - IClientController &m_clientController; - - /** - * @brief The Need data request map. - * Key: requestId - * Value: NeedDataRequest - */ - std::map> m_needDataRequestMap; - - /** - * @brief The current application state. Protected by m_needDataRequestMapMutex - */ - ApplicationState m_currentAppState; - - /** - * @brief The need data request map mutex. - */ - std::mutex m_needDataRequestMapMutex; - - /** - * @brief The media frame writer factory. - */ - std::shared_ptr m_mediaFrameWriterFactory; - - /** - * @brief The shared memory mutex. - */ - std::mutex m_shmMutex; - - /** - * @brief The current state of the MediaPipeline. - */ - std::atomic m_currentState; - - /** - * @brief The flush request mutex. - */ - std::mutex m_flushMutex; - - /** - * @brief The attach source mutex. - */ - std::mutex m_attachSourceMutex; - - /** - * @brief The attach source condition variable. - */ - std::condition_variable m_attachSourceCond; - - /** - * @brief Whether attachSource is currently in progress. - */ - bool m_attachingSource; - - /** - * @brief The container with attached source id <-> MediaSourceType mapping - */ - AttachedSources m_attachedSources; - - /** - * @brief Sets the new internal MediaPipeline state based on the NetworkState. - * - * @param[in] state : The new NeworkState. - */ - void updateState(NetworkState state); - - /** - * @brief Sets the new internal MediaPipeline state based on the PlaybackState. - * - * @param[in] state : The new PlaybackState. - */ - void updateState(PlaybackState state); - - /** - * @brief Handles a have data request. - * - * @param[in] status : The status - * @param[in] needDataRequestId : Need data request id - * - * @retval true on success. - */ - bool handleHaveData(MediaSourceStatus status, uint32_t needDataRequestId); - - /** - * @brief Handles a set position request. - * - * @param[in] position : The playback position in nanoseconds. - * - * @retval true on success. - */ - bool handleSetPosition(int64_t position); - - /** - * @brief Discards the need data request with id. - * - * @param[in] needDataRequestId : Need data request id - */ - void discardNeedDataRequest(uint32_t needDataRequestId); -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_MEDIA_PIPELINE_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaPipelineCapabilities.h b/middleware/rialto-client/media/client/main/include/MediaPipelineCapabilities.h deleted file mode 100644 index 591cab712..000000000 --- a/middleware/rialto-client/media/client/main/include/MediaPipelineCapabilities.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_H_ - -#include "IMediaPipelineCapabilities.h" -#include "IMediaPipelineCapabilitiesIpcFactory.h" -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief IMediaPipelineCapabilitiesFactory factory class definition. - */ -class MediaPipelineCapabilitiesFactory : public IMediaPipelineCapabilitiesFactory -{ -public: - MediaPipelineCapabilitiesFactory() = default; - ~MediaPipelineCapabilitiesFactory() override = default; - - std::unique_ptr createMediaPipelineCapabilities() const override; -}; - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -/** - * @brief The definition of the MediaPipelineCapabilities. - */ -class MediaPipelineCapabilities : public IMediaPipelineCapabilities -{ -public: - /** - * @brief The constructor. - * - * @param[in] mediaPipelineCapabilitiesIpcFactory : The media pipeline capabilities ipc factory. - */ - explicit MediaPipelineCapabilities( - const std::shared_ptr &MediaPipelineCapabilitiesIpcFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaPipelineCapabilities(); - - /** - * @brief Returns the MSE mime types supported by Rialto for \a sourceType - * - * @param[in] sourceType : source type - * - * @retval The supported mime types. - */ - std::vector getSupportedMimeTypes(MediaSourceType sourceType) override; - - /** - * @brief Indicates if the specified mime type is supported. - * - * This method should be called to ensure that the specified mime - * type is supported by Rialto. - * - * @param[in] mimeType : The mime type to check. - * - * @retval true if supported. - */ - bool isMimeTypeSupported(const std::string &mimeTypee) override; - - /** - * @brief Check sinks and decoders for supported properties - * - * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched - * @param[in] propertyNames : A vector of property names to look for - * - * @retval Returns the subset of propertyNames that are supported by the mediaType - */ - std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) override; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - bool isVideoMaster(bool &isVideoMaster) override; - -private: - /** - * @brief The media pipeline capabilities ipc object. - */ - std::unique_ptr m_mediaPipelineCapabilitiesIpc; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/client/main/include/MediaPipelineProxy.h b/middleware/rialto-client/media/client/main/include/MediaPipelineProxy.h deleted file mode 100644 index 3747f5535..000000000 --- a/middleware/rialto-client/media/client/main/include/MediaPipelineProxy.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_PROXY_H_ -#define FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_PROXY_H_ - -#include - -#include -#include - -#include "MediaPipeline.h" - -namespace firebolt::rialto::client -{ -class MediaPipelineProxy : public IMediaPipelineAndIControlClient -{ -public: - MediaPipelineProxy(const std::shared_ptr &mediaPipeline, - client::IClientController &clientController); - virtual ~MediaPipelineProxy(); - - std::weak_ptr getClient() override { return m_mediaPipeline->getClient(); } - - bool load(MediaType type, const std::string &mimeType, const std::string &url) override - { - return m_mediaPipeline->load(type, mimeType, url); - } - - bool attachSource(const std::unique_ptr &source) override - { - return m_mediaPipeline->attachSource(source); - } - - bool removeSource(int32_t id) override { return m_mediaPipeline->removeSource(id); } - - bool allSourcesAttached() override { return m_mediaPipeline->allSourcesAttached(); } - - bool play() override { return m_mediaPipeline->play(); } - - bool pause() override { return m_mediaPipeline->pause(); } - - bool stop() override { return m_mediaPipeline->stop(); } - - bool setPlaybackRate(double rate) override { return m_mediaPipeline->setPlaybackRate(rate); } - - bool setPosition(int64_t position) override { return m_mediaPipeline->setPosition(position); } - - bool getPosition(int64_t &position) override { return m_mediaPipeline->getPosition(position); } - - bool setImmediateOutput(int32_t sourceId, bool immediateOutput) - { - return m_mediaPipeline->setImmediateOutput(sourceId, immediateOutput); - } - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) - { - return m_mediaPipeline->getImmediateOutput(sourceId, immediateOutput); - } - - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) - { - return m_mediaPipeline->getStats(sourceId, renderedFrames, droppedFrames); - } - - bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override - { - return m_mediaPipeline->setVideoWindow(x, y, width, height); - } - - bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override - { - return m_mediaPipeline->haveData(status, needDataRequestId); - } - - AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override - { - return m_mediaPipeline->addSegment(needDataRequestId, mediaSegment); - } - - bool renderFrame() override { return m_mediaPipeline->renderFrame(); } - - bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override - { - return m_mediaPipeline->setVolume(targetVolume, volumeDuration, easeType); - } - - bool getVolume(double ¤tVolume) override { return m_mediaPipeline->getVolume(currentVolume); } - - bool setMute(int32_t sourceId, bool mute) override { return m_mediaPipeline->setMute(sourceId, mute); } - - bool getMute(int32_t sourceId, bool &mute) override { return m_mediaPipeline->getMute(sourceId, mute); } - - bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override - { - return m_mediaPipeline->setTextTrackIdentifier(textTrackIdentifier); - } - - bool getTextTrackIdentifier(std::string &textTrackIdentifier) override - { - return m_mediaPipeline->getTextTrackIdentifier(textTrackIdentifier); - } - - bool setLowLatency(bool lowLatency) override { return m_mediaPipeline->setLowLatency(lowLatency); } - - bool setSync(bool sync) override { return m_mediaPipeline->setSync(sync); } - - bool getSync(bool &sync) override { return m_mediaPipeline->getSync(sync); } - - bool setSyncOff(bool syncOff) override { return m_mediaPipeline->setSyncOff(syncOff); } - - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override - { - return m_mediaPipeline->setStreamSyncMode(sourceId, streamSyncMode); - } - - bool getStreamSyncMode(int32_t &streamSyncMode) override - { - return m_mediaPipeline->getStreamSyncMode(streamSyncMode); - } - - bool flush(int32_t sourceId, bool resetTime, bool &async) override - { - return m_mediaPipeline->flush(sourceId, resetTime, async); - } - - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) override - { - return m_mediaPipeline->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition); - } - - bool setSubtitleOffset(int32_t sourceId, int64_t position) override - { - return m_mediaPipeline->setSubtitleOffset(sourceId, position); - } - - bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override - { - return m_mediaPipeline->processAudioGap(position, duration, discontinuityGap, audioAac); - } - - bool setBufferingLimit(uint32_t limitBufferingMs) override - { - return m_mediaPipeline->setBufferingLimit(limitBufferingMs); - } - - bool getBufferingLimit(uint32_t &limitBufferingMs) override - { - return m_mediaPipeline->getBufferingLimit(limitBufferingMs); - } - - bool setUseBuffering(bool useBuffering) override { return m_mediaPipeline->setUseBuffering(useBuffering); } - - bool getUseBuffering(bool &useBuffering) override { return m_mediaPipeline->getUseBuffering(useBuffering); } - - bool switchSource(const std::unique_ptr &source) override - { - return m_mediaPipeline->switchSource(source); - } - - void notifyApplicationState(ApplicationState state) override { m_mediaPipeline->notifyApplicationState(state); } - -private: - std::shared_ptr m_mediaPipeline; - client::IClientController &m_clientController; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_MEDIA_PIPELINE_PROXY_H_ diff --git a/middleware/rialto-client/media/client/main/include/SharedMemoryHandle.h b/middleware/rialto-client/media/client/main/include/SharedMemoryHandle.h deleted file mode 100644 index 7c0ae2f3b..000000000 --- a/middleware/rialto-client/media/client/main/include/SharedMemoryHandle.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_SHARED_MEMORY_HANDLE_H_ -#define FIREBOLT_RIALTO_CLIENT_SHARED_MEMORY_HANDLE_H_ - -#include "ISharedMemoryHandle.h" - -namespace firebolt::rialto::client -{ -class SharedMemoryHandle : public ISharedMemoryHandle -{ -public: - SharedMemoryHandle(std::int32_t shmFd, std::uint32_t shmBufferLen); - ~SharedMemoryHandle() override; - - std::uint8_t *getShm() const override; - -private: - /** - * @brief The shared memory file descriptor. - */ - std::int32_t m_shmFd; - - /** - * @brief The shared memory buffer length. - */ - std::uint32_t m_shmBufferLen; - - /** - * @brief The shared memory buffer pointer. - */ - std::uint8_t *m_shmBuffer; -}; -} // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_SHARED_MEMORY_HANDLE_H_ diff --git a/middleware/rialto-client/media/client/main/include/WebAudioPlayer.h b/middleware/rialto-client/media/client/main/include/WebAudioPlayer.h deleted file mode 100644 index 2c5b11f9a..000000000 --- a/middleware/rialto-client/media/client/main/include/WebAudioPlayer.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_H_ -#define FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_H_ - -#include "IClientController.h" -#include "IControlClient.h" -#include "IWebAudioPlayer.h" -#include "IWebAudioPlayerIpc.h" -#include "IWebAudioPlayerIpcClient.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief IWebAudioPlayer factory class definition. - */ -class WebAudioPlayerFactory : public IWebAudioPlayerFactory -{ -public: - WebAudioPlayerFactory() = default; - ~WebAudioPlayerFactory() override = default; - - std::unique_ptr createWebAudioPlayer(std::weak_ptr client, - const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config) const override; - - /** - * @brief IWebAudioPlayer factory method with factory parameters for mock injection. - * - * @param[in] client : The Web Audio Player client. - * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM). - * @param[in] priority : Priority value for this pipeline. - * @param[in] config : Additional type dependent configuration data or nullptr. - * @param[in] webAudioPlayerIpcFactory : This was added for the test environment where a mock object needs to be - * passed in. - * @param[in] clientController : This was added for the test environment where a mock object needs to be - * passed in. - * - * @retval the new Web Audio Player instance or null on error. - */ - virtual std::unique_ptr - createWebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config, - std::weak_ptr webAudioPlayerIpcFactory, - std::weak_ptr clientController) const; -}; - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -class IWebAudioPlayerAndIControlClient : public IWebAudioPlayer, public IControlClient -{ -}; - -/** - * @brief The definition of the WebAudioPlayer. - */ -class WebAudioPlayer : public IWebAudioPlayerAndIControlClient, public client::IWebAudioPlayerIpcClient -{ -public: - /** - * @brief The constructor. - * - * @param[in] client : The Web Audio Player client - * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM) - * @param[in] priority : Priority value for this pipeline. - * @param[in] config : Additional type dependent configuration data or nullptr - */ - WebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config, - const std::shared_ptr &webAudioPlayerIpcFactory, - IClientController &clientController); - - /** - * @brief Virtual destructor. - */ - virtual ~WebAudioPlayer(); - - bool play() override; - - bool pause() override; - - bool setEos() override; - - bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) override; - - bool getBufferDelay(uint32_t &delayFrames) override; - - bool writeBuffer(const uint32_t numberOfFrames, void *data) override; - - bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override; - - bool setVolume(double volume) override; - - bool getVolume(double &volume) override; - - std::weak_ptr getClient() override; - - void notifyState(WebAudioPlayerState state) override; - - void notifyApplicationState(ApplicationState state) override; - -protected: - /** - * @brief The web audio player client. - */ - std::weak_ptr m_webAudioPlayerClient; - - /** - * @brief The media player ipc object. - */ - std::unique_ptr m_webAudioPlayerIpc; - - /** - * @brief The rialto client controller object. - */ - IClientController &m_clientController; - - /** - * @brief The shared memory region info. - */ - std::shared_ptr m_webAudioShmInfo; - - /** - * @brief Ensure thread safety for clients by preventing concurrent writing to the buffer. - */ - std::mutex m_bufLock; - - /** - * @brief The bytes per frame for this audio playback. - */ - uint32_t m_bytesPerFrame; - - /** - * @brief The current application state. - */ - std::atomic m_currentAppState; -}; - -}; // namespace firebolt::rialto::client - -#endif // FIREBOLT_RIALTO_CLIENT_WEB_AUDIO_PLAYER_H_ diff --git a/middleware/rialto-client/media/client/main/include/WebAudioPlayerProxy.h b/middleware/rialto-client/media/client/main/include/WebAudioPlayerProxy.h deleted file mode 100644 index 2902f818c..000000000 --- a/middleware/rialto-client/media/client/main/include/WebAudioPlayerProxy.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_WEB_AUDIO_PLAYER_PROXY_H_ -#define FIREBOLT_RIALTO_WEB_AUDIO_PLAYER_PROXY_H_ - -#include -#include - -#include "WebAudioPlayer.h" - -namespace firebolt::rialto -{ -class WebAudioPlayerProxy : public client::IWebAudioPlayerAndIControlClient -{ -public: - WebAudioPlayerProxy(const std::shared_ptr &webAudioPlayer, - client::IClientController &clientController); - virtual ~WebAudioPlayerProxy(); - - bool play() override { return m_webAudioPlayer->play(); } - - bool pause() override { return m_webAudioPlayer->pause(); } - - bool setEos() override { return m_webAudioPlayer->setEos(); } - - bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) override - { - return m_webAudioPlayer->getBufferAvailable(availableFrames, webAudioShmInfo); - } - - bool getBufferDelay(uint32_t &delayFrames) override { return m_webAudioPlayer->getBufferDelay(delayFrames); } - - bool writeBuffer(const uint32_t numberOfFrames, void *data) override - { - return m_webAudioPlayer->writeBuffer(numberOfFrames, data); - } - - bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override - { - return m_webAudioPlayer->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay); - } - - bool setVolume(double volume) override { return m_webAudioPlayer->setVolume(volume); } - - bool getVolume(double &volume) override { return m_webAudioPlayer->getVolume(volume); } - - std::weak_ptr getClient() override { return m_webAudioPlayer->getClient(); } - - void notifyApplicationState(ApplicationState state) override { m_webAudioPlayer->notifyApplicationState(state); } - -private: - std::shared_ptr m_webAudioPlayer; - client::IClientController &m_clientController; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_WEB_AUDIO_PLAYER_PROXY_H_ diff --git a/middleware/rialto-client/media/client/main/source/AttachedSources.cpp b/middleware/rialto-client/media/client/main/source/AttachedSources.cpp deleted file mode 100644 index a0980f512..000000000 --- a/middleware/rialto-client/media/client/main/source/AttachedSources.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "AttachedSources.h" - -namespace firebolt::rialto::client -{ -void AttachedSources::add(std::uint32_t id, const MediaSourceType &mediaSourceType) -{ - std::unique_lock lock{m_mutex}; - m_attachedSources.emplace(id, Source{mediaSourceType}); -} - -void AttachedSources::remove(std::uint32_t id) -{ - std::unique_lock lock{m_mutex}; - m_attachedSources.erase(id); -} - -MediaSourceType AttachedSources::getType(std::uint32_t id) const -{ - std::unique_lock lock{m_mutex}; - auto iter = m_attachedSources.find(id); - if (m_attachedSources.end() == iter) - { - return MediaSourceType::UNKNOWN; - } - return iter->second.type; -} - -bool AttachedSources::isFlushing(std::uint32_t id) const -{ - std::unique_lock lock{m_mutex}; - auto iter = m_attachedSources.find(id); - if (m_attachedSources.end() == iter) - { - return false; - } - return iter->second.isFlushing; -} - -void AttachedSources::setFlushing(std::uint32_t id, bool flushing) -{ - std::unique_lock lock{m_mutex}; - auto iter = m_attachedSources.find(id); - if (m_attachedSources.end() == iter) - { - return; - } - iter->second.isFlushing = flushing; -} -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/ClientController.cpp b/middleware/rialto-client/media/client/main/source/ClientController.cpp deleted file mode 100644 index 3b1a6fdb7..000000000 --- a/middleware/rialto-client/media/client/main/source/ClientController.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClientController.h" -#include "RialtoClientLogging.h" -#include "SharedMemoryHandle.h" -#include -#include -#include -#include -#include - -namespace -{ -// The following error would be reported if a client is deleted -// before unregisterClient() was called. Calling unregisterClient can -// be automated via a proxy class (like the class MediaPipelineProxy) -const std::string kClientPointerNotLocked{"A client could not be locked"}; -}; // namespace - -namespace firebolt::rialto::client -{ -IClientControllerAccessor &IClientControllerAccessor::instance() -{ - static ClientControllerAccessor factory; - return factory; -} - -IClientController &ClientControllerAccessor::getClientController() const -{ - static ClientController ClientController{IControlIpcFactory::createFactory()}; - return ClientController; -} - -ClientController::ClientController(const std::shared_ptr &ControlIpcFactory) - : m_currentState{ApplicationState::UNKNOWN}, m_registrationRequired{true} -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - const char kSrcRev[] = SRCREV; - const char kTags[] = TAGS; - - if (std::strlen(kSrcRev) > 0) - { - if (std::strlen(kTags) > 0) - { - RIALTO_CLIENT_LOG_MIL("Release Tag(s): %s (Commit ID: %s)", kTags, kSrcRev); - } - else - { - RIALTO_CLIENT_LOG_MIL("Release Tag(s): No Release Tags! (Commit ID: %s)", kSrcRev); - } - } - else - { - RIALTO_CLIENT_LOG_WARN("Failed to get git commit ID!"); - } - - m_controlIpc = ControlIpcFactory->createControlIpc(this); - if (nullptr == m_controlIpc) - { - throw std::runtime_error("Failed to create the ControlIpc object"); - } -} - -ClientController::~ClientController() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - termSharedMemory(); -} - -std::shared_ptr ClientController::getSharedMemoryHandle() -{ - std::lock_guard lock{m_mutex}; - return m_shmHandle; -} - -bool ClientController::registerClient(std::weak_ptr client, ApplicationState &appState) -{ - std::shared_ptr clientLocked = client.lock(); - if (!clientLocked) - { - RIALTO_CLIENT_LOG_ERROR("Client ptr is null"); - return false; - } - - std::lock_guard lock{m_mutex}; - if (m_registrationRequired) - { - if (!m_controlIpc->registerClient()) - { - RIALTO_CLIENT_LOG_ERROR("Failed to register client"); - return false; - } - } - m_registrationRequired = false; - - bool alreadyRegistered{std::find_if(m_clients.begin(), m_clients.end(), - [&](auto &i) - { - std::shared_ptr iLocked = i.lock(); - return (iLocked == clientLocked); - }) != m_clients.end()}; - if (!alreadyRegistered) - m_clients.push_back(client); - appState = m_currentState; - - return true; -} - -bool ClientController::unregisterClient(std::weak_ptr client) -{ - std::shared_ptr clientLocked = client.lock(); - if (!clientLocked) - { - RIALTO_CLIENT_LOG_ERROR("Client ptr is null"); - return false; - } - - std::lock_guard lock{m_mutex}; - - bool found{false}; - for (auto i = m_clients.begin(); i != m_clients.end();) - { - std::shared_ptr iLocked = i->lock(); - if (!iLocked) - { - RIALTO_CLIENT_LOG_ERROR("%s", kClientPointerNotLocked.c_str()); - i = m_clients.erase(i); - } - else if (iLocked == clientLocked) - { - i = m_clients.erase(i); - found = true; - break; - } - else - ++i; - } - - if (!found) - { - RIALTO_CLIENT_LOG_ERROR("Client not found"); - return false; - } - - return true; -} - -bool ClientController::initSharedMemory() -try -{ - std::lock_guard lock{m_mutex}; - int32_t shmFd{-1}; - uint32_t shmBufferLen{0U}; - if (!m_controlIpc->getSharedMemory(shmFd, shmBufferLen)) - { - RIALTO_CLIENT_LOG_ERROR("Failed to get the shared memory"); - return false; - } - m_shmHandle = std::make_shared(shmFd, shmBufferLen); - - RIALTO_CLIENT_LOG_INFO("Shared buffer was successfully initialised"); - return true; -} -catch (const std::exception &e) -{ - RIALTO_CLIENT_LOG_ERROR("Failed to initialise shared memory: %s", e.what()); - return false; -} - -void ClientController::termSharedMemory() -{ - std::lock_guard lock{m_mutex}; - m_shmHandle.reset(); -} - -void ClientController::notifyApplicationState(ApplicationState state) -{ - { - std::lock_guard lock{m_mutex}; - if (ApplicationState::UNKNOWN == state) - { - RIALTO_CLIENT_LOG_DEBUG("Application state changed to unknown. Client will have to register next time"); - m_registrationRequired = true; - } - if (m_currentState == state) - { - RIALTO_CLIENT_LOG_WARN("Rialto application state already set, %s", stateToString(m_currentState).c_str()); - return; - } - } - - switch (state) - { - case ApplicationState::RUNNING: - { - if (!initSharedMemory()) - { - RIALTO_CLIENT_LOG_ERROR("Could not initalise the shared memory"); - return; - } - // Inform clients after memory initialisation - changeStateAndNotifyClients(state); - break; - } - case ApplicationState::INACTIVE: - case ApplicationState::UNKNOWN: - { - // Inform clients before memory termination - changeStateAndNotifyClients(state); - termSharedMemory(); - break; - } - } -} - -std::string ClientController::stateToString(ApplicationState state) -{ - switch (state) - { - case ApplicationState::RUNNING: - { - return "RUNNING"; - } - case ApplicationState::INACTIVE: - { - return "INACTIVE"; - } - case ApplicationState::UNKNOWN: - default: - { - return "UNKNOWN"; - } - } -} - -void ClientController::changeStateAndNotifyClients(ApplicationState state) -{ - std::vector> currentClients; - { - std::lock_guard lock{m_mutex}; - RIALTO_CLIENT_LOG_MIL("Rialto application state changed from %s to %s", stateToString(m_currentState).c_str(), - stateToString(state).c_str()); - m_currentState = state; - for (const std::weak_ptr &client : m_clients) - { - std::shared_ptr clientLocked{client.lock()}; - if (clientLocked) - { - currentClients.push_back(clientLocked); - } - else - { - RIALTO_CLIENT_LOG_ERROR("%s", kClientPointerNotLocked.c_str()); - } - } - } - for (const auto &client : currentClients) - { - client->notifyApplicationState(state); - } -} -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/ClientLogControl.cpp b/middleware/rialto-client/media/client/main/source/ClientLogControl.cpp deleted file mode 100644 index c5b695d04..000000000 --- a/middleware/rialto-client/media/client/main/source/ClientLogControl.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClientLogControl.h" -#include "RialtoClientLogging.h" - -namespace -{ -const std::vector kAllComponentsToLog{RIALTO_COMPONENT_CLIENT, RIALTO_COMPONENT_IPC, - RIALTO_COMPONENT_COMMON}; - -firebolt::rialto::IClientLogHandler::Level convertLevel(const RIALTO_DEBUG_LEVEL &level) -{ - switch (level) - { - case RIALTO_DEBUG_LEVEL_FATAL: - return firebolt::rialto::IClientLogHandler::Level::Fatal; - case RIALTO_DEBUG_LEVEL_ERROR: - return firebolt::rialto::IClientLogHandler::Level::Error; - case RIALTO_DEBUG_LEVEL_WARNING: - return firebolt::rialto::IClientLogHandler::Level::Warning; - case RIALTO_DEBUG_LEVEL_MILESTONE: - return firebolt::rialto::IClientLogHandler::Level::Milestone; - case RIALTO_DEBUG_LEVEL_INFO: - return firebolt::rialto::IClientLogHandler::Level::Info; - case RIALTO_DEBUG_LEVEL_DEBUG: - return firebolt::rialto::IClientLogHandler::Level::Debug; - case RIALTO_DEBUG_LEVEL_EXTERNAL: - return firebolt::rialto::IClientLogHandler::Level::External; - case RIALTO_DEBUG_LEVEL_DEFAULT: - return firebolt::rialto::IClientLogHandler::Level::Milestone; - } - return firebolt::rialto::IClientLogHandler::Level::Debug; -} -} // namespace - -namespace firebolt::rialto -{ -std::shared_ptr IClientLogControlFactory::createFactory() -{ - return client::ClientLogControlFactory::createFactory(); -} -} // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -std::shared_ptr ClientLogControlFactory::createFactory() -{ - return std::make_shared(); -} - -IClientLogControl &ClientLogControlFactory::createClientLogControl() -{ - static std::unique_ptr clientLogControl{std::make_unique()}; - return *clientLogControl; -} - -ClientLogControl::ClientLogControl() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); -} - -ClientLogControl::~ClientLogControl() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - std::unique_lock lock{m_logHandlerMutex}; - if (m_logHandler) - cancelLogHandler(); -} - -bool ClientLogControl::registerLogHandler(const std::shared_ptr &handler, bool ignoreLogLevels) -{ - std::unique_lock lock{m_logHandlerMutex}; - - if (m_logHandler) - { - if (handler) - { - RIALTO_CLIENT_LOG_WARN("Replacing old log handler"); - } - cancelLogHandler(); - } - - m_logHandler = handler; - - if (!handler) - return true; - - for (auto component : kAllComponentsToLog) - { - if (firebolt::rialto::logging::setLogHandler(component, - std::bind(&ClientLogControl::forwardLog, this, component, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5, std::placeholders::_6), - ignoreLogLevels) != - firebolt::rialto::logging::RIALTO_LOGGING_STATUS_OK) - { - RIALTO_CLIENT_LOG_WARN("Unable to register log handler"); - cancelLogHandler(); - return false; - } - } - return true; -} - -void ClientLogControl::cancelLogHandler() -{ - RIALTO_CLIENT_LOG_INFO("Cancelling log handler"); - for (auto component : kAllComponentsToLog) - { - firebolt::rialto::logging::setLogHandler(component, nullptr, false); - } - m_logHandler = nullptr; -} - -void ClientLogControl::forwardLog(RIALTO_COMPONENT component, RIALTO_DEBUG_LEVEL level, const char *file, int line, - const char *function, const char *message, std::size_t messageLen) -{ - // Take a local copy to ensure thread safety - std::shared_ptr logHandler{m_logHandler}; - if (logHandler) - { - logHandler->log(convertLevel(level), std::string(file), line, std::string(function), std::string(message)); - } -} -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/Control.cpp b/middleware/rialto-client/media/client/main/source/Control.cpp deleted file mode 100644 index 9bd12f063..000000000 --- a/middleware/rialto-client/media/client/main/source/Control.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Control.h" -#include "IControlIpc.h" -#include "RialtoClientLogging.h" - -namespace firebolt::rialto -{ -std::shared_ptr IControlFactory::createFactory() -{ - return client::ControlFactory::createFactory(); -} -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -std::shared_ptr ControlFactory::createFactory() -{ - std::shared_ptr factory; - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the rialto control factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr ControlFactory::createControl() const -try -{ - return std::make_shared(IClientControllerAccessor::instance().getClientController()); -} -catch (const std::exception &e) -{ - RIALTO_CLIENT_LOG_ERROR("Failed to create the rialto control, reason: %s", e.what()); - return nullptr; -} - -Control::Control(IClientController &clientController) : m_clientController(clientController) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); -} - -Control::~Control() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - for (const auto &client : m_clientsToUnregister) - { - m_clientController.unregisterClient(client); - } -} - -bool Control::registerClient(std::weak_ptr client, ApplicationState &appState) -{ - std::shared_ptr lockedClient = client.lock(); - if (lockedClient && m_clientController.registerClient(lockedClient, appState)) - { - m_clientsToUnregister.push_back(lockedClient); - return true; - } - RIALTO_CLIENT_LOG_WARN("Unable to register client"); - return false; -} - -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/KeyIdMap.cpp b/middleware/rialto-client/media/client/main/source/KeyIdMap.cpp deleted file mode 100644 index 9444b5e1f..000000000 --- a/middleware/rialto-client/media/client/main/source/KeyIdMap.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "KeyIdMap.h" - -namespace firebolt::rialto::client -{ -KeyIdMap &KeyIdMap::instance() -{ - static KeyIdMap keyIdMap; - return keyIdMap; -} - -void KeyIdMap::addSession(std::int32_t keySessionId) -{ - std::unique_lock lock{m_mutex}; - m_keyIdMap.insert(std::make_pair(keySessionId, std::vector())); -} - -bool KeyIdMap::updateKey(std::int32_t keySessionId, const std::vector &keyId) -{ - std::unique_lock lock{m_mutex}; - auto keyIdIter{m_keyIdMap.find(keySessionId)}; - if (m_keyIdMap.end() == keyIdIter) - { - return false; - } - keyIdIter->second = keyId; - return true; -} - -std::vector KeyIdMap::get(std::int32_t keySessionId) const -{ - std::unique_lock lock{m_mutex}; - auto keyIdIter{m_keyIdMap.find(keySessionId)}; - if (m_keyIdMap.end() == keyIdIter) - { - return std::vector(); - } - return keyIdIter->second; -} - -void KeyIdMap::erase(std::int32_t keySessionId) -{ - std::unique_lock lock{m_mutex}; - m_keyIdMap.erase(keySessionId); -} -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/MediaKeys.cpp b/middleware/rialto-client/media/client/main/source/MediaKeys.cpp deleted file mode 100644 index 0324cf828..000000000 --- a/middleware/rialto-client/media/client/main/source/MediaKeys.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "KeyIdMap.h" -#include "MediaKeys.h" -#include "RialtoClientLogging.h" - -namespace -{ -bool isPlayready(const std::string &keySystem) -{ - return keySystem.find("playready") != std::string::npos; -} -} // namespace - -namespace firebolt::rialto -{ -std::shared_ptr IMediaKeysFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr MediaKeysFactory::createMediaKeys(const std::string &keySystem) const -{ - return createMediaKeys(keySystem, {}); -} - -std::unique_ptr -MediaKeysFactory::createMediaKeys(const std::string &keySystem, - std::weak_ptr mediaKeysIpcFactory) const -{ - std::unique_ptr mediaKeys; - try - { - std::shared_ptr mediaKeysIpcFactoryLocked = - mediaKeysIpcFactory.lock(); - mediaKeys = std::make_unique(keySystem, mediaKeysIpcFactoryLocked - ? mediaKeysIpcFactoryLocked - : client::IMediaKeysIpcFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys, reason: %s", e.what()); - } - - return mediaKeys; -} -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -MediaKeys::MediaKeys(const std::string &keySystem, const std::shared_ptr &mediaKeysIpcFactory) - : m_keySystem{keySystem} -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - m_mediaKeysIpc = mediaKeysIpcFactory->createMediaKeysIpc(keySystem); - if (!m_mediaKeysIpc) - { - throw std::runtime_error("Media keys ipc could not be created"); - } -} - -MediaKeys::~MediaKeys() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_mediaKeysIpc.reset(); -} - -MediaKeyErrorStatus MediaKeys::selectKeyId(int32_t keySessionId, const std::vector &keyId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - if (KeyIdMap::instance().updateKey(keySessionId, keyId)) - { - return MediaKeyErrorStatus::OK; - } - return MediaKeyErrorStatus::FAIL; -} - -bool MediaKeys::containsKey(int32_t keySessionId, const std::vector &keyId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->containsKey(keySessionId, keyId); -} - -MediaKeyErrorStatus MediaKeys::createKeySession(KeySessionType sessionType, std::weak_ptr client, - bool isLDL, int32_t &keySessionId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - auto result{m_mediaKeysIpc->createKeySession(sessionType, client, isLDL, keySessionId)}; - if (isPlayready(m_keySystem) && MediaKeyErrorStatus::OK == result) - { - KeyIdMap::instance().addSession(keySessionId); - } - return result; -} - -MediaKeyErrorStatus MediaKeys::generateRequest(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->generateRequest(keySessionId, initDataType, initData); -} - -MediaKeyErrorStatus MediaKeys::loadSession(int32_t keySessionId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->loadSession(keySessionId); -} - -MediaKeyErrorStatus MediaKeys::updateSession(int32_t keySessionId, const std::vector &responseData) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->updateSession(keySessionId, responseData); -} - -MediaKeyErrorStatus MediaKeys::setDrmHeader(int32_t keySessionId, const std::vector &requestData) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->setDrmHeader(keySessionId, requestData); -} - -MediaKeyErrorStatus MediaKeys::closeKeySession(int32_t keySessionId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - if (isPlayready(m_keySystem)) - { - KeyIdMap::instance().erase(keySessionId); - } - return m_mediaKeysIpc->closeKeySession(keySessionId); -} - -MediaKeyErrorStatus MediaKeys::removeKeySession(int32_t keySessionId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->removeKeySession(keySessionId); -} - -MediaKeyErrorStatus MediaKeys::deleteDrmStore() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->deleteDrmStore(); -} - -MediaKeyErrorStatus MediaKeys::deleteKeyStore() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->deleteKeyStore(); -} - -MediaKeyErrorStatus MediaKeys::getDrmStoreHash(std::vector &drmStoreHash) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->getDrmStoreHash(drmStoreHash); -} - -MediaKeyErrorStatus MediaKeys::getKeyStoreHash(std::vector &keyStoreHash) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->getKeyStoreHash(keyStoreHash); -} - -MediaKeyErrorStatus MediaKeys::getLdlSessionsLimit(uint32_t &ldlLimit) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->getLdlSessionsLimit(ldlLimit); -} - -MediaKeyErrorStatus MediaKeys::getLastDrmError(int32_t keySessionId, uint32_t &errorCode) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->getLastDrmError(keySessionId, errorCode); -} - -MediaKeyErrorStatus MediaKeys::getDrmTime(uint64_t &drmTime) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->getDrmTime(drmTime); -} - -MediaKeyErrorStatus MediaKeys::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->getCdmKeySessionId(keySessionId, cdmKeySessionId); -} - -MediaKeyErrorStatus MediaKeys::releaseKeySession(int32_t keySessionId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaKeysIpc->releaseKeySession(keySessionId); -} - -MediaKeyErrorStatus MediaKeys::getMetricSystemData(std::vector &buffer) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysIpc->getMetricSystemData(buffer); -} -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/MediaKeysCapabilities.cpp b/middleware/rialto-client/media/client/main/source/MediaKeysCapabilities.cpp deleted file mode 100644 index 1508b2fd1..000000000 --- a/middleware/rialto-client/media/client/main/source/MediaKeysCapabilities.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "IMediaKeysCapabilitiesIpcFactory.h" -#include "MediaKeysCapabilities.h" -#include "RialtoClientLogging.h" - -namespace firebolt::rialto -{ -std::weak_ptr MediaKeysCapabilitiesFactory::m_mediaKeysCapabilities; -std::mutex MediaKeysCapabilitiesFactory::m_creationMutex; - -std::shared_ptr IMediaKeysCapabilitiesFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys capabilities factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr MediaKeysCapabilitiesFactory::getMediaKeysCapabilities() const -{ - std::lock_guard lock{m_creationMutex}; - - std::shared_ptr mediaKeysCapabilities = - MediaKeysCapabilitiesFactory::m_mediaKeysCapabilities.lock(); - - if (!mediaKeysCapabilities) - { - try - { - mediaKeysCapabilities = std::make_shared( - client::IMediaKeysCapabilitiesIpcFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media keys capabilities, reason: %s", e.what()); - } - - MediaKeysCapabilitiesFactory::m_mediaKeysCapabilities = mediaKeysCapabilities; - } - - return mediaKeysCapabilities; -} - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -MediaKeysCapabilities::MediaKeysCapabilities( - const std::shared_ptr &MediaKeysCapabilitiesIpcFactory) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_mediaKeysCapabilitiesIpc = MediaKeysCapabilitiesIpcFactory->getMediaKeysCapabilitiesIpc(); - if (!m_mediaKeysCapabilitiesIpc) - { - throw std::runtime_error("Media keys capabilities ipc could not be created"); - } -} - -MediaKeysCapabilities::~MediaKeysCapabilities() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_mediaKeysCapabilitiesIpc.reset(); -} - -std::vector MediaKeysCapabilities::getSupportedKeySystems() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysCapabilitiesIpc->getSupportedKeySystems(); -} - -bool MediaKeysCapabilities::supportsKeySystem(const std::string &keySystem) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysCapabilitiesIpc->supportsKeySystem(keySystem); -} - -bool MediaKeysCapabilities::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysCapabilitiesIpc->getSupportedKeySystemVersion(keySystem, version); -} - -bool MediaKeysCapabilities::isServerCertificateSupported(const std::string &keySystem) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaKeysCapabilitiesIpc->isServerCertificateSupported(keySystem); -} - -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/MediaPipeline.cpp b/middleware/rialto-client/media/client/main/source/MediaPipeline.cpp deleted file mode 100644 index c7c6913a5..000000000 --- a/middleware/rialto-client/media/client/main/source/MediaPipeline.cpp +++ /dev/null @@ -1,901 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include "KeyIdMap.h" -#include "MediaPipeline.h" -#include "MediaPipelineProxy.h" -#include "RialtoClientLogging.h" - -namespace -{ -const char *toString(const firebolt::rialto::client::MediaPipeline::State &state) -{ - switch (state) - { - case firebolt::rialto::client::MediaPipeline::State::IDLE: - return "IDLE"; - case firebolt::rialto::client::MediaPipeline::State::BUFFERING: - return "BUFFERING"; - case firebolt::rialto::client::MediaPipeline::State::PLAYING: - return "PLAYING"; - case firebolt::rialto::client::MediaPipeline::State::SEEKING: - return "SEEKING"; - case firebolt::rialto::client::MediaPipeline::State::FAILURE: - return "FAILURE"; - case firebolt::rialto::client::MediaPipeline::State::END_OF_STREAM: - return "END_OF_STREAM"; - } - return "UNKNOWN"; -} - -const char *toString(const firebolt::rialto::PlaybackState &state) -{ - switch (state) - { - case firebolt::rialto::PlaybackState::IDLE: - return "IDLE"; - case firebolt::rialto::PlaybackState::PLAYING: - return "PLAYING"; - case firebolt::rialto::PlaybackState::PAUSED: - return "PAUSED"; - case firebolt::rialto::PlaybackState::SEEKING: - return "SEEKING"; - case firebolt::rialto::PlaybackState::SEEK_DONE: - return "SEEK_DONE"; - case firebolt::rialto::PlaybackState::STOPPED: - return "STOPPED"; - case firebolt::rialto::PlaybackState::END_OF_STREAM: - return "END_OF_STREAM"; - case firebolt::rialto::PlaybackState::FAILURE: - return "FAILURE"; - case firebolt::rialto::PlaybackState::UNKNOWN: - return "UNKNOWN"; - } - return "UNKNOWN"; -} - -const char *toString(const firebolt::rialto::NetworkState &state) -{ - switch (state) - { - case firebolt::rialto::NetworkState::IDLE: - return "IDLE"; - case firebolt::rialto::NetworkState::BUFFERING: - return "BUFFERING"; - case firebolt::rialto::NetworkState::BUFFERING_PROGRESS: - return "BUFFERING_PROGRESS"; - case firebolt::rialto::NetworkState::BUFFERED: - return "BUFFERED"; - case firebolt::rialto::NetworkState::STALLED: - return "STALLED"; - case firebolt::rialto::NetworkState::FORMAT_ERROR: - return "FORMAT_ERROR"; - case firebolt::rialto::NetworkState::NETWORK_ERROR: - return "NETWORK_ERROR"; - case firebolt::rialto::NetworkState::DECODE_ERROR: - return "DECODE_ERROR"; - case firebolt::rialto::NetworkState::UNKNOWN: - return "UNKNOWN"; - } - return "UNKNOWN"; -} -} // namespace - -namespace firebolt::rialto -{ -std::shared_ptr IMediaPipelineFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media player factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr MediaPipelineFactory::createMediaPipeline(std::weak_ptr client, - const VideoRequirements &videoRequirements) const -{ - return createMediaPipeline(client, videoRequirements, {}, {}); -} - -std::unique_ptr -MediaPipelineFactory::createMediaPipeline(std::weak_ptr client, - const VideoRequirements &videoRequirements, - std::weak_ptr mediaPipelineIpcFactory, - std::weak_ptr clientController) const -{ - std::unique_ptr mediaPipeline; - try - { - std::shared_ptr mediaPipelineIpcFactoryLocked = mediaPipelineIpcFactory.lock(); - std::shared_ptr clientControllerLocked = clientController.lock(); - firebolt::rialto::client::IClientController &cc = - clientControllerLocked ? *clientControllerLocked - : client::IClientControllerAccessor::instance().getClientController(); - - auto mp{std::make_shared(client, videoRequirements, - mediaPipelineIpcFactoryLocked - ? mediaPipelineIpcFactoryLocked - : client::IMediaPipelineIpcFactory::getFactory(), - common::IMediaFrameWriterFactory::getFactory(), cc)}; - mediaPipeline = std::move(std::make_unique(mp, cc)); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media player, reason: %s", e.what()); - } - - return mediaPipeline; -} - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -MediaPipelineProxy::MediaPipelineProxy(const std::shared_ptr &mediaPipeline, - IClientController &clientController) - : m_mediaPipeline{mediaPipeline}, m_clientController{clientController} -{ - ApplicationState state{ApplicationState::UNKNOWN}; - if (!m_clientController.registerClient(m_mediaPipeline, state)) - { - throw std::runtime_error("Failed to register client with clientController"); - } - m_mediaPipeline->notifyApplicationState(state); -} - -MediaPipelineProxy::~MediaPipelineProxy() -{ - if (!m_clientController.unregisterClient(m_mediaPipeline)) - { - RIALTO_CLIENT_LOG_WARN("Failed to unregister client with clientController"); - } -} - -MediaPipeline::MediaPipeline(std::weak_ptr client, const VideoRequirements &videoRequirements, - const std::shared_ptr &mediaPipelineIpcFactory, - const std::shared_ptr &mediaFrameWriterFactory, - IClientController &clientController) - : m_mediaPipelineClient(client), m_clientController{clientController}, m_currentAppState{ApplicationState::UNKNOWN}, - m_mediaFrameWriterFactory(mediaFrameWriterFactory), m_currentState(State::IDLE) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_mediaPipelineIpc = mediaPipelineIpcFactory->createMediaPipelineIpc(this, videoRequirements); - - if (!m_mediaPipelineIpc) - { - throw std::runtime_error("Media player ipc could not be created"); - } -} - -MediaPipeline::~MediaPipeline() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_mediaPipelineIpc.reset(); -} - -bool MediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->load(type, mimeType, url); -} - -bool MediaPipeline::attachSource(const std::unique_ptr &source) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - // We should not process needDatas while attach source is ongoing - { - std::unique_lock lock{m_attachSourceMutex}; - m_attachingSource = true; - } - - int32_t sourceId = -1; - - bool status = m_mediaPipelineIpc->attachSource(source, sourceId); - if (status) - { - source->setId(sourceId); - m_attachedSources.add(sourceId, source->getType()); - } - - // Unblock needDatas - { - std::unique_lock lock{m_attachSourceMutex}; - m_attachingSource = false; - m_attachSourceCond.notify_all(); - } - return status; -} - -bool MediaPipeline::removeSource(int32_t id) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - m_attachedSources.remove(id); - return m_mediaPipelineIpc->removeSource(id); -} - -bool MediaPipeline::allSourcesAttached() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->allSourcesAttached(); -} - -bool MediaPipeline::play() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->play(); -} - -bool MediaPipeline::pause() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->pause(); -} - -bool MediaPipeline::stop() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_currentState = State::IDLE; - - return m_mediaPipelineIpc->stop(); -} - -bool MediaPipeline::setPlaybackRate(double rate) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->setPlaybackRate(rate); -} - -bool MediaPipeline::setPosition(int64_t position) -{ - switch (m_currentState) - { - case State::PLAYING: - case State::BUFFERING: - case State::SEEKING: - case State::END_OF_STREAM: - { - return handleSetPosition(position); - } - case State::IDLE: - case State::FAILURE: - default: - { - RIALTO_CLIENT_LOG_WARN("SetPosition received in unexpected state '%s'", toString(m_currentState)); - return false; - } - } -} - -bool MediaPipeline::getPosition(int64_t &position) -{ - return m_mediaPipelineIpc->getPosition(position); -} - -bool MediaPipeline::setImmediateOutput(int32_t sourceId, bool immediateOutput) -{ - return m_mediaPipelineIpc->setImmediateOutput(sourceId, immediateOutput); -} - -bool MediaPipeline::getImmediateOutput(int32_t sourceId, bool &immediateOutput) -{ - return m_mediaPipelineIpc->getImmediateOutput(sourceId, immediateOutput); -} - -bool MediaPipeline::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) -{ - return m_mediaPipelineIpc->getStats(sourceId, renderedFrames, droppedFrames); -} - -bool MediaPipeline::handleSetPosition(int64_t position) -{ - // needData requests no longer valid - { - std::lock_guard lock{m_needDataRequestMapMutex}; - m_needDataRequestMap.clear(); - } - return m_mediaPipelineIpc->setPosition(position); -} - -bool MediaPipeline::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->setVideoWindow(x, y, width, height); -} - -bool MediaPipeline::haveData(MediaSourceStatus status, uint32_t needDataRequestId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - switch (m_currentState) - { - case State::BUFFERING: - case State::PLAYING: - { - return handleHaveData(status, needDataRequestId); - } - case State::SEEKING: - { - RIALTO_CLIENT_LOG_INFO("HaveData received while seeking, discarding NeedData request %u", needDataRequestId); - discardNeedDataRequest(needDataRequestId); - return true; - } - case State::IDLE: - case State::END_OF_STREAM: - case State::FAILURE: - default: - { - RIALTO_CLIENT_LOG_WARN("HaveData received in unexpected state '%s', discarding NeedData request %u", - toString(m_currentState), needDataRequestId); - discardNeedDataRequest(needDataRequestId); - return false; - } - } -} - -bool MediaPipeline::handleHaveData(MediaSourceStatus status, uint32_t needDataRequestId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - std::shared_ptr needDataRequest; - - // Find the needDataRequest for this needDataRequestId - // The needData request can be cancelled from another thread - { - std::lock_guard lock{m_needDataRequestMapMutex}; - - auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId); - if (needDataRequestIt == m_needDataRequestMap.end()) - { - // Return success here as the data written is just ignored - RIALTO_CLIENT_LOG_WARN("Could not find need data request, with id %u", needDataRequestId); - return true; - } - - needDataRequest = needDataRequestIt->second; - m_needDataRequestMap.erase(needDataRequestIt); - } - if (m_attachedSources.isFlushing(needDataRequest->sourceId)) - { - RIALTO_CLIENT_LOG_WARN("Source %d is flushing. Ignoring need data request, with id %u", - needDataRequest->sourceId, needDataRequestId); - return true; - } - - uint32_t numFrames = needDataRequest->frameWriter ? needDataRequest->frameWriter->getNumFrames() : 0; - return m_mediaPipelineIpc->haveData(status, numFrames, needDataRequestId); -} - -AddSegmentStatus MediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - if (nullptr == mediaSegment || nullptr == mediaSegment->getData()) - { - return AddSegmentStatus::ERROR; - } - - std::lock_guard lock{m_needDataRequestMapMutex}; - auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId); - if (needDataRequestIt == m_needDataRequestMap.end()) - { - RIALTO_CLIENT_LOG_ERROR("Could not find need data request, with id %u", needDataRequestId); - return AddSegmentStatus::ERROR; - } - - std::shared_ptr needDataRequest = needDataRequestIt->second; - std::shared_ptr shmHandle = m_clientController.getSharedMemoryHandle(); - if (nullptr == shmHandle || nullptr == shmHandle->getShm()) - { - RIALTO_CLIENT_LOG_ERROR("Shared buffer no longer valid"); - return AddSegmentStatus::ERROR; - } - - // This block of code is only for playready apps using rialto c++ interface - // Widevine apps and playready apps using rialto-ocdm set MediaSegment::keyId earlier - if (mediaSegment->isEncrypted()) - { - auto keyId = KeyIdMap::instance().get(mediaSegment->getMediaKeySessionId()); - if (!keyId.empty() && mediaSegment->getKeyId().empty()) - { - RIALTO_CLIENT_LOG_DEBUG("Adding Playready keyID to media segment"); - mediaSegment->setKeyId(keyId); - } - } - - if (!needDataRequest->frameWriter) - { - if (firebolt::rialto::MediaSourceType::UNKNOWN != mediaSegment->getType()) - { - needDataRequest->frameWriter = - m_mediaFrameWriterFactory->createFrameWriter(shmHandle->getShm(), needDataRequest->shmInfo); - } - else - { - RIALTO_CLIENT_LOG_ERROR("Unrecognised type %u", static_cast(mediaSegment->getType())); - return AddSegmentStatus::ERROR; - } - - if (!needDataRequest->frameWriter) - { - RIALTO_CLIENT_LOG_ERROR("Could not create frame writer"); - return AddSegmentStatus::ERROR; - } - } - - return needDataRequest->frameWriter->writeFrame(mediaSegment); -} - -bool MediaPipeline::renderFrame() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->renderFrame(); -} - -bool MediaPipeline::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->setVolume(targetVolume, volumeDuration, easeType); -} - -bool MediaPipeline::getVolume(double ¤tVolume) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->getVolume(currentVolume); -} - -bool MediaPipeline::setMute(int32_t sourceId, bool mute) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->setMute(sourceId, mute); -} - -bool MediaPipeline::getMute(int32_t sourceId, bool &mute) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->getMute(sourceId, mute); -} - -bool MediaPipeline::setTextTrackIdentifier(const std::string &textTrackIdentifier) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->setTextTrackIdentifier(textTrackIdentifier); -} - -bool MediaPipeline::getTextTrackIdentifier(std::string &textTrackIdentifier) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->getTextTrackIdentifier(textTrackIdentifier); -} - -bool MediaPipeline::setLowLatency(bool lowLatency) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->setLowLatency(lowLatency); -} - -bool MediaPipeline::setSync(bool sync) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->setSync(sync); -} - -bool MediaPipeline::getSync(bool &sync) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->getSync(sync); -} - -bool MediaPipeline::setSyncOff(bool syncOff) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->setSyncOff(syncOff); -} - -bool MediaPipeline::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->setStreamSyncMode(sourceId, streamSyncMode); -} - -bool MediaPipeline::getStreamSyncMode(int32_t &streamSyncMode) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - return m_mediaPipelineIpc->getStreamSyncMode(streamSyncMode); -} - -bool MediaPipeline::flush(int32_t sourceId, bool resetTime, bool &async) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - std::unique_lock flushLock{m_flushMutex}; - if (m_mediaPipelineIpc->flush(sourceId, resetTime, async)) - { - m_attachedSources.setFlushing(sourceId, true); - flushLock.unlock(); - - // Clear all need datas for flushed source - std::lock_guard lock{m_needDataRequestMapMutex}; - for (auto it = m_needDataRequestMap.begin(); it != m_needDataRequestMap.end();) - { - if (it->second->sourceId == sourceId) - { - it = m_needDataRequestMap.erase(it); - } - else - { - ++it; - } - } - return true; - } - return false; -} - -bool MediaPipeline::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition); -} - -bool MediaPipeline::setSubtitleOffset(int32_t sourceId, int64_t position) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->setSubtitleOffset(sourceId, position); -} - -bool MediaPipeline::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->processAudioGap(position, duration, discontinuityGap, audioAac); -} - -bool MediaPipeline::setBufferingLimit(uint32_t limitBufferingMs) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->setBufferingLimit(limitBufferingMs); -} - -bool MediaPipeline::getBufferingLimit(uint32_t &limitBufferingMs) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->getBufferingLimit(limitBufferingMs); -} - -bool MediaPipeline::setUseBuffering(bool useBuffering) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->setUseBuffering(useBuffering); -} - -bool MediaPipeline::getUseBuffering(bool &useBuffering) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->getUseBuffering(useBuffering); -} - -bool MediaPipeline::switchSource(const std::unique_ptr &source) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineIpc->switchSource(source); -} - -void MediaPipeline::discardNeedDataRequest(uint32_t needDataRequestId) -{ - // Find the needDataRequest for this needDataRequestId - // The needData request can be cancelled from another thread - { - std::lock_guard lock{m_needDataRequestMapMutex}; - - auto needDataRequestIt = m_needDataRequestMap.find(needDataRequestId); - if (needDataRequestIt == m_needDataRequestMap.end()) - { - RIALTO_CLIENT_LOG_INFO("Could not find need data request, with id %u", needDataRequestId); - } - else - { - RIALTO_CLIENT_LOG_INFO("Discarding need data request with id %u", needDataRequestId); - m_needDataRequestMap.erase(needDataRequestIt); - } - } -} - -std::weak_ptr MediaPipeline::getClient() -{ - return m_mediaPipelineClient; -} - -void MediaPipeline::updateState(NetworkState state) -{ - State newState = m_currentState; - - switch (state) - { - case NetworkState::BUFFERING: - case NetworkState::BUFFERING_PROGRESS: - case NetworkState::STALLED: - { - newState = State::BUFFERING; - break; - } - case NetworkState::FORMAT_ERROR: - case NetworkState::NETWORK_ERROR: - case NetworkState::DECODE_ERROR: - { - newState = State::FAILURE; - break; - } - default: - { - break; - } - } - - RIALTO_CLIENT_LOG_DEBUG("Received network state '%s', old state '%s', new state '%s'", toString(state), - toString(m_currentState), toString(newState)); - m_currentState = newState; -} - -void MediaPipeline::updateState(PlaybackState state) -{ - State newState = m_currentState; - - switch (state) - { - case PlaybackState::PLAYING: - case PlaybackState::PAUSED: - { - newState = State::PLAYING; - break; - } - case PlaybackState::SEEKING: - { - newState = State::SEEKING; - break; - } - case PlaybackState::STOPPED: - { - newState = State::IDLE; - break; - } - case PlaybackState::SEEK_DONE: - { - newState = State::BUFFERING; - break; - } - case PlaybackState::END_OF_STREAM: - { - newState = State::END_OF_STREAM; - break; - } - case PlaybackState::FAILURE: - { - newState = State::FAILURE; - break; - } - default: - { - break; - } - } - - RIALTO_CLIENT_LOG_DEBUG("Received playback state '%s', old state '%s', new state '%s'", toString(state), - toString(m_currentState), toString(newState)); - m_currentState = newState; -} - -void MediaPipeline::notifyPlaybackState(PlaybackState state) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - updateState(state); - - std::shared_ptr client = m_mediaPipelineClient.lock(); - if (client) - { - client->notifyPlaybackState(state); - } -} - -void MediaPipeline::notifyPosition(int64_t position) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - std::shared_ptr client = m_mediaPipelineClient.lock(); - if (client) - { - client->notifyPosition(position); - } -} - -void MediaPipeline::notifyNetworkState(NetworkState state) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - updateState(state); - - std::shared_ptr client = m_mediaPipelineClient.lock(); - if (client) - { - client->notifyNetworkState(state); - } -} - -void MediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t requestId, - const std::shared_ptr &shmInfo) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - // If attach source is ongoing wait till it has completed so that all sources are attached - { - std::unique_lock lock{m_attachSourceMutex}; - if (m_attachingSource) - m_attachSourceCond.wait(lock, [this] { return !m_attachingSource; }); - } - - if (MediaSourceType::UNKNOWN == m_attachedSources.getType(sourceId)) - { - RIALTO_CLIENT_LOG_WARN("NeedMediaData received for unknown source %d, ignoring request id %u", sourceId, - requestId); - return; - } - if (m_attachedSources.isFlushing(sourceId)) - { - RIALTO_CLIENT_LOG_WARN("NeedMediaData received for flushing source %d, ignoring request id %u", sourceId, - requestId); - return; - } - - switch (m_currentState) - { - case State::BUFFERING: - case State::PLAYING: - { - std::shared_ptr needDataRequest = std::make_shared(); - needDataRequest->sourceId = sourceId; - needDataRequest->shmInfo = shmInfo; - - { - std::lock_guard lock{m_needDataRequestMapMutex}; - if (ApplicationState::RUNNING != m_currentAppState) - { - RIALTO_CLIENT_LOG_INFO("NeedMediaData received in state != RUNNING, ignoring request id %u", requestId); - break; - } - m_needDataRequestMap[requestId] = needDataRequest; - } - - std::shared_ptr client = m_mediaPipelineClient.lock(); - if (client) - { - client->notifyNeedMediaData(sourceId, frameCount, requestId, nullptr); - } - - break; - } - case State::SEEKING: - { - RIALTO_CLIENT_LOG_INFO("NeedMediaData received while seeking, ignoring request id %u", requestId); - break; - } - case State::IDLE: - case State::END_OF_STREAM: - case State::FAILURE: - default: - { - RIALTO_CLIENT_LOG_WARN("NeedMediaData received in unexpected state '%s', ignoring request id %u", - toString(m_currentState), requestId); - break; - } - } -} - -void MediaPipeline::notifyApplicationState(ApplicationState state) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - std::lock_guard lock{m_needDataRequestMapMutex}; - m_currentAppState = state; - if (ApplicationState::RUNNING != state) - { - // If shared memory in use, wait for it to finish before returning - m_needDataRequestMap.clear(); - } -} - -void MediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - std::shared_ptr client = m_mediaPipelineClient.lock(); - if (client) - { - client->notifyQos(sourceId, qosInfo); - } -} - -void MediaPipeline::notifyBufferUnderflow(int32_t sourceId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - std::shared_ptr client = m_mediaPipelineClient.lock(); - if (client) - { - client->notifyBufferUnderflow(sourceId); - } -} - -void MediaPipeline::notifyPlaybackError(int32_t sourceId, PlaybackError error) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - std::shared_ptr client = m_mediaPipelineClient.lock(); - if (client) - { - client->notifyPlaybackError(sourceId, error); - } -} - -void MediaPipeline::notifySourceFlushed(int32_t sourceId) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - { - std::lock_guard lock{m_flushMutex}; - m_attachedSources.setFlushing(sourceId, false); - } - std::shared_ptr client = m_mediaPipelineClient.lock(); - if (client) - { - client->notifySourceFlushed(sourceId); - } - - State expected = State::END_OF_STREAM; - m_currentState.compare_exchange_strong(expected, State::BUFFERING); -} - -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/MediaPipelineCapabilities.cpp b/middleware/rialto-client/media/client/main/source/MediaPipelineCapabilities.cpp deleted file mode 100644 index f5a20aea8..000000000 --- a/middleware/rialto-client/media/client/main/source/MediaPipelineCapabilities.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "IMediaPipelineCapabilitiesIpcFactory.h" -#include "MediaPipelineCapabilities.h" -#include "RialtoClientLogging.h" - -namespace firebolt::rialto -{ -std::shared_ptr IMediaPipelineCapabilitiesFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media pipeline capabilities factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr MediaPipelineCapabilitiesFactory::createMediaPipelineCapabilities() const -{ - std::unique_ptr mediaPipelineCapabilities; - try - { - mediaPipelineCapabilities = std::make_unique( - client::IMediaPipelineCapabilitiesIpcFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the media pipeline capabilities, reason: %s", e.what()); - } - - return mediaPipelineCapabilities; -} - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -MediaPipelineCapabilities::MediaPipelineCapabilities( - const std::shared_ptr &MediaPipelineCapabilitiesIpcFactory) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_mediaPipelineCapabilitiesIpc = MediaPipelineCapabilitiesIpcFactory->createMediaPipelineCapabilitiesIpc(); - if (!m_mediaPipelineCapabilitiesIpc) - { - throw std::runtime_error("Media pipeline capabilities ipc could not be created"); - } -} - -MediaPipelineCapabilities::~MediaPipelineCapabilities() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_mediaPipelineCapabilitiesIpc.reset(); -} - -std::vector MediaPipelineCapabilities::getSupportedMimeTypes(MediaSourceType sourceType) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineCapabilitiesIpc->getSupportedMimeTypes(sourceType); -} - -bool MediaPipelineCapabilities::isMimeTypeSupported(const std::string &mimeType) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineCapabilitiesIpc->isMimeTypeSupported(mimeType); -} - -std::vector MediaPipelineCapabilities::getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineCapabilitiesIpc->getSupportedProperties(mediaType, propertyNames); -} - -bool MediaPipelineCapabilities::isVideoMaster(bool &isVideoMaster) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_mediaPipelineCapabilitiesIpc->isVideoMaster(isVideoMaster); -} -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/SharedMemoryHandle.cpp b/middleware/rialto-client/media/client/main/source/SharedMemoryHandle.cpp deleted file mode 100644 index e632dc6fe..000000000 --- a/middleware/rialto-client/media/client/main/source/SharedMemoryHandle.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SharedMemoryHandle.h" -#include "RialtoClientLogging.h" -#include -#include -#include -#include - -namespace firebolt::rialto::client -{ -SharedMemoryHandle::SharedMemoryHandle(std::int32_t shmFd, std::uint32_t shmBufferLen) - : m_shmFd{shmFd}, m_shmBufferLen{shmBufferLen} -{ - if ((-1 == m_shmFd) || (0U == m_shmBufferLen)) - { - throw std::runtime_error("Shared buffer invalid"); - } - - m_shmBuffer = reinterpret_cast(mmap(NULL, m_shmBufferLen, PROT_READ | PROT_WRITE, MAP_SHARED, m_shmFd, 0)); - if (MAP_FAILED == m_shmBuffer) - { - close(m_shmFd); - m_shmFd = -1; - m_shmBuffer = nullptr; - m_shmBufferLen = 0U; - throw std::runtime_error("Failed to map databuffer: " + std::string(strerror(errno))); - } -} - -SharedMemoryHandle::~SharedMemoryHandle() -{ - if (-1 == m_shmFd) - { - RIALTO_CLIENT_LOG_WARN("Shared memory not initalised"); - return; - } - - int32_t ret = munmap(m_shmBuffer, m_shmBufferLen); - if (-1 == ret) - { - RIALTO_CLIENT_LOG_ERROR("Failed to unmap databuffer: %s", strerror(errno)); - } - else - { - RIALTO_CLIENT_LOG_INFO("Shared buffer was successfully terminated"); - } - - close(m_shmFd); - m_shmBuffer = nullptr; - m_shmFd = -1; - m_shmBufferLen = 0U; -} - -std::uint8_t *SharedMemoryHandle::getShm() const -{ - return m_shmBuffer; -} -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/client/main/source/WebAudioPlayer.cpp b/middleware/rialto-client/media/client/main/source/WebAudioPlayer.cpp deleted file mode 100644 index d4a504245..000000000 --- a/middleware/rialto-client/media/client/main/source/WebAudioPlayer.cpp +++ /dev/null @@ -1,280 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "IWebAudioPlayerIpc.h" -#include "IWebAudioPlayerIpcClient.h" -#include "RialtoClientLogging.h" -#include "WebAudioPlayer.h" -#include "WebAudioPlayerProxy.h" - -namespace firebolt::rialto -{ -std::shared_ptr IWebAudioPlayerFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr -WebAudioPlayerFactory::createWebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config) const -{ - return createWebAudioPlayer(client, audioMimeType, priority, config, {}, {}); -} - -std::unique_ptr -WebAudioPlayerFactory::createWebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config, - std::weak_ptr webAudioPlayerIpcFactory, - std::weak_ptr clientController) const -{ - std::unique_ptr webAudioPlayer; - try - { - std::shared_ptr webAudioPlayerIpcFactoryLocked = - webAudioPlayerIpcFactory.lock(); - std::shared_ptr clientControllerLocked = clientController.lock(); - client::IClientController &cc = clientControllerLocked - ? *clientControllerLocked - : client::IClientControllerAccessor::instance().getClientController(); - - auto wap{std::make_shared(client, audioMimeType, priority, config, - webAudioPlayerIpcFactoryLocked - ? webAudioPlayerIpcFactoryLocked - : client::IWebAudioPlayerIpcFactory::getFactory(), - cc)}; - webAudioPlayer = std::make_unique(wap, cc); - } - catch (const std::exception &e) - { - RIALTO_CLIENT_LOG_ERROR("Failed to create the web audio player, reason: %s", e.what()); - } - - return webAudioPlayer; -} - -WebAudioPlayerProxy::WebAudioPlayerProxy(const std::shared_ptr &ptr, - client::IClientController &clientController) - : m_webAudioPlayer(ptr), m_clientController{clientController} -{ - ApplicationState state{ApplicationState::UNKNOWN}; - if (!m_clientController.registerClient(m_webAudioPlayer, state)) - { - throw std::runtime_error("Failed to register client with clientController"); - } - m_webAudioPlayer->notifyApplicationState(state); -} - -WebAudioPlayerProxy::~WebAudioPlayerProxy() -{ - if (!m_clientController.unregisterClient(m_webAudioPlayer)) - { - RIALTO_CLIENT_LOG_WARN("Failed to unregister client with clientController"); - } -} - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::client -{ -WebAudioPlayer::WebAudioPlayer(std::weak_ptr client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr webAudioConfig, - const std::shared_ptr &webAudioPlayerIpcFactory, - IClientController &clientController) - : m_webAudioPlayerClient(client), m_clientController{clientController}, m_bytesPerFrame{0}, - m_currentAppState{ApplicationState::UNKNOWN} -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - if (audioMimeType == "audio/x-raw") - { - std::shared_ptr kConfig = webAudioConfig.lock(); - if (!kConfig) - { - throw std::runtime_error("Config is null for 'audio/x-raw'"); - } - m_bytesPerFrame = kConfig->pcm.channels * (kConfig->pcm.sampleSize / CHAR_BIT); - if (m_bytesPerFrame == 0) - { - throw std::runtime_error("Bytes per frame cannot be 0, channels " + std::to_string(kConfig->pcm.channels) + - ", sampleSize " + std::to_string(kConfig->pcm.sampleSize)); - } - } - - if (!webAudioPlayerIpcFactory) - { - throw std::runtime_error("Web audio player ipc factory could not be null"); - } - - m_webAudioPlayerIpc = - webAudioPlayerIpcFactory->createWebAudioPlayerIpc(this, audioMimeType, priority, webAudioConfig); - if (!m_webAudioPlayerIpc) - { - throw std::runtime_error("Web audio player ipc could not be created"); - } -} - -WebAudioPlayer::~WebAudioPlayer() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - m_webAudioPlayerIpc.reset(); -} - -bool WebAudioPlayer::play() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_webAudioPlayerIpc->play(); -} - -bool WebAudioPlayer::pause() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_webAudioPlayerIpc->pause(); -} - -bool WebAudioPlayer::setEos() -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_webAudioPlayerIpc->setEos(); -} - -bool WebAudioPlayer::getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - std::lock_guard bufLocker(m_bufLock); - if (!m_webAudioShmInfo) - { - m_webAudioShmInfo = std::make_shared(); - } - return m_webAudioPlayerIpc->getBufferAvailable(availableFrames, m_webAudioShmInfo); -} - -bool WebAudioPlayer::getBufferDelay(uint32_t &delayFrames) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_webAudioPlayerIpc->getBufferDelay(delayFrames); -} - -bool WebAudioPlayer::writeBuffer(const uint32_t numberOfFrames, void *data) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - std::lock_guard bufLocker(m_bufLock); - if (!m_webAudioShmInfo) - { - RIALTO_CLIENT_LOG_ERROR("Web audio shared info is null!"); - return false; - } - - uint32_t dataLength = numberOfFrames * m_bytesPerFrame; - uint32_t availableDataLength = m_webAudioShmInfo->lengthMain + m_webAudioShmInfo->lengthWrap; - if (dataLength > availableDataLength) - { - RIALTO_CLIENT_LOG_ERROR("The number of frames to write exceeds the available space!"); - return false; - } - - if (ApplicationState::RUNNING != m_currentAppState) - { - RIALTO_CLIENT_LOG_ERROR("Current ApplicationState is not RUNNING!"); - return false; - } - - std::shared_ptr shmHandle = m_clientController.getSharedMemoryHandle(); - if (nullptr == shmHandle || nullptr == shmHandle->getShm()) - { - RIALTO_CLIENT_LOG_ERROR("Shared buffer no longer valid"); - return false; - } - - if (dataLength > m_webAudioShmInfo->lengthMain) - { - std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetMain, data, m_webAudioShmInfo->lengthMain); - std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetWrap, - reinterpret_cast(data) + m_webAudioShmInfo->lengthMain, - dataLength - m_webAudioShmInfo->lengthMain); - } - else - { - std::memcpy(shmHandle->getShm() + m_webAudioShmInfo->offsetMain, data, dataLength); - } - return m_webAudioPlayerIpc->writeBuffer(numberOfFrames); -} - -bool WebAudioPlayer::getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_webAudioPlayerIpc->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay); -} - -bool WebAudioPlayer::setVolume(double volume) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_webAudioPlayerIpc->setVolume(volume); -} - -bool WebAudioPlayer::getVolume(double &volume) -{ - RIALTO_CLIENT_LOG_DEBUG("entry:"); - - return m_webAudioPlayerIpc->getVolume(volume); -} - -std::weak_ptr WebAudioPlayer::getClient() -{ - return m_webAudioPlayerClient; -} - -void WebAudioPlayer::notifyState(WebAudioPlayerState state) -{ - std::shared_ptr client = m_webAudioPlayerClient.lock(); - if (client) - { - client->notifyState(state); - } -} - -void WebAudioPlayer::notifyApplicationState(ApplicationState state) -{ - m_currentAppState = state; -} - -}; // namespace firebolt::rialto::client diff --git a/middleware/rialto-client/media/common/CMakeLists.txt b/middleware/rialto-client/media/common/CMakeLists.txt deleted file mode 100644 index b393eec72..000000000 --- a/middleware/rialto-client/media/common/CMakeLists.txt +++ /dev/null @@ -1,77 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -# Find includes in corresponding build directories -set( CMAKE_INCLUDE_CURRENT_DIR ON ) - -add_library( - RialtoPlayerCommon - STATIC - - source/ByteWriter.cpp - source/MediaFrameWriterFactory.cpp - source/MediaFrameWriterV1.cpp - source/MediaFrameWriterV2.cpp - source/SchemaVersion.cpp - source/TypeConverters.cpp - ) - -set_property ( - TARGET - RialtoPlayerCommon - PROPERTY POSITION_INDEPENDENT_CODE ON -) - -target_include_directories( - RialtoPlayerCommon - - PUBLIC - interface - - PRIVATE - include - $ - $ - $ - $ - ) - -set ( - RIALTO_PLAYER_COMMON_PUBLIC_HEADERS - interface/ShmCommon.h - interface/IMediaFrameWriter.h -) - -install ( - FILES ${RIALTO_PLAYER_COMMON_PUBLIC_HEADERS} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rialto -) - -target_link_libraries ( - RialtoPlayerCommon - - PRIVATE - RialtoLogging - RialtoProtobuf - ) diff --git a/middleware/rialto-client/media/common/include/ByteWriter.h b/middleware/rialto-client/media/common/include/ByteWriter.h deleted file mode 100644 index c3931d7fd..000000000 --- a/middleware/rialto-client/media/common/include/ByteWriter.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_BYTE_WRITER_H_ -#define FIREBOLT_RIALTO_COMMON_BYTE_WRITER_H_ - -#include -#include -#include - -namespace firebolt::rialto::common -{ -class ByteWriter -{ -public: - /** - * @brief Virtual destructor - */ - virtual ~ByteWriter() {} - /** - * @brief Write a byte to the buffer - * - * @param[in] buf : the buffer pointer. - * @param[in] off : the offset within the buffer. - * @param[in] byte : the byte to write; - * - * @retval the new offset. - */ - virtual size_t writeByte(uint8_t *buf, size_t off, uint8_t byte) const; - - /** - * @brief Writes a number of bytes to the buffer - * - * @param[in] buf : the buffer pointer. - * @param[in] off : the offset within the buffer. - * @param[in] bytes : the bytes to write. - * @param[in] count : the number of bytes to write. - * - * @retval the new offset. - */ - virtual size_t writeBytes(uint8_t *buf, size_t off, const uint8_t *bytes, size_t count) const; - /** - * @brief Fills the buffer with a number of bytes. - * - * @param[in] buf : the buffer pointer. - * @param[in] off : the offset within the buffer. - * @param[in] byte : the byte to write. - * @param[in] count : the number of bytes to write. - * - * @retval the new offset. - */ - virtual size_t fillBytes(uint8_t *buf, size_t off, uint8_t byte, size_t count) const; - /** - * @brief Write a 32 bit unsigned int to the buffer - * - * @param[in] buf : the buffer pointer. - * @param[in] off : the offset within the buffer. - * @param[in] val : the value to write; - * - * @retval the new offset. - */ - virtual size_t writeUint32(uint8_t *buf, size_t off, uint32_t val) const; - /** - * @brief Write a 64 bit signed int to the buffer - * - * @param[in] buf : the buffer pointer. - * @param[in] off : the offset within the buffer. - * @param[in] val : the value to write; - * - * @retval the new offset. - */ - virtual size_t writeInt64(uint8_t *buf, size_t off, int64_t val) const; - /** - * @brief Write a C string to the buffer including terminating null. - * - * @param[in] buf : the buffer pointer. - * @param[in] off : the offset within the buffer. - * @param[in] str : the str to write; - * - * @retval the new offset. - */ - virtual size_t writeCString(uint8_t *buf, size_t off, const char *str) const; -}; -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_BYTE_WRITER_H_ diff --git a/middleware/rialto-client/media/common/include/MediaFrameWriterFactory.h b/middleware/rialto-client/media/common/include/MediaFrameWriterFactory.h deleted file mode 100644 index 6597b0917..000000000 --- a/middleware/rialto-client/media/common/include/MediaFrameWriterFactory.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITER_FACTORY_H_ -#define FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITER_FACTORY_H_ - -#include "IMediaFrameWriter.h" -#include - -namespace firebolt::rialto::common -{ -/** - * @brief IMediaFrameWriter factory class definition. - */ -class MediaFrameWriterFactory : public IMediaFrameWriterFactory -{ -public: - MediaFrameWriterFactory(); - std::unique_ptr createFrameWriter(uint8_t *shmBuffer, - const std::shared_ptr &shminfo) override; - -private: - int m_metadataVersion; -}; - -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITER_FACTORY_H_ diff --git a/middleware/rialto-client/media/common/include/MediaFrameWriterV1.h b/middleware/rialto-client/media/common/include/MediaFrameWriterV1.h deleted file mode 100644 index 8174ef76a..000000000 --- a/middleware/rialto-client/media/common/include/MediaFrameWriterV1.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV1_H_ -#define FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV1_H_ - -#include "ByteWriter.h" -#include "IMediaFrameWriter.h" -#include -#include - -namespace firebolt::rialto::common -{ -/** - * @brief The definition of the MediaFrameWriterV1. - */ -class MediaFrameWriterV1 : public IMediaFrameWriter -{ -public: - /** - * @brief The constructor. - * - * @param[in] shmBuffer : The shared buffer pointer. - * @param[in] shmInfo : The information for populating the shared memory. - */ - MediaFrameWriterV1(uint8_t *shmBuffer, const std::shared_ptr &shminfo); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaFrameWriterV1() {} - - /** - * @brief Write the frame data. - * - * @param[in] data : Media Segment data. - * - * @retval true on success. - */ - AddSegmentStatus writeFrame(const std::unique_ptr &data) override; - - /** - * @brief Gets number of written frames - * - * @retval number of written frames - */ - uint32_t getNumFrames() override { return m_numFrames; } - - /** - * @brief The version of metadata this object shall write. - */ - static const uint32_t m_kMetadataVersion = 1U; - - /** - * @brief The size of the encryption metadata set if the frame is encrypted. - */ - static const uint32_t m_kEncryptionMetadataSizeBytes = 32U; - -private: - /** - * @brief Pointer to the shared memory buffer. - */ - uint8_t *m_shmBuffer; - - /** - * @brief The maximum amout of media data that can be written. - */ - const uint32_t m_kMaxMediaBytes; - - /** - * @brief The maximum amout of metadata the shared buffer can hold. - */ - const uint32_t m_kMaxMetadataBytes; - - /** - * @brief The amount of metadata bytes written to the shared buffer. - */ - uint32_t m_metadataBytesWritten; - - /** - * @brief The amount of media bytes written to the shared buffer. - */ - uint32_t m_mediaBytesWritten; - - /** - * @brief The offset of the shared memory to write the data. - */ - uint32_t m_mediaDataOffset; - - /** - * @brief The offset of the shared memory to write the metadata. - */ - uint32_t m_metadataOffset; - - /** - * @brief ByteWriter object. - */ - ByteWriter m_bytewriter; - - uint32_t m_numFrames = 0; - - /** - * @brief Write the generic frame meta data. - * - * @param[in] data : Media Segment data. - * - * @retval true on success. - */ - bool writeMetaDataGeneric(const std::unique_ptr &data); - - /** - * @brief Write the generic frame meta data. - * - * @param[in] data : Media Segment data. - * - * @retval true on success. - */ - bool writeMetaDataTypeSpecific(const std::unique_ptr &data); - - /** - * @brief Write the sample data. - * - * @param[in] data : Media Segment data. - * - * @retval true on success. - */ - bool writeData(const std::unique_ptr &data); -}; -}; // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV1_H_ diff --git a/middleware/rialto-client/media/common/include/MediaFrameWriterV2.h b/middleware/rialto-client/media/common/include/MediaFrameWriterV2.h deleted file mode 100644 index cd27b1e78..000000000 --- a/middleware/rialto-client/media/common/include/MediaFrameWriterV2.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV2_H_ -#define FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV2_H_ - -#include "ByteWriter.h" -#include "IMediaFrameWriter.h" -#include "metadata.pb.h" -#include -#include - -namespace firebolt::rialto::common -{ -/** - * @brief The definition of the MediaFrameWriterV2. - */ -class MediaFrameWriterV2 : public IMediaFrameWriter -{ -public: - /** - * @brief The constructor. - * - * @param[in] shmBuffer : The shared buffer pointer. - * @param[in] shmInfo : The information for populating the shared memory. - */ - MediaFrameWriterV2(uint8_t *shmBuffer, const std::shared_ptr &shmInfo); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaFrameWriterV2() = default; - - /** - * @brief Write the frame data. - * - * @param[in] data : Media Segment data. - * - * @retval true on success. - */ - AddSegmentStatus writeFrame(const std::unique_ptr &data) override; - - /** - * @brief Gets number of written frames - * - * @retval number of written frames - */ - uint32_t getNumFrames() override { return m_numFrames; } - -private: - /** - * @brief Builds metadata proto object - * - * @param[in] data : Media Segment data. - * - * @warning Method may throw! - * - * @retval MediaSegmentMetadata proto object - */ - MediaSegmentMetadata buildMetadata(const std::unique_ptr &data) const; - -private: - /** - * @brief ByteWriter object. - */ - ByteWriter m_byteWriter; - - /** - * @brief Pointer to the shared memory buffer. - */ - uint8_t *m_shmBuffer; - - /** - * @brief The maximum amout of data that can be written. - */ - const uint32_t m_kMaxBytes; - - /** - * @brief The amount of media bytes written to the shared buffer. - */ - uint32_t m_bytesWritten; - - /** - * @brief The offset of the shared memory to write the data. - */ - uint32_t m_dataOffset; - - /** - * @brief Number of frames written. - */ - uint32_t m_numFrames; -}; -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_MEDIA_FRAME_WRITERV2_H_ diff --git a/middleware/rialto-client/media/common/interface/IMediaFrameWriter.h b/middleware/rialto-client/media/common/interface/IMediaFrameWriter.h deleted file mode 100644 index e92051bdb..000000000 --- a/middleware/rialto-client/media/common/interface/IMediaFrameWriter.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_I_MEDIA_FRAME_WRITER_H_ -#define FIREBOLT_RIALTO_COMMON_I_MEDIA_FRAME_WRITER_H_ - -#include - -#include -#include - -#include "IMediaPipeline.h" -#include -#include - -namespace firebolt::rialto::common -{ -class IMediaFrameWriter; - -/** - * @brief IMediaFrameWriter factory class, returns a concrete implementation of IMediaFrameWriter - */ -class IMediaFrameWriterFactory -{ -public: - IMediaFrameWriterFactory() = default; - virtual ~IMediaFrameWriterFactory() = default; - - /** - * @brief Gets the IMediaFrameWriterFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Creates a IMediaFrameWriter object. - * - * @param[in] shmBuffer : The shared buffer pointer. - * @param[in] shmInfo : The information for populating the shared memory. - * - * @retval the new media frame writer audio instance or null on error. - */ - virtual std::unique_ptr createFrameWriter(uint8_t *shmBuffer, - const std::shared_ptr &shminfo) = 0; -}; - -/** - * @brief The definition of the IMediaFrameWriter interface. - * - * This interface defines the media frame writer APIs that are used to write data the shared memory. - */ -class IMediaFrameWriter -{ -public: - IMediaFrameWriter() = default; - virtual ~IMediaFrameWriter() = default; - - IMediaFrameWriter(const IMediaFrameWriter &) = delete; - IMediaFrameWriter &operator=(const IMediaFrameWriter &) = delete; - IMediaFrameWriter(IMediaFrameWriter &&) = delete; - IMediaFrameWriter &operator=(IMediaFrameWriter &&) = delete; - - /** - * @brief Write the frame data. - * - * @param[in] data : Media Segment data. - * - * @retval true on success. - */ - virtual AddSegmentStatus writeFrame(const std::unique_ptr &data) = 0; - - /** - * @brief Gets number of written frames - * - * @retval number of written frames - */ - virtual uint32_t getNumFrames() = 0; -}; - -}; // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_I_MEDIA_FRAME_WRITER_H_ diff --git a/middleware/rialto-client/media/common/interface/SchemaVersion.h b/middleware/rialto-client/media/common/interface/SchemaVersion.h deleted file mode 100644 index ada394ba2..000000000 --- a/middleware/rialto-client/media/common/interface/SchemaVersion.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_SCHEMA_VERSION_H_ -#define FIREBOLT_RIALTO_COMMON_SCHEMA_VERSION_H_ - -#include -#include - -namespace firebolt::rialto::common -{ -class SchemaVersion -{ -public: - SchemaVersion(std::uint32_t major, std::uint32_t minor, std::uint32_t patch); - ~SchemaVersion() = default; - - bool operator==(const SchemaVersion &other) const; - bool isCompatible(const SchemaVersion &other) const; - std::string str() const; - std::uint32_t major() const; - std::uint32_t minor() const; - std::uint32_t patch() const; - -private: - std::uint32_t m_major; - std::uint32_t m_minor; - std::uint32_t m_patch; -}; - -// Current schema version, common for server and client. Taken from main CMakeLists.txt file -SchemaVersion getCurrentSchemaVersion(); -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_SCHEMA_VERSION_H_ diff --git a/middleware/rialto-client/media/common/interface/ShmCommon.h b/middleware/rialto-client/media/common/interface/ShmCommon.h deleted file mode 100644 index e24134e26..000000000 --- a/middleware/rialto-client/media/common/interface/ShmCommon.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_SHM_COMMON_H_ -#define FIREBOLT_RIALTO_COMMON_SHM_COMMON_H_ - -#include - -namespace firebolt::rialto::common -{ -/** - * @brief Metadata v1 size per frame in bytes. - */ -const uint32_t VERSION_SIZE_BYTES = 4U; - -/** - * @brief Maximum bytes of extra data. - */ -const uint32_t MAX_EXTRA_DATA_SIZE = 32U; - -/** - * @brief Metadata v1 size per frame in bytes. - */ -const uint32_t METADATA_V1_SIZE_PER_FRAME_BYTES = 104U; -}; // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_SHM_COMMON_H_ diff --git a/middleware/rialto-client/media/common/interface/TypeConverters.h b/middleware/rialto-client/media/common/interface/TypeConverters.h deleted file mode 100644 index e2afddca1..000000000 --- a/middleware/rialto-client/media/common/interface/TypeConverters.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_COMMON_TYPE_CONVERTERS_H_ -#define FIREBOLT_RIALTO_COMMON_TYPE_CONVERTERS_H_ - -#include "MediaCommon.h" - -namespace firebolt::rialto::common -{ -const char *convertMediaSourceType(const MediaSourceType &mediaSourceType); -const char *convertLayout(const Layout &layout); -const char *convertFormat(const Format &format); -} // namespace firebolt::rialto::common - -#endif // FIREBOLT_RIALTO_COMMON_TYPE_CONVERTERS_H_ diff --git a/middleware/rialto-client/media/common/proto/metadata.proto b/middleware/rialto-client/media/common/proto/metadata.proto deleted file mode 120000 index 4376a45ba..000000000 --- a/middleware/rialto-client/media/common/proto/metadata.proto +++ /dev/null @@ -1 +0,0 @@ -../../../proto/metadata.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/common/source/ByteWriter.cpp b/middleware/rialto-client/media/common/source/ByteWriter.cpp deleted file mode 100644 index e1634e57d..000000000 --- a/middleware/rialto-client/media/common/source/ByteWriter.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ByteWriter.h" -#include - -namespace firebolt::rialto::common -{ -size_t ByteWriter::writeByte(uint8_t *buf, size_t off, uint8_t byte) const -{ - buf[off++] = byte; - return off; -} - -size_t ByteWriter::writeBytes(uint8_t *buf, size_t off, const uint8_t *bytes, size_t count) const -{ - if (count) - memcpy(buf + off, bytes, count); - return off + count; -} - -size_t ByteWriter::fillBytes(uint8_t *buf, size_t off, uint8_t byte, size_t count) const -{ - if (count) - memset(buf + off, byte, count); - return off + count; -} - -size_t ByteWriter::writeUint32(uint8_t *buf, size_t off, uint32_t val) const -{ - buf[off++] = (uint8_t)((val & 0x000000ff) >> 0); - buf[off++] = (uint8_t)((val & 0x0000ff00) >> 8); - buf[off++] = (uint8_t)((val & 0x00ff0000) >> 16); - buf[off++] = (uint8_t)((val & 0xff000000) >> 24); - return off; -} - -size_t ByteWriter::writeInt64(uint8_t *buf, size_t off, int64_t val) const -{ - buf[off++] = (uint8_t)((val & 0x00000000000000ff) >> 0); - buf[off++] = (uint8_t)((val & 0x000000000000ff00) >> 8); - buf[off++] = (uint8_t)((val & 0x0000000000ff0000) >> 16); - buf[off++] = (uint8_t)((val & 0x00000000ff000000) >> 24); - buf[off++] = (uint8_t)((val & 0x000000ff00000000) >> 32); - buf[off++] = (uint8_t)((val & 0x0000ff0000000000) >> 40); - buf[off++] = (uint8_t)((val & 0x00ff000000000000) >> 48); - buf[off++] = (uint8_t)((val & 0xff00000000000000) >> 56); - return off; -} - -size_t ByteWriter::writeCString(uint8_t *buf, size_t off, const char *str) const -{ - while (*str) - { - buf[off++] = *str++; - } - buf[off++] = *str; - return off; -} -} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/MediaFrameWriterFactory.cpp b/middleware/rialto-client/media/common/source/MediaFrameWriterFactory.cpp deleted file mode 100644 index baa142fae..000000000 --- a/middleware/rialto-client/media/common/source/MediaFrameWriterFactory.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaFrameWriterFactory.h" -#include "MediaFrameWriterV1.h" -#include "MediaFrameWriterV2.h" -#include "RialtoCommonLogging.h" -#include -#include -#include - -namespace -{ -constexpr int kLatestMetadataVersion{2}; -const char *kMetadataEnvVariableName{"RIALTO_METADATA_VERSION"}; -} // namespace - -namespace firebolt::rialto::common -{ -std::shared_ptr IMediaFrameWriterFactory::getFactory() -try -{ - return std::make_shared(); -} -catch (const std::exception &e) -{ - RIALTO_COMMON_LOG_ERROR("Failed to create the media frame writer factory, reason: %s", e.what()); - return nullptr; -} - -MediaFrameWriterFactory::MediaFrameWriterFactory() : m_metadataVersion{kLatestMetadataVersion} -{ - const char *kEnvVar = getenv(kMetadataEnvVariableName); - if (!kEnvVar) - { - return; - } - std::string envVarStr{kEnvVar}; - try - { - m_metadataVersion = std::stoi(envVarStr); - } - catch (const std::exception &e) - { - } - if (m_metadataVersion > kLatestMetadataVersion) - { - m_metadataVersion = kLatestMetadataVersion; - } -} - -std::unique_ptr -MediaFrameWriterFactory::createFrameWriter(uint8_t *shmBuffer, const std::shared_ptr &shmInfo) -try -{ - if (1 == m_metadataVersion) - { - return std::make_unique(shmBuffer, shmInfo); - } - return std::make_unique(shmBuffer, shmInfo); -} -catch (const std::exception &e) -{ - RIALTO_COMMON_LOG_ERROR("Failed to create the frame writer, reason: %s", e.what()); - return nullptr; -} -} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/MediaFrameWriterV1.cpp b/middleware/rialto-client/media/common/source/MediaFrameWriterV1.cpp deleted file mode 100644 index 5a5d3cc62..000000000 --- a/middleware/rialto-client/media/common/source/MediaFrameWriterV1.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaFrameWriterV1.h" -#include "RialtoCommonLogging.h" - -namespace firebolt::rialto::common -{ -MediaFrameWriterV1::MediaFrameWriterV1(uint8_t *shmBuffer, const std::shared_ptr &shmInfo) - : m_shmBuffer(shmBuffer), m_kMaxMediaBytes(shmInfo->maxMediaBytes), m_kMaxMetadataBytes(shmInfo->maxMetadataBytes), - m_mediaBytesWritten(0U), m_mediaDataOffset(shmInfo->mediaDataOffset), m_metadataOffset(shmInfo->metadataOffset) -{ - RIALTO_COMMON_LOG_INFO("We are using a writer for Metadata V1"); - - // Zero metadata memory - m_bytewriter.fillBytes(m_shmBuffer, m_metadataOffset, 0, m_kMaxMetadataBytes); - - // Set metadata version - m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, m_kMetadataVersion); - - // Track the amount of metadata bytes written - m_metadataBytesWritten = sizeof(m_kMetadataVersion); -} - -AddSegmentStatus MediaFrameWriterV1::writeFrame(const std::unique_ptr &data) -{ - if (!writeMetaDataGeneric(data)) - { - RIALTO_COMMON_LOG_ERROR("Failed to write metadata"); - return AddSegmentStatus::NO_SPACE; - } - if (!writeData(data)) - { - RIALTO_COMMON_LOG_ERROR("Failed to write segment data"); - return AddSegmentStatus::NO_SPACE; - } - if (!writeMetaDataTypeSpecific(data)) - { - return AddSegmentStatus::ERROR; - } - - // Track the amount of metadata bytes written - m_numFrames++; - m_metadataBytesWritten += METADATA_V1_SIZE_PER_FRAME_BYTES; - - return AddSegmentStatus::OK; -} - -bool MediaFrameWriterV1::writeMetaDataGeneric(const std::unique_ptr &data) -{ - // Check that there is enough metadata space for the next frame - if (m_metadataBytesWritten + METADATA_V1_SIZE_PER_FRAME_BYTES > m_kMaxMetadataBytes) - { - RIALTO_COMMON_LOG_ERROR("Not enough space to write metadata, max size %u, current size %u, frame metadata size " - "%u", - m_kMaxMetadataBytes, m_metadataBytesWritten, METADATA_V1_SIZE_PER_FRAME_BYTES); - return false; - } - else - { - m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, m_mediaDataOffset); - m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, data->getDataLength()); - m_metadataOffset = m_bytewriter.writeInt64(m_shmBuffer, m_metadataOffset, data->getTimeStamp()); - m_metadataOffset = m_bytewriter.writeInt64(m_shmBuffer, m_metadataOffset, data->getDuration()); - m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, static_cast(data->getId())); - m_metadataOffset = - m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, static_cast(data->getExtraData().size())); - - if (0 != data->getExtraData().size()) - { - m_metadataOffset = m_bytewriter.writeBytes(m_shmBuffer, m_metadataOffset, - const_cast(&(data->getExtraData()[0])), - data->getExtraData().size()); - } - m_metadataOffset = - m_bytewriter.fillBytes(m_shmBuffer, m_metadataOffset, 0, MAX_EXTRA_DATA_SIZE - data->getExtraData().size()); - - // Not encrypted so skip the encrypted section of the metadata - m_metadataOffset += m_kEncryptionMetadataSizeBytes; - } - - return true; -} - -bool MediaFrameWriterV1::writeMetaDataTypeSpecific(const std::unique_ptr &data) -{ - if (MediaSourceType::AUDIO == data->getType()) - { - IMediaPipeline::MediaSegmentAudio *audioSegment = dynamic_cast(data.get()); - if (audioSegment) - { - m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, - static_cast(audioSegment->getSampleRate())); - m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, - static_cast(audioSegment->getNumberOfChannels())); - } - else - { - RIALTO_COMMON_LOG_ERROR("Failed to get the audio segment"); - return false; - } - } - else if (MediaSourceType::VIDEO == data->getType()) - { - IMediaPipeline::MediaSegmentVideo *videoSegment = dynamic_cast(data.get()); - if (videoSegment) - { - m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, videoSegment->getWidth()); - m_metadataOffset = m_bytewriter.writeUint32(m_shmBuffer, m_metadataOffset, videoSegment->getHeight()); - } - else - { - RIALTO_COMMON_LOG_ERROR("Failed to get the video segment"); - return false; - } - } - else - { - RIALTO_COMMON_LOG_ERROR("Failed to write type specific metadata - media source type not known"); - return false; - } - return true; -} - -bool MediaFrameWriterV1::writeData(const std::unique_ptr &data) -{ - if (m_mediaBytesWritten + data->getDataLength() > m_kMaxMediaBytes) - { - RIALTO_COMMON_LOG_ERROR("Not enough space to write media data, max size %u, current size %u, size to write %u", - m_kMaxMediaBytes, m_mediaBytesWritten, data->getDataLength()); - return false; - } - - m_mediaDataOffset = m_bytewriter.writeBytes(m_shmBuffer, m_mediaDataOffset, data->getData(), data->getDataLength()); - - // Track the amount of media bytes written - m_mediaBytesWritten += data->getDataLength(); - - return true; -} -}; // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/MediaFrameWriterV2.cpp b/middleware/rialto-client/media/common/source/MediaFrameWriterV2.cpp deleted file mode 100644 index 72879b28f..000000000 --- a/middleware/rialto-client/media/common/source/MediaFrameWriterV2.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaFrameWriterV2.h" -#include "RialtoCommonLogging.h" - -namespace -{ -/** - * @brief The version of metadata this object shall write. - */ -constexpr uint32_t kMetadataVersion = 2U; - -/** - * @brief Convert SegmentAlignment to protobuf object - */ -firebolt::rialto::MediaSegmentMetadata_SegmentAlignment -convertSegmentAlignment(const firebolt::rialto::SegmentAlignment &alignment) -{ - switch (alignment) - { - case firebolt::rialto::SegmentAlignment::UNDEFINED: - { - return firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_UNDEFINED; - } - case firebolt::rialto::SegmentAlignment::NAL: - { - return firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_NAL; - } - case firebolt::rialto::SegmentAlignment::AU: - { - return firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_AU; - } - } - return firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_UNDEFINED; -} - -/** - * @brief Convert CipherMode to protobuf object - */ -firebolt::rialto::MediaSegmentMetadata_CipherMode convertCipherMode(const firebolt::rialto::CipherMode &cipherMode) -{ - switch (cipherMode) - { - case firebolt::rialto::CipherMode::UNKNOWN: - { - return firebolt::rialto::MediaSegmentMetadata_CipherMode_UNKNOWN; - } - case firebolt::rialto::CipherMode::CENC: - { - return firebolt::rialto::MediaSegmentMetadata_CipherMode_CENC; - } - case firebolt::rialto::CipherMode::CBC1: - { - return firebolt::rialto::MediaSegmentMetadata_CipherMode_CBC1; - } - case firebolt::rialto::CipherMode::CENS: - { - return firebolt::rialto::MediaSegmentMetadata_CipherMode_CENS; - } - case firebolt::rialto::CipherMode::CBCS: - { - return firebolt::rialto::MediaSegmentMetadata_CipherMode_CBCS; - } - } - return firebolt::rialto::MediaSegmentMetadata_CipherMode_UNKNOWN; -} - -firebolt::rialto::MediaSegmentMetadata_CodecData_Type convertCodecDataType(const firebolt::rialto::CodecDataType &type) -{ - if (firebolt::rialto::CodecDataType::STRING == type) - { - return firebolt::rialto::MediaSegmentMetadata_CodecData_Type_STRING; - } - return firebolt::rialto::MediaSegmentMetadata_CodecData_Type_BUFFER; -} - -} // namespace - -namespace firebolt::rialto::common -{ -MediaFrameWriterV2::MediaFrameWriterV2(uint8_t *shmBuffer, const std::shared_ptr &shmInfo) - : m_shmBuffer(shmBuffer), m_kMaxBytes(shmInfo->maxMediaBytes), m_bytesWritten(0U), - m_dataOffset(shmInfo->mediaDataOffset), m_numFrames{0} -{ - RIALTO_COMMON_LOG_INFO("We are using a writer for Metadata V2"); - - // Zero memory - m_byteWriter.fillBytes(m_shmBuffer, shmInfo->metadataOffset, 0, shmInfo->maxMetadataBytes); - m_byteWriter.fillBytes(m_shmBuffer, m_dataOffset, 0, m_kMaxBytes); - - // Set metadata version - m_byteWriter.writeUint32(m_shmBuffer, shmInfo->metadataOffset, kMetadataVersion); -} - -AddSegmentStatus MediaFrameWriterV2::writeFrame(const std::unique_ptr &data) -try -{ - auto metadata{buildMetadata(data)}; - size_t metadataSize{metadata.ByteSizeLong()}; - if (m_bytesWritten + sizeof(metadataSize) + metadataSize + data->getDataLength() > m_kMaxBytes) - { - RIALTO_COMMON_LOG_ERROR("Not enough memory available to write MediaSegment"); - return AddSegmentStatus::NO_SPACE; - } - m_dataOffset = m_byteWriter.writeUint32(m_shmBuffer, m_dataOffset, static_cast(metadataSize)); - if (!metadata.SerializeToArray(m_shmBuffer + m_dataOffset, metadataSize)) - { - RIALTO_COMMON_LOG_ERROR("Failed to write type specific metadata - protobuf serialization failed."); - m_dataOffset -= 4; // size of metadata size written in previous step - return AddSegmentStatus::ERROR; - } - m_dataOffset += metadataSize; - m_dataOffset = m_byteWriter.writeBytes(m_shmBuffer, m_dataOffset, data->getData(), data->getDataLength()); - - // Track the amount of bytes written - m_bytesWritten += sizeof(metadataSize) + metadataSize + data->getDataLength(); - ++m_numFrames; - - return AddSegmentStatus::OK; -} -catch (std::exception &e) -{ - RIALTO_COMMON_LOG_ERROR("Failed to write type specific metadata - exception occured"); - return AddSegmentStatus::ERROR; -} - -MediaSegmentMetadata MediaFrameWriterV2::buildMetadata(const std::unique_ptr &data) const -{ - MediaSegmentMetadata metadata; - metadata.set_length(data->getDataLength()); - metadata.set_time_position(data->getTimeStamp()); - metadata.set_sample_duration(data->getDuration()); - metadata.set_stream_id(static_cast(data->getId())); - if (data->getDisplayOffset()) - { - metadata.set_display_offset(data->getDisplayOffset().value()); - } - if (MediaSourceType::AUDIO == data->getType()) - { - IMediaPipeline::MediaSegmentAudio &audioSegment = dynamic_cast(*data); - metadata.set_sample_rate(static_cast(audioSegment.getSampleRate())); - metadata.set_channels_num(static_cast(audioSegment.getNumberOfChannels())); - metadata.set_clipping_start(audioSegment.getClippingStart()); - metadata.set_clipping_end(audioSegment.getClippingEnd()); - } - else if (MediaSourceType::VIDEO == data->getType()) - { - IMediaPipeline::MediaSegmentVideo &videoSegment = dynamic_cast(*data); - metadata.set_width(videoSegment.getWidth()); - metadata.set_height(videoSegment.getHeight()); - metadata.mutable_frame_rate()->set_numerator(videoSegment.getFrameRate().numerator); - metadata.mutable_frame_rate()->set_denominator(videoSegment.getFrameRate().denominator); - } - else if (MediaSourceType::SUBTITLE != data->getType()) - { - RIALTO_COMMON_LOG_ERROR("Failed to write type specific metadata - media source type unsupported"); - throw std::exception(); - } - - if (!data->getExtraData().empty()) - { - metadata.set_extra_data(std::string(data->getExtraData().begin(), data->getExtraData().end())); - } - if (SegmentAlignment::UNDEFINED != data->getSegmentAlignment()) - { - metadata.set_segment_alignment(convertSegmentAlignment(data->getSegmentAlignment())); - } - if (data->getCodecData()) - { - metadata.mutable_codec_data()->set_data( - std::string(data->getCodecData()->data.begin(), data->getCodecData()->data.end())); - metadata.mutable_codec_data()->set_type(convertCodecDataType(data->getCodecData()->type)); - } - if (data->isEncrypted()) - { - metadata.set_media_key_session_id(data->getMediaKeySessionId()); - metadata.set_key_id(std::string(data->getKeyId().begin(), data->getKeyId().end())); - metadata.set_init_vector(std::string(data->getInitVector().begin(), data->getInitVector().end())); - metadata.set_init_with_last_15(data->getInitWithLast15()); - metadata.set_cipher_mode(convertCipherMode(data->getCipherMode())); - uint32_t crypt{0}; - uint32_t skip{0}; - if (data->getEncryptionPattern(crypt, skip)) - { - metadata.set_crypt(crypt); - metadata.set_skip(skip); - } - - for (const auto &subSample : data->getSubSamples()) - { - auto subSamplePair = metadata.mutable_sub_sample_info()->Add(); - subSamplePair->set_num_clear_bytes(static_cast(subSample.numClearBytes)); - subSamplePair->set_num_encrypted_bytes(static_cast(subSample.numEncryptedBytes)); - } - } - return metadata; -} -} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/SchemaVersion.cpp b/middleware/rialto-client/media/common/source/SchemaVersion.cpp deleted file mode 100644 index 8ed388546..000000000 --- a/middleware/rialto-client/media/common/source/SchemaVersion.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SchemaVersion.h" - -namespace firebolt::rialto::common -{ -SchemaVersion::SchemaVersion(std::uint32_t major, std::uint32_t minor, std::uint32_t patch) - : m_major{major}, m_minor{minor}, m_patch{patch} -{ -} - -bool SchemaVersion::operator==(const SchemaVersion &other) const -{ - return this->m_major == other.m_major && this->m_minor == other.m_minor && this->m_patch == other.m_patch; -} - -bool SchemaVersion::isCompatible(const SchemaVersion &other) const -{ - return this->m_major == other.m_major; -} - -std::string SchemaVersion::str() const -{ - return std::to_string(m_major) + "." + std::to_string(m_minor) + "." + std::to_string(m_patch); -} - -std::uint32_t SchemaVersion::major() const -{ - return m_major; -} - -std::uint32_t SchemaVersion::minor() const -{ - return m_minor; -} - -std::uint32_t SchemaVersion::patch() const -{ - return m_patch; -} - -SchemaVersion getCurrentSchemaVersion() -try -{ - return SchemaVersion{static_cast(std::stoul(PROJECT_VER_MAJOR)), - static_cast(std::stoul(PROJECT_VER_MINOR)), - static_cast(std::stoul(PROJECT_VER_PATCH))}; -} -catch (const std::exception &e) -{ - // If conversion can't be performed, return default version - return SchemaVersion{1, 0, 0}; -} -} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/common/source/TypeConverters.cpp b/middleware/rialto-client/media/common/source/TypeConverters.cpp deleted file mode 100644 index 422d6ca7f..000000000 --- a/middleware/rialto-client/media/common/source/TypeConverters.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "TypeConverters.h" -#include - -namespace firebolt::rialto::common -{ -const char *convertMediaSourceType(const MediaSourceType &mediaSourceType) -{ - static const std::unordered_map - kMediaSourceTypeToStr{{MediaSourceType::AUDIO, "Audio"}, - {MediaSourceType::VIDEO, "Video"}, - {MediaSourceType::SUBTITLE, "Subtitle"}, - {MediaSourceType::UNKNOWN, "Unknown"}}; - const auto kIt = kMediaSourceTypeToStr.find(mediaSourceType); - if (kMediaSourceTypeToStr.end() != kIt) - { - return kIt->second; - } - return "Unknown"; -} - -const char *convertLayout(const Layout &layout) -{ - static const std::unordered_map kLayoutToStr{{Layout::INTERLEAVED, "interleaved"}, - {Layout::NON_INTERLEAVED, "non-interleaved"}}; - const auto kIt = kLayoutToStr.find(layout); - if (kLayoutToStr.end() != kIt) - { - return kIt->second; - } - return ""; -} - -const char *convertFormat(const Format &format) -{ - static const std::unordered_map kFormatToStr{{Format::S8, "S8"}, - {Format::U8, "U8"}, - {Format::S16LE, "S16LE"}, - {Format::S16BE, "S16BE"}, - {Format::U16LE, "U16LE"}, - {Format::U16BE, "U16BE"}, - {Format::S24_32LE, "S24_32LE"}, - {Format::S24_32BE, "S24_32BE"}, - {Format::U24_32LE, "U24_32LE"}, - {Format::U24_32BE, "U24_32BE"}, - {Format::S32LE, "S32LE"}, - {Format::S32BE, "S32BE"}, - {Format::U32LE, "U32LE"}, - {Format::U32BE, "U32BE"}, - {Format::S24LE, "S24LE"}, - {Format::S24BE, "S24BE"}, - {Format::U24LE, "U24LE"}, - {Format::U24BE, "U24BE"}, - {Format::S20LE, "S20LE"}, - {Format::S20BE, "S20BE"}, - {Format::U20LE, "U20LE"}, - {Format::U20BE, "U20BE"}, - {Format::S18LE, "S18LE"}, - {Format::S18BE, "S18BE"}, - {Format::U18LE, "U18LE"}, - {Format::U18BE, "U18BE"}, - {Format::F32LE, "F32LE"}, - {Format::F32BE, "F32BE"}, - {Format::F64LE, "F64LE"}, - {Format::F64BE, "F64BE"}}; - const auto kIt = kFormatToStr.find(format); - if (kFormatToStr.end() != kIt) - { - return kIt->second; - } - return ""; -} -} // namespace firebolt::rialto::common diff --git a/middleware/rialto-client/media/public/CMakeLists.txt b/middleware/rialto-client/media/public/CMakeLists.txt deleted file mode 100644 index 97dffa3f6..000000000 --- a/middleware/rialto-client/media/public/CMakeLists.txt +++ /dev/null @@ -1,58 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -add_library( - RialtoPlayerPublic - INTERFACE - ) - -target_include_directories( - RialtoPlayerPublic - INTERFACE - $ - include - ) - -set ( - RIALTO_PLAYER_PUBLIC_HEADERS - include/ControlCommon.h - include/IClientLogControl.h - include/IClientLogHandler.h - include/IControl.h - include/IControlClient.h - include/IMediaKeys.h - include/IMediaKeysCapabilities.h - include/IMediaKeysClient.h - include/IMediaPipeline.h - include/IMediaPipelineCapabilities.h - include/IMediaPipelineClient.h - include/IWebAudioPlayer.h - include/IWebAudioPlayerClient.h - include/MediaCommon.h -) - -install ( - FILES ${RIALTO_PLAYER_PUBLIC_HEADERS} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rialto -) diff --git a/middleware/rialto-client/media/public/include/ControlCommon.h b/middleware/rialto-client/media/public/include/ControlCommon.h deleted file mode 100644 index c2a8ee16b..000000000 --- a/middleware/rialto-client/media/public/include/ControlCommon.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CONTROL_COMMON_H_ -#define FIREBOLT_RIALTO_CONTROL_COMMON_H_ - -/** - * @file ControlCommon.h - * - * The definition of the Control Common types - * - */ - -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief The application state. - */ -enum class ApplicationState -{ - UNKNOWN, - RUNNING, - INACTIVE -}; -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_CONTROL_COMMON_H_ diff --git a/middleware/rialto-client/media/public/include/IClientLogControl.h b/middleware/rialto-client/media/public/include/IClientLogControl.h deleted file mode 100644 index 2347bef93..000000000 --- a/middleware/rialto-client/media/public/include/IClientLogControl.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ -#define FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ - -/** - * @file IClientLogControl.h - * - * The definition of the IClientLogControl interface. - * - * Via this interface the logging of the Rialto Client can - * be redirected to a user specified call handler - */ - -#include -#include - -#include "ControlCommon.h" -#include "IClientLogHandler.h" -#include "IControlClient.h" - -namespace firebolt::rialto -{ -class IClientLogControl; - -/** - * @brief IClientLogControl factory class, returns a concrete implementation of IClientLogControl - */ -class IClientLogControlFactory -{ -public: - IClientLogControlFactory() = default; - virtual ~IClientLogControlFactory() = default; - - /** - * @brief Creates the IClientLogControlFactory - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IClientLogControl factory method, returns a concrete singleton implementation of IClientLogControl - * - * @retval the new IClientLogControl instance or null on error. - */ - virtual IClientLogControl &createClientLogControl() = 0; -}; - -/** - * @brief The definition of the IClientLogControl interface. - * - * This interface defines the public API for controlling Rialto client's - * log handling. This class is a singleton - * - */ -class IClientLogControl -{ -public: - IClientLogControl() = default; - virtual ~IClientLogControl() = default; - - IClientLogControl(const IClientLogControl &) = delete; - IClientLogControl &operator=(const IClientLogControl &) = delete; - IClientLogControl(IClientLogControl &&) = delete; - IClientLogControl &operator=(IClientLogControl &&) = delete; - - /** - * @brief Register a new log handler - * - * @param[in] handler : The user can pass in an object that will henceforth - * receive callbacks to it's log(...) method for rialto client log events. - * Please see IClientLogHandler for the parameters that log() must accept. - * To cancel callbacks then call this method again but pass a nullptr for - * the handler. - * @param[in] ignoreLogLevels : If true then the handler will receive ALL log level messages regardless of the - * currently configured log level - * - * @retval true if successful - */ - virtual bool registerLogHandler(const std::shared_ptr &handler, bool ignoreLogLevels) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ diff --git a/middleware/rialto-client/media/public/include/IClientLogHandler.h b/middleware/rialto-client/media/public/include/IClientLogHandler.h deleted file mode 100644 index 4afc91c3e..000000000 --- a/middleware/rialto-client/media/public/include/IClientLogHandler.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file ILogHandler.h - * - * This file comprises the class definition of ILogHandler. - * An interface, which provides API of custom server manager logging handler - */ - -#ifndef FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ -#define FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ - -/** - * @file IClientLogHandler.h - * - * The definition of the IClientLogHandler interface. - * - * This interface allows the user to define their own log handler for - * any messages generated by the rialto client library - */ - -#include - -namespace firebolt::rialto -{ -/** - * @brief IClientLogHandler allows the user to define their own log handler for - * any messages generated by the rialto client library - */ -class IClientLogHandler -{ -public: - IClientLogHandler() = default; - virtual ~IClientLogHandler() = default; - IClientLogHandler(const IClientLogHandler &) = delete; - IClientLogHandler &operator=(const IClientLogHandler &) = delete; - IClientLogHandler(IClientLogHandler &&) = delete; - IClientLogHandler &operator=(IClientLogHandler &&) = delete; - - /** - * @brief All possible log levels that could be used in the log callback - */ - - enum class Level - { - Fatal, - Error, - Warning, - Milestone, - Info, - Debug, - External - }; - - /** - * @brief A callback method for every log item generated by the rialto client library - * - * @param[in] level : The log level - * @param[in] file : The source code file where the log is defined - * @param[in] line : The line number within the file where the log is defined - * @param[in] function : The source code function within which the log is defined - * @param[in] message : The message of the log - */ - virtual void log(Level level, const std::string &file, int line, const std::string &function, - const std::string &message) = 0; -}; -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ diff --git a/middleware/rialto-client/media/public/include/IControl.h b/middleware/rialto-client/media/public/include/IControl.h deleted file mode 100644 index 740d4f236..000000000 --- a/middleware/rialto-client/media/public/include/IControl.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_CONTROL_H_ -#define FIREBOLT_RIALTO_I_CONTROL_H_ - -/** - * @file IControl.h - * - * The definition of the IControl interface. - * - * This interface defines the public API of Rialto for control of Rialto, - * including the IPC connection and shared memory. - */ - -#include -#include - -#include "ControlCommon.h" -#include "IControlClient.h" - -namespace firebolt::rialto -{ -class IControl; - -/** - * @brief IControl factory class, returns a concrete implementation of IControl - */ -class IControlFactory -{ -public: - IControlFactory() = default; - virtual ~IControlFactory() = default; - - /** - * @brief Creates a IControlFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IControl factory method, returns a concrete implementation of IControl - * - * @retval the new IControl instance or null on error. - */ - virtual std::shared_ptr createControl() const = 0; -}; - -/** - * @brief The definition of the IControl interface. - * - * This interface defines the public API for control of the ipc and shared memory. - * - */ -class IControl -{ -public: - IControl() = default; - virtual ~IControl() = default; - - IControl(const IControl &) = delete; - IControl &operator=(const IControl &) = delete; - IControl(IControl &&) = delete; - IControl &operator=(IControl &&) = delete; - - /** - * @brief Register new IControlClient. This method will hold a shared_ptr - * to the client until the destruction of the IControl object. - * At destruction the client will be unregistered and the - * shared_ptr will be released. - * - * @param[in] client : Client object for callbacks - * @param[out] appState : Current application state - * - * @retval true on success, false otherwise. - */ - virtual bool registerClient(std::weak_ptr client, ApplicationState &appState) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_CONTROL_H_ diff --git a/middleware/rialto-client/media/public/include/IControlClient.h b/middleware/rialto-client/media/public/include/IControlClient.h deleted file mode 100644 index 9f9539706..000000000 --- a/middleware/rialto-client/media/public/include/IControlClient.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ -#define FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ - -/** - * @file IControlClient.h - * - * The definition of the IControlClient interface. - * - * This file comprises the definition of the IControlClient abstract - * class. This is the API by which a IControl implementation will - * pass notifications to its client. - */ - -#include "ControlCommon.h" - -namespace firebolt::rialto -{ -/** - * @brief The Rialto control client interface. - * - * This is The Rialto control client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the - * state of the rialto server. - */ -class IControlClient -{ -public: - /** - * @brief Virtual destructor - */ - virtual ~IControlClient() = default; - - /** - * @brief Notifies the client that rialto server reached new application state - * - * @param[in] state: The new application state. - */ - virtual void notifyApplicationState(ApplicationState state) = 0; -}; -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaKeys.h b/middleware/rialto-client/media/public/include/IMediaKeys.h deleted file mode 100644 index d8b8a01cd..000000000 --- a/middleware/rialto-client/media/public/include/IMediaKeys.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ -#define FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ - -/** - * @file IMediaKeys.h - * - * The definition of the IMediaKeys interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content. - */ - -#include -#include -#include - -#include "IMediaKeysClient.h" -#include "MediaCommon.h" - -namespace firebolt::rialto -{ -class IMediaKeys; - -/** - * @brief IMediaKeys factory class, returns a concrete implementation of IMediaKeys - */ -class IMediaKeysFactory -{ -public: - IMediaKeysFactory() = default; - virtual ~IMediaKeysFactory() = default; - - /** - * @brief Create a IMediaKeysFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMediaKeys factory method, returns a concrete implementation of IMediaKeys - * - * @param[in] keySystem : The key system for which to create a Media Keys instance. - * - * @retval the new media keys instance or null on error. - */ - virtual std::unique_ptr createMediaKeys(const std::string &keySystem) const = 0; -}; - -/** - * @brief The definition of the IMediaKeys interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content - * which should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaKeys -{ -public: - IMediaKeys() = default; - virtual ~IMediaKeys() = default; - - IMediaKeys(const IMediaKeys &) = delete; - IMediaKeys &operator=(const IMediaKeys &) = delete; - IMediaKeys(IMediaKeys &&) = delete; - IMediaKeys &operator=(IMediaKeys &&) = delete; - - /** - * @brief Selects the specified keyId for the key session. Netflix specific API. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] keyId : The key id to select. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) = 0; - - /** - * @brief Returns true if the Key Session object contains the specified key. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] keyId : The key id. - * - * @retval true if it contains the key. - */ - virtual bool containsKey(int32_t keySessionId, const std::vector &keyId) = 0; - - /** - * @brief Creates a session and returns the session id. - * - * This method creates a new session and returns the session id in - * the specified string. Any other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] sessionType : The session type. - * @param[in] client : Client object for callbacks - * @param[in] isLDL : Is this an LDL - * @param[out] keySessionId: The key session id - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, - bool isLDL, int32_t &keySessionId) = 0; - - /** - * @brief Generates a licence request. - * - * This method triggers generation of a licence request. If the session - * id does not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the - * session type or init data type is not supported a - * MediaKeyErrorStatus:NOT_SUPPORTED value is be returned. Any other - * errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] initDataType : The init data type. - * @param[in] initData : The init data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) = 0; - - /** - * @brief Loads an existing key session - * - * This method loads an existing key session. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the - * session type or init data type is not supported a - * MediaKeyErrorStatus:NOT_SUPPORTED value must be returned. If the session - * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any - * other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id for the session. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus loadSession(int32_t keySessionId) = 0; - - /** - * @brief Updates a key session's state. - * - * This method updates a session's state. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the session - * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any - * other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] responseData : The license response data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) = 0; - - /** - * @brief Set DRM Header for a key session - * - * This method updates a key session's DRM header. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned.If the session - * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any - * other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The session id for the session. - * @param[in] requestData : The request data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) = 0; - - /** - * @brief Closes a key session - * - * This method closes an open session. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other - * errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus closeKeySession(int32_t keySessionId) = 0; - - /** - * @brief Removes a key session - * - * This method removes an open session. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other - * errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus removeKeySession(int32_t keySessionId) = 0; - - /** - * @brief Delete the DRM store for the object's key system - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus deleteDrmStore() = 0; - - /** - * @brief Delete the key store for the object's key system - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus deleteKeyStore() = 0; - - /** - * @brief Gets a hash of the DRM store for the object's key system - * - * @param[out] drmStoreHash : the hash value - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) = 0; - - /** - * @brief Gets a hash of the Key store for the object's key system - * - * @param[out] keyStoreHash : the hash value - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) = 0; - - /** - * @brief Get the limit on the number of ldl key sessions for the object's key system - * - * @param[out] ldlLimit : the limit on the number of ldl key sessions. - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) = 0; - - /** - * @brief Get the last cdm specific DRM error code - * - * @param[in] keySessionId : The key session id. - * @param[out] errorCode : the error code. - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) = 0; - - /** - * @brief Get the DRM system time for the object's key system - * - * @param[out] drmTime : the DRM system time - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) = 0; - - /** - * @brief Get the internal CDM key session ID - * - * @param[in] keySessionId : The key session id for the session. - * @param[out] cdmKeySessionId : The internal CDM key session ID - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) = 0; - - /** - * @brief Releases a key session - * - * This method releases an open session. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other - * errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) = 0; - - /** - * @brief Get metrics for a DRM system - * - * @param[out] buffer : Buffer that can hold the metric data - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaKeysCapabilities.h b/middleware/rialto-client/media/public/include/IMediaKeysCapabilities.h deleted file mode 100644 index 4269bf754..000000000 --- a/middleware/rialto-client/media/public/include/IMediaKeysCapabilities.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ - -/** - * @file IMediaKeysCapabilities.h - * - * The definition of the IMediaKeysCapabilities interface. - */ - -#include -#include -#include - -namespace firebolt::rialto -{ -class IMediaKeysCapabilities; - -/** - * @brief IMediaKeysCapabilities factory class, for getting the IMediaKeysCapabilities singleton object. - */ -class IMediaKeysCapabilitiesFactory -{ -public: - IMediaKeysCapabilitiesFactory() = default; - virtual ~IMediaKeysCapabilitiesFactory() = default; - - /** - * @brief Gets the IMediaKeysCapabilitiesFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Gets the IMediaKeysCapabilities singleton object. - * - * @retval the MediaKeysCapabilities instance or null on error. - */ - virtual std::shared_ptr getMediaKeysCapabilities() const = 0; -}; - -/** - * @brief The definition of the IMediaKeysCapabilities interface. - * - * This interface defines the public API of Rialto for querying EME decryption capabilities. - * It should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaKeysCapabilities -{ -public: - IMediaKeysCapabilities() = default; - virtual ~IMediaKeysCapabilities() = default; - - IMediaKeysCapabilities(const IMediaKeysCapabilities &) = delete; - IMediaKeysCapabilities &operator=(const IMediaKeysCapabilities &) = delete; - IMediaKeysCapabilities(IMediaKeysCapabilities &&) = delete; - IMediaKeysCapabilities &operator=(IMediaKeysCapabilities &&) = delete; - - /** - * @brief Returns the EME key systems supported by Rialto - * - * @retval The supported key systems. - */ - virtual std::vector getSupportedKeySystems() = 0; - - /** - * @brief Indicates if the specified key system is supported. - * - * This method should be called to ensure that the specified key - * system is supported by Rialto. - * - * @param[in] keySystem : The key system. - * - * @retval true if supported. - */ - virtual bool supportsKeySystem(const std::string &keySystem) = 0; - - /** - * @brief Returns version of supported key system - * - * @param[in] keySystem : The key system. - * @param[out] version : The supported version of the key system - * - * @retval true if operation was successful - */ - virtual bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) = 0; - - /** - * @brief Gets support server certificate. - * - * Some DRMs (e.g. WideVine) use a system-wide server certificate. This method - * gets if system has support for that certificate. - * - * @param[in] keySystem : The key system. - * - * @retval true if server certificate is supported - */ - virtual bool isServerCertificateSupported(const std::string &keySystem) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaKeysClient.h b/middleware/rialto-client/media/public/include/IMediaKeysClient.h deleted file mode 100644 index fe2d89e83..000000000 --- a/middleware/rialto-client/media/public/include/IMediaKeysClient.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ -#define FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ - -/** - * @file IMediaKeysClient.h - * - * The definition of the IMediaKeysClient interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content. - * This is the Rialto media keys client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the state - * of a key session. - */ - -#include "MediaCommon.h" -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief The definition of the IMediaKeysClient interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content - * which should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaKeysClient -{ -public: - /** - * @brief The virtual destructor. - */ - virtual ~IMediaKeysClient() {} - - /** - * @brief Notification that a license is required - * - * @param[in] keySessionId : The idea of the session triggering the callback - * @param[in] licenseRequestMessage : The license request message blob - * @param[in] url : URL to which the message should be sent or empty string - */ - virtual void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, - const std::string &url) = 0; - - /** - * @brief Notification that a license renewal is required - * - * @param[in] keySessionId : The idea of the session triggering the callback - * @param[in] licenseRenewalMessage : The license renewal message blob - */ - virtual void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) = 0; - - /** - * @brief Notification that the status of one or more keys in the key session has changed - * - * @param[in] keySessionId : The idea of the session triggering the callback - * @param[in] keyStatuses : Vector of key ID/key status pairs - */ - virtual void onKeyStatusesChanged(int32_t keySessionId, const KeyStatusVector &keyStatuses) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaPipeline.h b/middleware/rialto-client/media/public/include/IMediaPipeline.h deleted file mode 100644 index 30de4ee70..000000000 --- a/middleware/rialto-client/media/public/include/IMediaPipeline.h +++ /dev/null @@ -1,1542 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ -#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ - -/** - * @file IMediaPipeline.h - * - * The definition of the IMediaPipeline interface. - * - * This interface defines the public API of Rialto for playback of AV content. - */ - -#include - -#include -#include -#include -#include -#include - -#include "IMediaPipelineClient.h" -#include "MediaCommon.h" - -namespace firebolt::rialto -{ -class IMediaPipeline; - -/** - * @brief IMediaPipeline factory class, returns a concrete implementation of IMediaPipeline - */ -class IMediaPipelineFactory -{ -public: - IMediaPipelineFactory() = default; - virtual ~IMediaPipelineFactory() = default; - - /** - * @brief Create a IMediaPipelineFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMediaPipeline factory method, returns a concrete implementation of IMediaPipeline - * - * @param[in] client : The Rialto media player client. - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session - * - * @retval the new backend instance or null on error. - */ - virtual std::unique_ptr createMediaPipeline(std::weak_ptr client, - const VideoRequirements &videoRequirements) const = 0; -}; - -/** - * @brief The definition of the IMediaPipeline interface. - * - * This interface defines the public API of Rialto for playback of AV content which - * should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaPipeline -{ -public: - IMediaPipeline() = default; - virtual ~IMediaPipeline() = default; - - IMediaPipeline(const IMediaPipeline &) = delete; - IMediaPipeline &operator=(const IMediaPipeline &) = delete; - IMediaPipeline(IMediaPipeline &&) = delete; - IMediaPipeline &operator=(IMediaPipeline &&) = delete; - - /** - * @brief A class that represents a source of media data. - */ - class MediaSource - { - public: - /** - * @brief Virtual destructor. - */ - virtual ~MediaSource() {} - - /** - * @brief Create a copy - */ - virtual std::unique_ptr copy() const = 0; - - /** - * @brief Return the source type. - */ - virtual MediaSourceType getType() const { return MediaSourceType::UNKNOWN; } - - /** - * @brief Return the MIME type. - */ - std::string getMimeType() const { return m_mimeType; } - - /** - * @brief Return if source has drm - */ - bool getHasDrm() const { return m_hasDrm; } - - /** - * @brief Return the source config type. - */ - SourceConfigType getConfigType() const { return m_configType; } - - /** - * @brief Return the source id. - */ - int32_t getId() const { return m_id; } - - /** - * @brief Set the source id. - */ - void setId(int32_t id) { m_id = id; } - - protected: - /** - * @brief Default constructor. - * - * @param[in] configType : The source config type. - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - */ - explicit MediaSource(SourceConfigType configType = SourceConfigType::UNKNOWN, - const std::string &mimeType = std::string(), bool hasDrm = true) - : m_id(0), m_configType(configType), m_mimeType(mimeType), m_hasDrm(hasDrm) - { - } - /** - * @brief The source id. Parameter will be set by a successful call to attachSource() - */ - int32_t m_id; - - /** - * @brief The source config type. - */ - SourceConfigType m_configType; - - /** - * @brief The MIME type. - */ - std::string m_mimeType; - - /** - * @brief Parameter to check if encrypted frames will be used for this source. - */ - bool m_hasDrm; - }; - - /** - * @brief A class that represents media source audio and video derived from MediaSource class, which represents the - * source of media data - */ - class MediaSourceAV : public MediaSource - { - public: - ~MediaSourceAV() {} - std::unique_ptr copy() const { return std::make_unique(*this); } - - /** - * @brief Gets the segment alignment - */ - SegmentAlignment getSegmentAlignment() const { return m_alignment; } - - /** - * @brief Gets the codec data - */ - const std::shared_ptr &getCodecData() const { return m_codecData; } - - /** - * @brief Gets the stream format - */ - StreamFormat getStreamFormat() const { return m_streamFormat; } - - protected: - /** - * @brief Default constructor. - * - * @param[in] configType : The source config type. - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - explicit MediaSourceAV(SourceConfigType configType = SourceConfigType::UNKNOWN, - const std::string &mimeType = std::string(), bool hasDrm = true, - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSource(configType, mimeType, hasDrm), m_alignment(alignment), m_streamFormat(streamFormat), - m_codecData(codecData) - { - } - /** - * @brief The alignment of media segment - */ - SegmentAlignment m_alignment; - - /** - * @brief The stream format - */ - StreamFormat m_streamFormat; - - /** - * @brief Additional data for decoder - */ - std::shared_ptr m_codecData; - }; - - /** - * @brief A class that represents media source audio derived from MediaSource class, which represents the source of - * media data - */ - - class MediaSourceAudio : public MediaSourceAV - { - public: - /** - * @brief Constructor for audio specific configuration. - * - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - * @param[in] audioConfig : The audio specific configuration. - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - MediaSourceAudio(const std::string &mimeType, bool hasDrm = true, const AudioConfig &audioConfig = AudioConfig(), - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSourceAV(SourceConfigType::AUDIO, mimeType, hasDrm, alignment, streamFormat, codecData), - m_audioConfig(audioConfig) - { - } - - ~MediaSourceAudio() {} - - MediaSourceType getType() const override { return MediaSourceType::AUDIO; } - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Gets the audio specific configuration - * - * @retval audio specific configuration - */ - const AudioConfig &getAudioConfig() const { return m_audioConfig; } - - protected: - /** - * @brief Variable that stores the audio specific configuration - */ - AudioConfig m_audioConfig; - }; - - /** - * @brief A class that represents media source video derived from MediaSource class, which represents the source of - * media data - */ - - class MediaSourceVideo : public MediaSourceAV - { - public: - /** - * @brief Constructor for video specific configuration. - * - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - * @param[in] width : The width of the video - * @param[in] height : The height of the video - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - MediaSourceVideo(const std::string &mimeType, bool hasDrm = true, - int32_t width = firebolt::rialto::kUndefinedSize, - int32_t height = firebolt::rialto::kUndefinedSize, - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSourceAV(SourceConfigType::VIDEO, mimeType, hasDrm, alignment, streamFormat, codecData), - m_width(width), m_height(height) - { - } - ~MediaSourceVideo() {} - - MediaSourceType getType() const override { return MediaSourceType::VIDEO; } - std::unique_ptr copy() const { return std::make_unique(*this); } - - /** - * @brief Gets the width of the video - * - * @retval width of the video - */ - int32_t getWidth() const { return m_width; } - - /** - * @brief Gets the height of the video - * - * @retval height of the video - */ - int32_t getHeight() const { return m_height; } - - protected: - /** - * @brief Constructor for video specific configuration. - * - * @param[in] sourceConfigType : The source config type - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - * @param[in] width : The width of the video - * @param[in] height : The height of the video - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - MediaSourceVideo(SourceConfigType sourceConfigType, const std::string &mimeType, bool hasDrm = true, - int32_t width = firebolt::rialto::kUndefinedSize, - int32_t height = firebolt::rialto::kUndefinedSize, - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSourceAV(sourceConfigType, mimeType, hasDrm, alignment, streamFormat, codecData), m_width(width), - m_height(height) - { - } - - private: - /** - * @brief The video width - */ - int m_width; - - /** - * @brief The video height - */ - int m_height; - }; - - /** - * @brief A class that represents media source video dolby vision derived from media source video data - */ - - class MediaSourceVideoDolbyVision : public MediaSourceVideo - { - public: - /** - * @brief Constructor for dolby vision specific configuration. - * - * @param[in] mimeType : The mime type string. - * @param[in] dolbyVisionProfile : The dolby vision profile - * @param[in] hasDrm : Information if source will use drm - * @param[in] width : The width of the video - * @param[in] height : The height of the video - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - MediaSourceVideoDolbyVision(const std::string &mimeType, int32_t dolbyVisionProfile, bool hasDrm = true, - int32_t width = firebolt::rialto::kUndefinedSize, - int32_t height = firebolt::rialto::kUndefinedSize, - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSourceVideo(SourceConfigType::VIDEO_DOLBY_VISION, mimeType, hasDrm, width, height, alignment, - streamFormat, codecData), - m_dolbyVisionProfile(dolbyVisionProfile) - { - } - ~MediaSourceVideoDolbyVision() {} - std::unique_ptr copy() const { return std::make_unique(*this); } - - /** - * @brief Gets the dolby vision profile - * - * @retval dolby vision profile - */ - uint32_t getDolbyVisionProfile() const { return m_dolbyVisionProfile; } - - protected: - /** - * @brief Variable that stores the Dolby Vision Profile - */ - uint32_t m_dolbyVisionProfile; - }; - - /** - * @brief A class that represents media source subtitle derived from media source video data - */ - class MediaSourceSubtitle : public MediaSource - { - public: - /** - * @brief Construct a new Media Source Subtitle object - * - * @param mimeType : The mime type string - * @param textTrackIdentifier : The text track identifier string - */ - MediaSourceSubtitle(const std::string &mimeType, const std::string &textTrackIdentifier) - : MediaSource(SourceConfigType::SUBTITLE, mimeType, false), m_textTrackIdentifier(textTrackIdentifier) - { - } - - ~MediaSourceSubtitle() {} - - MediaSourceType getType() const override { return MediaSourceType::SUBTITLE; } - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Get the Text Track Identifier object - * - * @return the text track identifier - */ - const std::string &getTextTrackIdentifier() const { return m_textTrackIdentifier; } - - protected: - /** - * @brief Variable that stores the text track identifier - */ - std::string m_textTrackIdentifier; - }; - - /** - * @brief A class that represents a media segment - */ - class MediaSegment - { - public: - /** - * @brief Default constructor. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] type : The source type. - * @param[in] timeStamp : The timestamp in nanoseconds. - * @param[in] duration : The duration in nanoseconds. - */ - MediaSegment(int32_t sourceId = 0, MediaSourceType type = MediaSourceType::UNKNOWN, int64_t timeStamp = 0, - int64_t duration = 0) - : m_sourceId(sourceId), m_type(type), m_data(nullptr), m_dataLength(0u), m_timeStamp(timeStamp), - m_duration(duration), m_encrypted(false), m_mediaKeySessionId(0), m_initWithLast15(0), - m_alignment(SegmentAlignment::UNDEFINED), m_cipherMode(CipherMode::UNKNOWN), m_crypt(0), m_skip(0), - m_encryptionPatternSet(false), m_displayOffset(std::nullopt) - { - } - - /** - * @brief Virtual destructor. - */ - virtual ~MediaSegment() {} - - /** - * @brief Makes a shallow copy of the segment - * - * @retval Shallow copy of the segment - */ - virtual std::unique_ptr copy() const { return std::make_unique(*this); } - - /** - * @brief Return the source id. - * - * @retval the source id. - */ - int32_t getId() const { return m_sourceId; } - - /** - * @brief The source type for the data. - * - * @retval the source type. - */ - MediaSourceType getType() const { return m_type; } - - /** - * @brief Returns a pointer to the data. - * - * @retval the data. - */ - const uint8_t *getData() const { return m_data; } - - /** - * @brief Returns a the data length. - * - * @retval the data. - */ - uint32_t getDataLength() const { return m_dataLength; } - - /** - * @brief Returns the time stamp. - * - * @retval the timestamp in nanoseconds. - */ - int64_t getTimeStamp() const { return m_timeStamp; } - - /** - * @brief Sets the time stamp (value in nanoseconds). - */ - void setTimeStamp(int64_t timeStamp) { m_timeStamp = timeStamp; } - - /** - * @brief Returns the duration. - * - * @retval the duration in nanoseconds. - */ - int64_t getDuration() const { return m_duration; } - - /** - * @brief Returns a pointer to the extra data. - * - * @retval the data. - */ - const std::vector &getExtraData() const { return m_extraData; } - - /** - * @brief Indicates that the data is encrypted. - * - * @retval true if the data is encrypted. - */ - bool isEncrypted() const { return m_encrypted; } - - /** - * @brief Returns the media key session id. Empty if unencrypted. - * - * @retval the media key session id. - */ - const int32_t getMediaKeySessionId() const { return m_mediaKeySessionId; } - - /** - * @brief Returns the key id. Empty if unencrypted. - * - * @retval the key id. - */ - const std::vector &getKeyId() const { return m_keyId; } - - /** - * @brief Returns the initialisation vector. Empty if unencrypted. - * - * @retval the initialisation vector. - */ - const std::vector &getInitVector() const { return m_initVector; } - - /** - * @brief Returns the sub samples. Empty if unencrypted. - * - * @retval the sub samples. - */ - const std::vector &getSubSamples() const { return m_subSamples; } - - /** - * @brief Returns the initWithLast15 value - * - * @retval the initWithLast15 value. - */ - const uint32_t getInitWithLast15() const { return m_initWithLast15; } - - /** - * @brief Returns the segment alignment - * - * @retval the segment alignment - */ - const SegmentAlignment getSegmentAlignment() const { return m_alignment; } - - /** - * @brief Gets the codec data - * - * @retval the codec data - */ - const std::shared_ptr &getCodecData() const { return m_codecData; } - - /** - * @brief Gets the cipher mode for common encryption - * - * @retval cipher mode uses for this sample - */ - const CipherMode &getCipherMode() const { return m_cipherMode; } - - /** - * @brief Gets the crypt & skip byte block for pattern encryption - * - * @param[out] crypt : Crypt byte block value - * @param[out] skip : Skip byte block value - * - * @retval if the encryption pattern has been set - */ - const bool getEncryptionPattern(uint32_t &crypt, uint32_t &skip) const - { - crypt = m_crypt; - skip = m_skip; - return m_encryptionPatternSet; - } - - /** - * @brief Gets the display offset - * - * @retval The offset in the source file of the beginning of the media segment. - */ - std::optional getDisplayOffset() const { return m_displayOffset; } - - protected: - /** - * @brief The source id. - */ - int32_t m_sourceId; - - /** - * @brief The source type. - */ - MediaSourceType m_type; - - /** - * @brief The data - */ - const uint8_t *m_data; - - /** - * @brief The data length - */ - uint32_t m_dataLength; - - /** - * @brief The time stamp. - */ - int64_t m_timeStamp; - - /** - * @brief The duration. - */ - int64_t m_duration; - - /** - * @brief Additional data for decoder - */ - std::shared_ptr m_codecData; - - /** - * @brief The data - */ - std::vector m_extraData; - - /** - * @brief Indicates the data is encrypted. - */ - bool m_encrypted; - - /** - * @brief Key session ID to use for decryption - only required for Netflix. - */ - int32_t m_mediaKeySessionId; - - /** - * @brief The encryption key id. - */ - std::vector m_keyId; - - /** - * @brief The encryption key initialisation vector. - */ - std::vector m_initVector; - - /** - * @brief The sub-sample pairs. - */ - std::vector m_subSamples; - - /** - * @brief Whether decryption context needs to be initialized with - * last 15 bytes. Currently this only applies to PlayReady DRM. - */ - uint32_t m_initWithLast15; - - /** - * @brief The alignment of media segment - */ - SegmentAlignment m_alignment; - - /** - * @brief Cipher mode of the sample. - */ - CipherMode m_cipherMode; - - /** - * @brief Crypt byte block value. - */ - uint32_t m_crypt; - - /** - * @brief Skip byte block value. - */ - uint32_t m_skip; - - /** - * @brief Whether the encryption pattern has been set. - */ - bool m_encryptionPatternSet; - - /** - * @brief The offset in the source file of the beginning of the media segment. - */ - std::optional m_displayOffset; - - public: - /** - * @brief Sets the segment data. - * - * @warning Note that the caller must guarantee that the buffer referenced by 'data' must remain - * valid until the corresponding call to haveData() has completed (at which point the data will - * have been copied out). - * - * @note This is for performance reasons to avoid multiple copies of AV data. A raw pointer is - * used for the same reason since most runtimes will expose a raw pointer to the data. - * - * @retval true on success. - */ - bool setData(uint32_t dataLength, const uint8_t *data) - { - m_dataLength = dataLength; - m_data = data; - return true; - } - - /** - * @brief Sets the extra data. - * - * @retval true on success. - */ - bool setExtraData(const std::vector &extraData) - { - m_extraData = extraData; - return true; - } - - /** - * @brief Sets the segment alignment - * - * @param[in] alignment : The new segment alignment - */ - void setSegmentAlignment(const SegmentAlignment &alignment) { m_alignment = alignment; } - - /** - * @brief Sets new codec_data for the segment. - * - * @note Should only be called if the codec data changes - * - * @param[in] codecData The updated codec data for the source - */ - void setCodecData(const std::shared_ptr &codecData) { m_codecData = codecData; } - - /** - * @brief Sets the encrypted flag. - * - * @param[in] encrypted : Set true to indicated encrypted data. - */ - void setEncrypted(bool encrypted) { m_encrypted = encrypted; } - - /** - * @brief Sets the media key session id. - * - * @param[in] mksId : the media key session id. - */ - void setMediaKeySessionId(int32_t mksId) { m_mediaKeySessionId = mksId; } - - /** - * @brief Sets the key id. - * - * @param[in] keyId : The key id. - */ - void setKeyId(const std::vector &keyId) { m_keyId = keyId; } - - /** - * @brief Sets the encryption initialisation vector. - * - * @param[in] initVector : The initialisation vector. - */ - void setInitVector(const std::vector &initVector) { m_initVector = initVector; } - - /** - * @brief Adds a sub-sample pair to the sub samples. - * - * @param[in] numClearBytes : The number of clear bytes. - * @param[in] numEncryptedBytes : The number of encrypted bytes. - */ - void addSubSample(size_t numClearBytes, size_t numEncryptedBytes) - { - m_subSamples.emplace_back(SubSamplePair{numClearBytes, numEncryptedBytes}); - } - - /** - * @brief Sets initWithLast15 value - * - * @param[in] initWithLast15 : initWithLast15 value - */ - void setInitWithLast15(uint32_t initWithLast15) { m_initWithLast15 = initWithLast15; } - - /** - * @brief Sets the cipher mode for common encryption. - * - * @param[in] cipherMode : Specifies cipher mode uses for this sample. - */ - void setCipherMode(CipherMode cipherMode) { m_cipherMode = cipherMode; } - - /** - * @brief Sets the crypt & skip byte block for pattern encryption - * - * @param[in] crypt : Crypt byte block value - * @param[in] skip : Skip byte block value - */ - void setEncryptionPattern(uint32_t crypt, uint32_t skip) - { - m_crypt = crypt; - m_skip = skip; - m_encryptionPatternSet = true; - } - - /** - * @brief Sets the display offset - * - * @param[in] displayOffset : The offset in the source file of the beginning of the media segment. - */ - void setDisplayOffset(uint64_t displayOffset) { m_displayOffset = displayOffset; } - - /** - * @brief Copies the data from other to this. - */ - void copy(const MediaSegment &other); - }; - - /** - * @brief A class that represents media source audio data - */ - class MediaSegmentAudio : public MediaSegment - { - public: - /** - * @brief Default constructor. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] timeStamp : The timestamp in nanoseconds. - * @param[in] duration : The duration in nanoseconds. - * @param[in] sampleRate : The sample rate in samples per second. - * @param[in] numberOfChannels : The number of audio channels. - * @param[in] clippingStart : The amount of audio to clip from start of buffer - * @param[in] clippingEnd : The amount of audio to clip from end of buffer - */ - MediaSegmentAudio(int32_t sourceId = 0, int64_t timeStamp = 0, int64_t duration = 0, int32_t sampleRate = 0, - int32_t numberOfChannels = 0, uint64_t clippingStart = 0, uint64_t clippingEnd = 0) - : MediaSegment(sourceId, MediaSourceType::AUDIO, timeStamp, duration), m_sampleRate(sampleRate), - m_numberOfChannels(numberOfChannels), m_clippingStart(clippingStart), m_clippingEnd(clippingEnd) - { - } - - /** - * @brief Copy constructor. - */ - MediaSegmentAudio(const MediaSegmentAudio &other) : MediaSegment(other) - { - m_sampleRate = other.m_sampleRate; - m_numberOfChannels = other.m_numberOfChannels; - } - - /** - * @brief Makes a shallow copy of the segment - * - * @retval Shallow copy of the segment - */ - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Return the audio sample rate. - * - * @retval the sample rate in samples per second. - */ - int32_t getSampleRate() const { return m_sampleRate; } - - /** - * @brief Return the number of audio channels. - * - * @retval the number of channels. - */ - int32_t getNumberOfChannels() const { return m_numberOfChannels; } - - /** - * @brief Return the amount of audio to clip from start of buffer - * - * @retval the amount of audio to clip from start of buffer - */ - uint64_t getClippingStart() const { return m_clippingStart; } - - /** - * @brief Return the amount of audio to clip from end of buffer - * - * @retval the amount of audio to clip from end of buffer - */ - uint64_t getClippingEnd() const { return m_clippingEnd; } - - /** - * @brief Copy assignment operator. - * - * @retval the copy. - */ - MediaSegmentAudio &operator=(const MediaSegmentAudio &other) - { - copy(other); - return *this; - } - - protected: - /** - * @brief Copies the data from other to this. - */ - void copy(const MediaSegmentAudio &other); - - /** - * @brief The audio sample rate. - */ - int32_t m_sampleRate; - - /** - * @brief The number of audio channels. - */ - int32_t m_numberOfChannels; - - /** - * @brief The amount of audio to clip from start of buffer - */ - uint64_t m_clippingStart; - - /** - * @brief The amount of audio to clip from end of buffer - */ - uint64_t m_clippingEnd; - }; - - /** - * @brief A class that represents media source video data - */ - class MediaSegmentVideo : public MediaSegment - { - public: - /** - * @brief Default constructor. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] timeStamp : The timestamp in nanoseconds. - * @param[in] duration : The duration in nanoseconds. - * @param[in] width : The video width in pixels. - * @param[in] height : The video height in pixels. - * @param[in] frameRate : The fractional framerate of the sample. - */ - MediaSegmentVideo(int32_t sourceId = 0, int64_t timeStamp = 0, int64_t duration = 0, - int32_t width = firebolt::rialto::kUndefinedSize, - int32_t height = firebolt::rialto::kUndefinedSize, - firebolt::rialto::Fraction frameRate = {firebolt::rialto::kUndefinedSize, - firebolt::rialto::kUndefinedSize}) - : MediaSegment(sourceId, MediaSourceType::VIDEO, timeStamp, duration), m_width(width), m_height(height), - m_frameRate(frameRate) - { - } - - /** - * @brief Copy constructor. - */ - MediaSegmentVideo(const MediaSegmentVideo &other) : MediaSegment(other) - { - m_width = other.m_width; - m_height = other.m_height; - m_frameRate = other.m_frameRate; - } - - /** - * @brief Makes a shallow copy of the segment - * - * @retval Shallow copy of the segment - */ - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Return the video width. - * - * @retval the video width in pixels. - */ - int32_t getWidth() const { return m_width; } - - /** - * @brief Return the video height. - * - * @retval the video height in pixels. - */ - int32_t getHeight() const { return m_height; } - - /** - * @brief Return the video frameRate. - * - * @retval the fractional framerate of the sample. - */ - firebolt::rialto::Fraction getFrameRate() const { return m_frameRate; } - - /** - * @brief Copy assignment operator. - * - * @retval the copy. - */ - MediaSegmentVideo &operator=(const MediaSegmentVideo &other) - { - copy(other); - return *this; - } - - protected: - /** - * @brief Copies the data from other to this. - */ - void copy(const MediaSegmentVideo &other); - - /** - * @brief The video width in pixels. - */ - int32_t m_width; - - /** - * @brief The video height in pixels. - */ - int32_t m_height; - - /** - * @brief The fractional framerate of the sample. - */ - firebolt::rialto::Fraction m_frameRate; - }; - - /** - * @brief A vector that contains one or more media segments. - */ - typedef std::vector> MediaSegmentVector; - - /** - * @brief Returns the media player client. - * - * @retval The media player client. - */ - virtual std::weak_ptr getClient() = 0; - - /** - * @brief Loads the media and backend delegate. - * - * This method loads the media and backend appropriate for the media. - * The media type determines the backend delegate to use to play back - * the media. The MIME type confirms the type and CODECs for the media. - * The URL will comprise the media URL for types MediaType::URL and - * MediaType::HLS. For MediaType::MSE the URL will comprise a blob URL - * as the data is loaded by the browser. - * - * @param[in] type : The media type. - * @param[in] mimeType : The MIME type. - * @param[in] url : The URL. - */ - virtual bool load(MediaType type, const std::string &mimeType, const std::string &url) = 0; - - /** - * @brief Attaches a source stream to the backend. - * - * This method is called by Rialto Client to attach a media source stream to - * the backend. It is only called when Media Source Extensions are - * being used. I.e. if the MediaType value in load() is - * MediaType::MSE. - * - * @param[in] source : The source. - * - * @retval true on success. - */ - virtual bool attachSource(const std::unique_ptr &source) = 0; - - /** - * @brief Unattaches a source. - * - * This method is called by Rialto Client to detach a media source stream from - * the backend. It is only called when Media Source Extensions are - * being used. I.e. if the MediaType value in load() is - * MediaType::MSE. - * - * @param[in] id : The source id. Value should be set to the MediaSource.id returned after attachSource() - * - * @retval true on success. - */ - virtual bool removeSource(int32_t id) = 0; - - /** - * @brief Notifies Rialto Server that all sources were attached - * - * This method is called by Rialto Client to notify the RialtoServer - * that all sources were attached. - * - * Must be called, otherwise streaming cannot commence. - * Can be called only once. - * - * @retval true on success. - */ - virtual bool allSourcesAttached() = 0; - - /** - * @brief Starts playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request playback and then return. - * - * Once the backend is successfully playing it should notify the - * media player client of playback state - * IMediaPipelineClient::PlaybackState::PLAYING. - * - * @retval true on success. - */ - virtual bool play() = 0; - - /** - * @brief Pauses playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the playback pause and then return. - * - * Once the backend is successfully playing it should notify the - * media player client of playback state - *IMediaPipelineClient::PlaybackState::PAUSED. - * - * @retval true on success. - */ - virtual bool pause() = 0; - - /** - * @brief Stops playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the playback stop and then return. - * - * Once the backend is successfully stopped it should notify the - * media player client of playback state - * IMediaPipelineClient::PlaybackState::STOPPED. - * - * @retval true on success. - */ - virtual bool stop() = 0; - - /** - * @brief Set the playback rate - * - * This method sets the playback rate. The supported playback rates - * are dependent upon the backend playback method. - * - * @param[in] rate : The playback rate. - * - * @retval true on success. - */ - virtual bool setPlaybackRate(double rate) = 0; - - /** - * @brief Set the playback position in nanoseconds. - * - * If playback has not started this method sets the start position - * for playback. If playback has started this method performs a seek. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the new playback position and then return. - * - * Once the backend is seeking it should notify the media player - * client of playback state - * IMediaPipelineClient::PlaybackState::SEEKING. When seeking has - * completed the state IMediaPipelineClient::PlaybackState::SEEK_DONE - * should be notified followed by - * IMediaPipelineClient::PlaybackState::PLAYING. - * - * @param[in] position : The playback position in nanoseconds. - * - * @retval true on success. - */ - virtual bool setPosition(int64_t position) = 0; - - /** - * @brief Get the playback position in nanoseconds. - * - * This method is sychronous, it returns current playback position - * - * @param[out] position : The playback position in nanoseconds - * - * @retval true on success. - */ - virtual bool getPosition(int64_t &position) = 0; - - /** - * @brief Get stats for this source. - * - * This method is sychronous, it returns dropped frames and rendered frames - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[out] renderedFrames : The number of rendered frames - * @param[out] droppedFrames : The number of dropped frames - * - * @retval true on success. - */ - virtual bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; - - /** - * @brief Sets the "Immediate Output" property for this source. - * - * This method is asynchronous, it will set the "Immediate Output" property - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] immediateOutput : Set immediate output mode on the sink - * - * @retval true on success. - */ - virtual bool setImmediateOutput(int32_t sourceId, bool immediateOutput) = 0; - - /** - * @brief Gets the "Immediate Output" property for this source. - * - * This method is sychronous, it gets the "Immediate Output" property - * - * @param[in] sourceId : The source id. Value should be get to the MediaSource.id returned after attachSource() - * @param[out] immediateOutput : Get immediate output mode on the sink - * - * @retval true on success. - */ - virtual bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) = 0; - - /** - * @brief Sets the coordinates of where the video should be displayed. - * - * @param[in] x : The x position in pixels. - * @param[in] y : The y position in pixels. - * @param[in] width : The width in pixels. - * @param[in] height : The height in pixels. - * - * @retval true on success. - */ - virtual bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; - - /** - * @brief Returns data requested using notifyNeedMediaData(). - * - * This method is called as a result of calling notifyNeedMediaData() on - * the media client. The status value indicates the success or - * otherwise of the request. The client must first call addSegment() for - * for each media segment to be sent. - * A status of MediaSourceStatus::OK indicates success and there will - * be data within the data vector. A status of MediaSourceStatus::EOS - * indicates success but the end of the stream was reached. Again - * there will be data in the vector. A status of - * MediaSourceStatus::ERROR indicates an error occurred and no data - * was returned. - * - * - * @param[in] status : The status - * @param[in] needDataRequestId : Need data request id - */ - virtual bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) = 0; - - /** - * @brief Adds a single segment to Rialto in response to notifyNeedData() - * - * This method is should be called by the client as a result of a notifyNeedData() - * notification. The client should call this API for each segment to be sent in - * response to the notification and then call haveData() when all segments - * have been 'added'. - * - * If the return code is NO_SPACE the segment has not been accepted but this is - * not an error. The client should retain the segment until the next notifyNeedData() - * is received for the source and immediately call haveData() to trigger Rialto - * to start processing the segments already added. - * - * @param[in] needDataRequestId : The status - * @param[in] mediaSegment : The data returned. - * - * @retval status of adding segment - */ - virtual AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) = 0; - - /** - * @brief Requests to render a prerolled frame - */ - virtual bool renderFrame() = 0; - - /** - * @brief Set the target volume level and transition duration with easing type. - * By default volume is set immediately if duration and type are not set. - * - * @param[in] targetVolume : Target volume level (0.0 - 1.0) - * @param[in] volumeDuration : (Optional) Duration of the volume transition in milliseconds - * @param[in] easeType : (Optional) Easing type for the volume transition - * - * @retval true on success, false otherwise. - */ - virtual bool setVolume(double targetVolume, uint32_t volumeDuration = 0, - EaseType easeType = EaseType::EASE_LINEAR) = 0; - - /** - * @brief Get current audio level. Fetches the current volume level for the pipeline. - * - * @param[out] currentVolume : Current volume level (range 0.0 - 1.0) - * - * @retval true on success, false otherwise. - */ - virtual bool getVolume(double ¤tVolume) = 0; - - /** - * @brief Set mute status of pipeline. - * - * Change mute status of media source - * - * @param[in] sourceId Source, which mute status should be changed - * @param[in] mute Desired mute state, true=muted, false=not muted - * - * @retval true on success false otherwise - */ - virtual bool setMute(int32_t sourceId, bool mute) = 0; - - /** - * @brief Get current mute status of the media source - * - * @param[in] sourceId Source, which mute status should be fetched - * @param[out] mute Current mute state - * - * @retval true on success false otherwise - */ - virtual bool getMute(int32_t sourceId, bool &mute) = 0; - - /** - * @brief Change Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - virtual bool setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; - - /** - * @brief Get Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; - - /** - * @brief Set low latency property on the audio sink. Default false. - * - * For use with gaming (no audio decoding, no a/v sync). - * - * @param[in] lowLatency : The low latency value to set. - * - * @retval true on success false otherwise - */ - virtual bool setLowLatency(bool lowLatency) = 0; - - /** - * @brief Set sync property on the audio sink. Default false. - * - * Syncs the stream on the clock. - * - * @param[in] sync : The sync value to set. - * - * @retval true on success false otherwise - */ - virtual bool setSync(bool sync) = 0; - - /** - * @brief Get sync property on the audio sink. - * - * @param[out] sync : Current sync value. - * - * @retval true on success false otherwise - */ - virtual bool getSync(bool &sync) = 0; - - /** - * @brief Set sync off property on the audio decoder. Default false. - * - * Turn on free running audio. Must be set before pipeline is PLAYING state. - * - * @param[in] syncOff : The sync off value to set. - * - * @retval true on success false otherwise - */ - virtual bool setSyncOff(bool syncOff) = 0; - - /** - * @brief Set stream sync mode property on the audio decoder or video filter. Default 0. - * - * 1 - Frame to decode frame will immediately proceed next frame sync. - * 0 - Frame decoded with no frame sync. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] streamSyncMode : The stream sync mode value to set. - * - * @retval true on success false otherwise - */ - virtual bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) = 0; - - /** - * @brief Get stream sync mode property on the audio decoder. - * - * @param[out] streamSyncMode : Current stream sync mode value. - * - * @retval true on success false otherwise - */ - virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; - - /** - * @brief Flushes a source. - * - * This method is called by Rialto Client to flush out all queued data for a media source stream. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] resetTime : True if time should be reset - * @param[out] async : True if flushed source is asynchronous (will preroll after flush) - * - * @retval true on success. - */ - virtual bool flush(int32_t sourceId, bool resetTime, bool &async) = 0; - - /** - * @brief Set the source position in nanoseconds. - * - * This method sets the start position for a source. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] position : The position in nanoseconds. - * @param[in] resetTime : True if time should be reset - * @param[in] appliedRate : The applied rate after seek. Default value is 1.0. - * @param[in] stopPosition : The position of last pushed buffer - * - * @retval true on success. - */ - virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, - uint64_t stopPosition = kUndefinedPosition) = 0; - - /** - * @brief Set the subtitle offset in nanoseconds. - * - * This method sets the subtitle offset for a subtitle source. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] position : The offset position in nanoseconds. - * - * @retval true on success. - */ - virtual bool setSubtitleOffset(int32_t sourceId, int64_t position) = 0; - - /** - * @brief Process audio gap - * - * This method handles audio gap in order to avoid audio pops during transitions. - * - * @param[in] position : Audio pts fade position - * @param[in] duration : Audio pts fade duration - * @param[in] discontinuityGap : Audio discontinuity gap - * @param[in] audioAac : True if audio codec is AAC - * - * @retval true on success. - */ - virtual bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; - - /** - * @brief Set buffering limit - * - * This method enables/disables limit buffering and sets millisecond threshold used. - * Use kInvalidLimitBuffering to disable limit buffering - * - * @param[in] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - virtual bool setBufferingLimit(uint32_t limitBufferingMs) = 0; - - /** - * @brief Get buffering limit - * - * This method returns current value of buffering limit in milliseconds - * Method will return kInvalidLimitBuffering limit buffering is disabled - * - * @param[out] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; - - /** - * @brief Enables/disables the buffering option - * - * This method enables the buffering option so that BUFFERING messages are - * emitted based on low-/high-percent thresholds. - * - * @param[in] useBuffering : true if buffering option enabled. - * - * @retval true on success. - */ - virtual bool setUseBuffering(bool useBuffering) = 0; - - /** - * @brief Checks, if buffering is enabled - * - * This method returns true, if buffering is enabled - * - * @param[out] useBuffering : true if buffering option is enabled. - * - * @retval true on success. - */ - virtual bool getUseBuffering(bool &useBuffering) = 0; - - /** - * @brief Switches a source stream. - * - * This method is called to switch a media source stream. - * - * @param[in] source : The source. - * - * @retval true on success. - */ - virtual bool switchSource(const std::unique_ptr &source) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaPipelineCapabilities.h b/middleware/rialto-client/media/public/include/IMediaPipelineCapabilities.h deleted file mode 100644 index f63a816c4..000000000 --- a/middleware/rialto-client/media/public/include/IMediaPipelineCapabilities.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ - -/** - * @file IMediaPipelineCapabilities.h - * - * The definition of the IMediaPipelineCapabilities interface. - */ - -#include "MediaCommon.h" -#include -#include -#include - -namespace firebolt::rialto -{ -class IMediaPipelineCapabilities; - -/** - * @brief IMediaPipelineCapabilities factory class, for getting the IMediaPipelineCapabilities object. - */ -class IMediaPipelineCapabilitiesFactory -{ -public: - IMediaPipelineCapabilitiesFactory() = default; - virtual ~IMediaPipelineCapabilitiesFactory() = default; - - /** - * @brief Gets the IMediaPipelineCapabilitiesFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates the IMediaPipelineCapabilities object. - * - * @retval the MediaPipelineCapabilities instance or null on error. - */ - virtual std::unique_ptr createMediaPipelineCapabilities() const = 0; -}; - -/** - * @brief The definition of the IMediaPipelineCapabilities interface. - * - * This interface defines the public API of Rialto for querying EME decryption capabilities. - * It should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaPipelineCapabilities -{ -public: - IMediaPipelineCapabilities() = default; - virtual ~IMediaPipelineCapabilities() = default; - - IMediaPipelineCapabilities(const IMediaPipelineCapabilities &) = delete; - IMediaPipelineCapabilities &operator=(const IMediaPipelineCapabilities &) = delete; - IMediaPipelineCapabilities(IMediaPipelineCapabilities &&) = delete; - IMediaPipelineCapabilities &operator=(IMediaPipelineCapabilities &&) = delete; - - /** - * @brief Returns the MSE mime types supported by Rialto for \a sourceType - * - * @param[in] sourceType : source type - * - * @retval The supported mime types. - */ - virtual std::vector getSupportedMimeTypes(MediaSourceType sourceType) = 0; - - /** - * @brief Indicates if the specified mime type is supported. - * - * This method should be called to ensure that the specified mime - * type is supported by Rialto. - * - * @param[in] mimeType : The mime type to check. - * - * @retval true if supported. - */ - virtual bool isMimeTypeSupported(const std::string &mimeType) = 0; - - /** - * @brief Check sinks and decoders for supported properties - * - * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched - * @param[in] propertyNames : A vector of property names to look for - * - * @retval Returns the subset of propertyNames that are supported by the mediaType - */ - virtual std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) = 0; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - virtual bool isVideoMaster(bool &isVideoMaster) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/public/include/IMediaPipelineClient.h b/middleware/rialto-client/media/public/include/IMediaPipelineClient.h deleted file mode 100644 index ad66f152a..000000000 --- a/middleware/rialto-client/media/public/include/IMediaPipelineClient.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ -#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ - -#include -#include -#include -#include - -/** - * @file IMediaPipelineClient.h - * - * The definition of the IMediaPipelineClient interface. - * - * This file comprises the definition of the IMediaPipelineClient abstract - * class. This is the API by which a IMediaPipeline implementation will - * pass notifications to its client. - */ - -namespace firebolt::rialto -{ -/* Values representing custom duration values, used by IMediaPipelineClient::notifyDuration() method*/ -/** - * @brief Stream duration is unknown or undefined - * - */ -constexpr int64_t kDurationUnknown{-1}; -/** - * @brief Stream duration is unending or live - */ -constexpr int64_t kDurationUnending{-2}; - -/** - * @brief The Rialto media player client interface. - * - * This is The Rialto media player client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the - * state of the player or that provides data for media playback. - */ -class IMediaPipelineClient -{ -public: - /** - * @brief Virtual destructor - */ - virtual ~IMediaPipelineClient() {} - - /** - * @brief Notifies the client of the total duration of the media. - * - * This method notifies the client of the total duration of the - * media in nanoseconds. If this is unknown or undefined then a value - * of kDurationUnknown. If the stream is unending, for example - * live, then a value of kDurationUnending should be used. - * - * @param[in] duration : The duration of the media in seconds. - */ - virtual void notifyDuration(int64_t duration) = 0; - - /** - * @brief Notifies the client of the current playback position. - * - * This method notifies the client of the current playback position - * in nanoseconds. - * - * When playing this should be called often enough to provide - * sufficient granularity of position reporting. Typically this will - * be every 0.25s. - * - * @param[in] position : The playback position in nanoseconds. - */ - virtual void notifyPosition(int64_t position) = 0; - - /** - * @brief Notifies the client of the native size of the video and - the pixel aspect ratio. - * - * This method should be called one or more times to reporting the - * native video size. If the video size changes the method should be - * called with the updated size or aspect ratio. - * - * @param[in] width : The width in pixels. - * @param[in] height : The height in pixels. - * @param[in] aspect : The pixel aspect ratio. - */ - virtual void notifyNativeSize(uint32_t width, uint32_t height, double aspect = 1.0) = 0; - - /** - * @brief Notifies the client of the network state. - * - * The network state reflects the state of the network. For backend - * streaming, this is important as the backend uses the network to obtain the media data directly. - * - * For streaming that uses the browser to obtain data, say Media Source - * Extensions playback, only the states NetworkState::IDLE, - * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be - * indicated by the backend. - * - * @param[in] state : The new network state. - */ - virtual void notifyNetworkState(NetworkState state) = 0; - - /** - * @brief Notifies the client of the playback state. - * - * The player will start IDLE. Once play() has been called the player - * will be PLAYING, or once pause() has been called the player will be - * PAUSED. A seek() request will result in SEEKING and once the seek - * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED - * state will be issued after a stop() request. - * - * @param[in] state : The new playback state. - */ - virtual void notifyPlaybackState(PlaybackState state) = 0; - - /** - * @brief Notifies the client that video data is available - * - * @param[in] hasData: true if video data is available. - */ - virtual void notifyVideoData(bool hasData) = 0; - - /** - * @brief Notifies the client that audio data is available - * - * @param[in] hasData: true if audio data is available. - */ - virtual void notifyAudioData(bool hasData) = 0; - - /** - * @brief Notifies the client that we need media data. - * - * This method notifies the client that we need media data from the - * client. This is only used when Media Source Extensions are used. - * In that case media is read by JavaScript and buffered by the - * browser before being passed to this API for decoding. - * - * You cannot request data if a data request is currently pending. - * - * The frames the client sends should meet the criteria: - * numFramesSent <= frameCount - * numBytesSent <= maxMediaBytes - * - * @param[in] sourceId : The source to read data from. - * @param[in] frameCount : The number of frames to read. - * @param[in] needDataRequestId : Need data request id. - * @param[in] shmInfo : Information for populating the shared memory (null if not applicable to the client). - */ - virtual void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, - const std::shared_ptr &shmInfo) = 0; - - /** - * @brief Notifies the client to cancel any outstand need request. - * - * This method notifies the client to cancel any data request made using - * notifyNeedMediaData(). It is not an error to cancel a request for data - * when one is not pending. - * - * @param[in] sourceId : The source id to cancel the request for. - */ - virtual void notifyCancelNeedMediaData(int32_t sourceId) = 0; - - /** - * @brief Notifies the client of a Quality Of Service update from the Player. - * - * Notification shall be sent whenever a video/audio buffer drops a frame/sample. - * - * @param[in] sourceId : The id of the source that produced the Qos. - * @param[in] qosInfo : The information provided in the update. - */ - virtual void notifyQos(int32_t sourceId, const QosInfo &qosInfo) = 0; - - /** - * @brief Notifies the client that buffer underflow occurred. - * - * Notification shall be sent whenever a video/audio buffer underflow occurs - * - * @param[in] sourceId : The id of the source that produced the buffer underflow - */ - virtual void notifyBufferUnderflow(int32_t sourceId) = 0; - - /** - * @brief Notifies the client that a non-fatal error has occurred in the player. - * - * PlaybackState remains unchanged when an error occurs. - * - * @param[in] sourceId : The id of the source that produced the error. - * @param[in] error : The type of error that occured. - */ - virtual void notifyPlaybackError(int32_t sourceId, PlaybackError error) = 0; - - /** - * @brief Notifies the client that the source has been flushed. - * - * Notification shall be sent whenever a flush procedure is finished. - * - * @param[in] sourceId : The id of the source that has been flushed. - */ - virtual void notifySourceFlushed(int32_t sourceId) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ diff --git a/middleware/rialto-client/media/public/include/IWebAudioPlayer.h b/middleware/rialto-client/media/public/include/IWebAudioPlayer.h deleted file mode 100644 index d29d6677a..000000000 --- a/middleware/rialto-client/media/public/include/IWebAudioPlayer.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ -#define FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ - -/** - * @file IWebAudioPlayer.h - * - * The definition of the IWebAudioPlayer interface. - * - * This interface defines the public API of Rialto for mixing PCM audio with - * current audio output. - */ - -#include -#include -#include - -#include "IWebAudioPlayerClient.h" -#include "MediaCommon.h" - -namespace firebolt::rialto -{ -class IWebAudioPlayer; - -/** - * @brief IWebAudioPlayer factory class, returns a concrete implementation of IWebAudioPlayer - */ -class IWebAudioPlayerFactory -{ -public: - IWebAudioPlayerFactory() = default; - virtual ~IWebAudioPlayerFactory() = default; - - /** - * @brief Create a IWebAudioPlayerFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IWebAudioPlayer factory method, returns a concrete implementation of - * IWebAudioPlayer for playback of audio. - * - * @param[in] client: The Web Audio Player client - * @param[in] audioMimeType: The audio encoding format, currently only "audio/x-raw" (PCM) - * @param[in] priority: Priority value for this pipeline. - * @param[in] config: Additional type dependent configuration data or nullptr - * - * Some platforms have limited numbers of audio playbacks that can be mixed. The client application - * should therefore assign a priority to each audio player it creates, starting with priority 1 for - * the most important, priority 2 for the next etc. If a platform supports 'n' players, then any - * player with priority>n will appear to function normally by but the audio data will be silently - * discarded. - * - * @retval the new Web Audio Player instance or null on error. - */ - virtual std::unique_ptr createWebAudioPlayer(std::weak_ptr client, - const std::string &audioMimeType, - const uint32_t priority, - std::weak_ptr config) const = 0; -}; - -/** - * @brief The definition of the IWebAudioPlayer interface. - * - * This interface defines the public API of Rialto for mixing PCM audio with - * current audio output. It should be implemented by both Rialto Client & - * Rialto Server. - */ -class IWebAudioPlayer -{ -public: - IWebAudioPlayer() = default; - virtual ~IWebAudioPlayer() = default; - - IWebAudioPlayer(const IWebAudioPlayer &) = delete; - IWebAudioPlayer &operator=(const IWebAudioPlayer &) = delete; - IWebAudioPlayer(IWebAudioPlayer &&) = delete; - IWebAudioPlayer &operator=(IWebAudioPlayer &&) = delete; - - /** - * @brief Play the web audio. - * - * Sets the player to the PLAYING state (it is IDLE when created). - * - * @retval true on success. - */ - virtual bool play() = 0; - - /** - * @brief Pause the web audio. - * - * Sets the player to the PAUSED state (it is IDLE when created). - * - * @retval true on success. - */ - virtual bool pause() = 0; - - /** - * @brief Notify EOS. - * - * Notifies the player that no further frames will be provided. When - * all buffered frames are played the player will enter the EOS state. - * - * @retval true on success. - */ - virtual bool setEos() = 0; - - /** - * @brief Get the available frames. - * - * Gets the available buffer space for sending more frames. Client should not - * write more than the number of frames returned by this API. - * - * webAudioShmInfo is not required by the client application and can be ignored. - * - * @param[out] availableFrames : Number of frames available to be written. - * @param[out] webAudioShmInfo : Location in shm to write the data (Server only). - * - * @retval true on success. - */ - virtual bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) = 0; - - /** - * @brief Get the delay frames. - * - * Gets the frame delay of the playback from Rialto. Frame delay is the number - * of frames left to play by the server. - * - * @param[out] delayFrames : Number of frames to be played. - * - * @retval true on success. - */ - virtual bool getBufferDelay(uint32_t &delayFrames) = 0; - - /** - * @brief Write audio frames - * - * Sends a buffer of audio data for playback - * - * @param[in] numberOfFrames : Number of frames of audio in 'data'. - * @param[in] data : Pointer to the data, byte length = numberOfFrames*sampleSize - * - * @retval true on success. - */ - virtual bool writeBuffer(const uint32_t numberOfFrames, void *data) = 0; - - /** - * @brief Get device information. - * - * Gets information for the web audio playback. - * This information is used to determine the preferred buffer size to commit, - * the maximum buffer size an application can commit and whether buffers can - * be committed before a Play request. - * - * @param[out] preferredFrames : preferred number of frames to be commited. - * @param[out] maximumFrames : Maximum number of frames that can be commited. - * @param[out] supportDeferredPlay : Whether defered play is supported. - * - * @retval true on success. - */ - virtual bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) = 0; - - /** - * - * @brief Set level and transition of audio attenuation - * - * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume) - * - * @param[in] volume : Target volume level (0.0 - 1.0) - * - * @retval true on success false otherwise - */ - virtual bool setVolume(double volume) = 0; - - /** - * @brief Get current audio level - * - * Fetches the current volume level for the pipeline. - * - * @param[out] volume : Current volume level (range 0.0 - 1.0) - * - * @retval true on success false otherwise - */ - virtual bool getVolume(double &volume) = 0; - - /** - * @brief Returns the web audio player client. - * - * @retval The web audio player client. - */ - virtual std::weak_ptr getClient() = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ diff --git a/middleware/rialto-client/media/public/include/IWebAudioPlayerClient.h b/middleware/rialto-client/media/public/include/IWebAudioPlayerClient.h deleted file mode 100644 index 0c58dbef3..000000000 --- a/middleware/rialto-client/media/public/include/IWebAudioPlayerClient.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ -#define FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ - -/** - * @file IWebAudioPlayerClient.h - * - * The definition of the IWebAudioPlayerClient interface. - * - * This is the API by which a IWebAudioPlayer implementation will - * pass notifications to its client. - */ - -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief The Rialto web audio client interface. - * - * This is The Rialto web audio player client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the - * state of the web audio player. - */ -class IWebAudioPlayerClient -{ -public: - /** - * @brief Virtual destructor - */ - virtual ~IWebAudioPlayerClient() {} - - /** - * @brief Notifies the client of the playback state. - * - * The player will start IDLE. Once play() has been called the player - * will be PLAYING. When pause() is call3d the player will be PAUSED. - * When no further frames available for playout and setEos() has been - * called the player will be END_OF_STREAM. - * - * @param[in] state : The new playback state. - */ - virtual void notifyState(WebAudioPlayerState state) = 0; -}; - -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ diff --git a/middleware/rialto-client/media/public/include/MediaCommon.h b/middleware/rialto-client/media/public/include/MediaCommon.h deleted file mode 100644 index 199ffaf98..000000000 --- a/middleware/rialto-client/media/public/include/MediaCommon.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_MEDIA_COMMON_H_ -#define FIREBOLT_RIALTO_MEDIA_COMMON_H_ - -/** - * @file MediaCommon.h - * - * The definition of the Rialto Common types - * - */ - -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief The value of an invalid key session. - */ -constexpr int32_t kInvalidSessionId{-1}; - -/** - * @brief The value of an invalid audio channels number. - */ -constexpr uint32_t kInvalidAudioChannels{0}; - -/** - * @brief The value of an invalid audio sampling rate. - */ -constexpr uint32_t kInvalidAudioSampleRate{0}; - -/** - * @brief The value of an undefined size - */ -constexpr int32_t kUndefinedSize{0}; - -/** - * @brief The value of an invalid limitBuffering - */ -constexpr uint32_t kInvalidLimitBuffering{std::numeric_limits::max()}; - -/** - * @brief The value of undefined position - */ -constexpr uint64_t kUndefinedPosition{std::numeric_limits::max()}; - -/** - * @brief The supported types of media source. - */ -enum class MediaSourceType -{ - UNKNOWN, - AUDIO, - VIDEO, - SUBTITLE -}; - -/** - * @brief Shows the types of source configuration. - */ -enum class SourceConfigType -{ - UNKNOWN, - AUDIO, - VIDEO, - VIDEO_DOLBY_VISION, - SUBTITLE -}; - -/** - * @brief The supported audio ease types. - */ -enum class AudioEaseType -{ - LINEAR = 0, - INCUBIC, - OUTCUBIC -}; - -/** - * @brief The media type of media to be played. - */ -enum class MediaType -{ - UNKNOWN, /**< Media type not known. */ - MSE /**< Media is MSE and will request data. */ -}; - -/** - * @brief The media source status. This is the status of the source - * after a read. - */ -enum class MediaSourceStatus -{ - OK, /**< Source data provided without error. */ - EOS, /**< Source reached the end of stream. */ - ERROR, /**< There was an error providing source data. */ - CODEC_CHANGED, /**< The codec has changed and the decoder must be reconfigured */ - NO_AVAILABLE_SAMPLES /**< Could not retrieve media samples. */ -}; - -/** - * @brief The Network State - * - * The network state reflects the state of the network. For backend - * streaming, say using MediaPipelineURLDelegate, this is important - * as the backend uses the network to obtain the media data directly. - * - * For streaming that uses the browser to obtain data, say Media Source - * Extensions playback, only the states NetworkState::IDLE, - * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be - * indicated by the backend. - */ -enum class NetworkState -{ - UNKNOWN, /**< An unknown or undefined network state. */ - IDLE, /**< The network is idle. */ - BUFFERING, /**< The network is buffering data before playing. */ - BUFFERING_PROGRESS, /**< The network is buffering data whilst playing. */ - BUFFERED, /**< All the data is buffered. */ - STALLED, /**< The network has stalled but may recover. */ - FORMAT_ERROR, /**< The data is the wrong format. */ - NETWORK_ERROR, /**< There has been a network error. Playback stops. */ - DECODE_ERROR /**< There has been a decode error of the data. */ -}; - -/** - * @brief The Playback State - * - * The player will start IDLE. Once play() has been called the player - * will be PLAYING, or once pause() has been called the player will be - * PAUSED. A seek() request will result in SEEKING and once the seek - * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED - * state will be issued after a stop() request. - */ -enum class PlaybackState -{ - UNKNOWN, /**< An unknown or undefined playback state. */ - IDLE, /**< The backend player is idle. */ - PLAYING, /**< The backend player is playing media. */ - PAUSED, /**< The backend player is paused. */ - SEEKING, /**< The backend player is seeking a new playback position. */ - SEEK_DONE, /**< The backend player has finished seek. */ - STOPPED, /**< The backend player has stopped playback. */ - END_OF_STREAM, /**< The backend player has got to the end of playback. */ - FAILURE /**< The backend player failed to set playback state. */ -}; - -/** - * @brief The Format of the audio samples. Used by the raw audio media types - */ -enum class Format -{ - S8, - U8, - S16LE, - S16BE, - U16LE, - U16BE, - S24_32LE, - S24_32BE, - U24_32LE, - U24_32BE, - S32LE, - S32BE, - U32LE, - U32BE, - S24LE, - S24BE, - U24LE, - U24BE, - S20LE, - S20BE, - U20LE, - U20BE, - S18LE, - S18BE, - U18LE, - U18BE, - F32LE, - F32BE, - F64LE, - F64BE -}; - -/** - * @brief The layout of channels within a buffer. Used by the raw audio media types - */ -enum class Layout -{ - INTERLEAVED, - NON_INTERLEAVED -}; - -/** - * @brief Audio specific configuration - */ -struct AudioConfig -{ - uint32_t numberOfChannels = kInvalidAudioChannels; /**< The number of channels. */ - uint32_t sampleRate = kInvalidAudioSampleRate; /**< The sampling rate.*/ - std::vector codecSpecificConfig; /**< The audio specific config. Zero length if no specific config*/ - std::optional format; /**< The Format of the audio samples.*/ - std::optional layout; /**< The layout of channels within a buffer.*/ - std::optional channelMask; /**< Bitmask of channel positions present. */ - std::vector> streamHeader; /**< Stream header. Zero length if not present.*/ - std::optional - framed; /**< True if each buffer passed through the pipeline contains a complete, self-contained media unit*/ -}; - -/** - * @brief AddSegmentStatus - * - * The add segment status. This is the status adding new segment to Rialto - */ -enum class AddSegmentStatus -{ - OK, /**< Segment accepted. */ - NO_SPACE, /**< Too many frames sent or Rialto does not currently have space for this segment. */ - ERROR /**< Unexpected error. */ -}; - -/** - * @brief A pair describing the clear and encrypted bytes - * in a sub-sample. - */ -struct SubSamplePair -{ - size_t numClearBytes; /**< The number of clear bytes in the sample. */ - size_t numEncryptedBytes; /**< The number of encrypted bytes in the sample. */ -}; - -/** - * @brief Video decoder requirements used to allocate a suitable decoder for a MediaPipeline session - */ -struct VideoRequirements -{ - uint32_t maxWidth; /**< Maximum width of video frames to be decoded. */ - uint32_t maxHeight; /**< Maximum height of video frames to be decoded. */ -}; - -/** - * @brief Information about the shared memory required for writting data. - */ -struct MediaPlayerShmInfo -{ - uint32_t maxMetadataBytes; /**< The maximum amount of metadata that can be written. */ - uint32_t metadataOffset; /**< The offset to write the metadata. */ - uint32_t mediaDataOffset; /**< The offset to write the media data. */ - uint32_t maxMediaBytes; /**< The maximum amount of mediadata that can be written. */ -}; - -/** - * @brief The information provided in a QOS update. - */ -struct QosInfo -{ - uint64_t processed; /**< The total number of video frames/audio samples processed since MediaPipeline:load. */ - uint64_t dropped; /**< The total number of video frames/audio samples dropped since MediaPipeline:load. */ -}; - -/** - * @brief The error return status for session management methods. - */ -enum class MediaKeyErrorStatus -{ - OK, /**< No error. */ - FAIL, /**< An unspecified error occurred. */ - BAD_SESSION_ID, /**< The session id is not recognised. */ - NOT_SUPPORTED, /**< The request parameters are not supported. */ - INVALID_STATE, /**< The object is in an invalid state for the operation. */ - INTERFACE_NOT_IMPLEMENTED, /**< The interface is not implemented. */ - BUFFER_TOO_SMALL /**< The size of the buffer is too small. */ -}; - -/** - * @brief The media key session type. - */ -enum class KeySessionType -{ - UNKNOWN, /**< The session type is unknown. */ - TEMPORARY, /**< The session is a temporary session. */ - PERSISTENT_LICENCE, /**< The session is a persistent session. */ - PERSISTENT_RELEASE_MESSAGE /**< The session's persistent licence should be released. */ -}; - -/** - * @brief The init data type. - */ -enum class InitDataType -{ - UNKNOWN, /**< The init data type is unknown. */ - CENC, /**< The init data is in CENC format. */ - KEY_IDS, /**< The init data is key ids. */ - WEBM, /**< The init data is in WEBM format. */ - DRMHEADER /**< The init data is in DrmHeader format. */ -}; - -/** - * @brief The key status. - */ -enum class KeyStatus -{ - USABLE, - EXPIRED, - OUTPUT_RESTRICTED, - PENDING, - INTERNAL_ERROR, - RELEASED -}; - -/** - * @brief The alignment of media segment - */ -enum class SegmentAlignment -{ - UNDEFINED, - NAL, - AU -}; - -/** - * @brief The Stream Format of media segment - */ -enum class StreamFormat -{ - UNDEFINED, - RAW, - AVC, - BYTE_STREAM, - HVC1, - HEV1 -}; - -/** - * @brief A vector of key ID/key status pairs. - */ -typedef std::vector, KeyStatus>> KeyStatusVector; - -/** - * @brief Information about the shared memory required for writting data for the web audio playback. - */ -struct WebAudioShmInfo -{ - uint32_t offsetMain; /**< The offset to start writing the audio data. */ - uint32_t lengthMain; /**< The maximum number of bytes to write at offsetMain. */ - uint32_t offsetWrap; /**< The offset to continue writing the audio data if buffer wrapped. */ - uint32_t lengthWrap; /**< The maximum number of bytes to write at offsetWrap. */ -}; - -/** - * @brief Pcm config information. - */ -struct WebAudioPcmConfig -{ - uint32_t rate; /**< Rate of web audio (Hz) */ - uint32_t channels; /**< Number of channels */ - uint32_t sampleSize; /**< Size of each sample (bits) */ - bool isBigEndian; /**< Specifies if sample is stored as big-endian or little-endian format */ - bool isSigned; /**< Specifies if samples are signed or unsigned */ - bool isFloat; /**< Specifies if samples are float values or interger values*/ -}; - -/** - * @brief Type dependent configuration data. - */ -union WebAudioConfig -{ - /** - * @brief PCM audio configuration. - */ - WebAudioPcmConfig pcm; -}; - -/** - * @brief The Web Audio Player State. - */ -enum class WebAudioPlayerState -{ - UNKNOWN, /**< An unknown or undefined playback state. */ - IDLE, /**< The player is ready to play media. */ - PLAYING, /**< The player is playing media. */ - PAUSED, /**< The player is has paused media playback. */ - END_OF_STREAM, /**< The player has got to the end of playback. */ - FAILURE /**< The player failed to set playback state. */ -}; - -/** - * @brief Cipher mode for common encryption, see https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-3:v1:en - */ -enum class CipherMode -{ - UNKNOWN, - CENC, /* AES-CTR scheme */ - CBC1, /* AES-CBC scheme */ - CENS, /* AES-CTR subsample pattern encryption scheme */ - CBCS /* AES-CBC subsample pattern encryption scheme */ -}; - -/** - * @brief Fraction type. - */ -struct Fraction -{ - int32_t numerator; /**< The numerator */ - int32_t denominator; /**< The denominator */ -}; - -/** - * @brief Codec data type. - */ -enum class CodecDataType -{ - BUFFER, - STRING -}; - -/** - * @brief Codec data with type. - */ -struct CodecData -{ - std::vector data{}; /**< The codec data */ - CodecDataType type{CodecDataType::BUFFER}; /**< The codec data type */ -}; - -/** - * @brief None fatal asynchronous errors reported by the player. - */ -enum class PlaybackError -{ - UNKNOWN, - DECRYPTION, /* Player failed to decrypt a buffer and the frame has been dropped */ -}; - -/** - * @brief Ease type for audio volume changes. - */ -enum class EaseType -{ - EASE_LINEAR, - EASE_IN_CUBIC, - EASE_OUT_CUBIC -}; - -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_MEDIA_COMMON_H_ diff --git a/middleware/rialto-client/media/server/CMakeLists.txt b/middleware/rialto-client/media/server/CMakeLists.txt deleted file mode 100644 index 665b3a9d8..000000000 --- a/middleware/rialto-client/media/server/CMakeLists.txt +++ /dev/null @@ -1,77 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -add_subdirectory(common) -add_subdirectory(gstplayer) -add_subdirectory(main) -add_subdirectory(ipc) -add_subdirectory(service) - -add_executable ( - RialtoServer - - service/source/main.cpp -) - - -target_include_directories ( - RialtoServer - - PRIVATE - $ - $ - $ - $ - $ - $ - $ - $ -) - -set_target_properties( - RialtoServer - PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" -) - -target_link_libraries( - RialtoServer - - PRIVATE - RialtoServerIpc - RialtoServerMain - RialtoServerService - protobuf::libprotobuf -) - -if( NATIVE_BUILD ) - set_target_properties( - RialtoServer - PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib" -) -endif() - -install( - TARGETS RialtoServer - DESTINATION bin -) diff --git a/middleware/rialto-client/media/server/common/CMakeLists.txt b/middleware/rialto-client/media/server/common/CMakeLists.txt deleted file mode 100644 index 69f9e7bbf..000000000 --- a/middleware/rialto-client/media/server/common/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -add_library( - RialtoServerCommon - INTERFACE - ) - -target_include_directories( - RialtoServerCommon - - INTERFACE - include - ) diff --git a/middleware/rialto-client/media/server/common/include/RialtoServerLogging.h b/middleware/rialto-client/media/server/common/include/RialtoServerLogging.h deleted file mode 100644 index d6400a271..000000000 --- a/middleware/rialto-client/media/server/common/include/RialtoServerLogging.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef RIALTO_SERVER_LOGGING_H_ -#define RIALTO_SERVER_LOGGING_H_ - -#include "RialtoLogging.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define RIALTO_SERVER_LOG_FATAL(fmt, args...) RIALTO_LOG_FATAL(RIALTO_COMPONENT_SERVER, fmt, ##args) -#define RIALTO_SERVER_LOG_SYS_FATAL(err, fmt, args...) RIALTO_LOG_SYS_FATAL(RIALTO_COMPONENT_SERVER, err, fmt, ##args) -#define RIALTO_SERVER_LOG_ERROR(fmt, args...) RIALTO_LOG_ERROR(RIALTO_COMPONENT_SERVER, fmt, ##args) -#define RIALTO_SERVER_LOG_SYS_ERROR(err, fmt, args...) RIALTO_LOG_SYS_ERROR(RIALTO_COMPONENT_SERVER, err, fmt, ##args) -#define RIALTO_SERVER_LOG_WARN(fmt, args...) RIALTO_LOG_WARN(RIALTO_COMPONENT_SERVER, fmt, ##args) -#define RIALTO_SERVER_LOG_SYS_WARN(err, fmt, args...) RIALTO_LOG_SYS_WARN(RIALTO_COMPONENT_SERVER, err, fmt, ##args) -#define RIALTO_SERVER_LOG_MIL(fmt, args...) RIALTO_LOG_MIL(RIALTO_COMPONENT_SERVER, fmt, ##args) -#define RIALTO_SERVER_LOG_INFO(fmt, args...) RIALTO_LOG_INFO(RIALTO_COMPONENT_SERVER, fmt, ##args) -#define RIALTO_SERVER_LOG_DEBUG(fmt, args...) RIALTO_LOG_DEBUG(RIALTO_COMPONENT_SERVER, fmt, ##args) - -#ifdef __cplusplus -} -#endif - -#endif // RIALTO_SERVER_LOGGING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/CMakeLists.txt b/middleware/rialto-client/media/server/gstplayer/CMakeLists.txt deleted file mode 100644 index 8bc7291e7..000000000 --- a/middleware/rialto-client/media/server/gstplayer/CMakeLists.txt +++ /dev/null @@ -1,147 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Find includes in corresponding build directories -set( CMAKE_INCLUDE_CURRENT_DIR ON ) - -# RIALTO-197: deprecated-declarations error in the latest stable2 for gstreamer. -# Should be removed once the issue is fixed. -add_compile_options( - "-Wno-deprecated-declarations" -) - -find_package( PkgConfig REQUIRED ) -pkg_check_modules( GStreamerApp REQUIRED IMPORTED_TARGET gstreamer-app-1.0 gstreamer-pbutils-1.0 gstreamer-audio-1.0) - -add_library( - RialtoServerGstPlayer - STATIC - - source/tasks/generic/AttachSamples.cpp - source/tasks/generic/AttachSource.cpp - source/tasks/generic/CheckAudioUnderflow.cpp - source/tasks/generic/DeepElementAdded.cpp - source/tasks/generic/EnoughData.cpp - source/tasks/generic/Eos.cpp - source/tasks/generic/FinishSetupSource.cpp - source/tasks/generic/Flush.cpp - source/tasks/generic/GenericPlayerTaskFactory.cpp - source/tasks/generic/HandleBusMessage.cpp - source/tasks/generic/NeedData.cpp - source/tasks/generic/Pause.cpp - source/tasks/generic/Ping.cpp - source/tasks/generic/Play.cpp - source/tasks/generic/ProcessAudioGap.cpp - source/tasks/generic/ReadShmDataAndAttachSamples.cpp - source/tasks/generic/RemoveSource.cpp - source/tasks/generic/RenderFrame.cpp - source/tasks/generic/ReportPosition.cpp - source/tasks/generic/SetBufferingLimit.cpp - source/tasks/generic/SetImmediateOutput.cpp - source/tasks/generic/SetLowLatency.cpp - source/tasks/generic/SetMute.cpp - source/tasks/generic/SetPlaybackRate.cpp - source/tasks/generic/SetPosition.cpp - source/tasks/generic/SetSourcePosition.cpp - source/tasks/generic/SetSubtitleOffset.cpp - source/tasks/generic/SetStreamSyncMode.cpp - source/tasks/generic/SetSync.cpp - source/tasks/generic/SetSyncOff.cpp - source/tasks/generic/SetTextTrackIdentifier.cpp - source/tasks/generic/SetUseBuffering.cpp - source/tasks/generic/SetVideoGeometry.cpp - source/tasks/generic/SetVolume.cpp - source/tasks/generic/SetupElement.cpp - source/tasks/generic/SetupSource.cpp - source/tasks/generic/Shutdown.cpp - source/tasks/generic/Stop.cpp - source/tasks/generic/SwitchSource.cpp - source/tasks/generic/SynchroniseSubtitleClock.cpp - source/tasks/generic/Underflow.cpp - source/tasks/generic/UpdatePlaybackGroup.cpp - - source/tasks/webAudio/Eos.cpp - source/tasks/webAudio/HandleBusMessage.cpp - source/tasks/webAudio/Pause.cpp - source/tasks/webAudio/Ping.cpp - source/tasks/webAudio/Play.cpp - source/tasks/webAudio/SetCaps.cpp - source/tasks/webAudio/SetVolume.cpp - source/tasks/webAudio/Shutdown.cpp - source/tasks/webAudio/Stop.cpp - source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp - source/tasks/webAudio/WriteBuffer.cpp - - source/CapsBuilder.cpp - source/FlushWatcher.cpp - source/GstCapabilities.cpp - source/GstDecryptor.cpp - source/GstDispatcherThread.cpp - source/GstGenericPlayer.cpp - source/GstInitialiser.cpp - source/GstLogForwarding.cpp - source/GstProtectionMetadata.cpp - source/GstProtectionMetadataHelper.cpp - source/GstSrc.cpp - source/GstTextTrackSink.cpp - source/GstWebAudioPlayer.cpp - source/NeedDataMapping.cpp - source/Utils.cpp - source/WorkerThread.cpp - ) - -target_include_directories( - RialtoServerGstPlayer - - PUBLIC - interface - - PRIVATE - include - include/tasks - include/tasks/generic - include/tasks/webAudio - $ - $ - $ - $ - $ - $ - ${GStreamerApp_INCLUDE_DIRS} - - ) - - -set_property( - TARGET RialtoServerGstPlayer - PROPERTY POSITION_INDEPENDENT_CODE ON - - ) - -target_link_libraries( - RialtoServerGstPlayer - - PRIVATE - RialtoLogging - RialtoServerMain - RialtoWrappers - RialtoCommon - RialtoPlayerCommon - ${GStreamerApp_LIBRARIES} - ) diff --git a/middleware/rialto-client/media/server/gstplayer/include/CapsBuilder.h b/middleware/rialto-client/media/server/gstplayer/include/CapsBuilder.h deleted file mode 100644 index 21201258e..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/CapsBuilder.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_CAPS_BUILDER_H_ -#define FIREBOLT_RIALTO_SERVER_CAPS_BUILDER_H_ - -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "IMediaPipeline.h" -#include -#include - -namespace firebolt::rialto::server -{ -class MediaSourceCapsBuilder -{ -public: - MediaSourceCapsBuilder(std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const firebolt::rialto::IMediaPipeline::MediaSourceAV &source); - virtual ~MediaSourceCapsBuilder() = default; - virtual GstCaps *buildCaps(); - -protected: - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - const IMediaPipeline::MediaSourceAV &m_attachedSource; - - GstCaps *buildCommonCaps(); - void addAlignmentToCaps(GstCaps *caps) const; - void addCodecDataToCaps(GstCaps *caps) const; - void addStreamFormatToCaps(GstCaps *caps) const; -}; - -class MediaSourceAudioCapsBuilder : public MediaSourceCapsBuilder -{ -public: - MediaSourceAudioCapsBuilder(std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const IMediaPipeline::MediaSourceAudio &source); - ~MediaSourceAudioCapsBuilder() override = default; - GstCaps *buildCaps() override; - -protected: - GstCaps *createOpusCaps(); - GstCaps *getAudioSpecificConfiguration() const; - void addSampleRateAndChannelsToCaps(GstCaps *caps) const; - void addMpegVersion4ToCaps(GstCaps *caps) const; - void addMp3Caps(GstCaps *caps) const; - void addRawAudioData(GstCaps *caps) const; - void addFlacSpecificData(GstCaps *caps) const; - - const IMediaPipeline::MediaSourceAudio &m_attachedAudioSource; -}; - -class MediaSourceVideoCapsBuilder : public MediaSourceCapsBuilder -{ -public: - MediaSourceVideoCapsBuilder(std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const IMediaPipeline::MediaSourceVideo &source); - ~MediaSourceVideoCapsBuilder() override = default; - GstCaps *buildCaps() override; - -protected: - const IMediaPipeline::MediaSourceVideo &m_attachedVideoSource; -}; - -class MediaSourceVideoDolbyVisionCapsBuilder : public MediaSourceVideoCapsBuilder -{ -public: - MediaSourceVideoDolbyVisionCapsBuilder(std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const IMediaPipeline::MediaSourceVideoDolbyVision &source); - ~MediaSourceVideoDolbyVisionCapsBuilder() override = default; - GstCaps *buildCaps() override; - -protected: - const IMediaPipeline::MediaSourceVideoDolbyVision &m_attachedDolbySource; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_CAPS_BUILDER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/FlushWatcher.h b/middleware/rialto-client/media/server/gstplayer/include/FlushWatcher.h deleted file mode 100644 index 86865570e..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/FlushWatcher.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_H_ -#define FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_H_ - -#include "IFlushWatcher.h" -#include -#include - -namespace firebolt::rialto::server -{ -class FlushWatcher : public IFlushWatcher -{ -public: - FlushWatcher() = default; - ~FlushWatcher() override = default; - - void setFlushing(const MediaSourceType &type, bool async) override; - void setFlushed(const MediaSourceType &type) override; - bool isFlushOngoing() const override; - bool isAsyncFlushOngoing() const override; - -private: - mutable std::mutex m_mutex; - std::map m_flushingSources; -}; -} // namespace firebolt::rialto::server -#endif // FIREBOLT_RIALTO_SERVER_FLUSH_WATCHER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GenericPlayerContext.h b/middleware/rialto-client/media/server/gstplayer/include/GenericPlayerContext.h deleted file mode 100644 index b366cd196..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GenericPlayerContext.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_CONTEXT_H_ -#define FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_CONTEXT_H_ - -#include "IGstSrc.h" -#include "IRdkGstreamerUtilsWrapper.h" -#include "ITimer.h" -#include "MediaCommon.h" -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -constexpr double kNoPendingPlaybackRate{0.0}; - -enum class EosState -{ - PENDING, - SET -}; - -/** - * @brief Structure used for video geometry - */ -struct Rectangle -{ - int x, y, width, height; - constexpr Rectangle() : x(0), y(0), width(0), height(0) {} - constexpr Rectangle(int x_, int y_, int w_, int h_) : x(x_), y(y_), width(w_), height(h_) {} - Rectangle(const Rectangle &rhs) = default; - inline constexpr bool empty() { return (width == 0) || (height == 0); } - inline void clear() { x = y = width = height = 0; } -}; - -/** - * @brief Structure used for set source position - */ -struct SegmentData -{ - int64_t position; - bool resetTime; - double appliedRate; - uint64_t stopPosition; -}; - -struct GenericPlayerContext -{ - /** - * @brief The rialto src object. - */ - std::shared_ptr gstSrc{nullptr}; - - /** - * @brief The gstreamer pipeline. - */ - GstElement *pipeline{nullptr}; - - /** - * @brief The gstreamer source. - */ - GstElement *source{nullptr}; - - /** - * @brief A map of streams attached to the source. - */ - StreamInfoMap streamInfo{}; - - /** - * @brief Child sink of the autovideosink. - */ - GstElement *autoVideoChildSink{nullptr}; - - /** - * @brief Child sink of the autoaudiosink. - */ - GstElement *autoAudioChildSink{nullptr}; - - /** - * @brief The subtitle sink - */ - GstElement *subtitleSink{nullptr}; - - /** - * @brief The video sink - */ - GstElement *videoSink{nullptr}; - - /** - * @brief Flag used to check, if video decoder handle has been set. - */ - bool isVideoHandleSet{false}; - - /** - * @brief Flag used to check, if BUFFERED notification has been sent. - * - * Flag can be used only in worker thread - */ - bool bufferedNotificationSent{false}; - - /** - * @brief Flag used to check, if the playback is in the playing state - * - * Flag can be used only in worker thread - */ - bool isPlaying{false}; - - /** - * @brief Flag used to check, if EOS has been notified to the client - * - * Flag can be used only in worker thread - */ - bool eosNotified{false}; - - /** - * @brief Pending video geometry - */ - Rectangle pendingGeometry; - - /** - * @brief Current playback rate - */ - double playbackRate{1.0}; - - /** - * @brief Pending playback rate - */ - double pendingPlaybackRate{kNoPendingPlaybackRate}; - - /** - * @brief Pending immediate output for MediaSourceType::VIDEO - */ - std::optional pendingImmediateOutputForVideo{}; - - /** - * @brief Pending low latency - */ - std::optional pendingLowLatency{}; - - /** - * @brief Pending sync - */ - std::optional pendingSync{}; - - /** - * @brief Pending sync off - */ - std::optional pendingSyncOff{}; - - /** - * @brief Pending buffering limit - */ - std::optional pendingBufferingLimit{}; - - /** - * @brief Pending use buffering - */ - std::optional pendingUseBuffering{}; - - /** - * @brief Pending stream sync mode - */ - std::map pendingStreamSyncMode{}; - - /** - * @brief Pending render frame - */ - bool pendingRenderFrame{false}; - - /** - * @brief Pending show video window - */ - std::optional pendingShowVideoWindow{}; - - /** - * @brief Last audio sample timestamps - * TODO(LLDEV-31012) Needed to detect audio stream underflow - */ - int64_t lastAudioSampleTimestamps{0}; - - /** - * @brief The decryption service. - */ - IDecryptionService *decryptionService{nullptr}; - - /** - * @brief Flag used to check, if audio source has been recently removed - * - * Flag can be used only in worker thread - */ - bool audioSourceRemoved{false}; - - /** - * @brief Audio elements of gst pipeline. - * - * Attribute can be used only in worker thread - */ - firebolt::rialto::wrappers::PlaybackGroupPrivate playbackGroup; - - /** - * @brief A map of streams that have ended. - */ - std::unordered_map endOfStreamInfo{}; - - /** - * @brief Flag used to check if client already notified server that all sources were attached - * - * Attribute can be used only in worker thread - */ - bool wereAllSourcesAttached{false}; - - /** - * @brief Flag used to check if FinishSetupSource is finished. It is needed to avoid need data overwriting. - * - * Attribute can be used only in worker thread - */ - bool setupSourceFinished{false}; - - /** - * @brief Queued source positions. Used by SetSourcePosition task to request pushing new sample. - * - * Attribute can be used only in worker thread - */ - std::map> initialPositions; - - /** - * @brief Currently set position of a source. Used to check, if additional segment should be pushed. - * - * Attribute can be used only in worker thread - */ - std::map currentPosition; - - /** - * @brief The mutex, which protects properties, which are read/written by main/worker thread. - * This mutex should be removed in future, when we find out better solution for - * property read-write. - */ - std::mutex propertyMutex; - - /** - * @brief Flag used to check if audio fade is enabled - * - * Attribute can be used only in worker thread - */ - std::atomic_bool audioFadeEnabled{false}; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_CONTEXT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstCapabilities.h b/middleware/rialto-client/media/server/gstplayer/include/GstCapabilities.h deleted file mode 100644 index 41e5854c8..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstCapabilities.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_SERVER_GST_CAPABILITIES_H_ - -#include "IGlibWrapper.h" -#include "IGstCapabilities.h" -#include "IGstInitialiser.h" -#include "IGstWrapper.h" -#include "IRdkGstreamerUtilsWrapper.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief GstCapabilities factory class, returns a concrete implementation of GstCapabilities - */ -class GstCapabilitiesFactory : public IGstCapabilitiesFactory -{ -public: - /** - * @brief Weak pointer to the singleton factory object. - */ - static std::weak_ptr m_factory; - - /** - * @brief Creates a IGstCapabilities object. - * - * @retval the new gstreamer capabilities instance or null on error. - */ - std::unique_ptr createGstCapabilities() override; -}; - -class GstCapabilities : public IGstCapabilities -{ -public: - explicit GstCapabilities( - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr &rdkGstreamerUtilsWrapper, - const IGstInitialiser &gstInitialiser); - ~GstCapabilities(); - - GstCapabilities(const GstCapabilities &) = delete; - GstCapabilities &operator=(const GstCapabilities &) = delete; - GstCapabilities(GstCapabilities &&) = delete; - GstCapabilities &operator=(GstCapabilities &&) = delete; - - /** - * @brief Gets vector of mime types supported by gstreamer - * - * @retval vector of mime types supported by gstreamer - */ - std::vector getSupportedMimeTypes(MediaSourceType sourceType) override; - - /** - * @brief Checks is \a mimeType is supported by gstreamer - * - * @retval True if mime type is supported by gstreamer - */ - bool isMimeTypeSupported(const std::string &mimeType) override; - - /** - * @brief Check sinks and decoders for supported properties - * - * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched - * @param[in] propertyNames : A vector of property names to look for - * - * @retval Returns the subset of propertyNames that are supported by the mediaType - */ - std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) override; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - bool isVideoMaster(bool &isVideoMaster) override; - -private: - /** - * @brief Sets list of supported mime types - */ - void fillSupportedMimeTypes(); - - /** - * @brief Appends all unique caps from parser->decoders chains' sink pads to \a supportedCaps - */ - void appendLinkableCapsFromParserDecoderChains(std::vector &supportedCaps); - - /** - * @brief Appends all unique caps from \a type pads to \a supportedCaps - */ - void appendSupportedCapsFromFactoryType(const GstElementFactoryListType &type, std::vector &supportedCaps); - - /** - * @brief Adds unique sink pads from \a padTemplates list to \a capsVector - */ - void addAllUniqueSinkPadsCapsToVector(std::vector &capsVector, const GList *padTemplates); - - /** - * @brief Checks if any src pad of parser can be connected to decoder - * - * @retval True if it's possible - */ - bool canCreateParserDecoderChain(GstCaps *decoderCaps, const GList *parserPadTemplates); - - /** - * @brief Checks if caps equal to \a caps is already in \a capsVector - * - * @retval True if there is equal caps - */ - bool isCapsInVector(const std::vector &capsVector, GstCaps *caps) const; - - /** - * @brief Waits for supportd mime types initialisation - */ - void waitForInitialisation(); - - /** - * @brief Set of mime types which are supported by gstreamer - */ - std::unordered_set m_supportedMimeTypes; - - /** - * @brief The gstreamer wrapper object. - */ - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - std::shared_ptr m_rdkGstreamerUtilsWrapper; - const IGstInitialiser &m_gstInitialiser; - std::thread m_initialisationThread; - std::mutex m_initialisationMutex; - std::condition_variable m_initialisationCv; - bool m_isInitialised{false}; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorElementFactory.h b/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorElementFactory.h deleted file mode 100644 index ccea1bd61..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorElementFactory.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_ELEMENT_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_ELEMENT_FACTORY_H_ - -#include "IGstDecryptorElementFactory.h" -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IGstDecryptorElement factory class definition. - */ -class GstDecryptorElementFactory : public IGstDecryptorElementFactory -{ -public: - GstDecryptorElementFactory() = default; - ~GstDecryptorElementFactory() override = default; - - GstElement * - createDecryptorElement(const gchar *name, firebolt::rialto::server::IDecryptionService *decryptionService, - const std::shared_ptr &gstWrapper) const override; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_ELEMENT_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorPrivate.h b/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorPrivate.h deleted file mode 100644 index 8659aae15..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstDecryptorPrivate.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_PRIVATE_H_ -#define FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_PRIVATE_H_ - -#include "IDecryptionService.h" -#include "IGlibWrapper.h" -#include "IGstProtectionMetadataHelper.h" -#include "IGstWrapper.h" -#include -#include - -namespace firebolt::rialto::server -{ -class GstRialtoDecryptorPrivate -{ -public: - /** - * @brief The constructor. - - * @param[in] parentElement : The parent decryptor element. - * @param[in] gstWrapperFactory : The gstreamer wrapper factory. - * @param[in] glibWrapperFactory : The glib wrapper factory. - */ - GstRialtoDecryptorPrivate(GstBaseTransform *parentElement, - const std::shared_ptr &gstWrapperFactory, - const std::shared_ptr &glibWrapperFactory); - - /** - * @brief Decrypts the gst buffer. - * - * @param[in] buffer : The gst buffer to decrypt. - * @param[in] caps : The gst caps of buffer. - * - * @retval the gst flow return status. - */ - GstFlowReturn decrypt(GstBuffer *buffer, GstCaps *caps); - - /** - * @brief Set the decryption service object. - * - * @param[in] decryptionService : The service that performs decryption. - */ - void setDecryptionService(IDecryptionService *decryptionService); - - /** - * @brief Set the protection metadata object - * - * @param[in] metadataWrapper : The protection metadata object - */ - void setProtectionMetadataWrapper(std::unique_ptr &&metadataWrapper); - -private: - /** - * @brief The gstreamer wrapper object. - */ - std::shared_ptr m_gstWrapper; - - /** - * @brief The glib wrapper object. - */ - std::shared_ptr m_glibWrapper; - - /** - * @brief The parent decryptor element. - */ - GstBaseTransform *m_decryptorElement; - - /** - * @brief The service to perform decryption. - */ - IDecryptionService *m_decryptionService; - - /** - * @brief The protection metadata object - */ - std::unique_ptr m_metadataWrapper; - - /** - * @brief Creates the protection meta structure. - * - * @param[in] protectionData : The rialto protection data. - * - * @retval the gst structure of the protection meta. - */ - GstStructure *createProtectionMetaInfo(GstRialtoProtectionData *protectionData); -}; -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_DECRYPTOR_PRIVATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstDispatcherThread.h b/middleware/rialto-client/media/server/gstplayer/include/GstDispatcherThread.h deleted file mode 100644 index fa5ad3ac5..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstDispatcherThread.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_DISPATCHER_THREAD_H_ -#define FIREBOLT_RIALTO_SERVER_GST_DISPATCHER_THREAD_H_ - -#include "IGstDispatcherThread.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class GstDispatcherThreadFactory : public IGstDispatcherThreadFactory -{ -public: - ~GstDispatcherThreadFactory() override = default; - std::unique_ptr - createGstDispatcherThread(IGstDispatcherThreadClient &client, GstElement *pipeline, - const std::shared_ptr &gstWrapper) const override; -}; - -class GstDispatcherThread : public IGstDispatcherThread -{ -public: - GstDispatcherThread(IGstDispatcherThreadClient &client, GstElement *pipeline, - const std::shared_ptr &gstWrapper); - ~GstDispatcherThread() override; - -private: - /** - * @brief For handling gst bus messages in Gstreamer dispatcher thread - * - * @param[in] pipeline : The pipeline - */ - void gstBusEventHandler(GstElement *pipeline); - -private: - /** - * @brief The listening client. - */ - IGstDispatcherThreadClient &m_client; - - /** - * @brief The gstreamer wrapper object. - */ - std::shared_ptr m_gstWrapper; - - /** - * @brief Flag used to check, if task thread is active - */ - std::atomic m_isGstreamerDispatcherActive; - - /** - * @brief Thread for handling gst bus callbacks - */ - std::thread m_gstBusDispatcherThread; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_DISPATCHER_THREAD_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstGenericPlayer.h b/middleware/rialto-client/media/server/gstplayer/include/GstGenericPlayer.h deleted file mode 100644 index 3b495cf17..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstGenericPlayer.h +++ /dev/null @@ -1,425 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_GENERIC_PLAYER_H_ -#define FIREBOLT_RIALTO_SERVER_GST_GENERIC_PLAYER_H_ - -#include "GenericPlayerContext.h" -#include "IFlushWatcher.h" -#include "IGlibWrapper.h" -#include "IGstDispatcherThread.h" -#include "IGstDispatcherThreadClient.h" -#include "IGstGenericPlayer.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstInitialiser.h" -#include "IGstProtectionMetadataHelperFactory.h" -#include "IGstSrc.h" -#include "IGstWrapper.h" -#include "ITimer.h" -#include "IWorkerThread.h" -#include "NeedDataMapping.h" -#include "tasks/IGenericPlayerTaskFactory.h" -#include "tasks/IPlayerTask.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -constexpr uint32_t kMinPrimaryVideoWidth{1920}; -constexpr uint32_t kMinPrimaryVideoHeight{1080}; - -/** - * @brief IGstGenericPlayer factory class definition. - */ -class GstGenericPlayerFactory : public IGstGenericPlayerFactory -{ -public: - /** - * @brief Weak pointer to the singleton factory object. - */ - static std::weak_ptr m_factory; - - std::unique_ptr - createGstGenericPlayer(IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, - const VideoRequirements &videoRequirements, - const std::shared_ptr - &rdkGstreamerUtilsWrapperFactory) override; -}; - -/** - * @brief The definition of the GstGenericPlayer. - */ -class GstGenericPlayer : public IGstGenericPlayer, public IGstGenericPlayerPrivate, public IGstDispatcherThreadClient -{ -public: - /** - * @brief The constructor. - * - * @param[in] client : The gstreamer player client. - * @param[in] decryptionService : The decryption service - * @param[in] type : The media type the gstreamer player shall support. - * @param[in] videoRequirements : The video requirements for the playback. - * @param[in] gstWrapper : The gstreamer wrapper. - * @param[in] glibWrapper : The glib wrapper. - * @param[in] gstInitialiser : The gst initialiser - * @param[in] flushWatcher : The flush watcher - * @param[in] gstSrcFactory : The gstreamer rialto src factory. - * @param[in] timerFactory : The Timer factory - * @param[in] taskFactory : The task factory - * @param[in] workerThreadFactory : The worker thread factory - * @param[in] gstDispatcherThreadFactory : The gst dispatcher thread factory - */ - GstGenericPlayer(IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, - const VideoRequirements &videoRequirements, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr &rdkGstreamerUtilsWrapper, - const IGstInitialiser &gstInitialiser, std::unique_ptr &&flushWatcher, - const std::shared_ptr &gstSrcFactory, - std::shared_ptr timerFactory, - std::unique_ptr taskFactory, - std::unique_ptr workerThreadFactory, - std::unique_ptr gstDispatcherThreadFactory, - std::shared_ptr gstProtectionMetadataFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~GstGenericPlayer(); - - void attachSource(const std::unique_ptr &mediaSource) override; - void removeSource(const MediaSourceType &mediaSourceType) override; - void allSourcesAttached() override; - void play() override; - void pause() override; - void stop() override; - void attachSamples(const IMediaPipeline::MediaSegmentVector &mediaSegments) override; - void attachSamples(const std::shared_ptr &dataReader) override; - void setPosition(std::int64_t position) override; - void setVideoGeometry(int x, int y, int width, int height) override; - void setEos(const firebolt::rialto::MediaSourceType &type) override; - void setPlaybackRate(double rate) override; - bool getPosition(std::int64_t &position) override; - bool setImmediateOutput(const MediaSourceType &mediaSourceType, bool immediateOutput) override; - bool getImmediateOutput(const MediaSourceType &mediaSourceType, bool &immediateOutput) override; - bool getStats(const MediaSourceType &mediaSourceType, uint64_t &renderedFrames, uint64_t &droppedFrames) override; - void setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType) override; - bool getVolume(double &volume) override; - void setMute(const MediaSourceType &mediaSourceType, bool mute) override; - bool getMute(const MediaSourceType &mediaSourceType, bool &mute) override; - void setTextTrackIdentifier(const std::string &textTrackIdentifier) override; - bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; - bool setLowLatency(bool lowLatency) override; - bool setSync(bool sync) override; - bool getSync(bool &sync) override; - bool setSyncOff(bool syncOff) override; - bool setStreamSyncMode(const MediaSourceType &mediaSourceType, int32_t streamSyncMode) override; - bool getStreamSyncMode(int32_t &streamSyncMode) override; - void ping(std::unique_ptr &&heartbeatHandler) override; - void flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) override; - void setSourcePosition(const MediaSourceType &mediaSourceType, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) override; - void setSubtitleOffset(int64_t position) override; - void processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; - void setBufferingLimit(uint32_t limitBufferingMs) override; - bool getBufferingLimit(uint32_t &limitBufferingMs) override; - void setUseBuffering(bool useBuffering) override; - bool getUseBuffering(bool &useBuffering) override; - void switchSource(const std::unique_ptr &mediaSource) override; - -private: - void scheduleNeedMediaData(GstAppSrc *src) override; - void scheduleEnoughData(GstAppSrc *src) override; - void scheduleAudioUnderflow() override; - void scheduleVideoUnderflow() override; - void scheduleAllSourcesAttached() override; - bool setVideoSinkRectangle() override; - bool setImmediateOutput() override; - bool setShowVideoWindow() override; - bool setLowLatency() override; - bool setSync() override; - bool setSyncOff() override; - bool setStreamSyncMode(const MediaSourceType &type) override; - bool setRenderFrame() override; - bool setBufferingLimit() override; - bool setUseBuffering() override; - void notifyNeedMediaData(const MediaSourceType mediaSource) override; - GstBuffer *createBuffer(const IMediaPipeline::MediaSegment &mediaSegment) const override; - void attachData(const firebolt::rialto::MediaSourceType mediaType) override; - void updateAudioCaps(int32_t rate, int32_t channels, const std::shared_ptr &codecData) override; - void updateVideoCaps(int32_t width, int32_t height, Fraction frameRate, - const std::shared_ptr &codecData) override; - void addAudioClippingToBuffer(GstBuffer *buffer, uint64_t clippingStart, uint64_t clippingEnd) const override; - bool changePipelineState(GstState newState) override; - int64_t getPosition(GstElement *element) override; - void startPositionReportingAndCheckAudioUnderflowTimer() override; - void stopPositionReportingAndCheckAudioUnderflowTimer() override; - void startSubtitleClockResyncTimer() override; - void stopSubtitleClockResyncTimer() override; - void stopWorkerThread() override; - void cancelUnderflow(firebolt::rialto::MediaSourceType mediaSource) override; - void setPendingPlaybackRate() override; - void renderFrame() override; - void handleBusMessage(GstMessage *message, bool priority) override; - void updatePlaybackGroup(GstElement *typefind, const GstCaps *caps) override; - - void addAutoVideoSinkChild(GObject *object) override; - void addAutoAudioSinkChild(GObject *object) override; - void removeAutoVideoSinkChild(GObject *object) override; - void removeAutoAudioSinkChild(GObject *object) override; - void setPlaybinFlags(bool enableAudio = true) override; - void pushSampleIfRequired(GstElement *source, const std::string &typeStr) override; - bool reattachSource(const std::unique_ptr &source) override; - bool hasSourceType(const MediaSourceType &mediaSourceType) const override; - GstElement *getSink(const MediaSourceType &mediaSourceType) const override; - void setSourceFlushed(const MediaSourceType &mediaSourceType) override; - bool isAsync(const MediaSourceType &mediaSourceType) const; - void clearNeedDataScheduled(GstAppSrc *src) override; - -private: - /** - * @brief Initialises the player pipeline for MSE playback. - */ - void initMsePipeline(); - - /** - * @brief Gets the flag from gstreamer. - * - * @param[in] nick : The name of the flag in gstreamer. - * - * @retval Value of the flag or 0 on error. - */ - unsigned getGstPlayFlag(const char *nick); - - /** - * @brief Callback on source-setup. Called by the Gstreamer thread - * - * @param[in] pipeline : The pipeline the signal was fired from. - * @param[in] source : The source to setup. - * @param[in] self : Reference to the calling object. - */ - static void setupSource(GstElement *pipeline, GstElement *source, GstGenericPlayer *self); - - /** - * @brief Callback on element-setup. Called by the Gstreamer thread - * - * @param[in] pipeline : The pipeline the signal was fired from. - * @param[in] element : an element that was added to the playbin hierarchy - * @param[in] self : Reference to the calling object. - */ - static void setupElement(GstElement *pipeline, GstElement *element, GstGenericPlayer *self); - - /** - * @brief Callback on element-setup. Called by the Gstreamer thread - * - * @param[in] pipeline : The pipeline the signal was fired from. - * @param[in] bin : the GstBin the element was added to - * @param[in] element : an element that was added to the playbin hierarchy - * @param[in] self : Reference to the calling object. - */ - static void deepElementAdded(GstBin *pipeline, GstBin *bin, GstElement *element, GstGenericPlayer *self); - - /** - * @brief Creates a Westeros sink and sets the res-usage flag for a secondary video. - * - * @retval true on success. - */ - bool setWesterossinkSecondaryVideo(); - - /** - * @brief Creates an "erm" gstreamer context in the pipeline - * - * @retval true on success. - */ - bool setErmContext(); - - /** - * @brief Terminates the player pipeline. - */ - void termPipeline(); - - /** - * @brief Shutdown and destroys the worker thread. - */ - void resetWorkerThread(); - - /** - * @brief Whether native audio should be enabled on the current platform. - */ - bool shouldEnableNativeAudio(); - - /** - * @brief Sets codec_data in GstCaps if available - * - * @retval True if caps were changed - */ - bool setCodecData(GstCaps *caps, const std::shared_ptr &codecData) const; - - /** - * @brief Gets the video sink element child sink if present. - * Only gets children for GstAutoVideoSink's. - * - * @param[in] sink : Sink element to check. - * - * @retval Underlying child video sink or 'sink' if there are no children. - */ - GstElement *getSinkChildIfAutoVideoSink(GstElement *sink) const; - - /** - * @brief Gets the audio sink element child sink if present. - * Only gets children for GstAutoAudioSink's. - * - * @param[in] sink : Sink element to check. - * - * @retval Underlying child audio sink or 'sink' if there are no children. - */ - GstElement *getSinkChildIfAutoAudioSink(GstElement *sink) const; - - /** - * @brief Gets the decoder element for source type. - * - * @param[in] mediaSourceType : the source type to obtain the decoder for - * - * @retval The decoder, NULL if not found - */ - GstElement *getDecoder(const MediaSourceType &mediaSourceType); - - /** - * @brief Gets the parser element for source type. - * - * @param[in] mediaSourceType : the source type to obtain the parser for - * - * @retval The parser, NULL if not found - */ - GstElement *getParser(const MediaSourceType &mediaSourceType); - - /** - * @brief Constructs new Audio Attributes structure based on MediaSource - * Called by worker thread only! - * - * @param[in] source : the media source, which contains params needed by Audio Attributes struct - * - * @retval The Audio Attributes structure on success, std::nullopt on failure - */ - std::optional - createAudioAttributes(const std::unique_ptr &source) const; - - /** - * @brief Sets text track position before pushing data - * - * @param[in] source : the subtitle media source - */ - void setTextTrackPositionIfRequired(GstElement *source); - - /** - * @brief GstAppSrc does not replace segment, if it's the same as previous one. - * It causes problems with position reporing in amlogic devices, so we need to push - * two segments with different reset time value. - * - * @param[in] source : the media source - */ - void pushAdditionalSegmentIfRequired(GstElement *source); - -private: - /** - * @brief The player context. - */ - GenericPlayerContext m_context; - - /** - * @brief The gstreamer player client. - */ - IGstGenericPlayerClient *m_gstPlayerClient = nullptr; - - /** - * @brief The gstreamer wrapper object. - */ - std::shared_ptr m_gstWrapper; - - /** - * @brief The glib wrapper object. - */ - std::shared_ptr m_glibWrapper; - - /** - * @brief The rdk gstreamer utils wrapper object - */ - std::shared_ptr m_rdkGstreamerUtilsWrapper; - - /** - * @brief Thread for handling player tasks. - */ - std::unique_ptr m_workerThread; - - /** - * @brief Thread for handling gst bus callbacks - */ - std::unique_ptr m_gstDispatcherThread; - - /** - * @brief Factory creating timers - * - */ - std::shared_ptr m_timerFactory; - - /** - * @brief Timer to trigger FinishSourceSetup - */ - std::unique_ptr m_finishSourceSetupTimer{nullptr}; - - /** - * @brief Timer reporting playback position and check audio underflow - * - * Variable can be used only in worker thread - */ - std::unique_ptr m_positionReportingAndCheckAudioUnderflowTimer{nullptr}; - - /** - * @brief Timer to resync subtitle clock with AV clock - * - * Variable can be used only in worker thread - */ - std::unique_ptr m_subtitleClockResyncTimer{nullptr}; - - /** - * @brief The GstGenericPlayer task factory - */ - std::unique_ptr m_taskFactory; - - /** - * @brief The protection metadata wrapper - */ - std::unique_ptr m_protectionMetadataWrapper; - - /** - * @brief The object used to check flushing state for all sources - */ - std::unique_ptr m_flushWatcher; - - /** - * @brief The object used to check if NeedData is scheduled for given source - */ - NeedDataMapping m_scheduledNeedDatas; -}; - -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_GENERIC_PLAYER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstInitialiser.h b/middleware/rialto-client/media/server/gstplayer/include/GstInitialiser.h deleted file mode 100644 index 6ea8ba147..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstInitialiser.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_INITIALISER_H_ -#define FIREBOLT_RIALTO_SERVER_GST_INITIALISER_H_ - -#include "IGstInitialiser.h" -#include "IGstWrapper.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class GstInitialiser : public IGstInitialiser -{ -public: - GstInitialiser() = default; - ~GstInitialiser(); - - void initialise(int *argc, char ***argv) override; - void waitForInitialisation() const override; - -private: - bool m_isInitialised{false}; - mutable std::mutex m_mutex; - mutable std::condition_variable m_cv; - std::thread m_thread; - std::shared_ptr m_gstWrapper; -}; -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_INITIALISER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstLogForwarding.h b/middleware/rialto-client/media/server/gstplayer/include/GstLogForwarding.h deleted file mode 100644 index 2744995fb..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstLogForwarding.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_LOG_FORWARDING_H_ -#define FIREBOLT_RIALTO_SERVER_GST_LOG_FORWARDING_H_ - -namespace firebolt::rialto::server -{ -void enableGstLogForwarding(); -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_LOG_FORWARDING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstMimeMapping.h b/middleware/rialto-client/media/server/gstplayer/include/GstMimeMapping.h deleted file mode 100644 index bb8e63bef..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstMimeMapping.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_MIME_MAPPING_H_ -#define FIREBOLT_RIALTO_SERVER_GST_MIME_MAPPING_H_ - -#include "GstCapabilities.h" -#include "IGstWrapper.h" -#include "IMediaPipeline.h" -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ - -/** - * @brief Converts MIME types to simple caps. - * - * @param[in] m_gstWrapper : Member variable that is a shared pointer to an object of type IGstWrapper - * @param[in] m_attachedSource : A const reference to an object of type MediaSource - * - * @retval the pointer to the GstCaps object, which represents the simple caps for the given MIME type. If MIME type is - * not found, an empty GstCaps object is returned - */ - -inline GstCaps *createSimpleCapsFromMimeType(std::shared_ptr m_gstWrapper, - const IMediaPipeline::MediaSource &m_attachedSource) -{ - static const std::unordered_map mimeToMediaType = - {{"video/h264", "video/x-h264"}, {"video/h265", "video/x-h265"}, - {"video/x-av1", "video/x-av1"}, {"video/x-vp9", "video/x-vp9"}, - {"video/mp4", "video/mpeg"}, {"audio/mp4", "audio/mpeg"}, - {"audio/mp3", "audio/mpeg"}, {"audio/aac", "audio/mpeg"}, - {"audio/x-eac3", "audio/x-eac3"}, {"audio/x-opus", "audio/x-opus"}, - {"audio/b-wav", "audio/b-wav"}, {"audio/x-raw", "audio/x-raw"}, - {"audio/x-flac", "audio/x-flac"}, {"text/vtt", "application/x-subtitle-vtt"}, - {"text/ttml", "application/ttml+xml"}, {"text/cc", "subtitle/x-subtitle-cc"}}; - auto mimeToMediaTypeIt = mimeToMediaType.find(m_attachedSource.getMimeType()); - if (mimeToMediaTypeIt != mimeToMediaType.end()) - { - return m_gstWrapper->gstCapsNewEmptySimple(mimeToMediaTypeIt->second.c_str()); - } - - return m_gstWrapper->gstCapsNewEmpty(); -} - -/** - * @brief Converts simple caps to MIME types. - * - * @param[in] supportedCaps : A const reference to a vector of pointers to GstCaps objects representing the supported caps - * @param[in] m_gstWrapper : Member variable that is a shared pointer to an object of type IGstWrapper - * - * @retval an unordered set of strings representing the supported MIME types - */ - -inline std::unordered_set -convertFromCapsVectorToMimeSet(const std::vector &supportedCaps, - std::shared_ptr m_gstWrapper) -{ - std::vector>> capsToMimeVec = - {{m_gstWrapper->gstCapsFromString("audio/mpeg, mpegversion=(int)4"), {"audio/mp4", "audio/aac", "audio/x-eac3"}}, - {m_gstWrapper->gstCapsFromString("audio/mpeg, mpegversion=(int)1, layer=(int)3"), {"audio/mp3"}}, - {m_gstWrapper->gstCapsFromString("audio/x-eac3"), {"audio/x-eac3"}}, - {m_gstWrapper->gstCapsFromString("audio/b-wav"), {"audio/b-wav"}}, - {m_gstWrapper->gstCapsFromString("audio/x-raw"), {"audio/x-raw"}}, - {m_gstWrapper->gstCapsFromString("audio/x-opus"), {"audio/x-opus"}}, - {m_gstWrapper->gstCapsFromString("audio/x-opus, channel-mapping-family=(int)0"), {"audio/x-opus"}}, - {m_gstWrapper->gstCapsFromString("audio/x-flac"), {"audio/x-flac"}}, - {m_gstWrapper->gstCapsFromString("video/x-av1"), {"video/x-av1"}}, - {m_gstWrapper->gstCapsFromString("video/x-h264"), {"video/h264"}}, - {m_gstWrapper->gstCapsFromString("video/x-h265"), {"video/h265"}}, - {m_gstWrapper->gstCapsFromString("video/x-vp9"), {"video/x-vp9"}}, - {m_gstWrapper->gstCapsFromString("video/mpeg, mpegversion=(int)4"), {"video/mp4"}}, - {m_gstWrapper->gstCapsFromString("video/x-h264(memory:DMABuf)"), {"video/h264"}}, - {m_gstWrapper->gstCapsFromString("video/x-h265(memory:DMABuf)"), {"video/h265"}}, - {m_gstWrapper->gstCapsFromString("video/x-av1(memory:DMABuf)"), {"video/x-av1"}}, - {m_gstWrapper->gstCapsFromString("video/x-vp9(memory:DMABuf)"), {"video/x-vp9"}}}; - - std::unordered_set supportedMimes; - - for (GstCaps *caps : supportedCaps) - { - for (const auto &capsToMime : capsToMimeVec) - { - if (m_gstWrapper->gstCapsCanIntersect(capsToMime.first, caps)) - { - supportedMimes.insert(capsToMime.second.begin(), capsToMime.second.end()); - } - } - } - - for (auto &capsToMime : capsToMimeVec) - { - if (capsToMime.first) - m_gstWrapper->gstCapsUnref(capsToMime.first); - } - - return supportedMimes; -} - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_MIME_MAPPING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadata.h b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadata.h deleted file mode 100644 index 28769bef0..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadata.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_H_ // NOLINT(build/header_guard) -#define FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_H_ - -#include "IDecryptionService.h" -#include - -G_BEGIN_DECLS - -#define GST_RIALTO_PROTECTION_METADATA_GET_TYPE (rialto_eme_protection_metadata_get_type()) -#define GST_RIALTO_PROTECTION_METADATA_INFO (rialto_mse_protection_metadata_get_info()) - -struct GstRialtoProtectionData -{ - int32_t keySessionId = 0; - uint32_t subsampleCount = 0; - uint32_t initWithLast15 = 0; - GstBuffer *key = nullptr; - GstBuffer *iv = nullptr; - GstBuffer *subsamples = nullptr; - firebolt::rialto::CipherMode cipherMode = firebolt::rialto::CipherMode::UNKNOWN; - uint32_t crypt = 0; - uint32_t skip = 0; - bool encryptionPatternSet = false; - firebolt::rialto::server::IDecryptionService *decryptionService = nullptr; -}; - -struct _GstRialtoProtectionMetadata -{ - GstMeta parent; - GstRialtoProtectionData data; -}; - -typedef struct _GstRialtoProtectionMetadata GstRialtoProtectionMetadata; - -GType rialto_eme_protection_metadata_get_type(); // NOLINT(build/function_format) -const GstMetaInfo *rialto_mse_protection_metadata_get_info(); // NOLINT(build/function_format) -G_END_DECLS - -#endif // FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelper.h b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelper.h deleted file mode 100644 index 5b7b4a368..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelper.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_H_ -#define FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_H_ - -#include "IGstProtectionMetadataHelper.h" -#include "IGstWrapper.h" -#include - -namespace firebolt::rialto::server -{ -class GstProtectionMetadataHelper : public IGstProtectionMetadataHelper -{ -public: - explicit GstProtectionMetadataHelper(const std::shared_ptr &gstWrapper) - : m_gstWrapper(gstWrapper) - { - } - ~GstProtectionMetadataHelper() override = default; - GstMeta *addProtectionMetadata(GstBuffer *gstBuffer, GstRialtoProtectionData &data) override; - GstRialtoProtectionData *getProtectionMetadataData(GstBuffer *gstBuffer) override; - void removeProtectionMetadata(GstBuffer *gstBuffer) override; - -private: - /** - * @brief The gstreamer wrapper object. - */ - std::shared_ptr m_gstWrapper; -}; -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelperFactory.h b/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelperFactory.h deleted file mode 100644 index 9ad92324f..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstProtectionMetadataHelperFactory.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ - -#include "IGstProtectionMetadataHelperFactory.h" -#include - -namespace firebolt::rialto::server -{ -/** - * @brief GstProtectionMetadataHelperFactory factory class, for the creation of a GstProtectionMetadataHelper. - */ -class GstProtectionMetadataHelperFactory : public IGstProtectionMetadataHelperFactory -{ -public: - GstProtectionMetadataHelperFactory() = default; - ~GstProtectionMetadataHelperFactory() override = default; - - std::unique_ptr createProtectionMetadataWrapper( - const std::shared_ptr &gstWrapper) const override; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstRialtoTextTrackSinkPrivate.h b/middleware/rialto-client/media/server/gstplayer/include/GstRialtoTextTrackSinkPrivate.h deleted file mode 100644 index 859e97988..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstRialtoTextTrackSinkPrivate.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_RIALTO_TEXT_TRACK_SINK_PRIVATE_H_ -#define FIREBOLT_RIALTO_SERVER_GST_RIALTO_TEXT_TRACK_SINK_PRIVATE_H_ - -#include "ITextTrackSession.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -struct GstRialtoTextTrackSinkPrivate -{ - std::unique_ptr m_textTrackSession; - std::atomic m_isMuted{false}; - std::string m_textTrackIdentifier; - uint64_t m_videoDecoderIdentifier{0}; - bool m_capsSet{false}; - std::optional m_position; - std::optional m_queuedPosition; - std::optional m_offset; - std::optional m_queuedOffset; - std::mutex m_mutex; -}; -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_RIALTO_TEXT_TRACK_SINK_PRIVATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstSrc.h b/middleware/rialto-client/media/server/gstplayer/include/GstSrc.h deleted file mode 100644 index b795c49b4..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstSrc.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_SRC_H_ -#define FIREBOLT_RIALTO_SERVER_GST_SRC_H_ - -#include "IGlibWrapper.h" -#include "IGstDecryptorElementFactory.h" -#include "IGstSrc.h" -#include "IGstWrapper.h" - -#include -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define GST_RIALTO_TYPE_SRC (gst_rialto_src_get_type()) -#define GST_RIALTO_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_RIALTO_TYPE_SRC, GstRialtoSrc)) -#define GST_RIALTO_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST((klass), GST_RIALTO_TYPE_SRC, GstRialtoSrcClass)) -#define GST_IS_RIALTO_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_RIALTO_TYPE_SRC)) -#define GST_IS_RIALTO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_RIALTO_TYPE_SRC)) - -typedef struct _GstRialtoSrc GstRialtoSrc; -typedef struct _GstRialtoSrcClass GstRialtoSrcClass; -typedef struct _GstRialtoSrcPrivate GstRialtoSrcPrivate; - -struct _GstRialtoSrc -{ - GstBin parent; - GstRialtoSrcPrivate *priv; -}; - -struct _GstRialtoSrcClass -{ - GstBinClass parentClass; -}; - -GType gst_rialto_src_get_type(void); // NOLINT(build/function_format) - -struct _GstRialtoSrcPrivate -{ - gchar *uri; - guint appsrc_count; - gboolean async_start; - gboolean async_done; -}; - -enum -{ - PROP_0, - PROP_LOCATION -}; - -G_END_DECLS - -namespace firebolt::rialto::server -{ -/** - * @brief IGstSrc factory class definition. - */ -class GstSrcFactory : public IGstSrcFactory -{ -public: - /** - * @brief Weak pointer to the singleton factroy object. - */ - static std::weak_ptr m_factory; - - /** - * @brief Weak pointer to the singleton object. - */ - static std::weak_ptr m_gstSrc; - - /** - * @brief Mutex protection for creation of the GstSrc object. - */ - static std::mutex m_creationMutex; - - std::shared_ptr getGstSrc() override; -}; - -/** - * @brief The definition of the GstSrc. - */ -class GstSrc : public IGstSrc -{ -public: - /** - * @brief The constructor. - * - * @param[in] gstWrapperFactory : The gstreamer wrapper factory. - * @param[in] glibWrapperFactory : The glib wrapper factory. - * @param[in] decryptorFactory : The decryptor factory. - */ - GstSrc(const std::shared_ptr &gstWrapperFactory, - const std::shared_ptr &glibWrapperFactory, - const std::shared_ptr &decryptorFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~GstSrc() {} - - void initSrc() override; - - void setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, - GstAppSrcCallbacks *callbacks, gpointer userData, - firebolt::rialto::MediaSourceType type) override; - - void allAppSrcsAdded(GstElement *element) override; - -protected: - /* - * @brief sets the default stream format if needed. - */ - void setDefaultStreamFormatIfNeeded(GstElement *appSrc); - - /** - * @brief The gstreamer wrapper object. - */ - std::shared_ptr m_gstWrapper; - - /** - * @brief The glib wrapper object. - */ - std::shared_ptr m_glibWrapper; - - /** - * @brief The gst decryptor element factory object. - */ - std::shared_ptr m_decryptorFactory; - - /** - * @brief Create a payloader element. - * - * @retval the payloader element. - */ - GstElement *createPayloader(); -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_SRC_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstTextTrackSinkFactory.h b/middleware/rialto-client/media/server/gstplayer/include/GstTextTrackSinkFactory.h deleted file mode 100644 index 34c2b8a58..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstTextTrackSinkFactory.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_TEXT_TRACK_SINK_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_GST_TEXT_TRACK_SINK_FACTORY_H_ - -#include "IGstTextTrackSinkFactory.h" -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IGstTextTrackSink factory class definition. - */ -class GstTextTrackSinkFactory : public IGstTextTrackSinkFactory -{ -public: - GstTextTrackSinkFactory() = default; - ~GstTextTrackSinkFactory() override = default; - - GstElement *createGstTextTrackSink() const override; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_TEXT_TRACK_SINK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/GstWebAudioPlayer.h b/middleware/rialto-client/media/server/gstplayer/include/GstWebAudioPlayer.h deleted file mode 100644 index f32f05b75..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/GstWebAudioPlayer.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GST_WEB_AUDIO_PLAYER_H_ -#define FIREBOLT_RIALTO_SERVER_GST_WEB_AUDIO_PLAYER_H_ - -#include "IGlibWrapper.h" -#include "IGstDispatcherThread.h" -#include "IGstDispatcherThreadClient.h" -#include "IGstInitialiser.h" -#include "IGstSrc.h" -#include "IGstWebAudioPlayer.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IWorkerThread.h" -#include "WebAudioPlayerContext.h" -#include "tasks/IPlayerTask.h" -#include "tasks/IWebAudioPlayerTaskFactory.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IGstWebAudioPlayer factory class definition. - */ -class GstWebAudioPlayerFactory : public IGstWebAudioPlayerFactory -{ -public: - /** - * @brief Weak pointer to the singleton factory object. - */ - static std::weak_ptr m_factory; - - std::unique_ptr createGstWebAudioPlayer(IGstWebAudioPlayerClient *client, - const uint32_t priority) override; -}; - -/** - * @brief The definition of the GstWebAudioPlayer. - */ -class GstWebAudioPlayer : public IGstWebAudioPlayer, public IGstWebAudioPlayerPrivate, public IGstDispatcherThreadClient -{ -public: - /** - * @brief The constructor. - * - * @param[in] client : The gstreamer player client. - * @param[in] priority : Priority value for this pipeline. - * @param[in] gstWrapper : The gstreamer wrapper. - * @param[in] glibWrapper : The glib wrapper. - * @param[in] gstInitialiser : The gst initialiser - * @param[in] gstSrcFactory : The gstreamer rialto src factory. - * @param[in] taskFactory : The task factory - * @param[in] workerThreadFactory : The worker thread factory - * @param[in] gstDispatcherThreadFactory : The gst dispatcher thread factory - */ - GstWebAudioPlayer(IGstWebAudioPlayerClient *client, const uint32_t priority, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const IGstInitialiser &gstInitialiser, const std::shared_ptr &gstSrcFactory, - std::unique_ptr taskFactory, - std::unique_ptr workerThreadFactory, - std::unique_ptr gstDispatcherThreadFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~GstWebAudioPlayer(); - - void setCaps(const std::string &audioMimeType, std::weak_ptr config) override; - void play() override; - void pause() override; - void setVolume(double volume) override; - bool getVolume(double &volume) override; - uint32_t writeBuffer(uint8_t *mainPtr, uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength) override; - void setEos() override; - uint64_t getQueuedBytes() override; - - bool changePipelineState(GstState newState) override; - void stopWorkerThread() override; - void handleBusMessage(GstMessage *message, bool priority) override; - void ping(std::unique_ptr &&heartbeatHandler) override; - -private: - /** - * @brief Initialises the player pipeline for WebAudio playback. - * - * @param[in] priority : Priority value for this pipeline. - * - * @retval true on success false otherwise. - */ - bool initWebAudioPipeline(const uint32_t priority); - - /** - * @brief Creates a amlhalasink audio sink element and adds it to the pipeline. - * - * @retval constructed sink element or nullptr on failure. - */ - GstElement *createAmlhalaSink(); - - /** - * @brief Creates a rtkaudiosink audio sink element and adds it to the pipeline. - * - * @retval constructed sink element or nullptr on failure. - */ - GstElement *createRtkAudioSink(); - - /** - * @brief Creates a autoaudiosink sink element and adds it to the pipeline. - * - * @retval constructed sink element or nullptr on failure. - */ - GstElement *createAutoSink(); - - /** - * @brief Links the sink, audio convert and audio resample to the src. - * - * @param[in] sink : The constructed sink to link to the src. - * - * @retval true on success false otherwise. - */ - bool linkElementsToSrc(GstElement *sink); - - /** - * @brief Terminates the player pipeline for WebAudio playback. - */ - void termWebAudioPipeline(); - - /** - * @brief Shutdown and destroys the worker thread. - */ - void resetWorkerThread(); - -private: - /** - * @brief The player context. - */ - WebAudioPlayerContext m_context; - - /** - * @brief The gstreamer player client. - */ - IGstWebAudioPlayerClient *m_gstPlayerClient{nullptr}; - - /** - * @brief The gstreamer wrapper object. - */ - std::shared_ptr m_gstWrapper; - - /** - * @brief The glib wrapper object. - */ - std::shared_ptr m_glibWrapper; - - /** - * @brief Thread for handling player tasks. - */ - std::unique_ptr m_workerThread; - - /** - * @brief Thread for handling gst bus callbacks - */ - std::unique_ptr m_gstDispatcherThread; - - /** - * @brief The GstWebAudioPlayer task factory - */ - std::unique_ptr m_taskFactory; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GST_WEB_AUDIO_PLAYER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IFlushWatcher.h b/middleware/rialto-client/media/server/gstplayer/include/IFlushWatcher.h deleted file mode 100644 index c469f6950..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IFlushWatcher.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_FLUSH_WATCHER_H_ -#define FIREBOLT_RIALTO_SERVER_I_FLUSH_WATCHER_H_ - -#include "MediaCommon.h" - -namespace firebolt::rialto::server -{ -class IFlushWatcher -{ -public: - virtual ~IFlushWatcher() = default; - - virtual void setFlushing(const MediaSourceType &type, bool async) = 0; - virtual void setFlushed(const MediaSourceType &type) = 0; - virtual bool isFlushOngoing() const = 0; - virtual bool isAsyncFlushOngoing() const = 0; -}; -} // namespace firebolt::rialto::server -#endif // FIREBOLT_RIALTO_SERVER_I_FLUSH_WATCHER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstDecryptorElementFactory.h b/middleware/rialto-client/media/server/gstplayer/include/IGstDecryptorElementFactory.h deleted file mode 100644 index 32fed9597..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstDecryptorElementFactory.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_DECRYPTOR_ELEMENT_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_DECRYPTOR_ELEMENT_FACTORY_H_ - -#include "IDecryptionService.h" -#include "IGstWrapper.h" -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IGstDecryptorElement factory class, for the creation of a GstDecryptorElement. - */ -class IGstDecryptorElementFactory -{ -public: - IGstDecryptorElementFactory() = default; - virtual ~IGstDecryptorElementFactory() = default; - - /** - * @brief Creates a IGstDecryptorElementFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a IGstDecryptorElement. - * - * @param[in] decryptionService : The service used to decrypt frames. - * @param[in] gstWrapper : The gstreamer wrapper. - * - * @retval a decryptor element instance or null on error. - */ - virtual GstElement * - createDecryptorElement(const gchar *name, firebolt::rialto::server::IDecryptionService *decryptionService, - const std::shared_ptr &gstWrapper) const = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_DECRYPTOR_ELEMENT_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThread.h b/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThread.h deleted file mode 100644 index ce3d93c3f..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThread.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_H_ - -#include "IGstDispatcherThreadClient.h" -#include "IGstWrapper.h" -#include - -namespace firebolt::rialto::server -{ -class IGstDispatcherThread; - -class IGstDispatcherThreadFactory -{ -public: - IGstDispatcherThreadFactory() = default; - virtual ~IGstDispatcherThreadFactory() = default; - - virtual std::unique_ptr - createGstDispatcherThread(IGstDispatcherThreadClient &client, GstElement *pipeline, - const std::shared_ptr &gstWrapper) const = 0; -}; - -class IGstDispatcherThread -{ -public: - IGstDispatcherThread() = default; - virtual ~IGstDispatcherThread() = default; - - IGstDispatcherThread(const IGstDispatcherThread &) = delete; - IGstDispatcherThread(IGstDispatcherThread &&) = delete; - IGstDispatcherThread &operator=(const IGstDispatcherThread &) = delete; - IGstDispatcherThread &operator=(IGstDispatcherThread &&) = delete; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThreadClient.h b/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThreadClient.h deleted file mode 100644 index 5a945239b..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstDispatcherThreadClient.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_CLIENT_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_CLIENT_H_ - -#include - -namespace firebolt::rialto::server -{ -class IGstDispatcherThreadClient -{ -public: - IGstDispatcherThreadClient() = default; - virtual ~IGstDispatcherThreadClient() = default; - - IGstDispatcherThreadClient(const IGstDispatcherThreadClient &) = delete; - IGstDispatcherThreadClient(IGstDispatcherThreadClient &&) = delete; - IGstDispatcherThreadClient &operator=(const IGstDispatcherThreadClient &) = delete; - IGstDispatcherThreadClient &operator=(IGstDispatcherThreadClient &&) = delete; - - /** - * @brief Callback on a new bus message. - * - * @param[in] message : The new Gst message. - */ - virtual void handleBusMessage(GstMessage *message, bool priority) = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_DISPATCHER_THREAD_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstGenericPlayerPrivate.h b/middleware/rialto-client/media/server/gstplayer/include/IGstGenericPlayerPrivate.h deleted file mode 100644 index 44af949c2..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstGenericPlayerPrivate.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_PRIVATE_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_PRIVATE_H_ - -#include "IMediaPipeline.h" - -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IGstGenericPlayerPrivate -{ -public: - IGstGenericPlayerPrivate() = default; - virtual ~IGstGenericPlayerPrivate() = default; - - IGstGenericPlayerPrivate(const IGstGenericPlayerPrivate &) = delete; - IGstGenericPlayerPrivate &operator=(const IGstGenericPlayerPrivate &) = delete; - IGstGenericPlayerPrivate(IGstGenericPlayerPrivate &&) = delete; - IGstGenericPlayerPrivate &operator=(IGstGenericPlayerPrivate &&) = delete; - - /** - * @brief Schedules need media data task. Called by the worker thread. - */ - virtual void scheduleNeedMediaData(GstAppSrc *src) = 0; - - /** - * @brief Schedules enough data task. Called by the worker thread. - */ - virtual void scheduleEnoughData(GstAppSrc *src) = 0; - - /** - * @brief Schedules audio underflow task. Called by the worker thread. - */ - virtual void scheduleAudioUnderflow() = 0; - - /** - * @brief Schedules video underflow task. Called by the worker thread. - */ - virtual void scheduleVideoUnderflow() = 0; - - /** - * @brief Schedules all sources attached task. Called by the worker thread. - */ - virtual void scheduleAllSourcesAttached() = 0; - - /** - * @brief Sets video sink rectangle. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setVideoSinkRectangle() = 0; - - /** - * @brief Sets immediate output. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setImmediateOutput() = 0; - - /** - * @brief Sets the low latency property. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setLowLatency() = 0; - - /** - * @brief Sets the sync property. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setSync() = 0; - - /** - * @brief Sets the sync off property. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setSyncOff() = 0; - - /** - * @brief Sets the stream sync mode property. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setStreamSyncMode(const MediaSourceType &type) = 0; - - /** - * @brief Sets frame rendering. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setRenderFrame() = 0; - - /** - * @brief Sets buffering limit. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setBufferingLimit() = 0; - - /** - * @brief Sets use buffering. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setUseBuffering() = 0; - - /** - * @brief Sets Show Video Window property. Called by the worker thread. - * - * @retval true on success. - */ - virtual bool setShowVideoWindow() = 0; - - /** - * @brief Sends NeedMediaData notification. Called by the worker thread. - */ - virtual void notifyNeedMediaData(const MediaSourceType mediaSource) = 0; - - /** - * @brief Constructs a new buffer with data from media segment. Does not perform decryption. - * Called by the worker thread. - */ - virtual GstBuffer *createBuffer(const IMediaPipeline::MediaSegment &mediaSegment) const = 0; - - virtual void attachData(const firebolt::rialto::MediaSourceType mediaType) = 0; - - /** - * @brief Checks the new audio mediaSegment metadata and updates the caps accordingly. - */ - virtual void updateAudioCaps(int32_t rate, int32_t channels, const std::shared_ptr &codecData) = 0; - - /** - * @brief Checks the new video mediaSegment metadata and updates the caps accordingly. - */ - virtual void updateVideoCaps(int32_t width, int32_t height, Fraction frameRate, - const std::shared_ptr &codecData) = 0; - - /** - * @brief Adds clipping meta to the audio buffer. - * - * @param buffer the buffer to add the clipping meta to - * @param clippingStart the start of the clipping - * @param clippingEnd the end of the clipping - */ - virtual void addAudioClippingToBuffer(GstBuffer *buffer, uint64_t clippingStart, uint64_t clippingEnd) const = 0; - - /** - * @brief Changes pipeline state. - * - * @param[in] newState : The desired state. - * - * @retval true on success. - */ - virtual bool changePipelineState(GstState newState) = 0; - - /** - * @brief Gets the current position of the element - * - * @param[in] element : The GstElement to check. - * - * @retval position of the element; -1 in case of failure - */ - virtual int64_t getPosition(GstElement *element) = 0; - - /** - * @brief Starts position reporting and check audio underflow. Called by the worker thread. - */ - virtual void startPositionReportingAndCheckAudioUnderflowTimer() = 0; - - /** - * @brief Stops position reporting and check audio underflow. Called by the worker thread. - */ - virtual void stopPositionReportingAndCheckAudioUnderflowTimer() = 0; - - /** - * @brief Starts subtitle clock resync. Called by the worker thread. - */ - virtual void startSubtitleClockResyncTimer() = 0; - - /** - * @brief Stops subtitle clock resync. Called by the worker thread. - */ - virtual void stopSubtitleClockResyncTimer() = 0; - - /** - * @brief Stops worker thread. Called by the worker thread. - */ - virtual void stopWorkerThread() = 0; - - /** - * @brief Restores playback after underflow. Called by the worker thread. - * - * @param[in] underflowFlag : The audio or video underflow flag to be cleared. - */ - virtual void cancelUnderflow(firebolt::rialto::MediaSourceType mediaSource) = 0; - - /** - * @brief Sets pending playback rate after reaching PLAYING state - * - */ - virtual void setPendingPlaybackRate() = 0; - - /** - * @brief Updates Playback Group in PlayerContext. - */ - virtual void updatePlaybackGroup(GstElement *typefind, const GstCaps *caps) = 0; - - /** - * @brief Notification that a new child element has been added to the autovideosink. - * Stores the child video sink in the player context. - * - * @param[in] object : Element added to the autovideosink. - */ - virtual void addAutoVideoSinkChild(GObject *object) = 0; - - /** - * @brief Notification that a new child element has been added to the autoaudiosink. - * Stores the child audio sink in the player context. - * - * @param[in] object : Element added to the autoaudiosink. - */ - virtual void addAutoAudioSinkChild(GObject *object) = 0; - - /** - * @brief Notification that a child element has been removed from the autovideosink. - * Removes the child video sink in the player context if it has been stored. - * - * @param[in] object : Element removed from the autovideosink. - */ - virtual void removeAutoVideoSinkChild(GObject *object) = 0; - - /** - * @brief Notification that a child element has been removed from the autoaudiosink. - * Removes the child audio sink in the player context if it has been stored. - * - * @param[in] object : Element removed from the autoaudiosink. - */ - virtual void removeAutoAudioSinkChild(GObject *object) = 0; - - /** - * @brief Gets the sink element for source type. - * - * @param[in] mediaSourceType : the source type to obtain the sink for - * - * @retval The sink, NULL if not found. Please call getObjectUnref() if it's non-null - */ - virtual GstElement *getSink(const MediaSourceType &mediaSourceType) const = 0; - - /** - * @brief Sets the audio and video flags on the pipeline based on the input. - * - * @param[in] enableAudio : Whether to enable audio flags. - */ - virtual void setPlaybinFlags(bool enableAudio) = 0; - - /** - * @brief Pushes GstSample if playback position has changed or new segment needs to be sent. - * - * @param[in] source : The Gst Source element, that should receive new sample - * @param[in] typeStr : The media source type string - */ - virtual void pushSampleIfRequired(GstElement *source, const std::string &typeStr) = 0; - - /** - * @brief Reattaches source (or switches it) - * - * @param[in] source : The new media source - * - * @retval True on success - */ - virtual bool reattachSource(const std::unique_ptr &source) = 0; - - /** - * @brief Checks if the player has a source of the given type. - * - * @param[in] mediaSourceType : The source type to check - * - * @retval True if the player has a source of the given type, false otherwise - */ - virtual bool hasSourceType(const MediaSourceType &mediaSourceType) const = 0; - - /** - * @brief Sets source state flushed - * - * @param[in] mediaSourceType : the source type that has been flushed - */ - virtual void setSourceFlushed(const MediaSourceType &mediaSourceType) = 0; - - /** - * @brief Clears need data scheduled flag - * - * @param[in] src : the app source - */ - virtual void clearNeedDataScheduled(GstAppSrc *src) = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_PRIVATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelper.h b/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelper.h deleted file mode 100644 index daad25344..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelper.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_H_ - -#include "GstProtectionMetadata.h" - -namespace firebolt::rialto::server -{ -class IGstProtectionMetadataHelper -{ -public: - IGstProtectionMetadataHelper() = default; - virtual ~IGstProtectionMetadataHelper() = default; - virtual GstMeta *addProtectionMetadata(GstBuffer *gstBuffer, GstRialtoProtectionData &data) = 0; - virtual GstRialtoProtectionData *getProtectionMetadataData(GstBuffer *gstBuffer) = 0; - virtual void removeProtectionMetadata(GstBuffer *gstBuffer) = 0; -}; -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelperFactory.h b/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelperFactory.h deleted file mode 100644 index af872d8e9..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstProtectionMetadataHelperFactory.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ - -#include "IDecryptionService.h" -#include "IGstProtectionMetadataHelper.h" -#include "IGstWrapper.h" -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IGstProtectionMetadataHelperFactory factory class, for the creation of a GstProtectionMetadataHelper. - */ -class IGstProtectionMetadataHelperFactory -{ -public: - IGstProtectionMetadataHelperFactory() = default; - virtual ~IGstProtectionMetadataHelperFactory() = default; - - /** - * @brief Creates a IGstProtectionMetadataHelperFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a IGstProtectionMetadataHelperFactory. - * - * @retval a decryptor element instance or null on error. - */ - virtual std::unique_ptr - createProtectionMetadataWrapper(const std::shared_ptr &gstWrapper) const = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_PROTECTION_METADATA_HELPER_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstSrc.h b/middleware/rialto-client/media/server/gstplayer/include/IGstSrc.h deleted file mode 100644 index 97b443934..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstSrc.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_SRC_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_SRC_H_ - -#include "IDecryptionService.h" -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IGstSrc; - -/** - * @brief IGstSrc factory class, for the IGstSrc singleton object. - */ -class IGstSrcFactory -{ -public: - IGstSrcFactory() = default; - virtual ~IGstSrcFactory() = default; - - /** - * @brief Gets the IGstSrcFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Gets a IGstSrc singleton object. - * - * @retval the src instance or null on error. - */ - virtual std::shared_ptr getGstSrc() = 0; -}; - -/** - * @brief Structure used for stream info - */ -struct StreamInfo -{ - explicit StreamInfo(GstElement *appSrc_ = nullptr, bool hasDrm_ = true) : appSrc(appSrc_), hasDrm(hasDrm_) {} - bool operator==(const StreamInfo &other) const - { - return appSrc == other.appSrc && hasDrm == other.hasDrm && isDataNeeded == other.isDataNeeded && - isNeedDataPending == other.isNeedDataPending && isDataPushed == other.isDataPushed; - } - GstElement *appSrc; - bool hasDrm; - bool isDataNeeded{false}; - bool isNeedDataPending{false}; - bool isDataPushed{false}; - std::list buffers{}; - bool underflowOccured{false}; -}; -/** - * @brief Definition of a stream info map. - */ -using StreamInfoMap = std::unordered_map; - -class IGstSrc -{ -public: - IGstSrc() = default; - virtual ~IGstSrc() = default; - - IGstSrc(const IGstSrc &) = delete; - IGstSrc &operator=(const IGstSrc &) = delete; - IGstSrc(IGstSrc &&) = delete; - IGstSrc &operator=(IGstSrc &&) = delete; - - /** - * @brief Initalise rialto src. - */ - virtual void initSrc() = 0; - - /** - * @brief Sets up the app source. - * - * @param[in] source : The source element. - * @param[in] appsrc : The app source to attach. - * @param[in] callbacks : Callbacks to be set on the app source. - * @param[in] userData : Data to be passed to the callbacks. - * @param[in] type : The media type of the source. - */ - virtual void setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, - GstAppSrcCallbacks *callbacks, gpointer userData, - firebolt::rialto::MediaSourceType type) = 0; - - /** - * @brief Notify rialto source that all app sources have been added. - * - * @param[in] element : The source element. - */ - virtual void allAppSrcsAdded(GstElement *element) = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_SRC_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstTextTrackSinkFactory.h b/middleware/rialto-client/media/server/gstplayer/include/IGstTextTrackSinkFactory.h deleted file mode 100644 index 9a9c52b06..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstTextTrackSinkFactory.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_TEXT_TRACK_SINK_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_TEXT_TRACK_SINK_FACTORY_H_ - -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IGstTextTrackSinkFactory factory class, for the creation of a GstTextTrackSink. - */ -class IGstTextTrackSinkFactory -{ -public: - IGstTextTrackSinkFactory() = default; - virtual ~IGstTextTrackSinkFactory() = default; - - /** - * @brief Creates a IGstTextTrackSinkFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a GstTextTrackSink. - * - * @param[in] gstWrapper : The gstreamer wrapper. - * - * @retval an element instance or null on error. - */ - virtual GstElement *createGstTextTrackSink() const = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_TEXT_TRACK_SINK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h b/middleware/rialto-client/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h deleted file mode 100644 index c147dcd4f..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IGstWebAudioPlayerPrivate.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_PRIVATE_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_PRIVATE_H_ - -#include - -namespace firebolt::rialto::server -{ -class IGstWebAudioPlayerPrivate -{ -public: - IGstWebAudioPlayerPrivate() = default; - virtual ~IGstWebAudioPlayerPrivate() = default; - - IGstWebAudioPlayerPrivate(const IGstWebAudioPlayerPrivate &) = delete; - IGstWebAudioPlayerPrivate &operator=(const IGstWebAudioPlayerPrivate &) = delete; - IGstWebAudioPlayerPrivate(IGstWebAudioPlayerPrivate &&) = delete; - IGstWebAudioPlayerPrivate &operator=(IGstWebAudioPlayerPrivate &&) = delete; - - /** - * @brief Changes pipeline state. - * - * @param[in] newState : The desired state. - * - * @retval true on success. - */ - virtual bool changePipelineState(GstState newState) = 0; - - /** - * @brief Stops worker thread. Called by the worker thread. - */ - virtual void stopWorkerThread() = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_PRIVATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/IWorkerThread.h b/middleware/rialto-client/media/server/gstplayer/include/IWorkerThread.h deleted file mode 100644 index 9ea65b8a0..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/IWorkerThread.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_WORKER_THREAD_H_ -#define FIREBOLT_RIALTO_SERVER_I_WORKER_THREAD_H_ - -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server -{ -class IWorkerThread; -class IWorkerThreadFactory -{ -public: - IWorkerThreadFactory() = default; - virtual ~IWorkerThreadFactory() = default; - - virtual std::unique_ptr createWorkerThread() const = 0; -}; - -class IWorkerThread -{ -public: - IWorkerThread() = default; - virtual ~IWorkerThread() = default; - IWorkerThread(const IWorkerThread &) = delete; - IWorkerThread(IWorkerThread &&) = delete; - IWorkerThread &operator=(const IWorkerThread &) = delete; - IWorkerThread &operator=(IWorkerThread &&) = delete; - - /** - * @brief Stops the task thread - */ - virtual void stop() = 0; - - /** - * @brief Joins the task thread - */ - virtual void join() = 0; - - /** - * @brief Queues a task in the task queue. - */ - virtual void enqueueTask(std::unique_ptr &&task) = 0; - virtual void enqueuePriorityTask(std::unique_ptr &&task) = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_WORKER_THREAD_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/NeedDataMapping.h b/middleware/rialto-client/media/server/gstplayer/include/NeedDataMapping.h deleted file mode 100644 index 6cb0a7fef..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/NeedDataMapping.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_NEED_DATA_MAPPING_H_ -#define FIREBOLT_RIALTO_SERVER_NEED_DATA_MAPPING_H_ - -#include -#include -#include - -namespace firebolt::rialto::server -{ -class NeedDataMapping -{ -public: - NeedDataMapping() = default; - ~NeedDataMapping() = default; - NeedDataMapping(const NeedDataMapping &) = delete; - NeedDataMapping(NeedDataMapping &&) = delete; - NeedDataMapping &operator=(const NeedDataMapping &) = delete; - NeedDataMapping &operator=(NeedDataMapping &&) = delete; - - bool isNeedDataScheduled(GstAppSrc *src) const; - void setNeedDataScheduled(GstAppSrc *src); - void clearNeedDataScheduled(GstAppSrc *src); - -private: - mutable std::mutex m_mutex; - std::set m_scheduledNeedDatas; -}; -} // namespace firebolt::rialto::server -#endif // FIREBOLT_RIALTO_SERVER_NEED_DATA_MAPPING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/Utils.h b/middleware/rialto-client/media/server/gstplayer/include/Utils.h deleted file mode 100644 index 923545668..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/Utils.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_UTILS_H_ -#define FIREBOLT_RIALTO_SERVER_UTILS_H_ - -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "IMediaPipeline.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -bool isVideoDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -bool isAudioDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -bool isVideoParser(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -bool isVideoSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -bool isAudioSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -bool isSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -bool isDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -bool isAudio(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -bool isVideo(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element); -std::optional getUnderflowSignalName(const firebolt::rialto::wrappers::IGlibWrapper &glibWrapper, - GstElement *element); -GstCaps *createCapsFromMediaSource(const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::unique_ptr &source); -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_UTILS_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/WebAudioPlayerContext.h b/middleware/rialto-client/media/server/gstplayer/include/WebAudioPlayerContext.h deleted file mode 100644 index 8819e93be..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/WebAudioPlayerContext.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_CONTEXT_H_ -#define FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_CONTEXT_H_ - -#include -#include - -#include -#include -#include -#include - -#include "IGstSrc.h" - -namespace firebolt::rialto::server -{ -constexpr uint32_t kMaxWebAudioBytes{10 * 1024}; - -struct WebAudioPlayerContext -{ - /** - * @brief The rialto src object. - */ - std::shared_ptr gstSrc{nullptr}; - - /** - * @brief The gstreamer pipeline. - */ - GstElement *pipeline{nullptr}; - - /** - * @brief The gstreamer audio source. - */ - GstElement *source{nullptr}; - - /** - * @brief Write buffer mutex. - */ - std::mutex writeBufferMutex; - - /** - * @brief Write buffer condition variable. - */ - std::condition_variable writeBufferCond; - - /** - * @brief The previous number of bytes written to the gstreamer buffers. - */ - uint32_t lastBytesWritten{}; - - /** - * @brief The number of bytes per sample. - */ - uint32_t bytesPerSample{}; - - /** - * @brief Pointer to the gstreamer volume element - */ - GstStreamVolume *gstVolumeElement{nullptr}; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_CONTEXT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/WorkerThread.h b/middleware/rialto-client/media/server/gstplayer/include/WorkerThread.h deleted file mode 100644 index af6164ec7..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/WorkerThread.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_WORKER_THREAD_H_ -#define FIREBOLT_RIALTO_SERVER_WORKER_THREAD_H_ - -#include "IWorkerThread.h" -#include "tasks/IPlayerTask.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class WorkerThreadFactory : public IWorkerThreadFactory -{ -public: - std::unique_ptr createWorkerThread() const override; -}; - -class WorkerThread : public IWorkerThread -{ -public: - WorkerThread(); - ~WorkerThread() override; - - void stop() override; - void join() override; - void enqueueTask(std::unique_ptr &&task) override; - void enqueuePriorityTask(std::unique_ptr &&task) override; - -private: - /** - * @brief For handling new tasks in the worker thread. - */ - void taskHandler(); - - /** - * @brief Gets the next task or wait for a task on the queue. - * - * @retval Next task to process. - */ - std::unique_ptr waitForTask(); - -private: - /** - * @brief Flag used to check, if task thread is active - */ - bool m_isTaskThreadActive{true}; - - /** - * @brief Thread for handling player tasks. - */ - std::thread m_taskThread{}; - - /** - * @brief Mutex to protect the task handling. - */ - std::mutex m_taskMutex{}; - - /** - * @brief New task condition varaible. - */ - std::condition_variable m_taskCV{}; - - /** - * @brief Queue to store new tasks. - */ - std::deque> m_taskQueue{}; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_WORKER_THREAD_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h deleted file mode 100644 index 71b462675..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/IGenericPlayerTaskFactory.h +++ /dev/null @@ -1,550 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GENERIC_PLAYER_TASK_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_I_GENERIC_PLAYER_TASK_FACTORY_H_ - -#include "GenericPlayerContext.h" -#include "IDataReader.h" -#include "IFlushWatcher.h" -#include "IGstGenericPlayerPrivate.h" -#include "IHeartbeatHandler.h" -#include "IMediaPipeline.h" -#include "IPlayerTask.h" -#include "MediaCommon.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IGenericPlayerTaskFactory factory class, returns a concrete implementation of IPlayerTask - */ -class IGenericPlayerTaskFactory -{ -public: - IGenericPlayerTaskFactory() = default; - virtual ~IGenericPlayerTaskFactory() = default; - - /** - * @brief Creates a AttachSamples task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] mediaSegments : The media segments to attach - * - * @retval the new AttachSamples task instance. - */ - virtual std::unique_ptr - createAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const IMediaPipeline::MediaSegmentVector &mediaSegments) const = 0; - - /** - * @brief Creates a AttachSource task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] source : The source to attach. - * - * @retval the new AttachSource task instance. - */ - virtual std::unique_ptr - createAttachSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::unique_ptr &source) const = 0; - - /** - * @brief Creates a DeepElementAdded task. - * - * @param[in] context : The GstPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] pipeline : The pipeline the signal was fired from. - * @param[in] bin : the GstBin the element was added to - * @param[in] element : an element that was added to the playbin hierarchy - * - * @retval the new DeepElementAdded task instance. - */ - virtual std::unique_ptr createDeepElementAdded(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, GstBin *pipeline, - GstBin *bin, GstElement *element) const = 0; - - /** - * @brief Creates a EnoughData task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] src : The source, which reports enough data. - * - * @retval the new EnoughData task instance. - */ - virtual std::unique_ptr createEnoughData(GenericPlayerContext &context, GstAppSrc *src) const = 0; - - /** - * @brief Creates a Eos task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] type : The media source type, which reports eos. - * - * @retval the new Eos task instance. - */ - virtual std::unique_ptr createEos(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type) const = 0; - - /** - * @brief Creates a FinishSetupSource task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * - * @retval the new FinishSetupSource task instance. - */ - virtual std::unique_ptr createFinishSetupSource(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const = 0; - - /** - * @brief Creates a HandleBusMessage task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] message : The message to be handled. - * @param[in] flushWatcher : Flush watcher instance - * - * @retval the new HandleBusMessage task instance. - */ - virtual std::unique_ptr createHandleBusMessage(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, GstMessage *message, - const IFlushWatcher &flushWatcher) const = 0; - - /** - * @brief Creates a NeedData task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] src : The source, which reports need data. - * - * @retval the new NeedData task instance. - */ - virtual std::unique_ptr createNeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - GstAppSrc *src) const = 0; - - /** - * @brief Creates a Pause task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * - * @retval the new Pause task instance. - */ - virtual std::unique_ptr createPause(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const = 0; - - /** - * @brief Creates a Play task. - * - * @param[in] player : The GstGenericPlayer instance - * - * @retval the new Play task instance. - */ - virtual std::unique_ptr createPlay(IGstGenericPlayerPrivate &player) const = 0; - - /** - * @brief Creates a ReadShmDataAndAttachSamples task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] dataReader : The shared memory data reader - * - * @retval the new ReadShmDataAndAttachSamples task instance. - */ - virtual std::unique_ptr - createReadShmDataAndAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::shared_ptr &dataReader) const = 0; - - /** - * @brief Creates a Remove Source task. - * - * @param[in] context : The GstPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] type : The media source type to remove - * - * @retval the new Remove Source task instance. - */ - virtual std::unique_ptr createRemoveSource(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type) const = 0; - - /** - * @brief Creates a ReportPosition task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * - * @retval the new ReportPosition task instance. - */ - virtual std::unique_ptr createReportPosition(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const = 0; - - /** - * @brief Creates a CheckAudioUnderflow task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * - * @retval the new CheckAudioUnderflow task instance. - */ - virtual std::unique_ptr createCheckAudioUnderflow(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const = 0; - - /** - * @brief Creates a SetPlaybackRate task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] rate : The new playback rate. - * - * @retval the new SetPlaybackRate task instance. - */ - virtual std::unique_ptr createSetPlaybackRate(GenericPlayerContext &context, double rate) const = 0; - - /** - * @brief Creates a SetPosition task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] position : The position to be set - * - * @retval the new SetPosition task instance. - */ - virtual std::unique_ptr - createSetPosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, std::int64_t position) const = 0; - - /** - * @brief Creates a SetupElement task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] element : The element to be setup. - * - * @retval the new SetupElement task instance. - */ - virtual std::unique_ptr - createSetupElement(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstElement *element) const = 0; - - /** - * @brief Creates a SetupSource task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] source : The source to be setup. - * - * @retval the new SetupSource task instance. - */ - virtual std::unique_ptr - createSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstElement *source) const = 0; - - /** - * @brief Creates a SetVideoGeometry task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] rectangle : The video geometry data. - * - * @retval the new SetVideoGeometry task instance. - */ - virtual std::unique_ptr createSetVideoGeometry(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const Rectangle &rectangle) const = 0; - - /** - * @brief Creates a SetVolume task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] volume : The volume to be set - * - * @retval the new SetVolume task instance. - */ - virtual std::unique_ptr createSetVolume(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - double targetVolume, uint32_t volumeDuration, - firebolt::rialto::EaseType easeType) const = 0; - - /** - * @brief Creates a SetMute task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] mediaSourceType : The media source type to set mute - * @param[in] mute : The mute state to be set - * - * @retval the new SetMute task instance. - */ - virtual std::unique_ptr createSetMute(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const MediaSourceType &mediaSourceType, bool mute) const = 0; - - /** - * @brief Creates a SetTextTrackIdentifier task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] textTrackIdentifier : The text track identifier to be set - * - * @retval the new SetTextTrackIdentifier task instance. - */ - virtual std::unique_ptr createSetTextTrackIdentifier(GenericPlayerContext &context, - const std::string &textTrackIdentifier) const = 0; - - /** - * @brief Creates a SetLowLatency task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] lowLatency : The low latency value to set - * - * @retval the new SetLowLatency task instance. - */ - virtual std::unique_ptr createSetLowLatency(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, bool lowLatency) const = 0; - - /** - * @brief Creates a SetSync task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] sync : The sync value to set - * - * @retval the new SetSync task instance. - */ - virtual std::unique_ptr createSetSync(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - bool sync) const = 0; - - /** - * @brief Creates a SetSyncOff task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] syncOff : The syncOff value to set - * - * @retval the new SetSyncOff task instance. - */ - virtual std::unique_ptr createSetSyncOff(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, bool syncOff) const = 0; - - /** - * @brief Creates a SetStreamSyncMode task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] type : The media source type to set stream sync mode - * @param[in] streamSyncMode : The streamSyncMode value to set - * - * @retval the new SetStreamSyncMode task instance. - */ - virtual std::unique_ptr createSetStreamSyncMode(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - int32_t streamSyncMode) const = 0; - - /** - * @brief Creates a Shutdown task. - * - * @param[in] context : The GstGenericPlayer context - * - * @retval the new Shutdown task instance. - */ - virtual std::unique_ptr createShutdown(IGstGenericPlayerPrivate &player) const = 0; - - /** - * @brief Creates a Stop task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * - * @retval the new Stop task instance. - */ - virtual std::unique_ptr createStop(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const = 0; - - /** - * @brief Creates an Underflow task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstPlayer instance - * @param[in] underflowEnabled : The underflow enabled flag (audio or video). - * - * @retval the new Underflow task instance. - */ - virtual std::unique_ptr createUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - bool underflowEnabled, MediaSourceType sourceType) const = 0; - - /** - * @brief Creates an UpdatePlaybackGroup task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] typefind : The typefind element. - * @param[in] caps : The GstCaps of added element - * - * @retval the new UpdatePlaybackGroup task instance. - */ - virtual std::unique_ptr createUpdatePlaybackGroup(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - GstElement *typefind, const GstCaps *caps) const = 0; - - /** - * @brief Creates a RenderFrame task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstPlayer instance - * - * @retval the new RenderFrame task instance. - */ - virtual std::unique_ptr createRenderFrame(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const = 0; - - /** - * @brief Creates a Ping task. - * - * @param[in] heartbeatHandler : The HeartbeatHandler instance - * - * @retval the new Ping task instance. - */ - virtual std::unique_ptr createPing(std::unique_ptr &&heartbeatHandler) const = 0; - - /** - * @brief Creates a Flush task. - * - * @param[in] context : The GstPlayer context - * @param[in] type : The media source type to flush - * @param[in] resetTime : True if time should be reset - * - * @retval the new Flush task instance. - */ - virtual std::unique_ptr createFlush(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - bool resetTime) const = 0; - - /** - * @brief Creates a SetSourcePosition task. - * - * @param[in] context : The GstPlayer context - * @param[in] player : The GstGenericPlayer instance - * @param[in] type : The media source type to set position - * @param[in] position : The new source position - * @param[in] resetTime : True if time should be reset - * @param[in] appliedRate : The applied rate after seek - * @param[in] stopPosition : The position of last pushed buffer - * - * @retval the new SetSourcePosition task instance. - */ - virtual std::unique_ptr createSetSourcePosition(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - std::int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) const = 0; - - /** - * @brief Creates a SetSubtitleOffset task. - * - * @param[in] context : The GstPlayer context - * @param[in] position : The subtitle offset position in nanoseconds - * - * @retval the new SetSubtitleOffset task instance. - */ - virtual std::unique_ptr createSetSubtitleOffset(GenericPlayerContext &context, - std::int64_t position) const = 0; - - /** - * @brief Creates a ProcessAudioGap task. - * - * @param[in] context : The GstPlayer context - * @param[in] position : Audio pts fade position - * @param[in] duration : Audio pts fade duration - * @param[in] discontinuityGap : Audio discontinuity gap - * @param[in] audioAac : True if audio codec is AAC - * - * @retval the new ProcessAudioGap task instance. - */ - virtual std::unique_ptr createProcessAudioGap(GenericPlayerContext &context, std::int64_t position, - std::uint32_t duration, std::int64_t discontinuityGap, - bool audioAac) const = 0; - - /** - * @brief Creates a SetImmediateOutput task. - * - * @param[in] context : The GstPlayer context - * @param[in] player : The GstPlayer instance - * @param[in] type : The media source type - * @param[in] immediateOutput : the value to set for immediate-output - * - * @retval the new ProcessAudioGap task instance. - */ - virtual std::unique_ptr createSetImmediateOutput(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - bool immediateOutput) const = 0; - - /** - * @brief Creates a SetBufferingLimit task. - * - * @param[in] context : The GstPlayer context - * @param[in] player : The GstPlayer instance - * @param[in] limit : the value to set for buffering limit - * - * @retval the new ProcessAudioGap task instance. - */ - virtual std::unique_ptr createSetBufferingLimit(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - std::uint32_t limit) const = 0; - - /** - * @brief Creates a SetUseBuffering task. - * - * @param[in] context : The GstPlayer context - * @param[in] player : The GstPlayer instance - * @param[in] useBuffering : the value to set for use buffering - * - * @retval the new ProcessAudioGap task instance. - */ - virtual std::unique_ptr - createSetUseBuffering(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool useBuffering) const = 0; - - /** - * @brief Creates a SwitchSource task. - * - * @param[in] player : The GstGenericPlayer instance - * @param[in] source : The source to switch. - * - * @retval the new SwitchSource task instance. - */ - virtual std::unique_ptr - createSwitchSource(IGstGenericPlayerPrivate &player, - const std::unique_ptr &source) const = 0; - - /** - * @brief Creates a SynchroniseSubtitleClock task. - * - * @param[in] context : The GstGenericPlayer context - * @param[in] player : The GstGenericPlayer instance - * - * @retval the new SynchroniseSubtitleClock task instance. - */ - virtual std::unique_ptr createSynchroniseSubtitleClock(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const = 0; -}; - -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GENERIC_PLAYER_TASK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/IPlayerTask.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/IPlayerTask.h deleted file mode 100644 index 4dc31f36a..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/IPlayerTask.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_PLAYER_TASK_H_ -#define FIREBOLT_RIALTO_SERVER_I_PLAYER_TASK_H_ - -namespace firebolt::rialto::server -{ -class IPlayerTask -{ -public: - IPlayerTask() = default; - virtual ~IPlayerTask() = default; - IPlayerTask(const IPlayerTask &) = delete; - IPlayerTask(IPlayerTask &&) = delete; - IPlayerTask &operator=(const IPlayerTask &) = delete; - IPlayerTask &operator=(IPlayerTask &&) = delete; - - virtual void execute() const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_PLAYER_TASK_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h deleted file mode 100644 index a067f68a4..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/IWebAudioPlayerTaskFactory.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ - -#include "IGstWebAudioPlayerPrivate.h" -#include "IHeartbeatHandler.h" -#include "IPlayerTask.h" -#include "WebAudioPlayerContext.h" -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IWebAudioPlayerTaskFactory factory class, returns a concrete implementation of IPlayerTask - */ -class IWebAudioPlayerTaskFactory -{ -public: - IWebAudioPlayerTaskFactory() = default; - virtual ~IWebAudioPlayerTaskFactory() = default; - - /** - * @brief Creates a Shutdown task. - * - * @param[in] player : The GstWebAudioPlayer instance - * - * @retval the new Shutdown task instance. - */ - virtual std::unique_ptr createShutdown(IGstWebAudioPlayerPrivate &player) const = 0; - - /** - * @brief Creates a Stop task. - * - * @param[in] player : The GstWebAudioPlayer instance - * - * @retval the new Stop task instance. - */ - virtual std::unique_ptr createStop(IGstWebAudioPlayerPrivate &player) const = 0; - - /** - * @brief Creates a Play task. - * - * @param[in] player : The GstWebAudioPlayer instance - * - * @retval the new Play task instance. - */ - virtual std::unique_ptr createPlay(IGstWebAudioPlayerPrivate &player) const = 0; - - /** - * @brief Creates a Pause task. - * - * @param[in] player : The GstWebAudioPlayer instance - * - * @retval the new Pause task instance. - */ - virtual std::unique_ptr createPause(IGstWebAudioPlayerPrivate &player) const = 0; - - /** - * @brief Creates a SetCaps task. - * - * @param[in] context : The GstWebAudioPlayer context - * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM) - * @param[in] config : Additional type dependent configuration data or nullptr - * - * @retval the new SetCaps task instance. - */ - virtual std::unique_ptr createSetCaps(WebAudioPlayerContext &context, const std::string &audioMimeType, - std::weak_ptr config) const = 0; - - /** - * @brief Creates a Eos task. - * - * @param[in] context : The GstWebAudioPlayer context - * - * @retval the new Eos task instance. - */ - virtual std::unique_ptr createEos(WebAudioPlayerContext &context) const = 0; - - /** - * @brief Creates a SetVolume task. - * - * @param[in] context : The GstWebAudioPlayer context - * @param[in] volume : The volume to set - * - * @retval the new SetVolume task instance. - */ - virtual std::unique_ptr createSetVolume(WebAudioPlayerContext &context, double volume) const = 0; - - /** - * @brief Creates a WriteBuffer task. - * - * @param[in] context : The GstWebAudioPlayer context - * @param[in] mainPtr : Pointer to the start of the data - * @param[in] mainLength : Amount of bytes to write from the mainPtr - * @param[in] wrapPtr : Pointer to the start of the wrapped data - * @param[in] wrapLength : Amount of bytes to write from the wrapPtr - * - * @retval the new SetVolume task instance. - */ - virtual std::unique_ptr createWriteBuffer(WebAudioPlayerContext &context, uint8_t *mainPtr, - uint32_t mainLength, uint8_t *wrapPtr, - uint32_t wrapLength) const = 0; - - /** - * @brief Creates a HandleBusMessage task. - * - * @param[in] context : The GstWebAudioPlayer context - * @param[in] player : The GstWebAudioPlayer instance - * @param[in] message : The message to be handled - * - * @retval the new HandleBusMessage task instance. - */ - virtual std::unique_ptr createHandleBusMessage(WebAudioPlayerContext &context, - IGstWebAudioPlayerPrivate &player, - GstMessage *message) const = 0; - - /** - * @brief Creates a Ping task. - * - * @param[in] heartbeatHandler : The HeartbeatHandler instance - * - * @retval the new Ping task instance. - */ - virtual std::unique_ptr createPing(std::unique_ptr &&heartbeatHandler) const = 0; -}; - -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSamples.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSamples.h deleted file mode 100644 index 5c51d6bc7..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSamples.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SAMPLES_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SAMPLES_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IMediaPipeline.h" -#include "IPlayerTask.h" -#include -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class AttachSamples : public IPlayerTask -{ -public: - AttachSamples(GenericPlayerContext &context, - const std::shared_ptr &gstWrapper, - IGstGenericPlayerPrivate &player, const IMediaPipeline::MediaSegmentVector &mediaSegments); - ~AttachSamples() override; - void execute() const override; - -private: - void attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const; - struct AudioData - { - GstBuffer *buffer; - int32_t rate; - int32_t channels; - std::shared_ptr codecData; - uint64_t clippingStart; - uint64_t clippingEnd; - }; - struct VideoData - { - GstBuffer *buffer; - int32_t width; - int32_t height; - Fraction frameRate; - std::shared_ptr codecData; - }; - - GenericPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - IGstGenericPlayerPrivate &m_player; - std::vector m_audioData; - std::vector m_videoData; - std::vector m_subtitleData; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SAMPLES_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSource.h deleted file mode 100644 index b9f1f83d6..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/AttachSource.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SOURCE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SOURCE_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstTextTrackSinkFactory.h" -#include "IGstWrapper.h" -#include "IMediaPipeline.h" -#include "IPlayerTask.h" -#include "IRdkGstreamerUtilsWrapper.h" -#include -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class AttachSource : public IPlayerTask -{ -public: - AttachSource(GenericPlayerContext &context, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr &gstTextTrackSinkFactory, - IGstGenericPlayerPrivate &player, const std::unique_ptr &source); - ~AttachSource() override; - void execute() const override; - -private: - void addSource() const; - void reattachAudioSource() const; - - GenericPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - std::shared_ptr m_gstTextTrackSinkFactory; - IGstGenericPlayerPrivate &m_player; - std::unique_ptr m_attachedSource; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ATTACH_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/CheckAudioUnderflow.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/CheckAudioUnderflow.h deleted file mode 100644 index 5b36dd130..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/CheckAudioUnderflow.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_CHECK_AUDIO_UNDERFLOW_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_CHECK_AUDIO_UNDERFLOW_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class CheckAudioUnderflow : public IPlayerTask -{ -public: - CheckAudioUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper); - ~CheckAudioUnderflow() override = default; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; - std::shared_ptr m_gstWrapper; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_CHECK_AUDIO_UNDERFLOW_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/DeepElementAdded.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/DeepElementAdded.h deleted file mode 100644 index 424d61e81..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/DeepElementAdded.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_DEEP_ELEMENT_ADDED_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_DEEP_ELEMENT_ADDED_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class DeepElementAdded : public IPlayerTask -{ -public: - DeepElementAdded(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, GstBin *pipeline, - GstBin *bin, GstElement *element); - ~DeepElementAdded() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - GstBin *m_pipeline; - GstBin *m_bin; - GstElement *m_element; - gchar *m_elementName; - bool m_callbackRegistered; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_DEEP_ELEMENT_ADDED_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/EnoughData.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/EnoughData.h deleted file mode 100644 index debc39bed..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/EnoughData.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ENOUGH_DATA_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ENOUGH_DATA_H_ - -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server -{ -struct GenericPlayerContext; -} // namespace firebolt::rialto::server - -namespace firebolt::rialto::server::tasks::generic -{ -class EnoughData : public IPlayerTask -{ -public: - EnoughData(GenericPlayerContext &context, GstAppSrc *src); - ~EnoughData() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - GstAppSrc *m_src; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_ENOUGH_DATA_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Eos.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Eos.h deleted file mode 100644 index 650a64ab2..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Eos.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_EOS_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_EOS_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include "MediaCommon.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class Eos : public IPlayerTask -{ -public: - Eos(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::shared_ptr gstWrapper, - const firebolt::rialto::MediaSourceType &type); - ~Eos() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - std::shared_ptr m_gstWrapper; - firebolt::rialto::MediaSourceType m_type; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_EOS_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/FinishSetupSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/FinishSetupSource.h deleted file mode 100644 index 2bdc52869..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/FinishSetupSource.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FINISH_SETUP_SOURCE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FINISH_SETUP_SOURCE_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class FinishSetupSource : public IPlayerTask -{ -public: - FinishSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client); - ~FinishSetupSource() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FINISH_SETUP_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Flush.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Flush.h deleted file mode 100644 index 77b795d17..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Flush.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FLUSH_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FLUSH_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class Flush : public IPlayerTask -{ -public: - Flush(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper, const MediaSourceType &type, - bool resetTime); - ~Flush() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; - std::shared_ptr m_gstWrapper; - MediaSourceType m_type; - bool m_resetTime; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_FLUSH_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h deleted file mode 100644 index 87cc76f45..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/GenericPlayerTaskFactory.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_TASK_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_TASK_FACTORY_H_ - -#include "IGenericPlayerTaskFactory.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerClient.h" -#include "IGstTextTrackSinkFactory.h" -#include "IGstWrapper.h" -#include "IMediaPipeline.h" -#include -#include - -namespace firebolt::rialto::server -{ -class GenericPlayerTaskFactory : public IGenericPlayerTaskFactory -{ -public: - GenericPlayerTaskFactory( - IGstGenericPlayerClient *client, const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr &rdkGstreamerUtilsWrapper, - const std::shared_ptr &gstTextTrackSinkFactory); - ~GenericPlayerTaskFactory() override = default; - - std::unique_ptr createAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const IMediaPipeline::MediaSegmentVector &mediaSegments) const override; - std::unique_ptr - createAttachSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::unique_ptr &source) const override; - std::unique_ptr createDeepElementAdded(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - GstBin *pipeline, GstBin *bin, - GstElement *element) const override; - std::unique_ptr createEnoughData(GenericPlayerContext &context, GstAppSrc *src) const override; - std::unique_ptr createEos(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type) const override; - std::unique_ptr createFinishSetupSource(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const override; - std::unique_ptr createHandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - GstMessage *message, - const IFlushWatcher &flushWatcher) const override; - std::unique_ptr createNeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - GstAppSrc *src) const override; - std::unique_ptr createPause(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const override; - std::unique_ptr createPlay(IGstGenericPlayerPrivate &player) const override; - std::unique_ptr - createReadShmDataAndAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::shared_ptr &dataReader) const override; - std::unique_ptr createRemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type) const override; - std::unique_ptr createReportPosition(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const override; - std::unique_ptr createCheckAudioUnderflow(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const override; - std::unique_ptr createSetPlaybackRate(GenericPlayerContext &context, double rate) const override; - std::unique_ptr createSetPosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::int64_t position) const override; - std::unique_ptr createSetupElement(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - GstElement *element) const override; - std::unique_ptr createSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - GstElement *source) const override; - std::unique_ptr createSetVideoGeometry(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const Rectangle &rectangle) const override; - std::unique_ptr createSetVolume(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - double targetVolume, uint32_t volumeDuration, - firebolt::rialto::EaseType easeType) const override; - std::unique_ptr createSetMute(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const MediaSourceType &mediaSourceType, bool mute) const override; - std::unique_ptr createSetTextTrackIdentifier(GenericPlayerContext &context, - const std::string &textTrackIdentifier) const override; - std::unique_ptr createSetLowLatency(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - bool lowLatency) const override; - std::unique_ptr createSetSync(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - bool sync) const override; - std::unique_ptr createSetSyncOff(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - bool syncOff) const override; - std::unique_ptr createSetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - int32_t streamSyncMode) const override; - std::unique_ptr createShutdown(IGstGenericPlayerPrivate &player) const override; - std::unique_ptr createStop(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const override; - std::unique_ptr createUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - bool underflowEnable, MediaSourceType sourceType) const override; - std::unique_ptr createUpdatePlaybackGroup(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, GstElement *typefind, - const GstCaps *caps) const override; - std::unique_ptr createRenderFrame(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const override; - std::unique_ptr createPing(std::unique_ptr &&heartbeatHandler) const override; - std::unique_ptr createFlush(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - bool resetTime) const override; - std::unique_ptr createSetSourcePosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - std::int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) const override; - std::unique_ptr createSetSubtitleOffset(GenericPlayerContext &context, - std::int64_t position) const override; - std::unique_ptr createProcessAudioGap(GenericPlayerContext &context, std::int64_t position, - std::uint32_t duration, std::int64_t discontinuityGap, - bool audioAac) const override; - std::unique_ptr createSetImmediateOutput(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - bool immediateOutput) const override; - std::unique_ptr createSetBufferingLimit(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::uint32_t limit) const override; - std::unique_ptr createSetUseBuffering(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - bool useBuffering) const override; - std::unique_ptr - createSwitchSource(IGstGenericPlayerPrivate &player, - const std::unique_ptr &source) const override; - - std::unique_ptr createSynchroniseSubtitleClock(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const override; - -private: - IGstGenericPlayerClient *m_client; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - std::shared_ptr m_rdkGstreamerUtilsWrapper; - std::shared_ptr m_gstTextTrackSinkFactory; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_GENERIC_PLAYER_TASK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h deleted file mode 100644 index 87760d802..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/HandleBusMessage.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_HANDLE_BUS_MESSAGE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_HANDLE_BUS_MESSAGE_H_ - -#include "GenericPlayerContext.h" -#include "IFlushWatcher.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class HandleBusMessage : public IPlayerTask -{ -public: - HandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, GstMessage *message, - const IFlushWatcher &flushWatcher); - ~HandleBusMessage() override; - void execute() const override; - -private: - bool allSourcesEos() const; - - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - GstMessage *m_message; - const IFlushWatcher &m_flushWatcher; - bool m_isFlushOngoingDuringCreation; - bool m_isAsyncFlushOngoingDuringCreation; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_HANDLE_BUS_MESSAGE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/NeedData.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/NeedData.h deleted file mode 100644 index 47bac3d9c..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/NeedData.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_NEED_DATA_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_NEED_DATA_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class NeedData : public IPlayerTask -{ -public: - NeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - GstAppSrc *src); - ~NeedData() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; - GstAppSrc *m_src; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_NEED_DATA_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Pause.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Pause.h deleted file mode 100644 index 0e4339b17..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Pause.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PAUSE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PAUSE_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class Pause : public IPlayerTask -{ -public: - explicit Pause(GenericPlayerContext &context, IGstGenericPlayerPrivate &player); - ~Pause() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PAUSE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Ping.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Ping.h deleted file mode 100644 index 55f2a1978..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Ping.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PING_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PING_H_ - -#include "IHeartbeatHandler.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class Ping : public IPlayerTask -{ -public: - explicit Ping(std::unique_ptr &&heartbeatHandler); - ~Ping() override; - void execute() const override; - -private: - std::unique_ptr m_heartbeatHandler; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Play.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Play.h deleted file mode 100644 index bd4717569..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Play.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PLAY_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PLAY_H_ - -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class Play : public IPlayerTask -{ -public: - explicit Play(IGstGenericPlayerPrivate &player); - ~Play() override; - void execute() const override; - -private: - IGstGenericPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PLAY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ProcessAudioGap.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ProcessAudioGap.h deleted file mode 100644 index 1d77ff028..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ProcessAudioGap.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PROCESS_AUDIO_GAP_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PROCESS_AUDIO_GAP_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include "IRdkGstreamerUtilsWrapper.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class ProcessAudioGap : public IPlayerTask -{ -public: - ProcessAudioGap(GenericPlayerContext &context, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr rdkGstreamerUtilsWrapper, - std::int64_t position, std::uint32_t duration, std::int64_t discontinuityGap, bool audioAac); - ~ProcessAudioGap() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - std::shared_ptr m_rdkGstreamerUtilsWrapper; - std::int64_t m_position; - std::uint32_t m_duration; - std::int64_t m_discontinuityGap; - bool m_audioAac; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_PROCESS_AUDIO_GAP_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReadShmDataAndAttachSamples.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReadShmDataAndAttachSamples.h deleted file mode 100644 index 80844112b..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReadShmDataAndAttachSamples.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_READ_SHM_DATA_AND_ATTACH_SAMPLES_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_READ_SHM_DATA_AND_ATTACH_SAMPLES_H_ - -#include "GenericPlayerContext.h" -#include "IDataReader.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class ReadShmDataAndAttachSamples : public IPlayerTask -{ -public: - ReadShmDataAndAttachSamples(GenericPlayerContext &context, - const std::shared_ptr &gstWrapper, - IGstGenericPlayerPrivate &player, const std::shared_ptr &dataReader); - ~ReadShmDataAndAttachSamples() override; - void execute() const override; - -private: - void attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const; - GenericPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - IGstGenericPlayerPrivate &m_player; - std::shared_ptr m_dataReader; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_READ_SHM_DATA_AND_ATTACH_SAMPLES_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RemoveSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RemoveSource.h deleted file mode 100644 index 8e3eb1b68..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RemoveSource.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REMOVE_SOURCE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REMOVE_SOURCE_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class RemoveSource : public IPlayerTask -{ -public: - RemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper, const MediaSourceType &type); - ~RemoveSource() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; - std::shared_ptr m_gstWrapper; - MediaSourceType m_type; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REMOVE_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RenderFrame.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RenderFrame.h deleted file mode 100644 index c5e9801bf..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/RenderFrame.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_RENDER_FRAME_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_RENDER_FRAME_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class RenderFrame : public IPlayerTask -{ -public: - RenderFrame(GenericPlayerContext &context, IGstGenericPlayerPrivate &player); - ~RenderFrame() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_RENDER_FRAME_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReportPosition.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReportPosition.h deleted file mode 100644 index cbe98b5bf..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/ReportPosition.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REPORT_POSITION_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REPORT_POSITION_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class ReportPosition : public IPlayerTask -{ -public: - ReportPosition(GenericPlayerContext &context, IGstGenericPlayerClient *client, - const std::shared_ptr &gstWrapper, - IGstGenericPlayerPrivate &player); - ~ReportPosition() override = default; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerClient *m_gstPlayerClient; - std::shared_ptr m_gstWrapper; - IGstGenericPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_REPORT_POSITION_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetBufferingLimit.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetBufferingLimit.h deleted file mode 100644 index 70ecfa2c3..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetBufferingLimit.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_BUFFERING_LIMIT_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_BUFFERING_LIMIT_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetBufferingLimit : public IPlayerTask -{ -public: - SetBufferingLimit(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, std::uint32_t limit); - ~SetBufferingLimit() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - std::uint32_t m_limit; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_BUFFERING_LIMIT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetImmediateOutput.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetImmediateOutput.h deleted file mode 100644 index a5fdbb8fd..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetImmediateOutput.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_IMMEDIATE_OUTPUT_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_IMMEDIATE_OUTPUT_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" - -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetImmediateOutput : public IPlayerTask -{ -public: - explicit SetImmediateOutput(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const MediaSourceType &type, bool immediateOutput); - ~SetImmediateOutput() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - const MediaSourceType m_type; - bool m_immediateOutput; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_IMMEDIATE_OUTPUT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetLowLatency.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetLowLatency.h deleted file mode 100644 index 0094dab8e..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetLowLatency.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_LOW_LATENCY_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_LOW_LATENCY_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class SetLowLatency : public IPlayerTask -{ -public: - SetLowLatency(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool lowLatency); - ~SetLowLatency() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - bool m_lowLatency; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_LOW_LATENCY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetMute.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetMute.h deleted file mode 100644 index 92b6f91c8..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetMute.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_MUTE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_MUTE_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetMute : public IPlayerTask -{ -public: - SetMute(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const MediaSourceType &mediaSourceType, bool mute); - ~SetMute() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - const MediaSourceType &m_mediaSourceType; - bool m_mute; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_MUTE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPlaybackRate.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPlaybackRate.h deleted file mode 100644 index 9ca3acf6f..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPlaybackRate.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_PLAYBACK_RATE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_PLAYBACK_RATE_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetPlaybackRate : public IPlayerTask -{ -public: - SetPlaybackRate(GenericPlayerContext &context, std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, double rate); - ~SetPlaybackRate() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - double m_rate; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_PLAYBACK_RATE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPosition.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPosition.h deleted file mode 100644 index 974509cf9..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetPosition.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_POSITION_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_POSITION_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetPosition : public IPlayerTask -{ -public: - SetPosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper, std::int64_t position); - ~SetPosition() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; - std::shared_ptr m_gstWrapper; - std::int64_t m_position; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_POSITION_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSourcePosition.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSourcePosition.h deleted file mode 100644 index 253ab55f1..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSourcePosition.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SOURCE_POSITION_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SOURCE_POSITION_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetSourcePosition : public IPlayerTask -{ -public: - SetSourcePosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - const std::shared_ptr &glibWrapper, const MediaSourceType &type, - std::int64_t position, bool resetTime, double appliedRate, uint64_t stopPosition); - ~SetSourcePosition() override; - void execute() const override; - -private: - void setSubtitlePosition(GstElement *source) const; - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; - std::shared_ptr m_glibWrapper; - MediaSourceType m_type; - std::int64_t m_position; - bool m_resetTime; - double m_appliedRate; - uint64_t m_stopPosition; -}; - -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SOURCE_POSITION_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetStreamSyncMode.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetStreamSyncMode.h deleted file mode 100644 index 7085cc5d0..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetStreamSyncMode.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_STREAM_SYNC_MODE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_STREAM_SYNC_MODE_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class SetStreamSyncMode : public IPlayerTask -{ -public: - SetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, const MediaSourceType &type, - int32_t streamSyncMode); - ~SetStreamSyncMode() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - MediaSourceType m_type; - int32_t m_streamSyncMode; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_STREAM_SYNC_MODE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSubtitleOffset.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSubtitleOffset.h deleted file mode 100644 index e8533409d..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSubtitleOffset.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SUBTITLE_OFFSET_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SUBTITLE_OFFSET_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetSubtitleOffset : public IPlayerTask -{ -public: - SetSubtitleOffset(GenericPlayerContext &context, const std::shared_ptr &glibWrapper, - std::int64_t position); - ~SetSubtitleOffset() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - std::shared_ptr m_glibWrapper; - std::int64_t m_position; -}; - -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SUBTITLE_OFFSET_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSync.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSync.h deleted file mode 100644 index 9810ab8bf..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSync.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetSync : public IPlayerTask -{ -public: - SetSync(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool sync); - ~SetSync() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - bool m_sync; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSyncOff.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSyncOff.h deleted file mode 100644 index ac10f98e0..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetSyncOff.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_OFF_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_OFF_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class SetSyncOff : public IPlayerTask -{ -public: - SetSyncOff(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool syncOff); - ~SetSyncOff() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - bool m_syncOff; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_SYNC_OFF_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetTextTrackIdentifier.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetTextTrackIdentifier.h deleted file mode 100644 index 01dad493f..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetTextTrackIdentifier.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_TEXT_TRACK_IDENTIFIER_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_TEXT_TRACK_IDENTIFIER_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetTextTrackIdentifier : public IPlayerTask -{ -public: - SetTextTrackIdentifier(GenericPlayerContext &context, - std::shared_ptr glibWrapper, - const std::string &textTrackIdentifier); - ~SetTextTrackIdentifier() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - std::shared_ptr m_glibWrapper; - const std::string m_textTrackIdentifier; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_TEXT_TRACK_IDENTIFIER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetUseBuffering.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetUseBuffering.h deleted file mode 100644 index 67d6514a8..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetUseBuffering.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_USE_BUFFERING_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_USE_BUFFERING_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetUseBuffering : public IPlayerTask -{ -public: - SetUseBuffering(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool useBuffering); - ~SetUseBuffering() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - bool m_useBuffering; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_USE_BUFFERING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVideoGeometry.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVideoGeometry.h deleted file mode 100644 index be7e47974..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVideoGeometry.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VIDEO_GEOMETRY_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VIDEO_GEOMETRY_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class SetVideoGeometry : public IPlayerTask -{ -public: - SetVideoGeometry(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, const Rectangle &rectangle); - ~SetVideoGeometry() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - Rectangle m_rectangle; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VIDEO_GEOMETRY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVolume.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVolume.h deleted file mode 100644 index 347bd33f4..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetVolume.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VOLUME_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VOLUME_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetVolume : public IPlayerTask -{ -public: - SetVolume(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - std::shared_ptr rdkGstreamerUtilsWrapper, - double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType); - ~SetVolume() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - std::shared_ptr m_rdkGstreamerUtilsWrapper; - double m_targetVolume; - uint32_t m_volumeDuration; - firebolt::rialto::EaseType m_easeType; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SET_VOLUME_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupElement.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupElement.h deleted file mode 100644 index dc3afb377..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupElement.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_ELEMENT_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_ELEMENT_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetupElement : public IPlayerTask -{ -public: - SetupElement(GenericPlayerContext &context, std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - IGstGenericPlayerPrivate &player, GstElement *element); - ~SetupElement() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - IGstGenericPlayerPrivate &m_player; - GstElement *m_element; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_ELEMENT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupSource.h deleted file mode 100644 index bfcad97a9..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SetupSource.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_SOURCE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_SOURCE_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SetupSource : public IPlayerTask -{ -public: - SetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstElement *source); - ~SetupSource() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - GstElement *m_source; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SETUP_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Shutdown.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Shutdown.h deleted file mode 100644 index 32bf6d89e..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Shutdown.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ - -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server -{ -class IGstGenericPlayerPrivate; -} // namespace firebolt::rialto::server - -namespace firebolt::rialto::server::tasks::generic -{ -class Shutdown : public IPlayerTask -{ -public: - explicit Shutdown(IGstGenericPlayerPrivate &player); - ~Shutdown() override; - void execute() const override; - -private: - IGstGenericPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SHUTDOWN_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Stop.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Stop.h deleted file mode 100644 index 13316c78c..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Stop.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_STOP_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_STOP_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::generic -{ -class Stop : public IPlayerTask -{ -public: - Stop(GenericPlayerContext &context, IGstGenericPlayerPrivate &player); - ~Stop() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_STOP_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SwitchSource.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SwitchSource.h deleted file mode 100644 index e9a082fd5..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SwitchSource.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SWITCH_SOURCE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SWITCH_SOURCE_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IMediaPipeline.h" -#include "IPlayerTask.h" -#include "IRdkGstreamerUtilsWrapper.h" -#include -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SwitchSource : public IPlayerTask -{ -public: - SwitchSource(IGstGenericPlayerPrivate &player, const std::unique_ptr &source); - ~SwitchSource() override; - void execute() const override; - -private: - IGstGenericPlayerPrivate &m_player; - std::unique_ptr m_source; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SWITCH_SOURCE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SynchroniseSubtitleClock.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SynchroniseSubtitleClock.h deleted file mode 100644 index f38a1ccbb..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/SynchroniseSubtitleClock.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SYNCHRONISE_SUBTITLE_CLOCK_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SYNCHRONISE_SUBTITLE_CLOCK_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class SynchroniseSubtitleClock : public IPlayerTask -{ -public: - SynchroniseSubtitleClock(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper); - ~SynchroniseSubtitleClock() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_SYNCHRONISE_SUBTITLE_CLOCK_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Underflow.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Underflow.h deleted file mode 100644 index fc9507e63..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/Underflow.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UNDERFLOW_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UNDERFLOW_H_ - -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class Underflow : public IPlayerTask -{ -public: - Underflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - bool underflowEnabled, MediaSourceType sourceType); - ~Underflow() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - IGstGenericPlayerClient *m_gstPlayerClient; - bool m_underflowEnabled; - MediaSourceType m_sourceType; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UNDERFLOW_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/UpdatePlaybackGroup.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/UpdatePlaybackGroup.h deleted file mode 100644 index 6ecdd0eaf..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/generic/UpdatePlaybackGroup.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UPDATE_PLAYBACK_GROUP_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UPDATE_PLAYBACK_GROUP_H_ - -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -class UpdatePlaybackGroup : public IPlayerTask -{ -public: - UpdatePlaybackGroup(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, GstElement *typefind, - const GstCaps *caps); - ~UpdatePlaybackGroup() override; - void execute() const override; - -private: - GenericPlayerContext &m_context; - IGstGenericPlayerPrivate &m_player; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - GstElement *m_typefind; - const GstCaps *m_caps; -}; -} // namespace firebolt::rialto::server::tasks::generic - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_GENERIC_UPDATE_PLAYBACK_GROUP_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Eos.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Eos.h deleted file mode 100644 index 27a8b16ad..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Eos.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_EOS_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_EOS_H_ - -#include "IGstWebAudioPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include "MediaCommon.h" -#include "WebAudioPlayerContext.h" -#include - -namespace firebolt::rialto::server::tasks::webaudio -{ -class Eos : public IPlayerTask -{ -public: - Eos(WebAudioPlayerContext &context, std::shared_ptr gstWrapper); - ~Eos() override; - void execute() const override; - -private: - WebAudioPlayerContext &m_context; - std::shared_ptr m_gstWrapper; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_EOS_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/HandleBusMessage.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/HandleBusMessage.h deleted file mode 100644 index 996e6c258..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/HandleBusMessage.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_HANDLE_BUS_MESSAGE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_HANDLE_BUS_MESSAGE_H_ - -#include "IGlibWrapper.h" -#include "IGstWebAudioPlayerClient.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include "WebAudioPlayerContext.h" -#include -#include - -namespace firebolt::rialto::server::tasks::webaudio -{ -class HandleBusMessage : public IPlayerTask -{ -public: - HandleBusMessage(WebAudioPlayerContext &context, IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, GstMessage *message); - ~HandleBusMessage() override; - void execute() const override; - -private: - WebAudioPlayerContext &m_context; - IGstWebAudioPlayerPrivate &m_player; - IGstWebAudioPlayerClient *m_gstPlayerClient; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - GstMessage *m_message; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_HANDLE_BUS_MESSAGE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Pause.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Pause.h deleted file mode 100644 index da6c327bb..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Pause.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PAUSE_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PAUSE_H_ - -#include "IGstWebAudioPlayerClient.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -class Pause : public IPlayerTask -{ -public: - explicit Pause(IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client); - ~Pause() override; - void execute() const override; - -private: - IGstWebAudioPlayerPrivate &m_player; - IGstWebAudioPlayerClient *m_gstPlayerClient; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PAUSE_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Ping.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Ping.h deleted file mode 100644 index 4e9d38cb6..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Ping.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PING_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PING_H_ - -#include "IHeartbeatHandler.h" -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server::tasks::webaudio -{ -class Ping : public IPlayerTask -{ -public: - explicit Ping(std::unique_ptr &&heartbeatHandler); - ~Ping() override; - void execute() const override; - -private: - std::unique_ptr m_heartbeatHandler; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PING_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Play.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Play.h deleted file mode 100644 index 476335b61..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Play.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PLAY_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PLAY_H_ - -#include "IGstWebAudioPlayerClient.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -class Play : public IPlayerTask -{ -public: - Play(IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client); - ~Play() override; - void execute() const override; - -private: - IGstWebAudioPlayerPrivate &m_player; - IGstWebAudioPlayerClient *m_gstPlayerClient; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_PLAY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetCaps.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetCaps.h deleted file mode 100644 index fefafd0c3..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetCaps.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_CAPS_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_CAPS_H_ - -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include "WebAudioPlayerContext.h" -#include -#include - -namespace firebolt::rialto::server::tasks::webaudio -{ -class SetCaps : public IPlayerTask -{ -public: - SetCaps(WebAudioPlayerContext &context, std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, const std::string &audioMimeType, - std::weak_ptr config); - ~SetCaps() override; - void execute() const override; - -private: - GstCaps *createCapsFromMimeType() const; - void setBytesPerSample() const; - - WebAudioPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; - const std::string m_audioMimeType; - WebAudioConfig m_config; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_CAPS_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetVolume.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetVolume.h deleted file mode 100644 index 7355621f2..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/SetVolume.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_VOLUME_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_VOLUME_H_ - -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include "WebAudioPlayerContext.h" -#include - -namespace firebolt::rialto::server::tasks::webaudio -{ -class SetVolume : public IPlayerTask -{ -public: - SetVolume(WebAudioPlayerContext &context, std::shared_ptr gstWrapper, - double volume); - ~SetVolume() override; - void execute() const override; - -private: - WebAudioPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - double m_volume; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SET_VOLUME_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Shutdown.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Shutdown.h deleted file mode 100644 index 1721730c8..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Shutdown.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ - -#include "IPlayerTask.h" -#include - -namespace firebolt::rialto::server -{ -class IGstWebAudioPlayerPrivate; -} // namespace firebolt::rialto::server - -namespace firebolt::rialto::server::tasks::webaudio -{ -class Shutdown : public IPlayerTask -{ -public: - explicit Shutdown(IGstWebAudioPlayerPrivate &player); - ~Shutdown() override; - void execute() const override; - -private: - IGstWebAudioPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_SHUTDOWN_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Stop.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Stop.h deleted file mode 100644 index 519d84f19..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/Stop.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_STOP_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_STOP_H_ - -#include "IGstWebAudioPlayerPrivate.h" -#include "IPlayerTask.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -class Stop : public IPlayerTask -{ -public: - explicit Stop(IGstWebAudioPlayerPrivate &player); - ~Stop() override; - void execute() const override; - -private: - IGstWebAudioPlayerPrivate &m_player; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_STOP_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h deleted file mode 100644 index c1cbdc059..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WebAudioPlayerTaskFactory.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ - -#include "IGlibWrapper.h" -#include "IGstWebAudioPlayerClient.h" -#include "IGstWrapper.h" -#include "IWebAudioPlayerTaskFactory.h" -#include -#include - -namespace firebolt::rialto::server -{ -class WebAudioPlayerTaskFactory : public IWebAudioPlayerTaskFactory -{ -public: - WebAudioPlayerTaskFactory(IGstWebAudioPlayerClient *client, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper); - ~WebAudioPlayerTaskFactory() override = default; - - std::unique_ptr createShutdown(IGstWebAudioPlayerPrivate &player) const override; - std::unique_ptr createStop(IGstWebAudioPlayerPrivate &player) const override; - std::unique_ptr createPlay(IGstWebAudioPlayerPrivate &player) const override; - std::unique_ptr createPause(IGstWebAudioPlayerPrivate &player) const override; - std::unique_ptr createSetCaps(WebAudioPlayerContext &context, const std::string &audioMimeType, - std::weak_ptr config) const override; - std::unique_ptr createEos(WebAudioPlayerContext &context) const override; - std::unique_ptr createSetVolume(WebAudioPlayerContext &context, double volume) const override; - std::unique_ptr createWriteBuffer(WebAudioPlayerContext &context, uint8_t *mainPtr, uint32_t mainLength, - uint8_t *wrapPtr, uint32_t wrapLength) const override; - std::unique_ptr createHandleBusMessage(WebAudioPlayerContext &context, IGstWebAudioPlayerPrivate &player, - GstMessage *message) const override; - std::unique_ptr createPing(std::unique_ptr &&heartbeatHandler) const override; - -private: - IGstWebAudioPlayerClient *m_client; - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_TASK_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WriteBuffer.h b/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WriteBuffer.h deleted file mode 100644 index f8957250b..000000000 --- a/middleware/rialto-client/media/server/gstplayer/include/tasks/webAudio/WriteBuffer.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_WRITE_BUFFER_H_ -#define FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_WRITE_BUFFER_H_ - -#include "IGstWebAudioPlayerPrivate.h" -#include "IGstWrapper.h" -#include "IPlayerTask.h" -#include "MediaCommon.h" -#include "WebAudioPlayerContext.h" -#include - -namespace firebolt::rialto::server::tasks::webaudio -{ -class WriteBuffer : public IPlayerTask -{ -public: - WriteBuffer(WebAudioPlayerContext &context, std::shared_ptr gstWrapper, - uint8_t *mainPtr, uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength); - ~WriteBuffer() override; - void execute() const override; - -private: - WebAudioPlayerContext &m_context; - std::shared_ptr m_gstWrapper; - const uint8_t *m_mainPtr; - const uint64_t m_mainLength; - const uint8_t *m_wrapPtr; - const uint64_t m_wrapLength; -}; -} // namespace firebolt::rialto::server::tasks::webaudio - -#endif // FIREBOLT_RIALTO_SERVER_TASKS_WEBAUDIO_WRITE_BUFFER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstCapabilities.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstCapabilities.h deleted file mode 100644 index 1d0780ce6..000000000 --- a/middleware/rialto-client/media/server/gstplayer/interface/IGstCapabilities.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_CAPABILITIES_H_ - -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IGstCapabilities; - -/** - * @brief IGstCapabilities factory class, returns a concrete implementation of IGstCapabilities - */ -class IGstCapabilitiesFactory -{ -public: - IGstCapabilitiesFactory() = default; - virtual ~IGstCapabilitiesFactory() = default; - - /** - * @brief Gets the IGstCapabilitiesFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Creates a IGstCapabilities object. - * - * - * @retval the new gstreamer capabilities instance or null on error. - */ - virtual std::unique_ptr createGstCapabilities() = 0; -}; - -class IGstCapabilities -{ -public: - IGstCapabilities() = default; - virtual ~IGstCapabilities() = default; - - IGstCapabilities(const IGstCapabilities &) = delete; - IGstCapabilities &operator=(const IGstCapabilities &) = delete; - IGstCapabilities(IGstCapabilities &&) = delete; - IGstCapabilities &operator=(IGstCapabilities &&) = delete; - - /** - * @brief Gets vector of mime types supported by gstreamer - * - * @retval vector of mime types supported by gstreamer - */ - virtual std::vector getSupportedMimeTypes(MediaSourceType sourceType) = 0; - - /** - * @brief Checks is \a mimeType is supported by gstreamer - * - * @retval True if mime type is supported by gstreamer - */ - virtual bool isMimeTypeSupported(const std::string &mimeType) = 0; - - /** - * @brief Check sinks and decoders for supported properties - * - * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched - * @param[in] propertyNames : A vector of property names to look for - * - * @retval Returns the subset of propertyNames that are supported by the mediaType - */ - virtual std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) = 0; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - virtual bool isVideoMaster(bool &isVideoMaster) = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayer.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayer.h deleted file mode 100644 index 74bc67919..000000000 --- a/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayer.h +++ /dev/null @@ -1,460 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_H_ - -#include -#include -#include -#include - -#include "IDataReader.h" -#include "IDecryptionService.h" -#include "IGstGenericPlayerClient.h" -#include "IHeartbeatHandler.h" -#include "IMediaPipeline.h" -#include "IRdkGstreamerUtilsWrapper.h" - -namespace firebolt::rialto::server -{ -class IGstGenericPlayer; - -/** - * @brief IGstGenericPlayer factory class, returns a concrete implementation of IGstGenericPlayer - */ -class IGstGenericPlayerFactory -{ -public: - IGstGenericPlayerFactory() = default; - virtual ~IGstGenericPlayerFactory() = default; - - /** - * @brief Gets the IGstGenericPlayerFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Creates a IGstGenericPlayer object. - * - * @param[in] client : The gstreamer player client. - * @param[in] decryptionService : The decryption service. - * @param[in] type : The media type the gstreamer player shall support. - * @param[in] videoRequirements : The video requirements for the playback. - * - * @retval the new player instance or null on error. - */ - virtual std::unique_ptr - createGstGenericPlayer(IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, - const VideoRequirements &videoRequirements, - const std::shared_ptr - &rdkGstreamerUtilsWrapperFactory) = 0; -}; - -class IGstGenericPlayer -{ -public: - IGstGenericPlayer() = default; - virtual ~IGstGenericPlayer() = default; - - IGstGenericPlayer(const IGstGenericPlayer &) = delete; - IGstGenericPlayer &operator=(const IGstGenericPlayer &) = delete; - IGstGenericPlayer(IGstGenericPlayer &&) = delete; - IGstGenericPlayer &operator=(IGstGenericPlayer &&) = delete; - - /** - * @brief Attaches a source to gstreamer. - * - * @param[in] mediaSource : The media source. - * - */ - virtual void attachSource(const std::unique_ptr &mediaSource) = 0; - - /** - * @brief Unattaches a source. - * - * @param[in] mediaSourceType : The media source type. - * - */ - virtual void removeSource(const MediaSourceType &mediaSourceType) = 0; - - /** - * @brief Handles notification that all sources were attached - * - */ - virtual void allSourcesAttached() = 0; - - /** - * @brief Starts playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request playback and then return. - * - * Once the backend is successfully playing it should notify the - * media player client of playback state PlaybackState::PLAYING. - * - */ - virtual void play() = 0; - - /** - * @brief Pauses playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the playback pause and then return. - * - * Once the backend is successfully paused it should notify the - * media player client of playback state PlaybackState::PAUSED. - * - */ - virtual void pause() = 0; - - /** - * @brief Stops playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the playback stop and then return. - * - * Once the backend is successfully stopped it should notify the - * media player client of playback state PlaybackState::STOPPED. - * - */ - virtual void stop() = 0; - - /** - * @brief Sets video geometry - * - * @param[in] x : X position of rectangle on video - * @param[in] y : Y position of rectangle on video - * @param[in] width : width of rectangle - * @param[in] height : height of rectangle - * - */ - virtual void setVideoGeometry(int x, int y, int width, int height) = 0; - - /** - * @brief Queues the end of stream notification at the end of the gstreamer buffers. - * - * @param[in] type : the media source type to set eos - * - */ - virtual void setEos(const firebolt::rialto::MediaSourceType &type) = 0; - - /** - * @brief Attaches new samples - * - * This method is considered to be asynchronous and MUST NOT block - * but should request to attach new sample and then return. - */ - virtual void attachSamples(const IMediaPipeline::MediaSegmentVector &mediaSegments) = 0; - - /** - * @brief Attaches new samples - * - * This method is considered to be asynchronous and MUST NOT block - * but should request to attach new sample and then return. - */ - virtual void attachSamples(const std::shared_ptr &dataReader) = 0; - - /** - * @brief Set the playback position in nanoseconds. - * - * If playback has not started this method sets the start position - * for playback. If playback has started this method performs a seek. - * - * @param[in] position : The playback position in nanoseconds. - * - */ - virtual void setPosition(std::int64_t position) = 0; - - /** - * @brief Get the playback position in nanoseconds. - * - * @param[out] position : The playback position in nanoseconds. - * - * @retval True on success - */ - virtual bool getPosition(std::int64_t &position) = 0; - - /** - * @brief Sets the "Immediate Output" property for this source. - * - * @param[in] mediaSourceType : The media source type - * @param[in] immediateOutput : Set immediate output mode on the sink - * - * @retval true on success. - */ - virtual bool setImmediateOutput(const MediaSourceType &mediaSourceType, bool immediateOutput) = 0; - - /** - * @brief Gets the "Immediate Output" property for this source. - * - * @param[in] mediaSourceType : The media source type - * @param[out] immediateOutput : Get immediate output mode on the sink - * - * @retval true on success. - */ - virtual bool getImmediateOutput(const MediaSourceType &mediaSourceType, bool &immediateOutput) = 0; - - /** - * @brief Get stats for this source. - * - * @param[in] mediaSourceType : The media source type to get stats for - * @param[out] renderedFrames : The number of rendered frames - * @param[out] droppedFrames : The number of dropped frames - * - * @retval true on success. - */ - virtual bool getStats(const MediaSourceType &mediaSourceType, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; - - /** - * @brief Set the playback rate. - * - * @param[in] rate : The playback rate. - * - */ - virtual void setPlaybackRate(double rate) = 0; - - /** - * @brief Requests to render a prerolled frame - * - */ - virtual void renderFrame() = 0; - - /** - * @brief Set level and transition of audio attenuation. - * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume) - * - * @param[in] volume : Target volume level (0.0 - 1.0) - */ - virtual void setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType) = 0; - - /** - * @brief Get current audio level. Fetches the current volume level for the pipeline. - * - * @param[out] volume : Current volume level (range 0.0 - 1.0) - * - * @retval True on success - */ - virtual bool getVolume(double &volume) = 0; - - /** - * @brief Set mute status of pipeline - * - * Muting does not change the underlying volyme setting so when - * unmuted the user will hear audio at the same volume as previously - * set. - * - * @param[in] mute : Desired mute state, true=muted, false=not muted - */ - virtual void setMute(const MediaSourceType &mediaSourceType, bool mute) = 0; - - /** - * @brief Get current mute status of the pipeline - * - * @param[out] mute : Current mute state - * - * @retval True in success, false otherwise - */ - virtual bool getMute(const MediaSourceType &mediaSourceType, bool &mute) = 0; - - /** - * @brief Change Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - virtual void setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; - - /** - * @brief Get Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; - - /** - * @brief Set low latency property on the pipeline. Default false. - * - * @param[in] lowLatency : The low latency value to set. - * - * @retval true on success false otherwise - */ - virtual bool setLowLatency(bool lowLatency) = 0; - - /** - * @brief Set sync property on the pipeline. Default false. - * - * @param[in] sync : The sync value to set. - * - * @retval true on success false otherwise - */ - virtual bool setSync(bool sync) = 0; - - /** - * @brief Get sync property on the pipeline. - * - * @param[out] sync : Current sync value. - * - * @retval true on success false otherwise - */ - virtual bool getSync(bool &sync) = 0; - - /** - * @brief Set sync off property on the pipeline. Default false. - * - * @param[in] syncOff : The sync off value to set. - * - * @retval true on success false otherwise - */ - virtual bool setSyncOff(bool syncOff) = 0; - - /** - * @brief Set stream sync mode property on the pipeline. Default 0. - * - * @param[in] mediaSourceType : The media source type to set stream sync mode. - * @param[in] streamSyncMode : The stream sync mode value to set. - * - * @retval true on success false otherwise - */ - virtual bool setStreamSyncMode(const MediaSourceType &mediaSourceType, int32_t streamSyncMode) = 0; - - /** - * @brief Get stream sync mode property on the pipeline. - * - * @param[out] streamSyncMode : Current stream sync mode value. - * - * @retval true on success false otherwise - */ - virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; - - /** - * @brief Checks if worker thread is not deadlocked - * - * @param[out] heartbeatHandler : The heartbeat handler instance - * - */ - virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; - - /** - * @brief Flushes a source. - * - * @param[in] mediaSourceType : The media source type to flush. - * @param[in] resetTime : True if time should be reset - * @param[out] async : True if flushed source is asynchronous (will preroll after flush) - * - */ - virtual void flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) = 0; - - /** - * @brief Set the source position in nanoseconds. - * - * This method sets the start position for a source. - * - * @param[in] mediaSourceType : The media source type to flush. - * @param[in] position : The position in nanoseconds. - * @param[in] resetTime : True if time should be reset - * @param[in] appliedRate : The applied rate after seek - * @param[in] stopPosition : The position of last pushed buffer - */ - virtual void setSourcePosition(const MediaSourceType &mediaSourceType, int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) = 0; - - /** - * @brief Sets the subtitle offset. - * - * This method sets the subtitle offset to synchronize subtitle timing. - * - * @param[in] position : The subtitle offset position in nanoseconds. - */ - virtual void setSubtitleOffset(int64_t position) = 0; - - /** - * @brief Process audio gap - * - * This method handles audio gap in order to avoid audio pops during transitions. - * - * @param[in] position : Audio pts fade position value - * @param[in] duration : Audio pts fade duration - * @param[in] discontinuityGap : Audio discontinuity gap - * @param[in] audioAac : True if audio codec is AAC - */ - virtual void processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; - - /** - * @brief Set buffering limit - * - * This method enables/disables limit buffering and sets millisecond threshold used. - * Use kInvalidLimitBuffering to disable limit buffering - * - * @param[in] limitBufferingMs : buffering limit in ms - * - */ - virtual void setBufferingLimit(uint32_t limitBufferingMs) = 0; - - /** - * @brief Get buffering limit - * - * This method returns current value of buffering limit in milliseconds - * Method will return kInvalidLimitBuffering limit buffering is disabled - * - * @param[out] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; - - /** - * @brief Enables/disables the buffering option - * - * This method enables the buffering option so that BUFFERING messages are - * emitted based on low-/high-percent thresholds. - * - * @param[in] useBuffering : true if buffering option enabled. - * - */ - virtual void setUseBuffering(bool useBuffering) = 0; - - /** - * @brief Checks, if buffering is enabled - * - * This method returns true, if buffering is enabled - * - * @param[out] useBuffering : true if buffering option is enabled. - * - * @retval true on success. - */ - virtual bool getUseBuffering(bool &useBuffering) = 0; - - /** - * @brief Switches a source. - * - * @param[in] mediaSource : The media source. - * - */ - virtual void switchSource(const std::unique_ptr &mediaSource) = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayerClient.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayerClient.h deleted file mode 100644 index 29925b5d8..000000000 --- a/middleware/rialto-client/media/server/gstplayer/interface/IGstGenericPlayerClient.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_CLIENT_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_CLIENT_H_ - -#include -#include -#include - -/** - * @file IGstGenericPlayerClient.h - * - * The definition of the IGstGenericPlayerClient interface. - * - * This file comprises the definition of the IGstGenericPlayerClient abstract - * class. This is the API by which a IGstGenericPlayer implementation will - * pass notifications to its client. - */ - -namespace firebolt::rialto::server -{ -/** - * @brief The Rialto gstreamer player client interface. - * - * This is The Rialto gstreamer player client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the - * state of the gstreamer player or that provides data for playback. - */ -class IGstGenericPlayerClient -{ -public: - IGstGenericPlayerClient() = default; - virtual ~IGstGenericPlayerClient() = default; - - IGstGenericPlayerClient(const IGstGenericPlayerClient &) = delete; - IGstGenericPlayerClient &operator=(const IGstGenericPlayerClient &) = delete; - IGstGenericPlayerClient(IGstGenericPlayerClient &&) = delete; - IGstGenericPlayerClient &operator=(IGstGenericPlayerClient &&) = delete; - - /** - * @brief Notifies the client of the playback state. - * - * The player will start IDLE. Once play() has been called the player - * will be PLAYING, or once pause() has been called the player will be - * PAUSED. A seek() request will result in SEEKING and once the seek - * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED - * state will be issued after a stop() request. - * - * @param[in] state : The new playback state. - */ - virtual void notifyPlaybackState(PlaybackState state) = 0; - - /** - * @brief Notifies the client that we need media data. - * - * This method notifies the client that we need media data from the - * client. This is only used when Media Source Extensions are used. - * In that case media is read by JavaScript and buffered by the - * browser before being passed to this API for decoding. - * - * You cannot request data if a data request is currently pending. - * - * The frames the client sends should meet the criteria: - * numFramesSent <= frameCount - * numBytesSent <= maxBytes - * - * @param[in] mediaSourceType : The media type of source to read data from. - * - * @retval True on success. - */ - virtual bool notifyNeedMediaData(MediaSourceType mediaSourceType) = 0; - - /** - * @brief Notifies the client of the current playback position. - * - * This method notifies the client of the current playback position - * in nanoseconds. - * - * When playing this should be called often enough to provide - * sufficient granularity of position reporting. Typically this will - * be every 0.25s. - * - * @param[in] position : The playback position in nanoseconds. - * - */ - virtual void notifyPosition(std::int64_t position) = 0; - - /** - * @brief Notifies the client of the network state. - * - * The network state reflects the state of the network. For backend - * streaming, say using MediaPipelineURLDelegate, this is important - * as the backend uses the network to obtain the media data directly. - * - * For streaming that uses the browser to obtain data, say Media Source - * Extensions playback, only the states NetworkState::IDLE, - * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be - * indicated by the backend. - * - * @param[in] state : The new network state. - * - */ - virtual void notifyNetworkState(NetworkState state) = 0; - - /** - * @brief Clears all active NeedMediaDataRequests cache for session - * - */ - virtual void clearActiveRequestsCache() = 0; - - /** - * @brief Clears all active NeedMediaDataRequests cache for given Media Source Type - * - * @param[in] type : Media source type. - * - */ - virtual void invalidateActiveRequests(const MediaSourceType &type) = 0; - - /** - * @brief Notifies the client of a Quality Of Service update from the Player. - * - * @param[in] qosInfo : The Qos infomation extracted from the message. - * @param[in] sourceType : The type of source that sent the message. - */ - virtual void notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo) = 0; - - /** - * @brief Notifies the client that buffer underflow occurred. - * - * Notification shall be sent whenever a video/audio buffer underflow occurs - * - * @param[in] mediaSourceType : The type of the source that produced the buffer underflow - */ - virtual void notifyBufferUnderflow(MediaSourceType mediaSourceType) = 0; - - /** - * @brief Notifies the client that a non-fatal error has occurred in the player. - * - * PlaybackState remains unchanged when an error occurs. - * - * @param[in] mediaSourceType : The type of the source that produced the error. - * @param[in] error : The type of error that occurred. - */ - virtual void notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error) = 0; - - /** - * @brief Notifies the client that the source has been flushed. - * - * Notification shall be sent whenever a flush procedure is finished. - * - * @param[in] mediaSourceType : The type of the source that has been flushed. - */ - virtual void notifySourceFlushed(MediaSourceType mediaSourceType) = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_GENERIC_PLAYER_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstInitialiser.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstInitialiser.h deleted file mode 100644 index 75972ed10..000000000 --- a/middleware/rialto-client/media/server/gstplayer/interface/IGstInitialiser.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_INITIALISER_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_INITIALISER_H_ - -namespace firebolt::rialto::server -{ -class IGstInitialiser -{ -protected: - IGstInitialiser() = default; - virtual ~IGstInitialiser() = default; - IGstInitialiser(const IGstInitialiser &) = delete; - IGstInitialiser(IGstInitialiser &&) = delete; - IGstInitialiser &operator=(const IGstInitialiser &) = delete; - IGstInitialiser &operator=(IGstInitialiser &&) = delete; - -public: - static IGstInitialiser &instance(); - virtual void initialise(int *argc, char ***argv) = 0; - virtual void waitForInitialisation() const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_INITIALISER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayer.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayer.h deleted file mode 100644 index f72ca12c3..000000000 --- a/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayer.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_H_ - -#include "IGstWebAudioPlayerClient.h" -#include "IHeartbeatHandler.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IGstWebAudioPlayer; - -/** - * @brief IGstWebAudioPlayer factory class, returns a concrete implementation of IGstWebAudioPlayer - */ -class IGstWebAudioPlayerFactory -{ -public: - IGstWebAudioPlayerFactory() = default; - virtual ~IGstWebAudioPlayerFactory() = default; - - /** - * @brief Gets the IGstWebAudioPlayerFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Creates a IGstWebAudioPlayer object. - * - * @param[in] client : The gstreamer web audio player client. - * @param[in] priority : Priority value for this pipeline. - * - * @retval the new player instance or null on error. - */ - virtual std::unique_ptr createGstWebAudioPlayer(IGstWebAudioPlayerClient *client, - const uint32_t priority) = 0; -}; - -class IGstWebAudioPlayer -{ -public: - IGstWebAudioPlayer() = default; - virtual ~IGstWebAudioPlayer() = default; - - IGstWebAudioPlayer(const IGstWebAudioPlayer &) = delete; - IGstWebAudioPlayer &operator=(const IGstWebAudioPlayer &) = delete; - IGstWebAudioPlayer(IGstWebAudioPlayer &&) = delete; - IGstWebAudioPlayer &operator=(IGstWebAudioPlayer &&) = delete; - - /** - * @brief Sets the capabilities on the audio source. - * - * @param[in] audioMimeType: The audio encoding format, currently only "audio/x-raw" (PCM). - * @param[in] config: Additional type dependent configuration data or nullptr, - */ - virtual void setCaps(const std::string &audioMimeType, std::weak_ptr config) = 0; - - /** - * @brief Starts playback of the web audio. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request playback and then return. - * - * Once the backend is successfully playing it should notify the - * web audio player client of state WebAudioPlayerState::PLAYING. - */ - virtual void play() = 0; - - /** - * @brief Pauses playback of the web audio. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the playback pause and then return. - * - * Once the backend is successfully paused it should notify the - * web audio player client of state WebAudioPlayerState::PAUSED. - */ - virtual void pause() = 0; - - /** - * @brief Set level and transition of audio attenuation. - * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume). - * - * @param[in] volume : Target volume level (0.0 - 1.0) - */ - virtual void setVolume(double volume) = 0; - - /** - * @brief Get current audio level. Fetches the current volume level for the pipeline. - * - * @param[out] volume : Current volume level (range 0.0 - 1.0) - * - * @retval True on success. - */ - virtual bool getVolume(double &volume) = 0; - - /** - * @brief Write the buffer to gstreamer buffer. - * - * @param[in] mainPtr : Pointer to the start of the data. - * @param[in] mainLength : Amount of bytes to write from the mainPtr. - * @param[in] wrapPtr : Pointer to the start of the wrapped data. - * @param[in] wrapLength : Amount of bytes to write from the wrapPtr. - * - * @retval The number of bytes written to gstreamer. - */ - virtual uint32_t writeBuffer(uint8_t *mainPtr, uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength) = 0; - - /** - * @brief Notify EOS at the end of the gstreamer buffers. - */ - virtual void setEos() = 0; - - /** - * @brief Gets the amount of bytes queued for playback on the app source. - * - * @retval The number of bytes queued. - */ - virtual uint64_t getQueuedBytes() = 0; - - /** - * @brief Checks if worker thread is not deadlocked - * - * @param[out] heartbeatHandler : The heartbeat handler instance - * - */ - virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayerClient.h b/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayerClient.h deleted file mode 100644 index 7c505fd08..000000000 --- a/middleware/rialto-client/media/server/gstplayer/interface/IGstWebAudioPlayerClient.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_CLIENT_H_ -#define FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_CLIENT_H_ - -#include -#include - -/** - * @file IGstWebAudioPlayerClient.h - * - * The definition of the IGstWebAudioPlayerClient interface. - * - * This file comprises the definition of the IGstWebAudioPlayerClient abstract - * class. This is the API by which a IGstWebAudioPlayer implementation will - * pass notifications to its client. - */ - -namespace firebolt::rialto::server -{ -/** - * @brief The Rialto gstreamer player client interface. - * - * This is The Rialto gstreamer player client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the - * state of the gstreamer player or that provides data for playback. - */ -class IGstWebAudioPlayerClient -{ -public: - IGstWebAudioPlayerClient() = default; - virtual ~IGstWebAudioPlayerClient() = default; - - IGstWebAudioPlayerClient(const IGstWebAudioPlayerClient &) = delete; - IGstWebAudioPlayerClient &operator=(const IGstWebAudioPlayerClient &) = delete; - IGstWebAudioPlayerClient(IGstWebAudioPlayerClient &&) = delete; - IGstWebAudioPlayerClient &operator=(IGstWebAudioPlayerClient &&) = delete; - - /** - * @brief Notifies the client of the web audio state. - * - * The player will start IDLE. Once play() has been called the player - * will be PLAYING, or once pause() has been called the player will be - * PAUSED. Once the stream has reached end of the media EOS wibe notified. - * - * @param[in] state : The new web audio state. - */ - virtual void notifyState(WebAudioPlayerState state) = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_GST_WEB_AUDIO_PLAYER_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/gstplayer/source/CapsBuilder.cpp b/middleware/rialto-client/media/server/gstplayer/source/CapsBuilder.cpp deleted file mode 100644 index 55713943a..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/CapsBuilder.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "CapsBuilder.h" -#include "GstMimeMapping.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server -{ -MediaSourceCapsBuilder::MediaSourceCapsBuilder(std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const firebolt::rialto::IMediaPipeline::MediaSourceAV &source) - : m_gstWrapper(gstWrapper), m_glibWrapper(glibWrapper), m_attachedSource(source) -{ -} -GstCaps *MediaSourceCapsBuilder::buildCaps() -{ - return buildCommonCaps(); -} - -GstCaps *MediaSourceCapsBuilder::buildCommonCaps() -{ - GstCaps *caps = firebolt::rialto::server::createSimpleCapsFromMimeType(m_gstWrapper, m_attachedSource); - - addAlignmentToCaps(caps); - addCodecDataToCaps(caps); - addStreamFormatToCaps(caps); - - return caps; -} - -void MediaSourceCapsBuilder::addAlignmentToCaps(GstCaps *caps) const -{ - static const std::unordered_map aligmentMap = - {{firebolt::rialto::SegmentAlignment::AU, "au"}, {firebolt::rialto::SegmentAlignment::NAL, "nal"}}; - - auto aligmentMapIt = aligmentMap.find(m_attachedSource.getSegmentAlignment()); - if (aligmentMapIt != aligmentMap.end()) - { - m_gstWrapper->gstCapsSetSimple(caps, "alignment", G_TYPE_STRING, aligmentMapIt->second.c_str(), nullptr); - } -} - -void MediaSourceCapsBuilder::addCodecDataToCaps(GstCaps *caps) const -{ - const std::shared_ptr &kCodecData = m_attachedSource.getCodecData(); - if (kCodecData && CodecDataType::BUFFER == kCodecData->type) - { - gpointer memory = m_glibWrapper->gMemdup(kCodecData->data.data(), kCodecData->data.size()); - GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, kCodecData->data.size()); - m_gstWrapper->gstCapsSetSimple(caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr); - m_gstWrapper->gstBufferUnref(buf); - } - else if (kCodecData && CodecDataType::STRING == kCodecData->type) - { - std::string codecDataStr{kCodecData->data.begin(), kCodecData->data.end()}; - m_gstWrapper->gstCapsSetSimple(caps, "codec_data", G_TYPE_STRING, codecDataStr.c_str(), nullptr); - } -} - -void MediaSourceCapsBuilder::addStreamFormatToCaps(GstCaps *caps) const -{ - static const std::unordered_map formatMap = - {{firebolt::rialto::StreamFormat::RAW, "raw"}, - {firebolt::rialto::StreamFormat::AVC, "avc"}, - {firebolt::rialto::StreamFormat::BYTE_STREAM, "byte-stream"}, - {firebolt::rialto::StreamFormat::HVC1, "hvc1"}, - {firebolt::rialto::StreamFormat::HEV1, "hev1"}}; - - auto formatMapIt = formatMap.find(m_attachedSource.getStreamFormat()); - if (formatMapIt != formatMap.end()) - { - m_gstWrapper->gstCapsSetSimple(caps, "stream-format", G_TYPE_STRING, formatMapIt->second.c_str(), nullptr); - } -} - -MediaSourceAudioCapsBuilder::MediaSourceAudioCapsBuilder( - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, const IMediaPipeline::MediaSourceAudio &source) - : MediaSourceCapsBuilder(gstWrapper, glibWrapper, source), m_attachedAudioSource(source) -{ -} - -GstCaps *MediaSourceAudioCapsBuilder::buildCaps() -{ - std::string mimeType = m_attachedSource.getMimeType(); - if (mimeType == "audio/x-opus") - { - return createOpusCaps(); - } - - GstCaps *caps = MediaSourceCapsBuilder::buildCaps(); - if (mimeType == "audio/mp4" || mimeType == "audio/aac") - { - addMpegVersion4ToCaps(caps); - } - else if (mimeType == "audio/mp3") - { - addMp3Caps(caps); - } - else if (mimeType == "audio/b-wav" || mimeType == "audio/x-raw") - { - addRawAudioData(caps); - } - else if (mimeType == "audio/x-flac") - { - addFlacSpecificData(caps); - } - addSampleRateAndChannelsToCaps(caps); - - return caps; -} - -GstCaps *MediaSourceAudioCapsBuilder::createOpusCaps() -{ - GstCaps *caps = getAudioSpecificConfiguration(); - if (!caps) - { - caps = m_gstWrapper->gstCapsNewSimple("audio/x-opus", "channel-mapping-family", G_TYPE_INT, 0, nullptr); - addSampleRateAndChannelsToCaps(caps); - } - - return caps; -} - -GstCaps *MediaSourceAudioCapsBuilder::getAudioSpecificConfiguration() const -{ - GstCaps *caps = nullptr; - firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); - if (audioConfig.codecSpecificConfig.size()) - { - gsize codec_priv_size = audioConfig.codecSpecificConfig.size(); - gconstpointer codec_priv = audioConfig.codecSpecificConfig.data(); - - caps = m_gstWrapper->gstCodecUtilsOpusCreateCapsFromHeader(codec_priv, codec_priv_size); - if (!caps) - { - RIALTO_SERVER_LOG_ERROR("Failed to parse opus header"); - } - } - - return caps; -} - -void MediaSourceAudioCapsBuilder::addSampleRateAndChannelsToCaps(GstCaps *caps) const -{ - firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); - - if (audioConfig.numberOfChannels != firebolt::rialto::kInvalidAudioChannels) - m_gstWrapper->gstCapsSetSimple(caps, "channels", G_TYPE_INT, audioConfig.numberOfChannels, nullptr); - - if (audioConfig.sampleRate != firebolt::rialto::kInvalidAudioSampleRate) - m_gstWrapper->gstCapsSetSimple(caps, "rate", G_TYPE_INT, audioConfig.sampleRate, nullptr); -} - -void MediaSourceAudioCapsBuilder::addMpegVersion4ToCaps(GstCaps *caps) const -{ - m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 4, nullptr); -} - -void MediaSourceAudioCapsBuilder::addMp3Caps(GstCaps *caps) const -{ - m_gstWrapper->gstCapsSetSimple(caps, "mpegversion", G_TYPE_INT, 1, nullptr); - m_gstWrapper->gstCapsSetSimple(caps, "layer", G_TYPE_INT, 3, nullptr); -} - -void MediaSourceAudioCapsBuilder::addRawAudioData(GstCaps *caps) const -{ - firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); - if (audioConfig.format.has_value()) - m_gstWrapper->gstCapsSetSimple(caps, "format", G_TYPE_STRING, common::convertFormat(audioConfig.format.value()), - nullptr); - if (audioConfig.layout.has_value()) - m_gstWrapper->gstCapsSetSimple(caps, "layout", G_TYPE_STRING, common::convertLayout(audioConfig.layout.value()), - nullptr); - if (audioConfig.channelMask.has_value()) - m_gstWrapper->gstCapsSetSimple(caps, "channel-mask", GST_TYPE_BITMASK, audioConfig.channelMask.value(), nullptr); -} - -void MediaSourceAudioCapsBuilder::addFlacSpecificData(GstCaps *caps) const -{ - firebolt::rialto::AudioConfig audioConfig = m_attachedAudioSource.getAudioConfig(); - if (audioConfig.streamHeader.size()) - { - GValue streamHeaderArray = G_VALUE_INIT; - m_glibWrapper->gValueInit(&streamHeaderArray, GST_TYPE_ARRAY); - for (const auto &header : audioConfig.streamHeader) - { - gpointer memory = m_glibWrapper->gMemdup(header.data(), header.size()); - GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, header.size()); - GST_BUFFER_FLAG_SET(buf, GST_BUFFER_FLAG_HEADER); - - GValue value = G_VALUE_INIT; - m_glibWrapper->gValueInit(&value, GST_TYPE_BUFFER); - m_gstWrapper->gstValueSetBuffer(&value, buf); - m_gstWrapper->gstValueArrayAppendValue(&streamHeaderArray, &value); - - m_glibWrapper->gValueUnset(&value); - m_gstWrapper->gstBufferUnref(buf); - } - m_gstWrapper->gstStructureSetValue(m_gstWrapper->gstCapsGetStructure(caps, 0), "streamheader", - &streamHeaderArray); - m_glibWrapper->gValueUnset(&streamHeaderArray); - } - if (audioConfig.framed.has_value()) - { - m_gstWrapper->gstCapsSetSimple(caps, "framed", G_TYPE_BOOLEAN, audioConfig.framed.value(), nullptr); - } -} - -MediaSourceVideoCapsBuilder::MediaSourceVideoCapsBuilder( - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, const IMediaPipeline::MediaSourceVideo &source) - : MediaSourceCapsBuilder(gstWrapper, glibWrapper, source), m_attachedVideoSource(source) -{ -} - -GstCaps *MediaSourceVideoCapsBuilder::buildCaps() -{ - GstCaps *caps = MediaSourceCapsBuilder::buildCaps(); - if (m_attachedVideoSource.getWidth() != firebolt::rialto::kUndefinedSize) - m_gstWrapper->gstCapsSetSimple(caps, "width", G_TYPE_INT, m_attachedVideoSource.getWidth(), nullptr); - if (m_attachedVideoSource.getHeight() != firebolt::rialto::kUndefinedSize) - m_gstWrapper->gstCapsSetSimple(caps, "height", G_TYPE_INT, m_attachedVideoSource.getHeight(), nullptr); - - return caps; -} - -MediaSourceVideoDolbyVisionCapsBuilder::MediaSourceVideoDolbyVisionCapsBuilder( - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const IMediaPipeline::MediaSourceVideoDolbyVision &source) - : MediaSourceVideoCapsBuilder(gstWrapper, glibWrapper, source), m_attachedDolbySource(source) -{ -} - -GstCaps *MediaSourceVideoDolbyVisionCapsBuilder::buildCaps() -{ - GstCaps *caps = MediaSourceVideoCapsBuilder::buildCaps(); - m_gstWrapper->gstCapsSetSimple(caps, "dovi-stream", G_TYPE_BOOLEAN, true, nullptr); - m_gstWrapper->gstCapsSetSimple(caps, "dv_profile", G_TYPE_UINT, m_attachedDolbySource.getDolbyVisionProfile(), - nullptr); - return caps; -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/FlushWatcher.cpp b/middleware/rialto-client/media/server/gstplayer/source/FlushWatcher.cpp deleted file mode 100644 index b1c63d686..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/FlushWatcher.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "FlushWatcher.h" -#include - -namespace firebolt::rialto::server -{ -void FlushWatcher::setFlushing(const MediaSourceType &type, bool async) -{ - std::unique_lock lock{m_mutex}; - if (MediaSourceType::UNKNOWN != type) - { - m_flushingSources[type] = async; - } -} - -void FlushWatcher::setFlushed(const MediaSourceType &type) -{ - std::unique_lock lock{m_mutex}; - m_flushingSources.erase(type); -} - -bool FlushWatcher::isFlushOngoing() const -{ - std::unique_lock lock{m_mutex}; - return !m_flushingSources.empty(); -} - -bool FlushWatcher::isAsyncFlushOngoing() const -{ - std::unique_lock lock{m_mutex}; - return !m_flushingSources.empty() && std::any_of(m_flushingSources.begin(), m_flushingSources.end(), - [](const auto &source) { return source.second; }); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstCapabilities.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstCapabilities.cpp deleted file mode 100644 index d5d0a33ed..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstCapabilities.cpp +++ /dev/null @@ -1,464 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include "GstCapabilities.h" -#include "GstMimeMapping.h" -#include "RialtoServerLogging.h" - -namespace -{ -const char *toString(const GstElementFactoryListType &listType) -{ - switch (listType) - { - case GST_ELEMENT_FACTORY_TYPE_ANY: - return "Any"; - case GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS: - return "AudioVideo Sinks"; - case GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER: - return "Audio Encoder"; - case GST_ELEMENT_FACTORY_TYPE_DECODABLE: - return "Decodable"; - case GST_ELEMENT_FACTORY_TYPE_DECODER: - return "Decoder"; - case GST_ELEMENT_FACTORY_TYPE_DECRYPTOR: - return "Decryptor"; - case GST_ELEMENT_FACTORY_TYPE_DEMUXER: - return "Demuxer"; - case GST_ELEMENT_FACTORY_TYPE_DEPAYLOADER: - return "Depayloader"; - case GST_ELEMENT_FACTORY_TYPE_ENCODER: - return "Encoder"; - case GST_ELEMENT_FACTORY_TYPE_ENCRYPTOR: - return "Encryptor"; - case GST_ELEMENT_FACTORY_TYPE_FORMATTER: - return "Formatter"; - case GST_ELEMENT_FACTORY_TYPE_HARDWARE: - return "Hardware"; - case GST_ELEMENT_FACTORY_TYPE_MAX_ELEMENTS: - return "Max Elements"; - case GST_ELEMENT_FACTORY_TYPE_MEDIA_ANY: - return "Media Any"; - case GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO: - return "Media Audio"; - case GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE: - return "Media Image"; - case GST_ELEMENT_FACTORY_TYPE_MEDIA_METADATA: - return "Media Metadata"; - case GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE: - return "Media Subtitle"; - case GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO: - return "Media Video"; - case GST_ELEMENT_FACTORY_TYPE_MUXER: - return "Muxer"; - case GST_ELEMENT_FACTORY_TYPE_PARSER: - return "Parser"; - case GST_ELEMENT_FACTORY_TYPE_PAYLOADER: - return "Payloader"; - case GST_ELEMENT_FACTORY_TYPE_SINK: - return "Sink"; - case GST_ELEMENT_FACTORY_TYPE_SRC: - return "Source"; - case GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER: - return "Video Encoder"; - default: - return "Unknown"; - } -} -} // namespace - -namespace firebolt::rialto::server -{ -std::weak_ptr GstCapabilitiesFactory::m_factory; - -std::shared_ptr IGstCapabilitiesFactory::getFactory() -{ - std::shared_ptr factory = GstCapabilitiesFactory::m_factory.lock(); - - if (!factory) - { - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer capabilities factory, reason: %s", e.what()); - } - - GstCapabilitiesFactory::m_factory = factory; - } - - return factory; -} - -std::unique_ptr GstCapabilitiesFactory::createGstCapabilities() -{ - std::unique_ptr gstCapabilities; - try - { - std::shared_ptr gstWrapperFactory = - firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); - std::shared_ptr gstWrapper; - - if ((!gstWrapperFactory) || (!(gstWrapper = gstWrapperFactory->getGstWrapper()))) - { - throw std::runtime_error("Cannot create GstWrapper"); - } - - std::shared_ptr glibWrapperFactory = - firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(); - std::shared_ptr glibWrapper; - - if ((!glibWrapperFactory) || (!(glibWrapper = glibWrapperFactory->getGlibWrapper()))) - { - throw std::runtime_error("Cannot create GlibWrapper"); - } - - std::shared_ptr rdkGstreamerUtilsWrapperFactory = - firebolt::rialto::wrappers::IRdkGstreamerUtilsWrapperFactory::getFactory(); - std::shared_ptr rdkGstreamerUtilsWrapper; - - if ((!rdkGstreamerUtilsWrapperFactory) || - (!(rdkGstreamerUtilsWrapper = rdkGstreamerUtilsWrapperFactory->createRdkGstreamerUtilsWrapper()))) - { - throw std::runtime_error("Cannot create RdkGstreamerUtilsWrapper"); - } - - gstCapabilities = std::make_unique(gstWrapper, glibWrapper, rdkGstreamerUtilsWrapper, - IGstInitialiser::instance()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer capabilities, reason: %s", e.what()); - } - - return gstCapabilities; -} - -GstCapabilities::GstCapabilities( - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr &rdkGstreamerUtilsWrapper, - const IGstInitialiser &gstInitialiser) - : m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, - m_gstInitialiser{gstInitialiser} -{ - m_initialisationThread = std::thread( - [this]() - { - std::unique_lock lock{m_initialisationMutex}; - - m_gstInitialiser.waitForInitialisation(); - fillSupportedMimeTypes(); - m_isInitialised = true; - m_initialisationCv.notify_all(); - }); -} - -GstCapabilities::~GstCapabilities() -{ - if (m_initialisationThread.joinable()) - { - m_initialisationThread.join(); - } -} - -std::vector GstCapabilities::getSupportedMimeTypes(MediaSourceType sourceType) -{ - waitForInitialisation(); - - std::vector supportedMimeTypesSource; - std::string type; - if (sourceType == MediaSourceType::VIDEO) - { - type = "video/"; - } - else if (sourceType == MediaSourceType::AUDIO) - { - type = "audio/"; - } - else if (sourceType == MediaSourceType::SUBTITLE) - { - return {"text/vtt", "text/ttml", "text/cc"}; - } - else - { - RIALTO_SERVER_LOG_WARN("Unsupported media type"); - return {}; - } - - std::copy_if(m_supportedMimeTypes.begin(), m_supportedMimeTypes.end(), std::back_inserter(supportedMimeTypesSource), - [&type](const std::string &supportedMimeType) { return supportedMimeType.find(type) == 0; }); - - return supportedMimeTypesSource; -} - -bool GstCapabilities::isMimeTypeSupported(const std::string &mimeType) -{ - waitForInitialisation(); - return m_supportedMimeTypes.find(mimeType) != m_supportedMimeTypes.end(); -} - -std::vector GstCapabilities::getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) -{ - waitForInitialisation(); - - // Get gstreamer element factories. The following flag settings will fetch both SINK and DECODER types - // of gstreamer classes... - GstElementFactoryListType factoryListType{GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_DECODER | - GST_ELEMENT_FACTORY_TYPE_PARSER}; - { - // If MediaSourceType::AUDIO is specified then adjust the flag so that we - // restrict the list to gstreamer AUDIO element types (and likewise for video and subtitle)... - static const std::unordered_map - kLookupExtraConditions{{MediaSourceType::AUDIO, GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO}, - {MediaSourceType::VIDEO, GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO}, - {MediaSourceType::SUBTITLE, GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE}}; - auto i = kLookupExtraConditions.find(mediaType); - if (i != kLookupExtraConditions.end()) - factoryListType |= i->second; - } - - GList *factories{m_gstWrapper->gstElementFactoryListGetElements(factoryListType, GST_RANK_NONE)}; - - // Scan all returned elements for the specified properties... - std::unordered_set propertiesToLookFor{propertyNames.begin(), propertyNames.end()}; - std::vector propertiesFound; - for (GList *iter = factories; iter != nullptr && !propertiesToLookFor.empty(); iter = iter->next) - { - GstElementFactory *factory = GST_ELEMENT_FACTORY(iter->data); - - // WORKAROUND: initialising element "rtkv1sink" causes that another playback's video goes black - // we don't need to scan this element, so ignore it - if (std::string{GST_OBJECT_NAME(GST_OBJECT(factory))} == "rtkv1sink") - { - RIALTO_SERVER_LOG_DEBUG("Ignoring rtkv1sink element"); - continue; - } - - GstElement *elementObj{nullptr}; - - // We instantiate an object because fetching the class, even after gstPluginFeatureLoad, - // was found to sometimes return a class with no properties. A code branch is - // kept with this feature "supportedPropertiesViaClass" - elementObj = m_gstWrapper->gstElementFactoryCreate(factory, nullptr); - if (elementObj) - { - GParamSpec **props; - guint nProps; - props = m_glibWrapper->gObjectClassListProperties(G_OBJECT_GET_CLASS(elementObj), &nProps); - if (props) - { - for (guint j = 0; j < nProps && !propertiesToLookFor.empty(); ++j) - { - const std::string kPropName{props[j]->name}; - auto it = propertiesToLookFor.find(kPropName); - if (it != propertiesToLookFor.end()) - { - RIALTO_SERVER_LOG_DEBUG("Found property '%s'", kPropName.c_str()); - propertiesFound.push_back(kPropName); - propertiesToLookFor.erase(it); - } - } - m_glibWrapper->gFree(props); - } - m_gstWrapper->gstObjectUnref(elementObj); - } - } - - // Some sinks do not specifically support the "audio-fade" property, but the mechanism is supported through the use - // of the rdk_gstreamer_utils library. Check for audio fade support if the property is required and we haven't found it in the sinks. - if (propertiesToLookFor.find("audio-fade") != propertiesToLookFor.end()) - { - bool socAudioFadeSupported = m_rdkGstreamerUtilsWrapper->isSocAudioFadeSupported(); - if (socAudioFadeSupported) - { - RIALTO_SERVER_LOG_DEBUG("Audio fade property is supported by the SoC"); - propertiesFound.push_back("audio-fade"); // Add "audio-fade" if supported by SoC - } - } - // Cleanup - m_gstWrapper->gstPluginFeatureListFree(factories); - return propertiesFound; -} - -void GstCapabilities::fillSupportedMimeTypes() -{ - std::vector supportedCaps; - appendSupportedCapsFromFactoryType(GST_ELEMENT_FACTORY_TYPE_DECODER, supportedCaps); - - // Only append caps from decoder parser if they can link with the decoder - appendLinkableCapsFromParserDecoderChains(supportedCaps); - - // Sink caps do not require decoder support - appendSupportedCapsFromFactoryType(GST_ELEMENT_FACTORY_TYPE_SINK, supportedCaps); - - if (supportedCaps.empty()) - { - RIALTO_SERVER_LOG_WARN("There are no supported caps"); - return; - } - - m_supportedMimeTypes = firebolt::rialto::server::convertFromCapsVectorToMimeSet(supportedCaps, m_gstWrapper); - - for (GstCaps *caps : supportedCaps) - { - m_gstWrapper->gstCapsUnref(caps); - } -} - -void GstCapabilities::appendLinkableCapsFromParserDecoderChains(std::vector &supportedCaps) -{ - if (supportedCaps.empty()) - { - return; - } - - std::vector decoderSupportedCaps = supportedCaps; - - GList *parserFactories = - m_gstWrapper->gstElementFactoryListGetElements(GST_ELEMENT_FACTORY_TYPE_PARSER, GST_RANK_MARGINAL); - if (!parserFactories) - { - RIALTO_SERVER_LOG_WARN("Could not find any parser"); - return; - } - - for (GstCaps *decoderCaps : decoderSupportedCaps) - { - for (GList *factoriesIter = parserFactories; factoriesIter; factoriesIter = factoriesIter->next) - { - GstElementFactory *factory = static_cast(factoriesIter->data); - const GList *kParserPadTemplates = m_gstWrapper->gstElementFactoryGetStaticPadTemplates(factory); - - if (canCreateParserDecoderChain(decoderCaps, kParserPadTemplates)) - { - addAllUniqueSinkPadsCapsToVector(supportedCaps, kParserPadTemplates); - } - } - } - - m_gstWrapper->gstPluginFeatureListFree(parserFactories); -} - -void GstCapabilities::appendSupportedCapsFromFactoryType(const GstElementFactoryListType &type, - std::vector &supportedCaps) -{ - GList *factories = m_gstWrapper->gstElementFactoryListGetElements(type, GST_RANK_MARGINAL); - if (!factories) - { - RIALTO_SERVER_LOG_WARN("Could not find any %s", toString(type)); - return; - } - - for (GList *factoriesIter = factories; factoriesIter; factoriesIter = factoriesIter->next) - { - GstElementFactory *factory = static_cast(factoriesIter->data); - const GList *kPadTemplates = m_gstWrapper->gstElementFactoryGetStaticPadTemplates(factory); - - addAllUniqueSinkPadsCapsToVector(supportedCaps, kPadTemplates); - } - - m_gstWrapper->gstPluginFeatureListFree(factories); -} - -bool GstCapabilities::canCreateParserDecoderChain(GstCaps *decoderCaps, const GList *kParserPadTemplates) -{ - for (const GList *padTemplateIter = kParserPadTemplates; padTemplateIter; padTemplateIter = padTemplateIter->next) - { - GstStaticPadTemplate *padTemplate = static_cast(padTemplateIter->data); - if (padTemplate->direction == GST_PAD_SRC) - { - GstCaps *padTemplateCaps = m_gstWrapper->gstStaticCapsGet(&padTemplate->static_caps); - - // check if parser's src pad can be connected to decoder's sink pad - bool canIntersect = m_gstWrapper->gstCapsCanIntersect(decoderCaps, padTemplateCaps); - m_gstWrapper->gstCapsUnref(padTemplateCaps); - if (canIntersect) - { - return true; - } - } - } - - return false; -} - -void GstCapabilities::addAllUniqueSinkPadsCapsToVector(std::vector &capsVector, const GList *padTemplates) -{ - for (const GList *padTemplateIter = padTemplates; padTemplateIter; padTemplateIter = padTemplateIter->next) - { - GstStaticPadTemplate *padTemplate = static_cast(padTemplateIter->data); - if (padTemplate->direction == GST_PAD_SINK) - { - GstCaps *padTemplateCaps = m_gstWrapper->gstStaticCapsGet(&padTemplate->static_caps); - if (!isCapsInVector(capsVector, padTemplateCaps)) - { - capsVector.push_back(padTemplateCaps); - } - else - { - m_gstWrapper->gstCapsUnref(padTemplateCaps); - } - } - } -} - -bool GstCapabilities::isCapsInVector(const std::vector &capsVector, GstCaps *caps) const -{ - return std::find_if(capsVector.begin(), capsVector.end(), [&](const GstCaps *comparedCaps) - { return m_gstWrapper->gstCapsIsStrictlyEqual(caps, comparedCaps); }) != capsVector.end(); -} - -void GstCapabilities::waitForInitialisation() -{ - std::unique_lock lock{m_initialisationMutex}; - m_initialisationCv.wait(lock, [this]() { return m_isInitialised; }); -} - -bool GstCapabilities::isVideoMaster(bool &isVideoMaster) -{ - waitForInitialisation(); - - GstRegistry *reg = m_gstWrapper->gstRegistryGet(); - if (!reg) - { - RIALTO_SERVER_LOG_ERROR("Failed get the gst registry"); - return false; - } - GstPluginFeature *feature{nullptr}; - isVideoMaster = true; - if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "amlhalasink"))) - { - isVideoMaster = false; - m_gstWrapper->gstObjectUnref(feature); - } - return true; -} - -} // namespace firebolt::rialto::server - -// namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstDecryptor.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstDecryptor.cpp deleted file mode 100644 index 33206d494..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstDecryptor.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GstDecryptorElementFactory.h" -#include "GstDecryptorPrivate.h" -#include "GstProtectionMetadataHelperFactory.h" -#include "RialtoServerLogging.h" -#include - -#include -#include - -G_BEGIN_DECLS - -#define GST_RIALTO_DECRYPTOR_TYPE (gst_rialto_decryptor_get_type()) -#define GST_RIALTO_DECRYPTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_RIALTO_DECRYPTOR_TYPE, GstRialtoDecryptor)) -#define GST_RIALTO_DECRYPTOR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), GST_RIALTO_DECRYPTOR_TYPE, GstRialtoDecryptorClass)) - -typedef struct _GstRialtoDecryptor GstRialtoDecryptor; -typedef struct _GstRialtoDecryptorClass GstRialtoDecryptorClass; -typedef struct firebolt::rialto::server::GstRialtoDecryptorPrivate GstRialtoDecryptorPrivate; - -GType gst_rialto_decryptor_get_type(void); // NOLINT(build/function_format) - -struct _GstRialtoDecryptor -{ - GstBaseTransform parent; - GstRialtoDecryptorPrivate *priv; -}; - -struct _GstRialtoDecryptorClass -{ - GstBaseTransformClass parentClass; -}; - -G_END_DECLS - -static GstStaticPadTemplate sinkTemplate = - GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate srcTemplate = - GST_STATIC_PAD_TEMPLATE("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); - -GST_DEBUG_CATEGORY(gst_rialto_decryptor_debug_category); -#define GST_CAT_DEFAULT gst_rialto_decryptor_debug_category - -#define gst_rialto_decryptor_parent_class parent_class -G_DEFINE_TYPE_WITH_PRIVATE(GstRialtoDecryptor, gst_rialto_decryptor, GST_TYPE_BASE_TRANSFORM); - -static void gst_rialto_decryptor_finalize(GObject *); // NOLINT(build/function_format) -static GstCaps *gst_rialto_decryptor_transform_caps(GstBaseTransform *, // NOLINT(build/function_format) - GstPadDirection, GstCaps *, GstCaps *); -static GstFlowReturn gst_rialto_decryptor_transform_ip(GstBaseTransform *base, // NOLINT(build/function_format) - GstBuffer *buffer); - -static const char *toString(const firebolt::rialto::CipherMode &cipherMode) -{ - switch (cipherMode) - { - case firebolt::rialto::CipherMode::CBCS: - { - return "cbcs"; - } - case firebolt::rialto::CipherMode::CENC: - { - return "cenc"; - } - case firebolt::rialto::CipherMode::CBC1: - { - return "cbc1"; - } - case firebolt::rialto::CipherMode::CENS: - { - return "cens"; - } - case firebolt::rialto::CipherMode::UNKNOWN: - default: - { - return "unknown"; - } - } -} - -static void gst_rialto_decryptor_class_init(GstRialtoDecryptorClass *klass) // NOLINT(build/function_format) -{ - GST_DEBUG_CATEGORY_INIT(gst_rialto_decryptor_debug_category, "rialtodecryptor", 0, "Decryptor for Rialto"); - - GObjectClass *gobject_class = G_OBJECT_CLASS(klass); - gobject_class->finalize = GST_DEBUG_FUNCPTR(gst_rialto_decryptor_finalize); - - GstElementClass *element_class = GST_ELEMENT_CLASS(klass); - gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&sinkTemplate)); - gst_element_class_add_pad_template(element_class, gst_static_pad_template_get(&srcTemplate)); - gst_element_class_set_static_metadata(element_class, "Rialto Decryptor", GST_ELEMENT_FACTORY_KLASS_DECRYPTOR, - "Decryptor for Rialto.", - "Luke Williamson \n" - "Adam Czynszak "); - - GstBaseTransformClass *base_transform_class = GST_BASE_TRANSFORM_CLASS(klass); - base_transform_class->transform_caps = GST_DEBUG_FUNCPTR(gst_rialto_decryptor_transform_caps); - base_transform_class->transform_ip = GST_DEBUG_FUNCPTR(gst_rialto_decryptor_transform_ip); - base_transform_class->transform_ip_on_passthrough = FALSE; -} - -static void gst_rialto_decryptor_init(GstRialtoDecryptor *self) // NOLINT(build/function_format) -{ - GstRialtoDecryptorPrivate *priv = - reinterpret_cast(gst_rialto_decryptor_get_instance_private(self)); - GstBaseTransform *base = GST_BASE_TRANSFORM(self); - - self->priv = new (priv) GstRialtoDecryptorPrivate(base, firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(), - firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory()); - - gst_base_transform_set_in_place(base, TRUE); - gst_base_transform_set_passthrough(base, FALSE); - gst_base_transform_set_gap_aware(base, FALSE); -} - -static void gst_rialto_decryptor_finalize(GObject *object) // NOLINT(build/function_format) -{ - GstRialtoDecryptor *self = GST_RIALTO_DECRYPTOR(object); - GstRialtoDecryptorPrivate *priv = - reinterpret_cast(gst_rialto_decryptor_get_instance_private(self)); - - priv->~GstRialtoDecryptorPrivate(); - - GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); -} - -static GstCaps *gst_rialto_decryptor_transform_caps(GstBaseTransform *base, // NOLINT(build/function_format) - GstPadDirection direction, GstCaps *caps, GstCaps *filter) -{ - if (direction == GST_PAD_UNKNOWN) - return nullptr; - - GstRialtoDecryptor *self = GST_RIALTO_DECRYPTOR(base); - - GST_DEBUG_OBJECT(self, "Transform in direction: %s, caps %" GST_PTR_FORMAT ", filter %" GST_PTR_FORMAT, - direction == GST_PAD_SINK ? "GST_PAD_SINK" : "GST_PAD_SRC", caps, filter); - - return GST_BASE_TRANSFORM_CLASS(parent_class)->transform_caps(base, direction, caps, filter); -} - -static GstFlowReturn gst_rialto_decryptor_transform_ip(GstBaseTransform *base, // NOLINT(build/function_format) - GstBuffer *buffer) -{ - GstRialtoDecryptor *self = GST_RIALTO_DECRYPTOR(base); - GstRialtoDecryptorPrivate *priv = - reinterpret_cast(gst_rialto_decryptor_get_instance_private(self)); - - GST_TRACE_OBJECT(self, "Transform in place buf=(%" GST_PTR_FORMAT ")", buffer); - - GstPad *sink_pad = gst_element_get_static_pad(GST_ELEMENT(self), "sink"); - GstCaps *caps = gst_pad_get_current_caps(sink_pad); - - GstFlowReturn result = priv->decrypt(buffer, caps); - gst_caps_unref(caps); - gst_object_unref(sink_pad); - - return result; -} - -namespace firebolt::rialto::server -{ -std::shared_ptr IGstDecryptorElementFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the decryptor element factory, reason: %s", e.what()); - } - - return factory; -} - -GstElement *GstDecryptorElementFactory::createDecryptorElement( - const gchar *name, firebolt::rialto::server::IDecryptionService *decryptionService, - const std::shared_ptr &gstWrapper) const -{ - // Bypass the glib wrapper here, this is the only place we can create a proper Decryptor element - GstRialtoDecryptor *decryptor = GST_RIALTO_DECRYPTOR(g_object_new(GST_RIALTO_DECRYPTOR_TYPE, nullptr)); - if (name) - { - if (!gstWrapper->gstObjectSetName(GST_OBJECT(decryptor), name)) - { - RIALTO_SERVER_LOG_ERROR("Failed to set the decryptor name to %s", name); - g_object_unref(GST_OBJECT(decryptor)); - return nullptr; - } - } - - GstRialtoDecryptorPrivate *priv = - reinterpret_cast(gst_rialto_decryptor_get_instance_private(decryptor)); - std::shared_ptr metadataFactory = - firebolt::rialto::server::IGstProtectionMetadataHelperFactory::createFactory(); - if (priv) - { - priv->setDecryptionService(decryptionService); - priv->setProtectionMetadataWrapper(metadataFactory->createProtectionMetadataWrapper(gstWrapper)); - return GST_ELEMENT(decryptor); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to create the decryptor element"); - g_object_unref(GST_OBJECT(decryptor)); - return nullptr; - } -} - -GstRialtoDecryptorPrivate::GstRialtoDecryptorPrivate( - GstBaseTransform *parentElement, - const std::shared_ptr &gstWrapperFactory, - const std::shared_ptr &glibWrapperFactory) - : m_decryptorElement(parentElement) -{ - if ((!gstWrapperFactory) || (!(m_gstWrapper = gstWrapperFactory->getGstWrapper()))) - { - throw std::runtime_error("Cannot create GstWrapper"); - } - - if ((!glibWrapperFactory) || (!(m_glibWrapper = glibWrapperFactory->getGlibWrapper()))) - { - throw std::runtime_error("Cannot create GlibWrapper"); - } -} - -GstFlowReturn GstRialtoDecryptorPrivate::decrypt(GstBuffer *buffer, GstCaps *caps) -{ - GstRialtoDecryptor *self = GST_RIALTO_DECRYPTOR(m_decryptorElement); - GstRialtoProtectionData *protectionData = m_metadataWrapper->getProtectionMetadataData(buffer); - GstFlowReturn returnStatus = GST_BASE_TRANSFORM_FLOW_DROPPED; // By default drop frame on failure - if (!protectionData) - { - GST_TRACE_OBJECT(self, "Clear sample"); - returnStatus = GST_FLOW_OK; - } - else - { - if (!m_decryptionService) - { - GST_ERROR_OBJECT(self, "No decryption service object"); - } - else - { - if (protectionData->cipherMode == firebolt::rialto::CipherMode::CBC1 || - protectionData->cipherMode == firebolt::rialto::CipherMode::CENS) - { - GST_WARNING_OBJECT(self, "Untested cipher mode '%s'", toString(protectionData->cipherMode)); - } - - if (protectionData->encryptionPatternSet) - { - if (protectionData->cipherMode == firebolt::rialto::CipherMode::CENC || - protectionData->cipherMode == firebolt::rialto::CipherMode::CBC1) - { - GST_WARNING_OBJECT(self, "Encryption pattern set for non-pattern cipherMode '%s'", - toString(protectionData->cipherMode)); - } - } - - if (protectionData->key && m_decryptionService->isPlayreadyKeySystem(protectionData->keySessionId)) - { - GstMapInfo keyMap; - if (m_gstWrapper->gstBufferMap(protectionData->key, &keyMap, GST_MAP_READ)) - { - std::vector playreadyKey(keyMap.data, keyMap.data + keyMap.size); - m_gstWrapper->gstBufferUnmap(protectionData->key, &keyMap); - m_decryptionService->selectKeyId(protectionData->keySessionId, playreadyKey); - m_gstWrapper->gstBufferUnref(protectionData->key); - protectionData->key = m_gstWrapper->gstBufferNew(); - } - else - { - GST_ERROR_OBJECT(self, "Failed to map playready key id"); - } - } - - // Create new GstProtectionMeta decrypt - GstStructure *info = createProtectionMetaInfo(protectionData); - GstProtectionMeta *meta = m_gstWrapper->gstBufferAddProtectionMeta(buffer, info); - if (meta == nullptr) - { - GST_ERROR_OBJECT(self, "Failed to add protection meta to the buffer"); - } - else - { - firebolt::rialto::MediaKeyErrorStatus status = - m_decryptionService->decrypt(protectionData->keySessionId, buffer, caps); - if (firebolt::rialto::MediaKeyErrorStatus::OK != status) - { - GST_ERROR_OBJECT(self, "Failed decrypt the buffer"); - } - else - { - GST_TRACE_OBJECT(self, "Decryption successful"); - returnStatus = GST_FLOW_OK; - } - } - } - - m_metadataWrapper->removeProtectionMetadata(buffer); - } - - if (GST_BASE_TRANSFORM_FLOW_DROPPED == returnStatus) - { - // Notify dropped frame upstream as a non-fatal message - std::string message = "Failed to decrypt buffer, dropping frame and continuing"; - GError *gError{m_glibWrapper->gErrorNewLiteral(GST_STREAM_ERROR, GST_STREAM_ERROR_DECRYPT, message.c_str())}; - gboolean result = - m_gstWrapper->gstElementPostMessage(GST_ELEMENT_CAST(self), - m_gstWrapper->gstMessageNewWarning(GST_OBJECT_CAST(self), gError, - message.c_str())); - if (!result) - { - GST_WARNING_OBJECT(self, "Could not post decrypt warning"); - } - m_glibWrapper->gErrorFree(gError); - } - return returnStatus; -} - -GstStructure *GstRialtoDecryptorPrivate::createProtectionMetaInfo(GstRialtoProtectionData *protectionData) -{ - GstStructure *info = m_gstWrapper->gstStructureNew("application/x-cenc", "kid", GST_TYPE_BUFFER, - protectionData->key, "iv", GST_TYPE_BUFFER, protectionData->iv, - "subsample_count", G_TYPE_UINT, protectionData->subsampleCount, - "subsamples", GST_TYPE_BUFFER, protectionData->subsamples, - "encryption_scheme", G_TYPE_UINT, 0, "init_with_last_15", - G_TYPE_UINT, protectionData->initWithLast15, "cipher-mode", - G_TYPE_STRING, toString(protectionData->cipherMode), NULL); - - if (protectionData->encryptionPatternSet) - { - m_gstWrapper->gstStructureSet(info, "crypt_byte_block", G_TYPE_UINT, protectionData->crypt, NULL); - m_gstWrapper->gstStructureSet(info, "skip_byte_block", G_TYPE_UINT, protectionData->skip, NULL); - } - return info; -} - -void GstRialtoDecryptorPrivate::setDecryptionService(IDecryptionService *decryptionService) -{ - m_decryptionService = decryptionService; -} - -void GstRialtoDecryptorPrivate::setProtectionMetadataWrapper(std::unique_ptr &&metadataWrapper) -{ - m_metadataWrapper = std::move(metadataWrapper); -} - -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstDispatcherThread.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstDispatcherThread.cpp deleted file mode 100644 index 6fd473bb0..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstDispatcherThread.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GstDispatcherThread.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server -{ -std::unique_ptr GstDispatcherThreadFactory::createGstDispatcherThread( - IGstDispatcherThreadClient &client, GstElement *pipeline, - const std::shared_ptr &gstWrapper) const -{ - return std::make_unique(client, pipeline, gstWrapper); -} - -GstDispatcherThread::GstDispatcherThread(IGstDispatcherThreadClient &client, GstElement *pipeline, - const std::shared_ptr &gstWrapper) - : m_client{client}, m_gstWrapper{gstWrapper}, m_isGstreamerDispatcherActive{true} -{ - RIALTO_SERVER_LOG_INFO("GstDispatcherThread is starting"); - m_gstBusDispatcherThread = std::thread(&GstDispatcherThread::gstBusEventHandler, this, pipeline); -} - -GstDispatcherThread::~GstDispatcherThread() -{ - RIALTO_SERVER_LOG_INFO("Stopping GstDispatcherThread"); - m_isGstreamerDispatcherActive = false; - if (m_gstBusDispatcherThread.joinable()) - { - m_gstBusDispatcherThread.join(); - } -} - -void GstDispatcherThread::gstBusEventHandler(GstElement *pipeline) -{ - GstBus *bus = m_gstWrapper->gstPipelineGetBus(GST_PIPELINE(pipeline)); - if (!bus) - { - RIALTO_SERVER_LOG_ERROR("Failed to get gst bus"); - return; - } - - while (m_isGstreamerDispatcherActive) - { - GstMessage *message = - m_gstWrapper->gstBusTimedPopFiltered(bus, 100 * GST_MSECOND, - static_cast(GST_MESSAGE_STATE_CHANGED | - GST_MESSAGE_QOS | GST_MESSAGE_EOS | - GST_MESSAGE_ERROR | GST_MESSAGE_WARNING)); - - if (message) - { - bool shouldHandleMessage{true}; - bool isPrioritised{false}; - if (GST_MESSAGE_SRC(message) == GST_OBJECT(pipeline)) - { - switch (GST_MESSAGE_TYPE(message)) - { - case GST_MESSAGE_STATE_CHANGED: - { - isPrioritised = true; - GstState oldState, newState, pending; - m_gstWrapper->gstMessageParseStateChanged(message, &oldState, &newState, &pending); - switch (newState) - { - case GST_STATE_NULL: - { - m_isGstreamerDispatcherActive = false; - } - case GST_STATE_READY: - case GST_STATE_PAUSED: - case GST_STATE_PLAYING: - case GST_STATE_VOID_PENDING: - { - break; - } - } - break; - } - case GST_MESSAGE_ERROR: - { - m_isGstreamerDispatcherActive = false; - break; - } - default: - { - break; - } - } - } - else if (GST_MESSAGE_STATE_CHANGED == GST_MESSAGE_TYPE(message)) - { - // Skip handling GST_MESSAGE_STATE_CHANGED for non-pipeline objects. - // It signifficantly slows down rialto gst worker thread - shouldHandleMessage = false; - } - - if (shouldHandleMessage) - { - m_client.handleBusMessage(message, isPrioritised); - } - } - } - - RIALTO_SERVER_LOG_INFO("Gstbus dispatcher exitting"); - m_gstWrapper->gstObjectUnref(bus); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstGenericPlayer.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstGenericPlayer.cpp deleted file mode 100644 index 7aa7105da..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstGenericPlayer.cpp +++ /dev/null @@ -1,2270 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include "FlushWatcher.h" -#include "GstDispatcherThread.h" -#include "GstGenericPlayer.h" -#include "GstProtectionMetadata.h" -#include "IGstTextTrackSinkFactory.h" -#include "IMediaPipeline.h" -#include "ITimer.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" -#include "Utils.h" -#include "WorkerThread.h" -#include "tasks/generic/GenericPlayerTaskFactory.h" - -namespace -{ -/** - * @brief Report position interval in ms. - * The position reporting timer should be started whenever the PLAYING state is entered and stopped - * whenever the session moves to another playback state. - */ -constexpr std::chrono::milliseconds kPositionReportTimerMs{250}; -constexpr std::chrono::seconds kSubtitleClockResyncInterval{10}; - -bool operator==(const firebolt::rialto::server::SegmentData &lhs, const firebolt::rialto::server::SegmentData &rhs) -{ - return (lhs.position == rhs.position) && (lhs.resetTime == rhs.resetTime) && (lhs.appliedRate == rhs.appliedRate) && - (lhs.stopPosition == rhs.stopPosition); -} -} // namespace - -namespace firebolt::rialto::server -{ -std::weak_ptr GstGenericPlayerFactory::m_factory; - -std::shared_ptr IGstGenericPlayerFactory::getFactory() -{ - std::shared_ptr factory = GstGenericPlayerFactory::m_factory.lock(); - - if (!factory) - { - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer player factory, reason: %s", e.what()); - } - - GstGenericPlayerFactory::m_factory = factory; - } - - return factory; -} - -std::unique_ptr GstGenericPlayerFactory::createGstGenericPlayer( - IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, - const VideoRequirements &videoRequirements, - const std::shared_ptr &rdkGstreamerUtilsWrapperFactory) -{ - std::unique_ptr gstPlayer; - - try - { - auto gstWrapperFactory = firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); - auto glibWrapperFactory = firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(); - std::shared_ptr gstWrapper; - std::shared_ptr glibWrapper; - std::shared_ptr rdkGstreamerUtilsWrapper; - if ((!gstWrapperFactory) || (!(gstWrapper = gstWrapperFactory->getGstWrapper()))) - { - throw std::runtime_error("Cannot create GstWrapper"); - } - if ((!glibWrapperFactory) || (!(glibWrapper = glibWrapperFactory->getGlibWrapper()))) - { - throw std::runtime_error("Cannot create GlibWrapper"); - } - if ((!rdkGstreamerUtilsWrapperFactory) || - (!(rdkGstreamerUtilsWrapper = rdkGstreamerUtilsWrapperFactory->createRdkGstreamerUtilsWrapper()))) - { - throw std::runtime_error("Cannot create RdkGstreamerUtilsWrapper"); - } - gstPlayer = std::make_unique< - GstGenericPlayer>(client, decryptionService, type, videoRequirements, gstWrapper, glibWrapper, - rdkGstreamerUtilsWrapper, IGstInitialiser::instance(), std::make_unique(), - IGstSrcFactory::getFactory(), common::ITimerFactory::getFactory(), - std::make_unique(client, gstWrapper, glibWrapper, - rdkGstreamerUtilsWrapper, - IGstTextTrackSinkFactory::createFactory()), - std::make_unique(), std::make_unique(), - IGstProtectionMetadataHelperFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer player, reason: %s", e.what()); - } - - return gstPlayer; -} - -GstGenericPlayer::GstGenericPlayer( - IGstGenericPlayerClient *client, IDecryptionService &decryptionService, MediaType type, - const VideoRequirements &videoRequirements, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr &rdkGstreamerUtilsWrapper, - const IGstInitialiser &gstInitialiser, std::unique_ptr &&flushWatcher, - const std::shared_ptr &gstSrcFactory, std::shared_ptr timerFactory, - std::unique_ptr taskFactory, std::unique_ptr workerThreadFactory, - std::unique_ptr gstDispatcherThreadFactory, - std::shared_ptr gstProtectionMetadataFactory) - : m_gstPlayerClient(client), m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, - m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, m_timerFactory{timerFactory}, - m_taskFactory{std::move(taskFactory)}, m_flushWatcher{std::move(flushWatcher)} -{ - RIALTO_SERVER_LOG_DEBUG("GstGenericPlayer is constructed."); - - gstInitialiser.waitForInitialisation(); - - m_context.decryptionService = &decryptionService; - - if ((!gstSrcFactory) || (!(m_context.gstSrc = gstSrcFactory->getGstSrc()))) - { - throw std::runtime_error("Cannot create GstSrc"); - } - - if (!timerFactory) - { - throw std::runtime_error("TimeFactory is invalid"); - } - - if ((!gstProtectionMetadataFactory) || - (!(m_protectionMetadataWrapper = gstProtectionMetadataFactory->createProtectionMetadataWrapper(m_gstWrapper)))) - { - throw std::runtime_error("Cannot create protection metadata wrapper"); - } - - // Ensure that rialtosrc has been initalised - m_context.gstSrc->initSrc(); - - // Start task thread - if ((!workerThreadFactory) || (!(m_workerThread = workerThreadFactory->createWorkerThread()))) - { - throw std::runtime_error("Failed to create the worker thread"); - } - - // Initialise pipeline - switch (type) - { - case MediaType::MSE: - { - initMsePipeline(); - break; - } - default: - { - resetWorkerThread(); - throw std::runtime_error("Media type not supported"); - } - } - - // Check the video requirements for a limited video. - // If the video requirements are set to anything lower than the minimum, this playback is assumed to be a secondary - // video in a dual video scenario. - if ((kMinPrimaryVideoWidth > videoRequirements.maxWidth) || (kMinPrimaryVideoHeight > videoRequirements.maxHeight)) - { - RIALTO_SERVER_LOG_MIL("Secondary video playback selected"); - bool westerossinkSecondaryVideoResult = setWesterossinkSecondaryVideo(); - bool ermContextResult = setErmContext(); - if (!westerossinkSecondaryVideoResult && !ermContextResult) - { - resetWorkerThread(); - termPipeline(); - throw std::runtime_error("Could not set secondary video"); - } - } - else - { - RIALTO_SERVER_LOG_MIL("Primary video playback selected"); - } - - m_gstDispatcherThread = - gstDispatcherThreadFactory->createGstDispatcherThread(*this, m_context.pipeline, m_gstWrapper); -} - -GstGenericPlayer::~GstGenericPlayer() -{ - RIALTO_SERVER_LOG_DEBUG("GstGenericPlayer is destructed."); - m_gstDispatcherThread.reset(); - - resetWorkerThread(); - - termPipeline(); -} - -void GstGenericPlayer::initMsePipeline() -{ - // Make playbin - m_context.pipeline = m_gstWrapper->gstElementFactoryMake("playbin", "media_pipeline"); - // Set pipeline flags - setPlaybinFlags(true); - - // Set callbacks - m_glibWrapper->gSignalConnect(m_context.pipeline, "source-setup", G_CALLBACK(&GstGenericPlayer::setupSource), this); - m_glibWrapper->gSignalConnect(m_context.pipeline, "element-setup", G_CALLBACK(&GstGenericPlayer::setupElement), this); - m_glibWrapper->gSignalConnect(m_context.pipeline, "deep-element-added", - G_CALLBACK(&GstGenericPlayer::deepElementAdded), this); - - // Set uri - m_glibWrapper->gObjectSet(m_context.pipeline, "uri", "rialto://", nullptr); - - // Check playsink - GstElement *playsink = (m_gstWrapper->gstBinGetByName(GST_BIN(m_context.pipeline), "playsink")); - if (playsink) - { - m_glibWrapper->gObjectSet(G_OBJECT(playsink), "send-event-mode", 0, nullptr); - m_gstWrapper->gstObjectUnref(playsink); - } - else - { - GST_WARNING("No playsink ?!?!?"); - } - if (GST_STATE_CHANGE_FAILURE == m_gstWrapper->gstElementSetState(m_context.pipeline, GST_STATE_READY)) - { - GST_WARNING("Failed to set pipeline to READY state"); - } - RIALTO_SERVER_LOG_MIL("New RialtoServer's pipeline created"); -} - -void GstGenericPlayer::resetWorkerThread() -{ - // Shutdown task thread - m_workerThread->enqueueTask(m_taskFactory->createShutdown(*this)); - m_workerThread->join(); - m_workerThread.reset(); -} - -void GstGenericPlayer::termPipeline() -{ - if (m_finishSourceSetupTimer && m_finishSourceSetupTimer->isActive()) - { - m_finishSourceSetupTimer->cancel(); - } - - m_finishSourceSetupTimer.reset(); - - for (auto &elem : m_context.streamInfo) - { - StreamInfo &streamInfo = elem.second; - for (auto &buffer : streamInfo.buffers) - { - m_gstWrapper->gstBufferUnref(buffer); - } - - streamInfo.buffers.clear(); - } - - m_taskFactory->createStop(m_context, *this)->execute(); - GstBus *bus = m_gstWrapper->gstPipelineGetBus(GST_PIPELINE(m_context.pipeline)); - m_gstWrapper->gstBusSetSyncHandler(bus, nullptr, nullptr, nullptr); - m_gstWrapper->gstObjectUnref(bus); - - if (m_context.source) - { - m_gstWrapper->gstObjectUnref(m_context.source); - } - if (m_context.subtitleSink) - { - m_gstWrapper->gstObjectUnref(m_context.subtitleSink); - m_context.subtitleSink = nullptr; - } - - if (m_context.videoSink) - { - m_gstWrapper->gstObjectUnref(m_context.videoSink); - m_context.videoSink = nullptr; - } - - // Delete the pipeline - m_gstWrapper->gstObjectUnref(m_context.pipeline); - - RIALTO_SERVER_LOG_MIL("RialtoServer's pipeline terminated"); -} - -unsigned GstGenericPlayer::getGstPlayFlag(const char *nick) -{ - GFlagsClass *flagsClass = - static_cast(m_glibWrapper->gTypeClassRef(m_glibWrapper->gTypeFromName("GstPlayFlags"))); - GFlagsValue *flag = m_glibWrapper->gFlagsGetValueByNick(flagsClass, nick); - return flag ? flag->value : 0; -} - -void GstGenericPlayer::setupSource(GstElement *pipeline, GstElement *source, GstGenericPlayer *self) -{ - self->m_gstWrapper->gstObjectRef(source); - if (self->m_workerThread) - { - self->m_workerThread->enqueueTask(self->m_taskFactory->createSetupSource(self->m_context, *self, source)); - } -} - -void GstGenericPlayer::setupElement(GstElement *pipeline, GstElement *element, GstGenericPlayer *self) -{ - RIALTO_SERVER_LOG_DEBUG("Element %s added to the pipeline", GST_ELEMENT_NAME(element)); - self->m_gstWrapper->gstObjectRef(element); - if (self->m_workerThread) - { - self->m_workerThread->enqueueTask(self->m_taskFactory->createSetupElement(self->m_context, *self, element)); - } -} - -void GstGenericPlayer::deepElementAdded(GstBin *pipeline, GstBin *bin, GstElement *element, GstGenericPlayer *self) -{ - RIALTO_SERVER_LOG_DEBUG("Deep element %s added to the pipeline", GST_ELEMENT_NAME(element)); - if (self->m_workerThread) - { - self->m_workerThread->enqueueTask( - self->m_taskFactory->createDeepElementAdded(self->m_context, *self, pipeline, bin, element)); - } -} - -void GstGenericPlayer::attachSource(const std::unique_ptr &attachedSource) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createAttachSource(m_context, *this, attachedSource)); - } -} - -void GstGenericPlayer::removeSource(const MediaSourceType &mediaSourceType) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createRemoveSource(m_context, *this, mediaSourceType)); - } -} - -void GstGenericPlayer::allSourcesAttached() -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createFinishSetupSource(m_context, *this)); - } -} - -void GstGenericPlayer::attachSamples(const IMediaPipeline::MediaSegmentVector &mediaSegments) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createAttachSamples(m_context, *this, mediaSegments)); - } -} - -void GstGenericPlayer::attachSamples(const std::shared_ptr &dataReader) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createReadShmDataAndAttachSamples(m_context, *this, dataReader)); - } -} - -void GstGenericPlayer::setPosition(std::int64_t position) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetPosition(m_context, *this, position)); - } -} - -void GstGenericPlayer::setPlaybackRate(double rate) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetPlaybackRate(m_context, rate)); - } -} - -bool GstGenericPlayer::getPosition(std::int64_t &position) -{ - // We are on main thread here, but m_context.pipeline can be used, because it's modified only in GstGenericPlayer - // constructor and destructor. GstGenericPlayer is created/destructed on main thread, so we won't have a crash here. - position = getPosition(m_context.pipeline); - if (position == -1) - { - RIALTO_SERVER_LOG_WARN("Query position failed"); - return false; - } - - return true; -} - -GstElement *GstGenericPlayer::getSink(const MediaSourceType &mediaSourceType) const -{ - const char *kSinkName{nullptr}; - GstElement *sink{nullptr}; - switch (mediaSourceType) - { - case MediaSourceType::AUDIO: - kSinkName = "audio-sink"; - break; - case MediaSourceType::VIDEO: - kSinkName = "video-sink"; - break; - default: - break; - } - if (!kSinkName) - { - RIALTO_SERVER_LOG_WARN("mediaSourceType not supported %d", static_cast(mediaSourceType)); - } - else - { - if (m_context.pipeline == nullptr) - { - RIALTO_SERVER_LOG_WARN("Pipeline is NULL!"); - } - else - { - RIALTO_SERVER_LOG_DEBUG("Pipeline is valid: %p", m_context.pipeline); - } - m_glibWrapper->gObjectGet(m_context.pipeline, kSinkName, &sink, nullptr); - if (sink) - { - GstElement *autoSink{sink}; - if (firebolt::rialto::MediaSourceType::VIDEO == mediaSourceType) - autoSink = getSinkChildIfAutoVideoSink(sink); - else if (firebolt::rialto::MediaSourceType::AUDIO == mediaSourceType) - autoSink = getSinkChildIfAutoAudioSink(sink); - - // Is this an auto-sink?... - if (autoSink != sink) - { - m_gstWrapper->gstObjectUnref(GST_OBJECT(sink)); - - // increase the reference count of the auto sink - sink = GST_ELEMENT(m_gstWrapper->gstObjectRef(GST_OBJECT(autoSink))); - } - } - else - { - RIALTO_SERVER_LOG_WARN("%s could not be obtained", kSinkName); - } - } - return sink; -} - -void GstGenericPlayer::setSourceFlushed(const MediaSourceType &mediaSourceType) -{ - m_flushWatcher->setFlushed(mediaSourceType); -} - -GstElement *GstGenericPlayer::getDecoder(const MediaSourceType &mediaSourceType) -{ - GstIterator *it = m_gstWrapper->gstBinIterateRecurse(GST_BIN(m_context.pipeline)); - GValue item = G_VALUE_INIT; - gboolean done = FALSE; - - while (!done) - { - switch (m_gstWrapper->gstIteratorNext(it, &item)) - { - case GST_ITERATOR_OK: - { - GstElement *element = GST_ELEMENT(m_glibWrapper->gValueGetObject(&item)); - GstElementFactory *factory = m_gstWrapper->gstElementGetFactory(element); - - if (factory) - { - GstElementFactoryListType type = GST_ELEMENT_FACTORY_TYPE_DECODER; - if (mediaSourceType == MediaSourceType::AUDIO) - { - type |= GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO; - } - else if (mediaSourceType == MediaSourceType::VIDEO) - { - type |= GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO; - } - - if (m_gstWrapper->gstElementFactoryListIsType(factory, type)) - { - m_glibWrapper->gValueUnset(&item); - m_gstWrapper->gstIteratorFree(it); - return GST_ELEMENT(m_gstWrapper->gstObjectRef(element)); - } - } - - m_glibWrapper->gValueUnset(&item); - break; - } - case GST_ITERATOR_RESYNC: - m_gstWrapper->gstIteratorResync(it); - break; - case GST_ITERATOR_ERROR: - case GST_ITERATOR_DONE: - done = TRUE; - break; - } - } - - RIALTO_SERVER_LOG_WARN("Could not find decoder"); - - m_glibWrapper->gValueUnset(&item); - m_gstWrapper->gstIteratorFree(it); - - return nullptr; -} - -GstElement *GstGenericPlayer::getParser(const MediaSourceType &mediaSourceType) -{ - GstIterator *it = m_gstWrapper->gstBinIterateRecurse(GST_BIN(m_context.pipeline)); - GValue item = G_VALUE_INIT; - gboolean done = FALSE; - - while (!done) - { - switch (m_gstWrapper->gstIteratorNext(it, &item)) - { - case GST_ITERATOR_OK: - { - GstElement *element = GST_ELEMENT(m_glibWrapper->gValueGetObject(&item)); - GstElementFactory *factory = m_gstWrapper->gstElementGetFactory(element); - - if (factory) - { - GstElementFactoryListType type = GST_ELEMENT_FACTORY_TYPE_PARSER; - if (mediaSourceType == MediaSourceType::AUDIO) - { - type |= GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO; - } - else if (mediaSourceType == MediaSourceType::VIDEO) - { - type |= GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO; - } - - if (m_gstWrapper->gstElementFactoryListIsType(factory, type)) - { - m_glibWrapper->gValueUnset(&item); - m_gstWrapper->gstIteratorFree(it); - return GST_ELEMENT(m_gstWrapper->gstObjectRef(element)); - } - } - - m_glibWrapper->gValueUnset(&item); - break; - } - case GST_ITERATOR_RESYNC: - m_gstWrapper->gstIteratorResync(it); - break; - case GST_ITERATOR_ERROR: - case GST_ITERATOR_DONE: - done = TRUE; - break; - } - } - - RIALTO_SERVER_LOG_WARN("Could not find parser"); - - m_glibWrapper->gValueUnset(&item); - m_gstWrapper->gstIteratorFree(it); - - return nullptr; -} - -std::optional -GstGenericPlayer::createAudioAttributes(const std::unique_ptr &source) const -{ - std::optional audioAttributes; - const IMediaPipeline::MediaSourceAudio *kSource = dynamic_cast(source.get()); - if (kSource) - { - firebolt::rialto::AudioConfig audioConfig = kSource->getAudioConfig(); - audioAttributes = - firebolt::rialto::wrappers::AudioAttributesPrivate{"", // param set below. - audioConfig.numberOfChannels, audioConfig.sampleRate, - 0, // used only in one of logs in rdk_gstreamer_utils, no - // need to set this param. - 0, // used only in one of logs in rdk_gstreamer_utils, no - // need to set this param. - audioConfig.codecSpecificConfig.data(), - static_cast( - audioConfig.codecSpecificConfig.size())}; - if (source->getMimeType() == "audio/mp4" || source->getMimeType() == "audio/aac") - { - audioAttributes->m_codecParam = "mp4a"; - } - else if (source->getMimeType() == "audio/x-eac3") - { - audioAttributes->m_codecParam = "ec-3"; - } - else if (source->getMimeType() == "audio/b-wav" || source->getMimeType() == "audio/x-raw") - { - audioAttributes->m_codecParam = "lpcm"; - } - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to cast source"); - } - - return audioAttributes; -} - -bool GstGenericPlayer::setImmediateOutput(const MediaSourceType &mediaSourceType, bool immediateOutputParam) -{ - if (!m_workerThread) - return false; - - m_workerThread->enqueueTask( - m_taskFactory->createSetImmediateOutput(m_context, *this, mediaSourceType, immediateOutputParam)); - return true; -} - -bool GstGenericPlayer::getImmediateOutput(const MediaSourceType &mediaSourceType, bool &immediateOutputRef) -{ - bool returnValue{false}; - GstElement *sink{getSink(mediaSourceType)}; - if (sink) - { - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "immediate-output")) - { - m_glibWrapper->gObjectGet(sink, "immediate-output", &immediateOutputRef, nullptr); - returnValue = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("immediate-output not supported in element %s", GST_ELEMENT_NAME(sink)); - } - m_gstWrapper->gstObjectUnref(sink); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set immediate-output property, sink is NULL"); - } - - return returnValue; -} - -bool GstGenericPlayer::getStats(const MediaSourceType &mediaSourceType, uint64_t &renderedFrames, uint64_t &droppedFrames) -{ - bool returnValue{false}; - GstElement *sink{getSink(mediaSourceType)}; - if (sink) - { - GstStructure *stats{nullptr}; - m_glibWrapper->gObjectGet(sink, "stats", &stats, nullptr); - if (!stats) - { - RIALTO_SERVER_LOG_ERROR("failed to get stats from '%s'", GST_ELEMENT_NAME(sink)); - } - else - { - guint64 renderedFramesTmp; - guint64 droppedFramesTmp; - if (m_gstWrapper->gstStructureGetUint64(stats, "rendered", &renderedFramesTmp) && - m_gstWrapper->gstStructureGetUint64(stats, "dropped", &droppedFramesTmp)) - { - renderedFrames = renderedFramesTmp; - droppedFrames = droppedFramesTmp; - returnValue = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("failed to get 'rendered' or 'dropped' from structure (%s)", - GST_ELEMENT_NAME(sink)); - } - m_gstWrapper->gstStructureFree(stats); - } - m_gstWrapper->gstObjectUnref(sink); - } - - return returnValue; -} - -GstBuffer *GstGenericPlayer::createBuffer(const IMediaPipeline::MediaSegment &mediaSegment) const -{ - GstBuffer *gstBuffer = m_gstWrapper->gstBufferNewAllocate(nullptr, mediaSegment.getDataLength(), nullptr); - m_gstWrapper->gstBufferFill(gstBuffer, 0, mediaSegment.getData(), mediaSegment.getDataLength()); - - if (mediaSegment.isEncrypted()) - { - GstBuffer *keyId = m_gstWrapper->gstBufferNewAllocate(nullptr, mediaSegment.getKeyId().size(), nullptr); - m_gstWrapper->gstBufferFill(keyId, 0, mediaSegment.getKeyId().data(), mediaSegment.getKeyId().size()); - - GstBuffer *initVector = m_gstWrapper->gstBufferNewAllocate(nullptr, mediaSegment.getInitVector().size(), nullptr); - m_gstWrapper->gstBufferFill(initVector, 0, mediaSegment.getInitVector().data(), - mediaSegment.getInitVector().size()); - GstBuffer *subsamples{nullptr}; - if (!mediaSegment.getSubSamples().empty()) - { - auto subsamplesRawSize = mediaSegment.getSubSamples().size() * (sizeof(guint16) + sizeof(guint32)); - guint8 *subsamplesRaw = static_cast(m_glibWrapper->gMalloc(subsamplesRawSize)); - GstByteWriter writer; - m_gstWrapper->gstByteWriterInitWithData(&writer, subsamplesRaw, subsamplesRawSize, FALSE); - - for (const auto &subSample : mediaSegment.getSubSamples()) - { - m_gstWrapper->gstByteWriterPutUint16Be(&writer, subSample.numClearBytes); - m_gstWrapper->gstByteWriterPutUint32Be(&writer, subSample.numEncryptedBytes); - } - subsamples = m_gstWrapper->gstBufferNewWrapped(subsamplesRaw, subsamplesRawSize); - } - - uint32_t crypt = 0; - uint32_t skip = 0; - bool encryptionPatternSet = mediaSegment.getEncryptionPattern(crypt, skip); - - GstRialtoProtectionData data = {mediaSegment.getMediaKeySessionId(), - static_cast(mediaSegment.getSubSamples().size()), - mediaSegment.getInitWithLast15(), - keyId, - initVector, - subsamples, - mediaSegment.getCipherMode(), - crypt, - skip, - encryptionPatternSet, - m_context.decryptionService}; - - if (!m_protectionMetadataWrapper->addProtectionMetadata(gstBuffer, data)) - { - RIALTO_SERVER_LOG_ERROR("Failed to add protection metadata"); - if (keyId) - { - m_gstWrapper->gstBufferUnref(keyId); - } - if (initVector) - { - m_gstWrapper->gstBufferUnref(initVector); - } - if (subsamples) - { - m_gstWrapper->gstBufferUnref(subsamples); - } - } - } - - GST_BUFFER_TIMESTAMP(gstBuffer) = mediaSegment.getTimeStamp(); - GST_BUFFER_DURATION(gstBuffer) = mediaSegment.getDuration(); - return gstBuffer; -} - -void GstGenericPlayer::notifyNeedMediaData(const MediaSourceType mediaSource) -{ - auto elem = m_context.streamInfo.find(mediaSource); - if (elem != m_context.streamInfo.end()) - { - StreamInfo &streamInfo = elem->second; - streamInfo.isNeedDataPending = false; - - // Send new NeedMediaData if we still need it - if (m_gstPlayerClient && streamInfo.isDataNeeded) - { - streamInfo.isNeedDataPending = m_gstPlayerClient->notifyNeedMediaData(mediaSource); - } - } - else - { - RIALTO_SERVER_LOG_WARN("Media type %s could not be found", common::convertMediaSourceType(mediaSource)); - } -} - -void GstGenericPlayer::attachData(const firebolt::rialto::MediaSourceType mediaType) -{ - auto elem = m_context.streamInfo.find(mediaType); - if (elem != m_context.streamInfo.end()) - { - StreamInfo &streamInfo = elem->second; - if (streamInfo.buffers.empty() || !streamInfo.isDataNeeded) - { - return; - } - - if (firebolt::rialto::MediaSourceType::SUBTITLE == mediaType) - { - setTextTrackPositionIfRequired(streamInfo.appSrc); - } - else - { - pushSampleIfRequired(streamInfo.appSrc, common::convertMediaSourceType(mediaType)); - } - if (mediaType == firebolt::rialto::MediaSourceType::AUDIO) - { - // This needs to be done before gstAppSrcPushBuffer() is - // called because it can free the memory - m_context.lastAudioSampleTimestamps = static_cast(GST_BUFFER_PTS(streamInfo.buffers.back())); - } - - for (GstBuffer *buffer : streamInfo.buffers) - { - m_gstWrapper->gstAppSrcPushBuffer(GST_APP_SRC(streamInfo.appSrc), buffer); - } - streamInfo.buffers.clear(); - streamInfo.isDataPushed = true; - - const bool kIsSingle = m_context.streamInfo.size() == 1; - bool allOtherStreamsPushed = std::all_of(m_context.streamInfo.begin(), m_context.streamInfo.end(), - [](const auto &entry) { return entry.second.isDataPushed; }); - - if (!m_context.bufferedNotificationSent && (allOtherStreamsPushed || kIsSingle) && m_gstPlayerClient) - { - m_context.bufferedNotificationSent = true; - m_gstPlayerClient->notifyNetworkState(NetworkState::BUFFERED); - RIALTO_SERVER_LOG_MIL("Buffered NetworkState reached"); - } - cancelUnderflow(mediaType); - - const auto eosInfoIt = m_context.endOfStreamInfo.find(mediaType); - if (eosInfoIt != m_context.endOfStreamInfo.end() && eosInfoIt->second == EosState::PENDING) - { - setEos(mediaType); - } - } -} - -void GstGenericPlayer::updateAudioCaps(int32_t rate, int32_t channels, const std::shared_ptr &codecData) -{ - auto elem = m_context.streamInfo.find(firebolt::rialto::MediaSourceType::AUDIO); - if (elem != m_context.streamInfo.end()) - { - StreamInfo &streamInfo = elem->second; - - constexpr int kInvalidRate{0}, kInvalidChannels{0}; - GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(streamInfo.appSrc)); - GstCaps *newCaps = m_gstWrapper->gstCapsCopy(currentCaps); - - if (rate != kInvalidRate) - { - m_gstWrapper->gstCapsSetSimple(newCaps, "rate", G_TYPE_INT, rate, NULL); - } - - if (channels != kInvalidChannels) - { - m_gstWrapper->gstCapsSetSimple(newCaps, "channels", G_TYPE_INT, channels, NULL); - } - - setCodecData(newCaps, codecData); - - if (!m_gstWrapper->gstCapsIsEqual(currentCaps, newCaps)) - { - m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(streamInfo.appSrc), newCaps); - } - - m_gstWrapper->gstCapsUnref(newCaps); - m_gstWrapper->gstCapsUnref(currentCaps); - } -} - -void GstGenericPlayer::updateVideoCaps(int32_t width, int32_t height, Fraction frameRate, - const std::shared_ptr &codecData) -{ - auto elem = m_context.streamInfo.find(firebolt::rialto::MediaSourceType::VIDEO); - if (elem != m_context.streamInfo.end()) - { - StreamInfo &streamInfo = elem->second; - - GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(streamInfo.appSrc)); - GstCaps *newCaps = m_gstWrapper->gstCapsCopy(currentCaps); - - if (width > 0) - { - m_gstWrapper->gstCapsSetSimple(newCaps, "width", G_TYPE_INT, width, NULL); - } - - if (height > 0) - { - m_gstWrapper->gstCapsSetSimple(newCaps, "height", G_TYPE_INT, height, NULL); - } - - if ((kUndefinedSize != frameRate.numerator) && (kUndefinedSize != frameRate.denominator)) - { - m_gstWrapper->gstCapsSetSimple(newCaps, "framerate", GST_TYPE_FRACTION, frameRate.numerator, - frameRate.denominator, NULL); - } - - setCodecData(newCaps, codecData); - - if (!m_gstWrapper->gstCapsIsEqual(currentCaps, newCaps)) - { - m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(streamInfo.appSrc), newCaps); - } - - m_gstWrapper->gstCapsUnref(currentCaps); - m_gstWrapper->gstCapsUnref(newCaps); - } -} - -void GstGenericPlayer::addAudioClippingToBuffer(GstBuffer *buffer, uint64_t clippingStart, uint64_t clippingEnd) const -{ - if (clippingStart || clippingEnd) - { - if (m_gstWrapper->gstBufferAddAudioClippingMeta(buffer, GST_FORMAT_TIME, clippingStart, clippingEnd)) - { - RIALTO_SERVER_LOG_DEBUG("Added audio clipping to buffer %p, start: %" PRIu64 ", end %" PRIu64, buffer, - clippingStart, clippingEnd); - } - else - { - RIALTO_SERVER_LOG_WARN("Failed to add audio clipping to buffer %p, start: %" PRIu64 ", end %" PRIu64, - buffer, clippingStart, clippingEnd); - } - } -} - -bool GstGenericPlayer::setCodecData(GstCaps *caps, const std::shared_ptr &codecData) const -{ - if (codecData && CodecDataType::BUFFER == codecData->type) - { - gpointer memory = m_glibWrapper->gMemdup(codecData->data.data(), codecData->data.size()); - GstBuffer *buf = m_gstWrapper->gstBufferNewWrapped(memory, codecData->data.size()); - m_gstWrapper->gstCapsSetSimple(caps, "codec_data", GST_TYPE_BUFFER, buf, nullptr); - m_gstWrapper->gstBufferUnref(buf); - return true; - } - if (codecData && CodecDataType::STRING == codecData->type) - { - std::string codecDataStr(codecData->data.begin(), codecData->data.end()); - m_gstWrapper->gstCapsSetSimple(caps, "codec_data", G_TYPE_STRING, codecDataStr.c_str(), nullptr); - return true; - } - return false; -} - -void GstGenericPlayer::pushSampleIfRequired(GstElement *source, const std::string &typeStr) -{ - auto initialPosition = m_context.initialPositions.find(source); - if (m_context.initialPositions.end() == initialPosition) - { - // Sending initial sample not needed - return; - } - // GstAppSrc does not replace segment, if it's the same as previous one. - // It causes problems with position reporing in amlogic devices, so we need to push - // two segments with different reset time value. - pushAdditionalSegmentIfRequired(source); - - for (const auto &[position, resetTime, appliedRate, stopPosition] : initialPosition->second) - { - GstSeekFlags seekFlag = resetTime ? GST_SEEK_FLAG_FLUSH : GST_SEEK_FLAG_NONE; - RIALTO_SERVER_LOG_DEBUG("Pushing new %s sample...", typeStr.c_str()); - GstSegment *segment{m_gstWrapper->gstSegmentNew()}; - m_gstWrapper->gstSegmentInit(segment, GST_FORMAT_TIME); - if (!m_gstWrapper->gstSegmentDoSeek(segment, m_context.playbackRate, GST_FORMAT_TIME, seekFlag, - GST_SEEK_TYPE_SET, position, GST_SEEK_TYPE_SET, stopPosition, nullptr)) - { - RIALTO_SERVER_LOG_WARN("Segment seek failed."); - m_gstWrapper->gstSegmentFree(segment); - m_context.initialPositions.erase(initialPosition); - return; - } - segment->applied_rate = appliedRate; - RIALTO_SERVER_LOG_MIL("New %s segment: [%" GST_TIME_FORMAT ", %" GST_TIME_FORMAT - "], rate: %f, appliedRate %f, reset_time: %d\n", - typeStr.c_str(), GST_TIME_ARGS(segment->start), GST_TIME_ARGS(segment->stop), - segment->rate, segment->applied_rate, resetTime); - - GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(source)); - // We can't pass buffer in GstSample, because implementation of gst_app_src_push_sample - // uses gst_buffer_copy, which loses RialtoProtectionMeta (that causes problems with EME - // for first frame). - GstSample *sample = m_gstWrapper->gstSampleNew(nullptr, currentCaps, segment, nullptr); - m_gstWrapper->gstAppSrcPushSample(GST_APP_SRC(source), sample); - m_gstWrapper->gstSampleUnref(sample); - m_gstWrapper->gstCapsUnref(currentCaps); - - m_gstWrapper->gstSegmentFree(segment); - } - m_context.currentPosition[source] = initialPosition->second.back(); - m_context.initialPositions.erase(initialPosition); - return; -} - -void GstGenericPlayer::pushAdditionalSegmentIfRequired(GstElement *source) -{ - auto currentPosition = m_context.currentPosition.find(source); - if (m_context.currentPosition.end() == currentPosition) - { - return; - } - auto initialPosition = m_context.initialPositions.find(source); - if (m_context.initialPositions.end() == initialPosition) - { - return; - } - if (initialPosition->second.size() == 1 && initialPosition->second.back().resetTime && - currentPosition->second == initialPosition->second.back()) - { - RIALTO_SERVER_LOG_INFO("Adding additional segment with reset_time = false"); - SegmentData additionalSegment = initialPosition->second.back(); - additionalSegment.resetTime = false; - initialPosition->second.push_back(additionalSegment); - } -} - -void GstGenericPlayer::setTextTrackPositionIfRequired(GstElement *source) -{ - auto initialPosition = m_context.initialPositions.find(source); - if (m_context.initialPositions.end() == initialPosition) - { - // Sending initial sample not needed - return; - } - - RIALTO_SERVER_LOG_MIL("New subtitle position set %" GST_TIME_FORMAT, - GST_TIME_ARGS(initialPosition->second.back().position)); - m_glibWrapper->gObjectSet(m_context.subtitleSink, "position", - static_cast(initialPosition->second.back().position), nullptr); - - m_context.initialPositions.erase(initialPosition); -} - -bool GstGenericPlayer::reattachSource(const std::unique_ptr &source) -{ - if (m_context.streamInfo.find(source->getType()) == m_context.streamInfo.end()) - { - RIALTO_SERVER_LOG_ERROR("Unable to switch source, type does not exist"); - return false; - } - if (source->getMimeType().empty()) - { - RIALTO_SERVER_LOG_WARN("Skip switch audio source. Unknown mime type"); - return false; - } - std::optional audioAttributes{createAudioAttributes(source)}; - if (!audioAttributes) - { - RIALTO_SERVER_LOG_ERROR("Failed to create audio attributes"); - return false; - } - - long long currentDispPts = getPosition(m_context.pipeline); // NOLINT(runtime/int) - GstCaps *caps{createCapsFromMediaSource(m_gstWrapper, m_glibWrapper, source)}; - GstAppSrc *appSrc{GST_APP_SRC(m_context.streamInfo[source->getType()].appSrc)}; - GstCaps *oldCaps = m_gstWrapper->gstAppSrcGetCaps(appSrc); - if ((!oldCaps) || (!m_gstWrapper->gstCapsIsEqual(caps, oldCaps))) - { - RIALTO_SERVER_LOG_DEBUG("Caps not equal. Perform audio track codec channel switch."); - int sampleAttributes{ - 0}; // rdk_gstreamer_utils::performAudioTrackCodecChannelSwitch checks if this param != NULL only. - std::uint32_t status{0}; // must be 0 to make rdk_gstreamer_utils::performAudioTrackCodecChannelSwitch work - unsigned int ui32Delay{0}; // output param - long long audioChangeTargetPts{-1}; // NOLINT(runtime/int) output param. Set audioChangeTargetPts = - // currentDispPts in rdk_gstreamer_utils function stub - unsigned int audioChangeStage{0}; // Output param. Set to AUDCHG_ALIGN in rdk_gstreamer_utils function stub - gchar *oldCapsCStr = m_gstWrapper->gstCapsToString(oldCaps); - std::string oldCapsStr = std::string(oldCapsCStr); - m_glibWrapper->gFree(oldCapsCStr); - bool audioAac{oldCapsStr.find("audio/mpeg") != std::string::npos}; - bool svpEnabled{true}; // assume always true - bool retVal{false}; // Output param. Set to TRUE in rdk_gstreamer_utils function stub - bool result = - m_rdkGstreamerUtilsWrapper - ->performAudioTrackCodecChannelSwitch(&m_context.playbackGroup, &sampleAttributes, &(*audioAttributes), - &status, &ui32Delay, &audioChangeTargetPts, ¤tDispPts, - &audioChangeStage, - &caps, // may fail for amlogic - that implementation changes - // this parameter, it's probably used by Netflix later - &audioAac, svpEnabled, GST_ELEMENT(appSrc), &retVal); - - if (!result || !retVal) - { - RIALTO_SERVER_LOG_WARN("performAudioTrackCodecChannelSwitch failed! Result: %d, retval %d", result, retVal); - } - } - else - { - RIALTO_SERVER_LOG_DEBUG("Skip switching audio source - caps are the same."); - } - - m_context.lastAudioSampleTimestamps = currentDispPts; - if (caps) - m_gstWrapper->gstCapsUnref(caps); - if (oldCaps) - m_gstWrapper->gstCapsUnref(oldCaps); - - return true; -} - -bool GstGenericPlayer::hasSourceType(const MediaSourceType &mediaSourceType) const -{ - return m_context.streamInfo.find(mediaSourceType) != m_context.streamInfo.end(); -} - -void GstGenericPlayer::scheduleNeedMediaData(GstAppSrc *src) -{ - if (m_workerThread) - { - if (m_scheduledNeedDatas.isNeedDataScheduled(src)) - { - return; - } - m_scheduledNeedDatas.setNeedDataScheduled(src); - m_workerThread->enqueueTask(m_taskFactory->createNeedData(m_context, *this, src)); - } -} - -void GstGenericPlayer::scheduleEnoughData(GstAppSrc *src) -{ - if (m_workerThread) - { - clearNeedDataScheduled(src); - m_workerThread->enqueueTask(m_taskFactory->createEnoughData(m_context, src)); - } -} - -void GstGenericPlayer::scheduleAudioUnderflow() -{ - if (m_workerThread) - { - bool underflowEnabled = m_context.isPlaying && !m_context.audioSourceRemoved; - m_workerThread->enqueueTask( - m_taskFactory->createUnderflow(m_context, *this, underflowEnabled, MediaSourceType::AUDIO)); - } -} - -void GstGenericPlayer::scheduleVideoUnderflow() -{ - if (m_workerThread) - { - bool underflowEnabled = m_context.isPlaying; - m_workerThread->enqueueTask( - m_taskFactory->createUnderflow(m_context, *this, underflowEnabled, MediaSourceType::VIDEO)); - } -} - -void GstGenericPlayer::scheduleAllSourcesAttached() -{ - allSourcesAttached(); -} - -void GstGenericPlayer::cancelUnderflow(firebolt::rialto::MediaSourceType mediaSource) -{ - auto elem = m_context.streamInfo.find(mediaSource); - if (elem != m_context.streamInfo.end()) - { - StreamInfo &streamInfo = elem->second; - if (!streamInfo.underflowOccured) - { - return; - } - - RIALTO_SERVER_LOG_DEBUG("Cancelling %s underflow", common::convertMediaSourceType(mediaSource)); - streamInfo.underflowOccured = false; - } -} - -void GstGenericPlayer::play() -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createPlay(*this)); - } -} - -void GstGenericPlayer::pause() -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createPause(m_context, *this)); - } -} - -void GstGenericPlayer::stop() -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createStop(m_context, *this)); - } -} - -bool GstGenericPlayer::changePipelineState(GstState newState) -{ - if (!m_context.pipeline) - { - RIALTO_SERVER_LOG_ERROR("Change state failed - pipeline is nullptr"); - if (m_gstPlayerClient) - m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); - return false; - } - if (m_gstWrapper->gstElementSetState(m_context.pipeline, newState) == GST_STATE_CHANGE_FAILURE) - { - RIALTO_SERVER_LOG_ERROR("Change state failed - Gstreamer returned an error"); - if (m_gstPlayerClient) - m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); - return false; - } - return true; -} - -int64_t GstGenericPlayer::getPosition(GstElement *element) -{ - if (!element) - { - RIALTO_SERVER_LOG_WARN("Element is null"); - return -1; - } - - if (m_flushWatcher->isFlushOngoing()) - { - RIALTO_SERVER_LOG_WARN("Can't get position while flush is ongoing"); - return -1; - } - - m_gstWrapper->gstStateLock(element); - - const auto kElementState{m_gstWrapper->gstElementGetState(element)}; - const auto kStateChangeReturn{m_gstWrapper->gstElementGetStateReturn(element)}; - const auto kNextState{m_gstWrapper->gstElementGetStateNext(element)}; - if (kElementState < GST_STATE_PAUSED || - (kStateChangeReturn == GST_STATE_CHANGE_ASYNC && kNextState == GST_STATE_PAUSED)) - { - RIALTO_SERVER_LOG_WARN("Element is prerolling or in invalid state - state: %s, return: %s, next: %s", - m_gstWrapper->gstElementStateGetName(kElementState), - m_gstWrapper->gstElementStateChangeReturnGetName(kStateChangeReturn), - m_gstWrapper->gstElementStateGetName(kNextState)); - - m_gstWrapper->gstStateUnlock(element); - return -1; - } - m_gstWrapper->gstStateUnlock(element); - - gint64 position = -1; - if (!m_gstWrapper->gstElementQueryPosition(m_context.pipeline, GST_FORMAT_TIME, &position)) - { - RIALTO_SERVER_LOG_WARN("Failed to query position"); - return -1; - } - - return position; -} - -void GstGenericPlayer::setVideoGeometry(int x, int y, int width, int height) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask( - m_taskFactory->createSetVideoGeometry(m_context, *this, Rectangle{x, y, width, height})); - } -} - -void GstGenericPlayer::setEos(const firebolt::rialto::MediaSourceType &type) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createEos(m_context, *this, type)); - } -} - -bool GstGenericPlayer::setVideoSinkRectangle() -{ - bool result = false; - GstElement *videoSink{getSink(MediaSourceType::VIDEO)}; - if (videoSink) - { - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(videoSink), "rectangle")) - { - std::string rect = - std::to_string(m_context.pendingGeometry.x) + ',' + std::to_string(m_context.pendingGeometry.y) + ',' + - std::to_string(m_context.pendingGeometry.width) + ',' + std::to_string(m_context.pendingGeometry.height); - m_glibWrapper->gObjectSet(videoSink, "rectangle", rect.c_str(), nullptr); - m_context.pendingGeometry.clear(); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set the video rectangle"); - } - m_gstWrapper->gstObjectUnref(videoSink); - } - - return result; -} - -bool GstGenericPlayer::setImmediateOutput() -{ - bool result{false}; - if (m_context.pendingImmediateOutputForVideo.has_value()) - { - GstElement *sink{getSink(MediaSourceType::VIDEO)}; - if (sink) - { - bool immediateOutput{m_context.pendingImmediateOutputForVideo.value()}; - RIALTO_SERVER_LOG_DEBUG("Set immediate-output to %s", immediateOutput ? "TRUE" : "FALSE"); - - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "immediate-output")) - { - gboolean immediateOutputGboolean{immediateOutput ? TRUE : FALSE}; - m_glibWrapper->gObjectSet(sink, "immediate-output", immediateOutputGboolean, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set immediate-output property on sink '%s'", GST_ELEMENT_NAME(sink)); - } - m_context.pendingImmediateOutputForVideo.reset(); - m_gstWrapper->gstObjectUnref(sink); - } - else - { - RIALTO_SERVER_LOG_DEBUG("Pending an immediate-output, sink is NULL"); - } - } - return result; -} - -bool GstGenericPlayer::setShowVideoWindow() -{ - if (!m_context.pendingShowVideoWindow.has_value()) - { - RIALTO_SERVER_LOG_WARN("No show video window value to be set. Aborting..."); - return false; - } - - GstElement *videoSink{getSink(MediaSourceType::VIDEO)}; - if (!videoSink) - { - RIALTO_SERVER_LOG_DEBUG("Setting show video window queued. Video sink is NULL"); - return false; - } - bool result{false}; - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(videoSink), "show-video-window")) - { - m_glibWrapper->gObjectSet(videoSink, "show-video-window", m_context.pendingShowVideoWindow.value(), nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Setting show video window failed. Property does not exist"); - } - m_context.pendingShowVideoWindow.reset(); - m_gstWrapper->gstObjectUnref(GST_OBJECT(videoSink)); - return result; -} - -bool GstGenericPlayer::setLowLatency() -{ - bool result{false}; - if (m_context.pendingLowLatency.has_value()) - { - GstElement *sink{getSink(MediaSourceType::AUDIO)}; - if (sink) - { - bool lowLatency{m_context.pendingLowLatency.value()}; - RIALTO_SERVER_LOG_DEBUG("Set low-latency to %s", lowLatency ? "TRUE" : "FALSE"); - - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "low-latency")) - { - gboolean lowLatencyGboolean{lowLatency ? TRUE : FALSE}; - m_glibWrapper->gObjectSet(sink, "low-latency", lowLatencyGboolean, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set low-latency property on sink '%s'", GST_ELEMENT_NAME(sink)); - } - m_context.pendingLowLatency.reset(); - m_gstWrapper->gstObjectUnref(sink); - } - else - { - RIALTO_SERVER_LOG_DEBUG("Pending low-latency, sink is NULL"); - } - } - return result; -} - -bool GstGenericPlayer::setSync() -{ - bool result{false}; - if (m_context.pendingSync.has_value()) - { - GstElement *sink{getSink(MediaSourceType::AUDIO)}; - if (sink) - { - bool sync{m_context.pendingSync.value()}; - RIALTO_SERVER_LOG_DEBUG("Set sync to %s", sync ? "TRUE" : "FALSE"); - - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "sync")) - { - gboolean syncGboolean{sync ? TRUE : FALSE}; - m_glibWrapper->gObjectSet(sink, "sync", syncGboolean, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set sync property on sink '%s'", GST_ELEMENT_NAME(sink)); - } - m_context.pendingSync.reset(); - m_gstWrapper->gstObjectUnref(sink); - } - else - { - RIALTO_SERVER_LOG_DEBUG("Pending sync, sink is NULL"); - } - } - return result; -} - -bool GstGenericPlayer::setSyncOff() -{ - bool result{false}; - if (m_context.pendingSyncOff.has_value()) - { - GstElement *decoder = getDecoder(MediaSourceType::AUDIO); - if (decoder) - { - bool syncOff{m_context.pendingSyncOff.value()}; - RIALTO_SERVER_LOG_DEBUG("Set sync-off to %s", syncOff ? "TRUE" : "FALSE"); - - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "sync-off")) - { - gboolean syncOffGboolean{decoder ? TRUE : FALSE}; - m_glibWrapper->gObjectSet(decoder, "sync-off", syncOffGboolean, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set sync-off property on decoder '%s'", GST_ELEMENT_NAME(decoder)); - } - m_context.pendingSyncOff.reset(); - m_gstWrapper->gstObjectUnref(decoder); - } - else - { - RIALTO_SERVER_LOG_DEBUG("Pending sync-off, decoder is NULL"); - } - } - return result; -} - -bool GstGenericPlayer::setStreamSyncMode(const MediaSourceType &type) -{ - bool result{false}; - int32_t streamSyncMode{0}; - { - std::unique_lock lock{m_context.propertyMutex}; - if (m_context.pendingStreamSyncMode.find(type) == m_context.pendingStreamSyncMode.end()) - { - return false; - } - streamSyncMode = m_context.pendingStreamSyncMode[type]; - } - if (MediaSourceType::AUDIO == type) - { - GstElement *decoder = getDecoder(MediaSourceType::AUDIO); - if (!decoder) - { - RIALTO_SERVER_LOG_DEBUG("Pending stream-sync-mode, decoder is NULL"); - return false; - } - - RIALTO_SERVER_LOG_DEBUG("Set stream-sync-mode to %d", streamSyncMode); - - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "stream-sync-mode")) - { - gint streamSyncModeGint{static_cast(streamSyncMode)}; - m_glibWrapper->gObjectSet(decoder, "stream-sync-mode", streamSyncModeGint, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set stream-sync-mode property on decoder '%s'", GST_ELEMENT_NAME(decoder)); - } - m_gstWrapper->gstObjectUnref(decoder); - std::unique_lock lock{m_context.propertyMutex}; - m_context.pendingStreamSyncMode.erase(type); - } - else if (MediaSourceType::VIDEO == type) - { - GstElement *parser = getParser(MediaSourceType::VIDEO); - if (!parser) - { - RIALTO_SERVER_LOG_DEBUG("Pending syncmode-streaming, parser is NULL"); - return false; - } - - gboolean streamSyncModeBoolean{static_cast(streamSyncMode)}; - RIALTO_SERVER_LOG_DEBUG("Set syncmode-streaming to %d", streamSyncMode); - - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(parser), "syncmode-streaming")) - { - m_glibWrapper->gObjectSet(parser, "syncmode-streaming", streamSyncModeBoolean, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set syncmode-streaming property on parser '%s'", GST_ELEMENT_NAME(parser)); - } - m_gstWrapper->gstObjectUnref(parser); - std::unique_lock lock{m_context.propertyMutex}; - m_context.pendingStreamSyncMode.erase(type); - } - return result; -} - -bool GstGenericPlayer::setRenderFrame() -{ - bool result{false}; - if (m_context.pendingRenderFrame) - { - static const std::string kStepOnPrerollPropertyName = "frame-step-on-preroll"; - GstElement *sink{getSink(MediaSourceType::VIDEO)}; - if (sink) - { - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), kStepOnPrerollPropertyName.c_str())) - { - RIALTO_SERVER_LOG_INFO("Rendering preroll"); - - m_glibWrapper->gObjectSet(sink, kStepOnPrerollPropertyName.c_str(), 1, nullptr); - m_gstWrapper->gstElementSendEvent(sink, m_gstWrapper->gstEventNewStep(GST_FORMAT_BUFFERS, 1, 1.0, true, - false)); - m_glibWrapper->gObjectSet(sink, kStepOnPrerollPropertyName.c_str(), 0, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Video sink doesn't have property `%s`", kStepOnPrerollPropertyName.c_str()); - } - m_gstWrapper->gstObjectUnref(sink); - m_context.pendingRenderFrame = false; - } - else - { - RIALTO_SERVER_LOG_DEBUG("Pending render frame, sink is NULL"); - } - } - return result; -} - -bool GstGenericPlayer::setBufferingLimit() -{ - bool result{false}; - guint bufferingLimit{0}; - { - std::unique_lock lock{m_context.propertyMutex}; - if (!m_context.pendingBufferingLimit.has_value()) - { - return false; - } - bufferingLimit = static_cast(m_context.pendingBufferingLimit.value()); - } - - GstElement *decoder{getDecoder(MediaSourceType::AUDIO)}; - if (decoder) - { - RIALTO_SERVER_LOG_DEBUG("Set limit-buffering-ms to %u", bufferingLimit); - - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "limit-buffering-ms")) - { - m_glibWrapper->gObjectSet(decoder, "limit-buffering-ms", bufferingLimit, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set limit-buffering-ms property on decoder '%s'", - GST_ELEMENT_NAME(decoder)); - } - m_gstWrapper->gstObjectUnref(decoder); - std::unique_lock lock{m_context.propertyMutex}; - m_context.pendingBufferingLimit.reset(); - } - else - { - RIALTO_SERVER_LOG_DEBUG("Pending limit-buffering-ms, decoder is NULL"); - } - return result; -} - -bool GstGenericPlayer::setUseBuffering() -{ - std::unique_lock lock{m_context.propertyMutex}; - if (m_context.pendingUseBuffering.has_value()) - { - if (m_context.playbackGroup.m_curAudioDecodeBin) - { - gboolean useBufferingGboolean{m_context.pendingUseBuffering.value() ? TRUE : FALSE}; - RIALTO_SERVER_LOG_DEBUG("Set use-buffering to %d", useBufferingGboolean); - m_glibWrapper->gObjectSet(m_context.playbackGroup.m_curAudioDecodeBin, "use-buffering", - useBufferingGboolean, nullptr); - m_context.pendingUseBuffering.reset(); - return true; - } - else - { - RIALTO_SERVER_LOG_DEBUG("Pending use-buffering, decodebin is NULL"); - } - } - return false; -} - -bool GstGenericPlayer::setWesterossinkSecondaryVideo() -{ - bool result = false; - GstElementFactory *factory = m_gstWrapper->gstElementFactoryFind("westerossink"); - if (factory) - { - GstElement *videoSink = m_gstWrapper->gstElementFactoryCreate(factory, nullptr); - if (videoSink) - { - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(videoSink), "res-usage")) - { - m_glibWrapper->gObjectSet(videoSink, "res-usage", 0x0u, nullptr); - m_glibWrapper->gObjectSet(m_context.pipeline, "video-sink", videoSink, nullptr); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to set the westerossink res-usage"); - m_gstWrapper->gstObjectUnref(GST_OBJECT(videoSink)); - } - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to create the westerossink"); - } - - m_gstWrapper->gstObjectUnref(GST_OBJECT(factory)); - } - else - { - // No westeros sink - result = true; - } - - return result; -} - -bool GstGenericPlayer::setErmContext() -{ - bool result = false; - GstContext *context = m_gstWrapper->gstContextNew("erm", false); - if (context) - { - GstStructure *contextStructure = m_gstWrapper->gstContextWritableStructure(context); - if (contextStructure) - { - m_gstWrapper->gstStructureSet(contextStructure, "res-usage", G_TYPE_UINT, 0x0u, nullptr); - m_gstWrapper->gstElementSetContext(GST_ELEMENT(m_context.pipeline), context); - result = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to create the erm structure"); - } - m_gstWrapper->gstContextUnref(context); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to create the erm context"); - } - - return result; -} - -void GstGenericPlayer::startPositionReportingAndCheckAudioUnderflowTimer() -{ - if (m_positionReportingAndCheckAudioUnderflowTimer && m_positionReportingAndCheckAudioUnderflowTimer->isActive()) - { - return; - } - - m_positionReportingAndCheckAudioUnderflowTimer = m_timerFactory->createTimer( - kPositionReportTimerMs, - [this]() - { - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createReportPosition(m_context, *this)); - m_workerThread->enqueueTask(m_taskFactory->createCheckAudioUnderflow(m_context, *this)); - } - }, - firebolt::rialto::common::TimerType::PERIODIC); -} - -void GstGenericPlayer::stopPositionReportingAndCheckAudioUnderflowTimer() -{ - if (m_positionReportingAndCheckAudioUnderflowTimer && m_positionReportingAndCheckAudioUnderflowTimer->isActive()) - { - m_positionReportingAndCheckAudioUnderflowTimer->cancel(); - m_positionReportingAndCheckAudioUnderflowTimer.reset(); - } -} - -void GstGenericPlayer::startSubtitleClockResyncTimer() -{ - if (m_subtitleClockResyncTimer && m_subtitleClockResyncTimer->isActive()) - { - return; - } - - m_subtitleClockResyncTimer = m_timerFactory->createTimer( - kSubtitleClockResyncInterval, - [this]() - { - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSynchroniseSubtitleClock(m_context, *this)); - } - }, - firebolt::rialto::common::TimerType::PERIODIC); -} - -void GstGenericPlayer::stopSubtitleClockResyncTimer() -{ - if (m_subtitleClockResyncTimer && m_subtitleClockResyncTimer->isActive()) - { - m_subtitleClockResyncTimer->cancel(); - m_subtitleClockResyncTimer.reset(); - } -} - -void GstGenericPlayer::stopWorkerThread() -{ - if (m_workerThread) - { - m_workerThread->stop(); - } -} - -void GstGenericPlayer::setPendingPlaybackRate() -{ - RIALTO_SERVER_LOG_INFO("Setting pending playback rate"); - setPlaybackRate(m_context.pendingPlaybackRate); -} - -void GstGenericPlayer::renderFrame() -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createRenderFrame(m_context, *this)); - } -} - -void GstGenericPlayer::setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask( - m_taskFactory->createSetVolume(m_context, *this, targetVolume, volumeDuration, easeType)); - } -} - -bool GstGenericPlayer::getVolume(double ¤tVolume) -{ - // We are on main thread here, but m_context.pipeline can be used, because it's modified only in GstGenericPlayer - // constructor and destructor. GstGenericPlayer is created/destructed on main thread, so we won't have a crash here. - if (!m_context.pipeline) - { - return false; - } - - // NOTE: No gstreamer documentation for "fade-volume" could be found at the time this code was written. - // Therefore the author performed several tests on a supported platform (Flex2) to determine the behaviour of this property. - // The code has been written to be backwardly compatible on platforms that don't have this property. - // The observed behaviour was: - // - if the returned fade volume is negative then audio-fade is not active. In this case the usual technique - // to find volume in the pipeline works and is used. - // - if the returned fade volume is positive then audio-fade is active. In this case the returned fade volume - // directly returns the current volume level 0=min to 100=max (and the pipeline's current volume level is - // meaningless and doesn't contribute in this case). - GstElement *sink{getSink(MediaSourceType::AUDIO)}; - if (m_context.audioFadeEnabled && sink && - m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "fade-volume")) - { - gint fadeVolume{-100}; - m_glibWrapper->gObjectGet(sink, "fade-volume", &fadeVolume, NULL); - if (fadeVolume < 0) - { - currentVolume = m_gstWrapper->gstStreamVolumeGetVolume(GST_STREAM_VOLUME(m_context.pipeline), - GST_STREAM_VOLUME_FORMAT_LINEAR); - RIALTO_SERVER_LOG_INFO("Fade volume is negative, using volume from pipeline: %f", currentVolume); - } - else - { - currentVolume = static_cast(fadeVolume) / 100.0; - RIALTO_SERVER_LOG_INFO("Fade volume is supported: %f", currentVolume); - } - } - else - { - currentVolume = m_gstWrapper->gstStreamVolumeGetVolume(GST_STREAM_VOLUME(m_context.pipeline), - GST_STREAM_VOLUME_FORMAT_LINEAR); - RIALTO_SERVER_LOG_INFO("Fade volume is not supported, using volume from pipeline: %f", currentVolume); - } - - if (sink) - m_gstWrapper->gstObjectUnref(sink); - - return true; -} - -void GstGenericPlayer::setMute(const MediaSourceType &mediaSourceType, bool mute) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetMute(m_context, *this, mediaSourceType, mute)); - } -} - -bool GstGenericPlayer::getMute(const MediaSourceType &mediaSourceType, bool &mute) -{ - // We are on main thread here, but m_context.pipeline can be used, because it's modified only in GstGenericPlayer - // constructor and destructor. GstGenericPlayer is created/destructed on main thread, so we won't have a crash here. - if (mediaSourceType == MediaSourceType::SUBTITLE) - { - if (!m_context.subtitleSink) - { - RIALTO_SERVER_LOG_ERROR("There is no subtitle sink"); - return false; - } - gboolean muteValue{FALSE}; - m_glibWrapper->gObjectGet(m_context.subtitleSink, "mute", &muteValue, nullptr); - mute = muteValue; - } - else if (mediaSourceType == MediaSourceType::AUDIO) - { - if (!m_context.pipeline) - { - return false; - } - mute = m_gstWrapper->gstStreamVolumeGetMute(GST_STREAM_VOLUME(m_context.pipeline)); - } - else - { - RIALTO_SERVER_LOG_ERROR("Getting mute for type %s unsupported", common::convertMediaSourceType(mediaSourceType)); - return false; - } - - return true; -} - -bool GstGenericPlayer::isAsync(const MediaSourceType &mediaSourceType) const -{ - GstElement *sink = getSink(mediaSourceType); - if (!sink) - { - RIALTO_SERVER_LOG_WARN("Sink not found for %s", common::convertMediaSourceType(mediaSourceType)); - return true; // Our sinks are async by default - } - gboolean returnValue{TRUE}; - m_glibWrapper->gObjectGet(sink, "async", &returnValue, nullptr); - m_gstWrapper->gstObjectUnref(sink); - return returnValue == TRUE; -} - -void GstGenericPlayer::setTextTrackIdentifier(const std::string &textTrackIdentifier) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetTextTrackIdentifier(m_context, textTrackIdentifier)); - } -} - -bool GstGenericPlayer::getTextTrackIdentifier(std::string &textTrackIdentifier) -{ - if (!m_context.subtitleSink) - { - RIALTO_SERVER_LOG_ERROR("There is no subtitle sink"); - return false; - } - - gchar *identifier = nullptr; - m_glibWrapper->gObjectGet(m_context.subtitleSink, "text-track-identifier", &identifier, nullptr); - - if (identifier) - { - textTrackIdentifier = identifier; - m_glibWrapper->gFree(identifier); - return true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to get text track identifier"); - return false; - } -} - -bool GstGenericPlayer::setLowLatency(bool lowLatency) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetLowLatency(m_context, *this, lowLatency)); - } - return true; -} - -bool GstGenericPlayer::setSync(bool sync) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetSync(m_context, *this, sync)); - } - return true; -} - -bool GstGenericPlayer::getSync(bool &sync) -{ - bool returnValue{false}; - GstElement *sink{getSink(MediaSourceType::AUDIO)}; - if (sink) - { - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(sink), "sync")) - { - m_glibWrapper->gObjectGet(sink, "sync", &sync, nullptr); - returnValue = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Sync not supported in sink '%s'", GST_ELEMENT_NAME(sink)); - } - m_gstWrapper->gstObjectUnref(sink); - } - else if (m_context.pendingSync.has_value()) - { - RIALTO_SERVER_LOG_DEBUG("Returning queued value"); - sync = m_context.pendingSync.value(); - returnValue = true; - } - else - { - // We dont know the default setting on the sync, so return failure here - RIALTO_SERVER_LOG_WARN("No audio sink attached or queued value"); - } - - return returnValue; -} - -bool GstGenericPlayer::setSyncOff(bool syncOff) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetSyncOff(m_context, *this, syncOff)); - } - return true; -} - -bool GstGenericPlayer::setStreamSyncMode(const MediaSourceType &mediaSourceType, int32_t streamSyncMode) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask( - m_taskFactory->createSetStreamSyncMode(m_context, *this, mediaSourceType, streamSyncMode)); - } - return true; -} - -bool GstGenericPlayer::getStreamSyncMode(int32_t &streamSyncMode) -{ - bool returnValue{false}; - GstElement *decoder = getDecoder(MediaSourceType::AUDIO); - if (decoder && m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "stream-sync-mode")) - { - m_glibWrapper->gObjectGet(decoder, "stream-sync-mode", &streamSyncMode, nullptr); - returnValue = true; - } - else - { - std::unique_lock lock{m_context.propertyMutex}; - if (m_context.pendingStreamSyncMode.find(MediaSourceType::AUDIO) != m_context.pendingStreamSyncMode.end()) - { - RIALTO_SERVER_LOG_DEBUG("Returning queued value"); - streamSyncMode = m_context.pendingStreamSyncMode[MediaSourceType::AUDIO]; - returnValue = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Stream sync mode not supported in decoder '%s'", - (decoder ? GST_ELEMENT_NAME(decoder) : "null")); - } - } - - if (decoder) - m_gstWrapper->gstObjectUnref(GST_OBJECT(decoder)); - - return returnValue; -} - -void GstGenericPlayer::ping(std::unique_ptr &&heartbeatHandler) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createPing(std::move(heartbeatHandler))); - } -} - -void GstGenericPlayer::flush(const MediaSourceType &mediaSourceType, bool resetTime, bool &async) -{ - if (m_workerThread) - { - async = isAsync(mediaSourceType); - m_flushWatcher->setFlushing(mediaSourceType, async); - m_workerThread->enqueueTask(m_taskFactory->createFlush(m_context, *this, mediaSourceType, resetTime)); - } -} - -void GstGenericPlayer::setSourcePosition(const MediaSourceType &mediaSourceType, int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetSourcePosition(m_context, *this, mediaSourceType, position, - resetTime, appliedRate, stopPosition)); - } -} - -void GstGenericPlayer::setSubtitleOffset(int64_t position) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetSubtitleOffset(m_context, position)); - } -} - -void GstGenericPlayer::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask( - m_taskFactory->createProcessAudioGap(m_context, position, duration, discontinuityGap, audioAac)); - } -} - -void GstGenericPlayer::setBufferingLimit(uint32_t limitBufferingMs) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetBufferingLimit(m_context, *this, limitBufferingMs)); - } -} - -bool GstGenericPlayer::getBufferingLimit(uint32_t &limitBufferingMs) -{ - bool returnValue{false}; - GstElement *decoder = getDecoder(MediaSourceType::AUDIO); - if (decoder && m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(decoder), "limit-buffering-ms")) - { - m_glibWrapper->gObjectGet(decoder, "limit-buffering-ms", &limitBufferingMs, nullptr); - returnValue = true; - } - else - { - std::unique_lock lock{m_context.propertyMutex}; - if (m_context.pendingBufferingLimit.has_value()) - { - RIALTO_SERVER_LOG_DEBUG("Returning queued value"); - limitBufferingMs = m_context.pendingBufferingLimit.value(); - returnValue = true; - } - else - { - RIALTO_SERVER_LOG_ERROR("buffering limit not supported in decoder '%s'", - (decoder ? GST_ELEMENT_NAME(decoder) : "null")); - } - } - - if (decoder) - m_gstWrapper->gstObjectUnref(GST_OBJECT(decoder)); - - return returnValue; -} - -void GstGenericPlayer::setUseBuffering(bool useBuffering) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSetUseBuffering(m_context, *this, useBuffering)); - } -} - -bool GstGenericPlayer::getUseBuffering(bool &useBuffering) -{ - if (m_context.playbackGroup.m_curAudioDecodeBin) - { - m_glibWrapper->gObjectGet(m_context.playbackGroup.m_curAudioDecodeBin, "use-buffering", &useBuffering, nullptr); - return true; - } - else - { - std::unique_lock lock{m_context.propertyMutex}; - if (m_context.pendingUseBuffering.has_value()) - { - RIALTO_SERVER_LOG_DEBUG("Returning queued value"); - useBuffering = m_context.pendingUseBuffering.value(); - return true; - } - } - return false; -} - -void GstGenericPlayer::switchSource(const std::unique_ptr &mediaSource) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createSwitchSource(*this, mediaSource)); - } -} - -void GstGenericPlayer::handleBusMessage(GstMessage *message, bool priority) -{ - if (priority) - { - m_workerThread->enqueuePriorityTask( - m_taskFactory->createHandleBusMessage(m_context, *this, message, *m_flushWatcher)); - } - else - { - m_workerThread->enqueueTask(m_taskFactory->createHandleBusMessage(m_context, *this, message, *m_flushWatcher)); - } -} - -void GstGenericPlayer::updatePlaybackGroup(GstElement *typefind, const GstCaps *caps) -{ - m_workerThread->enqueueTask(m_taskFactory->createUpdatePlaybackGroup(m_context, *this, typefind, caps)); -} - -void GstGenericPlayer::addAutoVideoSinkChild(GObject *object) -{ - // Only add children that are sinks - if (GST_OBJECT_FLAG_IS_SET(GST_ELEMENT(object), GST_ELEMENT_FLAG_SINK)) - { - RIALTO_SERVER_LOG_DEBUG("Store AutoVideoSink child sink"); - - if (m_context.autoVideoChildSink && m_context.autoVideoChildSink != GST_ELEMENT(object)) - { - RIALTO_SERVER_LOG_MIL("AutoVideoSink child is been overwritten"); - } - m_context.autoVideoChildSink = GST_ELEMENT(object); - } -} - -void GstGenericPlayer::addAutoAudioSinkChild(GObject *object) -{ - // Only add children that are sinks - if (GST_OBJECT_FLAG_IS_SET(GST_ELEMENT(object), GST_ELEMENT_FLAG_SINK)) - { - RIALTO_SERVER_LOG_DEBUG("Store AutoAudioSink child sink"); - - if (m_context.autoAudioChildSink && m_context.autoAudioChildSink != GST_ELEMENT(object)) - { - RIALTO_SERVER_LOG_MIL("AutoAudioSink child is been overwritten"); - } - m_context.autoAudioChildSink = GST_ELEMENT(object); - } -} - -void GstGenericPlayer::removeAutoVideoSinkChild(GObject *object) -{ - if (GST_OBJECT_FLAG_IS_SET(GST_ELEMENT(object), GST_ELEMENT_FLAG_SINK)) - { - RIALTO_SERVER_LOG_DEBUG("Remove AutoVideoSink child sink"); - - if (m_context.autoVideoChildSink && m_context.autoVideoChildSink != GST_ELEMENT(object)) - { - RIALTO_SERVER_LOG_MIL("AutoVideoSink child sink is not the same as the one stored"); - return; - } - - m_context.autoVideoChildSink = nullptr; - } -} - -void GstGenericPlayer::removeAutoAudioSinkChild(GObject *object) -{ - if (GST_OBJECT_FLAG_IS_SET(GST_ELEMENT(object), GST_ELEMENT_FLAG_SINK)) - { - RIALTO_SERVER_LOG_DEBUG("Remove AutoAudioSink child sink"); - - if (m_context.autoAudioChildSink && m_context.autoAudioChildSink != GST_ELEMENT(object)) - { - RIALTO_SERVER_LOG_MIL("AutoAudioSink child sink is not the same as the one stored"); - return; - } - - m_context.autoAudioChildSink = nullptr; - } -} - -GstElement *GstGenericPlayer::getSinkChildIfAutoVideoSink(GstElement *sink) const -{ - const gchar *kTmpName = m_glibWrapper->gTypeName(G_OBJECT_TYPE(sink)); - if (!kTmpName) - return sink; - - const std::string kElementTypeName{kTmpName}; - if (kElementTypeName == "GstAutoVideoSink") - { - if (!m_context.autoVideoChildSink) - { - RIALTO_SERVER_LOG_WARN("No child sink has been added to the autovideosink"); - } - else - { - return m_context.autoVideoChildSink; - } - } - return sink; -} - -GstElement *GstGenericPlayer::getSinkChildIfAutoAudioSink(GstElement *sink) const -{ - const gchar *kTmpName = m_glibWrapper->gTypeName(G_OBJECT_TYPE(sink)); - if (!kTmpName) - return sink; - - const std::string kElementTypeName{kTmpName}; - if (kElementTypeName == "GstAutoAudioSink") - { - if (!m_context.autoAudioChildSink) - { - RIALTO_SERVER_LOG_WARN("No child sink has been added to the autoaudiosink"); - } - else - { - return m_context.autoAudioChildSink; - } - } - return sink; -} - -void GstGenericPlayer::setPlaybinFlags(bool enableAudio) -{ - unsigned flags = getGstPlayFlag("video") | getGstPlayFlag("native-video") | getGstPlayFlag("text"); - - if (enableAudio) - { - flags |= getGstPlayFlag("audio"); - flags |= shouldEnableNativeAudio() ? getGstPlayFlag("native-audio") : 0; - } - - m_glibWrapper->gObjectSet(m_context.pipeline, "flags", flags, nullptr); -} - -bool GstGenericPlayer::shouldEnableNativeAudio() -{ - GstElementFactory *factory = m_gstWrapper->gstElementFactoryFind("brcmaudiosink"); - if (factory) - { - m_gstWrapper->gstObjectUnref(GST_OBJECT(factory)); - return true; - } - return false; -} - -void GstGenericPlayer::clearNeedDataScheduled(GstAppSrc *src) -{ - m_scheduledNeedDatas.clearNeedDataScheduled(src); -} -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstInitialiser.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstInitialiser.cpp deleted file mode 100644 index 087358ee3..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstInitialiser.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GstInitialiser.h" -#include "GstLogForwarding.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server -{ -GstInitialiser::~GstInitialiser() -{ - if (m_thread.joinable()) - { - m_thread.join(); - } - -#ifdef FREE_MEM_BEFORE_EXIT - if (m_gstWrapper) - { - m_gstWrapper->gstDeinit(); - m_gstWrapper.reset(); - } -#endif -} - -IGstInitialiser &IGstInitialiser::instance() -{ - static GstInitialiser initialiser; - return initialiser; -} - -void GstInitialiser::initialise(int *argc, char ***argv) -{ - if (m_thread.joinable()) - { - RIALTO_SERVER_LOG_WARN("Gstreamer is already initialised, no need to do it twice..."); - return; - } - - m_thread = std::thread( - [=]() - { - std::shared_ptr factory = - firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); - m_gstWrapper = factory->getGstWrapper(); - - if (!m_gstWrapper) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gst wrapper"); - return; - } - - m_gstWrapper->gstInit(argc, argv); - - // remove rialto sinks from the registry - GstPlugin *rialtoPlugin = - m_gstWrapper->gstRegistryFindPlugin(m_gstWrapper->gstRegistryGet(), "rialtosinks"); - if (rialtoPlugin) - { - m_gstWrapper->gstRegistryRemovePlugin(m_gstWrapper->gstRegistryGet(), rialtoPlugin); - m_gstWrapper->gstObjectUnref(rialtoPlugin); - } - - enableGstLogForwarding(); - - std::unique_lock lock{m_mutex}; - m_isInitialised = true; - m_cv.notify_all(); - }); -} - -void GstInitialiser::waitForInitialisation() const -{ - std::unique_lock lock{m_mutex}; - m_cv.wait(lock, [this]() { return m_isInitialised; }); -} -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstLogForwarding.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstLogForwarding.cpp deleted file mode 100644 index 8d8f768ec..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstLogForwarding.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GstLogForwarding.h" -#include "RialtoLogging.h" -#include -#include - -namespace -{ -void gstreamerLogFunction(GstDebugCategory *category, GstDebugLevel level, const gchar *file, const gchar *function, - gint line, GObject *object, GstDebugMessage *message, gpointer data) -{ - std::stringstream ss; - switch (level) - { - case GST_LEVEL_NONE: - case GST_LEVEL_ERROR: - { - ss << "ERR: "; - break; - } - case GST_LEVEL_WARNING: - { - ss << "WRN: "; - break; - } - case GST_LEVEL_FIXME: - { - ss << "FIXME: "; - break; - } - case GST_LEVEL_INFO: - { - ss << "NFO: "; - break; - } - case GST_LEVEL_DEBUG: - { - ss << "DBG: "; - break; - } - case GST_LEVEL_LOG: - { - ss << "LOG: "; - break; - } - case GST_LEVEL_TRACE: - { - ss << "TRACE: "; - break; - } - case GST_LEVEL_MEMDUMP: - { - ss << "MEMDUMP: "; - break; - } - case GST_LEVEL_COUNT: - { - ss << "COUNT: "; - break; - } - default: - { - break; - } - } - ss << "C:" << gst_debug_category_get_name(category) << " M:" << file << " F:" << function << ":" << line; - if (object) - { - if (GST_IS_PAD(object) && GST_OBJECT_NAME(object) && GST_OBJECT_PARENT(object) && - GST_OBJECT_NAME(GST_OBJECT_PARENT(object))) - { - ss << " <" << GST_OBJECT_NAME(GST_OBJECT_PARENT(object)) << ":" << GST_OBJECT_NAME(object) << ">"; - } - else if (GST_IS_OBJECT(object) && GST_OBJECT_NAME(object)) - { - ss << " <" << GST_OBJECT_NAME(object) << ">"; - } - else if (G_IS_OBJECT(object)) - { - ss << " <" << G_OBJECT_TYPE_NAME(object) << "@" << static_cast(object) << ">"; - } - else - { - ss << " <" << static_cast(object) << ">"; - } - } - ss << ": " << gst_debug_message_get(message); - RIALTO_LOG_EXTERNAL("%s", ss.str().c_str()); -} -} // namespace - -namespace firebolt::rialto::server -{ -void enableGstLogForwarding() -{ - gst_debug_remove_log_function(gst_debug_log_default); - gst_debug_add_log_function(gstreamerLogFunction, nullptr, nullptr); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadata.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadata.cpp deleted file mode 100644 index bae8af817..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadata.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GstProtectionMetadata.h" -#include "RialtoServerLogging.h" -#include -#include - -static gboolean rialto_eme_protection_metadata_init(GstMeta *meta, gpointer params, // NOLINT(build/function_format) - GstBuffer *buffer) -{ - GstRialtoProtectionMetadata *emeta = reinterpret_cast(meta); - const GstRialtoProtectionData *data = static_cast(params); - emeta->data = *data; - - if (emeta->data.decryptionService) - { - emeta->data.decryptionService->incrementSessionIdUsageCounter(emeta->data.keySessionId); - } - - return true; -} - -static gboolean rialto_eme_protection_metadata_free(GstMeta *meta, GstBuffer *buffer) // NOLINT(build/function_format) -{ - GstRialtoProtectionMetadata *protectionMeta = reinterpret_cast(meta); - - if (protectionMeta->data.decryptionService) - { - protectionMeta->data.decryptionService->decrementSessionIdUsageCounter(protectionMeta->data.keySessionId); - } - - if (protectionMeta->data.subsamples) - { - gst_buffer_unref(protectionMeta->data.subsamples); - } - if (protectionMeta->data.iv) - { - gst_buffer_unref(protectionMeta->data.iv); - } - if (protectionMeta->data.key) - { - gst_buffer_unref(protectionMeta->data.key); - } - - return true; -} - -GST_EXPORT GType rialto_eme_protection_metadata_get_type() // NOLINT(build/function_format) -{ - static GType g_type; - static const gchar *api_tags[] = {"rialto", "protection", NULL}; - - if (g_once_init_enter(&g_type)) - { - GType _type = gst_meta_api_type_register("GstRialtoProtectionMetadataAPI", api_tags); - g_once_init_leave(&g_type, _type); - } - return g_type; -} - -const GstMetaInfo *rialto_mse_protection_metadata_get_info() // NOLINT(build/function_format) -{ - static const GstMetaInfo *kMetainfo = NULL; - if (g_once_init_enter(&kMetainfo)) - { - const GstMetaInfo *kGstMeta = - gst_meta_register(GST_RIALTO_PROTECTION_METADATA_GET_TYPE, "GstRialtoProtectionMetadata", - sizeof(GstRialtoProtectionMetadata), - (GstMetaInitFunction)rialto_eme_protection_metadata_init, - (GstMetaFreeFunction)rialto_eme_protection_metadata_free, (GstMetaTransformFunction)NULL); - - g_once_init_leave(&kMetainfo, kGstMeta); - } - return kMetainfo; -} diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadataHelper.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadataHelper.cpp deleted file mode 100644 index b813cb429..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstProtectionMetadataHelper.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GstProtectionMetadataHelper.h" -#include "GstProtectionMetadataHelperFactory.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server -{ -std::shared_ptr IGstProtectionMetadataHelperFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the protection metadata wrapper factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr GstProtectionMetadataHelperFactory::createProtectionMetadataWrapper( - const std::shared_ptr &gstWrapper) const -{ - return std::make_unique(gstWrapper); -} - -GstMeta *GstProtectionMetadataHelper::addProtectionMetadata(GstBuffer *gstBuffer, GstRialtoProtectionData &data) -{ - return m_gstWrapper->gstBufferAddMeta(gstBuffer, GST_RIALTO_PROTECTION_METADATA_INFO, &data); -} - -GstRialtoProtectionData *GstProtectionMetadataHelper::getProtectionMetadataData(GstBuffer *gstBuffer) -{ - GstMeta *meta = m_gstWrapper->gstBufferGetMeta(gstBuffer, GST_RIALTO_PROTECTION_METADATA_GET_TYPE); - if (!meta) - { - return nullptr; - } - - GstRialtoProtectionMetadata *protectionMetadata = reinterpret_cast(meta); - return &protectionMetadata->data; -} - -void GstProtectionMetadataHelper::removeProtectionMetadata(GstBuffer *gstBuffer) -{ - GstMeta *meta = m_gstWrapper->gstBufferGetMeta(gstBuffer, GST_RIALTO_PROTECTION_METADATA_GET_TYPE); - if (meta) - { - if (!m_gstWrapper->gstBufferRemoveMeta(gstBuffer, meta)) - { - RIALTO_SERVER_LOG_ERROR("Failed to remove metadata"); - } - } -} - -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstSrc.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstSrc.cpp deleted file mode 100644 index 83e7be57b..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstSrc.cpp +++ /dev/null @@ -1,531 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "GstSrc.h" -#include "GstTextTrackSinkFactory.h" -#include "RialtoServerLogging.h" -#include - -static void gstRialtoSrcUriHandlerInit(gpointer gIface, gpointer ifaceData); - -static GstStaticPadTemplate rialto_src_template = - GST_STATIC_PAD_TEMPLATE("src_%u", GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS_ANY); - -GST_DEBUG_CATEGORY(rialto_gst_player_debug); -#define GST_CAT_DEFAULT rialto_gst_player_debug -#define gst_rialto_src_parent_class parent_class -#define RIALTO_SRC_CATEGORY_INIT \ - GST_DEBUG_CATEGORY_INIT(rialto_gst_player_debug, "rialtosrc", 0, "Rialto source element"); -G_DEFINE_TYPE_WITH_CODE(GstRialtoSrc, gst_rialto_src, GST_TYPE_BIN, - G_ADD_PRIVATE(GstRialtoSrc) - G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gstRialtoSrcUriHandlerInit) - RIALTO_SRC_CATEGORY_INIT) - -static void gstRialtoSrcDispose(GObject *object) -{ - GST_CALL_PARENT(G_OBJECT_CLASS, dispose, (object)); -} - -static void gstRialtoSrcFinalize(GObject *object) -{ - GstRialtoSrc *src = GST_RIALTO_SRC(object); - GstRialtoSrcPrivate *priv = src->priv; - g_free(priv->uri); - priv->~GstRialtoSrcPrivate(); - GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); -} - -static void gstRialtoSrcSetProperty(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) -{ - GST_CALL_PARENT(G_OBJECT_CLASS, set_property, (object, prop_id, value, pspec)); -} - -static void gstRialtoSrcGetProperty(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) -{ - GST_CALL_PARENT(G_OBJECT_CLASS, get_property, (object, prop_id, value, pspec)); -} - -static GstURIType gstRialtoSrcUriGetType(GType) -{ - return GST_URI_SRC; -} - -const gchar *const *gstRialtoSrcGetProtocols(GType) -{ - static const char *protocols[] = {"rialto", 0}; - return protocols; -} - -static gchar *gstRialtoSrcGetUri(GstURIHandler *handler) -{ - GstRialtoSrc *src = GST_RIALTO_SRC(handler); - gchar *ret; - GST_OBJECT_LOCK(src); - ret = g_strdup(src->priv->uri); - GST_OBJECT_UNLOCK(src); - return ret; -} - -static gboolean gstRialtoSrcSetUri(GstURIHandler *handler, const gchar *uri, GError **error) -{ - GstRialtoSrc *src = GST_RIALTO_SRC(handler); - GstRialtoSrcPrivate *priv = src->priv; - if (GST_STATE(src) >= GST_STATE_PAUSED) - { - GST_ERROR_OBJECT(src, "URI can only be set in states < PAUSED"); - return FALSE; - } - GST_OBJECT_LOCK(src); - g_free(priv->uri); - priv->uri = 0; - if (!uri) - { - GST_OBJECT_UNLOCK(src); - return TRUE; - } - priv->uri = g_strdup(uri); - GST_OBJECT_UNLOCK(src); - return TRUE; -} - -static void gstRialtoSrcUriHandlerInit(gpointer gIface, gpointer) -{ - GstURIHandlerInterface *iface = reinterpret_cast(gIface); - iface->get_type = gstRialtoSrcUriGetType; - iface->get_protocols = gstRialtoSrcGetProtocols; - iface->get_uri = gstRialtoSrcGetUri; - iface->set_uri = gstRialtoSrcSetUri; -} - -static gboolean gstRialtoSrcQueryWithParent(GstPad *pad, GstObject *parent, GstQuery *query) -{ - gboolean result = FALSE; - switch (GST_QUERY_TYPE(query)) - { - default: - { - GstPad *target = gst_ghost_pad_get_target(GST_GHOST_PAD_CAST(pad)); - // Forward the query to the proxy target pad. - if (target) - result = gst_pad_query(target, query); - gst_object_unref(target); - break; - } - } - return result; -} - -void gstRialtoSrcHandleMessage(GstBin *bin, GstMessage *message) -{ - GstRialtoSrc *src = GST_RIALTO_SRC(GST_ELEMENT(bin)); - switch (GST_MESSAGE_TYPE(message)) - { - case GST_MESSAGE_EOS: - { - gboolean emit_eos = TRUE; - GstPad *pad = gst_element_get_static_pad(GST_ELEMENT(GST_MESSAGE_SRC(message)), "src"); - GST_DEBUG_OBJECT(src, "EOS received from %s", GST_MESSAGE_SRC_NAME(message)); - g_object_set_data(G_OBJECT(pad), "is-eos", GINT_TO_POINTER(1)); - gst_object_unref(pad); - for (guint i = 0; i < src->priv->appsrc_count; i++) - { - gchar *name = g_strdup_printf("src_%u", i); - GstPad *src_pad = gst_element_get_static_pad(GST_ELEMENT(src), name); - GstPad *target = gst_ghost_pad_get_target(GST_GHOST_PAD_CAST(src_pad)); - gint is_eos = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(target), "is-eos")); - gst_object_unref(target); - gst_object_unref(src_pad); - g_free(name); - if (!is_eos) - { - emit_eos = FALSE; - break; - } - } - gst_message_unref(message); - if (emit_eos) - { - GST_DEBUG_OBJECT(src, "All appsrc elements are EOS, emitting event now."); - gst_element_send_event(GST_ELEMENT(bin), gst_event_new_eos()); - } - break; - } - default: - GST_BIN_CLASS(parent_class)->handle_message(bin, message); - break; - } -} - -static void gstRialtoSrcDoAsyncStart(GstRialtoSrc *rialtoSrc) -{ - GstRialtoSrcPrivate *privateData = rialtoSrc->priv; - if (privateData->async_done) - { - GST_DEBUG_OBJECT(rialtoSrc, "Rialto src already done"); - return; - } - - GstMessage *message = gst_message_new_async_start(GST_OBJECT(rialtoSrc)); - GstBin *bin = GST_BIN(rialtoSrc); - - privateData->async_start = TRUE; - GST_BIN_CLASS(parent_class)->handle_message(bin, message); -} - -static void gstRialtoSrcDoAsyncDone(GstRialtoSrc *rialtoSrc) -{ - GstRialtoSrcPrivate *privateData = rialtoSrc->priv; - if (!privateData->async_start) - { - GST_DEBUG_OBJECT(rialtoSrc, "Rialto src not started"); - return; - } - - GstMessage *message = gst_message_new_async_done(GST_OBJECT(rialtoSrc), GST_CLOCK_TIME_NONE); - GstBin *bin = GST_BIN(rialtoSrc); - - GST_BIN_CLASS(parent_class)->handle_message(bin, message); - - privateData->async_done = TRUE; - privateData->async_start = FALSE; -} - -static GstStateChangeReturn gstRialtoSrcChangeState(GstElement *element, GstStateChange transition) -{ - GstRialtoSrc *rialtoSrc = GST_RIALTO_SRC(element); - GstRialtoSrcPrivate *privateData = rialtoSrc->priv; - GstStateChangeReturn status = GST_STATE_CHANGE_SUCCESS; - - if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) - { - gstRialtoSrcDoAsyncStart(rialtoSrc); - } - - status = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); - if (G_UNLIKELY(status == GST_STATE_CHANGE_FAILURE)) - { - gstRialtoSrcDoAsyncDone(rialtoSrc); - return status; - } - - switch (transition) - { - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - if (!privateData->async_done) - status = GST_STATE_CHANGE_ASYNC; - break; - } - case GST_STATE_CHANGE_PAUSED_TO_READY: - { - gstRialtoSrcDoAsyncDone(rialtoSrc); - break; - } - default: - break; - } - - return status; -} - -static void gst_rialto_src_init(GstRialtoSrc *src) // NOLINT(build/function_format) -{ - GstRialtoSrcPrivate *priv = reinterpret_cast(gst_rialto_src_get_instance_private(src)); - src->priv = priv; - src->priv->appsrc_count = 0; - src->priv->async_start = FALSE; - src->priv->async_done = FALSE; - g_object_set(GST_BIN(src), "message-forward", TRUE, nullptr); -} - -static void gst_rialto_src_class_init(GstRialtoSrcClass *klass) // NOLINT(build/function_format) -{ - GObjectClass *oklass = G_OBJECT_CLASS(klass); - GstElementClass *eklass = GST_ELEMENT_CLASS(klass); - GstBinClass *bklass = GST_BIN_CLASS(klass); - oklass->dispose = gstRialtoSrcDispose; - oklass->finalize = gstRialtoSrcFinalize; - oklass->set_property = gstRialtoSrcSetProperty; - oklass->get_property = gstRialtoSrcGetProperty; - GstPadTemplate *templ = gst_static_pad_template_get(&rialto_src_template); - gst_element_class_add_pad_template(eklass, templ); - gst_element_class_set_metadata(eklass, "Rialto source element", "Source", - "Handles data incoming from the Rialto player", "POC "); - g_object_class_install_property(oklass, PROP_LOCATION, - g_param_spec_string("location", "location", "Location to read from", 0, - (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - bklass->handle_message = GST_DEBUG_FUNCPTR(gstRialtoSrcHandleMessage); - eklass->change_state = GST_DEBUG_FUNCPTR(gstRialtoSrcChangeState); -} - -namespace firebolt::rialto::server -{ -std::weak_ptr GstSrcFactory::m_factory; -std::weak_ptr GstSrcFactory::m_gstSrc; -std::mutex GstSrcFactory::m_creationMutex; - -std::shared_ptr IGstSrcFactory::getFactory() -{ - std::shared_ptr factory = GstSrcFactory::m_factory.lock(); - - if (!factory) - { - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer src factory, reason: %s", e.what()); - } - - GstSrcFactory::m_factory = factory; - } - - return factory; -} - -std::shared_ptr GstSrcFactory::getGstSrc() -{ - std::lock_guard lock{m_creationMutex}; - - std::shared_ptr gstSrc = GstSrcFactory::m_gstSrc.lock(); - - if (!gstSrc) - { - try - { - gstSrc = std::make_shared(firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(), - firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(), - IGstDecryptorElementFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer src, reason: %s", e.what()); - } - - GstSrcFactory::m_gstSrc = gstSrc; - } - - return gstSrc; -} - -GstSrc::GstSrc(const std::shared_ptr &gstWrapperFactory, - const std::shared_ptr &glibWrapperFactory, - const std::shared_ptr &decryptorFactory) - : m_decryptorFactory(decryptorFactory) -{ - if ((!gstWrapperFactory) || (!(m_gstWrapper = gstWrapperFactory->getGstWrapper()))) - { - throw std::runtime_error("Cannot create GstWrapper"); - } - if ((!glibWrapperFactory) || (!(m_glibWrapper = glibWrapperFactory->getGlibWrapper()))) - { - throw std::runtime_error("Cannot create GlibWrapper"); - } - if (!m_decryptorFactory) - { - throw std::runtime_error("No decryptor factory provided"); - } -} - -void GstSrc::initSrc() -{ - GstElementFactory *src_factory = m_gstWrapper->gstElementFactoryFind("rialtosrc"); - if (!src_factory) - { - m_gstWrapper->gstElementRegister(0, "rialtosrc", GST_RANK_PRIMARY + 100, GST_RIALTO_TYPE_SRC); - } - else - { - m_gstWrapper->gstObjectUnref(src_factory); - src_factory = nullptr; - } -} - -void GstSrc::setDefaultStreamFormatIfNeeded(GstElement *appSrc) -{ - GstCaps *currentCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(appSrc)); - if (currentCaps) - { - GstStructure *structure = m_gstWrapper->gstCapsGetStructure(currentCaps, 0); - if (structure && (m_gstWrapper->gstStructureHasName(structure, "video/x-h264") || - m_gstWrapper->gstStructureHasName(structure, "video/x-h265"))) - { - bool hasStreamFormat = m_gstWrapper->gstStructureHasField(structure, "stream-format"); - bool hasCodecData = m_gstWrapper->gstStructureHasField(structure, "codec_data"); - - if (!hasStreamFormat && !hasCodecData) - { - GstCaps *newCaps = m_gstWrapper->gstCapsCopy(currentCaps); - if (newCaps) - { - m_gstWrapper->gstCapsSetSimple(newCaps, "stream-format", G_TYPE_STRING, "byte-stream", nullptr); - m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(appSrc), newCaps); - GST_INFO("Added stream-format=byte-stream to caps %" GST_PTR_FORMAT, newCaps); - m_gstWrapper->gstCapsUnref(newCaps); - } - } - } - } - m_gstWrapper->gstCapsUnref(currentCaps); -} - -void GstSrc::setupAndAddAppSrc(IDecryptionService *decryptionService, GstElement *source, StreamInfo &streamInfo, - GstAppSrcCallbacks *callbacks, gpointer userData, firebolt::rialto::MediaSourceType type) -{ - // Configure and add appsrc - m_glibWrapper->gObjectSet(streamInfo.appSrc, "block", FALSE, "format", GST_FORMAT_TIME, "stream-type", - GST_APP_STREAM_TYPE_STREAM, "min-percent", 20, "handle-segment-change", TRUE, nullptr); - m_gstWrapper->gstAppSrcSetCallbacks(GST_APP_SRC(streamInfo.appSrc), callbacks, userData, nullptr); - - const std::unordered_map queueSize = - {{firebolt::rialto::MediaSourceType::VIDEO, 8 * 1024 * 1024}, - {firebolt::rialto::MediaSourceType::AUDIO, 512 * 1024}, - {firebolt::rialto::MediaSourceType::SUBTITLE, 256 * 1024}}; - - auto sizeIt = queueSize.find(type); - if (sizeIt != queueSize.end()) - { - m_gstWrapper->gstAppSrcSetMaxBytes(GST_APP_SRC(streamInfo.appSrc), sizeIt->second); - } - else - { - GST_WARNING_OBJECT(source, "Could not find max-bytes value for appsrc"); - } - - m_gstWrapper->gstAppSrcSetStreamType(GST_APP_SRC(streamInfo.appSrc), GST_APP_STREAM_TYPE_SEEKABLE); - - GstRialtoSrc *src = GST_RIALTO_SRC(source); - guint id = src->priv->appsrc_count; - src->priv->appsrc_count++; - gchar *name = m_glibWrapper->gStrdupPrintf("src_%u", id); - m_gstWrapper->gstBinAdd(GST_BIN(source), streamInfo.appSrc); - - GstElement *src_elem = streamInfo.appSrc; - - // Configure and add decryptor - if (streamInfo.hasDrm) - { - gchar *decryptorName = - m_glibWrapper->gStrdupPrintf("rialtodecryptor%s_%u", - (type == firebolt::rialto::MediaSourceType::VIDEO) ? "video" : "audio", id); - GstElement *decryptor = - m_decryptorFactory->createDecryptorElement(decryptorName, decryptionService, m_gstWrapper); - m_glibWrapper->gFree(decryptorName); - if (decryptor) - { - GST_DEBUG_OBJECT(src, "Injecting decryptor element %" GST_PTR_FORMAT, decryptor); - - m_gstWrapper->gstBinAdd(GST_BIN(source), decryptor); - m_gstWrapper->gstElementSyncStateWithParent(decryptor); - m_gstWrapper->gstElementLink(src_elem, decryptor); - src_elem = decryptor; - } - else - { - GST_WARNING_OBJECT(src, "Could not create decryptor element"); - } - - if (type == firebolt::rialto::MediaSourceType::VIDEO) - { - // Configure and add payloader - GstElement *payloader = createPayloader(); - if (payloader) - { - /* - h264secparse and h265secparse have problems with parsing blank caps (with no stream-format nor - codec_data defined). This is a workaround to set the stream-format to byte-stream if needed. - */ - setDefaultStreamFormatIfNeeded(streamInfo.appSrc); - - if (GST_IS_BASE_TRANSFORM(payloader)) - { - m_gstWrapper->gstBaseTransformSetInPlace(GST_BASE_TRANSFORM(payloader), TRUE); - } - m_gstWrapper->gstBinAdd(GST_BIN(source), payloader); - m_gstWrapper->gstElementSyncStateWithParent(payloader); - m_gstWrapper->gstElementLink(src_elem, payloader); - src_elem = payloader; - } - else - { - GST_WARNING_OBJECT(src, "Could not create payloader element"); - } - } - } - - // Configure and add buffer queue - GstElement *queue = m_gstWrapper->gstElementFactoryMake("queue", nullptr); - if (queue) - { - m_glibWrapper->gObjectSet(G_OBJECT(queue), "max-size-buffers", 10, "max-size-bytes", 0, "max-size-time", - (gint64)0, "silent", TRUE, nullptr); - m_gstWrapper->gstBinAdd(GST_BIN(source), queue); - m_gstWrapper->gstElementSyncStateWithParent(queue); - m_gstWrapper->gstElementLink(src_elem, queue); - src_elem = queue; - } - else - { - GST_WARNING_OBJECT(src, "Could not create buffer queue element"); - } - - // Setup pad - GstPad *target = m_gstWrapper->gstElementGetStaticPad(src_elem, "src"); - GstPad *pad = m_gstWrapper->gstGhostPadNew(name, target); - m_gstWrapper->gstPadSetQueryFunction(pad, gstRialtoSrcQueryWithParent); - m_gstWrapper->gstPadSetActive(pad, TRUE); - - m_gstWrapper->gstElementAddPad(source, pad); - GST_OBJECT_FLAG_SET(pad, GST_PAD_FLAG_NEED_PARENT); - - m_gstWrapper->gstElementSyncStateWithParent(streamInfo.appSrc); - - m_glibWrapper->gFree(name); - m_gstWrapper->gstObjectUnref(target); -} - -void GstSrc::allAppSrcsAdded(GstElement *element) -{ - GstRialtoSrc *src = GST_RIALTO_SRC(element); - m_gstWrapper->gstElementNoMorePads(element); - gstRialtoSrcDoAsyncDone(src); -} - -GstElement *GstSrc::createPayloader() -{ - static GstElementFactory *factory = nullptr; - static gsize init = 0; - if (m_glibWrapper->gOnceInitEnter(&init)) - { - factory = m_gstWrapper->gstElementFactoryFind("svppay"); - m_glibWrapper->gOnceInitLeave(&init, 1); - } - if (!factory) - { - GST_WARNING("svppay not found"); - return nullptr; - } - return m_gstWrapper->gstElementFactoryCreate(factory, nullptr); -} - -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstTextTrackSink.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstTextTrackSink.cpp deleted file mode 100644 index a0308e8b3..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstTextTrackSink.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GstProtectionMetadataHelperFactory.h" -#include "GstRialtoTextTrackSinkPrivate.h" -#include "GstTextTrackSinkFactory.h" -#include "RialtoServerLogging.h" -#include -#include -#include -#include -#include -#include -G_BEGIN_DECLS - -enum -{ - PROP_0, - PROP_MUTE, - PROP_TEXT_TRACK_IDENTIFIER, - PROP_VIDEO_DECODER, - PROP_POSITION, - PROP_OFFSET, - PROP_LAST -}; - -#define GST_RIALTO_TEXT_TRACK_SINK_TYPE (gst_rialto_text_track_sink_get_type()) -#define GST_RIALTO_TEXT_TRACK_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_RIALTO_TEXT_TRACK_SINK_TYPE, GstRialtoTextTrackSink)) -#define GST_RIALTO_TEXT_TRACK_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), GST_RIALTO_TEXT_TRACK_SINK_TYPE, GstRialtoTextTrackSinkClass)) - -typedef struct _GstRialtoTextTrackSink GstRialtoTextTrackSink; -typedef struct _GstRialtoTextTrackSinkClass GstRialtoTextTrackSinkClass; -typedef struct firebolt::rialto::server::GstRialtoTextTrackSinkPrivate GstRialtoTextTrackSinkPrivate; - -GType gst_rialto_text_track_sink_get_type(void); // NOLINT(build/function_format) - -struct _GstRialtoTextTrackSink -{ - GstBaseSink parent; - GstRialtoTextTrackSinkPrivate *priv; -}; - -struct _GstRialtoTextTrackSinkClass -{ - GstBaseSink parentClass; -}; - -G_END_DECLS - -static GstStaticPadTemplate sinkTemplate = - GST_STATIC_PAD_TEMPLATE("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS("application/ttml+xml; text/vtt; application/x-subtitle-vtt; text/x-raw; " - "subtitle/x-subtitle-cc")); - -GST_DEBUG_CATEGORY(gst_rialto_text_track_sink_debug_category); -#define GST_CAT_DEFAULT gst_rialto_text_track_sink_debug_category - -#define gst_rialto_text_track_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_PRIVATE(GstRialtoTextTrackSink, gst_rialto_text_track_sink, GST_TYPE_BASE_SINK); - -static void gst_rialto_text_track_sink_finalize(GObject *object); // NOLINT(build/function_format) -static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, // NOLINT(build/function_format) - GstBuffer *buffer); -static gboolean gst_rialto_text_track_sink_set_caps(GstBaseSink *sink, GstCaps *caps); // NOLINT(build/function_format) -static gboolean gst_rialto_text_track_sink_start(GstBaseSink *sink); // NOLINT(build/function_format) -static gboolean gst_rialto_text_track_sink_stop(GstBaseSink *sink); // NOLINT(build/function_format) -static gboolean gst_rialto_text_track_sink_event(GstBaseSink *sink, GstEvent *event); // NOLINT(build/function_format) -static GstStateChangeReturn -gst_rialto_text_track_sink_change_state(GstElement *element, GstStateChange transition); // NOLINT(build/function_format) -static void gst_rialto_text_track_sink_get_property(GObject *object, guint propId, // NOLINT(build/function_format) - GValue *value, GParamSpec *pspec); -static void gst_rialto_text_track_sink_set_property(GObject *object, guint propId, // NOLINT(build/function_format) - const GValue *value, GParamSpec *pspec); -static gboolean gst_rialto_text_track_sink_query(GstElement *element, GstQuery *query); // NOLINT(build/function_format) - -static void gst_rialto_text_track_sink_class_init(GstRialtoTextTrackSinkClass *klass) // NOLINT(build/function_format) -{ - GST_DEBUG_CATEGORY_INIT(gst_rialto_text_track_sink_debug_category, "rialto_text_track_sink", 0, - "TextTrack Sink for Rialto"); - - GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); - GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); - GstBaseSinkClass *baseSinkClass = GST_BASE_SINK_CLASS(klass); - - gobjectClass->finalize = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_finalize); - gobjectClass->get_property = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_get_property); - gobjectClass->set_property = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_set_property); - baseSinkClass->start = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_start); - baseSinkClass->stop = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_stop); - baseSinkClass->render = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_render); - baseSinkClass->set_caps = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_set_caps); - baseSinkClass->event = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_event); - elementClass->change_state = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_change_state); - elementClass->query = GST_DEBUG_FUNCPTR(gst_rialto_text_track_sink_query); - - g_object_class_install_property(gobjectClass, PROP_MUTE, - g_param_spec_boolean("mute", "Mute", "Mute subtitles", FALSE, G_PARAM_READWRITE)); - - g_object_class_install_property(gobjectClass, PROP_TEXT_TRACK_IDENTIFIER, - g_param_spec_string("text-track-identifier", "Text Track Identifier", - "Identifier of text track", nullptr, - GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_VIDEO_DECODER, - g_param_spec_uint64("video-decoder", "Video Decoder", "Video Decoder", 0, - G_MAXUINT64, 0, GParamFlags(G_PARAM_WRITABLE))); - - g_object_class_install_property(gobjectClass, PROP_POSITION, - g_param_spec_uint64("position", "Position", "Position", 0, G_MAXUINT64, 0, - GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_OFFSET, - g_param_spec_uint64("offset", "Offset", "Offset", 0, G_MAXUINT64, 0, - GParamFlags(G_PARAM_WRITABLE))); - - gst_element_class_add_pad_template(elementClass, gst_static_pad_template_get(&sinkTemplate)); - gst_element_class_set_static_metadata(elementClass, "Rialto TextTrack Sink", "Sink/Parser/Subtitle", - "Rialto TextTrack Sink", "SKY"); -} - -static void gst_rialto_text_track_sink_init(GstRialtoTextTrackSink *self) // NOLINT(build/function_format) -{ - GstRialtoTextTrackSinkPrivate *priv = - reinterpret_cast(gst_rialto_text_track_sink_get_instance_private(self)); - - self->priv = new (priv) GstRialtoTextTrackSinkPrivate(); - - gst_base_sink_set_async_enabled(GST_BASE_SINK(self), FALSE); -} - -static void gst_rialto_text_track_sink_finalize(GObject *object) // NOLINT(build/function_format) -{ - GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(object); - GstRialtoTextTrackSinkPrivate *priv = - reinterpret_cast(gst_rialto_text_track_sink_get_instance_private(self)); - - priv->~GstRialtoTextTrackSinkPrivate(); - - GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); -} - -static gboolean gst_rialto_text_track_sink_start(GstBaseSink *sink) // NOLINT(build/function_format) -{ - const char *wayland_display = std::getenv("WAYLAND_DISPLAY"); - if (!wayland_display) - { - GST_ERROR_OBJECT(sink, "Failed to get WAYLAND_DISPLAY env variable"); - return false; - } - - std::string display{wayland_display}; - GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink); - try - { - self->priv->m_textTrackSession = - firebolt::rialto::server::ITextTrackSessionFactory::getFactory().createTextTrackSession(display); - } - catch (const std::exception &e) - { - GST_ERROR_OBJECT(sink, "Failed to create TextTrackSession. Reason '%s'", e.what()); - return false; - } - - GST_INFO_OBJECT(sink, "Successfully started TextTrack sink"); - return true; -} - -static gboolean gst_rialto_text_track_sink_stop(GstBaseSink *sink) // NOLINT(build/function_format) -{ - GstRialtoTextTrackSink *self = GST_RIALTO_TEXT_TRACK_SINK(sink); - self->priv->m_textTrackSession.reset(); - - GST_INFO_OBJECT(sink, "Successfully stopped TextTrack sink"); - return true; -} - -static GstFlowReturn gst_rialto_text_track_sink_render(GstBaseSink *sink, GstBuffer *buffer) // NOLINT(build/function_format) -{ - GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink); - - GstMapInfo info; - if (gst_buffer_map(buffer, &info, GST_MAP_READ)) - { - std::string data(reinterpret_cast(info.data), info.size); - int64_t displayOffset{0}; - if (GST_BUFFER_OFFSET_NONE != GST_BUFFER_OFFSET(buffer)) - { - displayOffset = static_cast(GST_BUFFER_OFFSET(buffer)); - } - textTrackSink->priv->m_textTrackSession->sendData(data, 0 - displayOffset); - - gst_buffer_unmap(buffer, &info); - } - else - { - GST_ERROR_OBJECT(textTrackSink, "Failed to map buffer"); - return GST_FLOW_ERROR; - } - - return GST_FLOW_OK; -} - -static gboolean gst_rialto_text_track_sink_set_position(GstRialtoTextTrackSink *textTrackSink) // NOLINT(build/function_format) -{ - if (!textTrackSink->priv->m_textTrackSession) - { - GST_ERROR_OBJECT(textTrackSink, "Session is NULL"); - return FALSE; - } - - uint64_t positionWithOffset = textTrackSink->priv->m_position.value_or(0) + textTrackSink->priv->m_offset.value_or(0); - - GST_DEBUG_OBJECT(textTrackSink, - "Setting position to %" GST_TIME_FORMAT " (pts %" GST_TIME_FORMAT ", offset %" GST_TIME_FORMAT ")", - GST_TIME_ARGS(positionWithOffset), GST_TIME_ARGS(textTrackSink->priv->m_position.value_or(0)), - GST_TIME_ARGS(textTrackSink->priv->m_offset.value_or(0))); - - textTrackSink->priv->m_textTrackSession->setPosition(positionWithOffset / GST_MSECOND); - return TRUE; -} - -static gboolean gst_rialto_text_track_sink_set_caps(GstBaseSink *sink, GstCaps *caps) // NOLINT(build/function_format) -{ - GST_INFO_OBJECT(sink, "Setting caps %" GST_PTR_FORMAT, caps); - GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink); - - GstStructure *structure = gst_caps_get_structure(caps, 0); - const gchar *mimeName = gst_structure_get_name(structure); - - if (g_str_has_prefix(mimeName, "text/vtt") || g_str_has_prefix(mimeName, "application/x-subtitle-vtt")) - { - GST_INFO_OBJECT(sink, "Setting session to WebVTT"); - textTrackSink->priv->m_textTrackSession->setSessionWebVTTSelection(); - } - else if (g_str_has_prefix(mimeName, "application/ttml+xml")) - { - GST_INFO_OBJECT(sink, "Setting session to TTML"); - textTrackSink->priv->m_textTrackSession->setSessionTTMLSelection(); - } - else if (g_str_has_prefix(mimeName, "subtitle/x-subtitle-cc")) - { - GST_INFO_OBJECT(sink, "Setting session to CC"); - std::string identifier = "CC1"; - if (textTrackSink->priv->m_textTrackIdentifier.empty()) - { - GST_WARNING_OBJECT(sink, "No text track identifier set, defaulting to %s", identifier.c_str()); - } - else - { - identifier = textTrackSink->priv->m_textTrackIdentifier; - } - textTrackSink->priv->m_textTrackSession->setSessionCCSelection(identifier); - - if (textTrackSink->priv->m_videoDecoderIdentifier) - { - textTrackSink->priv->m_textTrackSession->associateVideoDecoder(textTrackSink->priv->m_videoDecoderIdentifier); - } - } - else - { - GST_ERROR_OBJECT(sink, "Invalid mime name '%s'", mimeName); - return FALSE; - } - - textTrackSink->priv->m_textTrackSession->mute(textTrackSink->priv->m_isMuted); - - std::unique_lock lock{textTrackSink->priv->m_mutex}; - textTrackSink->priv->m_capsSet = true; - bool wasAnyQueued = textTrackSink->priv->m_queuedPosition.has_value() || - textTrackSink->priv->m_queuedOffset.has_value(); - if (textTrackSink->priv->m_queuedPosition.has_value()) - { - textTrackSink->priv->m_position = textTrackSink->priv->m_queuedPosition; - textTrackSink->priv->m_queuedPosition.reset(); - } - if (textTrackSink->priv->m_queuedOffset.has_value()) - { - textTrackSink->priv->m_offset = textTrackSink->priv->m_queuedOffset; - textTrackSink->priv->m_queuedOffset.reset(); - } - if (wasAnyQueued) - { - gst_rialto_text_track_sink_set_position(textTrackSink); - } - - return TRUE; -} - -static gboolean gst_rialto_text_track_sink_event(GstBaseSink *sink, GstEvent *event) // NOLINT(build/function_format) -{ - GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(sink); - GST_DEBUG_OBJECT(textTrackSink, "handling event %" GST_PTR_FORMAT, event); - - switch (GST_EVENT_TYPE(event)) - { - case GST_EVENT_FLUSH_START: - { - if (!textTrackSink->priv->m_textTrackSession->resetSession(textTrackSink->priv->m_isMuted)) - { - GST_ERROR_OBJECT(textTrackSink, "Failed to reset TextTrack session"); - } - break; - } - case GST_EVENT_FLUSH_STOP: - { - break; - } - case GST_EVENT_CUSTOM_DOWNSTREAM: - case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: - { - if (gst_event_has_name(event, "current-pts")) - { - uint64_t pts = 0; - const GstStructure *structure = gst_event_get_structure(event); - if (structure) - { - if (gst_structure_get_uint64(structure, "pts", &pts)) - { - if (pts == GST_CLOCK_TIME_NONE) - { - GST_ERROR_OBJECT(textTrackSink, "Invalid PTS value"); - return FALSE; - } - - std::unique_lock lock{textTrackSink->priv->m_mutex}; - textTrackSink->priv->m_position = pts; - - gst_rialto_text_track_sink_set_position(textTrackSink); - } - else - { - GST_ERROR_OBJECT(textTrackSink, "Failed to get PTS from structure"); - return FALSE; - } - } - else - { - GST_ERROR_OBJECT(textTrackSink, "Failed to get structure from event"); - return FALSE; - } - } - break; - } - default: - { - break; - } - } - - return GST_BASE_SINK_CLASS(parent_class)->event(sink, event); -} - -static GstStateChangeReturn -gst_rialto_text_track_sink_change_state(GstElement *element, GstStateChange transition) // NOLINT(build/function_format) -{ - GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(element); - - GstState current_state = GST_STATE_TRANSITION_CURRENT(transition); - GstState next_state = GST_STATE_TRANSITION_NEXT(transition); - GST_INFO_OBJECT(textTrackSink, "State change: (%s) -> (%s)", gst_element_state_get_name(current_state), - gst_element_state_get_name(next_state)); - - switch (transition) - { - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - { - if (!textTrackSink->priv->m_textTrackSession->play()) - { - GST_ERROR_OBJECT(textTrackSink, "Failed to play textTrack session"); - return GST_STATE_CHANGE_FAILURE; - } - break; - } - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - { - if (!textTrackSink->priv->m_textTrackSession->pause()) - { - GST_ERROR_OBJECT(textTrackSink, "Failed to pause textTrack session"); - return GST_STATE_CHANGE_FAILURE; - } - - break; - } - default: - break; - } - - GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); - if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) - { - GST_WARNING_OBJECT(textTrackSink, "State change failed"); - return result; - } - - return GST_STATE_CHANGE_SUCCESS; -} - -static void gst_rialto_text_track_sink_get_property(GObject *object, guint propId, // NOLINT(build/function_format) - GValue *value, GParamSpec *pspec) -{ - GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(object); - if (!textTrackSink) - { - GST_ERROR_OBJECT(textTrackSink, "Sink not initalised"); - return; - } - GstRialtoTextTrackSinkPrivate *priv = textTrackSink->priv; - - switch (propId) - { - case PROP_MUTE: - { - g_value_set_boolean(value, priv->m_isMuted.load()); - break; - } - case PROP_TEXT_TRACK_IDENTIFIER: - { - g_value_set_string(value, priv->m_textTrackIdentifier.c_str()); - break; - } - case PROP_POSITION: - { - // Thunder ITextTrack does not provide getPosition API so we are unable to determine current position - g_value_set_uint64(value, GST_CLOCK_TIME_NONE); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } -} - -static void gst_rialto_text_track_sink_set_property(GObject *object, guint propId, // NOLINT(build/function_format) - const GValue *value, GParamSpec *pspec) -{ - GstRialtoTextTrackSink *textTrackSink = GST_RIALTO_TEXT_TRACK_SINK(object); - if (!textTrackSink) - { - GST_ERROR_OBJECT(textTrackSink, "Sink not initalised"); - return; - } - GstRialtoTextTrackSinkPrivate *priv = textTrackSink->priv; - - switch (propId) - { - case PROP_MUTE: - { - priv->m_isMuted = g_value_get_boolean(value); - if (priv->m_textTrackSession) - { - priv->m_textTrackSession->mute(priv->m_isMuted); - } - break; - } - case PROP_TEXT_TRACK_IDENTIFIER: - { - priv->m_textTrackIdentifier = g_value_get_string(value); - if (priv->m_textTrackSession && priv->m_textTrackSession->isClosedCaptions()) - { - priv->m_textTrackSession->setSessionCCSelection(priv->m_textTrackIdentifier); - } - - break; - } - case PROP_VIDEO_DECODER: - { - priv->m_videoDecoderIdentifier = g_value_get_uint64(value); - if (priv->m_textTrackSession && priv->m_textTrackSession->isClosedCaptions()) - { - priv->m_textTrackSession->associateVideoDecoder(priv->m_videoDecoderIdentifier); - } - - break; - } - case PROP_POSITION: - { - guint64 position = g_value_get_uint64(value); - std::unique_lock lock{priv->m_mutex}; - if (priv->m_textTrackSession && priv->m_capsSet) - { - priv->m_position = position; - gst_rialto_text_track_sink_set_position(textTrackSink); - } - else - { - priv->m_queuedPosition = position; - } - break; - } - case PROP_OFFSET: - { - uint64_t offset = g_value_get_uint64(value); - std::unique_lock lock{priv->m_mutex}; - if (priv->m_textTrackSession && priv->m_capsSet) - { - priv->m_offset = offset; - gst_rialto_text_track_sink_set_position(textTrackSink); - } - else - { - priv->m_queuedOffset = offset; - } - break; - } - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } -} - -static gboolean gst_rialto_text_track_sink_query(GstElement *element, GstQuery *query) // NOLINT(build/function_format) -{ - GstRialtoTextTrackSink *sink = GST_RIALTO_TEXT_TRACK_SINK(element); - GST_DEBUG_OBJECT(sink, "handling query '%s'", GST_QUERY_TYPE_NAME(query)); - switch (GST_QUERY_TYPE(query)) - { - case GST_QUERY_POSITION: - { - GstFormat fmt; - gst_query_parse_position(query, &fmt, NULL); - switch (fmt) - { - case GST_FORMAT_TIME: - { - // GST_CLOCK_TIME_NONE has to be returned here, because otherwise whole pipeline returns incorrect position - gst_query_set_position(query, fmt, GST_CLOCK_TIME_NONE); - break; - } - default: - break; - } - return TRUE; - } - default: - break; - } - GstElement *parent = GST_ELEMENT(&sink->parent); - return GST_ELEMENT_CLASS(parent_class)->query(parent, query); -} - -namespace firebolt::rialto::server -{ -std::shared_ptr IGstTextTrackSinkFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the textTrackSink element factory, reason: %s", e.what()); - } - - return factory; -} - -GstElement *GstTextTrackSinkFactory::createGstTextTrackSink() const -{ - GstElement *elem = GST_ELEMENT(g_object_new(GST_RIALTO_TEXT_TRACK_SINK_TYPE, nullptr)); - - return elem; -} - -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/GstWebAudioPlayer.cpp b/middleware/rialto-client/media/server/gstplayer/source/GstWebAudioPlayer.cpp deleted file mode 100644 index ddb9bd2dd..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/GstWebAudioPlayer.cpp +++ /dev/null @@ -1,473 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GstWebAudioPlayer.h" -#include "GstDispatcherThread.h" -#include "RialtoServerLogging.h" -#include "WorkerThread.h" -#include "tasks/webAudio/WebAudioPlayerTaskFactory.h" -#include - -namespace -{ -constexpr uint32_t kMaxWriteBufferTimeoutMs{2000}; -} // namespace - -namespace firebolt::rialto::server -{ -std::weak_ptr GstWebAudioPlayerFactory::m_factory; - -std::shared_ptr IGstWebAudioPlayerFactory::getFactory() -{ - std::shared_ptr factory = GstWebAudioPlayerFactory::m_factory.lock(); - - if (!factory) - { - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer player factory, reason: %s", e.what()); - } - - GstWebAudioPlayerFactory::m_factory = factory; - } - - return factory; -} - -std::unique_ptr GstWebAudioPlayerFactory::createGstWebAudioPlayer(IGstWebAudioPlayerClient *client, - const uint32_t priority) -{ - std::unique_ptr gstPlayer; - - try - { - auto gstWrapperFactory = firebolt::rialto::wrappers::IGstWrapperFactory::getFactory(); - auto glibWrapperFactory = firebolt::rialto::wrappers::IGlibWrapperFactory::getFactory(); - std::shared_ptr gstWrapper; - std::shared_ptr glibWrapper; - if ((!gstWrapperFactory) || (!(gstWrapper = gstWrapperFactory->getGstWrapper()))) - { - throw std::runtime_error("Cannot create GstWrapper"); - } - if ((!glibWrapperFactory) || (!(glibWrapper = glibWrapperFactory->getGlibWrapper()))) - { - throw std::runtime_error("Cannot create GlibWrapper"); - } - gstPlayer = std::make_unique(client, priority, gstWrapper, glibWrapper, - IGstInitialiser::instance(), IGstSrcFactory::getFactory(), - std::make_unique(client, gstWrapper, - glibWrapper), - std::make_unique(), - std::make_unique()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gstreamer player, reason: %s", e.what()); - } - - return gstPlayer; -} - -GstWebAudioPlayer::GstWebAudioPlayer(IGstWebAudioPlayerClient *client, const uint32_t priority, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const IGstInitialiser &gstInitialiser, - const std::shared_ptr &gstSrcFactory, - std::unique_ptr taskFactory, - std::unique_ptr workerThreadFactory, - std::unique_ptr gstDispatcherThreadFactory) - : m_gstPlayerClient(client), m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, - m_taskFactory{std::move(taskFactory)} -{ - RIALTO_SERVER_LOG_DEBUG("GstWebAudioPlayer is constructed."); - - gstInitialiser.waitForInitialisation(); - - if ((!gstSrcFactory) || (!(m_context.gstSrc = gstSrcFactory->getGstSrc()))) - { - throw std::runtime_error("Cannot create GstSrc"); - } - - // Ensure that rialtosrc has been initalised - m_context.gstSrc->initSrc(); - - // Start task thread - if ((!workerThreadFactory) || (!(m_workerThread = workerThreadFactory->createWorkerThread()))) - { - throw std::runtime_error("Failed to create the worker thread"); - } - - if (!initWebAudioPipeline(priority)) - { - termWebAudioPipeline(); - resetWorkerThread(); - throw std::runtime_error("Failed to initalise the pipeline"); - } - - if ((!gstDispatcherThreadFactory) || - (!(m_gstDispatcherThread = - gstDispatcherThreadFactory->createGstDispatcherThread(*this, m_context.pipeline, m_gstWrapper)))) - { - termWebAudioPipeline(); - resetWorkerThread(); - throw std::runtime_error("Failed to create the dispatcher thread"); - } -} - -GstWebAudioPlayer::~GstWebAudioPlayer() -{ - RIALTO_SERVER_LOG_DEBUG("GstWebAudioPlayer is destructed."); - - m_gstDispatcherThread.reset(); - - resetWorkerThread(); - - termWebAudioPipeline(); -} - -bool GstWebAudioPlayer::initWebAudioPipeline(const uint32_t priority) -{ - m_context.pipeline = m_gstWrapper->gstPipelineNew(std::string("webaudiopipeline" + std::to_string(priority)).c_str()); - if (!m_context.pipeline) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the webaudiopipeline"); - return false; - } - - RIALTO_SERVER_LOG_MIL("RialtoServer's webaudio pipeline constructed"); - - // Create and initalise appsrc - m_context.source = m_gstWrapper->gstElementFactoryMake("appsrc", "audsrc"); - if (!m_context.source) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the appsrc"); - return false; - } - m_gstWrapper->gstAppSrcSetMaxBytes(GST_APP_SRC(m_context.source), kMaxWebAudioBytes); - m_glibWrapper->gObjectSet(m_context.source, "format", GST_FORMAT_TIME, nullptr); - - // Perform sink specific initalisation - GstPluginFeature *feature = nullptr; - GstRegistry *reg = m_gstWrapper->gstRegistryGet(); - if (!reg) - { - RIALTO_SERVER_LOG_ERROR("Failed get the gst registry"); - return false; - } - - GstElement *sink = nullptr; - if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "amlhalasink"))) - { - // LLama - RIALTO_SERVER_LOG_INFO("Use amlhalasink"); - sink = createAmlhalaSink(); - m_gstWrapper->gstObjectUnref(feature); - } - else if (nullptr != (feature = m_gstWrapper->gstRegistryLookupFeature(reg, "rtkaudiosink"))) - { - // XiOne - RIALTO_SERVER_LOG_INFO("Use rtkaudiosink"); - sink = createRtkAudioSink(); - m_gstWrapper->gstObjectUnref(feature); - } - else - { - RIALTO_SERVER_LOG_INFO("Use autoaudiosink"); - sink = createAutoSink(); - } - - if (sink) - { - return linkElementsToSrc(sink); - } - else - { - m_gstWrapper->gstObjectUnref(m_context.source); - m_context.source = nullptr; - } - return false; -} - -GstElement *GstWebAudioPlayer::createAmlhalaSink() -{ - GstElement *sink = m_gstWrapper->gstElementFactoryMake("amlhalasink", "webaudiosink"); - if (!sink) - { - RIALTO_SERVER_LOG_ERROR("Failed create the amlhalasink"); - return nullptr; - } - m_glibWrapper->gObjectSet(G_OBJECT(sink), "direct-mode", FALSE, NULL); - - return sink; -} - -GstElement *GstWebAudioPlayer::createRtkAudioSink() -{ - GstElement *sink = m_gstWrapper->gstElementFactoryMake("rtkaudiosink", "webaudiosink"); - if (!sink) - { - RIALTO_SERVER_LOG_ERROR("Failed create the rtkaudiosink"); - return nullptr; - } - m_glibWrapper->gObjectSet(G_OBJECT(sink), "media-tunnel", FALSE, NULL); - m_glibWrapper->gObjectSet(G_OBJECT(sink), "audio-service", TRUE, NULL); - - return sink; -} - -GstElement *GstWebAudioPlayer::createAutoSink() -{ - GstElement *sink = m_gstWrapper->gstElementFactoryMake("autoaudiosink", "webaudiosink"); - if (!sink) - { - RIALTO_SERVER_LOG_ERROR("Failed create the autoaudiosink"); - return nullptr; - } - - return sink; -} - -// NOTE:- -// This method hands the responsibility for the destruction of both { "sink", "m_context.source" } -// over to the pipeline (or if handover wasn't possible, it will unref) -bool GstWebAudioPlayer::linkElementsToSrc(GstElement *sink) -{ - bool status{true}; - - GstElement *convert{nullptr}; - GstElement *resample{nullptr}; - GstElement *volume{nullptr}; - GstElement *queue{nullptr}; - - convert = m_gstWrapper->gstElementFactoryMake("audioconvert", NULL); - if (!convert) - { - RIALTO_SERVER_LOG_ERROR("Failed create the audioconvert"); - status = false; - } - - if (status) - { - resample = m_gstWrapper->gstElementFactoryMake("audioresample", NULL); - if (!resample) - { - RIALTO_SERVER_LOG_ERROR("Failed create the audioresample"); - status = false; - } - } - - if (status) - { - volume = m_gstWrapper->gstElementFactoryMake("volume", NULL); - if (!volume) - { - RIALTO_SERVER_LOG_ERROR("Failed create the volume"); - status = false; - } - } - if (status) - { - queue = m_gstWrapper->gstElementFactoryMake("queue", NULL); - if (!queue) - { - RIALTO_SERVER_LOG_ERROR("Failed create the queue"); - status = false; - } - else - { - constexpr guint kWebAudioQueueSize{8192}; - m_glibWrapper->gObjectSet(queue, "max-size-bytes", kWebAudioQueueSize, nullptr); - } - } - - std::queue elementsToAdd; - elementsToAdd.push(m_context.source); - if (convert) - elementsToAdd.push(convert); - if (resample) - elementsToAdd.push(resample); - if (volume) - elementsToAdd.push(volume); - if (queue) - elementsToAdd.push(queue); - elementsToAdd.push(sink); - - if (status) - { - // Add elements to the pipeline - GstBin *pipelineBin = GST_BIN(m_context.pipeline); - while (!elementsToAdd.empty()) - { - if (m_gstWrapper->gstBinAdd(pipelineBin, elementsToAdd.front())) - elementsToAdd.pop(); - else - { - RIALTO_SERVER_LOG_ERROR("Failed to add element to the bin"); - status = false; - break; - } - } - } - - if (status) - { - if ((!m_gstWrapper->gstElementLink(m_context.source, convert)) || - (!m_gstWrapper->gstElementLink(convert, resample)) || (!m_gstWrapper->gstElementLink(resample, volume)) || - (!m_gstWrapper->gstElementLink(volume, queue)) || (!m_gstWrapper->gstElementLink(queue, sink))) - { - RIALTO_SERVER_LOG_ERROR("Failed to link elements"); - status = false; - } - m_context.gstVolumeElement = GST_STREAM_VOLUME(volume); - } - - if (!status) - { - // Unref anything that wasn't added to the pipeline - while (!elementsToAdd.empty()) - { - m_gstWrapper->gstObjectUnref(elementsToAdd.front()); - elementsToAdd.pop(); - } - m_context.source = nullptr; - } - - return status; -} - -void GstWebAudioPlayer::termWebAudioPipeline() -{ - if (m_context.pipeline) - { - m_taskFactory->createStop(*this)->execute(); - GstBus *bus = m_gstWrapper->gstPipelineGetBus(GST_PIPELINE(m_context.pipeline)); - if (bus) - { - m_gstWrapper->gstBusSetSyncHandler(bus, nullptr, nullptr, nullptr); - m_gstWrapper->gstObjectUnref(bus); - } - - m_gstWrapper->gstObjectUnref(m_context.pipeline); - } - RIALTO_SERVER_LOG_MIL("RialtoServer's webaudio pipeline terminated."); -} - -void GstWebAudioPlayer::resetWorkerThread() -{ - m_workerThread->enqueueTask(m_taskFactory->createShutdown(*this)); - m_workerThread->join(); - m_workerThread.reset(); -} - -void GstWebAudioPlayer::setCaps(const std::string &audioMimeType, std::weak_ptr config) -{ - m_workerThread->enqueueTask(m_taskFactory->createSetCaps(m_context, audioMimeType, config)); -} - -void GstWebAudioPlayer::play() -{ - m_workerThread->enqueueTask(m_taskFactory->createPlay(*this)); -} - -void GstWebAudioPlayer::pause() -{ - m_workerThread->enqueueTask(m_taskFactory->createPause(*this)); -} - -void GstWebAudioPlayer::setVolume(double volume) -{ - m_workerThread->enqueueTask(m_taskFactory->createSetVolume(m_context, volume)); -} - -bool GstWebAudioPlayer::getVolume(double &volume) -{ - // Must be called on the main thread, otherwise the pipeline can be destroyed during the query. - volume = m_gstWrapper->gstStreamVolumeGetVolume(m_context.gstVolumeElement, GST_STREAM_VOLUME_FORMAT_LINEAR); - return true; -} - -uint32_t GstWebAudioPlayer::writeBuffer(uint8_t *mainPtr, uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength) -{ - // Must block and wait for the data to be written from the shared buffer. - std::unique_lock lock(m_context.writeBufferMutex); - m_workerThread->enqueueTask(m_taskFactory->createWriteBuffer(m_context, mainPtr, mainLength, wrapPtr, wrapLength)); - std::cv_status status = m_context.writeBufferCond.wait_for(lock, std::chrono::milliseconds(kMaxWriteBufferTimeoutMs)); - if (std::cv_status::timeout == status) - { - RIALTO_SERVER_LOG_ERROR("Timed out writing to the gstreamer buffers"); - return 0; - } - else - { - return m_context.lastBytesWritten; - } -} - -void GstWebAudioPlayer::setEos() -{ - m_workerThread->enqueueTask(m_taskFactory->createEos(m_context)); -} - -uint64_t GstWebAudioPlayer::getQueuedBytes() -{ - // Must be called on the main thread, otherwise the pipeline can be destroyed during the query. - return m_gstWrapper->gstAppSrcGetCurrentLevelBytes(GST_APP_SRC(m_context.source)); -} - -bool GstWebAudioPlayer::changePipelineState(GstState newState) -{ - if (m_gstWrapper->gstElementSetState(m_context.pipeline, newState) == GST_STATE_CHANGE_FAILURE) - { - RIALTO_SERVER_LOG_ERROR("Change state failed - Gstreamer returned an error"); - if (m_gstPlayerClient) - m_gstPlayerClient->notifyState(WebAudioPlayerState::FAILURE); - return false; - } - return true; -} - -void GstWebAudioPlayer::stopWorkerThread() -{ - if (m_workerThread) - { - m_workerThread->stop(); - } -} - -void GstWebAudioPlayer::handleBusMessage(GstMessage *message, bool priority) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createHandleBusMessage(m_context, *this, message)); - } -} - -void GstWebAudioPlayer::ping(std::unique_ptr &&heartbeatHandler) -{ - if (m_workerThread) - { - m_workerThread->enqueueTask(m_taskFactory->createPing(std::move(heartbeatHandler))); - } -} - -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/NeedDataMapping.cpp b/middleware/rialto-client/media/server/gstplayer/source/NeedDataMapping.cpp deleted file mode 100644 index 05212e946..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/NeedDataMapping.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "NeedDataMapping.h" - -namespace firebolt::rialto::server -{ -bool NeedDataMapping::isNeedDataScheduled(GstAppSrc *src) const -{ - std::unique_lock lock{m_mutex}; - return m_scheduledNeedDatas.find(src) != m_scheduledNeedDatas.end(); -} - -void NeedDataMapping::setNeedDataScheduled(GstAppSrc *src) -{ - std::unique_lock lock{m_mutex}; - m_scheduledNeedDatas.insert(src); -} - -void NeedDataMapping::clearNeedDataScheduled(GstAppSrc *src) -{ - std::unique_lock lock{m_mutex}; - m_scheduledNeedDatas.erase(src); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/Utils.cpp b/middleware/rialto-client/media/server/gstplayer/source/Utils.cpp deleted file mode 100644 index 17f7c3aad..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/Utils.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Utils.h" -#include "CapsBuilder.h" -#include "GstMimeMapping.h" -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include -#include - -namespace -{ -const char *underflowSignals[]{"buffer-underflow-callback", "vidsink-underflow-callback", "underrun-callback"}; - -bool isType(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element, GstElementFactoryListType type) -{ - if (!element) - { - return false; - } - - GstElementFactory *factory{gstWrapper.gstElementGetFactory(element)}; - if (!factory) - { - return false; - } - return gstWrapper.gstElementFactoryListIsType(factory, type); -} -} // namespace - -namespace firebolt::rialto::server -{ - -bool isVideoDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO); -} - -bool isAudioDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); -} - -bool isVideoParser(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_PARSER | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO); -} - -bool isVideoSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO); -} - -bool isAudioSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK | GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); -} - -bool isSink(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_SINK); -} - -bool isDecoder(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_DECODER); -} - -bool isAudio(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO); -} - -bool isVideo(const firebolt::rialto::wrappers::IGstWrapper &gstWrapper, GstElement *element) -{ - return isType(gstWrapper, element, GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO); -} - -std::optional getUnderflowSignalName(const firebolt::rialto::wrappers::IGlibWrapper &glibWrapper, - GstElement *element) -{ - GType type = glibWrapper.gObjectType(element); - guint nsignals{0}; - guint *signals = glibWrapper.gSignalListIds(type, &nsignals); - - for (guint i = 0; i < nsignals; i++) - { - GSignalQuery query; - glibWrapper.gSignalQuery(signals[i], &query); - const auto signalNameIt = std::find_if(std::begin(underflowSignals), std::end(underflowSignals), - [&](const auto *signalName) - { return strcmp(signalName, query.signal_name) == 0; }); - - if (std::end(underflowSignals) != signalNameIt) - { - glibWrapper.gFree(signals); - return std::string(*signalNameIt); - } - } - glibWrapper.gFree(signals); - - return std::nullopt; -} - -GstCaps *createCapsFromMediaSource(const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::unique_ptr &source) -{ - std::unique_ptr capsBuilder; - - firebolt::rialto::SourceConfigType configType = source->getConfigType(); - if (configType == firebolt::rialto::SourceConfigType::AUDIO) - { - const IMediaPipeline::MediaSourceAudio *kSource = dynamic_cast(source.get()); - if (kSource) - { - capsBuilder = std::make_unique(gstWrapper, glibWrapper, *kSource); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to cast to audio source"); - return nullptr; - } - } - else if (configType == firebolt::rialto::SourceConfigType::VIDEO) - { - const IMediaPipeline::MediaSourceVideo *kSource = dynamic_cast(source.get()); - if (kSource) - { - capsBuilder = std::make_unique(gstWrapper, glibWrapper, *kSource); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to cast to video source"); - return nullptr; - } - } - else if (configType == firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION) - { - const IMediaPipeline::MediaSourceVideoDolbyVision *kSource = - dynamic_cast(source.get()); - if (kSource) - { - capsBuilder = std::make_unique(gstWrapper, glibWrapper, *kSource); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to cast to dolby vision source!"); - return nullptr; - } - } - else if (configType == firebolt::rialto::SourceConfigType::SUBTITLE) - { - // subtitle caps is just a simple type, without any extra parameters - return firebolt::rialto::server::createSimpleCapsFromMimeType(gstWrapper, *source.get()); - } - else - { - RIALTO_SERVER_LOG_ERROR("Invalid config type %u", static_cast(configType)); - return nullptr; - } - - return capsBuilder->buildCaps(); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/WorkerThread.cpp b/middleware/rialto-client/media/server/gstplayer/source/WorkerThread.cpp deleted file mode 100644 index 0b5177b27..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/WorkerThread.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WorkerThread.h" -#include "RialtoServerLogging.h" - -namespace -{ - -class FunctionTask : public firebolt::rialto::server::IPlayerTask -{ -public: - explicit FunctionTask(std::function &&callback) : m_callback(std::move(callback)) {} - - ~FunctionTask() override = default; - - void execute() const override { m_callback(); } - -private: - std::function m_callback; -}; - -} // namespace - -namespace firebolt::rialto::server -{ -std::unique_ptr WorkerThreadFactory::createWorkerThread() const -{ - std::unique_ptr workerThread; - try - { - workerThread = std::make_unique(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the worker thread, reason: %s", e.what()); - } - return workerThread; -} - -WorkerThread::WorkerThread() -{ - RIALTO_SERVER_LOG_INFO("Worker thread is starting"); - m_taskThread = std::thread(&WorkerThread::taskHandler, this); -} - -WorkerThread::~WorkerThread() -{ - stop(); - join(); -} - -void WorkerThread::stop() -{ - RIALTO_SERVER_LOG_INFO("Stopping worker thread"); - - auto shutdownTask = [this]() { m_isTaskThreadActive = false; }; - enqueueTask(std::make_unique(std::move(shutdownTask))); -} - -void WorkerThread::join() -{ - if (m_taskThread.joinable()) - { - m_taskThread.join(); - } -} - -void WorkerThread::enqueueTask(std::unique_ptr &&task) -{ - if (task) - { - std::unique_lock lock(m_taskMutex); - m_taskQueue.push_back(std::move(task)); - m_taskCV.notify_one(); - } -} - -void WorkerThread::enqueuePriorityTask(std::unique_ptr &&task) -{ - if (task) - { - std::unique_lock lock(m_taskMutex); - m_taskQueue.push_front(std::move(task)); - m_taskCV.notify_one(); - } -} - -void WorkerThread::taskHandler() -{ - while (m_isTaskThreadActive) - { - std::unique_ptr task = waitForTask(); - task->execute(); - } -} - -std::unique_ptr WorkerThread::waitForTask() -{ - std::unique_lock lock(m_taskMutex); - if (m_taskQueue.empty()) - { - m_taskCV.wait(lock, [this] { return !m_taskQueue.empty(); }); - } - std::unique_ptr task = std::move(m_taskQueue.front()); - m_taskQueue.pop_front(); - return task; -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSamples.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSamples.cpp deleted file mode 100644 index ccc91ca02..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSamples.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/AttachSamples.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -AttachSamples::AttachSamples(GenericPlayerContext &context, - const std::shared_ptr &gstWrapper, - IGstGenericPlayerPrivate &player, const IMediaPipeline::MediaSegmentVector &mediaSegments) - : m_context{context}, m_gstWrapper{gstWrapper}, m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing AttachSamples"); - for (const auto &mediaSegment : mediaSegments) - { - GstBuffer *gstBuffer = m_player.createBuffer(*mediaSegment); - if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::VIDEO) - { - try - { - IMediaPipeline::MediaSegmentVideo &videoSegment = - dynamic_cast(*mediaSegment); - VideoData videoData = {gstBuffer, videoSegment.getWidth(), videoSegment.getHeight(), - videoSegment.getFrameRate(), videoSegment.getCodecData()}; - m_videoData.push_back(videoData); - } - catch (const std::exception &e) - { - // Catching error, but continuing as best as we can - RIALTO_SERVER_LOG_ERROR("Failed to get the video segment, reason: %s", e.what()); - } - } - else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::AUDIO) - { - try - { - IMediaPipeline::MediaSegmentAudio &audioSegment = - dynamic_cast(*mediaSegment); - AudioData audioData = {gstBuffer, - audioSegment.getSampleRate(), - audioSegment.getNumberOfChannels(), - audioSegment.getCodecData(), - audioSegment.getClippingStart(), - audioSegment.getClippingEnd()}; - m_audioData.push_back(audioData); - } - catch (const std::exception &e) - { - // Catching error, but continuing as best as we can - RIALTO_SERVER_LOG_ERROR("Failed to get the audio segment, reason: %s", e.what()); - } - } - else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::SUBTITLE) - { - m_subtitleData.push_back(gstBuffer); - } - } -} - -AttachSamples::~AttachSamples() -{ - RIALTO_SERVER_LOG_DEBUG("AttachSamples finished"); -} - -void AttachSamples::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing AttachSamples"); - for (AudioData audioData : m_audioData) - { - m_player.updateAudioCaps(audioData.rate, audioData.channels, audioData.codecData); - m_player.addAudioClippingToBuffer(audioData.buffer, audioData.clippingStart, audioData.clippingEnd); - - attachData(firebolt::rialto::MediaSourceType::AUDIO, audioData.buffer); - } - for (VideoData videoData : m_videoData) - { - m_player.updateVideoCaps(videoData.width, videoData.height, videoData.frameRate, videoData.codecData); - - attachData(firebolt::rialto::MediaSourceType::VIDEO, videoData.buffer); - } - for (GstBuffer *buffer : m_subtitleData) - { - attachData(firebolt::rialto::MediaSourceType::SUBTITLE, buffer); - } - - if (!m_audioData.empty()) - { - m_player.notifyNeedMediaData(firebolt::rialto::MediaSourceType::AUDIO); - } - else if (!m_videoData.empty()) - { - m_player.notifyNeedMediaData(firebolt::rialto::MediaSourceType::VIDEO); - } - else if (!m_subtitleData.empty()) - { - m_player.notifyNeedMediaData(firebolt::rialto::MediaSourceType::SUBTITLE); - } -} - -void AttachSamples::attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const -{ - auto elem = m_context.streamInfo.find(mediaType); - if (elem != m_context.streamInfo.end()) - { - elem->second.buffers.push_back(buffer); - m_player.attachData(mediaType); - } - else - { - RIALTO_SERVER_LOG_WARN("Could not find stream info for %s", common::convertMediaSourceType(mediaType)); - m_gstWrapper->gstBufferUnref(buffer); - } -} - -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSource.cpp deleted file mode 100644 index ce8c80521..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/AttachSource.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/AttachSource.h" -#include "GstMimeMapping.h" -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "IMediaPipeline.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" -#include "Utils.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -AttachSource::AttachSource(GenericPlayerContext &context, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr &gstTextTrackSinkFactory, - IGstGenericPlayerPrivate &player, const std::unique_ptr &source) - : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, - m_gstTextTrackSinkFactory{gstTextTrackSinkFactory}, m_player{player}, m_attachedSource{source->copy()} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing AttachSource"); -} - -AttachSource::~AttachSource() -{ - RIALTO_SERVER_LOG_DEBUG("AttachSource finished"); -} - -void AttachSource::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing AttachSource %u", static_cast(m_attachedSource->getType())); - - if (m_attachedSource->getType() == MediaSourceType::UNKNOWN) - { - RIALTO_SERVER_LOG_ERROR("Unknown media source type"); - return; - } - - if (m_context.streamInfo.find(m_attachedSource->getType()) == m_context.streamInfo.end()) - { - addSource(); - } - else if (m_attachedSource->getType() == MediaSourceType::AUDIO && m_context.audioSourceRemoved) - { - reattachAudioSource(); - } - else - { - RIALTO_SERVER_LOG_ERROR("cannot update caps"); - } -} - -void AttachSource::addSource() const -{ - GstCaps *caps = createCapsFromMediaSource(m_gstWrapper, m_glibWrapper, m_attachedSource); - if (!caps) - { - RIALTO_SERVER_LOG_ERROR("Failed to create caps from media source"); - return; - } - gchar *capsStr = m_gstWrapper->gstCapsToString(caps); - GstElement *appSrc = nullptr; - if (m_attachedSource->getType() == MediaSourceType::AUDIO) - { - RIALTO_SERVER_LOG_MIL("Adding Audio appsrc with caps %s", capsStr); - appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "audsrc"); - } - else if (m_attachedSource->getType() == MediaSourceType::VIDEO) - { - RIALTO_SERVER_LOG_MIL("Adding Video appsrc with caps %s", capsStr); - appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "vidsrc"); - } - else if (m_attachedSource->getType() == MediaSourceType::SUBTITLE) - { - RIALTO_SERVER_LOG_MIL("Adding Subtitle appsrc with caps %s", capsStr); - appSrc = m_gstWrapper->gstElementFactoryMake("appsrc", "subsrc"); - - if (m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(m_context.pipeline), "text-sink")) - { - GstElement *elem = m_gstTextTrackSinkFactory->createGstTextTrackSink(); - m_context.subtitleSink = elem; - - m_glibWrapper->gObjectSet(m_context.pipeline, "text-sink", elem, nullptr); - } - } - m_glibWrapper->gFree(capsStr); - - m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(appSrc), caps); - m_context.streamInfo.emplace(m_attachedSource->getType(), StreamInfo{appSrc, m_attachedSource->getHasDrm()}); - - if (caps) - m_gstWrapper->gstCapsUnref(caps); -} - -void AttachSource::reattachAudioSource() const -{ - if (!m_player.reattachSource(m_attachedSource)) - { - RIALTO_SERVER_LOG_ERROR("Reattaching source failed!"); - return; - } - - // Restart audio sink - m_player.setPlaybinFlags(true); - - m_context.streamInfo[m_attachedSource->getType()].isDataNeeded = true; - m_context.audioSourceRemoved = false; - m_player.notifyNeedMediaData(MediaSourceType::AUDIO); - - RIALTO_SERVER_LOG_MIL("Audio source reattached"); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp deleted file mode 100644 index e556c4b62..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/CheckAudioUnderflow.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/CheckAudioUnderflow.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include "tasks/generic/Underflow.h" -#include - -#include - -namespace firebolt::rialto::server::tasks::generic -{ -CheckAudioUnderflow::CheckAudioUnderflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper) - : m_context{context}, m_player(player), m_gstPlayerClient{client}, m_gstWrapper{gstWrapper} -{ -} - -void CheckAudioUnderflow::execute() const -{ - // TODO(LLDEV-31012) Check if the audio stream is in underflow state. - if (m_context.streamInfo.find(firebolt::rialto::MediaSourceType::AUDIO) != m_context.streamInfo.end()) - { - gint64 position = m_player.getPosition(m_context.pipeline); - if (position == -1) - { - RIALTO_SERVER_LOG_WARN("Getting the position failed"); - return; - } - - constexpr int64_t kAudioUnderflowMarginNs = 350 * 1000000; - if ((position > m_context.lastAudioSampleTimestamps + kAudioUnderflowMarginNs) && - m_gstWrapper->gstElementGetState(m_context.pipeline) == GST_STATE_PLAYING && - m_gstWrapper->gstElementGetPendingState(m_context.pipeline) != GST_STATE_PAUSED) - { - RIALTO_SERVER_LOG_WARN("Audio stream underflow! Position %" PRIu64 ", lastAudioSampleTimestamps: %" PRIu64, - position, m_context.lastAudioSampleTimestamps); - bool underflowEnabled = m_context.isPlaying && !m_context.audioSourceRemoved; - Underflow task(m_context, m_player, m_gstPlayerClient, underflowEnabled, MediaSourceType::AUDIO); - task.execute(); - } - } -} - -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp deleted file mode 100644 index 56526fd4f..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/DeepElementAdded.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/DeepElementAdded.h" -#include "RialtoServerLogging.h" - -namespace -{ -void onHaveType(GstElement *typefind, guint probability, const GstCaps *caps, gpointer data) -{ - firebolt::rialto::server::IGstGenericPlayerPrivate *player = - static_cast(data); - player->updatePlaybackGroup(typefind, caps); -} -} // namespace - -namespace firebolt::rialto::server::tasks::generic -{ -DeepElementAdded::DeepElementAdded(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - GstBin *pipeline, GstBin *bin, GstElement *element) - : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_pipeline{pipeline}, - m_bin{bin}, m_element{element}, m_elementName{nullptr}, m_callbackRegistered{false} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing DeepElementAdded"); - // Signal connection has to happen immediately (we cannot wait for thread switch) - if (m_gstWrapper->gstObjectParent(m_element) == m_gstWrapper->gstObjectCast(m_bin)) - { - m_elementName = m_gstWrapper->gstElementGetName(m_element); - if (m_elementName) - { - RIALTO_SERVER_LOG_DEBUG("Element Name = %s", m_elementName); - if (m_glibWrapper->gStrrstr(m_elementName, "typefind")) - { - RIALTO_SERVER_LOG_DEBUG("Registering onHaveType callback"); - m_glibWrapper->gSignalConnect(G_OBJECT(m_element), "have-type", G_CALLBACK(onHaveType), &m_player); - m_callbackRegistered = true; - } - } - } -} - -DeepElementAdded::~DeepElementAdded() -{ - RIALTO_SERVER_LOG_DEBUG("DeepElementAdded finished"); - m_glibWrapper->gFree(m_elementName); -} - -void DeepElementAdded::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing DeepElementAdded"); - m_context.playbackGroup.m_gstPipeline = GST_ELEMENT(m_pipeline); - - RIALTO_SERVER_LOG_DEBUG("Element = %p Bin = %p Pipeline = %p", m_element, m_bin, m_pipeline); - if (m_callbackRegistered) - { - m_context.playbackGroup.m_curAudioTypefind = m_element; - } - if (m_elementName) - { - if (m_gstWrapper->gstObjectCast(m_bin) == m_gstWrapper->gstObjectCast(m_context.playbackGroup.m_curAudioDecodeBin)) - { - if (m_glibWrapper->gStrrstr(m_elementName, "parse")) - { - RIALTO_SERVER_LOG_DEBUG("curAudioParse = %s", m_elementName); - m_context.playbackGroup.m_curAudioParse = m_element; - } - else if (m_glibWrapper->gStrrstr(m_elementName, "dec")) - { - RIALTO_SERVER_LOG_DEBUG("curAudioDecoder = %s", m_elementName); - m_context.playbackGroup.m_curAudioDecoder = m_element; - } - } - else - { - if (m_glibWrapper->gStrrstr(m_elementName, "audiosink")) - { - GstElement *audioSinkParent = - reinterpret_cast(m_gstWrapper->gstElementGetParent(m_element)); - if (audioSinkParent) - { - gchar *audioSinkParentName = m_gstWrapper->gstElementGetName(audioSinkParent); - RIALTO_SERVER_LOG_DEBUG("audioSinkParentName = %s", audioSinkParentName); - if (audioSinkParentName && m_glibWrapper->gStrrstr(audioSinkParentName, "bin")) - { - RIALTO_SERVER_LOG_DEBUG("curAudioPlaysinkBin = %s", audioSinkParentName); - m_context.playbackGroup.m_curAudioPlaysinkBin = audioSinkParent; - } - m_glibWrapper->gFree(audioSinkParentName); - } - } - } - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/EnoughData.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/EnoughData.cpp deleted file mode 100644 index a25679eb7..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/EnoughData.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/EnoughData.h" -#include "GenericPlayerContext.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -EnoughData::EnoughData(GenericPlayerContext &context, GstAppSrc *src) : m_context{context}, m_src{src} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing EnoughData"); -} - -EnoughData::~EnoughData() -{ - RIALTO_SERVER_LOG_DEBUG("EnoughData finished"); -} - -void EnoughData::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing EnoughData"); - for (auto &elem : m_context.streamInfo) - { - firebolt::rialto::MediaSourceType sourceType = elem.first; - if (elem.second.appSrc == GST_ELEMENT(m_src)) - { - RIALTO_SERVER_LOG_DEBUG("%s source has enough data", common::convertMediaSourceType(sourceType)); - elem.second.isDataNeeded = false; - break; - } - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Eos.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Eos.cpp deleted file mode 100644 index f45968e05..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Eos.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Eos.h" -#include "GenericPlayerContext.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Eos::Eos(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::shared_ptr gstWrapper, - const firebolt::rialto::MediaSourceType &type) - : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_type{type} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Eos"); -} - -Eos::~Eos() -{ - RIALTO_SERVER_LOG_DEBUG("Eos finished"); -} - -void Eos::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Eos for %s", common::convertMediaSourceType(m_type)); - - m_player.cancelUnderflow(m_type); - - auto elem = m_context.streamInfo.find(m_type); - if (elem == m_context.streamInfo.end()) - { - RIALTO_SERVER_LOG_WARN("Set eos failed - Stream not found"); - return; - } - - const auto eosInfoIt = m_context.endOfStreamInfo.find(m_type); - if (eosInfoIt != m_context.endOfStreamInfo.end() && eosInfoIt->second == EosState::SET) - { - RIALTO_SERVER_LOG_DEBUG("Eos already set for source %s", common::convertMediaSourceType(m_type)); - return; - } - - StreamInfo &streamInfo = elem->second; - if (!streamInfo.buffers.empty()) - { - RIALTO_SERVER_LOG_INFO("There are pending buffers; delaying sending EOS"); - m_context.endOfStreamInfo[m_type] = EosState::PENDING; - } - else if (m_gstWrapper->gstAppSrcEndOfStream(GST_APP_SRC(elem->second.appSrc)) != GST_FLOW_OK) - { - RIALTO_SERVER_LOG_WARN("Set eos failed - Gstreamer error"); - } - else - { - RIALTO_SERVER_LOG_MIL("Successfully set EOS for source %s", common::convertMediaSourceType(m_type)); - m_context.endOfStreamInfo[m_type] = EosState::SET; - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp deleted file mode 100644 index e487e3740..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/FinishSetupSource.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/FinishSetupSource.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" -#include -#include - -namespace -{ -/** - * @brief Callback for need-data event from gstreamer. Called by the Gstreamer thread. - * - * @param[in] src : the appsrc element that emitted the signal - * @param[in] length : the amount of bytes needed. - * @param[in] user_data : The data to be passed with the message. - * - */ -void appSrcNeedData(GstAppSrc *src, guint length, gpointer user_data) -{ - firebolt::rialto::server::IGstGenericPlayerPrivate *self = - static_cast(user_data); - self->scheduleNeedMediaData(src); -} - -/** - * @brief Callback for enough-data event from gstreamer. Called by the Gstreamer thread. - * - * @param[in] src : the appsrc element that emitted the signal - * @param[in] user_data : The data to be passed with the message. - * - */ -void appSrcEnoughData(GstAppSrc *src, gpointer user_data) -{ - firebolt::rialto::server::IGstGenericPlayerPrivate *self = - static_cast(user_data); - self->scheduleEnoughData(src); -} - -/** - * @brief Callback for seek-data event from gstreamer. Called by the Gstreamer thread. - * - * @param[in] src : the appsrc element that emitted the signal - * @param[in] offset : the offset to seek to - * @param[in] user_data : The data to be passed with the message. - * - * @retval true if the handling of the message is successful, false otherwise. - */ -gboolean appSrcSeekData(GstAppSrc *src, guint64 offset, gpointer user_data) -{ - appSrcEnoughData(src, user_data); - return TRUE; -} -} // namespace - -namespace firebolt::rialto::server::tasks::generic -{ -FinishSetupSource::FinishSetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - IGstGenericPlayerClient *client) - : m_context{context}, m_player{player}, m_gstPlayerClient{client} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing FinishSetupSource"); -} - -FinishSetupSource::~FinishSetupSource() -{ - RIALTO_SERVER_LOG_DEBUG("FinishSetupSource finished"); -} - -void FinishSetupSource::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing FinishSetupSource"); - m_context.wereAllSourcesAttached = true; - - if (!m_context.source) - { - RIALTO_SERVER_LOG_DEBUG("Source is not ready"); - return; - } - - GstAppSrcCallbacks callbacks = {appSrcNeedData, appSrcEnoughData, appSrcSeekData, {nullptr}}; - - for (auto &elem : m_context.streamInfo) - { - firebolt::rialto::MediaSourceType sourceType = elem.first; - if (sourceType == firebolt::rialto::MediaSourceType::UNKNOWN) - { - RIALTO_SERVER_LOG_WARN("Unknown media segment type"); - continue; - } - - StreamInfo &streamInfo = elem.second; - m_context.gstSrc->setupAndAddAppSrc(m_context.decryptionService, m_context.source, streamInfo, &callbacks, - &m_player, sourceType); - m_player.notifyNeedMediaData(sourceType); - } - - m_context.gstSrc->allAppSrcsAdded(m_context.source); - - // Notify GstPlayerClient of Idle state once setup has finished - if (m_gstPlayerClient) - m_gstPlayerClient->notifyPlaybackState(PlaybackState::IDLE); - - m_context.setupSourceFinished = true; - - RIALTO_SERVER_LOG_MIL("All sources attached."); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Flush.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Flush.cpp deleted file mode 100644 index 82a61d729..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Flush.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Flush.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Flush::Flush(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper, const MediaSourceType &type, - bool resetTime) - : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_type{type}, - m_resetTime{resetTime} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Flush"); -} - -Flush::~Flush() -{ - RIALTO_SERVER_LOG_DEBUG("Flush finished"); -} - -void Flush::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Flush for %s source", common::convertMediaSourceType(m_type)); - - // Get source first - GstElement *source{nullptr}; - auto sourceElem = m_context.streamInfo.find(m_type); - if (sourceElem != m_context.streamInfo.end()) - { - source = sourceElem->second.appSrc; - } - if (!source) - { - RIALTO_SERVER_LOG_WARN("failed to flush %s - source is NULL", common::convertMediaSourceType(m_type)); - return; - } - - if (m_type == MediaSourceType::UNKNOWN) - { - RIALTO_SERVER_LOG_WARN("Flush failed: Media source type not supported."); - return; - } - - StreamInfo &streamInfo = sourceElem->second; - streamInfo.isDataNeeded = false; - streamInfo.isNeedDataPending = false; - m_player.clearNeedDataScheduled(GST_APP_SRC(source)); - - for (auto &buffer : streamInfo.buffers) - { - m_gstWrapper->gstBufferUnref(buffer); - } - streamInfo.buffers.clear(); - - m_gstPlayerClient->invalidateActiveRequests(m_type); - - if (GST_STATE(m_context.pipeline) >= GST_STATE_PAUSED) - { - m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); - // Flush source - GstEvent *flushStart = m_gstWrapper->gstEventNewFlushStart(); - if (!m_gstWrapper->gstElementSendEvent(source, flushStart)) - { - RIALTO_SERVER_LOG_WARN("failed to send flush-start event for %s", common::convertMediaSourceType(m_type)); - } - - GstEvent *flushStop = m_gstWrapper->gstEventNewFlushStop(m_resetTime); - if (!m_gstWrapper->gstElementSendEvent(source, flushStop)) - { - RIALTO_SERVER_LOG_WARN("failed to send flush-stop event for %s", common::convertMediaSourceType(m_type)); - } - } - else - { - RIALTO_SERVER_LOG_DEBUG("Skip sending flush event for %s - pipeline below paused", - common::convertMediaSourceType(m_type)); - } - - // Reset Eos info - m_context.endOfStreamInfo.erase(m_type); - m_context.eosNotified = false; - - // Notify client, that flush has been finished - m_gstPlayerClient->notifySourceFlushed(m_type); - - // Notify GstGenericPlayer, that flush has been finished - m_player.setSourceFlushed(m_type); - - RIALTO_SERVER_LOG_MIL("%s source flushed.", common::convertMediaSourceType(m_type)); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp deleted file mode 100644 index 83101affe..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/GenericPlayerTaskFactory.cpp +++ /dev/null @@ -1,363 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "tasks/generic/GenericPlayerTaskFactory.h" -#include "IMediaPipeline.h" -#include "tasks/generic/AttachSamples.h" -#include "tasks/generic/AttachSource.h" -#include "tasks/generic/CheckAudioUnderflow.h" -#include "tasks/generic/DeepElementAdded.h" -#include "tasks/generic/EnoughData.h" -#include "tasks/generic/Eos.h" -#include "tasks/generic/FinishSetupSource.h" -#include "tasks/generic/Flush.h" -#include "tasks/generic/HandleBusMessage.h" -#include "tasks/generic/NeedData.h" -#include "tasks/generic/Pause.h" -#include "tasks/generic/Ping.h" -#include "tasks/generic/Play.h" -#include "tasks/generic/ProcessAudioGap.h" -#include "tasks/generic/ReadShmDataAndAttachSamples.h" -#include "tasks/generic/RemoveSource.h" -#include "tasks/generic/RenderFrame.h" -#include "tasks/generic/ReportPosition.h" -#include "tasks/generic/SetBufferingLimit.h" -#include "tasks/generic/SetImmediateOutput.h" -#include "tasks/generic/SetLowLatency.h" -#include "tasks/generic/SetMute.h" -#include "tasks/generic/SetPlaybackRate.h" -#include "tasks/generic/SetPosition.h" -#include "tasks/generic/SetSourcePosition.h" -#include "tasks/generic/SetStreamSyncMode.h" -#include "tasks/generic/SetSubtitleOffset.h" -#include "tasks/generic/SetSync.h" -#include "tasks/generic/SetSyncOff.h" -#include "tasks/generic/SetTextTrackIdentifier.h" -#include "tasks/generic/SetUseBuffering.h" -#include "tasks/generic/SetVideoGeometry.h" -#include "tasks/generic/SetVolume.h" -#include "tasks/generic/SetupElement.h" -#include "tasks/generic/SetupSource.h" -#include "tasks/generic/Shutdown.h" -#include "tasks/generic/Stop.h" -#include "tasks/generic/SwitchSource.h" -#include "tasks/generic/SynchroniseSubtitleClock.h" -#include "tasks/generic/Underflow.h" -#include "tasks/generic/UpdatePlaybackGroup.h" - -namespace firebolt::rialto::server -{ -GenericPlayerTaskFactory::GenericPlayerTaskFactory( - IGstGenericPlayerClient *client, const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr &rdkGstreamerUtilsWrapper, - const std::shared_ptr &gstTextTrackSinkFactory) - : m_client{client}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, - m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, m_gstTextTrackSinkFactory{gstTextTrackSinkFactory} -{ -} - -std::unique_ptr -GenericPlayerTaskFactory::createAttachSamples(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const IMediaPipeline::MediaSegmentVector &mediaSegments) const -{ - return std::make_unique(context, m_gstWrapper, player, mediaSegments); -} - -std::unique_ptr -GenericPlayerTaskFactory::createAttachSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::unique_ptr &source) const -{ - return std::make_unique(context, m_gstWrapper, m_glibWrapper, - m_gstTextTrackSinkFactory, player, source); -} - -std::unique_ptr GenericPlayerTaskFactory::createDeepElementAdded(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - GstBin *pipeline, GstBin *bin, - GstElement *element) const -{ - return std::make_unique(context, player, m_gstWrapper, m_glibWrapper, pipeline, - bin, element); -} - -std::unique_ptr GenericPlayerTaskFactory::createEnoughData(GenericPlayerContext &context, GstAppSrc *src) const -{ - return std::make_unique(context, src); -} - -std::unique_ptr GenericPlayerTaskFactory::createEos(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type) const -{ - return std::make_unique(context, player, m_gstWrapper, type); -} - -std::unique_ptr GenericPlayerTaskFactory::createFinishSetupSource(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(context, player, m_client); -} - -std::unique_ptr GenericPlayerTaskFactory::createHandleBusMessage(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - GstMessage *message, - const IFlushWatcher &flushWatcher) const -{ - return std::make_unique(context, player, m_client, m_gstWrapper, m_glibWrapper, - message, flushWatcher); -} - -std::unique_ptr GenericPlayerTaskFactory::createNeedData(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - GstAppSrc *src) const -{ - return std::make_unique(context, player, m_client, src); -} - -std::unique_ptr GenericPlayerTaskFactory::createPause(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(context, player); -} - -std::unique_ptr GenericPlayerTaskFactory::createPlay(IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(player); -} - -std::unique_ptr GenericPlayerTaskFactory::createReadShmDataAndAttachSamples( - GenericPlayerContext &context, IGstGenericPlayerPrivate &player, const std::shared_ptr &dataReader) const -{ - return std::make_unique(context, m_gstWrapper, player, dataReader); -} - -std::unique_ptr -GenericPlayerTaskFactory::createRemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type) const -{ - return std::make_unique(context, player, m_client, m_gstWrapper, type); -} - -std::unique_ptr GenericPlayerTaskFactory::createReportPosition(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(context, m_client, m_gstWrapper, player); -} - -std::unique_ptr GenericPlayerTaskFactory::createCheckAudioUnderflow(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(context, player, m_client, m_gstWrapper); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetPlaybackRate(GenericPlayerContext &context, - double rate) const -{ - return std::make_unique(context, m_gstWrapper, m_glibWrapper, rate); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetPosition(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - std::int64_t position) const -{ - return std::make_unique(context, player, m_client, m_gstWrapper, position); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetupElement(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - GstElement *element) const -{ - return std::make_unique(context, m_gstWrapper, m_glibWrapper, player, element); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetupSource(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - GstElement *source) const -{ - return std::make_unique(context, player, source); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetVideoGeometry(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const Rectangle &rectangle) const -{ - return std::make_unique(context, player, rectangle); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetVolume(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - double targetVolume, uint32_t volumeDuration, - firebolt::rialto::EaseType easeType) const -{ - return std::make_unique(context, player, m_gstWrapper, m_glibWrapper, - m_rdkGstreamerUtilsWrapper, targetVolume, volumeDuration, - easeType); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetMute(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const MediaSourceType &mediaSourceType, - bool mute) const -{ - return std::make_unique(context, player, m_gstWrapper, m_glibWrapper, mediaSourceType, mute); -} - -std::unique_ptr -GenericPlayerTaskFactory::createSetTextTrackIdentifier(GenericPlayerContext &context, - const std::string &textTrackIdentifier) const -{ - return std::make_unique(context, m_glibWrapper, textTrackIdentifier); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetLowLatency(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - bool lowLatency) const -{ - return std::make_unique(context, player, lowLatency); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetSync(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, bool sync) const -{ - return std::make_unique(context, player, sync); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetSyncOff(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - bool syncOff) const -{ - return std::make_unique(context, player, syncOff); -} - -std::unique_ptr -GenericPlayerTaskFactory::createSetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - int32_t streamSyncMode) const -{ - return std::make_unique(context, player, type, streamSyncMode); -} - -std::unique_ptr GenericPlayerTaskFactory::createShutdown(IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(player); -} - -std::unique_ptr GenericPlayerTaskFactory::createStop(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(context, player); -} - -std::unique_ptr GenericPlayerTaskFactory::createUnderflow(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - bool underflowEnabled, - MediaSourceType sourceType) const -{ - return std::make_unique(context, player, m_client, underflowEnabled, sourceType); -} - -std::unique_ptr GenericPlayerTaskFactory::createUpdatePlaybackGroup(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - GstElement *typefind, - const GstCaps *caps) const -{ - return std::make_unique(context, player, m_gstWrapper, m_glibWrapper, typefind, - caps); -} - -std::unique_ptr GenericPlayerTaskFactory::createRenderFrame(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(context, player); -} - -std::unique_ptr GenericPlayerTaskFactory::createPing(std::unique_ptr &&heartbeatHandler) const -{ - return std::make_unique(std::move(heartbeatHandler)); -} - -std::unique_ptr GenericPlayerTaskFactory::createFlush(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - bool resetTime) const -{ - return std::make_unique(context, player, m_client, m_gstWrapper, type, resetTime); -} - -std::unique_ptr -GenericPlayerTaskFactory::createSetSourcePosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, std::int64_t position, - bool resetTime, double appliedRate, uint64_t stopPosition) const -{ - return std::make_unique(context, player, m_client, m_glibWrapper, type, position, - resetTime, appliedRate, stopPosition); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetSubtitleOffset(GenericPlayerContext &context, - std::int64_t position) const -{ - return std::make_unique(context, m_glibWrapper, position); -} - -std::unique_ptr GenericPlayerTaskFactory::createProcessAudioGap(GenericPlayerContext &context, - std::int64_t position, - std::uint32_t duration, - std::int64_t discontinuityGap, - bool audioAac) const -{ - return std::make_unique(context, m_gstWrapper, m_glibWrapper, - m_rdkGstreamerUtilsWrapper, position, duration, - discontinuityGap, audioAac); -} - -std::unique_ptr -GenericPlayerTaskFactory::createSetImmediateOutput(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const firebolt::rialto::MediaSourceType &type, - bool immediateOutput) const -{ - return std::make_unique(context, player, type, immediateOutput); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetBufferingLimit(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - std::uint32_t limit) const -{ - return std::make_unique(context, player, limit); -} - -std::unique_ptr GenericPlayerTaskFactory::createSetUseBuffering(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player, - bool useBuffering) const -{ - return std::make_unique(context, player, useBuffering); -} - -std::unique_ptr -GenericPlayerTaskFactory::createSwitchSource(IGstGenericPlayerPrivate &player, - const std::unique_ptr &source) const -{ - return std::make_unique(player, source); -} - -std::unique_ptr GenericPlayerTaskFactory::createSynchroniseSubtitleClock(GenericPlayerContext &context, - IGstGenericPlayerPrivate &player) const -{ - return std::make_unique(context, player, m_gstWrapper, m_glibWrapper); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp deleted file mode 100644 index 3905becb1..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/HandleBusMessage.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/HandleBusMessage.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -HandleBusMessage::HandleBusMessage(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - IGstGenericPlayerClient *client, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - GstMessage *message, const IFlushWatcher &flushWatcher) - : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, - m_glibWrapper{glibWrapper}, m_message{message}, m_flushWatcher{flushWatcher}, - m_isFlushOngoingDuringCreation{flushWatcher.isFlushOngoing()}, - m_isAsyncFlushOngoingDuringCreation{flushWatcher.isAsyncFlushOngoing()} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing HandleBusMessage"); -} - -HandleBusMessage::~HandleBusMessage() -{ - RIALTO_SERVER_LOG_DEBUG("HandleBusMessage finished"); -} - -void HandleBusMessage::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing HandleBusMessage"); - switch (GST_MESSAGE_TYPE(m_message)) - { - case GST_MESSAGE_STATE_CHANGED: - { - if (m_context.pipeline && GST_MESSAGE_SRC(m_message) == GST_OBJECT(m_context.pipeline)) - { - GstState oldState, newState, pending; - m_gstWrapper->gstMessageParseStateChanged(m_message, &oldState, &newState, &pending); - RIALTO_SERVER_LOG_MIL("State changed (old: %s, new: %s, pending: %s)", - m_gstWrapper->gstElementStateGetName(oldState), - m_gstWrapper->gstElementStateGetName(newState), - m_gstWrapper->gstElementStateGetName(pending)); - - if (!m_gstPlayerClient) - { - break; - } - switch (newState) - { - case GST_STATE_NULL: - { - m_gstPlayerClient->notifyPlaybackState(PlaybackState::STOPPED); - break; - } - case GST_STATE_PAUSED: - { - if (pending != GST_STATE_PAUSED) - { - // If async flush was requested before HandleBusMessage task creation (but it was not executed yet) - // or if async flush was created after HandleBusMessage task creation (but before its execution) - // we can't report playback state, because async flush causes state loss - reported state is probably invalid. - if (m_isAsyncFlushOngoingDuringCreation || m_flushWatcher.isAsyncFlushOngoing()) - { - RIALTO_SERVER_LOG_WARN("Skip PAUSED notification - flush is ongoing"); - break; - } - // newState==GST_STATE_PAUSED, pending==GST_STATE_PAUSED state transition is received as a result of - // waiting for preroll after seek. - // Subsequent newState==GST_STATE_PAUSED, pending!=GST_STATE_PAUSED transition will - // indicate that the pipeline is prerolled and it reached GST_STATE_PAUSED state after seek. - m_gstPlayerClient->notifyPlaybackState(PlaybackState::PAUSED); - } - if (m_player.hasSourceType(MediaSourceType::SUBTITLE)) - { - m_player.stopSubtitleClockResyncTimer(); - } - break; - } - case GST_STATE_PLAYING: - { - // If async flush was requested before HandleBusMessage task creation (but it was not executed yet) - // or if async flush was created after HandleBusMessage task creation (but before its execution) - // we can't report playback state, because async flush causes state loss - reported state is probably invalid. - if (m_isAsyncFlushOngoingDuringCreation || m_flushWatcher.isAsyncFlushOngoing()) - { - RIALTO_SERVER_LOG_WARN("Skip PLAYING notification - flush is ongoing"); - break; - } - - m_context.isPlaying = true; - m_gstPlayerClient->notifyPlaybackState(PlaybackState::PLAYING); - - if (m_context.pendingPlaybackRate != kNoPendingPlaybackRate) - { - m_player.setPendingPlaybackRate(); - } - m_player.startPositionReportingAndCheckAudioUnderflowTimer(); - if (m_player.hasSourceType(MediaSourceType::SUBTITLE)) - { - m_player.startSubtitleClockResyncTimer(); - } - break; - } - case GST_STATE_VOID_PENDING: - case GST_STATE_READY: - { - break; - } - } - std::string filename = std::string(m_gstWrapper->gstElementStateGetName(oldState)) + "-" + - std::string(m_gstWrapper->gstElementStateGetName(newState)); - m_gstWrapper->gstDebugBinToDotFileWithTs(GST_BIN(m_context.pipeline), GST_DEBUG_GRAPH_SHOW_ALL, - filename.c_str()); - } - break; - } - case GST_MESSAGE_EOS: - { - // If flush was requested before HandleBusMessage task creation (but it was not executed yet) - // or if flush was created after HandleBusMessage task creation (but before its execution) - // we can't report EOS, because flush clears EOS. - if (m_isFlushOngoingDuringCreation || m_flushWatcher.isFlushOngoing()) - { - RIALTO_SERVER_LOG_WARN("Skip EOS notification - flush is ongoing"); - break; - } - if (m_context.pipeline && GST_MESSAGE_SRC(m_message) == GST_OBJECT(m_context.pipeline)) - { - RIALTO_SERVER_LOG_MIL("End of stream reached."); - if (!m_context.eosNotified && m_gstPlayerClient) - { - m_gstPlayerClient->notifyPlaybackState(PlaybackState::END_OF_STREAM); - m_context.eosNotified = true; - } - } - break; - } - case GST_MESSAGE_QOS: - { - GstFormat format; - gboolean isLive = FALSE; - guint64 runningTime = 0; - guint64 streamTime = 0; - guint64 timestamp = 0; - guint64 duration = 0; - guint64 dropped = 0; - guint64 processed = 0; - - m_gstWrapper->gstMessageParseQos(m_message, &isLive, &runningTime, &streamTime, ×tamp, &duration); - m_gstWrapper->gstMessageParseQosStats(m_message, &format, &processed, &dropped); - - if (GST_FORMAT_BUFFERS == format || GST_FORMAT_DEFAULT == format) - { - RIALTO_SERVER_LOG_INFO("QOS message: runningTime %" G_GUINT64_FORMAT ", streamTime %" G_GUINT64_FORMAT - ", timestamp %" G_GUINT64_FORMAT ", duration %" G_GUINT64_FORMAT - ", format %u, processed %" G_GUINT64_FORMAT ", dropped %" G_GUINT64_FORMAT, - runningTime, streamTime, timestamp, duration, format, processed, dropped); - - if (m_gstPlayerClient) - { - firebolt::rialto::QosInfo qosInfo = {processed, dropped}; - const gchar *klass; - klass = m_gstWrapper->gstElementClassGetMetadata(GST_ELEMENT_GET_CLASS(GST_MESSAGE_SRC(m_message)), - GST_ELEMENT_METADATA_KLASS); - - if (g_strrstr(klass, "Video")) - { - m_gstPlayerClient->notifyQos(firebolt::rialto::MediaSourceType::VIDEO, qosInfo); - } - else if (g_strrstr(klass, "Audio")) - { - m_gstPlayerClient->notifyQos(firebolt::rialto::MediaSourceType::AUDIO, qosInfo); - } - else - { - RIALTO_SERVER_LOG_WARN("Unknown source type for class '%s', ignoring QOS Message", klass); - } - } - } - else - { - RIALTO_SERVER_LOG_WARN("Received a QOS_MESSAGE with unhandled format %s", - m_gstWrapper->gstFormatGetName(format)); - } - break; - } - case GST_MESSAGE_ERROR: - { - GError *err = nullptr; - gchar *debug = nullptr; - m_gstWrapper->gstMessageParseError(m_message, &err, &debug); - - if ((err->domain == GST_STREAM_ERROR) && (allSourcesEos())) - { - RIALTO_SERVER_LOG_WARN("Got stream error from %s. But all streams are ended, so reporting EOS. Error code " - "%d: %s " - "(%s).", - GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), err->code, err->message, debug); - if (!m_context.eosNotified && m_gstPlayerClient) - { - m_gstPlayerClient->notifyPlaybackState(PlaybackState::END_OF_STREAM); - m_context.eosNotified = true; - } - } - else - { - RIALTO_SERVER_LOG_ERROR("Error from %s - %d: %s (%s)", GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), - err->code, err->message, debug); - m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); - } - - m_glibWrapper->gFree(debug); - m_glibWrapper->gErrorFree(err); - break; - } - case GST_MESSAGE_WARNING: - { - PlaybackError rialtoError = PlaybackError::UNKNOWN; - GError *err = nullptr; - gchar *debug = nullptr; - m_gstWrapper->gstMessageParseWarning(m_message, &err, &debug); - - if ((err->domain == GST_STREAM_ERROR) && (err->code == GST_STREAM_ERROR_DECRYPT)) - { - RIALTO_SERVER_LOG_WARN("Decrypt error %s - %d: %s (%s)", GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), - err->code, err->message, debug); - rialtoError = PlaybackError::DECRYPTION; - } - else - { - RIALTO_SERVER_LOG_WARN("Unknown warning, ignoring %s - %d: %s (%s)", - GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), err->code, err->message, debug); - } - - if ((PlaybackError::UNKNOWN != rialtoError) && (m_gstPlayerClient)) - { - const gchar *kName = GST_ELEMENT_NAME(GST_ELEMENT(GST_MESSAGE_SRC(m_message))); - if (g_strrstr(kName, "video")) - { - m_gstPlayerClient->notifyPlaybackError(firebolt::rialto::MediaSourceType::VIDEO, - PlaybackError::DECRYPTION); - } - else if (g_strrstr(kName, "audio")) - { - m_gstPlayerClient->notifyPlaybackError(firebolt::rialto::MediaSourceType::AUDIO, - PlaybackError::DECRYPTION); - } - else - { - RIALTO_SERVER_LOG_WARN("Unknown source type for element '%s', not propagating error", kName); - } - } - - m_glibWrapper->gFree(debug); - m_glibWrapper->gErrorFree(err); - break; - } - default: - break; - } - - m_gstWrapper->gstMessageUnref(m_message); -} - -bool HandleBusMessage::allSourcesEos() const -{ - for (const auto &streamInfo : m_context.streamInfo) - { - const auto eosInfoIt = m_context.endOfStreamInfo.find(streamInfo.first); - if (eosInfoIt == m_context.endOfStreamInfo.end() || eosInfoIt->second != EosState::SET) - { - return false; - } - } - return true; -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/NeedData.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/NeedData.cpp deleted file mode 100644 index 5f0a6b5b1..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/NeedData.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/NeedData.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -NeedData::NeedData(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - GstAppSrc *src) - : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_src{src} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing NeedData"); -} - -NeedData::~NeedData() -{ - RIALTO_SERVER_LOG_DEBUG("NeedData finished"); -} - -void NeedData::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing NeedData"); - - for (auto &elem : m_context.streamInfo) - { - firebolt::rialto::MediaSourceType sourceType = elem.first; - if (elem.second.appSrc == GST_ELEMENT(m_src)) - { - RIALTO_SERVER_LOG_DEBUG("%s source needs data", common::convertMediaSourceType(sourceType)); - - elem.second.isDataNeeded = true; - - if (!elem.second.buffers.empty()) - { - RIALTO_SERVER_LOG_INFO("Attaching cached data for %s", common::convertMediaSourceType(sourceType)); - m_player.attachData(sourceType); - } - - if (m_gstPlayerClient && !elem.second.isNeedDataPending) - { - if (sourceType == MediaSourceType::AUDIO && m_context.audioSourceRemoved) - { - RIALTO_SERVER_LOG_DEBUG("Audio source is removed, no need to request data"); - break; - } - elem.second.isNeedDataPending = m_gstPlayerClient->notifyNeedMediaData(sourceType); - } - break; - } - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Pause.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Pause.cpp deleted file mode 100644 index 79c9ad14c..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Pause.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Pause.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Pause::Pause(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) : m_context{context}, m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Pause"); -} - -Pause::~Pause() -{ - RIALTO_SERVER_LOG_DEBUG("Pause finished"); -} - -void Pause::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Pause"); - m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); - m_player.changePipelineState(GST_STATE_PAUSED); - m_context.isPlaying = false; - RIALTO_SERVER_LOG_MIL("State change to PAUSED requested"); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Ping.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Ping.cpp deleted file mode 100644 index 82a042b99..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Ping.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Ping.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Ping::Ping(std::unique_ptr &&heartbeatHandler) : m_heartbeatHandler{std::move(heartbeatHandler)} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Ping"); -} - -Ping::~Ping() -{ - RIALTO_SERVER_LOG_DEBUG("Ping finished"); - m_heartbeatHandler.reset(); -} - -void Ping::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Ping"); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Play.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Play.cpp deleted file mode 100644 index fc13e3c1e..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Play.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Play.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Play::Play(IGstGenericPlayerPrivate &player) : m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Play"); -} - -Play::~Play() -{ - RIALTO_SERVER_LOG_DEBUG("Play finished"); -} - -void Play::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Play"); - m_player.changePipelineState(GST_STATE_PLAYING); - RIALTO_SERVER_LOG_MIL("State change to PLAYING requested"); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ProcessAudioGap.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ProcessAudioGap.cpp deleted file mode 100644 index d4b79c451..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ProcessAudioGap.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ProcessAudioGap.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -ProcessAudioGap::ProcessAudioGap( - GenericPlayerContext &context, const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper, - const std::shared_ptr rdkGstreamerUtilsWrapper, - std::int64_t position, std::uint32_t duration, std::int64_t discontinuityGap, bool audioAac) - : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, - m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, m_position{position}, m_duration{duration}, - m_discontinuityGap{discontinuityGap}, m_audioAac{audioAac} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing ProcessAudioGap"); -} - -ProcessAudioGap::~ProcessAudioGap() -{ - RIALTO_SERVER_LOG_DEBUG("ProcessAudioGap finished"); -} - -void ProcessAudioGap::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing ProcessAudioGap"); - if (!m_context.pipeline) - { - RIALTO_SERVER_LOG_ERROR("Process audio gap failed - pipeline is null"); - return; - } - m_rdkGstreamerUtilsWrapper->processAudioGap(m_context.pipeline, m_position, m_duration, m_discontinuityGap, - m_audioAac); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp deleted file mode 100644 index a01d2e4eb..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReadShmDataAndAttachSamples.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/ReadShmDataAndAttachSamples.h" -#include "GenericPlayerContext.h" -#include "IDataReader.h" -#include "IGstGenericPlayerPrivate.h" -#include "IMediaPipeline.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -ReadShmDataAndAttachSamples::ReadShmDataAndAttachSamples( - GenericPlayerContext &context, const std::shared_ptr &gstWrapper, - IGstGenericPlayerPrivate &player, const std::shared_ptr &dataReader) - : m_context{context}, m_gstWrapper{gstWrapper}, m_player{player}, m_dataReader{dataReader} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing ReadShmDataAndAttachSamples"); -} - -ReadShmDataAndAttachSamples::~ReadShmDataAndAttachSamples() -{ - RIALTO_SERVER_LOG_DEBUG("ReadShmDataAndAttachSamples finished"); -} - -void ReadShmDataAndAttachSamples::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing ReadShmDataAndAttachSamples"); - // Read media segments from shared memory - IMediaPipeline::MediaSegmentVector mediaSegments = m_dataReader->readData(); - - for (const auto &mediaSegment : mediaSegments) - { - if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::UNKNOWN) - { - RIALTO_SERVER_LOG_WARN("Unknown media segment type"); - continue; - } - - GstBuffer *gstBuffer = m_player.createBuffer(*mediaSegment); - if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::VIDEO) - { - try - { - IMediaPipeline::MediaSegmentVideo &videoSegment = - dynamic_cast(*mediaSegment); - m_player.updateVideoCaps(videoSegment.getWidth(), videoSegment.getHeight(), videoSegment.getFrameRate(), - videoSegment.getCodecData()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to get the video segment, reason: %s", e.what()); - } - } - else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::AUDIO) - { - try - { - IMediaPipeline::MediaSegmentAudio &audioSegment = - dynamic_cast(*mediaSegment); - m_player.updateAudioCaps(audioSegment.getSampleRate(), audioSegment.getNumberOfChannels(), - audioSegment.getCodecData()); - m_player.addAudioClippingToBuffer(gstBuffer, audioSegment.getClippingStart(), - audioSegment.getClippingEnd()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to get the audio segment, reason: %s", e.what()); - } - } - else if (mediaSegment->getType() == firebolt::rialto::MediaSourceType::SUBTITLE) - { - if (mediaSegment->getDisplayOffset()) - { - GST_BUFFER_OFFSET(gstBuffer) = mediaSegment->getDisplayOffset().value(); - } - } - - attachData(mediaSegment->getType(), gstBuffer); - } - // All segments in vector have the same type - if (!mediaSegments.empty()) - { - const auto kMediaType{mediaSegments.front()->getType()}; - const auto kFirstTimestamp{mediaSegments.front()->getTimeStamp()}; - const auto kLastTimestamp{mediaSegments.back()->getTimeStamp()}; - RIALTO_SERVER_LOG_DEBUG("%s data received. First ts: %" GST_TIME_FORMAT " last ts: %" GST_TIME_FORMAT, - common::convertMediaSourceType(kMediaType), GST_TIME_ARGS(kFirstTimestamp), - GST_TIME_ARGS(kLastTimestamp)); - m_player.notifyNeedMediaData(kMediaType); - } -} - -void ReadShmDataAndAttachSamples::attachData(const firebolt::rialto::MediaSourceType mediaType, GstBuffer *buffer) const -{ - auto elem = m_context.streamInfo.find(mediaType); - if (elem != m_context.streamInfo.end()) - { - elem->second.buffers.push_back(buffer); - m_player.attachData(mediaType); - } - else - { - RIALTO_SERVER_LOG_WARN("Could not find stream info for %s", common::convertMediaSourceType(mediaType)); - m_gstWrapper->gstBufferUnref(buffer); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp deleted file mode 100644 index 7d9314df0..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RemoveSource.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/RemoveSource.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -RemoveSource::RemoveSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper, - const MediaSourceType &type) - : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_type{type} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing RemoveSource"); -} - -RemoveSource::~RemoveSource() -{ - RIALTO_SERVER_LOG_DEBUG("RemoveSource finished"); -} - -void RemoveSource::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing RemoveSource for %s source", common::convertMediaSourceType(m_type)); - if (MediaSourceType::AUDIO != m_type) - { - RIALTO_SERVER_LOG_DEBUG("RemoveSource not supported for type != AUDIO"); - return; - } - m_context.audioSourceRemoved = true; - m_gstPlayerClient->invalidateActiveRequests(m_type); - GstElement *source{nullptr}; - auto sourceElem = m_context.streamInfo.find(m_type); - if (sourceElem != m_context.streamInfo.end()) - { - source = sourceElem->second.appSrc; - } - if (!source) - { - RIALTO_SERVER_LOG_WARN("failed to flush - source is NULL"); - return; - } - sourceElem->second.buffers.clear(); - sourceElem->second.isDataNeeded = false; - sourceElem->second.isNeedDataPending = false; - m_player.clearNeedDataScheduled(GST_APP_SRC(sourceElem->second.appSrc)); - m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); - GstEvent *flushStart = m_gstWrapper->gstEventNewFlushStart(); - if (!m_gstWrapper->gstElementSendEvent(source, flushStart)) - { - RIALTO_SERVER_LOG_WARN("failed to send flush-start event"); - } - GstEvent *flushStop = m_gstWrapper->gstEventNewFlushStop(FALSE); - if (!m_gstWrapper->gstElementSendEvent(source, flushStop)) - { - RIALTO_SERVER_LOG_WARN("failed to send flush-stop event"); - } - - // Turn audio off, removing audio sink from playsink - m_player.setPlaybinFlags(false); - - RIALTO_SERVER_LOG_MIL("%s source removed", common::convertMediaSourceType(m_type)); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RenderFrame.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RenderFrame.cpp deleted file mode 100644 index 04b386e8e..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/RenderFrame.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "RenderFrame.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -RenderFrame::RenderFrame(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) - : m_context{context}, m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing RenderFrame"); -} - -RenderFrame::~RenderFrame() -{ - RIALTO_SERVER_LOG_DEBUG("RenderFrame finished"); -} - -void RenderFrame::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing RenderFrame"); - - m_context.pendingRenderFrame = true; - if (m_context.pipeline) - { - m_player.setRenderFrame(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReportPosition.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReportPosition.cpp deleted file mode 100644 index 2eb46d7c1..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/ReportPosition.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/ReportPosition.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -ReportPosition::ReportPosition(GenericPlayerContext &context, IGstGenericPlayerClient *client, - const std::shared_ptr &gstWrapper, - IGstGenericPlayerPrivate &player) - : m_context{context}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_player{player} -{ -} - -void ReportPosition::execute() const -{ - gint64 position = m_player.getPosition(m_context.pipeline); - if (position == -1) - { - RIALTO_SERVER_LOG_WARN("Getting the position failed"); - return; - } - - if (m_gstPlayerClient) - { - m_gstPlayerClient->notifyPosition(position); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetBufferingLimit.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetBufferingLimit.cpp deleted file mode 100644 index 92922aa5a..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetBufferingLimit.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetBufferingLimit.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetBufferingLimit::SetBufferingLimit(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, std::uint32_t limit) - : m_context{context}, m_player(player), m_limit{limit} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetBufferingLimit"); -} - -SetBufferingLimit::~SetBufferingLimit() -{ - RIALTO_SERVER_LOG_DEBUG("SetBufferingLimit finished"); -} - -void SetBufferingLimit::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetBufferingLimit"); - - m_context.pendingBufferingLimit = m_limit; - if (m_context.pipeline) - { - m_player.setBufferingLimit(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetImmediateOutput.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetImmediateOutput.cpp deleted file mode 100644 index 4bb34e834..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetImmediateOutput.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetImmediateOutput.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetImmediateOutput::SetImmediateOutput(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const MediaSourceType &type, bool immediateOutput) - : m_context{context}, m_player(player), m_type{type}, m_immediateOutput{immediateOutput} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetImmediateOutput"); -} - -SetImmediateOutput::~SetImmediateOutput() -{ - RIALTO_SERVER_LOG_DEBUG("SetImmediateOutput finished"); -} - -void SetImmediateOutput::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetImmediateOutput for %s source", common::convertMediaSourceType(m_type)); - - if (m_type == MediaSourceType::VIDEO) - { - m_context.pendingImmediateOutputForVideo = m_immediateOutput; - } - else - { - RIALTO_SERVER_LOG_ERROR("SetImmediateOutput not currently supported for non-video"); - } - - if (m_context.pipeline) - { - m_player.setImmediateOutput(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetLowLatency.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetLowLatency.cpp deleted file mode 100644 index 85764237e..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetLowLatency.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetLowLatency.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetLowLatency::SetLowLatency(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool lowLatency) - : m_context(context), m_player(player), m_lowLatency{lowLatency} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetLowLatency"); -} - -SetLowLatency::~SetLowLatency() -{ - RIALTO_SERVER_LOG_DEBUG("SetLowLatency finished"); -} - -void SetLowLatency::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetLowLatency"); - - m_context.pendingLowLatency = m_lowLatency; - if (m_context.pipeline) - { - m_player.setLowLatency(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetMute.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetMute.cpp deleted file mode 100644 index 36c609b6f..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetMute.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SetMute.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -SetMute::SetMute(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const MediaSourceType &mediaSourceType, bool mute) - : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, - m_mediaSourceType{mediaSourceType}, m_mute{mute} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetMute"); -} - -SetMute::~SetMute() -{ - RIALTO_SERVER_LOG_DEBUG("SetMute finished"); -} - -void SetMute::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetMute"); - if (m_mediaSourceType == MediaSourceType::SUBTITLE) - { - if (!m_context.subtitleSink) - { - RIALTO_SERVER_LOG_ERROR("There is no subtitle sink"); - return; - } - m_glibWrapper->gObjectSet(m_context.subtitleSink, "mute", m_mute, nullptr); - } - else if (m_mediaSourceType == MediaSourceType::AUDIO) - { - if (!m_context.pipeline) - { - RIALTO_SERVER_LOG_ERROR("Setting mute failed. Pipeline is NULL"); - return; - } - m_gstWrapper->gstStreamVolumeSetMute(GST_STREAM_VOLUME(m_context.pipeline), m_mute); - } - else if (m_mediaSourceType == MediaSourceType::VIDEO) - { - m_context.pendingShowVideoWindow = !m_mute; - m_player.setShowVideoWindow(); - } - else - { - RIALTO_SERVER_LOG_ERROR("Setting mute for type %s unsupported", - common::convertMediaSourceType(m_mediaSourceType)); - return; - } - RIALTO_SERVER_LOG_MIL("%s source %s", common::convertMediaSourceType(m_mediaSourceType), - (m_mute ? "muted" : "unmuted")); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp deleted file mode 100644 index 5f0c6de85..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPlaybackRate.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SetPlaybackRate.h" -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include - -namespace -{ -const char kCustomInstantRateChangeEventName[] = "custom-instant-rate-change"; -} // namespace - -namespace firebolt::rialto::server::tasks::generic -{ -SetPlaybackRate::SetPlaybackRate(GenericPlayerContext &context, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, double rate) - : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_rate{rate} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetPlaybackRate"); -} - -SetPlaybackRate::~SetPlaybackRate() -{ - RIALTO_SERVER_LOG_DEBUG("SetPlaybackRate finished"); -} - -void SetPlaybackRate::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetPlaybackRate"); - if (m_context.playbackRate == m_rate) - { - RIALTO_SERVER_LOG_DEBUG("No need to change playback rate - it is already %lf", m_rate); - return; - } - - if (!m_context.pipeline) - { - RIALTO_SERVER_LOG_INFO("Postponing set playback rate to %lf. Pipeline is NULL", m_rate); - m_context.pendingPlaybackRate = m_rate; - return; - } - - if (GST_STATE(m_context.pipeline) < GST_STATE_PLAYING) - { - RIALTO_SERVER_LOG_INFO("Postponing set playback rate to %lf. Pipeline state is below PLAYING", m_rate); - m_context.pendingPlaybackRate = m_rate; - return; - } - m_context.pendingPlaybackRate = kNoPendingPlaybackRate; - - GstElement *audioSink{nullptr}; - gboolean success{FALSE}; - m_glibWrapper->gObjectGet(m_context.pipeline, "audio-sink", &audioSink, nullptr); - if (audioSink && m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(audioSink), "amlhalasink")) - { - GstSegment *segment{m_gstWrapper->gstSegmentNew()}; - m_gstWrapper->gstSegmentInit(segment, GST_FORMAT_TIME); - segment->rate = m_rate; - segment->start = GST_CLOCK_TIME_NONE; - segment->position = GST_CLOCK_TIME_NONE; - success = m_gstWrapper->gstPadSendEvent(GST_BASE_SINK_PAD(audioSink), m_gstWrapper->gstEventNewSegment(segment)); - RIALTO_SERVER_LOG_DEBUG("Sent new segment, success = %s", success ? "true" : "false"); - m_gstWrapper->gstSegmentFree(segment); - } - else - { - GstStructure *structure{ - m_gstWrapper->gstStructureNew(kCustomInstantRateChangeEventName, "rate", G_TYPE_DOUBLE, m_rate, NULL)}; - success = m_gstWrapper->gstElementSendEvent(m_context.pipeline, - m_gstWrapper->gstEventNewCustom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, - structure)); - RIALTO_SERVER_LOG_DEBUG("Sent new event, success = %s", success ? "true" : "false"); - } - - if (success) - { - RIALTO_SERVER_LOG_MIL("Playback rate set to: %lf", m_rate); - m_context.playbackRate = m_rate; - } - - if (audioSink) - { - m_glibWrapper->gObjectUnref(audioSink); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPosition.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPosition.cpp deleted file mode 100644 index 0ee4cb320..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetPosition.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SetPosition.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerClient.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include "tasks/generic/NeedData.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetPosition::SetPosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - std::shared_ptr gstWrapper, std::int64_t position) - : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, m_position{position} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetPosition"); -} - -SetPosition::~SetPosition() -{ - RIALTO_SERVER_LOG_DEBUG("SetPosition finished"); -} - -void SetPosition::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetPosition"); - if (!m_gstPlayerClient) - { - RIALTO_SERVER_LOG_ERROR("Seek failed - GstPlayerClient is NULL"); - return; - } - m_gstPlayerClient->notifyPlaybackState(PlaybackState::SEEKING); - - // Stop sending new NeedMediaData requests - for (auto &elem : m_context.streamInfo) - { - StreamInfo &streamInfo = elem.second; - streamInfo.isDataNeeded = false; - streamInfo.isNeedDataPending = false; - m_player.clearNeedDataScheduled(GST_APP_SRC(streamInfo.appSrc)); - - // Clear buffered samples for player session - for (auto &buffer : streamInfo.buffers) - { - m_gstWrapper->gstBufferUnref(buffer); - } - - streamInfo.buffers.clear(); - } - - // Clear local cache of any active data requests for player session - m_gstPlayerClient->clearActiveRequestsCache(); - m_context.lastAudioSampleTimestamps = m_position; - - if (!m_context.pipeline) - { - RIALTO_SERVER_LOG_ERROR("Seek failed - pipeline is null"); - m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); - return; - } - if (!m_gstWrapper->gstElementSeek(m_context.pipeline, m_context.playbackRate, GST_FORMAT_TIME, - static_cast(GST_SEEK_FLAG_FLUSH), GST_SEEK_TYPE_SET, m_position, - GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) - { - RIALTO_SERVER_LOG_ERROR("Seek failed - gstreamer error"); - m_gstPlayerClient->notifyPlaybackState(PlaybackState::FAILURE); - return; - } - - RIALTO_SERVER_LOG_MIL("Pipeline seek to: %" GST_TIME_FORMAT, GST_TIME_ARGS(m_position)); - - // Reset Eos info - m_context.endOfStreamInfo.clear(); - m_context.eosNotified = false; - - m_gstPlayerClient->notifyPlaybackState(PlaybackState::SEEK_DONE); - - // Trigger NeedMediaData for all attached sources - for (const auto &streamInfo : m_context.streamInfo) - { - if (streamInfo.second.appSrc) - { - NeedData task{m_context, m_player, m_gstPlayerClient, GST_APP_SRC(streamInfo.second.appSrc)}; - task.execute(); - } - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSourcePosition.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSourcePosition.cpp deleted file mode 100644 index 2e2dffb57..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSourcePosition.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetSourcePosition.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" -#include "tasks/generic/NeedData.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetSourcePosition::SetSourcePosition(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - IGstGenericPlayerClient *client, - const std::shared_ptr &glibWrapper, - const MediaSourceType &type, std::int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) - : m_context{context}, m_player(player), m_gstPlayerClient{client}, m_glibWrapper{glibWrapper}, m_type{type}, - m_position{position}, m_resetTime{resetTime}, m_appliedRate{appliedRate}, m_stopPosition{stopPosition} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetSourcePosition"); -} - -SetSourcePosition::~SetSourcePosition() -{ - RIALTO_SERVER_LOG_DEBUG("SetSourcePosition finished"); -} - -void SetSourcePosition::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetSourcePosition for %s source", common::convertMediaSourceType(m_type)); - - if (MediaSourceType::UNKNOWN == m_type) - { - RIALTO_SERVER_LOG_WARN("failed to set source position - source type is unknown"); - return; - } - - // Get source first - GstElement *source{nullptr}; - auto sourceElem = m_context.streamInfo.find(m_type); - if (sourceElem != m_context.streamInfo.end()) - { - source = sourceElem->second.appSrc; - } - if (!source) - { - RIALTO_SERVER_LOG_WARN("failed to set source position - %s source is NULL", - common::convertMediaSourceType(m_type)); - return; - } - - if (MediaSourceType::VIDEO == m_type || MediaSourceType::AUDIO == m_type) - { - m_context.initialPositions[source].emplace_back( - SegmentData{m_position, m_resetTime, m_appliedRate, m_stopPosition}); - } - else if (MediaSourceType::SUBTITLE == m_type) - { - setSubtitlePosition(source); - } - - if (m_context.setupSourceFinished) - { - // Reset Eos info - m_context.endOfStreamInfo.erase(m_type); - m_context.eosNotified = false; - - // Trigger NeedData for source - NeedData task{m_context, m_player, m_gstPlayerClient, GST_APP_SRC(source)}; - task.execute(); - } -} - -void SetSourcePosition::setSubtitlePosition(GstElement *source) const -{ - // in case of subtitles, all data might be already in the sink and we might not get any data anymore, - // so set position here and to not depend on any following buffers - if (m_context.setupSourceFinished) - { - m_glibWrapper->gObjectSet(m_context.subtitleSink, "position", static_cast(m_position), nullptr); - } - else - { - m_context.initialPositions[source].emplace_back( - SegmentData{m_position, m_resetTime, m_appliedRate, m_stopPosition}); - } -} - -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetStreamSyncMode.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetStreamSyncMode.cpp deleted file mode 100644 index 7dd79017e..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetStreamSyncMode.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetStreamSyncMode.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetStreamSyncMode::SetStreamSyncMode(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const MediaSourceType &type, int32_t streamSyncMode) - : m_context(context), m_player(player), m_type{type}, m_streamSyncMode{streamSyncMode} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetStreamSyncMode"); -} - -SetStreamSyncMode::~SetStreamSyncMode() -{ - RIALTO_SERVER_LOG_DEBUG("SetStreamSyncMode finished"); -} - -void SetStreamSyncMode::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetStreamSyncMode"); - - m_context.pendingStreamSyncMode.emplace(m_type, m_streamSyncMode); - if (m_context.pipeline) - { - m_player.setStreamSyncMode(m_type); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSubtitleOffset.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSubtitleOffset.cpp deleted file mode 100644 index 9023fff87..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSubtitleOffset.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetSubtitleOffset.h" -#include "RialtoServerLogging.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -SetSubtitleOffset::SetSubtitleOffset(GenericPlayerContext &context, - const std::shared_ptr &glibWrapper, std::int64_t position) - : m_context{context}, m_glibWrapper{glibWrapper}, m_position{position} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetSubtitleOffset"); -} - -SetSubtitleOffset::~SetSubtitleOffset() -{ - RIALTO_SERVER_LOG_DEBUG("SetSubtitleOffset finished"); -} - -void SetSubtitleOffset::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetSubtitleOffset"); - - if (m_context.subtitleSink) - { - RIALTO_SERVER_LOG_DEBUG("Setting subtitle offset to %" PRId64 " nanoseconds", m_position); - m_glibWrapper->gObjectSet(m_context.subtitleSink, "offset", static_cast(m_position), nullptr); - } - else - { - RIALTO_SERVER_LOG_WARN("Failed to set subtitle offset - subtitle sink is NULL"); - } -} - -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSync.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSync.cpp deleted file mode 100644 index 40c0cbf74..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSync.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetSync.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetSync::SetSync(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool sync) - : m_context(context), m_player(player), m_sync{sync} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetSync"); -} - -SetSync::~SetSync() -{ - RIALTO_SERVER_LOG_DEBUG("SetSync finished"); -} - -void SetSync::execute() const -{ - m_context.pendingSync = m_sync; - if (m_context.pipeline) - { - m_player.setSync(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSyncOff.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSyncOff.cpp deleted file mode 100644 index 45cf05107..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetSyncOff.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetSyncOff.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetSyncOff::SetSyncOff(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool syncOff) - : m_context(context), m_player(player), m_syncOff{syncOff} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetSyncOff"); -} - -SetSyncOff::~SetSyncOff() -{ - RIALTO_SERVER_LOG_DEBUG("SetSyncOff finished"); -} - -void SetSyncOff::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetSyncOff"); - - m_context.pendingSyncOff = m_syncOff; - if (m_context.pipeline) - { - m_player.setSyncOff(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetTextTrackIdentifier.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetTextTrackIdentifier.cpp deleted file mode 100644 index e58c93430..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetTextTrackIdentifier.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SetTextTrackIdentifier.h" -#include "RialtoServerLogging.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -SetTextTrackIdentifier::SetTextTrackIdentifier(GenericPlayerContext &context, - std::shared_ptr glibWrapper, - const std::string &textTrackIdentifier) - : m_context{context}, m_glibWrapper{glibWrapper}, m_textTrackIdentifier{textTrackIdentifier} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetTextTrackIdentifier"); -} - -SetTextTrackIdentifier::~SetTextTrackIdentifier() -{ - RIALTO_SERVER_LOG_DEBUG("SetTextTrackIdentifier finished"); -} - -void SetTextTrackIdentifier::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetTextTrackIdentifier"); - - if (!m_context.subtitleSink) - { - RIALTO_SERVER_LOG_ERROR("There is no subtitle sink"); - return; - } - - m_glibWrapper->gObjectSet(m_context.subtitleSink, "text-track-identifier", m_textTrackIdentifier.c_str(), nullptr); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetUseBuffering.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetUseBuffering.cpp deleted file mode 100644 index 21003aad6..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetUseBuffering.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetUseBuffering.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetUseBuffering::SetUseBuffering(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, bool useBuffering) - : m_context{context}, m_player(player), m_useBuffering{useBuffering} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetUseBuffering"); -} - -SetUseBuffering::~SetUseBuffering() -{ - RIALTO_SERVER_LOG_DEBUG("SetUseBuffering finished"); -} - -void SetUseBuffering::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetUseBuffering"); - - m_context.pendingUseBuffering = m_useBuffering; - if (m_context.pipeline) - { - m_player.setUseBuffering(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVideoGeometry.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVideoGeometry.cpp deleted file mode 100644 index 6e4ae2b92..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVideoGeometry.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SetVideoGeometry.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetVideoGeometry::SetVideoGeometry(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const Rectangle &rectangle) - : m_context{context}, m_player{player}, m_rectangle{rectangle} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetVideoGeometry"); -} - -SetVideoGeometry::~SetVideoGeometry() -{ - RIALTO_SERVER_LOG_DEBUG("SetVideoGeometry finished"); -} - -void SetVideoGeometry::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetVideoGeometry"); - m_context.pendingGeometry = m_rectangle; - if (m_context.pipeline) - { - m_player.setVideoSinkRectangle(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVolume.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVolume.cpp deleted file mode 100644 index dbe8a9d06..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetVolume.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SetVolume.h" -#include "IRdkGstreamerUtilsWrapper.h" -#include "RialtoServerLogging.h" -#include -#include -#include - -namespace firebolt::rialto::server::tasks::generic -{ -SetVolume::SetVolume(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - std::shared_ptr rdkGstreamerUtilsWrapper, - double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType) - : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, - m_rdkGstreamerUtilsWrapper{rdkGstreamerUtilsWrapper}, m_targetVolume{targetVolume}, - m_volumeDuration{volumeDuration}, m_easeType{easeType} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetVolume"); -} - -SetVolume::~SetVolume() -{ - RIALTO_SERVER_LOG_DEBUG("SetVolume finished"); -} - -firebolt::rialto::wrappers::rgu_Ease convertEaseTypeToRguEase(EaseType easeType) -{ - switch (easeType) - { - case EaseType::EASE_LINEAR: - return firebolt::rialto::wrappers::rgu_Ease::EaseLinear; - case EaseType::EASE_IN_CUBIC: - return firebolt::rialto::wrappers::rgu_Ease::EaseInCubic; - case EaseType::EASE_OUT_CUBIC: - return firebolt::rialto::wrappers::rgu_Ease::EaseOutCubic; - default: - RIALTO_SERVER_LOG_ERROR("Unknown EaseType, defaulting to EaseLinear"); - return firebolt::rialto::wrappers::rgu_Ease::EaseLinear; - } -} - -void SetVolume::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetVolume"); - - if (!m_context.pipeline) - { - RIALTO_SERVER_LOG_ERROR("Setting volume failed. Pipeline is NULL"); - return; - } - bool isImmediateVolumeChange = (m_volumeDuration == 0); - GstElement *audioSink = m_player.getSink(firebolt::rialto::MediaSourceType::AUDIO); - - if (isImmediateVolumeChange) - { - RIALTO_SERVER_LOG_DEBUG("Immediate volume change, setting volume directly"); - m_gstWrapper->gstStreamVolumeSetVolume(GST_STREAM_VOLUME(m_context.pipeline), GST_STREAM_VOLUME_FORMAT_LINEAR, - m_targetVolume); - } - else if (audioSink && m_glibWrapper->gObjectClassFindProperty(G_OBJECT_GET_CLASS(audioSink), "audio-fade")) - { - gchar fadeStr[32]; - uint32_t scaledTarget = trunc(100 * m_targetVolume); - std::string easeString = "L"; - - switch (m_easeType) - { - default: - case firebolt::rialto::EaseType::EASE_LINEAR: - easeString = "L"; - break; - case firebolt::rialto::EaseType::EASE_IN_CUBIC: - easeString = "I"; - break; - case firebolt::rialto::EaseType::EASE_OUT_CUBIC: - easeString = "O"; - break; - } - - snprintf(reinterpret_cast(fadeStr), sizeof(fadeStr), "%u,%u,%s", scaledTarget, m_volumeDuration, - easeString.c_str()); - RIALTO_SERVER_LOG_DEBUG("Fade String: %s", fadeStr); - - m_glibWrapper->gObjectSet(audioSink, "audio-fade", fadeStr, nullptr); - m_context.audioFadeEnabled = true; - } - else if (m_rdkGstreamerUtilsWrapper->isSocAudioFadeSupported()) - { - RIALTO_SERVER_LOG_DEBUG("SOC audio fading is supported, applying SOC audio fade"); - auto rguEaseType = convertEaseTypeToRguEase(m_easeType); - m_rdkGstreamerUtilsWrapper->doAudioEasingonSoc(m_targetVolume, m_volumeDuration, rguEaseType); - m_context.audioFadeEnabled = true; - } - else - { - RIALTO_SERVER_LOG_WARN("No audio-fade property found in audio sink or SOC"); - } - - if (audioSink) - m_gstWrapper->gstObjectUnref(GST_OBJECT(audioSink)); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupElement.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupElement.cpp deleted file mode 100644 index 5139fd220..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupElement.cpp +++ /dev/null @@ -1,325 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SetupElement.h" -#include "GenericPlayerContext.h" -#include "IGlibWrapper.h" -#include "IGstGenericPlayerPrivate.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include "Utils.h" - -namespace -{ -/** - * @brief Callback for audio underflow event from sink. Called by the Gstreamer thread. - * - * @param[in] object : the object that emitted the signal - * @param[in] fifoDepth : the fifo depth (may be 0) - * @param[in] queueDepth : the queue depth (may be NULL) - * @param[in] self : The pointer to IGstGenericPlayerPrivate - * - * @retval true if the handling of the message is successful, false otherwise. - */ -void audioUnderflowCallback(GstElement *object, guint fifoDepth, gpointer queueDepth, gpointer self) -{ - firebolt::rialto::server::IGstGenericPlayerPrivate *player = - static_cast(self); - player->scheduleAudioUnderflow(); -} - -/** - * @brief Callback for video underflow event from sink. Called by the Gstreamer thread. - * - * @param[in] object : the object that emitted the signal - * @param[in] fifoDepth : the fifo depth (may be 0) - * @param[in] queueDepth : the queue depth (may be NULL) - * @param[in] self : The pointer to IGstGenericPlayerPrivate - * - * @retval true if the handling of the message is successful, false otherwise. - */ -void videoUnderflowCallback(GstElement *object, guint fifoDepth, gpointer queueDepth, gpointer self) -{ - firebolt::rialto::server::IGstGenericPlayerPrivate *player = - static_cast(self); - player->scheduleVideoUnderflow(); -} - -/** - * @brief Callback for a autovideosink when a child has been added to the sink. - * - * @param[in] obj : the parent element (autovideosink) - * @param[in] object : the child element - * @param[in] name : the name of the child element - * @param[in] self : The pointer to IGstGenericPlayerPrivate - */ -void autoVideoSinkChildAddedCallback(GstChildProxy *obj, GObject *object, gchar *name, gpointer self) -{ - RIALTO_SERVER_LOG_DEBUG("AutoVideoSink added element %s", name); - firebolt::rialto::server::IGstGenericPlayerPrivate *player = - static_cast(self); - player->addAutoVideoSinkChild(object); -} - -/** - * @brief Callback for a autoaudiosink when a child has been added to the sink. - * - * @param[in] obj : the parent element (autoaudiosink) - * @param[in] object : the child element - * @param[in] name : the name of the child element - * @param[in] self : The pointer to IGstGenericPlayerPrivate - */ -void autoAudioSinkChildAddedCallback(GstChildProxy *obj, GObject *object, gchar *name, gpointer self) -{ - RIALTO_SERVER_LOG_DEBUG("AutoAudioSink added element %s", name); - firebolt::rialto::server::IGstGenericPlayerPrivate *player = - static_cast(self); - player->addAutoAudioSinkChild(object); -} - -/** - * @brief Callback for a autovideosink when a child has been removed from the sink. - * - * @param[in] obj : the parent element (autovideosink) - * @param[in] object : the child element - * @param[in] name : the name of the child element - * @param[in] self : The pointer to IGstGenericPlayerPrivate - */ -void autoVideoSinkChildRemovedCallback(GstChildProxy *obj, GObject *object, gchar *name, gpointer self) -{ - RIALTO_SERVER_LOG_DEBUG("AutoVideoSink removed element %s", name); - firebolt::rialto::server::IGstGenericPlayerPrivate *player = - static_cast(self); - player->removeAutoVideoSinkChild(object); -} - -/** - * @brief Callback for a autoaudiosink when a child has been removed from the sink. - * - * @param[in] obj : the parent element (autoaudiosink) - * @param[in] object : the child element - * @param[in] name : the name of the child element - * @param[in] self : The pointer to IGstGenericPlayerPrivate - */ -void autoAudioSinkChildRemovedCallback(GstChildProxy *obj, GObject *object, gchar *name, gpointer self) -{ - RIALTO_SERVER_LOG_DEBUG("AutoAudioSink removed element %s", name); - firebolt::rialto::server::IGstGenericPlayerPrivate *player = - static_cast(self); - player->removeAutoAudioSinkChild(object); -} -} // namespace - -namespace firebolt::rialto::server::tasks::generic -{ -SetupElement::SetupElement(GenericPlayerContext &context, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - IGstGenericPlayerPrivate &player, GstElement *element) - : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_player{player}, m_element{element} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetupElement"); -} - -SetupElement::~SetupElement() -{ - RIALTO_SERVER_LOG_DEBUG("SetupElement finished"); -} - -void SetupElement::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetupElement"); - - const std::string kElementTypeName = m_glibWrapper->gTypeName(G_OBJECT_TYPE(m_element)); - if (kElementTypeName == "GstAutoVideoSink") - { - // Check and store child sink so we can set underlying properties - m_glibWrapper->gSignalConnect(m_element, "child-added", G_CALLBACK(autoVideoSinkChildAddedCallback), &m_player); - m_glibWrapper->gSignalConnect(m_element, "child-removed", G_CALLBACK(autoVideoSinkChildRemovedCallback), - &m_player); - - // AutoVideoSink sets child before it is setup on the pipeline, so check for children here - GstIterator *sinks = m_gstWrapper->gstBinIterateSinks(GST_BIN(m_element)); - if (sinks && sinks->size > 1) - { - RIALTO_SERVER_LOG_WARN("More than one child sink attached"); - } - - GValue elem = G_VALUE_INIT; - if (m_gstWrapper->gstIteratorNext(sinks, &elem) == GST_ITERATOR_OK) - { - m_player.addAutoVideoSinkChild(G_OBJECT(m_glibWrapper->gValueGetObject(&elem))); - } - m_glibWrapper->gValueUnset(&elem); - - if (sinks) - m_gstWrapper->gstIteratorFree(sinks); - } - else if (kElementTypeName == "GstAutoAudioSink") - { - // Check and store child sink so we can set underlying properties - m_glibWrapper->gSignalConnect(m_element, "child-added", G_CALLBACK(autoAudioSinkChildAddedCallback), &m_player); - m_glibWrapper->gSignalConnect(m_element, "child-removed", G_CALLBACK(autoAudioSinkChildRemovedCallback), - &m_player); - - // AutoAudioSink sets child before it is setup on the pipeline, so check for children here - GstIterator *sinks = m_gstWrapper->gstBinIterateSinks(GST_BIN(m_element)); - if (sinks && sinks->size > 1) - { - RIALTO_SERVER_LOG_WARN("More than one child sink attached"); - } - - GValue elem = G_VALUE_INIT; - if (m_gstWrapper->gstIteratorNext(sinks, &elem) == GST_ITERATOR_OK) - { - m_player.addAutoAudioSinkChild(G_OBJECT(m_glibWrapper->gValueGetObject(&elem))); - } - m_glibWrapper->gValueUnset(&elem); - - if (sinks) - m_gstWrapper->gstIteratorFree(sinks); - } - - if (m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "amlhalasink")) - { - if (m_context.streamInfo.find(MediaSourceType::VIDEO) != m_context.streamInfo.end()) - { - // Wait for video so that the audio aligns at the starting point with timeout of 4000ms. - m_glibWrapper->gObjectSet(m_element, "wait-video", TRUE, "a-wait-timeout", 4000, nullptr); - } - - // Xrun occasionally pauses the underlying sink due to unstable playback, but the rest of the pipeline - // remains in the playing state. This causes problems with the synchronization of gst element and rialto - // ultimately hangs waiting for pipeline termination. - m_glibWrapper->gObjectSet(m_element, "disable-xrun", TRUE, nullptr); - } - else if (m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "brcmaudiosink")) - { - m_glibWrapper->gObjectSet(m_element, "async", TRUE, nullptr); - } - else if (m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "rialtotexttracksink")) - { - // in cannot be set during construction, because playsink overwrites "sync" value of text-sink during setup - m_glibWrapper->gObjectSet(m_element, "sync", FALSE, nullptr); - } - - if (m_context.subtitleSink) - { - if (!m_context.isVideoHandleSet && isVideoDecoder(*m_gstWrapper, m_element)) - { - if (m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "omx") || - m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "westerossink") || - m_glibWrapper->gStrHasPrefix(GST_ELEMENT_NAME(m_element), "brcmvideodecoder")) - { - uintptr_t videoDecoderHandle = reinterpret_cast(m_element); - m_glibWrapper->gObjectSet(m_context.subtitleSink, "video-decoder", videoDecoderHandle, nullptr); - RIALTO_SERVER_LOG_INFO("Setting video decoder handle for subtitle sink: %zu", videoDecoderHandle); - m_context.isVideoHandleSet = true; - } - } - } - - if (isDecoder(*m_gstWrapper, m_element) || isSink(*m_gstWrapper, m_element)) - { - std::optional underflowSignalName = getUnderflowSignalName(*m_glibWrapper, m_element); - if (underflowSignalName) - { - if (isAudio(*m_gstWrapper, m_element)) - { - RIALTO_SERVER_LOG_INFO("Connecting audio underflow callback for signal: %s", - underflowSignalName.value().c_str()); - m_glibWrapper->gSignalConnect(m_element, underflowSignalName.value().c_str(), - G_CALLBACK(audioUnderflowCallback), &m_player); - } - else if (isVideo(*m_gstWrapper, m_element)) - { - RIALTO_SERVER_LOG_INFO("Connecting video underflow callback for signal: %s", - underflowSignalName.value().c_str()); - m_glibWrapper->gSignalConnect(m_element, underflowSignalName.value().c_str(), - G_CALLBACK(videoUnderflowCallback), &m_player); - } - } - } - - if (isVideoSink(*m_gstWrapper, m_element)) - { - if (!m_context.videoSink) - { - m_gstWrapper->gstObjectRef(m_element); - m_context.videoSink = m_element; - } - if (!m_context.pendingGeometry.empty()) - { - m_player.setVideoSinkRectangle(); - } - if (m_context.pendingImmediateOutputForVideo.has_value()) - { - m_player.setImmediateOutput(); - } - if (m_context.pendingRenderFrame) - { - m_player.setRenderFrame(); - } - if (m_context.pendingShowVideoWindow.has_value()) - { - m_player.setShowVideoWindow(); - } - } - else if (isAudioDecoder(*m_gstWrapper, m_element)) - { - if (m_context.pendingSyncOff.has_value()) - { - m_player.setSyncOff(); - } - if (m_context.pendingStreamSyncMode.find(MediaSourceType::AUDIO) != m_context.pendingStreamSyncMode.end()) - { - m_player.setStreamSyncMode(MediaSourceType::AUDIO); - } - if (m_context.pendingBufferingLimit.has_value()) - { - m_player.setBufferingLimit(); - } - } - else if (isAudioSink(*m_gstWrapper, m_element)) - { - if (m_context.pendingLowLatency.has_value()) - { - m_player.setLowLatency(); - } - if (m_context.pendingSync.has_value()) - { - m_player.setSync(); - } - } - else if (isVideoParser(*m_gstWrapper, m_element)) - { - if (m_context.pendingStreamSyncMode.find(MediaSourceType::VIDEO) != m_context.pendingStreamSyncMode.end()) - { - m_player.setStreamSyncMode(MediaSourceType::VIDEO); - } - } - - if (m_gstWrapper->gstIsBaseParse(m_element)) - { - m_gstWrapper->gstBaseParseSetPtsInterpolation(GST_BASE_PARSE(m_element), FALSE); - } - - m_gstWrapper->gstObjectUnref(m_element); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupSource.cpp deleted file mode 100644 index 7bfa9e133..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SetupSource.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SetupSource.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SetupSource::SetupSource(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, GstElement *source) - : m_context{context}, m_player{player}, m_source{source} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetupSource"); -} - -SetupSource::~SetupSource() -{ - RIALTO_SERVER_LOG_DEBUG("SetupSource finished"); -} - -void SetupSource::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetupSource"); - m_context.source = m_source; - - if (m_context.wereAllSourcesAttached) - { - RIALTO_SERVER_LOG_DEBUG("Source ready. Schedulling allSourcesAttached"); - m_player.scheduleAllSourcesAttached(); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Shutdown.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Shutdown.cpp deleted file mode 100644 index 7619ca3b4..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Shutdown.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Shutdown.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Shutdown::Shutdown(IGstGenericPlayerPrivate &player) : m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Shutdown"); -} - -Shutdown::~Shutdown() -{ - RIALTO_SERVER_LOG_DEBUG("Shutdown finished"); -} - -void Shutdown::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Shutdown"); - m_player.stopWorkerThread(); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Stop.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Stop.cpp deleted file mode 100644 index 8b5936560..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Stop.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Stop.h" -#include "GenericPlayerContext.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Stop::Stop(GenericPlayerContext &context, IGstGenericPlayerPrivate &player) : m_context{context}, m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Stop"); -} - -Stop::~Stop() -{ - RIALTO_SERVER_LOG_DEBUG("Stop finished"); -} - -void Stop::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Stop"); - m_player.stopPositionReportingAndCheckAudioUnderflowTimer(); - m_player.changePipelineState(GST_STATE_NULL); - for (auto &streamInfo : m_context.streamInfo) - { - streamInfo.second.isDataNeeded = false; - } - RIALTO_SERVER_LOG_MIL("State change to NULL requested"); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp deleted file mode 100644 index 3fc48a866..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SwitchSource.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SwitchSource.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" -#include "Utils.h" - -namespace firebolt::rialto::server::tasks::generic -{ -SwitchSource::SwitchSource(IGstGenericPlayerPrivate &player, const std::unique_ptr &source) - : m_player{player}, m_source{source->copy()} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SwitchSource"); -} - -SwitchSource::~SwitchSource() -{ - RIALTO_SERVER_LOG_DEBUG("SwitchSource finished"); -} - -void SwitchSource::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SwitchSource"); - if (!m_player.reattachSource(m_source)) - { - RIALTO_SERVER_LOG_WARN("Switch audio source failed"); - return; - } - RIALTO_SERVER_LOG_MIL("%s source switched", common::convertMediaSourceType(m_source->getType())); -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SynchroniseSubtitleClock.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SynchroniseSubtitleClock.cpp deleted file mode 100644 index 4da52f0ff..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/SynchroniseSubtitleClock.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2025 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/SynchroniseSubtitleClock.h" -#include "IGstGenericPlayerPrivate.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" -#include - -namespace firebolt::rialto::server::tasks::generic -{ -SynchroniseSubtitleClock::SynchroniseSubtitleClock( - GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper) - : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SynchroniseSubtitleClock"); -} - -SynchroniseSubtitleClock::~SynchroniseSubtitleClock() -{ - RIALTO_SERVER_LOG_DEBUG("SynchroniseSubtitleClock finished"); -} - -void SynchroniseSubtitleClock::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SynchroniseSubtitleClock"); - if (m_context.videoSink) - { - gint64 position = 0; - if (m_gstWrapper->gstElementQueryPosition(m_context.videoSink, GST_FORMAT_TIME, &position)) - { - RIALTO_SERVER_LOG_DEBUG("Videosink position: %" PRId64 " ns", position); - } - - auto sourceElem = m_context.streamInfo.find(MediaSourceType::SUBTITLE); - GstElement *source{nullptr}; - - if (sourceElem != m_context.streamInfo.end()) - { - source = sourceElem->second.appSrc; - } - else - { - RIALTO_SERVER_LOG_WARN("subtitle source not found"); - return; - } - - GstStructure *structure = m_gstWrapper->gstStructureNew("current-pts", "pts", G_TYPE_UINT64, position, nullptr); - GstEvent *event = m_gstWrapper->gstEventNewCustom(GST_EVENT_CUSTOM_DOWNSTREAM_OOB, structure); - - if (event) - { - if (m_gstWrapper->gstElementSendEvent(source, event)) - { - RIALTO_SERVER_LOG_DEBUG("Sent current-pts event to subtitlesource"); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to send current-pts event to source"); - } - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to create current-pts event"); - } - } - else - { - RIALTO_SERVER_LOG_ERROR("video-sink is NULL"); - } -} - -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Underflow.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Underflow.cpp deleted file mode 100644 index f34ad11c2..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/Underflow.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/Underflow.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server::tasks::generic -{ -Underflow::Underflow(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, IGstGenericPlayerClient *client, - bool underflowEnabled, MediaSourceType sourceType) - : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_underflowEnabled{underflowEnabled}, - m_sourceType{sourceType} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Underflow"); -} - -Underflow::~Underflow() -{ - RIALTO_SERVER_LOG_DEBUG("Underflow finished"); -} - -void Underflow::execute() const -{ - RIALTO_SERVER_LOG_WARN("Executing Underflow for %s source", common::convertMediaSourceType(m_sourceType)); - if (!m_underflowEnabled) - { - return; - } - - auto elem = m_context.streamInfo.find(m_sourceType); - if (elem != m_context.streamInfo.end()) - { - StreamInfo &streamInfo = elem->second; - if (streamInfo.underflowOccured) - { - return; - } - - streamInfo.underflowOccured = true; - - if (m_gstPlayerClient) - { - m_gstPlayerClient->notifyBufferUnderflow(m_sourceType); - } - } -} - -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp deleted file mode 100644 index 0264da6f1..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/generic/UpdatePlaybackGroup.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/generic/UpdatePlaybackGroup.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::generic -{ -UpdatePlaybackGroup::UpdatePlaybackGroup(GenericPlayerContext &context, IGstGenericPlayerPrivate &player, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - GstElement *typefind, const GstCaps *caps) - : m_context{context}, m_player{player}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_typefind{typefind}, - m_caps{caps} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing UpdatePlaybackGroup"); -} - -UpdatePlaybackGroup::~UpdatePlaybackGroup() -{ - RIALTO_SERVER_LOG_DEBUG("UpdatePlaybackGroup finished"); -} - -void UpdatePlaybackGroup::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing UpdatePlaybackGroup"); - if (nullptr == m_caps) - { - RIALTO_SERVER_LOG_DEBUG("Typefind SRC Pad Caps NULL"); - return; - } - gchar *typefindCaps = m_gstWrapper->gstCapsToString(m_caps); - if (typefindCaps) - { - RIALTO_SERVER_LOG_DEBUG("Typefind SRC Pad Strm Parsed Caps %s", typefindCaps); - if (m_glibWrapper->gStrrstr(typefindCaps, "audio/")) - { - GstElement *typeFindParent = reinterpret_cast(m_gstWrapper->gstElementGetParent(m_typefind)); - if (typeFindParent) - { - gchar *elementName = m_gstWrapper->gstElementGetName(typeFindParent); - RIALTO_SERVER_LOG_DEBUG("elementName %s", elementName); - if (elementName && m_glibWrapper->gStrrstr(elementName, "decodebin")) - { - RIALTO_SERVER_LOG_DEBUG("m_context.playbackGroup.curAudioDecodeBin %s", elementName); - m_context.playbackGroup.m_curAudioDecodeBin = typeFindParent; - gchar *typefindName = m_gstWrapper->gstElementGetName(m_typefind); - RIALTO_SERVER_LOG_DEBUG("onTypeFound(): m_context.playbackGroup.curAudioTypefind %s", typefindName); - m_glibWrapper->gFree(typefindName); - m_context.playbackGroup.m_curAudioTypefind = m_typefind; - if (m_context.pendingUseBuffering.has_value()) - { - m_player.setUseBuffering(); - } - } - m_glibWrapper->gFree(elementName); - m_gstWrapper->gstObjectUnref(typeFindParent); - } - } - m_glibWrapper->gFree(typefindCaps); - } -} -} // namespace firebolt::rialto::server::tasks::generic diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Eos.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Eos.cpp deleted file mode 100644 index 031ed7a8c..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Eos.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/Eos.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include "WebAudioPlayerContext.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -Eos::Eos(WebAudioPlayerContext &context, std::shared_ptr gstWrapper) - : m_context{context}, m_gstWrapper{gstWrapper} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Eos"); -} - -Eos::~Eos() -{ - RIALTO_SERVER_LOG_DEBUG("Eos finished"); -} - -void Eos::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Eos"); - if (m_gstWrapper->gstAppSrcEndOfStream(GST_APP_SRC(m_context.source)) != GST_FLOW_OK) - { - RIALTO_SERVER_LOG_WARN("Set eos failed - Gstreamer error"); - } - RIALTO_SERVER_LOG_MIL("EOS set for webaudio source"); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp deleted file mode 100644 index d58e0d7c1..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/HandleBusMessage.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/HandleBusMessage.h" -#include "IGstWebAudioPlayerClient.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include "WebAudioPlayerContext.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -HandleBusMessage::HandleBusMessage(WebAudioPlayerContext &context, IGstWebAudioPlayerPrivate &player, - IGstWebAudioPlayerClient *client, - std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - GstMessage *message) - : m_context{context}, m_player{player}, m_gstPlayerClient{client}, m_gstWrapper{gstWrapper}, - m_glibWrapper{glibWrapper}, m_message{message} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing HandleBusMessage"); -} - -HandleBusMessage::~HandleBusMessage() -{ - RIALTO_SERVER_LOG_DEBUG("HandleBusMessage finished"); -} - -void HandleBusMessage::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing HandleBusMessage"); - switch (GST_MESSAGE_TYPE(m_message)) - { - case GST_MESSAGE_STATE_CHANGED: - { - if (m_context.pipeline && GST_MESSAGE_SRC(m_message) == GST_OBJECT(m_context.pipeline)) - { - GstState oldState, newState, pending; - m_gstWrapper->gstMessageParseStateChanged(m_message, &oldState, &newState, &pending); - RIALTO_SERVER_LOG_MIL("State changed (old: %s, new: %s, pending: %s)", - m_gstWrapper->gstElementStateGetName(oldState), - m_gstWrapper->gstElementStateGetName(newState), - m_gstWrapper->gstElementStateGetName(pending)); - - std::string filename = std::string(m_gstWrapper->gstElementStateGetName(oldState)) + "-" + - std::string(m_gstWrapper->gstElementStateGetName(newState)); - m_gstWrapper->gstDebugBinToDotFileWithTs(GST_BIN(m_context.pipeline), GST_DEBUG_GRAPH_SHOW_ALL, - filename.c_str()); - if (!m_gstPlayerClient) - { - break; - } - switch (newState) - { - case GST_STATE_PAUSED: - { - if (pending != GST_STATE_PAUSED) - { - // newState==GST_STATE_PAUSED, pending==GST_STATE_PAUSED state transition is received as a result of - // waiting for preroll after seek. - // Subsequent newState==GST_STATE_PAUSED, pending!=GST_STATE_PAUSED transition will - // indicate that the pipeline is prerolled and it reached GST_STATE_PAUSED state after seek. - m_gstPlayerClient->notifyState(WebAudioPlayerState::PAUSED); - } - break; - } - case GST_STATE_PLAYING: - { - m_gstPlayerClient->notifyState(WebAudioPlayerState::PLAYING); - break; - } - case GST_STATE_READY: - { - m_gstPlayerClient->notifyState(WebAudioPlayerState::IDLE); - break; - } - case GST_STATE_NULL: - case GST_STATE_VOID_PENDING: - default: - break; - } - } - break; - } - case GST_MESSAGE_EOS: - { - if (m_context.pipeline && GST_MESSAGE_SRC(m_message) == GST_OBJECT(m_context.pipeline)) - { - RIALTO_SERVER_LOG_MIL("End of stream reached."); - if (m_gstPlayerClient) - { - m_gstPlayerClient->notifyState(WebAudioPlayerState::END_OF_STREAM); - } - - // Flush the pipeline so that it can be reused - if ((!m_gstWrapper->gstElementSendEvent(m_context.pipeline, m_gstWrapper->gstEventNewFlushStart())) || - (!m_gstWrapper->gstElementSendEvent(m_context.pipeline, m_gstWrapper->gstEventNewFlushStop(TRUE)))) - { - RIALTO_SERVER_LOG_ERROR("Failed to flush the pipeline"); - } - } - break; - } - case GST_MESSAGE_ERROR: - { - GError *err = nullptr; - gchar *debug = nullptr; - m_gstWrapper->gstMessageParseError(m_message, &err, &debug); - - RIALTO_SERVER_LOG_ERROR("Error from %s - %d: %s (%s)", GST_OBJECT_NAME(GST_MESSAGE_SRC(m_message)), err->code, - err->message, debug); - m_gstPlayerClient->notifyState(WebAudioPlayerState::FAILURE); - - m_glibWrapper->gFree(debug); - m_glibWrapper->gErrorFree(err); - break; - } - default: - break; - } - - m_gstWrapper->gstMessageUnref(m_message); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Pause.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Pause.cpp deleted file mode 100644 index 53ff8a5d2..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Pause.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/Pause.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -Pause::Pause(IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client) - : m_player{player}, m_gstPlayerClient{client} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Pause"); -} - -Pause::~Pause() -{ - RIALTO_SERVER_LOG_DEBUG("Pause finished"); -} - -void Pause::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Pause"); - if (!m_player.changePipelineState(GST_STATE_PAUSED)) - { - RIALTO_SERVER_LOG_ERROR("Failed to pause the web audio player"); - } - RIALTO_SERVER_LOG_MIL("State change to PAUSED requested for webaudio pipeline"); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Ping.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Ping.cpp deleted file mode 100644 index 0204c1523..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Ping.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/Ping.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -Ping::Ping(std::unique_ptr &&heartbeatHandler) : m_heartbeatHandler{std::move(heartbeatHandler)} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Ping"); -} - -Ping::~Ping() -{ - RIALTO_SERVER_LOG_DEBUG("Ping finished"); - m_heartbeatHandler.reset(); -} - -void Ping::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Ping"); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Play.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Play.cpp deleted file mode 100644 index cee4382bf..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Play.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/Play.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -Play::Play(IGstWebAudioPlayerPrivate &player, IGstWebAudioPlayerClient *client) - : m_player{player}, m_gstPlayerClient{client} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Play"); -} - -Play::~Play() -{ - RIALTO_SERVER_LOG_DEBUG("Play finished"); -} - -void Play::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Play"); - if (!m_player.changePipelineState(GST_STATE_PLAYING)) - { - RIALTO_SERVER_LOG_ERROR("Failed to play the web audio player"); - } - RIALTO_SERVER_LOG_MIL("State change to PLAYING requested for webaudio pipeline"); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp deleted file mode 100644 index f1e0ff99a..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetCaps.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/SetCaps.h" -#include "IGlibWrapper.h" -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" - -#include -#include -#include - -namespace firebolt::rialto::server::tasks::webaudio -{ -namespace -{ -class WebAudioCapsBuilder -{ -public: - WebAudioCapsBuilder(std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper) - : m_gstWrapper(gstWrapper), m_glibWrapper(glibWrapper) - { - } - virtual ~WebAudioCapsBuilder() = default; - virtual GstCaps *buildCaps() = 0; - -protected: - std::shared_ptr m_gstWrapper; - std::shared_ptr m_glibWrapper; -}; - -class WebAudioPcmCapsBuilder : public WebAudioCapsBuilder -{ -public: - WebAudioPcmCapsBuilder(std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const WebAudioPcmConfig &pcmConfig) - : WebAudioCapsBuilder(gstWrapper, glibWrapper), m_pcmConfig(pcmConfig) - { - } - ~WebAudioPcmCapsBuilder() override = default; - - GstCaps *buildCaps() override - { - GstCaps *caps = m_gstWrapper->gstCapsNewEmptySimple("audio/x-raw"); - addFormat(caps); - m_gstWrapper->gstCapsSetSimple(caps, "channels", G_TYPE_INT, m_pcmConfig.channels, "layout", G_TYPE_STRING, - "interleaved", "rate", G_TYPE_INT, m_pcmConfig.rate, "channel-mask", - GST_TYPE_BITMASK, - m_gstWrapper->gstAudioChannelGetFallbackMask(m_pcmConfig.channels), nullptr); - - return caps; - } - -protected: - void addFormat(GstCaps *caps) - { - std::string format; - - if (m_pcmConfig.isFloat) - { - format += "F"; - } - else if (m_pcmConfig.isSigned) - { - format += "S"; - } - else - { - format += "U"; - } - - format += std::to_string(m_pcmConfig.sampleSize); - - if (m_pcmConfig.isBigEndian) - { - format += "BE"; - } - else - { - format += "LE"; - } - - m_gstWrapper->gstCapsSetSimple(caps, "format", G_TYPE_STRING, format.c_str(), nullptr); - } - - const WebAudioPcmConfig &m_pcmConfig; -}; -}; // namespace - -SetCaps::SetCaps(WebAudioPlayerContext &context, std::shared_ptr gstWrapper, - std::shared_ptr glibWrapper, - const std::string &audioMimeType, std::weak_ptr webAudioConfig) - : m_context{context}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper}, m_audioMimeType{audioMimeType} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetCaps"); - - if (m_audioMimeType == "audio/x-raw") - { - std::shared_ptr kConfig = webAudioConfig.lock(); - if (kConfig == nullptr) - { - throw std::runtime_error("Config is null for 'audio/x-raw'"); - } - m_config.pcm = kConfig->pcm; - } -} - -SetCaps::~SetCaps() -{ - RIALTO_SERVER_LOG_DEBUG("SetCaps finished"); -} - -void SetCaps::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing SetCaps"); - - GstCaps *caps = createCapsFromMimeType(); - if (caps) - { - gchar *capsStr = m_gstWrapper->gstCapsToString(caps); - std::string strCaps = capsStr; - m_glibWrapper->gFree(capsStr); - - RIALTO_SERVER_LOG_DEBUG("caps str: '%s'", strCaps.c_str()); - - GstCaps *appsrcCaps = m_gstWrapper->gstAppSrcGetCaps(GST_APP_SRC(m_context.source)); - if ((!appsrcCaps) || (!m_gstWrapper->gstCapsIsEqual(appsrcCaps, caps))) - { - RIALTO_SERVER_LOG_INFO("Updating web audio appsrc caps to '%s'", strCaps.c_str()); - m_gstWrapper->gstAppSrcSetCaps(GST_APP_SRC(m_context.source), caps); - } - - if (appsrcCaps) - m_gstWrapper->gstCapsUnref(appsrcCaps); - if (caps) - m_gstWrapper->gstCapsUnref(caps); - - setBytesPerSample(); - RIALTO_SERVER_LOG_MIL("New caps set for webaudio source: %s", strCaps.c_str()); - } -} - -GstCaps *SetCaps::createCapsFromMimeType() const -{ - std::unique_ptr capsBuilder; - - if (m_audioMimeType == "audio/x-raw") - { - capsBuilder = std::make_unique(m_gstWrapper, m_glibWrapper, m_config.pcm); - } - else - { - RIALTO_SERVER_LOG_ERROR("Invalid audio mime type %s", m_audioMimeType.c_str()); - return nullptr; - } - - return capsBuilder->buildCaps(); -} - -void SetCaps::setBytesPerSample() const -{ - if (m_audioMimeType == "audio/x-raw") - { - m_context.bytesPerSample = m_config.pcm.channels * (m_config.pcm.sampleSize / CHAR_BIT); - } - else - { - RIALTO_SERVER_LOG_ERROR("Cannot set bytes per sample, invalid audio mime type %s", m_audioMimeType.c_str()); - } -} - -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetVolume.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetVolume.cpp deleted file mode 100644 index 857ca3406..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/SetVolume.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "RialtoServerLogging.h" -#include "tasks/webAudio/SetVolume.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -SetVolume::SetVolume(WebAudioPlayerContext &context, - std::shared_ptr gstWrapper, double volume) - : m_context{context}, m_gstWrapper{gstWrapper}, m_volume{volume} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing SetVolume"); -} - -SetVolume::~SetVolume() -{ - RIALTO_SERVER_LOG_DEBUG("SetVolume finished"); -} - -void SetVolume::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("WebAudio Executing SetVolume %f", m_volume); - m_gstWrapper->gstStreamVolumeSetVolume(m_context.gstVolumeElement, GST_STREAM_VOLUME_FORMAT_LINEAR, m_volume); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp deleted file mode 100644 index a4275ade0..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Shutdown.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/Shutdown.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -Shutdown::Shutdown(IGstWebAudioPlayerPrivate &player) : m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Shutdown"); -} - -Shutdown::~Shutdown() -{ - RIALTO_SERVER_LOG_DEBUG("Shutdown finished"); -} - -void Shutdown::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Shutdown"); - m_player.stopWorkerThread(); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Stop.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Stop.cpp deleted file mode 100644 index 7e369eee4..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/Stop.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "tasks/webAudio/Stop.h" -#include "IGstWebAudioPlayerPrivate.h" -#include "RialtoServerLogging.h" -#include "WebAudioPlayerContext.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -Stop::Stop(IGstWebAudioPlayerPrivate &player) : m_player{player} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing Stop"); -} - -Stop::~Stop() -{ - RIALTO_SERVER_LOG_DEBUG("Stop finished"); -} - -void Stop::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing Stop"); - m_player.changePipelineState(GST_STATE_NULL); - RIALTO_SERVER_LOG_MIL("State change to NULL requested for webaudio pipeline"); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp deleted file mode 100644 index bdf107efc..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WebAudioPlayerTaskFactory.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include "tasks/webAudio/WebAudioPlayerTaskFactory.h" -#include "tasks/webAudio/Eos.h" -#include "tasks/webAudio/HandleBusMessage.h" -#include "tasks/webAudio/Pause.h" -#include "tasks/webAudio/Ping.h" -#include "tasks/webAudio/Play.h" -#include "tasks/webAudio/SetCaps.h" -#include "tasks/webAudio/SetVolume.h" -#include "tasks/webAudio/Shutdown.h" -#include "tasks/webAudio/Stop.h" -#include "tasks/webAudio/WriteBuffer.h" - -namespace firebolt::rialto::server -{ -WebAudioPlayerTaskFactory::WebAudioPlayerTaskFactory( - IGstWebAudioPlayerClient *client, const std::shared_ptr &gstWrapper, - const std::shared_ptr &glibWrapper) - : m_client{client}, m_gstWrapper{gstWrapper}, m_glibWrapper{glibWrapper} -{ -} - -std::unique_ptr WebAudioPlayerTaskFactory::createShutdown(IGstWebAudioPlayerPrivate &player) const -{ - return std::make_unique(player); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createStop(IGstWebAudioPlayerPrivate &player) const -{ - return std::make_unique(player); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createPlay(IGstWebAudioPlayerPrivate &player) const -{ - return std::make_unique(player, m_client); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createPause(IGstWebAudioPlayerPrivate &player) const -{ - return std::make_unique(player, m_client); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createEos(WebAudioPlayerContext &context) const -{ - return std::make_unique(context, m_gstWrapper); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createSetCaps(WebAudioPlayerContext &context, - const std::string &audioMimeType, - std::weak_ptr config) const -{ - return std::make_unique(context, m_gstWrapper, m_glibWrapper, audioMimeType, config); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createSetVolume(WebAudioPlayerContext &context, double volume) const -{ - return std::make_unique(context, m_gstWrapper, volume); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createWriteBuffer(WebAudioPlayerContext &context, - uint8_t *mainPtr, uint32_t mainLength, - uint8_t *wrapPtr, uint32_t wrapLength) const -{ - return std::make_unique(context, m_gstWrapper, mainPtr, mainLength, wrapPtr, - wrapLength); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createHandleBusMessage(WebAudioPlayerContext &context, - IGstWebAudioPlayerPrivate &player, - GstMessage *message) const -{ - return std::make_unique(context, player, m_client, m_gstWrapper, m_glibWrapper, - message); -} - -std::unique_ptr WebAudioPlayerTaskFactory::createPing(std::unique_ptr &&heartbeatHandler) const -{ - return std::make_unique(std::move(heartbeatHandler)); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WriteBuffer.cpp b/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WriteBuffer.cpp deleted file mode 100644 index f22870400..000000000 --- a/middleware/rialto-client/media/server/gstplayer/source/tasks/webAudio/WriteBuffer.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "IGstWrapper.h" -#include "RialtoServerLogging.h" -#include "WebAudioPlayerContext.h" -#include "tasks/webAudio/WriteBuffer.h" - -namespace firebolt::rialto::server::tasks::webaudio -{ -WriteBuffer::WriteBuffer(WebAudioPlayerContext &context, - std::shared_ptr gstWrapper, uint8_t *mainPtr, - uint32_t mainLength, uint8_t *wrapPtr, uint32_t wrapLength) - : m_context{context}, m_gstWrapper{gstWrapper}, m_mainPtr{mainPtr}, m_mainLength{mainLength}, m_wrapPtr{wrapPtr}, - m_wrapLength{wrapLength} -{ - RIALTO_SERVER_LOG_DEBUG("Constructing WriteBuffer"); -} - -WriteBuffer::~WriteBuffer() -{ - RIALTO_SERVER_LOG_DEBUG("WriteBuffer finished"); -} - -void WriteBuffer::execute() const -{ - RIALTO_SERVER_LOG_DEBUG("Executing WriteBuffer"); - - uint64_t freeBytes = kMaxWebAudioBytes - m_gstWrapper->gstAppSrcGetCurrentLevelBytes(GST_APP_SRC(m_context.source)); - uint64_t maxBytesToWrite = std::min(freeBytes, m_mainLength + m_wrapLength); - uint64_t bytesToWrite = maxBytesToWrite - (maxBytesToWrite % m_context.bytesPerSample); - uint64_t bytesWritten = 0; - - if (bytesToWrite > 0) - { - GstBuffer *gstBuffer = m_gstWrapper->gstBufferNewAllocate(nullptr, bytesToWrite, nullptr); - if (gstBuffer) - { - if (bytesToWrite == m_mainLength + m_wrapLength) - { - bytesWritten += m_gstWrapper->gstBufferFill(gstBuffer, 0, m_mainPtr, m_mainLength); - if (m_wrapLength > 0) - { - bytesWritten += m_gstWrapper->gstBufferFill(gstBuffer, bytesWritten, m_wrapPtr, m_wrapLength); - } - } - else if (bytesToWrite > m_mainLength) - { - bytesWritten += m_gstWrapper->gstBufferFill(gstBuffer, 0, m_mainPtr, m_mainLength); - bytesWritten += - m_gstWrapper->gstBufferFill(gstBuffer, bytesWritten, m_wrapPtr, bytesToWrite - bytesWritten); - } - else - { - bytesWritten += m_gstWrapper->gstBufferFill(gstBuffer, 0, m_mainPtr, bytesToWrite); - } - - if (bytesWritten != bytesToWrite) - { - RIALTO_SERVER_LOG_WARN("Did not write the correct number of bytes! expected %" PRIu64 - ", actual %" PRIu64, - bytesToWrite, bytesWritten); - } - - if (GST_FLOW_OK != m_gstWrapper->gstAppSrcPushBuffer(GST_APP_SRC(m_context.source), gstBuffer)) - { - RIALTO_SERVER_LOG_ERROR("Failed to push the buffers to the appsrc"); - m_gstWrapper->gstBufferUnref(gstBuffer); - bytesWritten = 0; - } - - RIALTO_SERVER_LOG_INFO("%" PRIu64 "bytes written to gstreamer", bytesWritten); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to create the gst buffer"); - } - } - else - { - RIALTO_SERVER_LOG_INFO("No space in gstreamer buffer to write samples"); - } - - { - std::unique_lock lock(m_context.writeBufferMutex); - m_context.lastBytesWritten = bytesWritten; - } - m_context.writeBufferCond.notify_one(); -} -} // namespace firebolt::rialto::server::tasks::webaudio diff --git a/middleware/rialto-client/media/server/ipc/CMakeLists.txt b/middleware/rialto-client/media/server/ipc/CMakeLists.txt deleted file mode 100644 index 17c5c6001..000000000 --- a/middleware/rialto-client/media/server/ipc/CMakeLists.txt +++ /dev/null @@ -1,82 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Find includes in corresponding build directories -set( CMAKE_INCLUDE_CURRENT_DIR ON ) - -add_library ( - RialtoServerIpc - STATIC - - source/AckSender.cpp - source/ApplicationManagementServer.cpp - source/IpcFactory.cpp - source/MediaPipelineClient.cpp - source/MediaPipelineModuleService.cpp - source/MediaPipelineCapabilitiesModuleService.cpp - source/MediaKeysClient.cpp - source/MediaKeysModuleService.cpp - source/MediaKeysCapabilitiesModuleService.cpp - source/ControlClientServerInternal.cpp - source/ControlModuleService.cpp - source/ServerManagerModuleService.cpp - source/SessionManagementServer.cpp - source/SetLogLevelsService.cpp - source/RialtoCommonModule.cpp - source/WebAudioPlayerClient.cpp - source/WebAudioPlayerModuleService.cpp -) - -set_property (TARGET - RialtoServerIpc - PROPERTY POSITION_INDEPENDENT_CODE ON -) - -target_include_directories ( - RialtoServerIpc - - PUBLIC - interface - - PRIVATE - include - $ - $ - $ - $ - $ - $ - $ - $ - $ -) - -target_link_libraries ( - RialtoServerIpc - - PRIVATE - RialtoIpcServer - RialtoIpcCommon - RialtoPlayerCommon - RialtoServerMain - RialtoServerService - RialtoWrappers - RialtoProtobuf - Threads::Threads -) diff --git a/middleware/rialto-client/media/server/ipc/include/AckSender.h b/middleware/rialto-client/media/server/ipc/include/AckSender.h deleted file mode 100644 index 9c8dda6a4..000000000 --- a/middleware/rialto-client/media/server/ipc/include/AckSender.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_ACK_SENDER_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_ACK_SENDER_H_ - -#include "IAckSender.h" -#include "IIpcServer.h" -#include - -namespace firebolt::rialto::server::ipc -{ -class AckSender : public IAckSender -{ -public: - explicit AckSender(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); - ~AckSender() override = default; - - void send(int id, bool success) const override; - -private: - std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_ACK_SENDER_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/ApplicationManagementServer.h b/middleware/rialto-client/media/server/ipc/include/ApplicationManagementServer.h deleted file mode 100644 index cec825d0b..000000000 --- a/middleware/rialto-client/media/server/ipc/include/ApplicationManagementServer.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_APPLICATION_MANAGEMENT_SERVER_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_APPLICATION_MANAGEMENT_SERVER_H_ - -#include "IApplicationManagementServer.h" -#include "IServerManagerModuleServiceFactory.h" -#include "ISessionServerManager.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class ApplicationManagementServer : public IApplicationManagementServer -{ -public: - ApplicationManagementServer(const std::shared_ptr &serverFactory, - const std::shared_ptr - &serverManagerModuleFactory, - service::ISessionServerManager &sessionServerManager); - ~ApplicationManagementServer() override; - ApplicationManagementServer(const ApplicationManagementServer &) = delete; - ApplicationManagementServer(ApplicationManagementServer &&) = delete; - ApplicationManagementServer &operator=(const ApplicationManagementServer &) = delete; - ApplicationManagementServer &operator=(ApplicationManagementServer &&) = delete; - - bool initialize(int socket) override; - bool sendStateChangedEvent(const common::SessionServerState &state) override; - void start() override; - void stop() override; - -private: - void onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client); - -private: - std::thread m_ipcServerThread; - std::shared_ptr<::firebolt::rialto::ipc::IServer> m_ipcServer; - std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; - std::shared_ptr<::rialto::ServerManagerModule> m_service; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_APPLICATION_MANAGEMENT_SERVER_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/ControlClientServerInternal.h b/middleware/rialto-client/media/server/ipc/include/ControlClientServerInternal.h deleted file mode 100644 index bede10525..000000000 --- a/middleware/rialto-client/media/server/ipc/include/ControlClientServerInternal.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_CONTROL_CLIENT_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_CONTROL_CLIENT_SERVER_INTERNAL_H_ - -#include "IControlClientServerInternal.h" -#include "IIpcServer.h" -#include - -namespace firebolt::rialto::server::ipc -{ -class ControlClientServerInternal : public IControlClientServerInternal -{ -public: - explicit ControlClientServerInternal(int controlId, - const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); - ~ControlClientServerInternal() override = default; - - void notifyApplicationState(ApplicationState state) override; - void ping(uint32_t id) override; - -private: - const int m_kControlId; - std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_CONTROL_CLIENT_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/ControlModuleService.h b/middleware/rialto-client/media/server/ipc/include/ControlModuleService.h deleted file mode 100644 index 8204c2cd5..000000000 --- a/middleware/rialto-client/media/server/ipc/include/ControlModuleService.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_CONTROL_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_CONTROL_MODULE_SERVICE_H_ - -#include "IControlModuleService.h" -#include "IControlService.h" -#include "IPlaybackService.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class ControlModuleServiceFactory : public IControlModuleServiceFactory -{ -public: - ControlModuleServiceFactory() = default; - virtual ~ControlModuleServiceFactory() = default; - - std::shared_ptr create(service::IPlaybackService &playbackService, - service::IControlService &controlService) const override; -}; - -class ControlModuleService : public IControlModuleService -{ -public: - explicit ControlModuleService(service::IPlaybackService &playbackService, service::IControlService &controlService); - ~ControlModuleService() override; - - void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - - void getSharedMemory(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetSharedMemoryRequest *request, - ::firebolt::rialto::GetSharedMemoryResponse *response, - ::google::protobuf::Closure *done) override; - void registerClient(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::RegisterClientRequest *request, - ::firebolt::rialto::RegisterClientResponse *response, ::google::protobuf::Closure *done) override; - void ack(::google::protobuf::RpcController *controller, const ::firebolt::rialto::AckRequest *request, - ::firebolt::rialto::AckResponse *response, ::google::protobuf::Closure *done) override; - -private: - service::IPlaybackService &m_playbackService; - service::IControlService &m_controlService; - std::map, std::set> m_controlIds; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_CONTROL_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IControlModuleService.h b/middleware/rialto-client/media/server/ipc/include/IControlModuleService.h deleted file mode 100644 index fce49275f..000000000 --- a/middleware/rialto-client/media/server/ipc/include/IControlModuleService.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_CONTROL_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_CONTROL_MODULE_SERVICE_H_ - -#include "IControlService.h" -#include "IPlaybackService.h" -#include "controlmodule.pb.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class IControlModuleService; - -/** - * @brief IControlModuleService factory class, returns a concrete implementation of IControlModuleService - */ -class IControlModuleServiceFactory -{ -public: - IControlModuleServiceFactory() = default; - virtual ~IControlModuleServiceFactory() = default; - - /** - * @brief Create a IControlModuleServiceFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a ControlModuleService object. - * - * @retval the control ipc instance or null on error. - */ - virtual std::shared_ptr create(service::IPlaybackService &playbackService, - service::IControlService &controlService) const = 0; -}; - -/** - * @brief The definition of the IControlModuleService interface. - */ -class IControlModuleService : public ::firebolt::rialto::ControlModule, - public std::enable_shared_from_this -{ -public: - IControlModuleService() = default; - virtual ~IControlModuleService() = default; - - IControlModuleService(const IControlModuleService &) = delete; - IControlModuleService(IControlModuleService &&) = delete; - IControlModuleService &operator=(const IControlModuleService &) = delete; - IControlModuleService &operator=(IControlModuleService &&) = delete; - - /** - * @brief Connect to the ipc client. - * - * @param[in] ipcClient : The ipc client to connect to. - */ - virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; - - /** - * @brief Disconnect from the ipc client. - * - * @param[in] ipcClient : The ipc client to disconnect to. - */ - virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; -}; - -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_CONTROL_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IMediaKeysCapabilitiesModuleService.h b/middleware/rialto-client/media/server/ipc/include/IMediaKeysCapabilitiesModuleService.h deleted file mode 100644 index ac1997960..000000000 --- a/middleware/rialto-client/media/server/ipc/include/IMediaKeysCapabilitiesModuleService.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ - -#include "ICdmService.h" -#include "mediakeyscapabilitiesmodule.pb.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class IMediaKeysCapabilitiesModuleService; - -/** - * @brief IMediaKeysCapabilitiesModuleService factory class, returns a concrete implementation of - * IMediaKeysCapabilitiesModuleService - */ -class IMediaKeysCapabilitiesModuleServiceFactory -{ -public: - IMediaKeysCapabilitiesModuleServiceFactory() = default; - virtual ~IMediaKeysCapabilitiesModuleServiceFactory() = default; - - /** - * @brief Create a IMediaKeysCapabilitiesModuleServiceFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a MediaKeysCapabilitiesModuleService object. - * - * @param[in] cdmService : The service for cdm objects. - * - * @retval the rialto controller ipc instance or null on error. - */ - virtual std::shared_ptr create(service::ICdmService &cdmService) const = 0; -}; - -/** - * @brief The definition of the IMediaKeysCapabilitiesModuleService interface. - */ -class IMediaKeysCapabilitiesModuleService : public ::firebolt::rialto::MediaKeysCapabilitiesModule, - public std::enable_shared_from_this -{ -public: - IMediaKeysCapabilitiesModuleService() = default; - virtual ~IMediaKeysCapabilitiesModuleService() = default; - - IMediaKeysCapabilitiesModuleService(const IMediaKeysCapabilitiesModuleService &) = delete; - IMediaKeysCapabilitiesModuleService(IMediaKeysCapabilitiesModuleService &&) = delete; - IMediaKeysCapabilitiesModuleService &operator=(const IMediaKeysCapabilitiesModuleService &) = delete; - IMediaKeysCapabilitiesModuleService &operator=(IMediaKeysCapabilitiesModuleService &&) = delete; - - /** - * @brief Connect to the ipc client. - * - * @param[in] ipcClient : The ipc client to connect to. - */ - virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; - - /** - * @brief Disconnect from the ipc client. - * - * @param[in] ipcClient : The ipc client to disconnect to. - */ - virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; -}; - -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IMediaKeysModuleService.h b/middleware/rialto-client/media/server/ipc/include/IMediaKeysModuleService.h deleted file mode 100644 index ea4d3f8c8..000000000 --- a/middleware/rialto-client/media/server/ipc/include/IMediaKeysModuleService.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_MODULE_SERVICE_H_ - -#include "ICdmService.h" -#include "mediakeysmodule.pb.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class IMediaKeysModuleService; - -/** - * @brief IMediaKeysModuleService factory class, returns a concrete implementation of IMediaKeysModuleService - */ -class IMediaKeysModuleServiceFactory -{ -public: - IMediaKeysModuleServiceFactory() = default; - virtual ~IMediaKeysModuleServiceFactory() = default; - - /** - * @brief Create a IMediaKeysModuleServiceFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a MediaKeysModuleService object. - * - * @param[in] cdmService : The service for cdm objects. - * - * @retval the rialto controller ipc instance or null on error. - */ - virtual std::shared_ptr create(service::ICdmService &cdmService) const = 0; -}; - -/** - * @brief The definition of the IMediaKeysModuleService interface. - */ -class IMediaKeysModuleService : public ::firebolt::rialto::MediaKeysModule, - public std::enable_shared_from_this -{ -public: - IMediaKeysModuleService() = default; - virtual ~IMediaKeysModuleService() = default; - - IMediaKeysModuleService(const IMediaKeysModuleService &) = delete; - IMediaKeysModuleService(IMediaKeysModuleService &&) = delete; - IMediaKeysModuleService &operator=(const IMediaKeysModuleService &) = delete; - IMediaKeysModuleService &operator=(IMediaKeysModuleService &&) = delete; - - /** - * @brief Connect to the ipc client. - * - * @param[in] ipcClient : The ipc client to connect to. - */ - virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; - - /** - * @brief Disconnect from the ipc client. - * - * @param[in] ipcClient : The ipc client to disconnect to. - */ - virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; -}; - -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_KEYS_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IMediaPipelineCapabilitiesModuleService.h b/middleware/rialto-client/media/server/ipc/include/IMediaPipelineCapabilitiesModuleService.h deleted file mode 100644 index df597614b..000000000 --- a/middleware/rialto-client/media/server/ipc/include/IMediaPipelineCapabilitiesModuleService.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ - -#include "IMediaPipelineService.h" -#include "mediapipelinecapabilitiesmodule.pb.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class IMediaPipelineCapabilitiesModuleService; - -/** - * @brief IMediaPipelineCapabilitiesModuleService factory class, returns a concrete implementation of - * IMediaPipelineCapabilitiesModuleService - */ -class IMediaPipelineCapabilitiesModuleServiceFactory -{ -public: - IMediaPipelineCapabilitiesModuleServiceFactory() = default; - virtual ~IMediaPipelineCapabilitiesModuleServiceFactory() = default; - - /** - * @brief Create a IMediaPipelineCapabilitiesModuleServiceFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a MediaPipelineCapabilitiesModuleService object. - * - * @param[in] mediaPipelineService : The service for media pipeline objects - */ - virtual std::shared_ptr - create(service::IMediaPipelineService &mediaPipelineService) const = 0; -}; - -/** - * @brief The definition of the IMediaPipelineCapabilitiesModuleService interface. - */ -class IMediaPipelineCapabilitiesModuleService - : public ::firebolt::rialto::MediaPipelineCapabilitiesModule, - public std::enable_shared_from_this -{ -public: - IMediaPipelineCapabilitiesModuleService() = default; - virtual ~IMediaPipelineCapabilitiesModuleService() = default; - - IMediaPipelineCapabilitiesModuleService(const IMediaPipelineCapabilitiesModuleService &) = delete; - IMediaPipelineCapabilitiesModuleService(IMediaPipelineCapabilitiesModuleService &&) = delete; - IMediaPipelineCapabilitiesModuleService &operator=(const IMediaPipelineCapabilitiesModuleService &) = delete; - IMediaPipelineCapabilitiesModuleService &operator=(IMediaPipelineCapabilitiesModuleService &&) = delete; - - /** - * @brief Connect to the ipc client. - * - * @param[in] ipcClient : The ipc client to connect to. - */ - virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; - - /** - * @brief Disconnect from the ipc client. - * - * @param[in] ipcClient : The ipc client to disconnect to. - */ - virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; -}; - -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IMediaPipelineModuleService.h b/middleware/rialto-client/media/server/ipc/include/IMediaPipelineModuleService.h deleted file mode 100644 index a9604a90c..000000000 --- a/middleware/rialto-client/media/server/ipc/include/IMediaPipelineModuleService.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_MODULE_SERVICE_H_ - -#include "IMediaPipelineService.h" -#include "mediapipelinemodule.pb.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class IMediaPipelineModuleService; - -/** - * @brief IMediaPipelineModuleService factory class, returns a concrete implementation of IMediaPipelineModuleService - */ -class IMediaPipelineModuleServiceFactory -{ -public: - IMediaPipelineModuleServiceFactory() = default; - virtual ~IMediaPipelineModuleServiceFactory() = default; - - /** - * @brief Create a IMediaPipelineModuleServiceFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a MediaPipelineModuleService object. - * - * @retval the rialto controller ipc instance or null on error. - */ - virtual std::shared_ptr - create(service::IMediaPipelineService &mediaPipelineService) const = 0; -}; - -/** - * @brief The definition of the IMediaPipelineModuleService interface. - */ -class IMediaPipelineModuleService : public ::firebolt::rialto::MediaPipelineModule, - public std::enable_shared_from_this -{ -public: - IMediaPipelineModuleService() = default; - virtual ~IMediaPipelineModuleService() = default; - - IMediaPipelineModuleService(const IMediaPipelineModuleService &) = delete; - IMediaPipelineModuleService(IMediaPipelineModuleService &&) = delete; - IMediaPipelineModuleService &operator=(const IMediaPipelineModuleService &) = delete; - IMediaPipelineModuleService &operator=(IMediaPipelineModuleService &&) = delete; - - /** - * @brief Connect to the ipc client. - * - * @param[in] ipcClient : The ipc client to connect to. - */ - virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; - - /** - * @brief Disconnect from the ipc client. - * - * @param[in] ipcClient : The ipc client to disconnect to. - */ - virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; -}; - -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_MEDIA_PIPELINE_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IServerManagerModuleServiceFactory.h b/middleware/rialto-client/media/server/ipc/include/IServerManagerModuleServiceFactory.h deleted file mode 100644 index 2901a9e2e..000000000 --- a/middleware/rialto-client/media/server/ipc/include/IServerManagerModuleServiceFactory.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_SERVER_MANAGER_MODULE_SERVICE_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_SERVER_MANAGER_MODULE_SERVICE_FACTORY_H_ - -#include "ISessionServerManager.h" -#include "servermanagermodule.pb.h" -#include - -namespace firebolt::rialto::server::ipc -{ -/** - * @brief IServerManagerModuleService factory class, returns a concrete implementation of IServerManagerModuleService - */ -class IServerManagerModuleServiceFactory -{ -public: - IServerManagerModuleServiceFactory() = default; - virtual ~IServerManagerModuleServiceFactory() = default; - - /** - * @brief Create a IServerManagerModuleServiceFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a ServerManagerModule object. - * - * @retval the rialto controller ipc instance or null on error. - */ - virtual std::shared_ptr<::rialto::ServerManagerModule> - create(service::ISessionServerManager &sessionServerManager) const = 0; -}; - -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_SERVER_MANAGER_MODULE_SERVICE_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/IWebAudioPlayerModuleService.h b/middleware/rialto-client/media/server/ipc/include/IWebAudioPlayerModuleService.h deleted file mode 100644 index 755ed6766..000000000 --- a/middleware/rialto-client/media/server/ipc/include/IWebAudioPlayerModuleService.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ - -#include "IWebAudioPlayerService.h" -#include "webaudioplayermodule.pb.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class IWebAudioPlayerModuleService; - -/** - * @brief IWebAudioPlayerModuleService factory class, returns a concrete implementation of IWebAudioPlayerModuleService - */ -class IWebAudioPlayerModuleServiceFactory -{ -public: - IWebAudioPlayerModuleServiceFactory() = default; - virtual ~IWebAudioPlayerModuleServiceFactory() = default; - - /** - * @brief Create a IWebAudioPlayerModuleServiceFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates a WebAudioPlayerModuleService object. - * - * @retval the web audio player ipc instance or null on error. - */ - virtual std::shared_ptr - create(service::IWebAudioPlayerService &webAudioPlayerService) const = 0; -}; - -/** - * @brief The definition of the IWebAudioPlayerModuleService interface. - */ -class IWebAudioPlayerModuleService : public ::firebolt::rialto::WebAudioPlayerModule, - public std::enable_shared_from_this -{ -public: - IWebAudioPlayerModuleService() = default; - virtual ~IWebAudioPlayerModuleService() = default; - - IWebAudioPlayerModuleService(const IWebAudioPlayerModuleService &) = delete; - IWebAudioPlayerModuleService(IWebAudioPlayerModuleService &&) = delete; - IWebAudioPlayerModuleService &operator=(const IWebAudioPlayerModuleService &) = delete; - IWebAudioPlayerModuleService &operator=(IWebAudioPlayerModuleService &&) = delete; - - /** - * @brief Connect to the ipc client. - * - * @param[in] ipcClient : The ipc client to connect to. - */ - virtual void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; - - /** - * @brief Disconnect from the ipc client. - * - * @param[in] ipcClient : The ipc client to disconnect to. - */ - virtual void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) = 0; -}; - -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaKeysCapabilitiesModuleService.h b/middleware/rialto-client/media/server/ipc/include/MediaKeysCapabilitiesModuleService.h deleted file mode 100644 index d88c3c0e5..000000000 --- a/middleware/rialto-client/media/server/ipc/include/MediaKeysCapabilitiesModuleService.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ - -#include "ICdmService.h" -#include "IMediaKeysCapabilitiesModuleService.h" -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class MediaKeysCapabilitiesModuleServiceFactory : public IMediaKeysCapabilitiesModuleServiceFactory -{ -public: - MediaKeysCapabilitiesModuleServiceFactory() = default; - virtual ~MediaKeysCapabilitiesModuleServiceFactory() = default; - - std::shared_ptr create(service::ICdmService &cdmService) const override; -}; - -class MediaKeysCapabilitiesModuleService : public IMediaKeysCapabilitiesModuleService -{ -public: - explicit MediaKeysCapabilitiesModuleService(service::ICdmService &cdmService); - ~MediaKeysCapabilitiesModuleService() override; - - void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - - void getSupportedKeySystems(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetSupportedKeySystemsRequest *request, - ::firebolt::rialto::GetSupportedKeySystemsResponse *response, - ::google::protobuf::Closure *done) override; - void supportsKeySystem(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SupportsKeySystemRequest *request, - ::firebolt::rialto::SupportsKeySystemResponse *response, - ::google::protobuf::Closure *done) override; - void getSupportedKeySystemVersion(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetSupportedKeySystemVersionRequest *request, - ::firebolt::rialto::GetSupportedKeySystemVersionResponse *response, - ::google::protobuf::Closure *done) override; - void isServerCertificateSupported(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::IsServerCertificateSupportedRequest *request, - ::firebolt::rialto::IsServerCertificateSupportedResponse *response, - ::google::protobuf::Closure *done) override; - -private: - service::ICdmService &m_cdmService; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CAPABILITIES_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaKeysClient.h b/middleware/rialto-client/media/server/ipc/include/MediaKeysClient.h deleted file mode 100644 index 9d9206b08..000000000 --- a/middleware/rialto-client/media/server/ipc/include/MediaKeysClient.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CLIENT_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CLIENT_H_ - -#include "IIpcServer.h" -#include "IMediaKeysClient.h" -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class MediaKeysClient : public IMediaKeysClient -{ -public: - MediaKeysClient(int mediaKeysHandle, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); - ~MediaKeysClient() override; - - void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, - const std::string &url) override; - void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) override; - void onKeyStatusesChanged(int32_t keySessionId, const KeyStatusVector &keyStatuses) override; - -private: - int m_mediaKeysHandle; - std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaKeysModuleService.h b/middleware/rialto-client/media/server/ipc/include/MediaKeysModuleService.h deleted file mode 100644 index 738201269..000000000 --- a/middleware/rialto-client/media/server/ipc/include/MediaKeysModuleService.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_MODULE_SERVICE_H_ - -#include "ICdmService.h" -#include "IMediaKeysModuleService.h" -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class MediaKeysModuleServiceFactory : public IMediaKeysModuleServiceFactory -{ -public: - MediaKeysModuleServiceFactory() = default; - virtual ~MediaKeysModuleServiceFactory() = default; - - std::shared_ptr create(service::ICdmService &cdmService) const override; -}; - -class MediaKeysModuleService : public IMediaKeysModuleService -{ -public: - explicit MediaKeysModuleService(service::ICdmService &cdmService); - ~MediaKeysModuleService() override; - - void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - - void createMediaKeys(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CreateMediaKeysRequest *request, - ::firebolt::rialto::CreateMediaKeysResponse *response, - ::google::protobuf::Closure *done) override; - void destroyMediaKeys(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DestroyMediaKeysRequest *request, - ::firebolt::rialto::DestroyMediaKeysResponse *response, - ::google::protobuf::Closure *done) override; - void containsKey(::google::protobuf::RpcController *controller, const ::firebolt::rialto::ContainsKeyRequest *request, - ::firebolt::rialto::ContainsKeyResponse *response, ::google::protobuf::Closure *done) override; - void createKeySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CreateKeySessionRequest *request, - ::firebolt::rialto::CreateKeySessionResponse *response, - ::google::protobuf::Closure *done) override; - void generateRequest(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GenerateRequestRequest *request, - ::firebolt::rialto::GenerateRequestResponse *response, - ::google::protobuf::Closure *done) override; - void loadSession(::google::protobuf::RpcController *controller, const ::firebolt::rialto::LoadSessionRequest *request, - ::firebolt::rialto::LoadSessionResponse *response, ::google::protobuf::Closure *done) override; - void updateSession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::UpdateSessionRequest *request, - ::firebolt::rialto::UpdateSessionResponse *response, ::google::protobuf::Closure *done) override; - void setDrmHeader(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetDrmHeaderRequest *request, - ::firebolt::rialto::SetDrmHeaderResponse *response, ::google::protobuf::Closure *done) override; - void closeKeySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CloseKeySessionRequest *request, - ::firebolt::rialto::CloseKeySessionResponse *response, - ::google::protobuf::Closure *done) override; - void removeKeySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::RemoveKeySessionRequest *request, - ::firebolt::rialto::RemoveKeySessionResponse *response, - ::google::protobuf::Closure *done) override; - void deleteDrmStore(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DeleteDrmStoreRequest *request, - ::firebolt::rialto::DeleteDrmStoreResponse *response, ::google::protobuf::Closure *done) override; - void deleteKeyStore(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DeleteKeyStoreRequest *request, - ::firebolt::rialto::DeleteKeyStoreResponse *response, ::google::protobuf::Closure *done) override; - void getDrmStoreHash(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetDrmStoreHashRequest *request, - ::firebolt::rialto::GetDrmStoreHashResponse *response, - ::google::protobuf::Closure *done) override; - void getKeyStoreHash(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetKeyStoreHashRequest *request, - ::firebolt::rialto::GetKeyStoreHashResponse *response, - ::google::protobuf::Closure *done) override; - void getLdlSessionsLimit(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetLdlSessionsLimitRequest *request, - ::firebolt::rialto::GetLdlSessionsLimitResponse *response, - ::google::protobuf::Closure *done) override; - void getLastDrmError(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetLastDrmErrorRequest *request, - ::firebolt::rialto::GetLastDrmErrorResponse *response, - ::google::protobuf::Closure *done) override; - void getDrmTime(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetDrmTimeRequest *request, - ::firebolt::rialto::GetDrmTimeResponse *response, ::google::protobuf::Closure *done) override; - void getCdmKeySessionId(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetCdmKeySessionIdRequest *request, - ::firebolt::rialto::GetCdmKeySessionIdResponse *response, - ::google::protobuf::Closure *done) override; - void releaseKeySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::ReleaseKeySessionRequest *request, - ::firebolt::rialto::ReleaseKeySessionResponse *response, - ::google::protobuf::Closure *done) override; - void getMetricSystemData(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetMetricSystemDataRequest *request, - ::firebolt::rialto::GetMetricSystemDataResponse *response, - ::google::protobuf::Closure *done) override; - -private: - service::ICdmService &m_cdmService; - std::map, std::set> m_clientMediaKeysHandles; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_KEYS_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h b/middleware/rialto-client/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h deleted file mode 100644 index e74f19fcf..000000000 --- a/middleware/rialto-client/media/server/ipc/include/MediaPipelineCapabilitiesModuleService.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ - -#include "IMediaPipelineCapabilitiesModuleService.h" -#include "IMediaPipelineService.h" -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class MediaPipelineCapabilitiesModuleServiceFactory : public IMediaPipelineCapabilitiesModuleServiceFactory -{ -public: - MediaPipelineCapabilitiesModuleServiceFactory() = default; - virtual ~MediaPipelineCapabilitiesModuleServiceFactory() = default; - - std::shared_ptr - create(service::IMediaPipelineService &mediaPipelineService) const override; -}; - -class MediaPipelineCapabilitiesModuleService : public IMediaPipelineCapabilitiesModuleService -{ -public: - explicit MediaPipelineCapabilitiesModuleService(service::IMediaPipelineService &mediaPipelineService); - ~MediaPipelineCapabilitiesModuleService() override; - - void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - - void getSupportedMimeTypes(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetSupportedMimeTypesRequest *request, - ::firebolt::rialto::GetSupportedMimeTypesResponse *response, - ::google::protobuf::Closure *done) override; - void isMimeTypeSupported(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::IsMimeTypeSupportedRequest *request, - ::firebolt::rialto::IsMimeTypeSupportedResponse *response, - ::google::protobuf::Closure *done) override; - void getSupportedProperties(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetSupportedPropertiesRequest *request, - ::firebolt::rialto::GetSupportedPropertiesResponse *response, - ::google::protobuf::Closure *done) override; - void isVideoMaster(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::IsVideoMasterRequest *request, - ::firebolt::rialto::IsVideoMasterResponse *response, ::google::protobuf::Closure *done) override; - -private: - service::IMediaPipelineService &m_mediaPipelineService; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CAPABILITIES_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaPipelineClient.h b/middleware/rialto-client/media/server/ipc/include/MediaPipelineClient.h deleted file mode 100644 index e8514052a..000000000 --- a/middleware/rialto-client/media/server/ipc/include/MediaPipelineClient.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CLIENT_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CLIENT_H_ - -#include "IIpcServer.h" -#include "IMediaPipelineClient.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class MediaPipelineClient : public IMediaPipelineClient -{ -public: - MediaPipelineClient(int sessionId, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); - ~MediaPipelineClient() override; - - void notifyDuration(int64_t duration) override; - void notifyPosition(int64_t position) override; - void notifyNativeSize(uint32_t width, uint32_t height, double aspect) override; - void notifyNetworkState(NetworkState state) override; - void notifyPlaybackState(PlaybackState state) override; - void notifyVideoData(bool hasData) override; - void notifyAudioData(bool hasData) override; - void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, - const std::shared_ptr &shmInfo) override; - void notifyCancelNeedMediaData(int32_t sourceId) override; - void notifyQos(int32_t sourceId, const QosInfo &qosInfo) override; - void notifyBufferUnderflow(int32_t sourceId) override; - void notifyPlaybackError(int32_t sourceId, PlaybackError error) override; - void notifySourceFlushed(int32_t sourceId) override; - -private: - int m_sessionId; - std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; - - // It is possible for a needData to be sent while a source is been attached, - // this causes an issue in client side as they recieve a needData from a source - // id they are unaware of. - std::mutex m_needDataMutex; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/MediaPipelineModuleService.h b/middleware/rialto-client/media/server/ipc/include/MediaPipelineModuleService.h deleted file mode 100644 index 86ae1239f..000000000 --- a/middleware/rialto-client/media/server/ipc/include/MediaPipelineModuleService.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_MODULE_SERVICE_H_ - -#include "IMediaPipelineClient.h" -#include "IMediaPipelineModuleService.h" -#include "IMediaPipelineService.h" -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class MediaPipelineModuleServiceFactory : public IMediaPipelineModuleServiceFactory -{ -public: - MediaPipelineModuleServiceFactory() = default; - virtual ~MediaPipelineModuleServiceFactory() = default; - - std::shared_ptr create(service::IMediaPipelineService &mediaPipelineService) const override; -}; - -class MediaPipelineModuleService : public IMediaPipelineModuleService -{ -public: - explicit MediaPipelineModuleService(service::IMediaPipelineService &mediaPipelineService); - ~MediaPipelineModuleService() override; - - void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - - void createSession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CreateSessionRequest *request, - ::firebolt::rialto::CreateSessionResponse *response, ::google::protobuf::Closure *done) override; - void destroySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DestroySessionRequest *request, - ::firebolt::rialto::DestroySessionResponse *response, ::google::protobuf::Closure *done) override; - void load(::google::protobuf::RpcController *controller, const ::firebolt::rialto::LoadRequest *request, - ::firebolt::rialto::LoadResponse *response, ::google::protobuf::Closure *done) override; - void setVideoWindow(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetVideoWindowRequest *request, - ::firebolt::rialto::SetVideoWindowResponse *response, ::google::protobuf::Closure *done) override; - void attachSource(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::AttachSourceRequest *request, - ::firebolt::rialto::AttachSourceResponse *response, ::google::protobuf::Closure *done) override; - void removeSource(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::RemoveSourceRequest *request, - ::firebolt::rialto::RemoveSourceResponse *response, ::google::protobuf::Closure *done) override; - void allSourcesAttached(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::AllSourcesAttachedRequest *request, - ::firebolt::rialto::AllSourcesAttachedResponse *response, - ::google::protobuf::Closure *done) override; - void play(::google::protobuf::RpcController *controller, const ::firebolt::rialto::PlayRequest *request, - ::firebolt::rialto::PlayResponse *response, ::google::protobuf::Closure *done) override; - void pause(::google::protobuf::RpcController *controller, const ::firebolt::rialto::PauseRequest *request, - ::firebolt::rialto::PauseResponse *response, ::google::protobuf::Closure *done) override; - void stop(::google::protobuf::RpcController *controller, const ::firebolt::rialto::StopRequest *request, - ::firebolt::rialto::StopResponse *response, ::google::protobuf::Closure *done) override; - void setPosition(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetPositionRequest *request, - ::firebolt::rialto::SetPositionResponse *response, ::google::protobuf::Closure *done) override; - void haveData(::google::protobuf::RpcController *controller, const ::firebolt::rialto::HaveDataRequest *request, - ::firebolt::rialto::HaveDataResponse *response, ::google::protobuf::Closure *done) override; - void setPlaybackRate(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetPlaybackRateRequest *request, - ::firebolt::rialto::SetPlaybackRateResponse *response, - ::google::protobuf::Closure *done) override; - void getPosition(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetPositionRequest *request, - ::firebolt::rialto::GetPositionResponse *response, ::google::protobuf::Closure *done) override; - void setImmediateOutput(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetImmediateOutputRequest *request, - ::firebolt::rialto::SetImmediateOutputResponse *response, - ::google::protobuf::Closure *done) override; - void getImmediateOutput(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetImmediateOutputRequest *request, - ::firebolt::rialto::GetImmediateOutputResponse *response, - ::google::protobuf::Closure *done) override; - void getStats(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetStatsRequest *request, - ::firebolt::rialto::GetStatsResponse *response, ::google::protobuf::Closure *done) override; - void renderFrame(::google::protobuf::RpcController *controller, const ::firebolt::rialto::RenderFrameRequest *request, - ::firebolt::rialto::RenderFrameResponse *response, ::google::protobuf::Closure *done) override; - void setVolume(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetVolumeRequest *request, - ::firebolt::rialto::SetVolumeResponse *response, ::google::protobuf::Closure *done) override; - void getVolume(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetVolumeRequest *request, - ::firebolt::rialto::GetVolumeResponse *response, ::google::protobuf::Closure *done) override; - void setMute(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetMuteRequest *request, - ::firebolt::rialto::SetMuteResponse *response, ::google::protobuf::Closure *done) override; - void getMute(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetMuteRequest *request, - ::firebolt::rialto::GetMuteResponse *response, ::google::protobuf::Closure *done) override; - void setTextTrackIdentifier(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetTextTrackIdentifierRequest *request, - ::firebolt::rialto::SetTextTrackIdentifierResponse *response, - ::google::protobuf::Closure *done) override; - void getTextTrackIdentifier(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetTextTrackIdentifierRequest *request, - ::firebolt::rialto::GetTextTrackIdentifierResponse *response, - ::google::protobuf::Closure *done) override; - void setLowLatency(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetLowLatencyRequest *request, - ::firebolt::rialto::SetLowLatencyResponse *response, ::google::protobuf::Closure *done) override; - void setSync(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetSyncRequest *request, - ::firebolt::rialto::SetSyncResponse *response, ::google::protobuf::Closure *done) override; - void getSync(::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSyncRequest *request, - ::firebolt::rialto::GetSyncResponse *response, ::google::protobuf::Closure *done) override; - void setSyncOff(::google::protobuf::RpcController *controller, const ::firebolt::rialto::SetSyncOffRequest *request, - ::firebolt::rialto::SetSyncOffResponse *response, ::google::protobuf::Closure *done) override; - void setStreamSyncMode(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetStreamSyncModeRequest *request, - ::firebolt::rialto::SetStreamSyncModeResponse *response, - ::google::protobuf::Closure *done) override; - void getStreamSyncMode(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetStreamSyncModeRequest *request, - ::firebolt::rialto::GetStreamSyncModeResponse *response, - ::google::protobuf::Closure *done) override; - void flush(::google::protobuf::RpcController *controller, const ::firebolt::rialto::FlushRequest *request, - ::firebolt::rialto::FlushResponse *response, ::google::protobuf::Closure *done) override; - void setSourcePosition(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetSourcePositionRequest *request, - ::firebolt::rialto::SetSourcePositionResponse *response, - ::google::protobuf::Closure *done) override; - void setSubtitleOffset(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetSubtitleOffsetRequest *request, - ::firebolt::rialto::SetSubtitleOffsetResponse *response, - ::google::protobuf::Closure *done) override; - void processAudioGap(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::ProcessAudioGapRequest *request, - ::firebolt::rialto::ProcessAudioGapResponse *response, - ::google::protobuf::Closure *done) override; - void setBufferingLimit(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetBufferingLimitRequest *request, - ::firebolt::rialto::SetBufferingLimitResponse *response, - ::google::protobuf::Closure *done) override; - void getBufferingLimit(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetBufferingLimitRequest *request, - ::firebolt::rialto::GetBufferingLimitResponse *response, - ::google::protobuf::Closure *done) override; - void setUseBuffering(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetUseBufferingRequest *request, - ::firebolt::rialto::SetUseBufferingResponse *response, - ::google::protobuf::Closure *done) override; - void getUseBuffering(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetUseBufferingRequest *request, - ::firebolt::rialto::GetUseBufferingResponse *response, - ::google::protobuf::Closure *done) override; - -private: - service::IMediaPipelineService &m_mediaPipelineService; - std::map, std::set> m_clientSessions; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_MEDIA_PIPELINE_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/RialtoCommonModule.h b/middleware/rialto-client/media/server/ipc/include/RialtoCommonModule.h deleted file mode 100644 index cea726195..000000000 --- a/middleware/rialto-client/media/server/ipc/include/RialtoCommonModule.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_RIALTO_COMMON_MODULE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_RIALTO_COMMON_MODULE_H_ - -#include "MediaCommon.h" -#include "rialtocommon.pb.h" - -namespace firebolt::rialto::server::ipc -{ -firebolt::rialto::MediaSourceType convertMediaSourceType(const firebolt::rialto::ProtoMediaSourceType &mediaSourceType); -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_RIALTO_COMMON_MODULE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/ServerManagerModuleService.h b/middleware/rialto-client/media/server/ipc/include/ServerManagerModuleService.h deleted file mode 100644 index 483c2e138..000000000 --- a/middleware/rialto-client/media/server/ipc/include/ServerManagerModuleService.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_SERVER_MANAGER_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_SERVER_MANAGER_MODULE_SERVICE_H_ - -#include "IServerManagerModuleServiceFactory.h" -#include "ISessionServerManager.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class ServerManagerModuleServiceFactory : public IServerManagerModuleServiceFactory -{ -public: - ServerManagerModuleServiceFactory() = default; - virtual ~ServerManagerModuleServiceFactory() = default; - - std::shared_ptr<::rialto::ServerManagerModule> - create(service::ISessionServerManager &sessionServerManager) const override; -}; - -class ServerManagerModuleService : public ::rialto::ServerManagerModule -{ -public: - explicit ServerManagerModuleService(service::ISessionServerManager &sessionServerManager); - ~ServerManagerModuleService() override; - - void setConfiguration(::google::protobuf::RpcController *controller, const ::rialto::SetConfigurationRequest *request, - ::rialto::SetConfigurationResponse *response, ::google::protobuf::Closure *done) override; - void setState(::google::protobuf::RpcController *controller, const ::rialto::SetStateRequest *request, - ::rialto::SetStateResponse *response, ::google::protobuf::Closure *done) override; - void setLogLevels(::google::protobuf::RpcController *controller, const ::rialto::SetLogLevelsRequest *request, - ::rialto::SetLogLevelsResponse *response, ::google::protobuf::Closure *done) override; - void ping(::google::protobuf::RpcController *controller, const ::rialto::PingRequest *request, - ::rialto::PingResponse *response, ::google::protobuf::Closure *done) override; - -private: - service::ISessionServerManager &m_sessionServerManager; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_SERVER_MANAGER_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/SessionManagementServer.h b/middleware/rialto-client/media/server/ipc/include/SessionManagementServer.h deleted file mode 100644 index 81510d7a5..000000000 --- a/middleware/rialto-client/media/server/ipc/include/SessionManagementServer.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_SESSION_MANAGEMENT_SERVER_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_SESSION_MANAGEMENT_SERVER_H_ - -#include "IControlModuleService.h" -#include "IControlService.h" -#include "ILinuxWrapper.h" -#include "IMediaKeysCapabilitiesModuleService.h" -#include "IMediaKeysModuleService.h" -#include "IMediaPipelineCapabilitiesModuleService.h" -#include "IMediaPipelineModuleService.h" -#include "IPlaybackService.h" -#include "ISessionManagementServer.h" -#include "IWebAudioPlayerModuleService.h" -#include "SetLogLevelsService.h" -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class SessionManagementServer : public ISessionManagementServer -{ -public: - SessionManagementServer( - const std::shared_ptr &serverFactory, - const std::shared_ptr &mediaPipelineModuleFactory, - const std::shared_ptr &mediaPipelineCapabilitiesModuleFactory, - const std::shared_ptr &mediaKeysModuleFactory, - const std::shared_ptr &mediaKeysCapabilitiesModuleFactory, - const std::shared_ptr &webAudioPlayerModuleFactory, - const std::shared_ptr &controlModuleFactory, - service::IPlaybackService &playbackService, service::ICdmService &cdmService, - service::IControlService &controlService); - ~SessionManagementServer() override; - SessionManagementServer(const SessionManagementServer &) = delete; - SessionManagementServer(SessionManagementServer &&) = delete; - SessionManagementServer &operator=(const SessionManagementServer &) = delete; - SessionManagementServer &operator=(SessionManagementServer &&) = delete; - - bool initialize(const std::string &socketName, unsigned int socketPermissions, const std::string &socketOwner, - const std::string &socketGroup) override; - bool initialize(int32_t socketFd) override; - void start() override; - void stop() override; - void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, - RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) override; - -private: - void onClientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client); - void onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client); - size_t getBufferSizeForPasswordStructureCalls() const; - -private: - std::atomic m_isRunning; - std::thread m_ipcServerThread; - std::shared_ptr<::firebolt::rialto::ipc::IServer> m_ipcServer; - std::shared_ptr m_mediaPipelineModule; - std::shared_ptr m_mediaPipelineCapabilitiesModule; - std::shared_ptr m_mediaKeysModule; - std::shared_ptr m_mediaKeysCapabilitiesModule; - std::shared_ptr m_webAudioPlayerModule; - std::shared_ptr m_controlModule; - SetLogLevelsService m_setLogLevelsService; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_SESSION_MANAGEMENT_SERVER_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/SetLogLevelsService.h b/middleware/rialto-client/media/server/ipc/include/SetLogLevelsService.h deleted file mode 100644 index 196f89536..000000000 --- a/middleware/rialto-client/media/server/ipc/include/SetLogLevelsService.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_SET_LOG_LEVELS_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_SET_LOG_LEVELS_SERVICE_H_ - -#include -#include -#include - -#include "IIpcServer.h" -#include "RialtoLogging.h" - -namespace firebolt::rialto::server::ipc -{ -class SetLogLevelsService -{ -public: - SetLogLevelsService() = default; - ~SetLogLevelsService() = default; - SetLogLevelsService(const SetLogLevelsService &) = delete; - SetLogLevelsService(SetLogLevelsService &&) = delete; - SetLogLevelsService &operator=(const SetLogLevelsService &) = delete; - SetLogLevelsService &operator=(SetLogLevelsService &&) = delete; - - void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); - void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); - void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, - RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels); - -private: - std::mutex m_mutex; - std::set> m_connectedClients; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_SET_LOG_LEVELS_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerClient.h b/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerClient.h deleted file mode 100644 index dc01f189a..000000000 --- a/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerClient.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_CLIENT_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_CLIENT_H_ - -#include "IIpcServer.h" -#include "IWebAudioPlayerClient.h" -#include - -namespace firebolt::rialto::server::ipc -{ -class WebAudioPlayerClient : public IWebAudioPlayerClient -{ -public: - WebAudioPlayerClient(int webAudioPlayerHandle, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient); - ~WebAudioPlayerClient() override; - - void notifyState(WebAudioPlayerState state) override; - -private: - int m_webAudioPlayerHandle; - std::shared_ptr<::firebolt::rialto::ipc::IClient> m_ipcClient; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_CLIENT_H_ diff --git a/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerModuleService.h b/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerModuleService.h deleted file mode 100644 index a863928ba..000000000 --- a/middleware/rialto-client/media/server/ipc/include/WebAudioPlayerModuleService.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ - -#include "IWebAudioPlayerClient.h" -#include "IWebAudioPlayerModuleService.h" -#include "IWebAudioPlayerService.h" -#include -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class WebAudioPlayerModuleServiceFactory : public IWebAudioPlayerModuleServiceFactory -{ -public: - WebAudioPlayerModuleServiceFactory() = default; - virtual ~WebAudioPlayerModuleServiceFactory() = default; - - std::shared_ptr - create(service::IWebAudioPlayerService &webAudioPlayerService) const override; -}; - -class WebAudioPlayerModuleService : public IWebAudioPlayerModuleService -{ -public: - explicit WebAudioPlayerModuleService(service::IWebAudioPlayerService &webAudioPlayerService); - ~WebAudioPlayerModuleService() override; - - void clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - void clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) override; - - void createWebAudioPlayer(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CreateWebAudioPlayerRequest *request, - ::firebolt::rialto::CreateWebAudioPlayerResponse *response, - ::google::protobuf::Closure *done) override; - void destroyWebAudioPlayer(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DestroyWebAudioPlayerRequest *request, - ::firebolt::rialto::DestroyWebAudioPlayerResponse *response, - ::google::protobuf::Closure *done) override; - void play(::google::protobuf::RpcController *controller, const ::firebolt::rialto::WebAudioPlayRequest *request, - ::firebolt::rialto::WebAudioPlayResponse *response, ::google::protobuf::Closure *done) override; - void pause(::google::protobuf::RpcController *controller, const ::firebolt::rialto::WebAudioPauseRequest *request, - ::firebolt::rialto::WebAudioPauseResponse *response, ::google::protobuf::Closure *done) override; - void setEos(::google::protobuf::RpcController *controller, const ::firebolt::rialto::WebAudioSetEosRequest *request, - ::firebolt::rialto::WebAudioSetEosResponse *response, ::google::protobuf::Closure *done) override; - void getBufferAvailable(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioGetBufferAvailableRequest *request, - ::firebolt::rialto::WebAudioGetBufferAvailableResponse *response, - ::google::protobuf::Closure *done) override; - void getBufferDelay(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioGetBufferDelayRequest *request, - ::firebolt::rialto::WebAudioGetBufferDelayResponse *response, - ::google::protobuf::Closure *done) override; - void writeBuffer(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioWriteBufferRequest *request, - ::firebolt::rialto::WebAudioWriteBufferResponse *response, - ::google::protobuf::Closure *done) override; - void getDeviceInfo(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioGetDeviceInfoRequest *request, - ::firebolt::rialto::WebAudioGetDeviceInfoResponse *response, - ::google::protobuf::Closure *done) override; - void setVolume(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioSetVolumeRequest *request, - ::firebolt::rialto::WebAudioSetVolumeResponse *response, ::google::protobuf::Closure *done) override; - void getVolume(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioGetVolumeRequest *request, - ::firebolt::rialto::WebAudioGetVolumeResponse *response, ::google::protobuf::Closure *done) override; - -private: - service::IWebAudioPlayerService &m_webAudioPlayerService; - std::map, std::set> m_clientWebAudioPlayerHandles; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_WEB_AUDIO_PLAYER_MODULE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/ipc/interface/IApplicationManagementServer.h b/middleware/rialto-client/media/server/ipc/interface/IApplicationManagementServer.h deleted file mode 100644 index 781bed0e9..000000000 --- a/middleware/rialto-client/media/server/ipc/interface/IApplicationManagementServer.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_APPLICATION_MANAGEMENT_SERVER_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_APPLICATION_MANAGEMENT_SERVER_H_ - -#include "SessionServerCommon.h" -#include - -namespace firebolt::rialto::server::ipc -{ -class IApplicationManagementServer -{ -public: - IApplicationManagementServer() = default; - virtual ~IApplicationManagementServer() = default; - - IApplicationManagementServer(const IApplicationManagementServer &) = delete; - IApplicationManagementServer(IApplicationManagementServer &&) = delete; - IApplicationManagementServer &operator=(const IApplicationManagementServer &) = delete; - IApplicationManagementServer &operator=(IApplicationManagementServer &&) = delete; - - virtual bool initialize(int socket) = 0; - virtual bool sendStateChangedEvent(const common::SessionServerState &state) = 0; - virtual void start() = 0; - virtual void stop() = 0; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_APPLICATION_MANAGEMENT_SERVER_H_ diff --git a/middleware/rialto-client/media/server/ipc/interface/IIpcFactory.h b/middleware/rialto-client/media/server/ipc/interface/IIpcFactory.h deleted file mode 100644 index 6473c051e..000000000 --- a/middleware/rialto-client/media/server/ipc/interface/IIpcFactory.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_IPC_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_IPC_FACTORY_H_ - -#include "IApplicationManagementServer.h" -#include "ICdmService.h" -#include "IControlService.h" -#include "IPlaybackService.h" -#include "ISessionManagementServer.h" -#include "ISessionServerManager.h" -#include - -namespace firebolt::rialto::server::ipc -{ -class IIpcFactory -{ -public: - IIpcFactory() = default; - virtual ~IIpcFactory() = default; - - virtual std::unique_ptr - createApplicationManagementServer(service::ISessionServerManager &sessionServerManager) const = 0; - virtual std::unique_ptr - createSessionManagementServer(service::IPlaybackService &playbackService, service::ICdmService &cdmService, - service::IControlService &controlService) const = 0; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/ipc/interface/ISessionManagementServer.h b/middleware/rialto-client/media/server/ipc/interface/ISessionManagementServer.h deleted file mode 100644 index 0f7b35334..000000000 --- a/middleware/rialto-client/media/server/ipc/interface/ISessionManagementServer.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_I_SESSION_MANAGEMENT_SERVER_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_I_SESSION_MANAGEMENT_SERVER_H_ - -#include "RialtoServerLogging.h" -#include -#include - -namespace firebolt::rialto::server::ipc -{ -class ISessionManagementServer -{ -public: - ISessionManagementServer() = default; - virtual ~ISessionManagementServer() = default; - - ISessionManagementServer(const ISessionManagementServer &) = delete; - ISessionManagementServer(ISessionManagementServer &&) = delete; - ISessionManagementServer &operator=(const ISessionManagementServer &) = delete; - ISessionManagementServer &operator=(ISessionManagementServer &&) = delete; - - virtual bool initialize(const std::string &socketName, unsigned int socketPermissions, - const std::string &socketOwner, const std::string &socketGroup) = 0; - virtual bool initialize(int32_t socketFd) = 0; - virtual void start() = 0; - virtual void stop() = 0; - virtual void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, - RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) = 0; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_I_SESSION_MANAGEMENT_SERVER_H_ diff --git a/middleware/rialto-client/media/server/ipc/interface/IpcFactory.h b/middleware/rialto-client/media/server/ipc/interface/IpcFactory.h deleted file mode 100644 index 68beb84f5..000000000 --- a/middleware/rialto-client/media/server/ipc/interface/IpcFactory.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_IPC_IPC_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_IPC_IPC_FACTORY_H_ - -#include "IIpcFactory.h" -#include - -namespace firebolt::rialto::server::ipc -{ -class IpcFactory : public IIpcFactory -{ -public: - IpcFactory() = default; - ~IpcFactory() override = default; - IpcFactory(const IpcFactory &) = delete; - IpcFactory(IpcFactory &&) = delete; - IpcFactory &operator=(const IpcFactory &) = delete; - IpcFactory &operator=(IpcFactory &&) = delete; - - std::unique_ptr - createApplicationManagementServer(service::ISessionServerManager &sessionServerManager) const override; - std::unique_ptr - createSessionManagementServer(service::IPlaybackService &playbackService, service::ICdmService &cdmService, - service::IControlService &controlService) const override; -}; -} // namespace firebolt::rialto::server::ipc - -#endif // FIREBOLT_RIALTO_SERVER_IPC_IPC_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/ipc/proto/controlmodule.proto b/middleware/rialto-client/media/server/ipc/proto/controlmodule.proto deleted file mode 120000 index 6e95f531f..000000000 --- a/middleware/rialto-client/media/server/ipc/proto/controlmodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/controlmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/mediakeyscapabilitiesmodule.proto b/middleware/rialto-client/media/server/ipc/proto/mediakeyscapabilitiesmodule.proto deleted file mode 120000 index e508c1392..000000000 --- a/middleware/rialto-client/media/server/ipc/proto/mediakeyscapabilitiesmodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/mediakeyscapabilitiesmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/mediakeysmodule.proto b/middleware/rialto-client/media/server/ipc/proto/mediakeysmodule.proto deleted file mode 120000 index 98b44b620..000000000 --- a/middleware/rialto-client/media/server/ipc/proto/mediakeysmodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/mediakeysmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/mediapipelinecapabilitiesmodule.proto b/middleware/rialto-client/media/server/ipc/proto/mediapipelinecapabilitiesmodule.proto deleted file mode 120000 index 7af44cdd7..000000000 --- a/middleware/rialto-client/media/server/ipc/proto/mediapipelinecapabilitiesmodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/mediapipelinecapabilitiesmodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/mediapipelinemodule.proto b/middleware/rialto-client/media/server/ipc/proto/mediapipelinemodule.proto deleted file mode 120000 index 6f1b4bdbe..000000000 --- a/middleware/rialto-client/media/server/ipc/proto/mediapipelinemodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/mediapipelinemodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/rialtocommon.proto b/middleware/rialto-client/media/server/ipc/proto/rialtocommon.proto deleted file mode 120000 index 2c6e7a2bb..000000000 --- a/middleware/rialto-client/media/server/ipc/proto/rialtocommon.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/rialtocommon.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/servermanagermodule.proto b/middleware/rialto-client/media/server/ipc/proto/servermanagermodule.proto deleted file mode 120000 index bc952e7b5..000000000 --- a/middleware/rialto-client/media/server/ipc/proto/servermanagermodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/servermanagermodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/proto/webaudioplayermodule.proto b/middleware/rialto-client/media/server/ipc/proto/webaudioplayermodule.proto deleted file mode 120000 index 4c84680f4..000000000 --- a/middleware/rialto-client/media/server/ipc/proto/webaudioplayermodule.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/webaudioplayermodule.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/ipc/source/AckSender.cpp b/middleware/rialto-client/media/server/ipc/source/AckSender.cpp deleted file mode 100644 index 003fb83f1..000000000 --- a/middleware/rialto-client/media/server/ipc/source/AckSender.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "AckSender.h" -#include "RialtoServerLogging.h" -#include "servermanagermodule.pb.h" - -namespace firebolt::rialto::server::ipc -{ -AckSender::AckSender(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) : m_ipcClient{ipcClient} {} - -void AckSender::send(int id, bool success) const -{ - RIALTO_SERVER_LOG_DEBUG("Sending AckEvent with id %d", id); - - auto event = std::make_shared<::rialto::AckEvent>(); - event->set_id(id); - event->set_success(success); - - m_ipcClient->sendEvent(event); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/ApplicationManagementServer.cpp b/middleware/rialto-client/media/server/ipc/source/ApplicationManagementServer.cpp deleted file mode 100644 index 8ca47c197..000000000 --- a/middleware/rialto-client/media/server/ipc/source/ApplicationManagementServer.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ApplicationManagementServer.h" -#include "IServerManagerModuleServiceFactory.h" -#include "RialtoServerLogging.h" -#include - -namespace -{ -rialto::SessionServerState convertSessionServerState(const firebolt::rialto::common::SessionServerState &state) -{ - switch (state) - { - case firebolt::rialto::common::SessionServerState::UNINITIALIZED: - return rialto::SessionServerState::UNINITIALIZED; - case firebolt::rialto::common::SessionServerState::INACTIVE: - return rialto::SessionServerState::INACTIVE; - case firebolt::rialto::common::SessionServerState::ACTIVE: - return rialto::SessionServerState::ACTIVE; - case firebolt::rialto::common::SessionServerState::NOT_RUNNING: - return rialto::SessionServerState::NOT_RUNNING; - case firebolt::rialto::common::SessionServerState::ERROR: - return rialto::SessionServerState::ERROR; - } - return rialto::SessionServerState::ERROR; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -ApplicationManagementServer::ApplicationManagementServer( - const std::shared_ptr &serverFactory, - const std::shared_ptr &serverManagerModuleFactory, - service::ISessionServerManager &sessionServerManager) - : m_ipcServer{serverFactory->create()}, m_service{serverManagerModuleFactory->create(sessionServerManager)} -{ -} - -ApplicationManagementServer::~ApplicationManagementServer() -{ - stop(); - if (m_ipcServerThread.joinable()) - { - m_ipcServerThread.join(); - } -} - -bool ApplicationManagementServer::initialize(int socket) -{ - RIALTO_SERVER_LOG_INFO("Initializing ApplicationManagementServer, socket: %d", socket); - if (!m_ipcServer) - { - RIALTO_SERVER_LOG_ERROR("Failed to initialize ApplicationManagementServer - Ipc server instance is NULL"); - return false; - } - - m_ipcClient = m_ipcServer->addClient(socket, std::bind(&ApplicationManagementServer::onClientDisconnected, this, - std::placeholders::_1)); - if (!m_ipcClient) - { - RIALTO_SERVER_LOG_ERROR("Failed to initialize ApplicationManagementServer - Client is NULL"); - return false; - } - m_ipcClient->exportService(m_service); - RIALTO_SERVER_LOG_MIL("ApplicationManagementServer initialized"); - return true; -} - -bool ApplicationManagementServer::sendStateChangedEvent(const common::SessionServerState &state) -{ - if (!m_ipcClient->isConnected()) - { - return false; - } - auto stateChangedEvent = std::make_shared<::rialto::StateChangedEvent>(); - stateChangedEvent->set_sessionserverstate(convertSessionServerState(state)); - m_ipcClient->sendEvent(stateChangedEvent); - return true; -} - -void ApplicationManagementServer::start() -{ - m_ipcServerThread = std::thread( - [this]() - { - while (m_ipcServer->process() && m_ipcClient && m_ipcClient->isConnected()) - { - m_ipcServer->wait(-1); - } - }); -} - -void ApplicationManagementServer::stop() -{ - if (m_ipcClient && m_ipcClient->isConnected()) - { - m_ipcClient->disconnect(); - } -} - -void ApplicationManagementServer::onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) -{ - RIALTO_SERVER_LOG_WARN("Rialto Server Manager disconnected"); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/ControlClientServerInternal.cpp b/middleware/rialto-client/media/server/ipc/source/ControlClientServerInternal.cpp deleted file mode 100644 index c7d9741a5..000000000 --- a/middleware/rialto-client/media/server/ipc/source/ControlClientServerInternal.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ControlClientServerInternal.h" -#include "RialtoServerLogging.h" -#include "controlmodule.pb.h" -#include - -namespace -{ -firebolt::rialto::ApplicationStateChangeEvent_ApplicationState -convertApplicationState(const firebolt::rialto::ApplicationState &state) -{ - switch (state) - { - case firebolt::rialto::ApplicationState::RUNNING: - return firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_RUNNING; - case firebolt::rialto::ApplicationState::INACTIVE: - return firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_INACTIVE; - case firebolt::rialto::ApplicationState::UNKNOWN: - break; - // do nothing - } - return firebolt::rialto::ApplicationStateChangeEvent_ApplicationState_UNKNOWN; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -ControlClientServerInternal::ControlClientServerInternal(int controlId, - const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) - : m_kControlId{controlId}, m_ipcClient{ipcClient} -{ -} - -void ControlClientServerInternal::notifyApplicationState(ApplicationState state) -{ - RIALTO_SERVER_LOG_DEBUG("Sending ApplicationStateChangeEvent"); - - auto event = std::make_shared(); - event->set_control_handle(m_kControlId); - event->set_application_state(convertApplicationState(state)); - - m_ipcClient->sendEvent(event); -} - -void ControlClientServerInternal::ping(uint32_t id) -{ - RIALTO_SERVER_LOG_DEBUG("Sending PingEvent with id: %d", id); - - auto event = std::make_shared(); - event->set_control_handle(m_kControlId); - event->set_id(id); - - m_ipcClient->sendEvent(event); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/ControlModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/ControlModuleService.cpp deleted file mode 100644 index 40f930c40..000000000 --- a/middleware/rialto-client/media/server/ipc/source/ControlModuleService.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ControlModuleService.h" -#include "ControlClientServerInternal.h" -#include "IPlaybackService.h" -#include "RialtoServerLogging.h" -#include "SchemaVersion.h" -#include -#include -#include - -namespace -{ -int generateControlId() -{ - static int id{0}; - return id++; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -std::shared_ptr IControlModuleServiceFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the rialto control module service factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr ControlModuleServiceFactory::create(service::IPlaybackService &playbackService, - service::IControlService &controlService) const -{ - std::shared_ptr controlModule; - - try - { - controlModule = std::make_shared(playbackService, controlService); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the rialto control module service, reason: %s", e.what()); - } - - return controlModule; -} - -ControlModuleService::ControlModuleService(service::IPlaybackService &playbackService, - service::IControlService &controlService) - : m_playbackService{playbackService}, m_controlService{controlService} -{ -} - -ControlModuleService::~ControlModuleService() -{ - for (const auto &controlIds : m_controlIds) - { - for (int id : controlIds.second) - { - m_controlService.removeControl(id); - } - } -} - -void ControlModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client Connected!"); - m_controlIds.emplace(ipcClient, std::set()); - ipcClient->exportService(shared_from_this()); -} - -void ControlModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client disconnected!"); - auto controlIdsIter = m_controlIds.find(ipcClient); - if (m_controlIds.end() != controlIdsIter) - { - for (int id : controlIdsIter->second) - { - m_controlService.removeControl(id); - } - m_controlIds.erase(controlIdsIter); - } -} - -void ControlModuleService::getSharedMemory(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetSharedMemoryRequest *request, - ::firebolt::rialto::GetSharedMemoryResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - int32_t fd; - uint32_t size; - if (!m_playbackService.getSharedMemory(fd, size)) - { - RIALTO_SERVER_LOG_ERROR("getSharedMemory failed"); - controller->SetFailed("Operation failed"); - done->Run(); - return; - } - response->set_fd(fd); - response->set_size(size); - done->Run(); -} - -void ControlModuleService::registerClient(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::RegisterClientRequest *request, - ::firebolt::rialto::RegisterClientResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - const auto kCurrentSchemaVersion{common::getCurrentSchemaVersion()}; - if (request->has_client_schema_version()) - { - const firebolt::rialto::common::SchemaVersion kClientSchemaVersion{request->client_schema_version().major(), - request->client_schema_version().minor(), - request->client_schema_version().patch()}; - RIALTO_SERVER_LOG_DEBUG("Server schema version: %s, client schema version: %s", - kCurrentSchemaVersion.str().c_str(), kClientSchemaVersion.str().c_str()); - if (!kCurrentSchemaVersion.isCompatible(kClientSchemaVersion)) - { - RIALTO_SERVER_LOG_ERROR("Server and client schema versions not compatible"); - controller->SetFailed("Server and client schema versions not compatible"); - done->Run(); - return; - } - } - else - { - RIALTO_SERVER_LOG_WARN("Client schema version not present in RegisterClientRequest message"); - } - const int kControlId{generateControlId()}; - auto ipcClient = ipcController->getClient(); - auto controlClient{std::make_shared(kControlId, ipcClient)}; - m_controlService.addControl(kControlId, controlClient); - m_controlIds[ipcClient].insert(kControlId); - response->set_control_handle(kControlId); - response->mutable_server_schema_version()->set_major(kCurrentSchemaVersion.major()); - response->mutable_server_schema_version()->set_minor(kCurrentSchemaVersion.minor()); - response->mutable_server_schema_version()->set_patch(kCurrentSchemaVersion.patch()); - done->Run(); -} - -void ControlModuleService::ack(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::AckRequest *request, ::firebolt::rialto::AckResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_controlService.ack(request->control_handle(), request->id())) - { - RIALTO_SERVER_LOG_ERROR("ack failed"); - controller->SetFailed("Operation failed"); - done->Run(); - return; - } - done->Run(); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/IpcFactory.cpp b/middleware/rialto-client/media/server/ipc/source/IpcFactory.cpp deleted file mode 100644 index 0849fe8dd..000000000 --- a/middleware/rialto-client/media/server/ipc/source/IpcFactory.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "IpcFactory.h" -#include "ApplicationManagementServer.h" -#include "IControlModuleService.h" -#include "IIpcServer.h" -#include "IMediaKeysCapabilitiesModuleService.h" -#include "IMediaKeysModuleService.h" -#include "IMediaPipelineCapabilitiesModuleService.h" -#include "IMediaPipelineModuleService.h" -#include "IServerManagerModuleServiceFactory.h" -#include "IWebAudioPlayerModuleService.h" -#include "SessionManagementServer.h" - -namespace firebolt::rialto::server::ipc -{ -std::unique_ptr -IpcFactory::createApplicationManagementServer(service::ISessionServerManager &sessionServerManager) const -{ - return std::make_unique< - ApplicationManagementServer>(firebolt::rialto::ipc::IServerFactory::createFactory(), - firebolt::rialto::server::ipc::IServerManagerModuleServiceFactory::createFactory(), - sessionServerManager); -} - -std::unique_ptr -IpcFactory::createSessionManagementServer(service::IPlaybackService &playbackService, service::ICdmService &cdmService, - service::IControlService &controlService) const -{ - return std::make_unique< - SessionManagementServer>(firebolt::rialto::ipc::IServerFactory::createFactory(), - firebolt::rialto::server::ipc::IMediaPipelineModuleServiceFactory::createFactory(), - firebolt::rialto::server::ipc::IMediaPipelineCapabilitiesModuleServiceFactory::createFactory(), - firebolt::rialto::server::ipc::IMediaKeysModuleServiceFactory::createFactory(), - firebolt::rialto::server::ipc::IMediaKeysCapabilitiesModuleServiceFactory::createFactory(), - firebolt::rialto::server::ipc::IWebAudioPlayerModuleServiceFactory::createFactory(), - firebolt::rialto::server::ipc::IControlModuleServiceFactory::createFactory(), - playbackService, cdmService, controlService); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaKeysCapabilitiesModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/MediaKeysCapabilitiesModuleService.cpp deleted file mode 100644 index 23eb482aa..000000000 --- a/middleware/rialto-client/media/server/ipc/source/MediaKeysCapabilitiesModuleService.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include "ICdmService.h" -#include "MediaKeysCapabilitiesModuleService.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::ipc -{ -std::shared_ptr IMediaKeysCapabilitiesModuleServiceFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media keys capabilities module service factory, reason: %s", - e.what()); - } - - return factory; -} - -std::shared_ptr -MediaKeysCapabilitiesModuleServiceFactory::create(service::ICdmService &cdmService) const -{ - std::shared_ptr mediaKeysCapabilitiesModule; - - try - { - mediaKeysCapabilitiesModule = std::make_shared(cdmService); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media keys capabilities module service, reason: %s", e.what()); - } - - return mediaKeysCapabilitiesModule; -} - -MediaKeysCapabilitiesModuleService::MediaKeysCapabilitiesModuleService(service::ICdmService &cdmService) - : m_cdmService{cdmService} -{ -} - -MediaKeysCapabilitiesModuleService::~MediaKeysCapabilitiesModuleService() {} - -void MediaKeysCapabilitiesModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client Connected!"); - ipcClient->exportService(shared_from_this()); -} - -void MediaKeysCapabilitiesModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client disconnected!"); -} - -void MediaKeysCapabilitiesModuleService::getSupportedKeySystems( - ::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSupportedKeySystemsRequest *request, - ::firebolt::rialto::GetSupportedKeySystemsResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - std::vector keySystems = m_cdmService.getSupportedKeySystems(); - - for (auto it = keySystems.begin(); it != keySystems.end(); it++) - { - response->add_key_systems(*it); - } - done->Run(); -} - -void MediaKeysCapabilitiesModuleService::supportsKeySystem(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SupportsKeySystemRequest *request, - ::firebolt::rialto::SupportsKeySystemResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - response->set_is_supported(m_cdmService.supportsKeySystem(request->key_system())); - done->Run(); -} - -void MediaKeysCapabilitiesModuleService::getSupportedKeySystemVersion( - ::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSupportedKeySystemVersionRequest *request, - ::firebolt::rialto::GetSupportedKeySystemVersionResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - std::string version; - bool status = m_cdmService.getSupportedKeySystemVersion(request->key_system(), version); - if (status) - { - response->set_version(version); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to get the key system version"); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaKeysCapabilitiesModuleService::isServerCertificateSupported( - ::google::protobuf::RpcController *controller, const ::firebolt::rialto::IsServerCertificateSupportedRequest *request, - ::firebolt::rialto::IsServerCertificateSupportedResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - response->set_is_supported(m_cdmService.isServerCertificateSupported(request->key_system())); - done->Run(); -} - -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaKeysClient.cpp b/middleware/rialto-client/media/server/ipc/source/MediaKeysClient.cpp deleted file mode 100644 index d45f906fa..000000000 --- a/middleware/rialto-client/media/server/ipc/source/MediaKeysClient.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaKeysClient.h" -#include "IIpcServer.h" -#include "RialtoServerLogging.h" -#include "mediakeysmodule.pb.h" - -namespace -{ -firebolt::rialto::KeyStatusesChangedEvent_KeyStatus convertKeyStatus(const firebolt::rialto::KeyStatus &keyStatus) -{ - switch (keyStatus) - { - case firebolt::rialto::KeyStatus::USABLE: - { - return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_USABLE; - } - case firebolt::rialto::KeyStatus::EXPIRED: - { - return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_EXPIRED; - } - case firebolt::rialto::KeyStatus::OUTPUT_RESTRICTED: - { - return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_OUTPUT_RESTRICTED; - } - case firebolt::rialto::KeyStatus::PENDING: - { - return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_PENDING; - } - case firebolt::rialto::KeyStatus::INTERNAL_ERROR: - { - return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_INTERNAL_ERROR; - } - case firebolt::rialto::KeyStatus::RELEASED: - { - return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_RELEASED; - } - } - return firebolt::rialto::KeyStatusesChangedEvent_KeyStatus_INTERNAL_ERROR; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -MediaKeysClient::MediaKeysClient(int mediaKeysHandle, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) - : m_mediaKeysHandle{mediaKeysHandle}, m_ipcClient{ipcClient} -{ -} - -MediaKeysClient::~MediaKeysClient() {} - -void MediaKeysClient::onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, - const std::string &url) -{ - RIALTO_SERVER_LOG_DEBUG("Sending LicenseRequestEvent"); - - auto event = std::make_shared(); - for (auto it = licenseRequestMessage.begin(); it != licenseRequestMessage.end(); it++) - { - event->add_license_request_message(*it); - } - event->set_media_keys_handle(m_mediaKeysHandle); - event->set_key_session_id(keySessionId); - event->set_url(url); - - m_ipcClient->sendEvent(event); -} - -void MediaKeysClient::onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) -{ - RIALTO_SERVER_LOG_DEBUG("Sending LicenseRenewalEvent"); - - auto event = std::make_shared(); - for (auto it = licenseRenewalMessage.begin(); it != licenseRenewalMessage.end(); it++) - { - event->add_license_renewal_message(*it); - } - event->set_media_keys_handle(m_mediaKeysHandle); - event->set_key_session_id(keySessionId); - - m_ipcClient->sendEvent(event); -} - -void MediaKeysClient::onKeyStatusesChanged(int32_t keySessionId, const KeyStatusVector &keyStatuses) -{ - RIALTO_SERVER_LOG_DEBUG("Sending KeyStatusesChangedEvent"); - - auto event = std::make_shared(); - for (auto it = keyStatuses.begin(); it != keyStatuses.end(); it++) - { - ::firebolt::rialto::KeyStatusesChangedEvent_KeyStatusPair *keyStatusPair = event->add_key_statuses(); - for (auto it2 = it->first.begin(); it2 != it->first.end(); it2++) - { - keyStatusPair->add_key_id(*it2); - } - keyStatusPair->set_key_status(convertKeyStatus(it->second)); - } - event->set_media_keys_handle(m_mediaKeysHandle); - event->set_key_session_id(keySessionId); - - m_ipcClient->sendEvent(event); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaKeysModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/MediaKeysModuleService.cpp deleted file mode 100644 index 4ef3b6aab..000000000 --- a/middleware/rialto-client/media/server/ipc/source/MediaKeysModuleService.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaKeysModuleService.h" -#include "ICdmService.h" -#include "MediaKeysClient.h" -#include "RialtoServerLogging.h" -#include -#include -#include - -namespace -{ -int generateHandle() -{ - static int mediaKeysHandle{0}; - return mediaKeysHandle++; -} - -firebolt::rialto::ProtoMediaKeyErrorStatus -convertMediaKeyErrorStatus(const firebolt::rialto::MediaKeyErrorStatus &errorStatus) -{ - switch (errorStatus) - { - case firebolt::rialto::MediaKeyErrorStatus::OK: - { - return firebolt::rialto::ProtoMediaKeyErrorStatus::OK; - } - case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: - { - return firebolt::rialto::ProtoMediaKeyErrorStatus::BAD_SESSION_ID; - } - case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: - { - return firebolt::rialto::ProtoMediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED; - } - case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: - { - return firebolt::rialto::ProtoMediaKeyErrorStatus::BUFFER_TOO_SMALL; - } - case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: - { - return firebolt::rialto::ProtoMediaKeyErrorStatus::NOT_SUPPORTED; - } - case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: - { - return firebolt::rialto::ProtoMediaKeyErrorStatus::INVALID_STATE; - } - case firebolt::rialto::MediaKeyErrorStatus::FAIL: - { - return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; - } - } - return firebolt::rialto::ProtoMediaKeyErrorStatus::FAIL; -} -firebolt::rialto::KeySessionType -convertKeySessionType(const firebolt::rialto::CreateKeySessionRequest_KeySessionType &protoKeySessionType) -{ - switch (protoKeySessionType) - { - case firebolt::rialto::CreateKeySessionRequest_KeySessionType::CreateKeySessionRequest_KeySessionType_TEMPORARY: - return firebolt::rialto::KeySessionType::TEMPORARY; - case firebolt::rialto::CreateKeySessionRequest_KeySessionType::CreateKeySessionRequest_KeySessionType_PERSISTENT_LICENCE: - return firebolt::rialto::KeySessionType::PERSISTENT_LICENCE; - case firebolt::rialto::CreateKeySessionRequest_KeySessionType::CreateKeySessionRequest_KeySessionType_PERSISTENT_RELEASE_MESSAGE: - return firebolt::rialto::KeySessionType::PERSISTENT_RELEASE_MESSAGE; - default: - return firebolt::rialto::KeySessionType::UNKNOWN; - } -} -firebolt::rialto::InitDataType covertInitDataType(firebolt::rialto::GenerateRequestRequest_InitDataType protoInitDataType) -{ - switch (protoInitDataType) - { - case firebolt::rialto::GenerateRequestRequest_InitDataType::GenerateRequestRequest_InitDataType_CENC: - return firebolt::rialto::InitDataType::CENC; - case firebolt::rialto::GenerateRequestRequest_InitDataType::GenerateRequestRequest_InitDataType_KEY_IDS: - return firebolt::rialto::InitDataType::KEY_IDS; - case firebolt::rialto::GenerateRequestRequest_InitDataType::GenerateRequestRequest_InitDataType_WEBM: - return firebolt::rialto::InitDataType::WEBM; - case firebolt::rialto::GenerateRequestRequest_InitDataType::GenerateRequestRequest_InitDataType_DRMHEADER: - return firebolt::rialto::InitDataType::DRMHEADER; - default: - return firebolt::rialto::InitDataType::UNKNOWN; - } -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -std::shared_ptr IMediaKeysModuleServiceFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media keys module service factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr MediaKeysModuleServiceFactory::create(service::ICdmService &cdmService) const -{ - std::shared_ptr mediaKeysModule; - - try - { - mediaKeysModule = std::make_shared(cdmService); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media keys module service, reason: %s", e.what()); - } - - return mediaKeysModule; -} - -MediaKeysModuleService::MediaKeysModuleService(service::ICdmService &cdmService) : m_cdmService{cdmService} {} - -MediaKeysModuleService::~MediaKeysModuleService() {} - -void MediaKeysModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client Connected!"); - { - m_clientMediaKeysHandles.emplace(ipcClient, std::set()); - } - ipcClient->exportService(shared_from_this()); -} - -void MediaKeysModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client disconnected!"); - std::set mediaKeysHandles; - { - auto handleIter = m_clientMediaKeysHandles.find(ipcClient); - if (handleIter == m_clientMediaKeysHandles.end()) - { - RIALTO_SERVER_LOG_ERROR("unknown client disconnected"); - return; - } - mediaKeysHandles = handleIter->second; // copy to avoid deadlock - m_clientMediaKeysHandles.erase(handleIter); - } - for (const auto &mediaKeysHandle : mediaKeysHandles) - { - m_cdmService.destroyMediaKeys(mediaKeysHandle); - } -} - -void MediaKeysModuleService::createMediaKeys(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CreateMediaKeysRequest *request, - ::firebolt::rialto::CreateMediaKeysResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - int mediaKeysHandle = generateHandle(); - bool mediaKeysCreated = m_cdmService.createMediaKeys(mediaKeysHandle, request->key_system()); - if (mediaKeysCreated) - { - // Assume that IPC library works well and client is present - m_clientMediaKeysHandles[ipcController->getClient()].insert(mediaKeysHandle); - response->set_media_keys_handle(mediaKeysHandle); - } - else - { - RIALTO_SERVER_LOG_ERROR("Create media keys failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaKeysModuleService::destroyMediaKeys(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DestroyMediaKeysRequest *request, - ::firebolt::rialto::DestroyMediaKeysResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - if (!m_cdmService.destroyMediaKeys(request->media_keys_handle())) - { - RIALTO_SERVER_LOG_ERROR("Destroy session failed"); - controller->SetFailed("Operation failed"); - done->Run(); - return; - } - auto handleIter = m_clientMediaKeysHandles.find(ipcController->getClient()); - if (handleIter != m_clientMediaKeysHandles.end()) - { - handleIter->second.erase(request->media_keys_handle()); - } - done->Run(); -} - -void MediaKeysModuleService::containsKey(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::ContainsKeyRequest *request, - ::firebolt::rialto::ContainsKeyResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result = m_cdmService.containsKey(request->media_keys_handle(), request->key_session_id(), - std::vector{request->key_id().begin(), request->key_id().end()}); - response->set_contains_key(result); - done->Run(); -} - -void MediaKeysModuleService::createKeySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CreateKeySessionRequest *request, - ::firebolt::rialto::CreateKeySessionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - int32_t keySessionId; - MediaKeyErrorStatus status = - m_cdmService.createKeySession(request->media_keys_handle(), convertKeySessionType(request->session_type()), - std::make_shared(request->media_keys_handle(), - ipcController->getClient()), - request->is_ldl(), keySessionId); - if (MediaKeyErrorStatus::OK == status) - { - response->set_key_session_id(keySessionId); - } - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::generateRequest(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GenerateRequestRequest *request, - ::firebolt::rialto::GenerateRequestResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.generateRequest(request->media_keys_handle(), request->key_session_id(), - covertInitDataType(request->init_data_type()), - std::vector{request->init_data().begin(), - request->init_data().end()}); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::loadSession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::LoadSessionRequest *request, - ::firebolt::rialto::LoadSessionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.loadSession(request->media_keys_handle(), request->key_session_id()); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::updateSession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::UpdateSessionRequest *request, - ::firebolt::rialto::UpdateSessionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.updateSession(request->media_keys_handle(), request->key_session_id(), - std::vector{request->response_data().begin(), - request->response_data().end()}); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::setDrmHeader(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetDrmHeaderRequest *request, - ::firebolt::rialto::SetDrmHeaderResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.setDrmHeader(request->media_keys_handle(), request->key_session_id(), - std::vector{request->request_data().begin(), - request->request_data().end()}); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::closeKeySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CloseKeySessionRequest *request, - ::firebolt::rialto::CloseKeySessionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.closeKeySession(request->media_keys_handle(), request->key_session_id()); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::removeKeySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::RemoveKeySessionRequest *request, - ::firebolt::rialto::RemoveKeySessionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.removeKeySession(request->media_keys_handle(), request->key_session_id()); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::deleteDrmStore(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DeleteDrmStoreRequest *request, - ::firebolt::rialto::DeleteDrmStoreResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.deleteDrmStore(request->media_keys_handle()); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::deleteKeyStore(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DeleteKeyStoreRequest *request, - ::firebolt::rialto::DeleteKeyStoreResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.deleteKeyStore(request->media_keys_handle()); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::getDrmStoreHash(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetDrmStoreHashRequest *request, - ::firebolt::rialto::GetDrmStoreHashResponse *response, - ::google::protobuf::Closure *done) -{ - std::vector drmStoreHash; - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.getDrmStoreHash(request->media_keys_handle(), drmStoreHash); - response->set_error_status(convertMediaKeyErrorStatus(status)); - for (const auto &item : drmStoreHash) - { - response->add_drm_store_hash(item); - } - done->Run(); -} - -void MediaKeysModuleService::getKeyStoreHash(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetKeyStoreHashRequest *request, - ::firebolt::rialto::GetKeyStoreHashResponse *response, - ::google::protobuf::Closure *done) -{ - std::vector keyStoreHash; - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.getKeyStoreHash(request->media_keys_handle(), keyStoreHash); - response->set_error_status(convertMediaKeyErrorStatus(status)); - for (const auto &item : keyStoreHash) - { - response->add_key_store_hash(item); - } - done->Run(); -} - -void MediaKeysModuleService::getLdlSessionsLimit(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetLdlSessionsLimitRequest *request, - ::firebolt::rialto::GetLdlSessionsLimitResponse *response, - ::google::protobuf::Closure *done) -{ - uint32_t ldlLimit{0}; - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.getLdlSessionsLimit(request->media_keys_handle(), ldlLimit); - response->set_error_status(convertMediaKeyErrorStatus(status)); - response->set_ldl_limit(ldlLimit); - done->Run(); -} - -void MediaKeysModuleService::getLastDrmError(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetLastDrmErrorRequest *request, - ::firebolt::rialto::GetLastDrmErrorResponse *response, - ::google::protobuf::Closure *done) -{ - uint32_t errorCode{0}; - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = - m_cdmService.getLastDrmError(request->media_keys_handle(), request->key_session_id(), errorCode); - response->set_error_status(convertMediaKeyErrorStatus(status)); - response->set_error_code(errorCode); - done->Run(); -} - -void MediaKeysModuleService::getDrmTime(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetDrmTimeRequest *request, - ::firebolt::rialto::GetDrmTimeResponse *response, - ::google::protobuf::Closure *done) -{ - uint64_t drmTime{0}; - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.getDrmTime(request->media_keys_handle(), drmTime); - response->set_error_status(convertMediaKeyErrorStatus(status)); - response->set_drm_time(drmTime); - done->Run(); -} - -void MediaKeysModuleService::getCdmKeySessionId(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetCdmKeySessionIdRequest *request, - ::firebolt::rialto::GetCdmKeySessionIdResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - std::string cdmKeySessionId; - MediaKeyErrorStatus status = - m_cdmService.getCdmKeySessionId(request->media_keys_handle(), request->key_session_id(), cdmKeySessionId); - response->set_error_status(convertMediaKeyErrorStatus(status)); - response->set_cdm_key_session_id(cdmKeySessionId); - done->Run(); -} - -void MediaKeysModuleService::releaseKeySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::ReleaseKeySessionRequest *request, - ::firebolt::rialto::ReleaseKeySessionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.releaseKeySession(request->media_keys_handle(), request->key_session_id()); - response->set_error_status(convertMediaKeyErrorStatus(status)); - done->Run(); -} - -void MediaKeysModuleService::getMetricSystemData(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetMetricSystemDataRequest *request, - ::firebolt::rialto::GetMetricSystemDataResponse *response, - ::google::protobuf::Closure *done) -{ - std::vector buffer; - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status = m_cdmService.getMetricSystemData(request->media_keys_handle(), buffer); - response->set_error_status(convertMediaKeyErrorStatus(status)); - for (const auto &buf : buffer) - { - response->add_buffer(buf); - } - done->Run(); -} - -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp deleted file mode 100644 index dc73b0ee6..000000000 --- a/middleware/rialto-client/media/server/ipc/source/MediaPipelineCapabilitiesModuleService.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaPipelineCapabilitiesModuleService.h" -#include "RialtoCommonModule.h" -#include "RialtoServerLogging.h" -#include - -namespace firebolt::rialto::server::ipc -{ -std::shared_ptr -IMediaPipelineCapabilitiesModuleServiceFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media player capabilities module service factory, reason: %s", - e.what()); - } - - return factory; -} - -std::shared_ptr -MediaPipelineCapabilitiesModuleServiceFactory::create(service::IMediaPipelineService &mediaPipelineService) const -{ - std::shared_ptr mediaPipelineCapabilitiesModule; - - try - { - mediaPipelineCapabilitiesModule = std::make_shared(mediaPipelineService); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media player module service, reason: %s", e.what()); - } - - return mediaPipelineCapabilitiesModule; -} - -MediaPipelineCapabilitiesModuleService::MediaPipelineCapabilitiesModuleService( - service::IMediaPipelineService &mediaPipelineService) - : m_mediaPipelineService{mediaPipelineService} -{ -} - -MediaPipelineCapabilitiesModuleService::~MediaPipelineCapabilitiesModuleService() {} - -void MediaPipelineCapabilitiesModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client Connected!"); - ipcClient->exportService(shared_from_this()); -} - -void MediaPipelineCapabilitiesModuleService::clientDisconnected( - const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client disconnected!"); -} - -void MediaPipelineCapabilitiesModuleService::getSupportedMimeTypes( - ::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSupportedMimeTypesRequest *request, - ::firebolt::rialto::GetSupportedMimeTypesResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - firebolt::rialto::MediaSourceType sourceType = convertMediaSourceType(request->media_type()); - std::vector supportedMimeTypes = m_mediaPipelineService.getSupportedMimeTypes(sourceType); - - for (std::string &mimeType : supportedMimeTypes) - { - response->add_mime_types(mimeType); - } - - done->Run(); -} - -void MediaPipelineCapabilitiesModuleService::isMimeTypeSupported( - ::google::protobuf::RpcController *controller, const ::firebolt::rialto::IsMimeTypeSupportedRequest *request, - ::firebolt::rialto::IsMimeTypeSupportedResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - bool isSupported = m_mediaPipelineService.isMimeTypeSupported(request->mime_type()); - response->set_is_supported(isSupported); - - done->Run(); -} - -void MediaPipelineCapabilitiesModuleService::getSupportedProperties( - ::google::protobuf::RpcController *controller, const ::firebolt::rialto::GetSupportedPropertiesRequest *request, - ::firebolt::rialto::GetSupportedPropertiesResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - firebolt::rialto::MediaSourceType mediaType = convertMediaSourceType(request->media_type()); - std::vector propertiesToSearch{request->property_names().begin(), request->property_names().end()}; - - std::vector supportedProperties{ - m_mediaPipelineService.getSupportedProperties(mediaType, propertiesToSearch)}; - - for (const std::string &property : supportedProperties) - { - response->add_supported_properties(property.c_str()); - } - - done->Run(); -} - -void MediaPipelineCapabilitiesModuleService::isVideoMaster(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::IsVideoMasterRequest *request, - ::firebolt::rialto::IsVideoMasterResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - bool isMaster{false}; - if (!m_mediaPipelineService.isVideoMaster(isMaster)) - { - RIALTO_SERVER_LOG_ERROR("isVideoMaster check failed"); - controller->SetFailed("isVideoMaster check failed"); - done->Run(); - return; - } - - response->set_is_video_master(isMaster); - - done->Run(); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaPipelineClient.cpp b/middleware/rialto-client/media/server/ipc/source/MediaPipelineClient.cpp deleted file mode 100644 index d3542a1e4..000000000 --- a/middleware/rialto-client/media/server/ipc/source/MediaPipelineClient.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaPipelineClient.h" -#include "RialtoServerLogging.h" -#include "mediapipelinemodule.pb.h" -#include - -namespace -{ -firebolt::rialto::PlaybackStateChangeEvent_PlaybackState -convertPlaybackState(const firebolt::rialto::PlaybackState &playbackState) -{ - switch (playbackState) - { - case firebolt::rialto::PlaybackState::UNKNOWN: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_UNKNOWN; - } - case firebolt::rialto::PlaybackState::IDLE: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_IDLE; - } - case firebolt::rialto::PlaybackState::PLAYING: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PLAYING; - } - case firebolt::rialto::PlaybackState::PAUSED: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_PAUSED; - } - case firebolt::rialto::PlaybackState::SEEKING: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEKING; - } - case firebolt::rialto::PlaybackState::SEEK_DONE: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_SEEK_DONE; - } - case firebolt::rialto::PlaybackState::STOPPED: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_STOPPED; - } - case firebolt::rialto::PlaybackState::END_OF_STREAM: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_END_OF_STREAM; - } - case firebolt::rialto::PlaybackState::FAILURE: - { - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_FAILURE; - } - } - return firebolt::rialto::PlaybackStateChangeEvent_PlaybackState_UNKNOWN; -} - -firebolt::rialto::NetworkStateChangeEvent_NetworkState -convertNetworkState(const firebolt::rialto::NetworkState &networkState) -{ - switch (networkState) - { - case firebolt::rialto::NetworkState::UNKNOWN: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_UNKNOWN; - } - case firebolt::rialto::NetworkState::IDLE: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_IDLE; - } - case firebolt::rialto::NetworkState::BUFFERING: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING; - } - case firebolt::rialto::NetworkState::BUFFERING_PROGRESS: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERING_PROGRESS; - } - case firebolt::rialto::NetworkState::BUFFERED: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_BUFFERED; - } - case firebolt::rialto::NetworkState::STALLED: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_STALLED; - } - case firebolt::rialto::NetworkState::FORMAT_ERROR: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_FORMAT_ERROR; - } - case firebolt::rialto::NetworkState::NETWORK_ERROR: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_NETWORK_ERROR; - } - case firebolt::rialto::NetworkState::DECODE_ERROR: - { - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_DECODE_ERROR; - } - } - return firebolt::rialto::NetworkStateChangeEvent_NetworkState_UNKNOWN; -} - -firebolt::rialto::PlaybackErrorEvent_PlaybackError convertPlaybackError(const firebolt::rialto::PlaybackError &playbackError) -{ - switch (playbackError) - { - case firebolt::rialto::PlaybackError::UNKNOWN: - { - return firebolt::rialto::PlaybackErrorEvent_PlaybackError_UNKNOWN; - } - case firebolt::rialto::PlaybackError::DECRYPTION: - { - return firebolt::rialto::PlaybackErrorEvent_PlaybackError_DECRYPTION; - } - } - return firebolt::rialto::PlaybackErrorEvent_PlaybackError_UNKNOWN; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -MediaPipelineClient::MediaPipelineClient(int sessionId, const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) - : m_sessionId{sessionId}, m_ipcClient{ipcClient} -{ -} - -MediaPipelineClient::~MediaPipelineClient() {} - -void MediaPipelineClient::notifyDuration(int64_t duration) -{ - RIALTO_SERVER_LOG_WARN("Notify Duration not supported"); -} - -void MediaPipelineClient::notifyPosition(int64_t position) -{ - RIALTO_SERVER_LOG_DEBUG("Sending PositionChangeEvent"); - - auto event = std::make_shared(); - event->set_session_id(m_sessionId); - event->set_position(position); - - m_ipcClient->sendEvent(event); -} - -void MediaPipelineClient::notifyNativeSize(uint32_t width, uint32_t height, double aspect) -{ - RIALTO_SERVER_LOG_WARN("Notify Native Size not supported"); -} - -void MediaPipelineClient::notifyNetworkState(NetworkState state) -{ - RIALTO_SERVER_LOG_DEBUG("Sending NetworkStateChangeEvent"); - - auto event = std::make_shared(); - event->set_session_id(m_sessionId); - event->set_state(convertNetworkState(state)); - - m_ipcClient->sendEvent(event); -} - -void MediaPipelineClient::notifyPlaybackState(PlaybackState state) -{ - RIALTO_SERVER_LOG_DEBUG("Sending PlaybackStateChangeEvent..."); - - auto event = std::make_shared(); - event->set_session_id(m_sessionId); - event->set_state(convertPlaybackState(state)); - - m_ipcClient->sendEvent(event); -} - -void MediaPipelineClient::notifyVideoData(bool hasData) -{ - RIALTO_SERVER_LOG_WARN("Notify Video Data not supported"); -} - -void MediaPipelineClient::notifyAudioData(bool hasData) -{ - RIALTO_SERVER_LOG_WARN("Notify Audio Data not supported"); -} - -void MediaPipelineClient::notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, - const std::shared_ptr &shmInfo) -{ - RIALTO_SERVER_LOG_DEBUG("Sending NeedMediaDataEvent..."); - - auto event = std::make_shared(); - event->set_session_id(m_sessionId); - event->set_source_id(sourceId); - event->set_request_id(needDataRequestId); - event->set_frame_count(frameCount); - event->mutable_shm_info()->set_max_metadata_bytes(shmInfo->maxMetadataBytes); - event->mutable_shm_info()->set_metadata_offset(shmInfo->metadataOffset); - event->mutable_shm_info()->set_media_data_offset(shmInfo->mediaDataOffset); - event->mutable_shm_info()->set_max_media_bytes(shmInfo->maxMediaBytes); - - m_ipcClient->sendEvent(event); -} - -void MediaPipelineClient::notifyCancelNeedMediaData(int32_t sourceId) -{ - RIALTO_SERVER_LOG_WARN("Notify Cancel Need Media Data not supported"); -} - -void MediaPipelineClient::notifyQos(int32_t sourceId, const QosInfo &qosInfo) -{ - RIALTO_SERVER_LOG_DEBUG("Sending QosEvent..."); - - auto event = std::make_shared(); - event->set_session_id(m_sessionId); - event->set_source_id(sourceId); - event->mutable_qos_info()->set_processed(qosInfo.processed); - event->mutable_qos_info()->set_dropped(qosInfo.dropped); - - m_ipcClient->sendEvent(event); -} - -void MediaPipelineClient::notifyBufferUnderflow(int32_t sourceId) -{ - RIALTO_SERVER_LOG_DEBUG("Sending BufferUnderflowEvent..."); - - auto event = std::make_shared(); - event->set_session_id(m_sessionId); - event->set_source_id(sourceId); - - m_ipcClient->sendEvent(event); -} - -void MediaPipelineClient::notifyPlaybackError(int32_t sourceId, PlaybackError error) -{ - RIALTO_SERVER_LOG_DEBUG("Sending notifyPlaybackError..."); - - auto event = std::make_shared(); - event->set_session_id(m_sessionId); - event->set_source_id(sourceId); - event->set_error(convertPlaybackError(error)); - - m_ipcClient->sendEvent(event); -} - -void MediaPipelineClient::notifySourceFlushed(int32_t sourceId) -{ - RIALTO_SERVER_LOG_DEBUG("Sending SourceFlushedEvent..."); - - auto event = std::make_shared(); - event->set_session_id(m_sessionId); - event->set_source_id(sourceId); - - m_ipcClient->sendEvent(event); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/MediaPipelineModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/MediaPipelineModuleService.cpp deleted file mode 100644 index c74a74f1d..000000000 --- a/middleware/rialto-client/media/server/ipc/source/MediaPipelineModuleService.cpp +++ /dev/null @@ -1,1082 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaPipelineModuleService.h" -#include "IMediaPipelineService.h" -#include "MediaPipelineClient.h" -#include "RialtoCommonModule.h" -#include "RialtoServerLogging.h" -#include -#include -#include -#include - -namespace -{ -int generateSessionId() -{ - static int sessionId{0}; - return sessionId++; -} - -firebolt::rialto::MediaType convertMediaType(const firebolt::rialto::LoadRequest_MediaType &mediaType) -{ - switch (mediaType) - { - case firebolt::rialto::LoadRequest_MediaType::LoadRequest_MediaType_UNKNOWN: - { - return firebolt::rialto::MediaType::UNKNOWN; - } - case firebolt::rialto::LoadRequest_MediaType::LoadRequest_MediaType_MSE: - { - return firebolt::rialto::MediaType::MSE; - } - } - return firebolt::rialto::MediaType::UNKNOWN; -} - -firebolt::rialto::EaseType convertEaseType(const firebolt::rialto::SetVolumeRequest_EaseType &easeType) -{ - switch (easeType) - { - case firebolt::rialto::SetVolumeRequest_EaseType::SetVolumeRequest_EaseType_EASE_LINEAR: - { - return firebolt::rialto::EaseType::EASE_LINEAR; - } - case firebolt::rialto::SetVolumeRequest_EaseType::SetVolumeRequest_EaseType_EASE_IN_CUBIC: - { - return firebolt::rialto::EaseType::EASE_IN_CUBIC; - } - case firebolt::rialto::SetVolumeRequest_EaseType::SetVolumeRequest_EaseType_EASE_OUT_CUBIC: - { - return firebolt::rialto::EaseType::EASE_OUT_CUBIC; - } - } - return firebolt::rialto::EaseType::EASE_LINEAR; -} - -firebolt::rialto::MediaSourceStatus -convertMediaSourceStatus(const firebolt::rialto::HaveDataRequest_MediaSourceStatus &status) -{ - switch (status) - { - case firebolt::rialto::HaveDataRequest_MediaSourceStatus_UNKNOWN: - { - return firebolt::rialto::MediaSourceStatus::ERROR; - } - case firebolt::rialto::HaveDataRequest_MediaSourceStatus_OK: - { - return firebolt::rialto::MediaSourceStatus::OK; - } - case firebolt::rialto::HaveDataRequest_MediaSourceStatus_EOS: - { - return firebolt::rialto::MediaSourceStatus::EOS; - } - case firebolt::rialto::HaveDataRequest_MediaSourceStatus_ERROR: - { - return firebolt::rialto::MediaSourceStatus::ERROR; - } - case firebolt::rialto::HaveDataRequest_MediaSourceStatus_CODEC_CHANGED: - { - return firebolt::rialto::MediaSourceStatus::CODEC_CHANGED; - } - case firebolt::rialto::HaveDataRequest_MediaSourceStatus_NO_AVAILABLE_SAMPLES: - { - return firebolt::rialto::MediaSourceStatus::NO_AVAILABLE_SAMPLES; - } - } - return firebolt::rialto::MediaSourceStatus::ERROR; -} - -firebolt::rialto::SourceConfigType convertConfigType(const firebolt::rialto::AttachSourceRequest_ConfigType &configType) -{ - switch (configType) - { - case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_UNKNOWN: - { - return firebolt::rialto::SourceConfigType::UNKNOWN; - } - case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_AUDIO: - { - return firebolt::rialto::SourceConfigType::AUDIO; - } - case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO: - { - return firebolt::rialto::SourceConfigType::VIDEO; - } - case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_VIDEO_DOLBY_VISION: - { - return firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION; - } - case firebolt::rialto::AttachSourceRequest_ConfigType_CONFIG_TYPE_SUBTITLE: - { - return firebolt::rialto::SourceConfigType::SUBTITLE; - } - } - return firebolt::rialto::SourceConfigType::UNKNOWN; -} - -firebolt::rialto::SegmentAlignment -convertSegmentAlignment(const firebolt::rialto::AttachSourceRequest_SegmentAlignment &alignment) -{ - switch (alignment) - { - case firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_UNDEFINED: - { - return firebolt::rialto::SegmentAlignment::UNDEFINED; - } - case firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_NAL: - { - return firebolt::rialto::SegmentAlignment::NAL; - } - case firebolt::rialto::AttachSourceRequest_SegmentAlignment_ALIGNMENT_AU: - { - return firebolt::rialto::SegmentAlignment::AU; - } - } - - return firebolt::rialto::SegmentAlignment::UNDEFINED; -} - -firebolt::rialto::StreamFormat convertStreamFormat(const firebolt::rialto::AttachSourceRequest_StreamFormat &streamFormat) -{ - switch (streamFormat) - { - case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_RAW: - { - return firebolt::rialto::StreamFormat::RAW; - } - case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_AVC: - { - return firebolt::rialto::StreamFormat::AVC; - } - case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_BYTE_STREAM: - { - return firebolt::rialto::StreamFormat::BYTE_STREAM; - } - case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HVC1: - { - return firebolt::rialto::StreamFormat::HVC1; - } - case firebolt::rialto::AttachSourceRequest_StreamFormat_STREAM_FORMAT_HEV1: - { - return firebolt::rialto::StreamFormat::HEV1; - } - default: - return firebolt::rialto::StreamFormat::UNDEFINED; - } -} - -firebolt::rialto::CodecDataType convertCodecDataType(const firebolt::rialto::AttachSourceRequest_CodecData_Type &type) -{ - if (firebolt::rialto::AttachSourceRequest_CodecData_Type_STRING == type) - { - return firebolt::rialto::CodecDataType::STRING; - } - return firebolt::rialto::CodecDataType::BUFFER; -} - -firebolt::rialto::Format convertFormat(const firebolt::rialto::AttachSourceRequest_AudioConfig_Format &format) -{ - static const std::unordered_map - kFormatConversionMap{ - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S8, firebolt::rialto::Format::S8}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U8, firebolt::rialto::Format::U8}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16LE, firebolt::rialto::Format::S16LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S16BE, firebolt::rialto::Format::S16BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16LE, firebolt::rialto::Format::U16LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U16BE, firebolt::rialto::Format::U16BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32LE, firebolt::rialto::Format::S24_32LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24_32BE, firebolt::rialto::Format::S24_32BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32LE, firebolt::rialto::Format::U24_32LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24_32BE, firebolt::rialto::Format::U24_32BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32LE, firebolt::rialto::Format::S32LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S32BE, firebolt::rialto::Format::S32BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32LE, firebolt::rialto::Format::U32LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U32BE, firebolt::rialto::Format::U32BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24LE, firebolt::rialto::Format::S24LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S24BE, firebolt::rialto::Format::S24BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24LE, firebolt::rialto::Format::U24LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U24BE, firebolt::rialto::Format::U24BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20LE, firebolt::rialto::Format::S20LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S20BE, firebolt::rialto::Format::S20BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20LE, firebolt::rialto::Format::U20LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U20BE, firebolt::rialto::Format::U20BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18LE, firebolt::rialto::Format::S18LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_S18BE, firebolt::rialto::Format::S18BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18LE, firebolt::rialto::Format::U18LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_U18BE, firebolt::rialto::Format::U18BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32LE, firebolt::rialto::Format::F32LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F32BE, firebolt::rialto::Format::F32BE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64LE, firebolt::rialto::Format::F64LE}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Format_F64BE, firebolt::rialto::Format::F64BE}}; - const auto kIt = kFormatConversionMap.find(format); - if (kFormatConversionMap.end() != kIt) - { - return kIt->second; - } - return firebolt::rialto::Format::S8; -} - -firebolt::rialto::Layout convertLayout(const firebolt::rialto::AttachSourceRequest_AudioConfig_Layout &layout) -{ - static const std::unordered_map - kLayoutConversionMap{{firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_INTERLEAVED, - firebolt::rialto::Layout::INTERLEAVED}, - {firebolt::rialto::AttachSourceRequest_AudioConfig_Layout_NON_INTERLEAVED, - firebolt::rialto::Layout::NON_INTERLEAVED}}; - const auto kIt = kLayoutConversionMap.find(layout); - if (kLayoutConversionMap.end() != kIt) - { - return kIt->second; - } - return firebolt::rialto::Layout::INTERLEAVED; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -std::shared_ptr IMediaPipelineModuleServiceFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media player module service factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr -MediaPipelineModuleServiceFactory::create(service::IMediaPipelineService &mediaPipelineService) const -{ - std::shared_ptr mediaPipelineModule; - - try - { - mediaPipelineModule = std::make_shared(mediaPipelineService); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media player module service, reason: %s", e.what()); - } - - return mediaPipelineModule; -} - -MediaPipelineModuleService::MediaPipelineModuleService(service::IMediaPipelineService &mediaPipelineService) - : m_mediaPipelineService{mediaPipelineService} -{ -} - -MediaPipelineModuleService::~MediaPipelineModuleService() {} - -void MediaPipelineModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client Connected!"); - { - m_clientSessions.emplace(ipcClient, std::set()); - } - ipcClient->exportService(shared_from_this()); -} - -void MediaPipelineModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client disconnected!"); - std::set sessionIds; - { - auto sessionIter = m_clientSessions.find(ipcClient); - if (sessionIter == m_clientSessions.end()) - { - RIALTO_SERVER_LOG_ERROR("unknown client disconnected"); - return; - } - sessionIds = sessionIter->second; // copy to avoid deadlock - m_clientSessions.erase(sessionIter); - } - for (const auto &sessionId : sessionIds) - { - m_mediaPipelineService.destroySession(sessionId); - } -} - -void MediaPipelineModuleService::createSession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CreateSessionRequest *request, - ::firebolt::rialto::CreateSessionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - int sessionId = generateSessionId(); - bool sessionCreated = - m_mediaPipelineService.createSession(sessionId, - std::make_shared(sessionId, ipcController->getClient()), - request->max_width(), request->max_height()); - if (sessionCreated) - { - // Assume that IPC library works well and client is present - m_clientSessions[ipcController->getClient()].insert(sessionId); - response->set_session_id(sessionId); - } - else - { - RIALTO_SERVER_LOG_ERROR("Create session failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::destroySession(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DestroySessionRequest *request, - ::firebolt::rialto::DestroySessionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - if (!m_mediaPipelineService.destroySession(request->session_id())) - { - RIALTO_SERVER_LOG_ERROR("Destroy session failed"); - controller->SetFailed("Operation failed"); - done->Run(); - return; - } - auto sessionIter = m_clientSessions.find(ipcController->getClient()); - if (sessionIter != m_clientSessions.end()) - { - sessionIter->second.erase(request->session_id()); - } - done->Run(); -} - -void MediaPipelineModuleService::load(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::LoadRequest *request, - ::firebolt::rialto::LoadResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.load(request->session_id(), convertMediaType(request->type()), request->mime_type(), - request->url())) - { - RIALTO_SERVER_LOG_ERROR("Load failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::setVideoWindow(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetVideoWindowRequest *request, - ::firebolt::rialto::SetVideoWindowResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.setVideoWindow(request->session_id(), request->x(), request->y(), request->width(), - request->height())) - { - RIALTO_SERVER_LOG_ERROR("Set Video Window failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::attachSource(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::AttachSourceRequest *request, - ::firebolt::rialto::AttachSourceResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("mime_type: %s", request->mime_type().c_str()); - - std::shared_ptr codecData{}; - if (request->has_codec_data()) - { - auto codecDataProto = request->codec_data(); - codecData = std::make_shared(); - codecData->data = std::vector(codecDataProto.data().begin(), codecDataProto.data().end()); - codecData->type = convertCodecDataType(codecDataProto.type()); - } - std::unique_ptr mediaSource; - firebolt::rialto::SourceConfigType configType = convertConfigType(request->config_type()); - bool hasDrm = request->has_drm(); - - if (configType == firebolt::rialto::SourceConfigType::AUDIO) - { - const auto &kConfig = request->audio_config(); - uint32_t numberofchannels = kConfig.number_of_channels(); - uint32_t sampleRate = kConfig.sample_rate(); - - std::vector codecSpecificConfig; - if (kConfig.has_codec_specific_config()) - { - auto codecSpecificConfigStr = kConfig.codec_specific_config(); - codecSpecificConfig.assign(codecSpecificConfigStr.begin(), codecSpecificConfigStr.end()); - } - std::optional format{std::nullopt}; - if (kConfig.has_format()) - { - format = convertFormat(kConfig.format()); - } - std::optional layout{std::nullopt}; - if (kConfig.has_layout()) - { - layout = convertLayout(kConfig.layout()); - } - std::optional channelMask{std::nullopt}; - if (kConfig.has_channel_mask()) - { - channelMask = kConfig.channel_mask(); - } - std::vector> streamHeaders; - for (int i = 0; i < kConfig.stream_header_size(); ++i) - { - auto streamHeaderStr = kConfig.stream_header(i); - streamHeaders.push_back(std::vector{streamHeaderStr.begin(), streamHeaderStr.end()}); - } - std::optional framed; - if (kConfig.has_framed()) - { - framed = kConfig.framed(); - } - AudioConfig audioConfig{numberofchannels, sampleRate, codecSpecificConfig, format, - layout, channelMask, streamHeaders, framed}; - - mediaSource = - std::make_unique(request->mime_type(), hasDrm, audioConfig, - convertSegmentAlignment(request->segment_alignment()), - convertStreamFormat(request->stream_format()), codecData); - } - else if (configType == firebolt::rialto::SourceConfigType::VIDEO) - { - mediaSource = - std::make_unique(request->mime_type().c_str(), hasDrm, request->width(), - request->height(), - convertSegmentAlignment(request->segment_alignment()), - convertStreamFormat(request->stream_format()), codecData); - } - else if (configType == firebolt::rialto::SourceConfigType::VIDEO_DOLBY_VISION) - { - mediaSource = - std::make_unique(request->mime_type().c_str(), - request->dolby_vision_profile(), hasDrm, - request->width(), request->height(), - convertSegmentAlignment( - request->segment_alignment()), - convertStreamFormat(request->stream_format()), - codecData); - } - else if (configType == firebolt::rialto::SourceConfigType::SUBTITLE) - { - mediaSource = std::make_unique(request->mime_type().c_str(), - request->text_track_identifier()); - } - else - { - RIALTO_SERVER_LOG_ERROR("Unknown source type"); - controller->SetFailed("Operation failed"); - done->Run(); - return; - } - - if (!request->has_switch_source() || !request->switch_source()) - { - RIALTO_SERVER_LOG_DEBUG("Attaching source"); - if (!m_mediaPipelineService.attachSource(request->session_id(), mediaSource)) - { - RIALTO_SERVER_LOG_ERROR("Attach source failed"); - controller->SetFailed("Operation failed"); - } - } - else - { - RIALTO_SERVER_LOG_DEBUG("Switching source"); - if (!m_mediaPipelineService.switchSource(request->session_id(), mediaSource)) - { - RIALTO_SERVER_LOG_ERROR("Switch source failed"); - controller->SetFailed("Operation failed"); - } - } - response->set_source_id(mediaSource->getId()); - done->Run(); -} - -void MediaPipelineModuleService::removeSource(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::RemoveSourceRequest *request, - ::firebolt::rialto::RemoveSourceResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.removeSource(request->session_id(), request->source_id())) - { - RIALTO_SERVER_LOG_ERROR("Remove source failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::allSourcesAttached(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::AllSourcesAttachedRequest *request, - ::firebolt::rialto::AllSourcesAttachedResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.allSourcesAttached(request->session_id())) - { - RIALTO_SERVER_LOG_ERROR("All sources attached failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::play(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::PlayRequest *request, - ::firebolt::rialto::PlayResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.play(request->session_id())) - { - RIALTO_SERVER_LOG_ERROR("Play failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::pause(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::PauseRequest *request, - ::firebolt::rialto::PauseResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.pause(request->session_id())) - { - RIALTO_SERVER_LOG_ERROR("pause failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::stop(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::StopRequest *request, - ::firebolt::rialto::StopResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.stop(request->session_id())) - { - RIALTO_SERVER_LOG_ERROR("Stop failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::setPosition(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetPositionRequest *request, - ::firebolt::rialto::SetPositionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.setPosition(request->session_id(), request->position())) - { - RIALTO_SERVER_LOG_ERROR("Set Position failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::haveData(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::HaveDataRequest *request, - ::firebolt::rialto::HaveDataResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - firebolt::rialto::MediaSourceStatus status{convertMediaSourceStatus(request->status())}; - if (!m_mediaPipelineService.haveData(request->session_id(), status, request->num_frames(), request->request_id())) - { - RIALTO_SERVER_LOG_ERROR("Have data failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::setPlaybackRate(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetPlaybackRateRequest *request, - ::firebolt::rialto::SetPlaybackRateResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.setPlaybackRate(request->session_id(), request->rate())) - { - RIALTO_SERVER_LOG_ERROR("Set playback rate failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::getPosition(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetPositionRequest *request, - ::firebolt::rialto::GetPositionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - int64_t position{}; - if (!m_mediaPipelineService.getPosition(request->session_id(), position)) - { - RIALTO_SERVER_LOG_ERROR("Get position failed"); - controller->SetFailed("Operation failed"); - } - else - { - response->set_position(position); - } - done->Run(); -} - -void MediaPipelineModuleService::setImmediateOutput(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetImmediateOutputRequest *request, - ::firebolt::rialto::SetImmediateOutputResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.setImmediateOutput(request->session_id(), request->source_id(), - request->immediate_output())) - { - RIALTO_SERVER_LOG_ERROR("Set Immediate Output failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::getImmediateOutput(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetImmediateOutputRequest *request, - ::firebolt::rialto::GetImmediateOutputResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - bool immediateOutputState; - if (!m_mediaPipelineService.getImmediateOutput(request->session_id(), request->source_id(), immediateOutputState)) - { - RIALTO_SERVER_LOG_ERROR("Get Immediate Output failed"); - controller->SetFailed("Operation failed"); - } - else - { - response->set_immediate_output(immediateOutputState); - } - done->Run(); -} - -void MediaPipelineModuleService::getStats(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetStatsRequest *request, - ::firebolt::rialto::GetStatsResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - uint64_t renderedFrames; - uint64_t droppedFrames; - if (!m_mediaPipelineService.getStats(request->session_id(), request->source_id(), renderedFrames, droppedFrames)) - { - RIALTO_SERVER_LOG_ERROR("Get stats failed"); - controller->SetFailed("Operation failed"); - } - else - { - response->set_rendered_frames(renderedFrames); - response->set_dropped_frames(droppedFrames); - } - done->Run(); -} - -void MediaPipelineModuleService::renderFrame(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::RenderFrameRequest *request, - ::firebolt::rialto::RenderFrameResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_mediaPipelineService.renderFrame(request->session_id())) - { - RIALTO_SERVER_LOG_ERROR("Render frame"); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaPipelineModuleService::setVolume(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetVolumeRequest *request, - ::firebolt::rialto::SetVolumeResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_mediaPipelineService.setVolume(request->session_id(), request->volume(), request->volume_duration(), - convertEaseType(request->ease_type()))) - { - RIALTO_SERVER_LOG_ERROR("Set volume failed."); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaPipelineModuleService::getVolume(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetVolumeRequest *request, - ::firebolt::rialto::GetVolumeResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - double volume{}; - - if (!m_mediaPipelineService.getVolume(request->session_id(), volume)) - { - RIALTO_SERVER_LOG_ERROR("Get volume failed."); - controller->SetFailed("Operation failed"); - } - else - { - response->set_volume(volume); - } - - done->Run(); -} - -void MediaPipelineModuleService::setMute(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetMuteRequest *request, - ::firebolt::rialto::SetMuteResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_mediaPipelineService.setMute(request->session_id(), request->source_id(), request->mute())) - { - RIALTO_SERVER_LOG_ERROR("Set mute failed."); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaPipelineModuleService::getMute(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetMuteRequest *request, - ::firebolt::rialto::GetMuteResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - bool mute{}; - - if (!m_mediaPipelineService.getMute(request->session_id(), request->source_id(), mute)) - { - RIALTO_SERVER_LOG_ERROR("Get mute failed."); - controller->SetFailed("Operation failed"); - } - else - { - response->set_mute(mute); - } - - done->Run(); -} - -void MediaPipelineModuleService::setTextTrackIdentifier(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetTextTrackIdentifierRequest *request, - ::firebolt::rialto::SetTextTrackIdentifierResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_mediaPipelineService.setTextTrackIdentifier(request->session_id(), request->text_track_identifier())) - { - RIALTO_SERVER_LOG_ERROR("Set text track identifier failed."); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaPipelineModuleService::getTextTrackIdentifier(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetTextTrackIdentifierRequest *request, - ::firebolt::rialto::GetTextTrackIdentifierResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - std::string textTrackIdentifier{}; - - if (!m_mediaPipelineService.getTextTrackIdentifier(request->session_id(), textTrackIdentifier)) - { - RIALTO_SERVER_LOG_ERROR("Get TextTrackIdentifier failed."); - controller->SetFailed("Operation failed"); - } - else - { - response->set_text_track_identifier(textTrackIdentifier); - } - - done->Run(); -} - -void MediaPipelineModuleService::setLowLatency(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetLowLatencyRequest *request, - ::firebolt::rialto::SetLowLatencyResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_mediaPipelineService.setLowLatency(request->session_id(), request->low_latency())) - { - RIALTO_SERVER_LOG_ERROR("Set low latency failed."); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaPipelineModuleService::setSync(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetSyncRequest *request, - ::firebolt::rialto::SetSyncResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_mediaPipelineService.setSync(request->session_id(), request->sync())) - { - RIALTO_SERVER_LOG_ERROR("Set sync failed."); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaPipelineModuleService::getSync(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetSyncRequest *request, - ::firebolt::rialto::GetSyncResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - bool sync{}; - - if (!m_mediaPipelineService.getSync(request->session_id(), sync)) - { - RIALTO_SERVER_LOG_ERROR("Get sync failed."); - controller->SetFailed("Operation failed"); - } - else - { - response->set_sync(sync); - } - - done->Run(); -} - -void MediaPipelineModuleService::setSyncOff(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetSyncOffRequest *request, - ::firebolt::rialto::SetSyncOffResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_mediaPipelineService.setSyncOff(request->session_id(), request->sync_off())) - { - RIALTO_SERVER_LOG_ERROR("Set sync off failed."); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaPipelineModuleService::setStreamSyncMode(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetStreamSyncModeRequest *request, - ::firebolt::rialto::SetStreamSyncModeResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_mediaPipelineService.setStreamSyncMode(request->session_id(), request->source_id(), - request->stream_sync_mode())) - { - RIALTO_SERVER_LOG_ERROR("Set stream sync mode failed."); - controller->SetFailed("Operation failed"); - } - - done->Run(); -} - -void MediaPipelineModuleService::getStreamSyncMode(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetStreamSyncModeRequest *request, - ::firebolt::rialto::GetStreamSyncModeResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - int32_t streamSyncMode{}; - - if (!m_mediaPipelineService.getStreamSyncMode(request->session_id(), streamSyncMode)) - { - RIALTO_SERVER_LOG_ERROR("Get stream sync mode failed."); - controller->SetFailed("Operation failed"); - } - else - { - response->set_stream_sync_mode(streamSyncMode); - } - - done->Run(); -} - -void MediaPipelineModuleService::flush(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::FlushRequest *request, - ::firebolt::rialto::FlushResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool isAsync{false}; - if (!m_mediaPipelineService.flush(request->session_id(), request->source_id(), request->reset_time(), isAsync)) - { - RIALTO_SERVER_LOG_ERROR("Flush failed."); - controller->SetFailed("Operation failed"); - } - response->set_async(isAsync); - - done->Run(); -} - -void MediaPipelineModuleService::setSourcePosition(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetSourcePositionRequest *request, - ::firebolt::rialto::SetSourcePositionResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.setSourcePosition(request->session_id(), request->source_id(), request->position(), - request->reset_time(), request->applied_rate(), - request->stop_position())) - { - RIALTO_SERVER_LOG_ERROR("Set Source Position failed."); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::setSubtitleOffset(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetSubtitleOffsetRequest *request, - ::firebolt::rialto::SetSubtitleOffsetResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.setSubtitleOffset(request->session_id(), request->source_id(), request->position())) - { - RIALTO_SERVER_LOG_ERROR("Set Subtitle Offset failed."); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::processAudioGap(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::ProcessAudioGapRequest *request, - ::firebolt::rialto::ProcessAudioGapResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.processAudioGap(request->session_id(), request->position(), request->duration(), - request->discontinuity_gap(), request->audio_aac())) - { - RIALTO_SERVER_LOG_ERROR("Process audio gap failed."); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::setBufferingLimit(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetBufferingLimitRequest *request, - ::firebolt::rialto::SetBufferingLimitResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.setBufferingLimit(request->session_id(), request->limit_buffering_ms())) - { - RIALTO_SERVER_LOG_ERROR("Set buffering limit failed."); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::getBufferingLimit(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetBufferingLimitRequest *request, - ::firebolt::rialto::GetBufferingLimitResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - uint32_t bufferingLimit{}; - - if (!m_mediaPipelineService.getBufferingLimit(request->session_id(), bufferingLimit)) - { - RIALTO_SERVER_LOG_ERROR("Get buffering limit failed."); - controller->SetFailed("Operation failed"); - } - else - { - response->set_limit_buffering_ms(bufferingLimit); - } - - done->Run(); -} - -void MediaPipelineModuleService::setUseBuffering(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::SetUseBufferingRequest *request, - ::firebolt::rialto::SetUseBufferingResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_mediaPipelineService.setUseBuffering(request->session_id(), request->use_buffering())) - { - RIALTO_SERVER_LOG_ERROR("Set use buffering failed."); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void MediaPipelineModuleService::getUseBuffering(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::GetUseBufferingRequest *request, - ::firebolt::rialto::GetUseBufferingResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - bool useBuffering{}; - - if (!m_mediaPipelineService.getUseBuffering(request->session_id(), useBuffering)) - { - RIALTO_SERVER_LOG_ERROR("Get use buffering failed."); - controller->SetFailed("Operation failed"); - } - else - { - response->set_use_buffering(useBuffering); - } - - done->Run(); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/RialtoCommonModule.cpp b/middleware/rialto-client/media/server/ipc/source/RialtoCommonModule.cpp deleted file mode 100644 index d06e9bbee..000000000 --- a/middleware/rialto-client/media/server/ipc/source/RialtoCommonModule.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "RialtoCommonModule.h" - -namespace firebolt::rialto::server::ipc -{ -firebolt::rialto::MediaSourceType convertMediaSourceType(const firebolt::rialto::ProtoMediaSourceType &mediaSourceType) -{ - switch (mediaSourceType) - { - case firebolt::rialto::ProtoMediaSourceType::UNKNOWN: - { - return firebolt::rialto::MediaSourceType::UNKNOWN; - } - case firebolt::rialto::ProtoMediaSourceType::AUDIO: - { - return firebolt::rialto::MediaSourceType::AUDIO; - } - case firebolt::rialto::ProtoMediaSourceType::VIDEO: - { - return firebolt::rialto::MediaSourceType::VIDEO; - } - case firebolt::rialto::ProtoMediaSourceType::SUBTITLE: - { - return firebolt::rialto::MediaSourceType::SUBTITLE; - } - } - return firebolt::rialto::MediaSourceType::UNKNOWN; -} - -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/ServerManagerModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/ServerManagerModuleService.cpp deleted file mode 100644 index fd33fb6f6..000000000 --- a/middleware/rialto-client/media/server/ipc/source/ServerManagerModuleService.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ServerManagerModuleService.h" -#include "AckSender.h" -#include "ISessionServerManager.h" -#include "RialtoServerLogging.h" -#include - -namespace -{ -firebolt::rialto::common::SessionServerState convertSessionServerState(const rialto::SessionServerState &state) -{ - switch (state) - { - case rialto::SessionServerState::UNINITIALIZED: - return firebolt::rialto::common::SessionServerState::UNINITIALIZED; - case rialto::SessionServerState::INACTIVE: - return firebolt::rialto::common::SessionServerState::INACTIVE; - case rialto::SessionServerState::ACTIVE: - return firebolt::rialto::common::SessionServerState::ACTIVE; - case rialto::SessionServerState::NOT_RUNNING: - return firebolt::rialto::common::SessionServerState::NOT_RUNNING; - case rialto::SessionServerState::ERROR: - return firebolt::rialto::common::SessionServerState::ERROR; - } - return firebolt::rialto::common::SessionServerState::ERROR; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -std::shared_ptr IServerManagerModuleServiceFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the server maanger module service factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr<::rialto::ServerManagerModule> -ServerManagerModuleServiceFactory::create(service::ISessionServerManager &sessionServerManager) const -{ - std::shared_ptr<::rialto::ServerManagerModule> serverManagerModule; - try - { - serverManagerModule = std::make_shared(sessionServerManager); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the server manager module service, reason: %s", e.what()); - } - - return serverManagerModule; -} - -ServerManagerModuleService::ServerManagerModuleService(service::ISessionServerManager &sessionServerManager) - : m_sessionServerManager{sessionServerManager} -{ -} - -ServerManagerModuleService::~ServerManagerModuleService() {} - -void ServerManagerModuleService::setConfiguration(::google::protobuf::RpcController *controller, - const ::rialto::SetConfigurationRequest *request, - ::rialto::SetConfigurationResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("SetConfiguration received from ServerManager"); - common::MaxResourceCapabilitites maxResource{request->resources().maxplaybacks(), - request->resources().maxwebaudioplayers()}; - const auto kClientDisplayName = request->has_clientdisplayname() ? request->clientdisplayname() : ""; - bool success{true}; - if (request->has_sessionmanagementsocketfd()) - { - m_sessionServerManager.configureIpc(request->sessionmanagementsocketfd()); - } - else - { - m_sessionServerManager.configureIpc(request->sessionmanagementsocketname(), request->socketpermissions(), - request->socketowner(), request->socketgroup()); - } - success &= m_sessionServerManager.configureServices(convertSessionServerState(request->initialsessionserverstate()), - maxResource, kClientDisplayName, request->appname()); - m_sessionServerManager.setLogLevels(static_cast(request->loglevels().defaultloglevels()), - static_cast(request->loglevels().clientloglevels()), - static_cast(request->loglevels().sessionserverloglevels()), - static_cast(request->loglevels().ipcloglevels()), - static_cast(request->loglevels().servermanagerloglevels()), - static_cast(request->loglevels().commonloglevels())); - if (!success) - { - RIALTO_SERVER_LOG_ERROR("SetConfiguration operation failed"); - controller->SetFailed("SetConfiguration failed"); - } - done->Run(); -} - -void ServerManagerModuleService::setState(::google::protobuf::RpcController *controller, - const ::rialto::SetStateRequest *request, - ::rialto::SetStateResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("SetState received from ServerManager"); - bool success = m_sessionServerManager.setState(convertSessionServerState(request->sessionserverstate())); - if (!success) - { - RIALTO_SERVER_LOG_ERROR("SetState operation failed"); - controller->SetFailed("SetState failed"); - } - done->Run(); -} - -void ServerManagerModuleService::setLogLevels(::google::protobuf::RpcController *controller, - const ::rialto::SetLogLevelsRequest *request, - ::rialto::SetLogLevelsResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("setLogLevels received from ServerManager"); - m_sessionServerManager.setLogLevels(static_cast(request->loglevels().defaultloglevels()), - static_cast(request->loglevels().clientloglevels()), - static_cast(request->loglevels().sessionserverloglevels()), - static_cast(request->loglevels().ipcloglevels()), - static_cast(request->loglevels().servermanagerloglevels()), - static_cast(request->loglevels().commonloglevels())); - done->Run(); -} - -void ServerManagerModuleService::ping(::google::protobuf::RpcController *controller, const ::rialto::PingRequest *request, - ::rialto::PingResponse *response, ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("Ping received from ServerManager"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - bool success = m_sessionServerManager.ping(request->id(), std::make_shared(ipcController->getClient())); - if (!success) - { - RIALTO_SERVER_LOG_ERROR("Ping failed"); - controller->SetFailed("Ping failed"); - } - done->Run(); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/SessionManagementServer.cpp b/middleware/rialto-client/media/server/ipc/source/SessionManagementServer.cpp deleted file mode 100644 index 20e5b2b7d..000000000 --- a/middleware/rialto-client/media/server/ipc/source/SessionManagementServer.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SessionManagementServer.h" -#include "IControlModuleService.h" -#include "IMediaKeysCapabilitiesModuleService.h" -#include "IMediaKeysModuleService.h" -#include "IMediaPipelineModuleService.h" -#include "IWebAudioPlayerModuleService.h" -#include "LinuxUtils.h" -#include "RialtoServerLogging.h" -#include -#include -#include -#include -#include -#include - -namespace -{ -constexpr uid_t kNoOwnerChange = -1; // -1 means chown() won't change the owner -constexpr gid_t kNoGroupChange = -1; // -1 means chown() won't change the group -} // namespace -namespace firebolt::rialto::server::ipc -{ -SessionManagementServer::SessionManagementServer( - const std::shared_ptr &ipcFactory, - const std::shared_ptr &mediaPipelineModuleFactory, - const std::shared_ptr &mediaPipelineCapabilitiesModuleFactory, - const std::shared_ptr &mediaKeysModuleFactory, - const std::shared_ptr &mediaKeysCapabilitiesModuleFactory, - const std::shared_ptr &webAudioPlayerModuleFactory, - const std::shared_ptr &controlModuleFactory, service::IPlaybackService &playbackService, - service::ICdmService &cdmService, service::IControlService &controlService) - : m_isRunning{false}, - m_mediaPipelineModule{mediaPipelineModuleFactory->create(playbackService.getMediaPipelineService())}, - m_mediaPipelineCapabilitiesModule{ - mediaPipelineCapabilitiesModuleFactory->create(playbackService.getMediaPipelineService())}, - m_mediaKeysModule{mediaKeysModuleFactory->create(cdmService)}, - m_mediaKeysCapabilitiesModule{mediaKeysCapabilitiesModuleFactory->create(cdmService)}, - m_webAudioPlayerModule{webAudioPlayerModuleFactory->create(playbackService.getWebAudioPlayerService())}, - m_controlModule{controlModuleFactory->create(playbackService, controlService)} -{ - m_ipcServer = ipcFactory->create(); -} - -SessionManagementServer::~SessionManagementServer() -{ - stop(); - if (m_ipcServerThread.joinable()) - { - m_ipcServerThread.join(); - } -} - -size_t SessionManagementServer::getBufferSizeForPasswordStructureCalls() const -{ - // Can return -1 on error - return sysconf(_SC_GETPW_R_SIZE_MAX); -} - -bool SessionManagementServer::initialize(const std::string &socketName, unsigned int socketPermissions, - const std::string &socketOwner, const std::string &socketGroup) -{ - RIALTO_SERVER_LOG_INFO("Initializing Session Management Server. Socket name: '%s'", socketName.c_str()); - if (!m_ipcServer) - { - RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - Ipc server instance is NULL"); - return false; - } - - // add a socket for clients and associate with a streamer object - if (!m_ipcServer->addSocket(socketName, - std::bind(&SessionManagementServer::onClientConnected, this, std::placeholders::_1), - std::bind(&SessionManagementServer::onClientDisconnected, this, std::placeholders::_1))) - { - RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - can't add socket '%s' to the ipc " - "server", - socketName.c_str()); - return false; - } - - common::setFilePermissions(socketName, socketPermissions); - common::setFileOwnership(socketName, socketOwner, socketGroup); - - RIALTO_SERVER_LOG_MIL("Session Management Server initialized"); - - return true; -} - -bool SessionManagementServer::initialize(int32_t socketFd) -{ - RIALTO_SERVER_LOG_INFO("Initializing Session Management Server. Socket fd: %d", socketFd); - if (!m_ipcServer) - { - RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - Ipc server instance is NULL"); - return false; - } - - // add a socket for clients and associate with a streamer object - if (!m_ipcServer->addSocket(socketFd, - std::bind(&SessionManagementServer::onClientConnected, this, std::placeholders::_1), - std::bind(&SessionManagementServer::onClientDisconnected, this, std::placeholders::_1))) - { - RIALTO_SERVER_LOG_ERROR("Failed to initialize SessionManagementServer - can't add socket fd %d to the ipc " - "server", - socketFd); - return false; - } - - RIALTO_SERVER_LOG_MIL("Session Management Server initialized"); - - return true; -} - -void SessionManagementServer::start() -{ - if (m_isRunning.load()) - { - RIALTO_SERVER_LOG_DEBUG("Server is already in running state"); - return; - } - RIALTO_SERVER_LOG_DEBUG("Starting Session Management Server event loop"); - m_isRunning.store(true); - m_ipcServerThread = std::thread( - [this]() - { - constexpr int kPollInterval{100}; - while (m_ipcServer->process() && m_isRunning.load()) - { - m_ipcServer->wait(kPollInterval); - } - RIALTO_SERVER_LOG_MIL("Session Management Server event loop finished."); - }); -} - -void SessionManagementServer::stop() -{ - m_isRunning.store(false); -} - -void SessionManagementServer::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, - RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) -{ - m_setLogLevelsService.setLogLevels(defaultLogLevels, clientLogLevels, ipcLogLevels, commonLogLevels); -} - -void SessionManagementServer::onClientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) -{ - RIALTO_SERVER_LOG_MIL("Client app connected"); - m_controlModule->clientConnected(client); - m_mediaPipelineModule->clientConnected(client); - m_mediaPipelineCapabilitiesModule->clientConnected(client); - m_mediaKeysModule->clientConnected(client); - m_mediaKeysCapabilitiesModule->clientConnected(client); - m_webAudioPlayerModule->clientConnected(client); - m_setLogLevelsService.clientConnected(client); -} - -void SessionManagementServer::onClientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &client) -{ - RIALTO_SERVER_LOG_MIL("Client app disconnected"); - m_setLogLevelsService.clientDisconnected(client); - m_mediaKeysCapabilitiesModule->clientDisconnected(client); - m_mediaKeysModule->clientDisconnected(client); - m_mediaPipelineCapabilitiesModule->clientDisconnected(client); - m_mediaPipelineModule->clientDisconnected(client); - m_webAudioPlayerModule->clientDisconnected(client); - m_controlModule->clientDisconnected(client); -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/SetLogLevelsService.cpp b/middleware/rialto-client/media/server/ipc/source/SetLogLevelsService.cpp deleted file mode 100644 index a266ddca0..000000000 --- a/middleware/rialto-client/media/server/ipc/source/SetLogLevelsService.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SetLogLevelsService.h" -#include "mediapipelinemodule.pb.h" - -namespace firebolt::rialto::server::ipc -{ -void SetLogLevelsService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - std::lock_guard lock(m_mutex); - m_connectedClients.insert(ipcClient); -} - -void SetLogLevelsService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - std::lock_guard lock(m_mutex); - m_connectedClients.erase(ipcClient); -} - -void SetLogLevelsService::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, - RIALTO_DEBUG_LEVEL ipcLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) -{ - auto event = std::make_shared(); - event->set_defaultloglevels(static_cast(defaultLogLevels)); - event->set_clientloglevels(static_cast(clientLogLevels)); - event->set_ipcloglevels(static_cast(ipcLogLevels)); - event->set_commonloglevels(static_cast(commonLogLevels)); - - std::lock_guard lock(m_mutex); - for (const auto &client : m_connectedClients) - { - client->sendEvent(event); - } -} -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerClient.cpp b/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerClient.cpp deleted file mode 100644 index 234683a7a..000000000 --- a/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerClient.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WebAudioPlayerClient.h" -#include "RialtoServerLogging.h" -#include "webaudioplayermodule.pb.h" -#include - -namespace -{ -firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState -convertWebAudioPlayerState(const firebolt::rialto::WebAudioPlayerState &state) -{ - switch (state) - { - case firebolt::rialto::WebAudioPlayerState::UNKNOWN: - { - return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_UNKNOWN; - } - case firebolt::rialto::WebAudioPlayerState::IDLE: - { - return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_IDLE; - } - case firebolt::rialto::WebAudioPlayerState::PLAYING: - { - return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_PLAYING; - } - case firebolt::rialto::WebAudioPlayerState::PAUSED: - { - return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_PAUSED; - } - case firebolt::rialto::WebAudioPlayerState::END_OF_STREAM: - { - return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_END_OF_STREAM; - } - case firebolt::rialto::WebAudioPlayerState::FAILURE: - { - return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_FAILURE; - } - } - return firebolt::rialto::WebAudioPlayerStateEvent_WebAudioPlayerState_UNKNOWN; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -WebAudioPlayerClient::WebAudioPlayerClient(int webAudioPlayerHandle, - const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) - : m_webAudioPlayerHandle{webAudioPlayerHandle}, m_ipcClient{ipcClient} -{ -} - -WebAudioPlayerClient::~WebAudioPlayerClient() {} - -void WebAudioPlayerClient::notifyState(WebAudioPlayerState state) -{ - RIALTO_SERVER_LOG_DEBUG("Sending WebAudioPlayerStateEvent"); - - auto event = std::make_shared(); - event->set_web_audio_player_handle(m_webAudioPlayerHandle); - event->set_state(convertWebAudioPlayerState(state)); - - m_ipcClient->sendEvent(event); -} - -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerModuleService.cpp b/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerModuleService.cpp deleted file mode 100644 index 717c08078..000000000 --- a/middleware/rialto-client/media/server/ipc/source/WebAudioPlayerModuleService.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WebAudioPlayerModuleService.h" -#include "IWebAudioPlayerService.h" -#include "RialtoServerLogging.h" -#include "WebAudioPlayerClient.h" -#include -#include -#include - -namespace -{ -int generateHandle() -{ - static int webAudioPlayerHandle{0}; - return webAudioPlayerHandle++; -} -} // namespace - -namespace firebolt::rialto::server::ipc -{ -std::shared_ptr IWebAudioPlayerModuleServiceFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player module service factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr -WebAudioPlayerModuleServiceFactory::create(service::IWebAudioPlayerService &webAudioPlayerService) const -{ - std::shared_ptr webAudioPlayerModule; - - try - { - webAudioPlayerModule = std::make_shared(webAudioPlayerService); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player module service, reason: %s", e.what()); - } - - return webAudioPlayerModule; -} - -WebAudioPlayerModuleService::WebAudioPlayerModuleService(service::IWebAudioPlayerService &webAudioPlayerService) - : m_webAudioPlayerService{webAudioPlayerService} -{ -} - -WebAudioPlayerModuleService::~WebAudioPlayerModuleService() {} - -void WebAudioPlayerModuleService::clientConnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client Connected!"); - { - m_clientWebAudioPlayerHandles.emplace(ipcClient, std::set()); - } - ipcClient->exportService(shared_from_this()); -} - -void WebAudioPlayerModuleService::clientDisconnected(const std::shared_ptr<::firebolt::rialto::ipc::IClient> &ipcClient) -{ - RIALTO_SERVER_LOG_INFO("Client disconnected!"); - std::set webAudioPlayerHandles; - { - auto handleIter = m_clientWebAudioPlayerHandles.find(ipcClient); - if (handleIter == m_clientWebAudioPlayerHandles.end()) - { - RIALTO_SERVER_LOG_ERROR("unknown client disconnected"); - return; - } - webAudioPlayerHandles = handleIter->second; // copy to avoid deadlock - m_clientWebAudioPlayerHandles.erase(handleIter); - } - for (const auto &webAudioPlayerHandle : webAudioPlayerHandles) - { - m_webAudioPlayerService.destroyWebAudioPlayer(webAudioPlayerHandle); - } -} - -void WebAudioPlayerModuleService::createWebAudioPlayer(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::CreateWebAudioPlayerRequest *request, - ::firebolt::rialto::CreateWebAudioPlayerResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - - std::shared_ptr config = std::make_shared(); - if (request->has_config()) - { - if (request->config().has_pcm()) - { - config->pcm.rate = request->config().pcm().rate(); - config->pcm.channels = request->config().pcm().channels(); - config->pcm.sampleSize = request->config().pcm().sample_size(); - config->pcm.isBigEndian = request->config().pcm().is_big_endian(); - config->pcm.isSigned = request->config().pcm().is_signed(); - config->pcm.isFloat = request->config().pcm().is_float(); - } - } - int handle = generateHandle(); - bool webAudioPlayerCreated = - m_webAudioPlayerService.createWebAudioPlayer(handle, - std::make_shared(handle, - ipcController->getClient()), - request->audio_mime_type(), request->priority(), config); - if (webAudioPlayerCreated) - { - // Assume that IPC library works well and client is present - m_clientWebAudioPlayerHandles[ipcController->getClient()].insert(handle); - response->set_web_audio_player_handle(handle); - } - else - { - RIALTO_SERVER_LOG_ERROR("Create web audio player failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void WebAudioPlayerModuleService::destroyWebAudioPlayer(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::DestroyWebAudioPlayerRequest *request, - ::firebolt::rialto::DestroyWebAudioPlayerResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto ipcController = dynamic_cast(controller); - if (!ipcController) - { - RIALTO_SERVER_LOG_ERROR("ipc library provided incompatible controller object"); - controller->SetFailed("ipc library provided incompatible controller object"); - done->Run(); - return; - } - if (!m_webAudioPlayerService.destroyWebAudioPlayer(request->web_audio_player_handle())) - { - RIALTO_SERVER_LOG_ERROR("Destroy web audio player failed"); - controller->SetFailed("Operation failed"); - done->Run(); - return; - } - auto handleIter = m_clientWebAudioPlayerHandles.find(ipcController->getClient()); - if (handleIter != m_clientWebAudioPlayerHandles.end()) - { - handleIter->second.erase(request->web_audio_player_handle()); - } - done->Run(); -} - -void WebAudioPlayerModuleService::play(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioPlayRequest *request, - ::firebolt::rialto::WebAudioPlayResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_webAudioPlayerService.play(request->web_audio_player_handle())) - { - RIALTO_SERVER_LOG_ERROR("play failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void WebAudioPlayerModuleService::pause(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioPauseRequest *request, - ::firebolt::rialto::WebAudioPauseResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_webAudioPlayerService.pause(request->web_audio_player_handle())) - { - RIALTO_SERVER_LOG_ERROR("pause failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void WebAudioPlayerModuleService::setEos(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioSetEosRequest *request, - ::firebolt::rialto::WebAudioSetEosResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_webAudioPlayerService.setEos(request->web_audio_player_handle())) - { - RIALTO_SERVER_LOG_ERROR("setEos failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void WebAudioPlayerModuleService::getBufferAvailable(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioGetBufferAvailableRequest *request, - ::firebolt::rialto::WebAudioGetBufferAvailableResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - uint32_t availableFrames{}; - std::shared_ptr shmInfo = std::make_shared(); - if (!m_webAudioPlayerService.getBufferAvailable(request->web_audio_player_handle(), availableFrames, shmInfo)) - { - RIALTO_SERVER_LOG_ERROR("getBufferAvailable failed"); - controller->SetFailed("Operation failed"); - } - else - { - response->set_available_frames(availableFrames); - auto responseShmInfo = response->mutable_shm_info(); - responseShmInfo->set_offset_main(shmInfo->offsetMain); - responseShmInfo->set_length_main(shmInfo->lengthMain); - responseShmInfo->set_offset_wrap(shmInfo->offsetWrap); - responseShmInfo->set_length_wrap(shmInfo->lengthWrap); - } - done->Run(); -} - -void WebAudioPlayerModuleService::getBufferDelay(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioGetBufferDelayRequest *request, - ::firebolt::rialto::WebAudioGetBufferDelayResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - uint32_t delayFrames{}; - if (!m_webAudioPlayerService.getBufferDelay(request->web_audio_player_handle(), delayFrames)) - { - RIALTO_SERVER_LOG_ERROR("getBufferDelay failed"); - controller->SetFailed("Operation failed"); - } - else - { - response->set_delay_frames(delayFrames); - } - done->Run(); -} - -void WebAudioPlayerModuleService::writeBuffer(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioWriteBufferRequest *request, - ::firebolt::rialto::WebAudioWriteBufferResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_webAudioPlayerService.writeBuffer(request->web_audio_player_handle(), request->number_of_frames(), nullptr)) - { - RIALTO_SERVER_LOG_ERROR("writeBuffer failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void WebAudioPlayerModuleService::getDeviceInfo(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioGetDeviceInfoRequest *request, - ::firebolt::rialto::WebAudioGetDeviceInfoResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - uint32_t preferredFrames{}; - uint32_t maximumFrames{}; - bool supportDeferredPlay{}; - if (!m_webAudioPlayerService.getDeviceInfo(request->web_audio_player_handle(), preferredFrames, maximumFrames, - supportDeferredPlay)) - { - RIALTO_SERVER_LOG_ERROR("getDeviceInfo failed"); - controller->SetFailed("Operation failed"); - } - else - { - response->set_preferred_frames(preferredFrames); - response->set_maximum_frames(maximumFrames); - response->set_support_deferred_play(supportDeferredPlay); - } - done->Run(); -} - -void WebAudioPlayerModuleService::setVolume(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioSetVolumeRequest *request, - ::firebolt::rialto::WebAudioSetVolumeResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - if (!m_webAudioPlayerService.setVolume(request->web_audio_player_handle(), request->volume())) - { - RIALTO_SERVER_LOG_ERROR("setVolume failed"); - controller->SetFailed("Operation failed"); - } - done->Run(); -} - -void WebAudioPlayerModuleService::getVolume(::google::protobuf::RpcController *controller, - const ::firebolt::rialto::WebAudioGetVolumeRequest *request, - ::firebolt::rialto::WebAudioGetVolumeResponse *response, - ::google::protobuf::Closure *done) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - double volume{}; - if (!m_webAudioPlayerService.getVolume(request->web_audio_player_handle(), volume)) - { - RIALTO_SERVER_LOG_ERROR("getVolume failed"); - controller->SetFailed("Operation failed"); - } - else - { - response->set_volume(volume); - } - done->Run(); -} - -} // namespace firebolt::rialto::server::ipc diff --git a/middleware/rialto-client/media/server/main/CMakeLists.txt b/middleware/rialto-client/media/server/main/CMakeLists.txt deleted file mode 100644 index e21462bb1..000000000 --- a/middleware/rialto-client/media/server/main/CMakeLists.txt +++ /dev/null @@ -1,97 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -set( CMAKE_CXX_STANDARD 17 ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -include( CheckCXXCompilerFlag ) - -# Find includes in corresponding build directories -set( CMAKE_INCLUDE_CURRENT_DIR ON ) - -add_library( - RialtoServerMain STATIC - - ${PROTO_SRCS} - ${PROTO_HEADERS} - - source/MediaPipelineServerInternal.cpp - source/MediaPipelineCapabilities.cpp - source/ActiveRequests.cpp - source/DataReaderFactory.cpp - source/DataReaderV1.cpp - source/DataReaderV2.cpp - source/NeedMediaData.cpp - source/SharedMemoryBuffer.cpp - source/MediaKeysServerInternal.cpp - source/MediaKeysCapabilities.cpp - source/MediaKeySession.cpp - source/MainThread.cpp - source/WebAudioPlayerServerInternal.cpp - source/ControlServerInternal.cpp - source/HeartbeatProcedure.cpp - source/TextTrackAccessor.cpp - source/TextTrackSession.cpp - ) - -target_include_directories( - RialtoServerMain - - PUBLIC - interface - ${GStreamerApp_INCLUDE_DIRS} - - PRIVATE - include - $ - $ - $ - $ - $ - $ - ) - -set_target_properties( - RialtoServerMain - PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" - - ) - -target_compile_options( - RialtoServerMain - - PRIVATE - ) - -target_link_libraries( - RialtoServerMain - - PRIVATE - RialtoLogging - RialtoServerGstPlayer - RialtoWrappers - RialtoCommon - RialtoProtobuf - Threads::Threads - ) - -install( - TARGETS RialtoServerMain - DESTINATION lib - ) diff --git a/middleware/rialto-client/media/server/main/include/ActiveRequests.h b/middleware/rialto-client/media/server/main/include/ActiveRequests.h deleted file mode 100644 index 980758bd6..000000000 --- a/middleware/rialto-client/media/server/main/include/ActiveRequests.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_ACTIVE_REQUESTS_H_ -#define FIREBOLT_RIALTO_SERVER_ACTIVE_REQUESTS_H_ - -#include "IActiveRequests.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -class ActiveRequests : public IActiveRequests -{ -public: - class ActiveRequestsData - { - public: - ActiveRequestsData(MediaSourceType type, std::uint32_t maxMediaBytes) - : m_type(type), m_bytesWritten(0), m_maxMediaBytes(maxMediaBytes) - { - } - ~ActiveRequestsData(); - ActiveRequestsData(ActiveRequestsData &&) = default; - ActiveRequestsData &operator=(ActiveRequestsData &&) = default; - - ActiveRequestsData(const ActiveRequestsData &) = delete; - ActiveRequestsData &operator=(const ActiveRequestsData &) = delete; - - AddSegmentStatus addSegment(const std::unique_ptr &segment); - - MediaSourceType getType() const { return m_type; } - const IMediaPipeline::MediaSegmentVector &getSegments() const { return m_segments; } - - private: - MediaSourceType m_type; - std::uint32_t m_bytesWritten; - std::uint32_t m_maxMediaBytes; - IMediaPipeline::MediaSegmentVector m_segments; - }; - - ActiveRequests(); - ~ActiveRequests() override = default; - ActiveRequests(const ActiveRequests &) = delete; - ActiveRequests(ActiveRequests &&) = delete; - ActiveRequests &operator=(const ActiveRequests &) = delete; - ActiveRequests &operator=(ActiveRequests &&) = delete; - - std::uint32_t insert(const MediaSourceType &mediaSourceType, std::uint32_t maxMediaBytes) override; - MediaSourceType getType(std::uint32_t requestId) const override; - void erase(std::uint32_t requestId) override; - void erase(const MediaSourceType &mediaSourceType) override; - void clear() override; - AddSegmentStatus addSegment(std::uint32_t requestId, - const std::unique_ptr &segment) override; - const IMediaPipeline::MediaSegmentVector &getSegments(std::uint32_t requestId) const override; - -private: - mutable std::mutex m_mutex; - std::uint32_t m_currentId; - std::map m_requestMap; - // only used in server-only mode - std::map> m_addedSegments; -}; - -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_ACTIVE_REQUESTS_H_ diff --git a/middleware/rialto-client/media/server/main/include/ControlServerInternal.h b/middleware/rialto-client/media/server/main/include/ControlServerInternal.h deleted file mode 100644 index dc6ca3655..000000000 --- a/middleware/rialto-client/media/server/main/include/ControlServerInternal.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_CONTROL_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_CONTROL_SERVER_INTERNAL_H_ - -#include - -#include "IControlServerInternal.h" -#include "IMainThread.h" - -namespace firebolt::rialto::server -{ -class ControlServerInternalFactory : public IControlServerInternalFactory -{ -public: - ControlServerInternalFactory() = default; - ~ControlServerInternalFactory() override = default; - - std::shared_ptr createControl() const override; - std::shared_ptr - createControlServerInternal(int id, const std::shared_ptr &client) const override; -}; - -class ControlServerInternal : public IControlServerInternal -{ -public: - explicit ControlServerInternal(const std::shared_ptr &mainThreadFactory, int id, - const std::shared_ptr &client); - ~ControlServerInternal() override; - - void ack(int32_t id) override; - void setApplicationState(const ApplicationState &state) override; - void ping(std::unique_ptr &&heartbeatHandler) override; - bool registerClient(std::weak_ptr client, ApplicationState &appState) override; - -private: - const int m_controlId; - std::shared_ptr m_client; - ApplicationState m_currentState; - std::shared_ptr m_mainThread; - std::unique_ptr m_heartbeatHandler; - uint32_t m_mainThreadClientId; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_CONTROL_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/include/DataReaderFactory.h b/middleware/rialto-client/media/server/main/include/DataReaderFactory.h deleted file mode 100644 index 5ba7f6558..000000000 --- a/middleware/rialto-client/media/server/main/include/DataReaderFactory.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_DATA_READER_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_DATA_READER_FACTORY_H_ - -#include "IDataReaderFactory.h" -#include - -namespace firebolt::rialto::server -{ -class DataReaderFactory : public IDataReaderFactory -{ -public: - DataReaderFactory() = default; - ~DataReaderFactory() override = default; - std::shared_ptr createDataReader(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, - std::uint32_t dataOffset, std::uint32_t numFrames) const override; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_DATA_READER_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/main/include/DataReaderV1.h b/middleware/rialto-client/media/server/main/include/DataReaderV1.h deleted file mode 100644 index 88a35d895..000000000 --- a/middleware/rialto-client/media/server/main/include/DataReaderV1.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_DATA_READERV1_H_ -#define FIREBOLT_RIALTO_SERVER_DATA_READERV1_H_ - -#include "IDataReader.h" -#include "MediaCommon.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class DataReaderV1 : public IDataReader -{ - struct MetadataV1 - { - std::uint32_t offset; /* Offset of first byte of sample in CM buffer */ - std::uint32_t length; /* Number of bytes in sample */ - std::int64_t timePosition; /* Position in stream in nanoseconds */ - std::int64_t sampleDuration; /* Frame/sample duration in nanoseconds */ - std::uint32_t streamId; /* stream id (unique ID for ES, as defined in attachSource()) */ - std::uint32_t extraDataSize; /* extraData size */ - std::uint8_t extraData[32]; /* buffer containing extradata */ - std::uint32_t mediaKeysId; /* Identifier of MediaKeys instance to use for decryption. If 0 use any CDM - containing the MKS ID */ - std::uint32_t mediaKeySessionIdentifierOffset; /* Offset to the location of the MediaKeySessionIdentifier */ - std::uint32_t mediaKeySessionIdentifierLength; /* Length of the MediaKeySessionIdentifier */ - std::uint32_t initVectorOffset; /* Offset to the location of the initialization vector */ - std::uint32_t initVectorLength; /* Length of initialization vector */ - std::uint32_t subSampleInfoOffset; /* Offset to the location of the sub sample info table */ - std::uint32_t subSampleInfoLen; /* Length of sub-sample Info table */ - std::uint32_t initWithLast15; - std::uint32_t extra1; /* Samples per second for audio; Video width in pixels for video */ - std::uint32_t extra2; /* Number of channels for audio; Video height in pixels for video */ - }; - -public: - DataReaderV1(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t metadataOffset, - std::uint32_t numFrames); - ~DataReaderV1() override = default; - - IMediaPipeline::MediaSegmentVector readData() const override; - -private: - std::vector readMetadata() const; - -private: - MediaSourceType m_mediaSourceType; - std::uint8_t *m_buffer; - std::uint32_t m_metadataOffset; - std::uint32_t m_numFrames; - - template std::unique_ptr createSegment(const MetadataV1 &metadata) const - { - std::unique_ptr mediaSegment{std::make_unique(0, metadata.timePosition, - metadata.sampleDuration, - metadata.extra1, metadata.extra2)}; - mediaSegment->setData(metadata.length, m_buffer + metadata.offset); - std::vector extraDataVec; - std::copy(&metadata.extraData[0], &metadata.extraData[metadata.extraDataSize], std::back_inserter(extraDataVec)); - mediaSegment->setExtraData(extraDataVec); - mediaSegment->setEncrypted(false); // temporary, only clear content playback should be supported now - return mediaSegment; - } -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_DATA_READERV1_H_ diff --git a/middleware/rialto-client/media/server/main/include/DataReaderV2.h b/middleware/rialto-client/media/server/main/include/DataReaderV2.h deleted file mode 100644 index 6871022f5..000000000 --- a/middleware/rialto-client/media/server/main/include/DataReaderV2.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_DATA_READERV2_H_ -#define FIREBOLT_RIALTO_SERVER_DATA_READERV2_H_ - -#include "IDataReader.h" -#include "MediaCommon.h" -#include - -namespace firebolt::rialto::server -{ -class DataReaderV2 : public IDataReader -{ -public: - DataReaderV2(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t dataOffset, - std::uint32_t numFrames); - ~DataReaderV2() override = default; - - IMediaPipeline::MediaSegmentVector readData() const override; - -private: - MediaSourceType m_mediaSourceType; - std::uint8_t *m_buffer; - std::uint32_t m_dataOffset; - std::uint32_t m_numFrames; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_DATA_READERV2_H_ diff --git a/middleware/rialto-client/media/server/main/include/HeartbeatProcedure.h b/middleware/rialto-client/media/server/main/include/HeartbeatProcedure.h deleted file mode 100644 index 66da279a8..000000000 --- a/middleware/rialto-client/media/server/main/include/HeartbeatProcedure.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_HEARTBEAT_PROCEDURE_H_ -#define FIREBOLT_RIALTO_SERVER_HEARTBEAT_PROCEDURE_H_ - -#include "IHeartbeatProcedure.h" -#include -#include - -namespace firebolt::rialto::server -{ -class HeartbeatProcedureFactory : public IHeartbeatProcedureFactory -{ -public: - HeartbeatProcedureFactory() = default; - ~HeartbeatProcedureFactory() override = default; - std::shared_ptr createHeartbeatProcedure(const std::shared_ptr &ackSender, - std::int32_t pingId) const override; -}; - -class HeartbeatProcedure : public std::enable_shared_from_this, public IHeartbeatProcedure -{ - class HeartbeatHandler : public IHeartbeatHandler - { - public: - HeartbeatHandler(const std::shared_ptr &procedure, std::int32_t pingId); - ~HeartbeatHandler() override; - - void error() override; - std::int32_t id() const override; - - private: - std::shared_ptr m_procedure; - const std::int32_t m_kPingId; - bool m_success; - }; - -public: - HeartbeatProcedure(const std::shared_ptr &ackSender, std::int32_t pingId); - ~HeartbeatProcedure() override; - std::unique_ptr createHandler() override; - -private: - void onFinish(bool success); - -private: - std::shared_ptr m_ackSender; - const std::int32_t m_kPingId; - std::atomic_bool m_success; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_HEARTBEAT_PROCEDURE_H_ diff --git a/middleware/rialto-client/media/server/main/include/IActiveRequests.h b/middleware/rialto-client/media/server/main/include/IActiveRequests.h deleted file mode 100644 index d2e728c36..000000000 --- a/middleware/rialto-client/media/server/main/include/IActiveRequests.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_ACTIVE_REQUESTS_H_ -#define FIREBOLT_RIALTO_SERVER_I_ACTIVE_REQUESTS_H_ - -#include "MediaCommon.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IActiveRequests -{ -public: - IActiveRequests() = default; - virtual ~IActiveRequests() = default; - - IActiveRequests(const IActiveRequests &) = delete; - IActiveRequests(IActiveRequests &&) = delete; - IActiveRequests &operator=(const IActiveRequests &) = delete; - IActiveRequests &operator=(IActiveRequests &&) = delete; - - virtual std::uint32_t insert(const MediaSourceType &mediaSourceType, std::uint32_t maxMediaBytes) = 0; - virtual MediaSourceType getType(std::uint32_t requestId) const = 0; - virtual void erase(std::uint32_t requestId) = 0; - virtual void erase(const MediaSourceType &mediaSourceType) = 0; - virtual void clear() = 0; - virtual AddSegmentStatus addSegment(std::uint32_t requestId, - const std::unique_ptr &segment) = 0; - virtual const IMediaPipeline::MediaSegmentVector &getSegments(std::uint32_t requestId) const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_ACTIVE_REQUESTS_H_ diff --git a/middleware/rialto-client/media/server/main/include/IDataReaderFactory.h b/middleware/rialto-client/media/server/main/include/IDataReaderFactory.h deleted file mode 100644 index b4dee55e4..000000000 --- a/middleware/rialto-client/media/server/main/include/IDataReaderFactory.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_DATA_READER_FACTORY_H_ -#define FIREBOLT_RIALTO_SERVER_I_DATA_READER_FACTORY_H_ - -#include "MediaCommon.h" -#include -#include - -namespace firebolt::rialto::server -{ -class IDataReader; -} // namespace firebolt::rialto::server - -namespace firebolt::rialto::server -{ -class IDataReaderFactory -{ -public: - IDataReaderFactory() = default; - virtual ~IDataReaderFactory() = default; - - virtual std::shared_ptr createDataReader(const MediaSourceType &mediaSourceType, std::uint8_t *data, - std::uint32_t dataOffset, std::uint32_t numFrames) const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_DATA_READER_FACTORY_H_ diff --git a/middleware/rialto-client/media/server/main/include/IMediaKeySession.h b/middleware/rialto-client/media/server/main/include/IMediaKeySession.h deleted file mode 100644 index f962f66bb..000000000 --- a/middleware/rialto-client/media/server/main/include/IMediaKeySession.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_MEDIA_KEY_SESSION_H_ -#define FIREBOLT_RIALTO_SERVER_I_MEDIA_KEY_SESSION_H_ - -#include "IMediaKeysClient.h" -#include "IOcdmSystem.h" -#include "MediaCommon.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IMediaKeySession; - -/** - * @brief IMediaKeySession factory class, returns a concrete implementation of IMediaKeySession - */ -class IMediaKeySessionFactory -{ -public: - IMediaKeySessionFactory() = default; - virtual ~IMediaKeySessionFactory() = default; - - /** - * @brief Create a IMediaKeySessionFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMediaKeySession factory method, returns a concrete implementation of IMediaKeySession - * - * @param[in] keySystem : The key system for this session. - * @param[in] keySessionId : The key session id for this session. - * @param[in] ocdmSystem : The ocdm system object to create the session on. - * @param[in] sessionType : The session type. - * @param[in] client : Client object for callbacks. - * @param[in] isLDL : Is this an LDL. - * - * @retval the new media keys instance or null on error. - */ - virtual std::unique_ptr - createMediaKeySession(const std::string &keySystem, int32_t keySessionId, - const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, KeySessionType sessionType, - std::weak_ptr client, bool isLDL) const = 0; -}; - -/** - * @brief The definition of the IMediaKeySession interface. - */ -class IMediaKeySession -{ -public: - IMediaKeySession() = default; - virtual ~IMediaKeySession() = default; - - IMediaKeySession(const IMediaKeySession &) = delete; - IMediaKeySession &operator=(const IMediaKeySession &) = delete; - IMediaKeySession(IMediaKeySession &&) = delete; - IMediaKeySession &operator=(IMediaKeySession &&) = delete; - - /** - * @brief Generates a licence request. - * - * @param[in] initDataType : The init data type. - * @param[in] initData : The init data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus generateRequest(InitDataType initDataType, const std::vector &initData) = 0; - - /** - * @brief Loads the existing key session. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus loadSession() = 0; - - /** - * @brief Updates the key session's state. - * - * @param[in] responseData : The license response data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus updateSession(const std::vector &responseData) = 0; - - /** - * @brief Decrypts the buffer. - * - * @param[in] encrypted : Gstreamer buffer containing encrypted data and related meta data. If applicable, - * decrypted data will be stored here after this call returns. - * @param[in] caps : The gst caps of buffer. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus decrypt(GstBuffer *encrypted, GstCaps *caps) = 0; - - /** - * @brief Closes the key session. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus closeKeySession() = 0; - - /** - * @brief Removes the key session. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus removeKeySession() = 0; - - /** - * @brief Get the internal CDM key session ID - * - * @param[out] cdmKeySessionId : The internal CDM key session ID - * - * @retval the return status. - */ - virtual MediaKeyErrorStatus getCdmKeySessionId(std::string &cdmKeySessionId) = 0; - - /** - * @brief Returns true if the Key Session object contains the specified key. - * - * @param[in] keyId : The key id. - * - * @retval true if it contains the key. - */ - virtual bool containsKey(const std::vector &keyId) = 0; - - /** - * @brief Set DRM Header for a key session - * - * This method updates a key session's DRM header. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned.If the session - * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any - * other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] requestData : The request data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus setDrmHeader(const std::vector &requestData) = 0; - - /** - * @brief Get the last cdm specific DRM error code - * - * @param[out] errorCode : the error code. - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getLastDrmError(uint32_t &errorCode) = 0; - - /** - * @brief Selects the specified keyId for the key session. Playready specific API. - * - * @param[in] keyId : The key id to select. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus selectKeyId(const std::vector &keyId) = 0; - - /** - * @brief Checks, if key system of media key session is playready. - * - * @retval true if key system is playready - */ - virtual bool isPlayreadyKeySystem() const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_MEDIA_KEY_SESSION_H_ diff --git a/middleware/rialto-client/media/server/main/include/INeedMediaDataThread.h b/middleware/rialto-client/media/server/main/include/INeedMediaDataThread.h deleted file mode 100644 index 7023cc039..000000000 --- a/middleware/rialto-client/media/server/main/include/INeedMediaDataThread.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_NEED_MEDIA_DATA_THREAD_H_ -#define FIREBOLT_RIALTO_SERVER_I_NEED_MEDIA_DATA_THREAD_H_ - -namespace firebolt::rialto::server -{ -class INeedMediaDataThread -{ -public: - INeedMediaDataThread() = default; - virtual ~INeedMediaDataThread() = default; - - INeedMediaDataThread(const INeedMediaDataThread &) = delete; - INeedMediaDataThread(INeedMediaDataThread &&) = delete; - INeedMediaDataThread &operator=(const INeedMediaDataThread &) = delete; - INeedMediaDataThread &operator=(INeedMediaDataThread &&) = delete; - - virtual void queueEvent() = 0; - virtual void stop() = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_NEED_MEDIA_DATA_THREAD_H_ diff --git a/middleware/rialto-client/media/server/main/include/ITextTrackAccessor.h b/middleware/rialto-client/media/server/main/include/ITextTrackAccessor.h deleted file mode 100644 index 86ebc846d..000000000 --- a/middleware/rialto-client/media/server/main/include/ITextTrackAccessor.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_ACCESSOR_H_ -#define FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_ACCESSOR_H_ - -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class ITextTrackAccessor; - -class ITextTrackAccessorFactory -{ -public: - virtual ~ITextTrackAccessorFactory() = default; - - static ITextTrackAccessorFactory &getFactory(); - virtual std::shared_ptr getTextTrackAccessor() const = 0; -}; - -class ITextTrackAccessor -{ -public: - enum class DataType - { - UNKNOWN, - WebVTT, - TTML, - CC - }; - - ITextTrackAccessor() = default; - virtual ~ITextTrackAccessor() = default; - virtual std::optional openSession(const std::string &displayName) = 0; - virtual bool closeSession(uint32_t sessionId) = 0; - virtual bool resetSession(uint32_t sessionId) = 0; - virtual bool pause(uint32_t sessionId) = 0; - virtual bool play(uint32_t sessionId) = 0; - virtual bool mute(uint32_t sessionId, bool mute) = 0; - virtual bool setPosition(uint32_t sessionId, uint64_t mediaTimestampMs) = 0; - virtual bool sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs = 0) = 0; - virtual bool setSessionWebVTTSelection(uint32_t sessionId) = 0; - virtual bool setSessionTTMLSelection(uint32_t sessionId) = 0; - virtual bool setSessionCCSelection(uint32_t sessionId, const std::string &service) = 0; - virtual bool associateVideoDecoder(uint32_t sessionId, const std::string &videoDecoder) = 0; -}; - -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_ACCESSOR_H_ diff --git a/middleware/rialto-client/media/server/main/include/MainThread.h b/middleware/rialto-client/media/server/main/include/MainThread.h deleted file mode 100644 index 9610b1bac..000000000 --- a/middleware/rialto-client/media/server/main/include/MainThread.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_MAIN_THREAD_H_ -#define FIREBOLT_RIALTO_SERVER_MAIN_THREAD_H_ - -#include "IMainThread.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IMainThread factory class definition. - */ -class MainThreadFactory : public IMainThreadFactory -{ -public: - MainThreadFactory() = default; - ~MainThreadFactory() override = default; - - std::shared_ptr getMainThread() const override; - -protected: - /** - * @brief Weak pointer to the singleton main thread object. - */ - static std::weak_ptr m_mainThread; - - /** - * @brief Mutex protection for creation of the MainThread object. - */ - static std::mutex m_creationMutex; -}; - -/** - * @brief The definition of the MediaKeys. - */ -class MainThread : public IMainThread -{ -public: - MainThread(); - virtual ~MainThread(); - - int32_t registerClient() override; - void unregisterClient(uint32_t clientId) override; - - void enqueueTask(uint32_t clientId, Task task) override; - void enqueueTaskAndWait(uint32_t clientId, Task task) override; - void enqueuePriorityTaskAndWait(uint32_t clientId, Task task) override; - -private: - /** - * @brief Information of a task. - */ - struct TaskInfo - { - uint32_t clientId; /**< The id of the client creating the task. */ - Task task; /**< The task to execute. */ - std::unique_ptr mutex; /**< Mutex for the task condition variable. */ - std::unique_ptr cv; /**< The condition variable of the task. */ - }; - - /** - * @brief Starts a loop that listens for enqueued tasks. - */ - void mainThreadLoop(); - - /** - * @brief Waits for tasks to enter the queue and returns the next task. - * - * @retval The next task in the queue. - */ - const std::shared_ptr waitForTask(); - - /** - * @brief Whether the main thread is running. - */ - bool m_isMainThreadRunning; - - /** - * @brief The main thread. - */ - std::thread m_thread; - - /** - * @brief A mutex protecting access to the task queue. - */ - std::mutex m_taskQueueMutex; - - /** - * @brief A condition variable used to notify of tasks entering the task queue. - */ - std::condition_variable m_taskQueueCv; - - /** - * @brief The queue of tasks and there infomation. - */ - std::deque> m_taskQueue; - - /** - * @brief The main thread objects client id, for registering new clients. - */ - const uint32_t m_mainThreadClientId; - - /** - * @brief The next client id to be given to a registering client. - */ - std::atomic m_nextClientId; - - /** - * @brief Clients registered on this thread. - */ - std::set m_registeredClients; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_MAIN_THREAD_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaKeySession.h b/middleware/rialto-client/media/server/main/include/MediaKeySession.h deleted file mode 100644 index 513cbf9fd..000000000 --- a/middleware/rialto-client/media/server/main/include/MediaKeySession.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_KEY_SESSION_H_ -#define FIREBOLT_RIALTO_SERVER_MEDIA_KEY_SESSION_H_ - -#include "IMainThread.h" -#include "IMediaKeySession.h" -#include "IOcdmSessionClient.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IMediaKeySessionFactory factory class definition. - */ -class MediaKeySessionFactory : public IMediaKeySessionFactory -{ -public: - MediaKeySessionFactory() = default; - ~MediaKeySessionFactory() override = default; - - std::unique_ptr createMediaKeySession(const std::string &keySystem, int32_t keySessionId, - const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, - KeySessionType sessionType, - std::weak_ptr client, - bool isLDL) const override; -}; - -/** - * @brief The definition of the MediaKeySession. - */ -class MediaKeySession : public IMediaKeySession, public firebolt::rialto::wrappers::IOcdmSessionClient -{ -public: - /** - * @brief The constructor. - * - * @param[in] keySystem : The key system for this session. - * @param[in] keySessionId : The key session id for this session. - * @param[in] ocdmSystem : The ocdm system object to create the session on. - * @param[in] sessionType : The session type. - * @param[in] client : Client object for callbacks. - * @param[in] isLDL : Is this an LDL. - * @param[in] mainThreadFactory : The main thread factory. - */ - MediaKeySession(const std::string &keySystem, int32_t keySessionId, - const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, KeySessionType sessionType, - std::weak_ptr client, bool isLDL, - const std::shared_ptr &mainThreadFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaKeySession(); - - MediaKeyErrorStatus generateRequest(InitDataType initDataType, const std::vector &initData) override; - - MediaKeyErrorStatus loadSession() override; - - MediaKeyErrorStatus updateSession(const std::vector &responseData) override; - - MediaKeyErrorStatus decrypt(GstBuffer *encrypted, GstCaps *caps) override; - - MediaKeyErrorStatus closeKeySession() override; - - MediaKeyErrorStatus removeKeySession() override; - - MediaKeyErrorStatus getCdmKeySessionId(std::string &cdmKeySessionId) override; - - bool containsKey(const std::vector &keyId) override; - - MediaKeyErrorStatus setDrmHeader(const std::vector &requestData) override; - - MediaKeyErrorStatus getLastDrmError(uint32_t &errorCode) override; - - MediaKeyErrorStatus selectKeyId(const std::vector &keyId) override; - - bool isPlayreadyKeySystem() const override; - - void onProcessChallenge(const char url[], const uint8_t challenge[], const uint16_t challengeLength) override; - - void onKeyUpdated(const uint8_t keyId[], const uint8_t keyIdLength) override; - - void onAllKeysUpdated() override; - - void onError(const char message[]) override; - -private: - /** - * @brief KeySystem type of the MediaKeys. - */ - const std::string m_kKeySystem; - - /** - * @brief The key session id for this session. - */ - const int32_t m_kKeySessionId; - - /** - * @brief The key session type of this session. - */ - const KeySessionType m_kSessionType; - - /** - * @brief The media keys client object. - */ - std::weak_ptr m_mediaKeysClient; - - /** - * @brief The IOcdmSession instance. - */ - std::unique_ptr m_ocdmSession; - - /** - * @brief The mainThread object. - */ - std::shared_ptr m_mainThread; - - /** - * @brief Is the session LDL. - */ - const bool m_kIsLDL; - - /** - * @brief Is the ocdm session constructed. - */ - bool m_isSessionConstructed; - - /** - * @brief Is the ocdm session closed. - */ - bool m_isSessionClosed; - - /** - * @brief Set to true if generateRequest has complete and waiting for license response. - */ - std::atomic m_licenseRequested; - - /** - * @brief Store of the updated key statuses from a onKeyUpdated. - */ - KeyStatusVector m_updatedKeyStatuses; - - /** - * @brief This objects id registered on the main thread - */ - uint32_t m_mainThreadClientId; - - /** - * @brief Currently selected key id (PR specific) - */ - std::vector m_selectedKeyId; - - /** - * @brief Whether a Ocdm call is currently ongoing. - */ - bool m_ongoingOcdmOperation; - - /** - * @brief Whether Ocdm has returned an error via the onError callback. - */ - bool m_ocdmError; - - /** - * @brief Mutex protecting the ocdm error checking. - */ - std::mutex m_ocdmErrorMutex; - - /** - * @brief Drm header to be set once the session is constructed - */ - std::vector m_queuedDrmHeader; - - /** - * @brief Posts a getChallenge task onto the main thread. - * - * The challenge data is retrieved from ocdm and notified on a onLicenseRequest. - */ - void getChallenge(); - - /** - * @brief Initalises the ocdm error data which checks for onError callbacks. - */ - void initOcdmErrorChecking(); - - /** - * @brief Checks if onError has been received. - * - * @param[in] operationStr : Operation name for logging purposes. - * - * @retval True if an error was received. - */ - bool checkForOcdmErrors(const char *operationStr); -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_MEDIA_KEY_SESSION_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaKeysCapabilities.h b/middleware/rialto-client/media/server/main/include/MediaKeysCapabilities.h deleted file mode 100644 index 8c0117c66..000000000 --- a/middleware/rialto-client/media/server/main/include/MediaKeysCapabilities.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_CAPABILITIES_H_ - -#include "IMediaKeysCapabilities.h" -#include "IOcdm.h" -#include "IOcdmSystem.h" -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief IMediaKeysCapabilities factory class definition. - */ -class MediaKeysCapabilitiesFactory : public IMediaKeysCapabilitiesFactory -{ -public: - MediaKeysCapabilitiesFactory() = default; - ~MediaKeysCapabilitiesFactory() override = default; - - std::shared_ptr getMediaKeysCapabilities() const override; -}; - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::server -{ -/** - * @brief The definition of the MediaKeys. - */ -class MediaKeysCapabilities : public IMediaKeysCapabilities -{ -public: - /** - * @brief The constructor. - * - * @param[in] ocdmFactory : The ocdm factory. - * @param[in] ocdmSystemFactory : The ocdmSystem factory. - */ - MediaKeysCapabilities(std::shared_ptr ocdmFactory, - std::shared_ptr ocdmSystemFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaKeysCapabilities(); - - std::vector getSupportedKeySystems() override; - - bool supportsKeySystem(const std::string &keySystem) override; - - bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) override; - - bool isServerCertificateSupported(const std::string &keySystem) override; - -private: - /** - * @brief The IOcdm instance. - */ - std::shared_ptr m_ocdm; - - /** - * @brief The IOcdmSystem factory. - */ - std::shared_ptr m_ocdmSystemFactory; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaKeysCommon.h b/middleware/rialto-client/media/server/main/include/MediaKeysCommon.h deleted file mode 100644 index 70a26a534..000000000 --- a/middleware/rialto-client/media/server/main/include/MediaKeysCommon.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_COMMON_H_ -#define FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_COMMON_H_ - -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief Widevine key system string. - */ -const std::string kWidevineKeySystem{"com.widevine.alpha"}; - -/** - * @brief Playready key system string. - */ -const std::string kPlayreadyKeySystem{"com.microsoft.playready"}; - -/** - * @brief Netflix key system string. - */ -const std::string kNetflixKeySystem{"com.netflix.playready"}; - -/** - * @brief Supported key systems. - */ -const std::array kSupportedKeySystems{kWidevineKeySystem, kPlayreadyKeySystem, kNetflixKeySystem}; -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_COMMON_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaKeysServerInternal.h b/middleware/rialto-client/media/server/main/include/MediaKeysServerInternal.h deleted file mode 100644 index 327aabc5c..000000000 --- a/middleware/rialto-client/media/server/main/include/MediaKeysServerInternal.h +++ /dev/null @@ -1,312 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_SERVER_INTERNAL_H_ - -#include "IMainThread.h" -#include "IMediaKeySession.h" -#include "IMediaKeysServerInternal.h" -#include "IOcdmSystem.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IMediaKeys factory class definition. - */ -class MediaKeysServerInternalFactory : public IMediaKeysServerInternalFactory -{ -public: - MediaKeysServerInternalFactory() = default; - ~MediaKeysServerInternalFactory() override = default; - - std::unique_ptr createMediaKeys(const std::string &keySystem) const override; - std::unique_ptr createMediaKeysServerInternal(const std::string &keySystem) const override; -}; - -}; // namespace firebolt::rialto::server - -namespace firebolt::rialto::server -{ -/** - * @brief The definition of the MediaKeysServerInternal. - */ -class MediaKeysServerInternal : public IMediaKeysServerInternal -{ -public: - struct MediaKeySessionUsage - { - std::unique_ptr mediaKeySession; - uint32_t bufCounter = 0; - bool shouldBeClosed = false; - bool shouldBeReleased = false; - }; - /** - * @brief The constructor. - * - * @param[in] keySystem : The key system for which to create a Media Keys instance. - * @param[in] mainThreadFactory : The main thread factory. - * @param[in] ocdmSystemFactory : The ocdm system factory. - * @param[in] mediaKeySessionFactory : The media key session factory. - * - */ - MediaKeysServerInternal(const std::string &keySystem, const std::shared_ptr &mainThreadFactory, - std::shared_ptr ocdmSystemFactory, - std::shared_ptr mediaKeySessionFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaKeysServerInternal(); - - MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) override; - - bool containsKey(int32_t keySessionId, const std::vector &keyId) override; - - MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, bool isLDL, - int32_t &keySessionId) override; - - MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) override; - - MediaKeyErrorStatus loadSession(int32_t keySessionId) override; - - MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) override; - - MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) override; - - MediaKeyErrorStatus closeKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus removeKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus deleteDrmStore() override; - - MediaKeyErrorStatus deleteKeyStore() override; - - MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) override; - - MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) override; - - MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) override; - - MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) override; - - MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) override; - - MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) override; - - MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) override; - - MediaKeyErrorStatus decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) override; - - MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) override; - - bool hasSession(int32_t keySessionId) const override; - - bool isPlayreadyKeySystem(int32_t keySessionId) const override; - - void incrementSessionIdUsageCounter(int32_t keySessionId) override; - void decrementSessionIdUsageCounter(int32_t keySessionId) override; - void ping(std::unique_ptr &&heartbeatHandler) override; - -private: - /** - * @brief The mainThread object. - */ - std::shared_ptr m_mainThread; - - /** - * @brief The factory for creating MediaKeySessions. - */ - std::shared_ptr m_mediaKeySessionFactory; - - /** - * @brief The IOcdmSystem instance. - */ - std::shared_ptr m_ocdmSystem; - - /** - * @brief Map containing created sessions. - */ - std::map m_mediaKeySessions; - - /** - * @brief KeySystem type of the MediaKeysServerInternal. - */ - const std::string m_keySystem; - - /** - * @brief This objects id registered on the main thread - */ - uint32_t m_mainThreadClientId; - - /** - * @brief Creates a session internally, only to be called on the main thread. - * - * @param[in] sessionType : The session type. - * @param[in] client : Client object for callbacks - * @param[in] isLDL : Is this an LDL - * @param[out] keySessionId: The key session id - * - * @retval an error status. - */ - MediaKeyErrorStatus createKeySessionInternal(KeySessionType sessionType, std::weak_ptr client, - bool isLDL, int32_t &keySessionId); - - /** - * @brief Generate internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] initDataType : The init data type. - * @param[in] initData : The init data. - * - * @retval an error status. - */ - MediaKeyErrorStatus generateRequestInternal(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData); - - /** - * @brief Load internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id for the session. - * - * @retval an error status. - */ - MediaKeyErrorStatus loadSessionInternal(int32_t keySessionId); - - /** - * @brief Update internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] responseData : The license response data. - * - * @retval an error status. - */ - MediaKeyErrorStatus updateSessionInternal(int32_t keySessionId, const std::vector &responseData); - - /** - * @brief Close a key session internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - MediaKeyErrorStatus closeKeySessionInternal(int32_t keySessionId); - - /** - * @brief Removes a key session internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - MediaKeyErrorStatus removeKeySessionInternal(int32_t keySessionId); - - /** - * @brief Get the key session id internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id for the session. - * @param[out] cdmKeySessionId : The internal CDM key session ID - * - * @retval an error status. - */ - MediaKeyErrorStatus getCdmKeySessionIdInternal(int32_t keySessionId, std::string &cdmKeySessionId); - - /** - * @brief Decrypt internally, only to be called on the main thread. - * - * @param[in] keySessionId : The session id for the session. - * @param[in] encrypted : Gstreamer buffer containing encrypted data and related meta data. If applicable, - * decrypted data will be stored here after this call returns. - * @param[in] caps : The gst caps of buffer. - * - * @retval an error status. - */ - MediaKeyErrorStatus decryptInternal(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps); - - /** - * @brief Selects the specified keyId for the key session internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] keyId : The key id to select. - * - * @retval an error status. - */ - MediaKeyErrorStatus selectKeyIdInternal(int32_t keySessionId, const std::vector &keyId); - - /** - * @brief Returns true if the Key Session object contains the specified key internally, - * only to be called on the main thread. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] keyId : The key id. - * - * @retval true if it contains the key. - */ - bool containsKeyInternal(int32_t keySessionId, const std::vector &keyId); - - /** - * @brief Set DRM Header for a key session internally, only to be called on the main thread. - * - * @param[in] keySessionId : The session id for the session. - * @param[in] requestData : The request data. - * - * @retval an error status. - */ - MediaKeyErrorStatus setDrmHeaderInternal(int32_t keySessionId, const std::vector &requestData); - - /** - * @brief Get the last cdm specific DRM error code internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id. - * @param[out] errorCode : the error code. - * - * @retval the return status value. - */ - MediaKeyErrorStatus getLastDrmErrorInternal(int32_t keySessionId, uint32_t &errorCode); - - /** - * @brief Checks, if key system of media key session is Playready internally, only to be called on the main thread. - * - * @param[in] keySessionId : The session id for the session. - * - * @retval true if key system is Playready - */ - bool isPlayreadyKeySystemInternal(int32_t keySessionId) const; - - /** - * @brief Releases a key session internally, only to be called on the main thread. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - MediaKeyErrorStatus releaseKeySessionInternal(int32_t keySessionId); - - void incrementSessionIdUsageCounterInternal(int32_t keySessionId); - void decrementSessionIdUsageCounterInternal(int32_t keySessionId); -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_MEDIA_KEYS_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaPipelineCapabilities.h b/middleware/rialto-client/media/server/main/include/MediaPipelineCapabilities.h deleted file mode 100644 index e65ac91f7..000000000 --- a/middleware/rialto-client/media/server/main/include/MediaPipelineCapabilities.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_CAPABILITIES_H_ - -#include "IGstCapabilities.h" -#include "IMediaPipelineCapabilities.h" -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief IMediaPipelineCapabilities factory class definition. - */ -class MediaPipelineCapabilitiesFactory : public IMediaPipelineCapabilitiesFactory -{ -public: - MediaPipelineCapabilitiesFactory() = default; - ~MediaPipelineCapabilitiesFactory() override = default; - - std::unique_ptr createMediaPipelineCapabilities() const override; -}; - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::server -{ -/** - * @brief The definition of the MediaPipeline. - */ -class MediaPipelineCapabilities : public IMediaPipelineCapabilities -{ -public: - /** - * @brief The constructor. - * - * @param[in] gstCapabilitiesFactory : The gstreamer capabilities factory. - */ - explicit MediaPipelineCapabilities(std::shared_ptr gstCapabilitiesFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaPipelineCapabilities(); - - std::vector getSupportedMimeTypes(MediaSourceType sourceType) override; - bool isMimeTypeSupported(const std::string &mimeType) override; - std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) override; - bool isVideoMaster(bool &isVideoMaster) override; - -private: - /** - * @brief The gstreamer capabilities. - */ - std::unique_ptr m_gstCapabilities; - - /** - * @brief The gstreamer capabilities factory object. - */ - const std::shared_ptr m_kGstCapabilitiesFactory; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_CAPABILITIES_H_ diff --git a/middleware/rialto-client/media/server/main/include/MediaPipelineServerInternal.h b/middleware/rialto-client/media/server/main/include/MediaPipelineServerInternal.h deleted file mode 100644 index 7379bad14..000000000 --- a/middleware/rialto-client/media/server/main/include/MediaPipelineServerInternal.h +++ /dev/null @@ -1,720 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_SERVER_INTERNAL_H_ - -#include "DataReaderFactory.h" -#include "IActiveRequests.h" -#include "IGstGenericPlayer.h" -#include "IMainThread.h" -#include "IMediaPipelineServerInternal.h" -#include "ITimer.h" -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IMediaPipelineServerInternal factory class definition. - */ -class MediaPipelineServerInternalFactory : public server::IMediaPipelineServerInternalFactory -{ -public: - MediaPipelineServerInternalFactory() = default; - ~MediaPipelineServerInternalFactory() override = default; - - std::unique_ptr createMediaPipeline(std::weak_ptr client, - const VideoRequirements &videoRequirements) const override; - - std::unique_ptr createMediaPipelineServerInternal( - std::weak_ptr client, const VideoRequirements &videoRequirements, int sessionId, - const std::shared_ptr &shmBuffer, IDecryptionService &decryptionService) const override; - - /** - * @brief Create the generic media player factory object. - * - * @retval the generic media player factory instance or null on error. - */ - static std::shared_ptr createFactory(); -}; - -/** - * @brief The definition of the MediaPipelineServerInternal. - */ -class MediaPipelineServerInternal : public IMediaPipelineServerInternal, public IGstGenericPlayerClient -{ -public: - /** - * @brief The constructor. - * - * @param[in] client : The Rialto media player client. - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session. - * @param[in] gstPlayerFactory : The gstreamer player factory. - * @param[in] sessionId : The session id - * @param[in] shmBuffer : The shared memory buffer - * @param[in] mainThreadFactory : The main thread factory. - * @param[in] dataReaderFactory : The data reader factory - * @param[in] activeRequests : The active requests - * @param[in] decryptionService : The decryption service - */ - MediaPipelineServerInternal(std::shared_ptr client, const VideoRequirements &videoRequirements, - const std::shared_ptr &gstPlayerFactory, int sessionId, - const std::shared_ptr &shmBuffer, - const std::shared_ptr &mainThreadFactory, - std::shared_ptr timerFactory, - std::unique_ptr &&dataReaderFactory, - std::unique_ptr &&activeRequests, IDecryptionService &decryptionService); - - /** - * @brief Virtual destructor. - */ - virtual ~MediaPipelineServerInternal(); - - bool load(MediaType type, const std::string &mimeType, const std::string &url) override; - - bool attachSource(const std::unique_ptr &source) override; - - bool removeSource(int32_t id) override; - - bool allSourcesAttached() override; - - bool play() override; - - bool pause() override; - - bool stop() override; - - bool setPlaybackRate(double rate) override; - - bool setPosition(int64_t position) override; - - bool getPosition(int64_t &position) override; - - bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override; - - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override; - - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; - - bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; - - bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override; - - bool haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId) override; - - void ping(std::unique_ptr &&heartbeatHandler) override; - - bool renderFrame() override; - - bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override; - - bool getVolume(double ¤tVolume) override; - - bool setMute(std::int32_t sourceId, bool mute) override; - - bool getMute(std::int32_t sourceId, bool &mute) override; - - bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; - - bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; - - bool setLowLatency(bool lowLatency) override; - - bool setSync(bool sync) override; - - bool getSync(bool &sync) override; - - bool setSyncOff(bool syncOff) override; - - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; - - bool getStreamSyncMode(int32_t &streamSyncMode) override; - - bool flush(int32_t sourceId, bool resetTime, bool &async) override; - - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) override; - - bool setSubtitleOffset(int32_t sourceId, int64_t position) override; - - bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; - - bool setBufferingLimit(uint32_t limitBufferingMs) override; - - bool getBufferingLimit(uint32_t &limitBufferingMs) override; - - bool setUseBuffering(bool useBuffering) override; - - bool getUseBuffering(bool &useBuffering) override; - - bool switchSource(const std::unique_ptr &source) override; - - AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; - - std::weak_ptr getClient() override; - - void notifyPlaybackState(PlaybackState state) override; - - bool notifyNeedMediaData(MediaSourceType mediaSourceType) override; - - void notifyPosition(std::int64_t position) override; - - void notifyNetworkState(NetworkState state) override; - - void clearActiveRequestsCache() override; - - void invalidateActiveRequests(const MediaSourceType &type) override; - - void notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo) override; - - void notifyBufferUnderflow(MediaSourceType mediaSourceType) override; - - void notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error) override; - - void notifySourceFlushed(MediaSourceType mediaSourceType) override; - -protected: - /** - * @brief The media player client. - */ - std::shared_ptr m_mediaPipelineClient; - - /** - * @brief The mainThread object. - */ - std::shared_ptr m_mainThread; - - /** - * @brief The gstreamer player factory object. - */ - const std::shared_ptr m_kGstPlayerFactory; - - /** - * @brief The gstreamer player. - */ - std::unique_ptr m_gstPlayer; - - /** - * @brief The video decoder requirements for the MediaPipeline session. - */ - const VideoRequirements m_kVideoRequirements; - - /** - * @brief ID of a session represented by this MediaPipeline - */ - int m_sessionId; - - /** - * @brief Shared memory buffer - */ - std::shared_ptr m_shmBuffer; - - /** - * @brief DataReader factory - */ - std::unique_ptr m_dataReaderFactory; - - /** - * @brief Factory creating timers - */ - std::shared_ptr m_timerFactory; - - /** - * @brief Object containing all active NeedDataRequests - */ - std::unique_ptr m_activeRequests; - - /** - * @brief This objects id registered on the main thread - */ - uint32_t m_mainThreadClientId; - - /** - * @brief Decryption service - */ - IDecryptionService &m_decryptionService; - - /** - * @brief Current playback state - */ - PlaybackState m_currentPlaybackState; - - /** - * @brief Map containing scheduled need media data requests. - */ - std::unordered_map> m_needMediaDataTimers; - - /** - * @brief Currently attached sources - */ - std::map m_attachedSources; - - /** - * @brief Map to keep track of the count of MediaSourceStatus with the value NO_AVAILABLE_SAMPLES for each MediaSource - */ - std::map m_noAvailableSamplesCounter; - - /** - * @brief Flag used to check if allSourcesAttached was already called - */ - bool m_wasAllSourcesAttachedCalled; - - /** - * @brief Flag used to check if low latency is set for video source - */ - bool m_IsLowLatencyVideoPlayer{false}; - - /** - * @brief Flag used to check if low latency is set for audio source - */ - bool m_IsLowLatencyAudioPlayer{false}; - - /** - * @brief Map of flags used to check if Eos has been set on the media type for this playback - */ - std::map m_isMediaTypeEosMap; - - /** - * @brief Mutex to protect gstPlayer access in getPosition method - */ - std::shared_mutex m_getPositionMutex; - - /** - * @brief Load internally, only to be called on the main thread. - * - * @param[in] type : The media type. - * @param[in] mimeType : The MIME type. - * @param[in] url : The URL. - * - * @retval true on success. - */ - bool loadInternal(MediaType type, const std::string &mimeType, const std::string &url); - - /** - * @brief Attach source internally, only to be called on the main thread. - * - * @param[in] source : The source. - * - * @retval true on success. - */ - bool attachSourceInternal(const std::unique_ptr &source); - - /** - * @brief Remove source internally, only to be called on the main thread. - * - * @param[in] id : The source id. - * - * @retval true on success. - */ - bool removeSourceInternal(int32_t id); - - /** - * @brief Notify all sources attached internally, only to be called on the main thread. - * - * @retval true on success. - */ - bool allSourcesAttachedInternal(); - - /** - * @brief Play internally, only to be called on the main thread. - * - * @retval true on success. - */ - bool playInternal(); - - /** - * @brief Pause internally, only to be called on the main thread. - * - * @retval true on success. - */ - bool pauseInternal(); - - /** - * @brief Stop internally, only to be called on the main thread. - * - * @retval true on success. - */ - bool stopInternal(); - - /** - * @brief Set the playback rate internally, only to be called on the main thread. - * - * @param[in] rate : The playback rate. - * - * @retval true on success. - */ - bool setPlaybackRateInternal(double rate); - - /** - * @brief Set the position internally, only to be called on the main thread. - * - * @param[in] position : The playback position in nanoseconds. - * - * @retval true on success. - */ - bool setPositionInternal(int64_t position); - - /** - * @brief Sets the "Immediate Output" property for this source. - * - * This method is asynchronous - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] immediateOutput : The desired immediate output mode on the sink - * - * @retval true on success. - */ - bool setImmediateOutputInternal(int32_t sourceId, bool immediateOutput); - - /** - * @brief Gets the "Immediate Output" property for this source. - * - * This method is sychronous - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[out] immediateOutput : Returns the immediate output mode on the sink - * - * @retval true on success. - */ - bool getImmediateOutputInternal(int32_t sourceId, bool &immediateOutput); - - /** - * @brief Get stats for this source. - * - * This method is sychronous, it returns dropped frames and rendered frames - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[out] renderedFrames : The number of rendered frames - * @param[out] droppedFrames : The number of dropped frames - * - * @retval true on success. - */ - bool getStatsInternal(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames); - - /** - * @brief Set video window internally, only to be called on the main thread. - * - * @param[in] x : The x position in pixels. - * @param[in] y : The y position in pixels. - * @param[in] width : The width in pixels. - * @param[in] height : The height in pixels. - * - * @retval true on success. - */ - bool setVideoWindowInternal(uint32_t x, uint32_t y, uint32_t width, uint32_t height); - - /** - * @brief Have data internally, only to be called on the main thread. - * - * @param[in] status : The status - * @param[in] needDataRequestId : Need data request id - * - * @retval true on success. - */ - bool haveDataInternal(MediaSourceStatus status, uint32_t needDataRequestId); - - /** - * @brief Render frame internally, only to be called on the main thread. - * - * @retval true on success. - */ - bool renderFrameInternal(); - - /** - * @brief Have data internally, only to be called on the main thread. - * - * @param[in] status : The status - * @param[in] numFrames : The number of frames written. - * @param[in] needDataRequestId : Need data request id - * - * @retval true on success. - */ - bool haveDataInternal(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId); - - /** - * @brief Add segment internally, only to be called on the main thread. - * - * @param[in] needDataRequestId : The status - * @param[in] mediaSegment : The data returned. - * - * @retval status of adding segment - */ - AddSegmentStatus addSegmentInternal(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment); - - /** - * @brief Notify need media data internally, only to be called on the main thread. - * - * @param[in] mediaSourceType : The media source type. - */ - bool notifyNeedMediaDataInternal(MediaSourceType mediaSourceType); - - /** - * @brief Schedules resending of NeedMediaData after a short delay. Used when no segments were received in the - * haveData() call to prevent a storm of needData()/haveData() calls, only to be called on the main thread. - * - * @param[in] mediaSourceType : The media source type. - */ - void scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType); - - /** - * @brief Set the target volume level with a transition internally, only to be called on the main thread. - * - * @param[in] targetVolume : Target volume level (0.0 - 1.0) - * @param[in] volumeDuration : Duration of the volume transition in milliseconds - * @param[in] ease_type : Easing type for the volume transition - * - * @retval true on success, false otherwise - */ - bool setVolumeInternal(double targetVolume, uint32_t volumeDuration, EaseType easeType); - - /** - * @brief Get the current volume level internally, only to be called on the main thread. - * Fetches the current volume level for the pipeline. - * - * @param[out] currentVolume : Current volume level (range 0.0 - 1.0) - * - * @retval true on success, false otherwise - */ - bool getVolumeInternal(double ¤tVolume); - - /** - * @brief Set mute internally, only to be called on the main thread. - * - * @param[in] mute Desired mute state, true=muted, false=not muted - * - * @retval true on success false otherwise - */ - bool setMuteInternal(std::int32_t sourceId, bool mute); - - /** - * @brief Get mute internally, only to be called on the main thread. - * - * @param[out] mute Current mute state - * - * @retval true on success false otherwise - */ - bool getMuteInternal(std::int32_t sourceId, bool &mute); - - /** - * @brief Change Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - bool setTextTrackIdentifierInternal(const std::string &textTrackIdentifier); - - /** - * @brief Get Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - bool getTextTrackIdentifierInternal(std::string &textTrackIdentifier); - - /** - * @brief Set low latency internally, only to be called on the main thread. - * - * @param[in] lowLatency : The low latency value to set. - * - * @retval true on success false otherwise - */ - bool setLowLatencyInternal(bool lowLatency); - - /** - * @brief Set sync internally, only to be called on the main thread. - * - * @param[in] sync : The sync value to set. - * - * @retval true on success false otherwise - */ - bool setSyncInternal(bool sync); - - /** - * @brief Get sync internally, only to be called on the main thread. - * - * @param[out] sync : Current sync value. - * - * @retval true on success false otherwise - */ - bool getSyncInternal(bool &sync); - - /** - * @brief Set sync off internally, only to be called on the main thread. - * - * @param[in] syncOff : The sync off value to set. - * - * @retval true on success false otherwise - */ - bool setSyncOffInternal(bool syncOff); - - /** - * @brief Set stream sync mode internally, only to be called on the main thread. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] streamSyncMode : The stream sync mode value to set. - * - * @retval true on success false otherwise - */ - bool setStreamSyncModeInternal(int32_t sourceId, int32_t streamSyncMode); - - /** - * @brief Get stream sync mode internally, only to be called on the main thread. - * - * @param[out] streamSyncMode : Current stream sync mode value. - * - * @retval true on success false otherwise - */ - bool getStreamSyncModeInternal(int32_t &streamSyncMode); - - /** - * @brief Checks if MediaPipeline threads are not deadlocked internally - * - * @param[out] heartbeatHandler : The heartbeat handler instance - */ - void pingInternal(std::unique_ptr &&heartbeatHandler); - - /** - * @brief Flushes a source. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] resetTime : True if time should be reset - * @param[out] async : True if flushed source is asynchronous (will preroll after flush) - * - * @retval true on success. - */ - bool flushInternal(int32_t sourceId, bool resetTime, bool &async); - - /** - * @brief Set the source position in nanoseconds. - * - * This method sets the start position for a source. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] position : The position in nanoseconds. - * @param[in] resetTime : True if time should be reset - * @param[in] appliedRate : The applied rate after seek - * @param[in] stopPosition : The position of last pushed buffer - * - * @retval true on success. - */ - bool setSourcePositionInternal(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition); - - /** - * @brief Set subtitle offset for a subtitle source. - * - * This method is used to set the subtitle offset for a subtitle source. - * - * @param[in] sourceId : The id of the subtitle source - * @param[in] position : The subtitle offset position in nanoseconds - * - * @retval true on success. - */ - bool setSubtitleOffsetInternal(int32_t sourceId, int64_t position); - - /** - * @brief Process audio gap - * - * This method handles audio gap in order to avoid audio pops during transitions. - * - * @param[in] position : Audio pts fade position - * @param[in] duration : Audio pts fade duration - * @param[in] discontinuityGap : Audio discontinuity gap - * @param[in] audioAac : True if audio codec is AAC - * - * @retval true on success. - */ - bool processAudioGapInternal(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac); - - /** - * @brief Set buffering limit - * - * This method enables/disables limit buffering and sets millisecond threshold used. - * Use kInvalidLimitBuffering to disable limit buffering - * - * @param[in] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - bool setBufferingLimitInternal(uint32_t limitBufferingMs); - - /** - * @brief Get buffering limit - * - * This method returns current value of buffering limit in milliseconds - * Method will return kInvalidLimitBuffering limit buffering is disabled - * - * @param[out] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - bool getBufferingLimitInternal(uint32_t &limitBufferingMs); - - /** - * @brief Enables/disables the buffering option - * - * This method enables the buffering option so that BUFFERING messages are - * emitted based on low-/high-percent thresholds. - * - * @param[in] useBuffering : true if buffering option enabled. - * - * @retval true on success. - */ - bool setUseBufferingInternal(bool useBuffering); - - /** - * @brief Checks, if buffering is enabled - * - * This method returns true, if buffering is enabled - * - * @param[out] useBuffering : true if buffering option is enabled. - * - * @retval true on success. - */ - bool getUseBufferingInternal(bool &useBuffering); - - /** - * @brief Switches a source. - * - * @param[in] mediaSource : The media source. - * - */ - bool switchSourceInternal(const std::unique_ptr &source); - - /** - * @brief Returns how long should we wait to send next NeedMediaData - * if rialto client returns NO_AVAILABLE_SAMPLES - * - * @param[in] mediaSourceType : The media source type. - * - * @retval NeedMediaData timeout - */ - std::chrono::milliseconds getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_MEDIA_PIPELINE_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/include/NeedMediaData.h b/middleware/rialto-client/media/server/main/include/NeedMediaData.h deleted file mode 100644 index 3345b49f8..000000000 --- a/middleware/rialto-client/media/server/main/include/NeedMediaData.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_NEED_MEDIA_DATA_H_ -#define FIREBOLT_RIALTO_SERVER_NEED_MEDIA_DATA_H_ - -#include "IActiveRequests.h" -#include "IMediaPipelineClient.h" -#include "ISharedMemoryBuffer.h" -#include "MediaCommon.h" -#include -#include - -namespace firebolt::rialto::server -{ -class NeedMediaData -{ -public: - NeedMediaData(std::weak_ptr client, IActiveRequests &activeRequests, - const ISharedMemoryBuffer &shmBuffer, int sessionId, MediaSourceType mediaSourceType, - std::int32_t sourceId, PlaybackState currentPlaybackState); - ~NeedMediaData() = default; - - bool send() const; - -private: - std::weak_ptr m_client; - IActiveRequests &m_activeRequests; - MediaSourceType m_mediaSourceType; - std::uint32_t m_frameCount; - std::int32_t m_sourceId; - std::uint32_t m_maxMediaBytes; - std::shared_ptr m_shmInfo; - bool m_isValid; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_NEED_MEDIA_DATA_H_ diff --git a/middleware/rialto-client/media/server/main/include/SharedMemoryBuffer.h b/middleware/rialto-client/media/server/main/include/SharedMemoryBuffer.h deleted file mode 100644 index 5f43a6f8d..000000000 --- a/middleware/rialto-client/media/server/main/include/SharedMemoryBuffer.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SHARED_MEMORY_BUFFER_H_ -#define FIREBOLT_RIALTO_SERVER_SHARED_MEMORY_BUFFER_H_ - -#include "ISharedMemoryBuffer.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -class SharedMemoryBufferFactory : public ISharedMemoryBufferFactory -{ -public: - ~SharedMemoryBufferFactory() override = default; - std::shared_ptr createSharedMemoryBuffer(unsigned numOfPlaybacks, - unsigned numOfWebAudioPlayers) const override; -}; - -class SharedMemoryBuffer : public ISharedMemoryBuffer -{ -public: - explicit SharedMemoryBuffer(unsigned numOfPlaybacks, unsigned numOfWebAudioPlayers); - ~SharedMemoryBuffer() override; - SharedMemoryBuffer(const SharedMemoryBuffer &) = delete; - SharedMemoryBuffer(SharedMemoryBuffer &&) = delete; - SharedMemoryBuffer &operator=(const SharedMemoryBuffer &) = delete; - SharedMemoryBuffer &operator=(SharedMemoryBuffer &&) = delete; - - bool mapPartition(MediaPlaybackType playbackType, int id) override; - bool unmapPartition(MediaPlaybackType playbackType, int id) override; - - bool clearData(MediaPlaybackType playbackType, int id, const MediaSourceType &mediaSourceType) const override; - - std::uint32_t getDataOffset(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const override; - std::uint32_t getMaxDataLen(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const override; - std::uint8_t *getDataPtr(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const override; - - int getFd() const override; - std::uint32_t getSize() const override; - std::uint8_t *getBuffer() const override; - - struct Partition - { - int id; - std::uint32_t dataBufferAudioLen; - std::uint32_t dataBufferVideoLen; - std::uint32_t dataBufferSubtitleLen; - }; - -private: - size_t calculateBufferSize() const; - bool getDataPtrForPartition(MediaPlaybackType playbackType, int id, std::uint8_t **ptr) const; - const std::vector *getPlaybackTypePartition(MediaPlaybackType playbackType) const; - std::vector *getPlaybackTypePartition(MediaPlaybackType playbackType); - -private: - std::vector m_genericPartitions; - std::vector m_webAudioPartitions; - std::uint32_t m_dataBufferLen; - int m_dataBufferFd; - std::uint8_t *m_dataBuffer; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_SHARED_MEMORY_BUFFER_H_ diff --git a/middleware/rialto-client/media/server/main/include/ShmUtils.h b/middleware/rialto-client/media/server/main/include/ShmUtils.h deleted file mode 100644 index 34f722fb6..000000000 --- a/middleware/rialto-client/media/server/main/include/ShmUtils.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SHM_UTILS_H_ -#define FIREBOLT_RIALTO_SERVER_SHM_UTILS_H_ - -#include "ShmCommon.h" -#include - -namespace firebolt::rialto::server -{ -constexpr std::uint32_t kPrerollNumFrames{3}; -constexpr std::uint32_t kMaxFrames{24}; -constexpr std::uint32_t getMaxMetadataBytes() -{ - // The Rialto Server must size the metadata regions to be at least the following size: - // 4 bytes version + max_frames_to_request * (maximum metadata struct size for stream type & - // supported metadata format versions) - - // Metadata V2 contains version only, so maximum metadata size is size of MetadataV1 - std::uint32_t maxMetadataStructSize = common::METADATA_V1_SIZE_PER_FRAME_BYTES; - return common::VERSION_SIZE_BYTES + kMaxFrames * maxMetadataStructSize; -} -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_SHM_UTILS_H_ diff --git a/middleware/rialto-client/media/server/main/include/TextTrackAccessor.h b/middleware/rialto-client/media/server/main/include/TextTrackAccessor.h deleted file mode 100644 index 98cce9db5..000000000 --- a/middleware/rialto-client/media/server/main/include/TextTrackAccessor.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TEXT_TRACK_ACCESSOR_H_ -#define FIREBOLT_RIALTO_SERVER_TEXT_TRACK_ACCESSOR_H_ - -#include "ITextTrackAccessor.h" -#include "ITextTrackPluginWrapper.h" -#include "ITextTrackWrapper.h" -#include "IThunderWrapper.h" -#include "RialtoServerLogging.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class TextTrackAccessorFactory : public ITextTrackAccessorFactory -{ -public: - std::shared_ptr getTextTrackAccessor() const override; -}; - -class TextTrackAccessor : public ITextTrackAccessor -{ -public: - TextTrackAccessor(const std::shared_ptr &textTrackPluginWrapper, - const std::shared_ptr &thunderWrapper); - ~TextTrackAccessor() override; - std::optional openSession(const std::string &displayName) override; - bool closeSession(uint32_t sessionId) override; - bool resetSession(uint32_t sessionId) override; - bool pause(uint32_t sessionId) override; - bool play(uint32_t sessionId) override; - bool mute(uint32_t sessionId, bool mute) override; - bool setPosition(uint32_t sessionId, uint64_t mediaTimestampMs) override; - bool sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs) override; - bool setSessionWebVTTSelection(uint32_t sessionId) override; - bool setSessionTTMLSelection(uint32_t sessionId) override; - bool setSessionCCSelection(uint32_t sessionId, const std::string &service) override; - bool associateVideoDecoder(uint32_t sessionId, const std::string &videoDecoder) override; - -private: - bool createTextTrackControlInterface(); - - std::shared_ptr m_textTrackPluginWrapper; - std::shared_ptr m_thunderWrapper; - std::shared_ptr m_textTrackWrapper; -}; - -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_TEXT_TRACK_ACCESSOR_H_ diff --git a/middleware/rialto-client/media/server/main/include/TextTrackSession.h b/middleware/rialto-client/media/server/main/include/TextTrackSession.h deleted file mode 100644 index 16be2c6e9..000000000 --- a/middleware/rialto-client/media/server/main/include/TextTrackSession.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_TEXT_TRACK_SESSION_H_ -#define FIREBOLT_RIALTO_SERVER_TEXT_TRACK_SESSION_H_ - -#include "ITextTrackAccessor.h" -#include "ITextTrackSession.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -class TextTrackSessionFactory : public ITextTrackSessionFactory -{ -public: - std::unique_ptr createTextTrackSession(const std::string &display) const override; -}; - -class TextTrackSession : public ITextTrackSession -{ -public: - TextTrackSession(const std::string &displayName, const ITextTrackAccessorFactory &textTrackAccessorFactory); - ~TextTrackSession() override; - bool resetSession(bool isMuted) override; - bool pause() override; - bool play() override; - bool mute(bool mute) override; - bool setPosition(uint64_t mediaTimestampMs) override; - bool sendData(const std::string &data, int64_t displayOffsetMs = 0) override; - bool setSessionWebVTTSelection() override; - bool setSessionTTMLSelection() override; - bool setSessionCCSelection(const std::string &service) override; - bool associateVideoDecoder(uint64_t decoderId) override; - bool isClosedCaptions() const override; - -private: - std::shared_ptr m_textTrackAccessor; - ITextTrackAccessor::DataType m_dataType{ITextTrackAccessor::DataType::UNKNOWN}; - uint32_t m_sessionId{0}; - std::optional m_ccService; - std::optional m_videoDecoderId; -}; -} // namespace firebolt::rialto::server -#endif // FIREBOLT_RIALTO_SERVER_TEXT_TRACK_SESSION_H_ diff --git a/middleware/rialto-client/media/server/main/include/WebAudioPlayerServerInternal.h b/middleware/rialto-client/media/server/main/include/WebAudioPlayerServerInternal.h deleted file mode 100644 index c4755966e..000000000 --- a/middleware/rialto-client/media/server/main/include/WebAudioPlayerServerInternal.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ - -#include "IGstWebAudioPlayer.h" -#include "IMainThread.h" -#include "ITimer.h" -#include "IWebAudioPlayer.h" -#include "IWebAudioPlayerServerInternal.h" - -#include -#include -#include - -namespace firebolt::rialto::server -{ -/** - * @brief IWebAudioPlayer factory class definition. - */ -class WebAudioPlayerServerInternalFactory : public IWebAudioPlayerServerInternalFactory -{ -public: - WebAudioPlayerServerInternalFactory() = default; - ~WebAudioPlayerServerInternalFactory() override = default; - - std::unique_ptr createWebAudioPlayer(std::weak_ptr client, - const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config) const override; - - std::unique_ptr createWebAudioPlayerServerInternal( - std::weak_ptr client, const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config, const std::shared_ptr &shmBuffer, int handle, - const std::shared_ptr &mainThreadFactory, - const std::shared_ptr &gstPlayerFactory, - std::weak_ptr timerFactory) const override; -}; - -/** - * @brief The definition of the WebAudioPlayerServerInternal. - */ -class WebAudioPlayerServerInternal : public IWebAudioPlayerServerInternal, public IGstWebAudioPlayerClient -{ -public: - /** - * @brief The constructor. - * - * @param[in] client : The Web Audio Player client. - * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM). - * @param[in] priority : Priority value for this pipeline. - * @param[in] config : Additional type dependent configuration data or nullptr. - * @param[in] shmBuffer : The shared memory buffer. - * @param[in] handle : The handle for this WebAudioPlayer. - * @param[in] mainThreadFactory : The main thread factory. - * @param[in] gstPlayerFactory : The gstreamer player factory. - * @param[in] timerFactory : The timer factory. - */ - WebAudioPlayerServerInternal(std::weak_ptr client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config, - const std::shared_ptr &shmBuffer, int handle, - const std::shared_ptr &mainThreadFactory, - const std::shared_ptr &gstPlayerFactory, - std::weak_ptr timerFactory); - - /** - * @brief Virtual destructor. - */ - virtual ~WebAudioPlayerServerInternal(); - - bool play() override; - - bool pause() override; - - bool setEos() override; - - bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) override; - - bool getBufferDelay(uint32_t &delayFrames) override; - - bool writeBuffer(const uint32_t numberOfFrames, void *data) override; - - bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override; - - bool setVolume(double volume) override; - - bool getVolume(double &volume) override; - - std::weak_ptr getClient() override; - - void notifyState(WebAudioPlayerState state) override; - - void ping(std::unique_ptr &&heartbeatHandler) override; - -protected: - /** - * @brief The web audio player client. - */ - std::shared_ptr m_webAudioPlayerClient; - - /** - * @brief Shared memory buffer. - */ - std::shared_ptr m_shmBuffer; - - /** - * @brief The mainThread object. - */ - std::shared_ptr m_mainThread; - - /** - * @brief This objects id registered on the main thread. - */ - uint32_t m_mainThreadClientId; - - /** - * @brief This priority of the WebAudioPlayer object. - */ - const uint32_t m_priority; - - /** - * @brief The gstreamer player. - */ - std::unique_ptr m_gstPlayer; - - /** - * @brief The id of the shared memory partition. - */ - const int m_shmId; - - /** - * @brief Pointer to the start of the shared buffer. - */ - uint8_t *m_shmPtr; - - /** - * @brief Offset of the web audio partition relative to the start of the shared memory. - */ - uint32_t m_partitionOffset; - - /** - * @brief Length of the shared buffer partition. - */ - uint32_t m_maxDataLength; - - /** - * @brief The details of the free space in the shared buffer partition. - */ - WebAudioShmInfo m_availableBuffer; - - /** - * @brief True if a writeBuffer call is expected. - */ - bool m_expectWriteBuffer; - - /** - * @brief Factory for creating timers. - */ - std::shared_ptr m_timerFactory; - - /** - * @brief Timer set to write data to gstreamer. - */ - std::unique_ptr m_writeDataTimer; - - /** - * @brief The bytes per frame for this audio playback. - */ - uint32_t m_bytesPerFrame; - - /** - * @brief Whether EOS has been requested at the end of the buffer. - */ - bool m_isEosRequested; - - /** - * @brief Initalises the WebAudioPlayer. - * - * @param[in] audioMimeType : The audio encoding format. - * @param[in] config : Additional type dependent configuration data or nullptr. - * @param[in] gstPlayerFactory : The gstreamer player factory. - * - * @retval true on success. - */ - bool initWebAudioPlayerInternal(const std::string &audioMimeType, std::weak_ptr config, - const std::shared_ptr &gstPlayerFactory); - - /** - * @brief Initalises the GstWebAudioPlayer. - * - * @param[in] audioMimeType : The audio encoding format. - * @param[in] config : Additional type dependent configuration data or nullptr. - * @param[in] gstPlayerFactory : The gstreamer player factory. - * - * @retval true on success. - */ - bool initGstWebAudioPlayer(const std::string &audioMimeType, std::weak_ptr config, - const std::shared_ptr &gstPlayerFactory); - - /** - * @brief Write audio frames internally, only to be called on the main thread. - * - * @param[in] numberOfFrames : Number of frames of audio in the shared memory. - * - * @retval true on success. - */ - bool writeBufferInternal(const uint32_t numberOfFrames); - - /** - * @brief Write the data that has been stored in the shared memory to gstreamer. - * - * Uses the available buffer variable to calculate the data to pass to gstreamer for writting. - * - * @retval true if all stored data was written to gstreamer. - */ - bool writeStoredBuffers(); - - /** - * @brief Update the available buffer variable with the new bytes written to the shared memory and gstreamer. - * - * @param[in] bytesWrittenToShm : Number of bytes newly written to the shared memory. - * @param[in] bytesWrittenToGst : Number of bytes newly written to gstreamer. - */ - void updateAvailableBuffer(uint32_t bytesWrittenToShm, uint32_t bytesWrittenToGst); - - /** - * @brief Handles the timeout of the write data timer. - */ - void handleWriteDataTimer(); - - /** - * @brief Gets the number of queued frames in the shared memory. - * - * @retval The number of frames queued. - */ - uint32_t getQueuedFramesInShm(); -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IAckSender.h b/middleware/rialto-client/media/server/main/interface/IAckSender.h deleted file mode 100644 index ca0754f8c..000000000 --- a/middleware/rialto-client/media/server/main/interface/IAckSender.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_ACK_SENDER_H_ -#define FIREBOLT_RIALTO_SERVER_I_ACK_SENDER_H_ - -namespace firebolt::rialto::server -{ -class IAckSender -{ -public: - virtual ~IAckSender() = default; - virtual void send(int id, bool success) const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_ACK_SENDER_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IControlClientServerInternal.h b/middleware/rialto-client/media/server/main/interface/IControlClientServerInternal.h deleted file mode 100644 index 7f02adcec..000000000 --- a/middleware/rialto-client/media/server/main/interface/IControlClientServerInternal.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_CONTROL_CLIENT_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_I_CONTROL_CLIENT_SERVER_INTERNAL_H_ - -/** - * @file IControlClientServerInternal.h - * - * The definition of the IControlClientServerInternal interface. - * - * This file comprises the definition of the IControlClientServerInternal abstract - * class. This is the API by which a IControl implementation will - * pass notifications to its client. - */ - -#include "IControlClient.h" - -namespace firebolt::rialto::server -{ -/** - * @brief The Rialto control client server internal interface. - * - * This is server internal Rialto control client abstract base class. It should be - * implemented by any object that sends notification about rialto server state to its client - * - */ - -class IControlClientServerInternal : public IControlClient -{ -public: - /** - * @brief Virtual destructor - */ - virtual ~IControlClientServerInternal() = default; - - /** - * @brief Ping notification for checking system health - * The client should perform any health checks then respond with - * a call to ack(id) if system healthy - * - * @param[in] id : Unique id, should be passed to corresponding ack call - */ - virtual void ping(uint32_t id) = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_CONTROL_CLIENT_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IControlServerInternal.h b/middleware/rialto-client/media/server/main/interface/IControlServerInternal.h deleted file mode 100644 index 965f7826c..000000000 --- a/middleware/rialto-client/media/server/main/interface/IControlServerInternal.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_CONTROL_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_I_CONTROL_SERVER_INTERNAL_H_ - -/** - * @file IControlServerInternal.h - * - * The definition of the IControlServerInternal interface. - * - * This interface defines the server internal API of Rialto for controlling rialto clients. - */ - -#include "IControl.h" -#include "IControlClientServerInternal.h" -#include "IHeartbeatHandler.h" -#include - -namespace firebolt::rialto::server -{ -class IControlServerInternal; -class IControlServerInternalFactory : public IControlFactory -{ -public: - IControlServerInternalFactory() = default; - ~IControlServerInternalFactory() override = default; - - /** - * @brief Create a IControlServerInternalFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IControlServerInternal factory method, returns a concrete implementation of IControlServerInternal - * - * @param[in] id : Control id - * @param[in] client : Client object for callbacks - * - * @retval the new IControlServerInternal instance or null on error. - */ - virtual std::shared_ptr - createControlServerInternal(int id, const std::shared_ptr &client) const = 0; -}; - -class IControlServerInternal : public IControl -{ -public: - IControlServerInternal() = default; - virtual ~IControlServerInternal() = default; - - /** - * @brief Informs connected rialto client about rialto server state change - * - * @param[in] state: The new application state. - */ - virtual void setApplicationState(const ApplicationState &state) = 0; - - /** - * @brief Acknowledgement of a received ping request - * - * @param[in] id : id received in ping notification - */ - virtual void ack(int32_t id) = 0; - - /** - * @brief Ping notification for checking system health - * The client should perform any health checks then respond with - * a call to ack(id) if system healthy - * - * @param[in] heartbeatHandler : Handler of current heartbeat request - */ - virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_CONTROL_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IDataReader.h b/middleware/rialto-client/media/server/main/interface/IDataReader.h deleted file mode 100644 index 44666897d..000000000 --- a/middleware/rialto-client/media/server/main/interface/IDataReader.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_DATA_READER_H_ -#define FIREBOLT_RIALTO_SERVER_I_DATA_READER_H_ - -#include "IMediaPipeline.h" - -namespace firebolt::rialto::server -{ -class IDataReader -{ -public: - virtual ~IDataReader() = default; - virtual IMediaPipeline::MediaSegmentVector readData() const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_DATA_READER_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IDecryptionService.h b/middleware/rialto-client/media/server/main/interface/IDecryptionService.h deleted file mode 100644 index 443147b1c..000000000 --- a/middleware/rialto-client/media/server/main/interface/IDecryptionService.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_DECRYPTION_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_I_DECRYPTION_SERVICE_H_ - -#include "MediaCommon.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IDecryptionService -{ -public: - virtual ~IDecryptionService() = default; - virtual MediaKeyErrorStatus decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) = 0; - virtual bool isPlayreadyKeySystem(int32_t keySessionId) = 0; - virtual MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) = 0; - virtual void incrementSessionIdUsageCounter(int32_t keySessionId) = 0; - virtual void decrementSessionIdUsageCounter(int32_t keySessionId) = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_DECRYPTION_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IHeartbeatHandler.h b/middleware/rialto-client/media/server/main/interface/IHeartbeatHandler.h deleted file mode 100644 index 08956f8c4..000000000 --- a/middleware/rialto-client/media/server/main/interface/IHeartbeatHandler.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_HANDLER_H_ -#define FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_HANDLER_H_ - -#include - -/** - * @file IHeartbeatHandler.h - * - * The definition of the IHeartbeatHandler interface. - * - * This interface defines the handler of single ping/ack action. - * - */ - -namespace firebolt::rialto::server -{ -class IHeartbeatHandler -{ -public: - IHeartbeatHandler() = default; - IHeartbeatHandler(const IHeartbeatHandler &) = delete; - IHeartbeatHandler(IHeartbeatHandler &&) = delete; - IHeartbeatHandler &operator=(const IHeartbeatHandler &) = delete; - IHeartbeatHandler &operator=(IHeartbeatHandler &&) = delete; - virtual ~IHeartbeatHandler() = default; - - virtual void error() = 0; - virtual std::int32_t id() const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_HANDLER_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IHeartbeatProcedure.h b/middleware/rialto-client/media/server/main/interface/IHeartbeatProcedure.h deleted file mode 100644 index 967feeaf0..000000000 --- a/middleware/rialto-client/media/server/main/interface/IHeartbeatProcedure.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_PROCEDURE_H_ -#define FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_PROCEDURE_H_ - -/** - * @file IHeartbeatHandler.h - * - * The definition of the IHeartbeatProcedure interface. - * - * This interface defines the ping/ack procedure sent for each client. - * - */ - -#include "IAckSender.h" -#include "IHeartbeatHandler.h" -#include - -namespace firebolt::rialto::server -{ -class IHeartbeatProcedure; -class IHeartbeatProcedureFactory -{ -public: - virtual ~IHeartbeatProcedureFactory() = default; - - static std::unique_ptr createFactory(); - virtual std::shared_ptr createHeartbeatProcedure(const std::shared_ptr &ackSender, - std::int32_t pingId) const = 0; -}; - -class IHeartbeatProcedure -{ -public: - virtual ~IHeartbeatProcedure() = default; - virtual std::unique_ptr createHandler() = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_HEARTBEAT_PROCEDURE_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IMainThread.h b/middleware/rialto-client/media/server/main/interface/IMainThread.h deleted file mode 100644 index 530af2864..000000000 --- a/middleware/rialto-client/media/server/main/interface/IMainThread.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_MAIN_THREAD_H_ -#define FIREBOLT_RIALTO_SERVER_I_MAIN_THREAD_H_ - -#include "IMainThread.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IMainThread; - -/** - * @brief IMainThread factory class, gets the concrete implementation of IMainThread - */ -class IMainThreadFactory -{ -public: - IMainThreadFactory() = default; - virtual ~IMainThreadFactory() = default; - - /** - * @brief Create a IMainThreadFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMainThread factory method, gets a concrete implementation of IMainThread - * - * @retval the main thread instance or null on error. - */ - virtual std::shared_ptr getMainThread() const = 0; -}; - -/** - * @brief The definition of the IMainThread interface. - */ -class IMainThread -{ -public: - using Task = std::function; - - IMainThread() = default; - virtual ~IMainThread() = default; - - IMainThread(const IMainThread &) = delete; - IMainThread(IMainThread &&) = delete; - IMainThread &operator=(const IMainThread &) = delete; - IMainThread &operator=(IMainThread &&) = delete; - - /** - * @brief Register a client on the main thread. - * - * Required by clients who want to enqueue tasks on the main thread. - * - * @retval The registered client id. - */ - virtual int32_t registerClient() = 0; - - /** - * @brief Unregister a client on the main thread. - * - * Should be called on the main thread. - * After been called the client will no longer be able to enqueue tasks. - * - * @param[in] clientId : The id of the registered client. - */ - virtual void unregisterClient(uint32_t clientId) = 0; - - /** - * @brief Enqueue a task on the main thread and return. - * - * @param[in] clientId : The id of the registered client. - * @param[in] task : Task to queue. - */ - virtual void enqueueTask(uint32_t clientId, Task task) = 0; - - /** - * @brief Enqueue a task on the main thread and wait for it to finish before returning. - * - * @param[in] clientId : The id of the registered client. - * @param[in] task : Task to queue. - */ - virtual void enqueueTaskAndWait(uint32_t clientId, Task task) = 0; - - /** - * @brief Enqueue a priority task on the main thread and wait for it to finish before returning. - * - * @param[in] clientId : The id of the registered client. - * @param[in] task : Task to queue. - */ - virtual void enqueuePriorityTaskAndWait(uint32_t clientId, Task task) = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_MAIN_THREAD_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IMediaKeysServerInternal.h b/middleware/rialto-client/media/server/main/interface/IMediaKeysServerInternal.h deleted file mode 100644 index 909c9973a..000000000 --- a/middleware/rialto-client/media/server/main/interface/IMediaKeysServerInternal.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_MEDIA_KEYS_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_I_MEDIA_KEYS_SERVER_INTERNAL_H_ - -/** - * @file IMediaKeysServerInternal.h - * - * The definition of the IMediaKeys interface. - * - * This interface defines the server internal API of Rialto for EME decryption of AV content. - */ - -#include "IHeartbeatHandler.h" -#include "IMediaKeys.h" -#include "MediaCommon.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server -{ -class IMediaKeysServerInternal; -/** - * @brief IMediaKeysServerInternal factory class, returns a concrete implementation of IMediaKeysServerInternal - */ -class IMediaKeysServerInternalFactory : public IMediaKeysFactory -{ -public: - IMediaKeysServerInternalFactory() = default; - ~IMediaKeysServerInternalFactory() override = default; - - /** - * @brief Create a IMediaKeysServerInternalFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMediaKeysServerInternal factory method, returns a concrete implementation of IMediaKeysServerInternal - * - * @param[in] keySystem : The key system for which to create a Media Keys instance - * - * @retval the new media keys instance or null on error. - */ - virtual std::unique_ptr createMediaKeysServerInternal(const std::string &keySystem) const = 0; -}; - -/** - * @brief The definition of the IMediaKeysServerInternal interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content - * which should be implemented by Rialto Server. - */ -class IMediaKeysServerInternal : public IMediaKeys -{ -public: - /** - * @brief Decrypts the buffer. - * - * Encryption metadata shall be attached to the encrypted buffer as protection meta prior to this call. - * - * @param[in] keySessionId : The session id for the session. - * @param[in] encrypted : Gstreamer buffer containing encrypted data and related meta data. If applicable, - * decrypted data will be stored here after this call returns. - * @param[in] caps : The gst caps of buffer. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) = 0; - - /** - * @brief Checks if session with given id is handled by this MediaKeys instance - * - * @param[in] keySessionId : The session id for the session. - * - * @retval true if session is handled by this MediaKeys instance - */ - virtual bool hasSession(int32_t keySessionId) const = 0; - - /** - * @brief Checks, if key system of media key session is Playready. - * - * @param[in] keySessionId : The session id for the session. - * - * @retval true if key system is Playready - */ - virtual bool isPlayreadyKeySystem(int32_t keySessionId) const = 0; - - /** - * @brief Increments number of buffers using keySessionId - * - * @param[in] keySessionId : The session id for the session. - * - */ - - virtual void incrementSessionIdUsageCounter(int32_t keySessionId) = 0; - /** - * @brief Decrements number of buffers using keySessionId - * - * @param[in] keySessionId : The session id for the session. - * - */ - virtual void decrementSessionIdUsageCounter(int32_t keySessionId) = 0; - - /** - * @brief Checks, if MediaKeys main thread is not deadlocked - * - * @param[in] heartbeatHandler : The heartbeat handler instance. - * - */ - virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_MEDIA_KEYS_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IMediaPipelineServerInternal.h b/middleware/rialto-client/media/server/main/interface/IMediaPipelineServerInternal.h deleted file mode 100644 index 71b125d8f..000000000 --- a/middleware/rialto-client/media/server/main/interface/IMediaPipelineServerInternal.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_MEDIA_PIPELINE_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_I_MEDIA_PIPELINE_SERVER_INTERNAL_H_ - -/** - * @file IMediaPipelineServerInternal.h - * - * The definition of the IMediaPipelineServerInternal interface. - * - * This interface defines the server internal APIs for playback of AV content. - */ - -#include - -#include -#include -#include - -#include "IDecryptionService.h" -#include "IHeartbeatHandler.h" -#include "IMediaPipeline.h" -#include "ISharedMemoryBuffer.h" -#include - -namespace firebolt::rialto::server -{ -class IMediaPipelineServerInternal; - -/** - * @brief IMediaPipelineServerInternal factory class, returns a concrete implementation of IMediaPipelineServerInternal - */ -class IMediaPipelineServerInternalFactory : public IMediaPipelineFactory -{ -public: - virtual ~IMediaPipelineServerInternalFactory() = default; - - /** - * @brief Create a IMediaPipelineServerInternalFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMediaPipelineServerInternal factory method, returns a concrete implementation of IMediaPipeline - * - * @param[in] client : The Rialto media player client. - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session - * @param[in] sessionId : The session id for this MediaPipeline. - * @param[in] shmBuffer : The shared buffer object. - * @param[in] decryptionService : The decryption service object. - * - * @retval the new backend instance or null on error. - */ - virtual std::unique_ptr createMediaPipelineServerInternal( - std::weak_ptr client, const VideoRequirements &videoRequirements, int sessionId, - const std::shared_ptr &shmBuffer, IDecryptionService &decryptionService) const = 0; -}; - -/** - * @brief The definition of the IMediaPipelineServerInternal interface. - * - * This interface defines the internal server APIs for playback of AV content which - * should be implemented by Rialto Server only. - */ -class IMediaPipelineServerInternal : public IMediaPipeline -{ -public: - /** - * @brief Returns data requested using notifyNeedMediaData(). - * - * This is a server only implementation. The data from the client has already been - * writen to the shared memory. - * - * A successful notifyNeedMediaData() request will return at least one frame - * of data but may return less than originally requested. - * - * @param[in] status : The status - * @param[in] numFrames : The number of frames written. - * @param[in] needDataRequestId : Need data request id - */ - virtual bool haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId) = 0; - - /** - * @brief Checks if MediaPipeline threads are not deadlocked - * - * @param[out] heartbeatHandler : The heartbeat handler instance - */ - virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; -}; - -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_MEDIA_PIPELINE_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/interface/ISharedMemoryBuffer.h b/middleware/rialto-client/media/server/main/interface/ISharedMemoryBuffer.h deleted file mode 100644 index fac404126..000000000 --- a/middleware/rialto-client/media/server/main/interface/ISharedMemoryBuffer.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_SHARED_MEMORY_BUFFER_H_ -#define FIREBOLT_RIALTO_SERVER_I_SHARED_MEMORY_BUFFER_H_ - -#include -#include - -#include "MediaCommon.h" - -namespace firebolt::rialto::server -{ -class ISharedMemoryBuffer; -class ISharedMemoryBufferFactory -{ -public: - ISharedMemoryBufferFactory() = default; - virtual ~ISharedMemoryBufferFactory() = default; - - static std::unique_ptr createFactory(); - virtual std::shared_ptr createSharedMemoryBuffer(unsigned numOfPlaybacks, - unsigned numOfWebAudioPlayers) const = 0; -}; - -class ISharedMemoryBuffer -{ -public: - ISharedMemoryBuffer() = default; - virtual ~ISharedMemoryBuffer() = default; - - ISharedMemoryBuffer(const ISharedMemoryBuffer &) = delete; - ISharedMemoryBuffer(ISharedMemoryBuffer &&) = delete; - ISharedMemoryBuffer &operator=(const ISharedMemoryBuffer &) = delete; - ISharedMemoryBuffer &operator=(ISharedMemoryBuffer &&) = delete; - - /** - * @brief The type of media playback. - */ - enum class MediaPlaybackType - { - GENERIC, - WEB_AUDIO - }; - - /** - * @brief Maps the partition for playback. - * - * @param[in] playbackType : The type of playback partition. - * @param[in] id : The id for the partition of playbackType. - * - * @retval true on success. - */ - virtual bool mapPartition(MediaPlaybackType playbackType, int id) = 0; - - /** - * @brief Unmaps the partition for playback. - * - * @param[in] playbackType : The type of playback partition. - * @param[in] id : The id for the partition of playbackType. - * - * @retval true on success. - */ - virtual bool unmapPartition(MediaPlaybackType playbackType, int id) = 0; - - /** - * @brief Clears the data in the specified partition. - * - * @param[in] playbackType : The type of playback partition. - * @param[in] id : The id for the partition of playbackType. - * @param[in] mediaSourceType : The type of media source partition. - * - * @retval true on success. - */ - virtual bool clearData(MediaPlaybackType playbackType, int id, const MediaSourceType &mediaSourceType) const = 0; - - /** - * @brief Gets the offset of the specified data partition. - * - * @param[in] playbackType : The type of playback partition. - * @param[in] id : The id for the partition of playbackType. - * @param[in] mediaSourceType : The type of media source partition. - * - * @retval true on success. - */ - virtual std::uint32_t getDataOffset(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const = 0; - - /** - * @brief Gets the maximum length of the specified data partition. - * - * @param[in] playbackType : The type of playback partition. - * @param[in] id : The id for the partition of playbackType. - * @param[in] mediaSourceType : The type of media source partition. - * - * @retval true on success. - */ - virtual std::uint32_t getMaxDataLen(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const = 0; - - /** - * @brief Gets the pointer to the start of the specified data partition. - * - * @param[in] playbackType : The type of playback partition. - * @param[in] id : The id for the partition of playbackType. - * @param[in] mediaSourceType : The type of media source partition. - * - * @retval true on success. - */ - virtual std::uint8_t *getDataPtr(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const = 0; - - /** - * @brief Gets file descriptor of the shared memory. - * - * @retval > -1 on success. - */ - virtual int getFd() const = 0; - - /** - * @brief Gets the allocated size of the shared memory. - * - * @retval > 0 on success. - */ - virtual std::uint32_t getSize() const = 0; - - /** - * @brief Gets the pointer to the shared memory. - * - * @retval None null ptr value on success. - */ - virtual std::uint8_t *getBuffer() const = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_SHARED_MEMORY_BUFFER_H_ diff --git a/middleware/rialto-client/media/server/main/interface/ITextTrackSession.h b/middleware/rialto-client/media/server/main/interface/ITextTrackSession.h deleted file mode 100644 index fe156f811..000000000 --- a/middleware/rialto-client/media/server/main/interface/ITextTrackSession.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_SESSION_H_ -#define FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_SESSION_H_ - -#include -#include - -namespace firebolt::rialto::server -{ -class ITextTrackSession; - -class ITextTrackSessionFactory -{ -public: - virtual ~ITextTrackSessionFactory() = default; - static ITextTrackSessionFactory &getFactory(); - virtual std::unique_ptr createTextTrackSession(const std::string &display) const = 0; -}; - -class ITextTrackSession -{ -public: - ITextTrackSession() = default; - virtual ~ITextTrackSession() = default; - - virtual bool resetSession(bool isMuted) = 0; - virtual bool pause() = 0; - virtual bool play() = 0; - virtual bool mute(bool mute) = 0; - virtual bool setPosition(uint64_t mediaTimestampMs) = 0; - virtual bool sendData(const std::string &data, int64_t displayOffsetMs = 0) = 0; - virtual bool setSessionWebVTTSelection() = 0; - virtual bool setSessionTTMLSelection() = 0; - virtual bool setSessionCCSelection(const std::string &service) = 0; - virtual bool associateVideoDecoder(uint64_t decoderId) = 0; - virtual bool isClosedCaptions() const = 0; -}; -} // namespace firebolt::rialto::server -#endif // FIREBOLT_RIALTO_SERVER_I_TEXT_TRACK_SESSION_H_ diff --git a/middleware/rialto-client/media/server/main/interface/IWebAudioPlayerServerInternal.h b/middleware/rialto-client/media/server/main/interface/IWebAudioPlayerServerInternal.h deleted file mode 100644 index c604ebce6..000000000 --- a/middleware/rialto-client/media/server/main/interface/IWebAudioPlayerServerInternal.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ -#define FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ - -/** - * @file IWebAudioPlayerServerInternal.h - * - * The definition of the IWebAudioPlayerServerInternal interface. - * - * This interface defines the server internal APIs for playback of AV content. - */ - -#include - -#include -#include -#include - -#include "IDecryptionService.h" -#include "IGstWebAudioPlayer.h" -#include "IHeartbeatHandler.h" -#include "IMainThread.h" -#include "ISharedMemoryBuffer.h" -#include "ITimer.h" -#include "IWebAudioPlayer.h" -#include "MediaCommon.h" - -namespace firebolt::rialto::server -{ -class IWebAudioPlayerServerInternal; -/** - * @brief IWebAudioPlayer factory class, returns a concrete implementation of IWebAudioPlayer for internal server use - */ -class IWebAudioPlayerServerInternalFactory : public IWebAudioPlayerFactory -{ -public: - virtual ~IWebAudioPlayerServerInternalFactory() = default; - - /** - * @brief Create a IWebAudioPlayerServerInternalFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IWebAudioPlayerServerInternalFactory method, returns a concrete implementation of IWebAudioPlayer for - * internal server use - * - * @param[in] client : The Web Audio Player client - * @param[in] audioMimeType : The audio encoding format, currently only "audio/x-raw" (PCM) - * @param[in] priority : Priority value for this pipeline. - * @param[in] config : Additional type dependent configuration data or nullptr - * @param[in] shmBuffer : The shared buffer object. - * @param[in] handle : The handle for this WebAudioPlayer. - * - * @retval the new backend instance or null on error. - */ - virtual std::unique_ptr createWebAudioPlayerServerInternal( - std::weak_ptr client, const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config, const std::shared_ptr &shmBuffer, int handle, - const std::shared_ptr &mainThreadFactory, - const std::shared_ptr &gstPlayerFactory, - std::weak_ptr timerFactory) const = 0; -}; - -/** - * @brief The definition of the IWebAudioPlayerServerInternal interface. - * - * This interface defines the public API of Rialto for mixing PCM audio with - * current audio output. It should be implemented by both Rialto Client & - * Rialto Server. - */ -class IWebAudioPlayerServerInternal : public IWebAudioPlayer -{ -public: - /** - * @brief Checks if WebAudioPlayer threads are not deadlocked - * - * @param[out] heartbeatHandler : The heartbeat handler instance - */ - virtual void ping(std::unique_ptr &&heartbeatHandler) = 0; -}; -}; // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_WEB_AUDIO_PLAYER_SERVER_INTERNAL_H_ diff --git a/middleware/rialto-client/media/server/main/proto/metadata.proto b/middleware/rialto-client/media/server/main/proto/metadata.proto deleted file mode 120000 index 31c2471b2..000000000 --- a/middleware/rialto-client/media/server/main/proto/metadata.proto +++ /dev/null @@ -1 +0,0 @@ -../../../../proto/metadata.proto \ No newline at end of file diff --git a/middleware/rialto-client/media/server/main/source/ActiveRequests.cpp b/middleware/rialto-client/media/server/main/source/ActiveRequests.cpp deleted file mode 100644 index b91cfa67b..000000000 --- a/middleware/rialto-client/media/server/main/source/ActiveRequests.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ActiveRequests.h" -#include -#include - -namespace firebolt::rialto::server -{ -ActiveRequests::ActiveRequestsData::~ActiveRequestsData() -{ - for (std::unique_ptr &segment : m_segments) - { - delete[] segment->getData(); - } -} - -AddSegmentStatus ActiveRequests::ActiveRequestsData::addSegment(const std::unique_ptr &segment) -{ - if (m_bytesWritten + segment->getDataLength() > m_maxMediaBytes) - return AddSegmentStatus::NO_SPACE; - - std::unique_ptr copiedSegment = segment->copy(); - - uint8_t *data = new uint8_t[segment->getDataLength()]; - std::memcpy(data, segment->getData(), segment->getDataLength()); - - copiedSegment->setData(segment->getDataLength(), data); - m_segments.push_back(std::move(copiedSegment)); - - m_bytesWritten += segment->getDataLength(); - return AddSegmentStatus::OK; -} - -ActiveRequests::ActiveRequests() : m_currentId{0} {} - -std::uint32_t ActiveRequests::insert(const MediaSourceType &mediaSourceType, std::uint32_t maxMediaBytes) -{ - std::unique_lock lock{m_mutex}; - m_requestMap.insert(std::make_pair(m_currentId, ActiveRequestsData(mediaSourceType, maxMediaBytes))); - return m_currentId++; -} - -MediaSourceType ActiveRequests::getType(std::uint32_t requestId) const -{ - std::unique_lock lock{m_mutex}; - auto requestIter{m_requestMap.find(requestId)}; - if (requestIter != m_requestMap.end()) - { - return requestIter->second.getType(); - } - return MediaSourceType::UNKNOWN; -} - -void ActiveRequests::erase(std::uint32_t requestId) -{ - std::unique_lock lock{m_mutex}; - m_requestMap.erase(requestId); -} - -void ActiveRequests::erase(const MediaSourceType &mediaSourceType) -{ - std::unique_lock lock{m_mutex}; - for (auto it = m_requestMap.begin(); it != m_requestMap.end();) - { - if (it->second.getType() == mediaSourceType) - { - it = m_requestMap.erase(it); - } - else - { - ++it; - } - } -} - -void ActiveRequests::clear() -{ - std::unique_lock lock{m_mutex}; - m_requestMap.clear(); -} - -AddSegmentStatus ActiveRequests::addSegment(std::uint32_t requestId, - const std::unique_ptr &segment) -{ - if (nullptr == segment || nullptr == segment->getData()) - { - return AddSegmentStatus::ERROR; - } - - auto requestIter{m_requestMap.find(requestId)}; - if (requestIter != m_requestMap.end()) - { - return requestIter->second.addSegment(segment); - } - - return AddSegmentStatus::ERROR; -} - -const IMediaPipeline::MediaSegmentVector &ActiveRequests::getSegments(std::uint32_t requestId) const -{ - auto requestIter{m_requestMap.find(requestId)}; - if (requestIter != m_requestMap.end()) - { - return requestIter->second.getSegments(); - } - - throw std::runtime_error("No segments for request id " + std::to_string(requestId)); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/ControlServerInternal.cpp b/middleware/rialto-client/media/server/main/source/ControlServerInternal.cpp deleted file mode 100644 index 2c746fd6f..000000000 --- a/middleware/rialto-client/media/server/main/source/ControlServerInternal.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ControlServerInternal.h" -#include "RialtoServerLogging.h" -#include - -namespace -{ -const char *convertApplicationState(const firebolt::rialto::ApplicationState &appState) -{ - switch (appState) - { - case firebolt::rialto::ApplicationState::UNKNOWN: - return "UNKNOWN"; - case firebolt::rialto::ApplicationState::RUNNING: - return "RUNNING"; - case firebolt::rialto::ApplicationState::INACTIVE: - return "INACTIVE"; - } - return "UNKNOWN"; -} -} // namespace - -namespace firebolt::rialto -{ -std::shared_ptr IControlFactory::createFactory() -{ - return server::IControlServerInternalFactory::createFactory(); -} -} // namespace firebolt::rialto - -namespace firebolt::rialto::server -{ -std::shared_ptr IControlServerInternalFactory::createFactory() -try -{ - return std::make_shared(); -} -catch (std::exception &e) -{ - RIALTO_SERVER_LOG_ERROR("ControlServerInternalFactory creation failed"); - return nullptr; -} - -std::shared_ptr ControlServerInternalFactory::createControl() const -{ - RIALTO_SERVER_LOG_ERROR("This function can't be used by rialto server. Please use createControlServerInternal"); - return nullptr; -} - -std::shared_ptr ControlServerInternalFactory::createControlServerInternal( - int id, const std::shared_ptr &client) const -try -{ - return std::make_shared(server::IMainThreadFactory::createFactory(), id, client); -} -catch (const std::exception &e) -{ - RIALTO_SERVER_LOG_ERROR("ControlServerInternal creation failed"); - return nullptr; -} - -ControlServerInternal::ControlServerInternal(const std::shared_ptr &mainThreadFactory, int id, - const std::shared_ptr &client) - : m_controlId{id}, m_client{client}, m_currentState{ApplicationState::UNKNOWN} -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - m_mainThread = mainThreadFactory->getMainThread(); - if (!m_mainThread) - { - throw std::runtime_error("Failed to get the main thread"); - } - m_mainThreadClientId = m_mainThread->registerClient(); -} - -ControlServerInternal::~ControlServerInternal() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - m_mainThread->unregisterClient(m_mainThreadClientId); -} - -void ControlServerInternal::ack(int32_t ackId) -{ - RIALTO_SERVER_LOG_DEBUG("Control with id: %d received ack for ping: %d", m_controlId, ackId); - auto task = [&]() - { - if (!m_heartbeatHandler) - { - RIALTO_SERVER_LOG_WARN("No heartbeatHandler present for control with id: %d", m_controlId); - return; - } - if (m_heartbeatHandler->id() != ackId) - { - RIALTO_SERVER_LOG_WARN("Control with id: %d received ack with wrong id: %d", m_controlId, ackId); - return; - } - m_heartbeatHandler.reset(); - }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -void ControlServerInternal::setApplicationState(const ApplicationState &state) -{ - RIALTO_SERVER_LOG_MIL("Notify rialto client about state changed to: %s", convertApplicationState(state)); - auto task = [&]() - { - m_currentState = state; - if (m_client) - m_client->notifyApplicationState(state); - }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -void ControlServerInternal::ping(std::unique_ptr &&heartbeatHandler) -{ - RIALTO_SERVER_LOG_DEBUG("Control with id: %d will send ping with id: %d", m_controlId, heartbeatHandler->id()); - auto task = [&]() - { - if (m_currentState != ApplicationState::RUNNING) - { - RIALTO_SERVER_LOG_DEBUG("Control with id: %d in INACTIVE state. Ack immediately for ping with id: %d", - m_controlId, heartbeatHandler->id()); - m_heartbeatHandler.reset(); - heartbeatHandler.reset(); - return; - } - if (m_heartbeatHandler) - { - m_heartbeatHandler->error(); - m_heartbeatHandler.reset(); - } - if (m_client) - { - m_client->ping(heartbeatHandler->id()); - m_heartbeatHandler = std::move(heartbeatHandler); - } - }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -bool ControlServerInternal::registerClient(std::weak_ptr client, ApplicationState &appState) -{ - RIALTO_SERVER_LOG_ERROR("Method not implemented"); - return false; -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/DataReaderFactory.cpp b/middleware/rialto-client/media/server/main/source/DataReaderFactory.cpp deleted file mode 100644 index 079fe0b6d..000000000 --- a/middleware/rialto-client/media/server/main/source/DataReaderFactory.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "DataReaderFactory.h" -#include "DataReaderV1.h" -#include "DataReaderV2.h" -#include "ShmCommon.h" -#include "ShmUtils.h" - -namespace -{ -uint32_t readLEUint32(const uint8_t *buffer) -{ - uint32_t value = buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0]; - return value; -} -} // namespace - -namespace firebolt::rialto::server -{ -std::shared_ptr DataReaderFactory::createDataReader(const MediaSourceType &mediaSourceType, - std::uint8_t *buffer, std::uint32_t dataOffset, - std::uint32_t numFrames) const -{ - // Version is always first 4 bytes of data - std::uint8_t *metadata = buffer + dataOffset; - std::uint32_t version = readLEUint32(metadata); - if (1 == version) - { - std::uint32_t metadataOffsetWithoutVersion = dataOffset + common::VERSION_SIZE_BYTES; - return std::make_shared(mediaSourceType, buffer, metadataOffsetWithoutVersion, numFrames); - } - if (2 == version) - { - std::uint32_t v2DataOffset = dataOffset + getMaxMetadataBytes(); - return std::make_shared(mediaSourceType, buffer, v2DataOffset, numFrames); - } - return nullptr; -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/DataReaderV1.cpp b/middleware/rialto-client/media/server/main/source/DataReaderV1.cpp deleted file mode 100644 index 9e61080ed..000000000 --- a/middleware/rialto-client/media/server/main/source/DataReaderV1.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "DataReaderV1.h" -#include "RialtoServerLogging.h" -#include "ShmCommon.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server -{ -DataReaderV1::DataReaderV1(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t metadataOffset, - std::uint32_t numFrames) - : m_mediaSourceType{mediaSourceType}, m_buffer{buffer}, m_metadataOffset{metadataOffset}, m_numFrames{numFrames} -{ - RIALTO_SERVER_LOG_DEBUG("Detected Metadata in Version 1. Media source type: %s", - common::convertMediaSourceType(m_mediaSourceType)); - static_assert(sizeof(DataReaderV1::MetadataV1) == common::METADATA_V1_SIZE_PER_FRAME_BYTES, - "Size of firebolt::rialto::server::DataReaderV1::MetadataV1 is not equal to " - "firebolt::rialto::common::METADATA_V1_SIZE_PER_FRAME_BYTES"); -} - -IMediaPipeline::MediaSegmentVector DataReaderV1::readData() const -{ - IMediaPipeline::MediaSegmentVector mediaSegments; - auto metadatas = readMetadata(); - for (const auto &metadata : metadatas) - { - if (m_mediaSourceType == MediaSourceType::AUDIO) - { - mediaSegments.emplace_back(createSegment(metadata)); - } - else if (m_mediaSourceType == MediaSourceType::VIDEO) - { - mediaSegments.emplace_back(createSegment(metadata)); - } - } - return mediaSegments; -} - -std::vector DataReaderV1::readMetadata() const -{ - std::vector result; - std::uint8_t *regionMetadataOffset = m_buffer + m_metadataOffset; - for (std::uint32_t frame = 0; frame < m_numFrames; ++frame) - { - std::uint8_t *frameMetadataOffset = regionMetadataOffset + (frame * common::METADATA_V1_SIZE_PER_FRAME_BYTES); - DataReaderV1::MetadataV1 *metadataPtr = reinterpret_cast(frameMetadataOffset); - result.emplace_back(*metadataPtr); - } - return result; -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/DataReaderV2.cpp b/middleware/rialto-client/media/server/main/source/DataReaderV2.cpp deleted file mode 100644 index eab51c355..000000000 --- a/middleware/rialto-client/media/server/main/source/DataReaderV2.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "DataReaderV2.h" -#include "RialtoServerLogging.h" -#include "ShmCommon.h" -#include "TypeConverters.h" -#include "metadata.pb.h" - -namespace -{ -firebolt::rialto::SegmentAlignment -convertSegmentAlignment(const firebolt::rialto::MediaSegmentMetadata_SegmentAlignment &segmentAlignment) -{ - switch (segmentAlignment) - { - case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_UNDEFINED: - { - return firebolt::rialto::SegmentAlignment::UNDEFINED; - } - case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_NAL: - { - return firebolt::rialto::SegmentAlignment::NAL; - } - case firebolt::rialto::MediaSegmentMetadata_SegmentAlignment_ALIGNMENT_AU: - { - return firebolt::rialto::SegmentAlignment::AU; - } - } - return firebolt::rialto::SegmentAlignment::UNDEFINED; -} - -firebolt::rialto::CipherMode convertCipherMode(const firebolt::rialto::MediaSegmentMetadata_CipherMode &cipherMode) -{ - switch (cipherMode) - { - case firebolt::rialto::MediaSegmentMetadata_CipherMode_UNKNOWN: - { - return firebolt::rialto::CipherMode::UNKNOWN; - } - case firebolt::rialto::MediaSegmentMetadata_CipherMode_CENC: - { - return firebolt::rialto::CipherMode::CENC; - } - case firebolt::rialto::MediaSegmentMetadata_CipherMode_CBC1: - { - return firebolt::rialto::CipherMode::CBC1; - } - case firebolt::rialto::MediaSegmentMetadata_CipherMode_CENS: - { - return firebolt::rialto::CipherMode::CENS; - } - case firebolt::rialto::MediaSegmentMetadata_CipherMode_CBCS: - { - return firebolt::rialto::CipherMode::CBCS; - } - } - return firebolt::rialto::CipherMode::UNKNOWN; -} - -firebolt::rialto::CodecDataType convertCodecDataType(const firebolt::rialto::MediaSegmentMetadata_CodecData_Type &type) -{ - if (firebolt::rialto::MediaSegmentMetadata_CodecData_Type_STRING == type) - { - return firebolt::rialto::CodecDataType::STRING; - } - return firebolt::rialto::CodecDataType::BUFFER; -} - -std::unique_ptr -createSegment(const firebolt::rialto::MediaSegmentMetadata &metadata, const firebolt::rialto::MediaSourceType &type) -{ - // Create segment - std::unique_ptr segment; - if (type == firebolt::rialto::MediaSourceType::AUDIO) - { - if (!metadata.has_sample_rate() || !metadata.has_channels_num()) - { - RIALTO_SERVER_LOG_ERROR("SampleRate/ChannelsNum not present in audio metadata"); - return nullptr; - } - segment = std::make_unique(metadata.stream_id(), - metadata.time_position(), - metadata.sample_duration(), - metadata.sample_rate(), - metadata.channels_num(), - metadata.clipping_start(), - metadata.clipping_end()); - } - else if (type == firebolt::rialto::MediaSourceType::VIDEO) - { - if (!metadata.has_width() || !metadata.has_height()) - { - RIALTO_SERVER_LOG_ERROR("Width/height not present in video metadata"); - return nullptr; - } - - firebolt::rialto::Fraction frameRate{firebolt::rialto::kUndefinedSize, firebolt::rialto::kUndefinedSize}; - if (metadata.has_frame_rate()) - { - frameRate = {metadata.frame_rate().numerator(), metadata.frame_rate().denominator()}; - } - segment = std::make_unique(metadata.stream_id(), - metadata.time_position(), - metadata.sample_duration(), - metadata.width(), - metadata.height(), frameRate); - } - else if (type == firebolt::rialto::MediaSourceType::SUBTITLE) - { - segment = - std::make_unique(metadata.stream_id(), - firebolt::rialto::MediaSourceType::SUBTITLE, - metadata.time_position(), - metadata.sample_duration()); - } - else - { - RIALTO_SERVER_LOG_ERROR("Unknown segment type"); - return nullptr; - } - - // Read optional data - if (metadata.has_segment_alignment()) - { - segment->setSegmentAlignment(convertSegmentAlignment(metadata.segment_alignment())); - } - if (metadata.has_extra_data()) - { - segment->setExtraData(std::vector(metadata.extra_data().begin(), metadata.extra_data().end())); - } - if (metadata.has_codec_data()) - { - auto codecData = std::make_shared(); - codecData->type = convertCodecDataType(metadata.codec_data().type()); - codecData->data = std::vector(metadata.codec_data().data().begin(), metadata.codec_data().data().end()); - segment->setCodecData(codecData); - } - - // Read encryption data - if (metadata.has_media_key_session_id() || metadata.has_key_id() || metadata.has_init_vector() || - metadata.has_init_with_last_15()) - { - segment->setEncrypted(true); - } - else - { - segment->setEncrypted(false); - } - if (metadata.has_media_key_session_id()) - { - segment->setMediaKeySessionId(metadata.media_key_session_id()); - } - if (metadata.has_key_id()) - { - segment->setKeyId(std::vector(metadata.key_id().begin(), metadata.key_id().end())); - } - if (metadata.has_init_vector()) - { - segment->setInitVector(std::vector(metadata.init_vector().begin(), metadata.init_vector().end())); - } - if (metadata.has_init_with_last_15()) - { - segment->setInitWithLast15(metadata.init_with_last_15()); - } - if (metadata.has_cipher_mode()) - { - segment->setCipherMode(convertCipherMode(metadata.cipher_mode())); - } - if (metadata.has_crypt() && metadata.has_skip()) - { - segment->setEncryptionPattern(metadata.crypt(), metadata.skip()); - } - if (metadata.has_display_offset()) - { - segment->setDisplayOffset(metadata.display_offset()); - } - - for (const auto &info : metadata.sub_sample_info()) - { - segment->addSubSample(info.num_clear_bytes(), info.num_encrypted_bytes()); - } - return segment; -} -} // namespace - -namespace firebolt::rialto::server -{ -DataReaderV2::DataReaderV2(const MediaSourceType &mediaSourceType, std::uint8_t *buffer, std::uint32_t dataOffset, - std::uint32_t numFrames) - : m_mediaSourceType{mediaSourceType}, m_buffer{buffer}, m_dataOffset{dataOffset}, m_numFrames{numFrames} -{ - RIALTO_SERVER_LOG_DEBUG("Detected Metadata in Version 2. Media source type: %s", - common::convertMediaSourceType(m_mediaSourceType)); -} - -IMediaPipeline::MediaSegmentVector DataReaderV2::readData() const -{ - IMediaPipeline::MediaSegmentVector mediaSegments; - uint8_t *currentReadPosition{m_buffer + m_dataOffset}; - for (auto i = 0U; i < m_numFrames; ++i) - { - std::uint32_t *metadataSize{reinterpret_cast(currentReadPosition)}; - currentReadPosition += sizeof(uint32_t); - MediaSegmentMetadata metadata; - if (!metadata.ParseFromArray(currentReadPosition, *metadataSize)) - { - RIALTO_SERVER_LOG_ERROR("Metadata parsing failed!"); - return IMediaPipeline::MediaSegmentVector{}; - } - auto newSegment{createSegment(metadata, m_mediaSourceType)}; - if (!newSegment) - { - RIALTO_SERVER_LOG_ERROR("Segment parsing failed!"); - return IMediaPipeline::MediaSegmentVector{}; - } - currentReadPosition += *metadataSize; - newSegment->setData(metadata.length(), currentReadPosition); - currentReadPosition += metadata.length(); - mediaSegments.emplace_back(std::move(newSegment)); - } - return mediaSegments; -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/HeartbeatProcedure.cpp b/middleware/rialto-client/media/server/main/source/HeartbeatProcedure.cpp deleted file mode 100644 index d3955571c..000000000 --- a/middleware/rialto-client/media/server/main/source/HeartbeatProcedure.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "HeartbeatProcedure.h" - -namespace firebolt::rialto::server -{ -std::unique_ptr IHeartbeatProcedureFactory::createFactory() -{ - return std::make_unique(); -} - -std::shared_ptr -HeartbeatProcedureFactory::createHeartbeatProcedure(const std::shared_ptr &ackSender, std::int32_t pingId) const -{ - return std::make_shared(ackSender, pingId); -} - -HeartbeatProcedure::HeartbeatHandler::HeartbeatHandler(const std::shared_ptr &procedure, - std::int32_t pingId) - : m_procedure{procedure}, m_kPingId{pingId}, m_success{true} -{ -} - -HeartbeatProcedure::HeartbeatHandler::~HeartbeatHandler() -{ - m_procedure->onFinish(m_success); -} - -void HeartbeatProcedure::HeartbeatHandler::error() -{ - m_success = false; -} - -std::int32_t HeartbeatProcedure::HeartbeatHandler::id() const -{ - return m_kPingId; -} - -HeartbeatProcedure::HeartbeatProcedure(const std::shared_ptr &ackSender, std::int32_t pingId) - : m_ackSender{ackSender}, m_kPingId{pingId}, m_success{true} -{ -} - -HeartbeatProcedure::~HeartbeatProcedure() -{ - m_ackSender->send(m_kPingId, m_success); -} - -std::unique_ptr HeartbeatProcedure::createHandler() -{ - return std::make_unique(shared_from_this(), m_kPingId); -} - -void HeartbeatProcedure::onFinish(bool success) -{ - if (!success) - { - m_success = false; - } -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MainThread.cpp b/middleware/rialto-client/media/server/main/source/MainThread.cpp deleted file mode 100644 index 83c2a3755..000000000 --- a/middleware/rialto-client/media/server/main/source/MainThread.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MainThread.h" -#include "RialtoServerLogging.h" -#include -#include -#include - -namespace firebolt::rialto::server -{ -std::weak_ptr MainThreadFactory::m_mainThread; -std::mutex MainThreadFactory::m_creationMutex; - -std::shared_ptr IMainThreadFactory::createFactory() -{ - std::shared_ptr factory; - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the main thread factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr MainThreadFactory::getMainThread() const -{ - std::lock_guard lock{m_creationMutex}; - - std::shared_ptr mainThread = m_mainThread.lock(); - if (!mainThread) - { - try - { - mainThread = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the main thread, reason: %s", e.what()); - } - - m_mainThread = mainThread; - } - - return mainThread; -} - -MainThread::MainThread() : m_isMainThreadRunning{true}, m_mainThreadClientId{0}, m_nextClientId{1} -{ - RIALTO_SERVER_LOG_DEBUG("MainThread is constructed"); - m_thread = std::thread(std::bind(&MainThread::mainThreadLoop, this)); - - // Register itself - m_registeredClients.insert(m_mainThreadClientId); -} - -MainThread::~MainThread() -{ - RIALTO_SERVER_LOG_DEBUG("MainThread is destructed"); - auto shutdownTask = [this]() { m_isMainThreadRunning = false; }; - enqueueTask(m_mainThreadClientId, shutdownTask); - m_thread.join(); -} - -void MainThread::mainThreadLoop() -{ - while (m_isMainThreadRunning) - { - const std::shared_ptr kTaskInfo = waitForTask(); - if (m_registeredClients.find(kTaskInfo->clientId) != m_registeredClients.end()) - { - kTaskInfo->task(); - } - else - { - RIALTO_SERVER_LOG_WARN("Task ignored, client '%d' not registered", kTaskInfo->clientId); - } - - if (nullptr != kTaskInfo->cv) - { - std::unique_lock lockTask(*(kTaskInfo->mutex)); - kTaskInfo->cv->notify_one(); - } - } -} - -const std::shared_ptr MainThread::waitForTask() -{ - std::unique_lock lock(m_taskQueueMutex); - if (m_taskQueue.empty()) - { - m_taskQueueCv.wait(lock, [this] { return !m_taskQueue.empty(); }); - } - const std::shared_ptr kTaskInfo = m_taskQueue.front(); - m_taskQueue.pop_front(); - return kTaskInfo; -} - -int32_t MainThread::registerClient() -{ - uint32_t clientId = m_nextClientId++; - - auto task = [&, clientId]() - { - RIALTO_SERVER_LOG_INFO("Registering client '%u'", clientId); - m_registeredClients.insert(clientId); - }; - enqueueTask(m_mainThreadClientId, task); - - return clientId; -} - -void MainThread::unregisterClient(uint32_t clientId) -{ - RIALTO_SERVER_LOG_INFO("Unregistering client '%u'", clientId); - m_registeredClients.erase(clientId); -} - -void MainThread::enqueueTask(uint32_t clientId, Task task) -{ - std::shared_ptr newTask = std::make_shared(); - newTask->clientId = clientId; - newTask->task = task; - { - std::unique_lock lock(m_taskQueueMutex); - m_taskQueue.push_back(newTask); - } - m_taskQueueCv.notify_one(); -} - -void MainThread::enqueueTaskAndWait(uint32_t clientId, Task task) -{ - std::shared_ptr newTask = std::make_shared(); - newTask->clientId = clientId; - newTask->task = task; - newTask->mutex = std::make_unique(); - newTask->cv = std::make_unique(); - - { - std::unique_lock lockTask(*(newTask->mutex)); - { - std::unique_lock lockQueue(m_taskQueueMutex); - m_taskQueue.push_back(newTask); - } - m_taskQueueCv.notify_one(); - - newTask->cv->wait(lockTask); - } -} - -void MainThread::enqueuePriorityTaskAndWait(uint32_t clientId, Task task) -{ - std::shared_ptr newTask = std::make_shared(); - newTask->clientId = clientId; - newTask->task = task; - newTask->mutex = std::make_unique(); - newTask->cv = std::make_unique(); - - { - std::unique_lock lockTask(*(newTask->mutex)); - { - std::unique_lock lockQueue(m_taskQueueMutex); - m_taskQueue.push_front(newTask); - } - m_taskQueueCv.notify_one(); - - newTask->cv->wait(lockTask); - } -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaKeySession.cpp b/middleware/rialto-client/media/server/main/source/MediaKeySession.cpp deleted file mode 100644 index e57468e6c..000000000 --- a/middleware/rialto-client/media/server/main/source/MediaKeySession.cpp +++ /dev/null @@ -1,489 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "MediaKeySession.h" -#include "MediaKeysCommon.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server -{ -std::shared_ptr IMediaKeySessionFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media key session factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr MediaKeySessionFactory::createMediaKeySession( - const std::string &keySystem, int32_t keySessionId, const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, - KeySessionType sessionType, std::weak_ptr client, bool isLDL) const -{ - std::unique_ptr mediaKeys; - try - { - mediaKeys = std::make_unique(keySystem, keySessionId, ocdmSystem, sessionType, client, - isLDL, server::IMainThreadFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media key session, reason: %s", e.what()); - } - - return mediaKeys; -} - -MediaKeySession::MediaKeySession(const std::string &keySystem, int32_t keySessionId, - const firebolt::rialto::wrappers::IOcdmSystem &ocdmSystem, KeySessionType sessionType, - std::weak_ptr client, bool isLDL, - const std::shared_ptr &mainThreadFactory) - : m_kKeySystem(keySystem), m_kKeySessionId(keySessionId), m_kSessionType(sessionType), m_mediaKeysClient(client), - m_kIsLDL(isLDL), m_isSessionConstructed(false), m_isSessionClosed(false), m_licenseRequested(false), - m_ongoingOcdmOperation(false), m_ocdmError(false) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - m_mainThread = mainThreadFactory->getMainThread(); - if (!m_mainThread) - { - throw std::runtime_error("Failed to get the main thread"); - } - m_mainThreadClientId = m_mainThread->registerClient(); - - m_ocdmSession = ocdmSystem.createSession(this); - if (!m_ocdmSession) - { - throw std::runtime_error("Ocdm session could not be created"); - } - RIALTO_SERVER_LOG_MIL("New OCDM session created"); -} - -MediaKeySession::~MediaKeySession() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (m_isSessionConstructed) - { - if (!m_isSessionClosed) - { - if (MediaKeyErrorStatus::OK != closeKeySession()) - { - RIALTO_SERVER_LOG_ERROR("Failed to close the key session"); - } - } - if (MediaKeyErrorStatus::OK != m_ocdmSession->destructSession()) - { - RIALTO_SERVER_LOG_ERROR("Failed to destruct the key session"); - } - } - - m_mainThread->unregisterClient(m_mainThreadClientId); -} - -MediaKeyErrorStatus MediaKeySession::generateRequest(InitDataType initDataType, const std::vector &initData) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - // Set the request flag for the onLicenseRequest callback - m_licenseRequested = true; - - // Only construct session if it hasnt previously been constructed - if (!m_isSessionConstructed) - { - initOcdmErrorChecking(); - - MediaKeyErrorStatus status = - m_ocdmSession->constructSession(m_kSessionType, initDataType, &initData[0], initData.size()); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to construct the key session"); - m_licenseRequested = false; - } - else - { - m_isSessionConstructed = true; - - if (!m_queuedDrmHeader.empty()) - { - RIALTO_SERVER_LOG_DEBUG("Setting queued drm header after session construction"); - setDrmHeader(m_queuedDrmHeader); - m_queuedDrmHeader.clear(); - } - if (isPlayreadyKeySystem()) - { - // Ocdm-playready does not notify onProcessChallenge when complete. - // Fetch the challenge manually. - getChallenge(); - } - } - - if ((checkForOcdmErrors("generateRequest")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; - } - - return MediaKeyErrorStatus::OK; -} - -void MediaKeySession::getChallenge() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto task = [&]() - { - uint32_t challengeSize = 0; - MediaKeyErrorStatus status = m_ocdmSession->getChallengeData(m_kIsLDL, nullptr, &challengeSize); - if (challengeSize == 0) - { - RIALTO_SERVER_LOG_ERROR("Failed to get the challenge data size, no onLicenseRequest will be generated"); - return; - } - std::vector challenge(challengeSize, 0x00); - status = m_ocdmSession->getChallengeData(m_kIsLDL, &challenge[0], &challengeSize); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to get the challenge data, no onLicenseRequest will be generated"); - return; - } - - std::string url; - onProcessChallenge(url.c_str(), &challenge[0], challengeSize); - }; - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -MediaKeyErrorStatus MediaKeySession::loadSession() -{ - initOcdmErrorChecking(); - - MediaKeyErrorStatus status = m_ocdmSession->load(); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to load the key session"); - } - - if ((checkForOcdmErrors("loadSession")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -MediaKeyErrorStatus MediaKeySession::updateSession(const std::vector &responseData) -{ - initOcdmErrorChecking(); - - MediaKeyErrorStatus status; - if (isPlayreadyKeySystem()) - { - status = m_ocdmSession->storeLicenseData(&responseData[0], responseData.size()); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to store the license data for the key session"); - } - } - else - { - status = m_ocdmSession->update(&responseData[0], responseData.size()); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to update the key session"); - } - } - - if ((checkForOcdmErrors("updateSession")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -MediaKeyErrorStatus MediaKeySession::decrypt(GstBuffer *encrypted, GstCaps *caps) -{ - initOcdmErrorChecking(); - - MediaKeyErrorStatus status = m_ocdmSession->decryptBuffer(encrypted, caps); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to decrypt buffer"); - } - - if ((checkForOcdmErrors("decrypt")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -MediaKeyErrorStatus MediaKeySession::closeKeySession() -{ - initOcdmErrorChecking(); - - MediaKeyErrorStatus status; - if (isPlayreadyKeySystem()) - { - if (MediaKeyErrorStatus::OK != m_ocdmSession->cancelChallengeData()) - { - RIALTO_SERVER_LOG_WARN("Failed to cancel the challenge data for the key session"); - } - - if (MediaKeyErrorStatus::OK != m_ocdmSession->cleanDecryptContext()) - { - RIALTO_SERVER_LOG_WARN("Failed to clean the decrypt context for the key session"); - } - status = MediaKeyErrorStatus::OK; - RIALTO_SERVER_LOG_MIL("OCDM session closed"); - } - else - { - status = m_ocdmSession->close(); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to Close the key session"); - } - } - m_isSessionClosed = (MediaKeyErrorStatus::OK == status); - - if ((checkForOcdmErrors("closeKeySession")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -MediaKeyErrorStatus MediaKeySession::removeKeySession() -{ - initOcdmErrorChecking(); - - MediaKeyErrorStatus status = m_ocdmSession->remove(); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to remove the key session"); - } - - if ((checkForOcdmErrors("removeKeySession")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -MediaKeyErrorStatus MediaKeySession::getCdmKeySessionId(std::string &cdmKeySessionId) -{ - initOcdmErrorChecking(); - - MediaKeyErrorStatus status = m_ocdmSession->getCdmKeySessionId(cdmKeySessionId); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to get cdm key session id"); - } - - if ((checkForOcdmErrors("getCdmKeySessionId")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -bool MediaKeySession::containsKey(const std::vector &keyId) -{ - uint32_t result = m_ocdmSession->hasKeyId(keyId.data(), keyId.size()); - - return static_cast(result); -} - -MediaKeyErrorStatus MediaKeySession::setDrmHeader(const std::vector &requestData) -{ - initOcdmErrorChecking(); - - if (!m_isSessionConstructed) - { - RIALTO_SERVER_LOG_INFO("Session not yet constructed, queueing drm header to be set after construction"); - m_queuedDrmHeader = requestData; - return MediaKeyErrorStatus::OK; - } - - MediaKeyErrorStatus status = m_ocdmSession->setDrmHeader(requestData.data(), requestData.size()); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to set drm header"); - } - - if ((checkForOcdmErrors("setDrmHeader")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -MediaKeyErrorStatus MediaKeySession::getLastDrmError(uint32_t &errorCode) -{ - initOcdmErrorChecking(); - - MediaKeyErrorStatus status = m_ocdmSession->getLastDrmError(errorCode); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to get last drm error"); - } - - if ((checkForOcdmErrors("getLastDrmError")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -MediaKeyErrorStatus MediaKeySession::selectKeyId(const std::vector &keyId) -{ - if (m_selectedKeyId == keyId) - { - return MediaKeyErrorStatus::OK; - } - - initOcdmErrorChecking(); - - MediaKeyErrorStatus status = m_ocdmSession->selectKeyId(keyId.size(), keyId.data()); - if (MediaKeyErrorStatus::OK == status) - { - RIALTO_SERVER_LOG_INFO("New keyId selected successfully"); - m_selectedKeyId = keyId; - } - - if ((checkForOcdmErrors("selectKeyId")) && (MediaKeyErrorStatus::OK == status)) - { - status = MediaKeyErrorStatus::FAIL; - } - - return status; -} - -bool MediaKeySession::isPlayreadyKeySystem() const -{ - return m_kKeySystem.find("playready") != std::string::npos; -} - -void MediaKeySession::onProcessChallenge(const char url[], const uint8_t challenge[], const uint16_t challengeLength) -{ - std::string urlStr = url; - std::vector challengeVec = std::vector{challenge, challenge + challengeLength}; - auto task = [&, urlStr, challengeVec]() - { - std::shared_ptr client = m_mediaKeysClient.lock(); - if (client) - { - if (m_licenseRequested) - { - client->onLicenseRequest(m_kKeySessionId, challengeVec, urlStr); - m_licenseRequested = false; - } - else - { - client->onLicenseRenewal(m_kKeySessionId, challengeVec); - } - } - }; - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaKeySession::onKeyUpdated(const uint8_t keyId[], const uint8_t keyIdLength) -{ - std::vector keyIdVec = std::vector{keyId, keyId + keyIdLength}; - auto task = [&, keyIdVec]() - { - std::shared_ptr client = m_mediaKeysClient.lock(); - if (client) - { - KeyStatus status = m_ocdmSession->getStatus(&keyIdVec[0], keyIdVec.size()); - m_updatedKeyStatuses.push_back(std::make_pair(keyIdVec, status)); - } - }; - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaKeySession::onAllKeysUpdated() -{ - auto task = [&]() - { - std::shared_ptr client = m_mediaKeysClient.lock(); - if (client) - { - client->onKeyStatusesChanged(m_kKeySessionId, m_updatedKeyStatuses); - m_updatedKeyStatuses.clear(); - } - }; - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaKeySession::onError(const char message[]) -{ - RIALTO_SERVER_LOG_ERROR("Ocdm returned error: %s", message); - - std::lock_guard lock(m_ocdmErrorMutex); - if (!m_ongoingOcdmOperation) - { - RIALTO_SERVER_LOG_WARN("Received an asycronous OCDM error, ignoring"); - } - else - { - m_ocdmError = true; - } -} - -void MediaKeySession::initOcdmErrorChecking() -{ - std::lock_guard lock(m_ocdmErrorMutex); - m_ongoingOcdmOperation = true; - m_ocdmError = false; -} - -bool MediaKeySession::checkForOcdmErrors(const char *operationStr) -{ - bool error = false; - - std::lock_guard lock(m_ocdmErrorMutex); - if (m_ocdmError) - { - RIALTO_SERVER_LOG_ERROR("MediaKeySession received an onError callback, operation '%s' failed", operationStr); - error = true; - } - m_ongoingOcdmOperation = false; - - return error; -} - -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaKeysCapabilities.cpp b/middleware/rialto-client/media/server/main/source/MediaKeysCapabilities.cpp deleted file mode 100644 index 7bdb3836e..000000000 --- a/middleware/rialto-client/media/server/main/source/MediaKeysCapabilities.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "MediaCommon.h" -#include "MediaKeysCapabilities.h" -#include "MediaKeysCommon.h" -#include "RialtoServerLogging.h" - -namespace -{ -/** - * @brief Coverts MediaKeyErrorStatus to string. - */ -const char *toString(const firebolt::rialto::MediaKeyErrorStatus &status) -{ - switch (status) - { - case firebolt::rialto::MediaKeyErrorStatus::OK: - return "OK"; - case firebolt::rialto::MediaKeyErrorStatus::FAIL: - return "FAIL"; - case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: - return "BAD_SESSION_ID"; - case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: - return "INTERFACE_NOT_IMPLEMENTED"; - case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: - return "BUFFER_TOO_SMALL"; - case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: - return "NOT_SUPPORTED"; - case firebolt::rialto::MediaKeyErrorStatus::INVALID_STATE: - return "INVALID_STATE"; - } - return "Unknown"; -} -} // namespace - -namespace firebolt::rialto -{ -std::shared_ptr IMediaKeysCapabilitiesFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media keys capabilities factory, reason: %s", e.what()); - } - - return factory; -} - -std::shared_ptr MediaKeysCapabilitiesFactory::getMediaKeysCapabilities() const -{ - std::shared_ptr mediaKeysCapabilities; - try - { - mediaKeysCapabilities = - std::make_shared(wrappers::IOcdmFactory::createFactory(), - wrappers::IOcdmSystemFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media keys capabilities, reason: %s", e.what()); - } - - return mediaKeysCapabilities; -} - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::server -{ -MediaKeysCapabilities::MediaKeysCapabilities(std::shared_ptr ocdmFactory, - std::shared_ptr ocdmSystemFactory) - : m_ocdmSystemFactory{ocdmSystemFactory} -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!ocdmFactory) - { - throw std::runtime_error("ocdmFactory invalid"); - } - - m_ocdm = ocdmFactory->getOcdm(); - if (!m_ocdm) - { - throw std::runtime_error("Ocdm could not be fetched"); - } -} - -MediaKeysCapabilities::~MediaKeysCapabilities() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); -} - -std::vector MediaKeysCapabilities::getSupportedKeySystems() -{ - std::vector supportedKeySystemVector; - for (auto it = kSupportedKeySystems.begin(); it != kSupportedKeySystems.end(); it++) - { - MediaKeyErrorStatus status = m_ocdm->isTypeSupported(*it); - if (MediaKeyErrorStatus::OK == status) - { - supportedKeySystemVector.push_back(*it); - } - } - - return supportedKeySystemVector; -} - -bool MediaKeysCapabilities::supportsKeySystem(const std::string &keySystem) -{ - MediaKeyErrorStatus status = m_ocdm->isTypeSupported(keySystem); - if (MediaKeyErrorStatus::OK != status) - { - return false; - } - return true; -} - -bool MediaKeysCapabilities::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) -{ - std::shared_ptr ocdmSystem = - m_ocdmSystemFactory->createOcdmSystem(keySystem); - if (!ocdmSystem) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the ocdm system object"); - version = ""; - return false; - } - - MediaKeyErrorStatus status = ocdmSystem->getVersion(version); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Ocdm getVersion failed with status %s", toString(status)); - version = ""; - return false; - } - return true; -} - -bool MediaKeysCapabilities::isServerCertificateSupported(const std::string &keySystem) -{ - std::shared_ptr ocdmSystem = - m_ocdmSystemFactory->createOcdmSystem(keySystem); - if (!ocdmSystem) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the ocdm system object"); - return false; - } - return ocdmSystem->supportsServerCertificate(); -} - -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaKeysServerInternal.cpp b/middleware/rialto-client/media/server/main/source/MediaKeysServerInternal.cpp deleted file mode 100644 index 11fb88488..000000000 --- a/middleware/rialto-client/media/server/main/source/MediaKeysServerInternal.cpp +++ /dev/null @@ -1,759 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "MediaKeysServerInternal.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto -{ -const char *mediaKeyErrorStatusToString(const MediaKeyErrorStatus &status) -{ - switch (status) - { - case firebolt::rialto::MediaKeyErrorStatus::OK: - return "OK"; - case firebolt::rialto::MediaKeyErrorStatus::BAD_SESSION_ID: - return "BAD_SESSION_ID"; - case firebolt::rialto::MediaKeyErrorStatus::INTERFACE_NOT_IMPLEMENTED: - return "INTERFACE_NOT_IMPLEMENTED"; - case firebolt::rialto::MediaKeyErrorStatus::BUFFER_TOO_SMALL: - return "BUFFER_TOO_SMALL"; - case firebolt::rialto::MediaKeyErrorStatus::NOT_SUPPORTED: - return "NOT_SUPPORTED"; - default: - return "FAIL"; - } -} - -std::shared_ptr IMediaKeysFactory::createFactory() -{ - return server::IMediaKeysServerInternalFactory::createFactory(); -} -} // namespace firebolt::rialto - -namespace firebolt::rialto::server -{ -int32_t generateSessionId() -{ - static int32_t keySessionId{0}; - return keySessionId++; -} - -std::shared_ptr IMediaKeysServerInternalFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media keys factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr MediaKeysServerInternalFactory::createMediaKeys(const std::string &keySystem) const -{ - RIALTO_SERVER_LOG_ERROR("This function can't be used by rialto server. Please use createMediaKeysServerInternal"); - return nullptr; -} - -std::unique_ptr -MediaKeysServerInternalFactory::createMediaKeysServerInternal(const std::string &keySystem) const -{ - std::unique_ptr mediaKeys; - try - { - mediaKeys = std::make_unique(keySystem, - server::IMainThreadFactory::createFactory(), - wrappers::IOcdmSystemFactory::createFactory(), - server::IMediaKeySessionFactory::createFactory()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media keys, reason: %s", e.what()); - } - - return mediaKeys; -} -}; // namespace firebolt::rialto::server - -namespace firebolt::rialto::server -{ -MediaKeysServerInternal::MediaKeysServerInternal( - const std::string &keySystem, const std::shared_ptr &mainThreadFactory, - std::shared_ptr ocdmSystemFactory, - std::shared_ptr mediaKeySessionFactory) - : m_mediaKeySessionFactory(mediaKeySessionFactory), m_keySystem(keySystem) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - m_mainThread = mainThreadFactory->getMainThread(); - if (!m_mainThread) - { - throw std::runtime_error("Failed to get the main thread"); - } - m_mainThreadClientId = m_mainThread->registerClient(); - - if (!ocdmSystemFactory) - { - throw std::runtime_error("No ocdmSystemFactory"); - } - - bool result = false; - auto task = [&]() - { - m_ocdmSystem = ocdmSystemFactory->createOcdmSystem(keySystem); - if (!m_ocdmSystem) - { - RIALTO_SERVER_LOG_ERROR("Ocdm system could not be created"); - } - else - { - result = true; - } - }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - if (!result) - { - throw std::runtime_error("MediaKeys construction failed"); - } -} - -MediaKeysServerInternal::~MediaKeysServerInternal() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() - { - m_ocdmSystem.reset(); - - m_mainThread->unregisterClient(m_mainThreadClientId); - }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -MediaKeyErrorStatus MediaKeysServerInternal::selectKeyId(int32_t keySessionId, const std::vector &keyId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = selectKeyIdInternal(keySessionId, keyId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::selectKeyIdInternal(int32_t keySessionId, const std::vector &keyId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->selectKeyId(keyId); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to select key id"); - return status; - } - - return status; -} - -bool MediaKeysServerInternal::containsKey(int32_t keySessionId, const std::vector &keyId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result{false}; - auto task = [&]() { result = containsKeyInternal(keySessionId, keyId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaKeysServerInternal::containsKeyInternal(int32_t keySessionId, const std::vector &keyId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return false; - } - - return sessionIter->second.mediaKeySession->containsKey(keyId); -} - -MediaKeyErrorStatus MediaKeysServerInternal::createKeySession(KeySessionType sessionType, - std::weak_ptr client, bool isLDL, - int32_t &keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = createKeySessionInternal(sessionType, client, isLDL, keySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::createKeySessionInternal(KeySessionType sessionType, - std::weak_ptr client, - bool isLDL, int32_t &keySessionId) -{ - int32_t keySessionIdTemp = generateSessionId(); - std::unique_ptr mediaKeySession = - m_mediaKeySessionFactory->createMediaKeySession(m_keySystem, keySessionIdTemp, *m_ocdmSystem, sessionType, - client, isLDL); - if (!mediaKeySession) - { - RIALTO_SERVER_LOG_ERROR("Failed to create a new media key session"); - return MediaKeyErrorStatus::FAIL; - } - keySessionId = keySessionIdTemp; - m_mediaKeySessions.emplace(std::make_pair(keySessionId, MediaKeySessionUsage{std::move(mediaKeySession)})); - - return MediaKeyErrorStatus::OK; -} - -MediaKeyErrorStatus MediaKeysServerInternal::generateRequest(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = generateRequestInternal(keySessionId, initDataType, initData); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::generateRequestInternal(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->generateRequest(initDataType, initData); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to generate request for the key session %d", keySessionId); - return status; - } - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::loadSession(int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = loadSessionInternal(keySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::loadSessionInternal(int32_t keySessionId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->loadSession(); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to load the session %d", keySessionId); - return status; - } - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::updateSession(int32_t keySessionId, const std::vector &responseData) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = updateSessionInternal(keySessionId, responseData); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::updateSessionInternal(int32_t keySessionId, - const std::vector &responseData) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->updateSession(responseData); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to update the session %d", keySessionId); - return status; - } - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::setDrmHeader(int32_t keySessionId, const std::vector &requestData) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = setDrmHeaderInternal(keySessionId, requestData); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::setDrmHeaderInternal(int32_t keySessionId, - const std::vector &requestData) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->setDrmHeader(requestData); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to set drm header"); - return status; - } - - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::closeKeySession(int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = closeKeySessionInternal(keySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::closeKeySessionInternal(int32_t keySessionId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - if (sessionIter->second.bufCounter == 0) - { - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->closeKeySession(); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to close the key session %d", keySessionId); - return status; - } - return status; - } - - RIALTO_SERVER_LOG_INFO("Deferring closing of key session %d", keySessionId); - sessionIter->second.shouldBeClosed = true; - return MediaKeyErrorStatus::OK; -} - -MediaKeyErrorStatus MediaKeysServerInternal::removeKeySession(int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = removeKeySessionInternal(keySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::removeKeySessionInternal(int32_t keySessionId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->removeKeySession(); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to remove the key session %d", keySessionId); - return status; - } - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::deleteDrmStore() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = m_ocdmSystem->deleteSecureStore(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::deleteKeyStore() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = m_ocdmSystem->deleteKeyStore(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::getDrmStoreHash(std::vector &drmStoreHash) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - constexpr size_t kHashSize{256}; - drmStoreHash.resize(kHashSize); - MediaKeyErrorStatus status; - auto task = [&]() { status = m_ocdmSystem->getSecureStoreHash(&drmStoreHash[0], kHashSize); }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::getKeyStoreHash(std::vector &keyStoreHash) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - constexpr size_t kHashSize{256}; - keyStoreHash.resize(kHashSize); - MediaKeyErrorStatus status; - auto task = [&]() { status = m_ocdmSystem->getKeyStoreHash(&keyStoreHash[0], kHashSize); }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::getLdlSessionsLimit(uint32_t &ldlLimit) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = m_ocdmSystem->getLdlSessionsLimit(&ldlLimit); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::getLastDrmError(int32_t keySessionId, uint32_t &errorCode) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = getLastDrmErrorInternal(keySessionId, errorCode); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::getLastDrmErrorInternal(int32_t keySessionId, uint32_t &errorCode) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->getLastDrmError(errorCode); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to get last drm error"); - } - - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::getDrmTime(uint64_t &drmTime) -{ - MediaKeyErrorStatus status; - auto task = [&]() { status = m_ocdmSystem->getDrmTime(&drmTime); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = getCdmKeySessionIdInternal(keySessionId, cdmKeySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::releaseKeySession(int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = releaseKeySessionInternal(keySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::releaseKeySessionInternal(int32_t keySessionId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - if (sessionIter->second.bufCounter == 0) - { - m_mediaKeySessions.erase(sessionIter); - return MediaKeyErrorStatus::OK; - } - - RIALTO_SERVER_LOG_INFO("Deferring releasing of key session %d", keySessionId); - sessionIter->second.shouldBeReleased = true; - return MediaKeyErrorStatus::OK; -} - -MediaKeyErrorStatus MediaKeysServerInternal::getCdmKeySessionIdInternal(int32_t keySessionId, std::string &cdmKeySessionId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->getCdmKeySessionId(cdmKeySessionId); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to get cdm key session id"); - return status; - } - - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - MediaKeyErrorStatus status; - auto task = [&]() { status = decryptInternal(keySessionId, encrypted, caps); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -MediaKeyErrorStatus MediaKeysServerInternal::decryptInternal(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return MediaKeyErrorStatus::BAD_SESSION_ID; - } - - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->decrypt(encrypted, caps); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to decrypt buffer."); - return status; - } - - return status; -} - -bool MediaKeysServerInternal::hasSession(int32_t keySessionId) const -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = m_mediaKeySessions.find(keySessionId) != m_mediaKeySessions.end(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaKeysServerInternal::isPlayreadyKeySystem(int32_t keySessionId) const -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - bool result; - auto task = [&]() { result = isPlayreadyKeySystemInternal(keySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaKeysServerInternal::isPlayreadyKeySystemInternal(int32_t keySessionId) const -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return false; - } - return sessionIter->second.mediaKeySession->isPlayreadyKeySystem(); -} - -void MediaKeysServerInternal::incrementSessionIdUsageCounter(int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto task = [&]() { incrementSessionIdUsageCounterInternal(keySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -void MediaKeysServerInternal::incrementSessionIdUsageCounterInternal(int32_t keySessionId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return; - } - - sessionIter->second.bufCounter++; -} - -void MediaKeysServerInternal::decrementSessionIdUsageCounter(int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto task = [&]() { decrementSessionIdUsageCounterInternal(keySessionId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -void MediaKeysServerInternal::decrementSessionIdUsageCounterInternal(int32_t keySessionId) -{ - auto sessionIter = m_mediaKeySessions.find(keySessionId); - if (sessionIter == m_mediaKeySessions.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to find the session %d", keySessionId); - return; - } - - if (sessionIter->second.bufCounter > 0) - { - sessionIter->second.bufCounter--; - } - - if (sessionIter->second.bufCounter == 0) - { - if (sessionIter->second.shouldBeClosed) - { - RIALTO_SERVER_LOG_INFO("Deferred closing of mksId %d", keySessionId); - MediaKeyErrorStatus status = sessionIter->second.mediaKeySession->closeKeySession(); - if (MediaKeyErrorStatus::OK != status) - { - RIALTO_SERVER_LOG_ERROR("Failed to close the key session %d", keySessionId); - } - } - if (sessionIter->second.shouldBeReleased) - { - m_mediaKeySessions.erase(sessionIter); - } - } -} - -void MediaKeysServerInternal::ping(std::unique_ptr &&heartbeatHandler) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto task = [&]() { heartbeatHandler.reset(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -MediaKeyErrorStatus MediaKeysServerInternal::getMetricSystemData(std::vector &buffer) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - uint32_t bufferLength{1024}; - const uint32_t kMaxBufferLength{65536}; - MediaKeyErrorStatus status; - buffer.resize(bufferLength); - - for (int attempts = 0; bufferLength <= kMaxBufferLength; ++attempts) - { - auto task = [&]() { status = m_ocdmSystem->getMetricSystemData(bufferLength, buffer); }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - - if (status != MediaKeyErrorStatus::BUFFER_TOO_SMALL) - { - break; - } - - if (bufferLength >= kMaxBufferLength) - { - RIALTO_SERVER_LOG_ERROR("Buffer size %u exceeds the maximum allowed size %u", bufferLength, kMaxBufferLength); - return MediaKeyErrorStatus::BUFFER_TOO_SMALL; - } - - RIALTO_SERVER_LOG_WARN("Buffer is too small, resizing from %u to %u", bufferLength, bufferLength * 2); - bufferLength *= 2; - buffer.resize(bufferLength); - } - - if (status == MediaKeyErrorStatus::OK) - { - // If the buffer remains larger than bufferLength (due to a previous resize), - // the client may have values in the extra space. So this resize would ensure the buffer is trimmed to the correct size. - buffer.resize(bufferLength); - RIALTO_SERVER_LOG_DEBUG("Successfully retrieved metric system data, final buffer length: %u", bufferLength); - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to retrieve metric system data, status: %s, last buffer length tried: %u", - firebolt::rialto::mediaKeyErrorStatusToString(status), bufferLength); - } - return status; -} - -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaPipelineCapabilities.cpp b/middleware/rialto-client/media/server/main/source/MediaPipelineCapabilities.cpp deleted file mode 100644 index 3d874d5e2..000000000 --- a/middleware/rialto-client/media/server/main/source/MediaPipelineCapabilities.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "MediaPipelineCapabilities.h" -#include "RialtoServerLogging.h" -#include - -namespace firebolt::rialto -{ -std::shared_ptr IMediaPipelineCapabilitiesFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media pipeline capabilities factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr MediaPipelineCapabilitiesFactory::createMediaPipelineCapabilities() const -{ - std::unique_ptr mediaPipelineCapabilities; - try - { - mediaPipelineCapabilities = - std::make_unique(server::IGstCapabilitiesFactory::getFactory()); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media pipeline capabilities, reason: %s", e.what()); - } - - return mediaPipelineCapabilities; -} - -}; // namespace firebolt::rialto - -namespace firebolt::rialto::server -{ -MediaPipelineCapabilities::MediaPipelineCapabilities(std::shared_ptr gstCapabilitiesFactory) - : m_kGstCapabilitiesFactory{gstCapabilitiesFactory} -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - m_gstCapabilities = m_kGstCapabilitiesFactory->createGstCapabilities(); - if (!m_gstCapabilities) - { - throw std::runtime_error("Gstreamer capabilities could not be created"); - } -} - -MediaPipelineCapabilities::~MediaPipelineCapabilities() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); -} - -std::vector MediaPipelineCapabilities::getSupportedMimeTypes(MediaSourceType sourceType) -{ - return m_gstCapabilities->getSupportedMimeTypes(sourceType); -} - -bool MediaPipelineCapabilities::isMimeTypeSupported(const std::string &mimeType) -{ - return m_gstCapabilities->isMimeTypeSupported(mimeType); -} - -std::vector MediaPipelineCapabilities::getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) -{ - return m_gstCapabilities->getSupportedProperties(mediaType, propertyNames); -} - -bool MediaPipelineCapabilities::isVideoMaster(bool &isVideoMaster) -{ - return m_gstCapabilities->isVideoMaster(isVideoMaster); -} - -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/MediaPipelineServerInternal.cpp b/middleware/rialto-client/media/server/main/source/MediaPipelineServerInternal.cpp deleted file mode 100644 index 21aa0bbae..000000000 --- a/middleware/rialto-client/media/server/main/source/MediaPipelineServerInternal.cpp +++ /dev/null @@ -1,1620 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "ActiveRequests.h" -#include "DataReaderFactory.h" -#include "IDataReader.h" -#include "IRdkGstreamerUtilsWrapper.h" -#include "ISharedMemoryBuffer.h" -#include "MediaPipelineServerInternal.h" -#include "NeedMediaData.h" -#include "RialtoServerLogging.h" -#include "TypeConverters.h" - -namespace -{ -const char *toString(const firebolt::rialto::MediaSourceStatus &status) -{ - switch (status) - { - case firebolt::rialto::MediaSourceStatus::OK: - return "OK"; - case firebolt::rialto::MediaSourceStatus::EOS: - return "EOS"; - case firebolt::rialto::MediaSourceStatus::ERROR: - return "ERROR"; - case firebolt::rialto::MediaSourceStatus::CODEC_CHANGED: - return "CODEC_CHANGED"; - case firebolt::rialto::MediaSourceStatus::NO_AVAILABLE_SAMPLES: - return "NO_AVAILABLE_SAMPLES"; - } - return "Unknown"; -} - -std::int32_t generateSourceId() -{ - static std::int32_t sourceId{1}; - return sourceId++; -} -} // namespace - -namespace firebolt::rialto -{ -std::shared_ptr IMediaPipelineFactory::createFactory() -{ - return server::MediaPipelineServerInternalFactory::createFactory(); -} -}; // namespace firebolt::rialto - -namespace firebolt::rialto::server -{ -std::shared_ptr IMediaPipelineServerInternalFactory::createFactory() -{ - return MediaPipelineServerInternalFactory::createFactory(); -} - -std::shared_ptr MediaPipelineServerInternalFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media player server internal factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr -MediaPipelineServerInternalFactory::createMediaPipeline(std::weak_ptr client, - const VideoRequirements &videoRequirements) const -{ - RIALTO_SERVER_LOG_ERROR( - "This function can't be used by rialto server. Please use createMediaPipelineServerInternal"); - return nullptr; -} - -std::unique_ptr MediaPipelineServerInternalFactory::createMediaPipelineServerInternal( - std::weak_ptr client, const VideoRequirements &videoRequirements, int sessionId, - const std::shared_ptr &shmBuffer, IDecryptionService &decryptionService) const -{ - std::shared_ptr sharedClient = client.lock(); - if (!sharedClient) - { - RIALTO_SERVER_LOG_ERROR("Couldn't create client's shared pointer"); - return nullptr; - } - - std::unique_ptr mediaPipeline; - try - { - mediaPipeline = - std::make_unique(sharedClient, videoRequirements, - server::IGstGenericPlayerFactory::getFactory(), - sessionId, shmBuffer, - server::IMainThreadFactory::createFactory(), - common::ITimerFactory::getFactory(), - std::make_unique(), - std::make_unique(), decryptionService); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the media player server internal, reason: %s", e.what()); - } - - return mediaPipeline; -} - -MediaPipelineServerInternal::MediaPipelineServerInternal( - std::shared_ptr client, const VideoRequirements &videoRequirements, - const std::shared_ptr &gstPlayerFactory, int sessionId, - const std::shared_ptr &shmBuffer, const std::shared_ptr &mainThreadFactory, - std::shared_ptr timerFactory, std::unique_ptr &&dataReaderFactory, - std::unique_ptr &&activeRequests, IDecryptionService &decryptionService) - : m_mediaPipelineClient(client), m_kGstPlayerFactory(gstPlayerFactory), m_kVideoRequirements(videoRequirements), - m_sessionId{sessionId}, m_shmBuffer{shmBuffer}, m_dataReaderFactory{std::move(dataReaderFactory)}, - m_timerFactory{timerFactory}, m_activeRequests{std::move(activeRequests)}, m_decryptionService{decryptionService}, - m_currentPlaybackState{PlaybackState::UNKNOWN}, m_wasAllSourcesAttachedCalled{false} -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - m_mainThread = mainThreadFactory->getMainThread(); - if (!m_mainThread) - { - throw std::runtime_error("Failed to get the main thread"); - } - m_mainThreadClientId = m_mainThread->registerClient(); - - bool result = false; - auto task = [&]() - { - if (!m_shmBuffer->mapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId)) - { - RIALTO_SERVER_LOG_ERROR("Unable to map shm partition"); - } - else - { - result = true; - } - }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - if (!result) - { - throw std::runtime_error("MediaPipelineServerInternal construction failed"); - } -} - -MediaPipelineServerInternal::~MediaPipelineServerInternal() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() - { - for (const auto &timer : m_needMediaDataTimers) - { - if (timer.second && timer.second->isActive()) - { - timer.second->cancel(); - } - } - if (!m_shmBuffer->unmapPartition(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId)) - { - RIALTO_SERVER_LOG_ERROR("Unable to unmap shm partition"); - } - - m_shmBuffer.reset(); - m_mainThread->unregisterClient(m_mainThreadClientId); - }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -bool MediaPipelineServerInternal::load(MediaType type, const std::string &mimeType, const std::string &url) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = loadInternal(type, mimeType, url); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::loadInternal(MediaType type, const std::string &mimeType, const std::string &url) -{ - std::unique_lock lock{m_getPositionMutex}; - /* If gstreamer player already created, destroy the old one first */ - if (m_gstPlayer) - { - m_gstPlayer.reset(); - } - - m_gstPlayer = - m_kGstPlayerFactory - ->createGstGenericPlayer(this, m_decryptionService, type, m_kVideoRequirements, - firebolt::rialto::wrappers::IRdkGstreamerUtilsWrapperFactory::getFactory()); - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to load gstreamer player"); - return false; - } - - notifyNetworkState(NetworkState::BUFFERING); - - return true; -} - -bool MediaPipelineServerInternal::attachSource(const std::unique_ptr &source) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = attachSourceInternal(source); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::attachSourceInternal(const std::unique_ptr &source) -{ - source->setId(-1); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Gstreamer player has not been loaded"); - return false; - } - - if (source->getType() == MediaSourceType::UNKNOWN) - { - RIALTO_SERVER_LOG_ERROR("Media source type unknown"); - return false; - } - - m_gstPlayer->attachSource(source); - - const auto kSourceIter = m_attachedSources.find(source->getType()); - if (m_attachedSources.cend() == kSourceIter) - { - source->setId(generateSourceId()); - RIALTO_SERVER_LOG_DEBUG("New ID generated for MediaSourceType: %s: %d", - common::convertMediaSourceType(source->getType()), source->getId()); - m_attachedSources.emplace(source->getType(), source->getId()); - } - else - { - RIALTO_SERVER_LOG_WARN("SourceType '%s' already attached", common::convertMediaSourceType(source->getType())); - return false; - } - - return true; -} - -bool MediaPipelineServerInternal::removeSource(int32_t id) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = removeSourceInternal(id); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::removeSourceInternal(int32_t id) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to remove source - Gstreamer player has not been loaded"); - return false; - } - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [id](const auto &src) { return src.second == id; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to remove source with id %d- Source not found", id); - return false; - } - - m_gstPlayer->removeSource(sourceIter->first); - m_needMediaDataTimers.erase(sourceIter->first); - m_attachedSources.erase(sourceIter); - return true; -} - -bool MediaPipelineServerInternal::allSourcesAttached() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = allSourcesAttachedInternal(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::allSourcesAttachedInternal() -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to notify all sources attached - Gstreamer player has not been loaded"); - return false; - } - - if (m_wasAllSourcesAttachedCalled) - { - RIALTO_SERVER_LOG_WARN("Failed to notify all sources attached - It was already called"); - return false; - } - - m_gstPlayer->allSourcesAttached(); - m_wasAllSourcesAttachedCalled = true; - return true; -} - -bool MediaPipelineServerInternal::play() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = playInternal(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::playInternal() -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to play - Gstreamer player has not been loaded"); - return false; - } - - m_gstPlayer->play(); - return true; -} - -bool MediaPipelineServerInternal::pause() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = pauseInternal(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::pauseInternal() -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to pause - Gstreamer player has not been loaded"); - return false; - } - - m_gstPlayer->pause(); - return true; -} - -bool MediaPipelineServerInternal::stop() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = stopInternal(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::stopInternal() -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to stop - Gstreamer player has not been loaded"); - return false; - } - - m_gstPlayer->stop(); - return true; -} - -bool MediaPipelineServerInternal::setPlaybackRate(double rate) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setPlaybackRateInternal(rate); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setPlaybackRateInternal(double rate) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set playback rate - Gstreamer player has not been loaded"); - return false; - } - - if (0.0 == rate) - { - RIALTO_SERVER_LOG_ERROR("Failed to set playback rate to 0.0 - pause method should be used instead."); - return false; - } - - m_gstPlayer->setPlaybackRate(rate); - return true; -} - -bool MediaPipelineServerInternal::setPosition(int64_t position) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setPositionInternal(position); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setPositionInternal(int64_t position) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set position - Gstreamer player has not been loaded"); - return false; - } - - m_gstPlayer->setPosition(position); - - // Reset Eos on seek - for (auto &isMediaTypeEos : m_isMediaTypeEosMap) - { - isMediaTypeEos.second = false; - } - - return true; -} - -bool MediaPipelineServerInternal::getPosition(int64_t &position) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - std::shared_lock lock{m_getPositionMutex}; - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get position - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->getPosition(position); -} - -bool MediaPipelineServerInternal::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = getStatsInternal(sourceId, renderedFrames, droppedFrames); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getStatsInternal(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get stats - Gstreamer player has not been loaded"); - return false; - } - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to get stats - Source not found"); - return false; - } - return m_gstPlayer->getStats(sourceIter->first, renderedFrames, droppedFrames); -} - -bool MediaPipelineServerInternal::setImmediateOutput(int32_t sourceId, bool immediateOutput) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setImmediateOutputInternal(sourceId, immediateOutput); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setImmediateOutputInternal(int32_t sourceId, bool immediateOutput) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded"); - return false; - } - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed - Source not found"); - return false; - } - - m_IsLowLatencyVideoPlayer = immediateOutput; - return m_gstPlayer->setImmediateOutput(sourceIter->first, immediateOutput); -} - -bool MediaPipelineServerInternal::getImmediateOutput(int32_t sourceId, bool &immediateOutput) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = getImmediateOutputInternal(sourceId, immediateOutput); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getImmediateOutputInternal(int32_t sourceId, bool &immediateOutput) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed - Gstreamer player has not been loaded"); - return false; - } - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed - Source not found"); - return false; - } - return m_gstPlayer->getImmediateOutput(sourceIter->first, immediateOutput); -} - -bool MediaPipelineServerInternal::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setVideoWindowInternal(x, y, width, height); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setVideoWindowInternal(uint32_t x, uint32_t y, uint32_t width, uint32_t height) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set video window - Gstreamer player has not been loaded"); - return false; - } - - m_gstPlayer->setVideoGeometry(x, y, width, height); - return true; -} - -bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t needDataRequestId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = haveDataInternal(status, needDataRequestId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t needDataRequestId) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded"); - return false; - } - - MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId); - if (MediaSourceType::UNKNOWN == mediaSourceType) - { - RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId); - return true; - } - - unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType]; - if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS) - { - // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS. - - ++counter; - if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES) - { - RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u " - "consecutively for mediaSourceType: %s", - needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType)); - } - else - { - RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status: %s", - common::convertMediaSourceType(mediaSourceType), needDataRequestId, toString(status)); - counter = 0; - } - - m_activeRequests->erase(needDataRequestId); - scheduleNotifyNeedMediaData(mediaSourceType); - return true; - } - else - { - RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status", - common::convertMediaSourceType(mediaSourceType), needDataRequestId); - counter = 0; - } - - try - { - const IMediaPipeline::MediaSegmentVector &kSegments = m_activeRequests->getSegments(needDataRequestId); - m_gstPlayer->attachSamples(kSegments); - } - catch (const std::runtime_error &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to get segments %s", e.what()); - m_activeRequests->erase(needDataRequestId); - return false; - } - - m_activeRequests->erase(needDataRequestId); - if (status == MediaSourceStatus::EOS) - { - m_gstPlayer->setEos(mediaSourceType); - m_isMediaTypeEosMap[mediaSourceType] = true; - } - - return true; -} - -bool MediaPipelineServerInternal::haveData(MediaSourceStatus status, uint32_t numFrames, uint32_t needDataRequestId) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = haveDataInternal(status, numFrames, needDataRequestId); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::haveDataInternal(MediaSourceStatus status, uint32_t numFrames, - uint32_t needDataRequestId) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("HaveData failed - Gstreamer player has not been loaded"); - return false; - } - MediaSourceType mediaSourceType = m_activeRequests->getType(needDataRequestId); - if (MediaSourceType::UNKNOWN == mediaSourceType) - { - RIALTO_SERVER_LOG_WARN("NeedData RequestID is not valid: %u", needDataRequestId); - return true; - } - m_activeRequests->erase(needDataRequestId); - - unsigned int &counter = m_noAvailableSamplesCounter[mediaSourceType]; - if (status != MediaSourceStatus::OK && status != MediaSourceStatus::EOS) - { - // Incrementing the counter allows us to track the occurrences where the status is other than OK or EOS. - - ++counter; - if (status == MediaSourceStatus::NO_AVAILABLE_SAMPLES) - { - RIALTO_SERVER_LOG_DEBUG("Data request for needDataRequestId: %u. NO_AVAILABLE_SAMPLES received: %u " - "consecutively for mediaSourceType: %s", - needDataRequestId, counter, common::convertMediaSourceType(mediaSourceType)); - } - else - { - RIALTO_SERVER_LOG_WARN("%s Data request for needDataRequestId: %u received with wrong status", - common::convertMediaSourceType(mediaSourceType), needDataRequestId); - counter = 0; - } - scheduleNotifyNeedMediaData(mediaSourceType); - return true; - } - else - { - RIALTO_SERVER_LOG_DEBUG("%s Data request for needDataRequestId: %u received with correct status", - common::convertMediaSourceType(mediaSourceType), needDataRequestId); - counter = 0; - } - - uint8_t *buffer = m_shmBuffer->getBuffer(); - if (!buffer) - { - RIALTO_SERVER_LOG_ERROR("No buffer available"); - notifyPlaybackState(PlaybackState::FAILURE); - return false; - } - - std::uint32_t regionOffset = 0; - try - { - regionOffset = - m_shmBuffer->getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType); - } - catch (const std::runtime_error &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to get region's buffer offset, reason: %s", e.what()); - notifyPlaybackState(PlaybackState::FAILURE); - return false; - } - - if (0 != numFrames) - { - std::shared_ptr dataReader = - m_dataReaderFactory->createDataReader(mediaSourceType, buffer, regionOffset, numFrames); - if (!dataReader) - { - RIALTO_SERVER_LOG_ERROR("Metadata version not supported for %s request id: %u", - common::convertMediaSourceType(mediaSourceType), needDataRequestId); - notifyPlaybackState(PlaybackState::FAILURE); - return false; - } - m_gstPlayer->attachSamples(dataReader); - } - if (status == MediaSourceStatus::EOS) - { - m_gstPlayer->setEos(mediaSourceType); - m_isMediaTypeEosMap[mediaSourceType] = true; - } - - return true; -} - -void MediaPipelineServerInternal::ping(std::unique_ptr &&heartbeatHandler) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() { pingInternal(std::move(heartbeatHandler)); }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::pingInternal(std::unique_ptr &&heartbeatHandler) -{ - if (!m_gstPlayer) - { - // No need to check GstPlayer worker thread, we reached this function, so main thread is working fine. - heartbeatHandler.reset(); - return; - } - // Check GstPlayer worker thread - m_gstPlayer->ping(std::move(heartbeatHandler)); -} - -bool MediaPipelineServerInternal::renderFrame() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = renderFrameInternal(); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::renderFrameInternal() -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("renderFrame failed - Gstreamer player has not been loaded"); - return false; - } - - m_gstPlayer->renderFrame(); - return true; -} - -bool MediaPipelineServerInternal::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setVolumeInternal(targetVolume, volumeDuration, easeType); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setVolumeInternal(double targetVolume, uint32_t volumeDuration, EaseType easeType) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set volume - Gstreamer player has not been loaded"); - return false; - } - m_gstPlayer->setVolume(targetVolume, volumeDuration, easeType); - return true; -} - -bool MediaPipelineServerInternal::getVolume(double ¤tVolume) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = getVolumeInternal(currentVolume); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getVolumeInternal(double ¤tVolume) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get volume - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->getVolume(currentVolume); -} - -bool MediaPipelineServerInternal::setMute(std::int32_t sourceId, bool mute) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setMuteInternal(sourceId, mute); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setMuteInternal(std::int32_t sourceId, bool mute) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set mute - Gstreamer player has not been loaded"); - return false; - } - - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to set mute - Source with id: %d not found", sourceId); - return false; - } - - m_gstPlayer->setMute(sourceIter->first, mute); - - return true; -} - -bool MediaPipelineServerInternal::getMute(std::int32_t sourceId, bool &mute) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = getMuteInternal(sourceId, mute); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getMuteInternal(std::int32_t sourceId, bool &mute) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded"); - return false; - } - - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to get mute - Source with id: %d not found", sourceId); - return false; - } - - return m_gstPlayer->getMute(sourceIter->first, mute); -} - -bool MediaPipelineServerInternal::setTextTrackIdentifier(const std::string &textTrackIdentifier) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setTextTrackIdentifierInternal(textTrackIdentifier); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setTextTrackIdentifierInternal(const std::string &textTrackIdentifier) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set text track identifier - Gstreamer player has not been loaded"); - return false; - } - - m_gstPlayer->setTextTrackIdentifier(textTrackIdentifier); - - return true; -} - -bool MediaPipelineServerInternal::getTextTrackIdentifier(std::string &textTrackIdentifier) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = getTextTrackIdentifierInternal(textTrackIdentifier); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getTextTrackIdentifierInternal(std::string &textTrackIdentifier) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get mute - Gstreamer player has not been loaded"); - return false; - } - - return m_gstPlayer->getTextTrackIdentifier(textTrackIdentifier); -} - -bool MediaPipelineServerInternal::flush(int32_t sourceId, bool resetTime, bool &async) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = flushInternal(sourceId, resetTime, async); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setLowLatency(bool lowLatency) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setLowLatencyInternal(lowLatency); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setLowLatencyInternal(bool lowLatency) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set low latency - Gstreamer player has not been loaded"); - return false; - } - m_IsLowLatencyAudioPlayer = lowLatency; - - return m_gstPlayer->setLowLatency(lowLatency); -} - -bool MediaPipelineServerInternal::setSync(bool sync) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setSyncInternal(sync); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setSyncInternal(bool sync) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set sync - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->setSync(sync); -} - -bool MediaPipelineServerInternal::getSync(bool &sync) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = getSyncInternal(sync); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getSyncInternal(bool &sync) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get sync - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->getSync(sync); -} - -bool MediaPipelineServerInternal::setSyncOff(bool syncOff) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setSyncOffInternal(syncOff); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setSyncOffInternal(bool syncOff) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set sync off - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->setSyncOff(syncOff); -} - -bool MediaPipelineServerInternal::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setStreamSyncModeInternal(sourceId, streamSyncMode); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setStreamSyncModeInternal(int32_t sourceId, int32_t streamSyncMode) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Gstreamer player has not been loaded"); - return false; - } - - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to set stream sync mode - Source with id: %d not found", sourceId); - return false; - } - - return m_gstPlayer->setStreamSyncMode(sourceIter->first, streamSyncMode); -} - -bool MediaPipelineServerInternal::getStreamSyncMode(int32_t &streamSyncMode) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = getStreamSyncModeInternal(streamSyncMode); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getStreamSyncModeInternal(int32_t &streamSyncMode) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get stream sync mode - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->getStreamSyncMode(streamSyncMode); -} - -bool MediaPipelineServerInternal::flushInternal(int32_t sourceId, bool resetTime, bool &async) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to flush - Gstreamer player has not been loaded"); - return false; - } - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to flush - Source with id: %d not found", sourceId); - return false; - } - - m_gstPlayer->flush(sourceIter->first, resetTime, async); - - // Reset Eos on flush - auto it = m_isMediaTypeEosMap.find(sourceIter->first); - if (it != m_isMediaTypeEosMap.end() && it->second) - { - it->second = false; - } - - return true; -} - -bool MediaPipelineServerInternal::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setSourcePositionInternal(sourceId, position, resetTime, appliedRate, stopPosition); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setSourcePositionInternal(int32_t sourceId, int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set source position - Gstreamer player has not been loaded"); - return false; - } - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to set source position - Source with id: %d not found", sourceId); - return false; - } - - m_gstPlayer->setSourcePosition(sourceIter->first, position, resetTime, appliedRate, stopPosition); - - // Reset Eos on seek - auto it = m_isMediaTypeEosMap.find(sourceIter->first); - if (it != m_isMediaTypeEosMap.end() && it->second) - { - it->second = false; - } - - return true; -} - -bool MediaPipelineServerInternal::setSubtitleOffset(int32_t sourceId, int64_t position) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = setSubtitleOffsetInternal(sourceId, position); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setSubtitleOffsetInternal(int32_t sourceId, int64_t position) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Gstreamer player has not been loaded"); - return false; - } - auto sourceIter = std::find_if(m_attachedSources.begin(), m_attachedSources.end(), - [sourceId](const auto &src) { return src.second == sourceId; }); - if (sourceIter == m_attachedSources.end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to set subtitle offset - Source with id: %d not found", sourceId); - return false; - } - - m_gstPlayer->setSubtitleOffset(position); - return true; -} - -bool MediaPipelineServerInternal::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, - bool audioAac) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result; - auto task = [&]() { result = processAudioGapInternal(position, duration, discontinuityGap, audioAac); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::processAudioGapInternal(int64_t position, uint32_t duration, int64_t discontinuityGap, - bool audioAac) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to process audio gap - Gstreamer player has not been loaded"); - return false; - } - m_gstPlayer->processAudioGap(position, duration, discontinuityGap, audioAac); - return true; -} - -bool MediaPipelineServerInternal::setBufferingLimit(uint32_t limitBufferingMs) -{ - bool result; - auto task = [&]() { result = setBufferingLimitInternal(limitBufferingMs); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setBufferingLimitInternal(uint32_t limitBufferingMs) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set buffering limit - Gstreamer player has not been loaded"); - return false; - } - m_gstPlayer->setBufferingLimit(limitBufferingMs); - return true; -} - -bool MediaPipelineServerInternal::getBufferingLimit(uint32_t &limitBufferingMs) -{ - bool result; - auto task = [&]() { result = getBufferingLimitInternal(limitBufferingMs); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getBufferingLimitInternal(uint32_t &limitBufferingMs) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get buffering limit - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->getBufferingLimit(limitBufferingMs); -} - -bool MediaPipelineServerInternal::setUseBuffering(bool useBuffering) -{ - bool result; - auto task = [&]() { result = setUseBufferingInternal(useBuffering); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::setUseBufferingInternal(bool useBuffering) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to set use buffering - Gstreamer player has not been loaded"); - return false; - } - m_gstPlayer->setUseBuffering(useBuffering); - return true; -} - -bool MediaPipelineServerInternal::getUseBuffering(bool &useBuffering) -{ - bool result; - auto task = [&]() { result = getUseBufferingInternal(useBuffering); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::getUseBufferingInternal(bool &useBuffering) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to get use buffering - Gstreamer player has not been loaded"); - return false; - } - return m_gstPlayer->getUseBuffering(useBuffering); -} - -bool MediaPipelineServerInternal::switchSource(const std::unique_ptr &source) -{ - bool result; - auto task = [&]() { result = switchSourceInternal(source); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return result; -} - -bool MediaPipelineServerInternal::switchSourceInternal(const std::unique_ptr &source) -{ - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to switch source - Gstreamer player has not been loaded"); - return false; - } - m_gstPlayer->switchSource(source); - return true; -} - -AddSegmentStatus MediaPipelineServerInternal::addSegment(uint32_t needDataRequestId, - const std::unique_ptr &mediaSegment) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - AddSegmentStatus status{AddSegmentStatus::ERROR}; - auto task = [&]() { status = addSegmentInternal(needDataRequestId, mediaSegment); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -AddSegmentStatus MediaPipelineServerInternal::addSegmentInternal(uint32_t needDataRequestId, - const std::unique_ptr &mediaSegment) -{ - AddSegmentStatus status = m_activeRequests->addSegment(needDataRequestId, mediaSegment); - if (status != AddSegmentStatus::OK) - { - RIALTO_SERVER_LOG_ERROR("Failed to add segment for request id: %u", needDataRequestId); - } - - return status; -} - -std::weak_ptr MediaPipelineServerInternal::getClient() -{ - return m_mediaPipelineClient; -} - -void MediaPipelineServerInternal::notifyPlaybackState(PlaybackState state) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (m_mediaPipelineClient) - { - m_mediaPipelineClient->notifyPlaybackState(state); - } - auto task = [&, state]() { m_currentPlaybackState = state; }; - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -bool MediaPipelineServerInternal::notifyNeedMediaData(MediaSourceType mediaSourceType) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - // the task won't execute for a disconnected client therefore - // set a default value of true which will help to stop any further - // action being taken - bool result{true}; - - auto task = [&]() { result = notifyNeedMediaDataInternal(mediaSourceType); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - - return result; -} - -bool MediaPipelineServerInternal::notifyNeedMediaDataInternal(MediaSourceType mediaSourceType) -{ - m_needMediaDataTimers.erase(mediaSourceType); - m_shmBuffer->clearData(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, m_sessionId, mediaSourceType); - const auto kSourceIter = m_attachedSources.find(mediaSourceType); - - if (m_attachedSources.cend() == kSourceIter) - { - RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s - sourceId not found", - common::convertMediaSourceType(mediaSourceType)); - return false; - } - auto it = m_isMediaTypeEosMap.find(mediaSourceType); - if (it != m_isMediaTypeEosMap.end() && it->second) - { - RIALTO_SERVER_LOG_INFO("EOS, NeedMediaData not needed for %s", common::convertMediaSourceType(mediaSourceType)); - return false; - } - NeedMediaData event{m_mediaPipelineClient, *m_activeRequests, *m_shmBuffer, m_sessionId, - mediaSourceType, kSourceIter->second, m_currentPlaybackState}; - if (!event.send()) - { - RIALTO_SERVER_LOG_WARN("NeedMediaData event sending failed for %s", - common::convertMediaSourceType(mediaSourceType)); - return false; - } - - RIALTO_SERVER_LOG_DEBUG("%s NeedMediaData sent.", common::convertMediaSourceType(mediaSourceType)); - - return true; -} - -void MediaPipelineServerInternal::notifyPosition(std::int64_t position) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, position]() - { - if (m_mediaPipelineClient) - { - m_mediaPipelineClient->notifyPosition(position); - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::notifyNetworkState(NetworkState state) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, state]() - { - if (m_mediaPipelineClient) - { - m_mediaPipelineClient->notifyNetworkState(state); - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::clearActiveRequestsCache() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() { m_activeRequests->clear(); }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::invalidateActiveRequests(const MediaSourceType &type) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, type]() { m_activeRequests->erase(type); }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::notifyQos(MediaSourceType mediaSourceType, const QosInfo &qosInfo) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, mediaSourceType, qosInfo]() - { - if (m_mediaPipelineClient) - { - const auto kSourceIter = m_attachedSources.find(mediaSourceType); - if (m_attachedSources.cend() == kSourceIter) - { - RIALTO_SERVER_LOG_WARN("Qos notification failed - sourceId not found for %s", - common::convertMediaSourceType(mediaSourceType)); - return; - } - m_mediaPipelineClient->notifyQos(kSourceIter->second, qosInfo); - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::notifyBufferUnderflow(MediaSourceType mediaSourceType) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, mediaSourceType]() - { - if (m_mediaPipelineClient) - { - const auto kSourceIter = m_attachedSources.find(mediaSourceType); - if (m_attachedSources.cend() == kSourceIter) - { - RIALTO_SERVER_LOG_WARN("Buffer underflow notification failed - sourceId not found for %s", - common::convertMediaSourceType(mediaSourceType)); - return; - } - m_mediaPipelineClient->notifyBufferUnderflow(kSourceIter->second); - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::notifyPlaybackError(MediaSourceType mediaSourceType, PlaybackError error) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, mediaSourceType, error]() - { - if (m_mediaPipelineClient) - { - const auto kSourceIter = m_attachedSources.find(mediaSourceType); - if (m_attachedSources.cend() == kSourceIter) - { - RIALTO_SERVER_LOG_WARN("Playback error notification failed - sourceId not found for %s", - common::convertMediaSourceType(mediaSourceType)); - return; - } - m_mediaPipelineClient->notifyPlaybackError(kSourceIter->second, error); - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::notifySourceFlushed(MediaSourceType mediaSourceType) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, mediaSourceType]() - { - if (m_mediaPipelineClient) - { - const auto kSourceIter = m_attachedSources.find(mediaSourceType); - if (m_attachedSources.cend() == kSourceIter) - { - RIALTO_SERVER_LOG_WARN("Source flushed notification failed - sourceId not found for: %s", - common::convertMediaSourceType(mediaSourceType)); - return; - } - m_mediaPipelineClient->notifySourceFlushed(kSourceIter->second); - RIALTO_SERVER_LOG_DEBUG("%s source flushed", common::convertMediaSourceType(mediaSourceType)); - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -void MediaPipelineServerInternal::scheduleNotifyNeedMediaData(MediaSourceType mediaSourceType) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - auto timer = m_needMediaDataTimers.find(mediaSourceType); - if (m_needMediaDataTimers.end() != timer && timer->second && timer->second->isActive()) - { - RIALTO_SERVER_LOG_DEBUG("Skip scheduling need media data for %s - it is already scheduled", - common::convertMediaSourceType(mediaSourceType)); - return; - } - - m_needMediaDataTimers[mediaSourceType] = - m_timerFactory - ->createTimer(getNeedMediaDataTimeout(mediaSourceType), - [this, mediaSourceType]() - { - m_mainThread - ->enqueueTask(m_mainThreadClientId, - [this, mediaSourceType]() - { - m_needMediaDataTimers.erase(mediaSourceType); - if (!notifyNeedMediaDataInternal(mediaSourceType)) - { - RIALTO_SERVER_LOG_WARN("Scheduled Need media data sending " - "failed for: %s. Scheduling again...", - common::convertMediaSourceType( - mediaSourceType)); - scheduleNotifyNeedMediaData(mediaSourceType); - } - }); - }); -} - -std::chrono::milliseconds MediaPipelineServerInternal::getNeedMediaDataTimeout(MediaSourceType mediaSourceType) const -{ - constexpr std::chrono::milliseconds kDefaultNeedMediaDataResendTimeMs{15}; - constexpr std::chrono::milliseconds kNeedMediaDataResendTimeMsForLowLatency{5}; - if ((mediaSourceType == MediaSourceType::VIDEO && m_IsLowLatencyVideoPlayer) || - (mediaSourceType == MediaSourceType::AUDIO && m_IsLowLatencyAudioPlayer)) - { - return kNeedMediaDataResendTimeMsForLowLatency; - } - return kDefaultNeedMediaDataResendTimeMs; -} -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/NeedMediaData.cpp b/middleware/rialto-client/media/server/main/source/NeedMediaData.cpp deleted file mode 100644 index 19a00b7a7..000000000 --- a/middleware/rialto-client/media/server/main/source/NeedMediaData.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "NeedMediaData.h" -#include "IActiveRequests.h" -#include "IMediaPipelineClient.h" -#include "ISharedMemoryBuffer.h" -#include "RialtoServerLogging.h" -#include "ShmUtils.h" -#include "TypeConverters.h" - -namespace firebolt::rialto::server -{ -NeedMediaData::NeedMediaData(std::weak_ptr client, IActiveRequests &activeRequests, - const ISharedMemoryBuffer &shmBuffer, int sessionId, MediaSourceType mediaSourceType, - std::int32_t sourceId, PlaybackState currentPlaybackState) - : m_client{client}, m_activeRequests{activeRequests}, m_mediaSourceType{mediaSourceType}, m_frameCount{kMaxFrames}, - m_sourceId{sourceId} -{ - if (PlaybackState::PLAYING != currentPlaybackState) - { - RIALTO_SERVER_LOG_DEBUG("Pipeline in prerolling state. Sending smaller frame count for %s", - common::convertMediaSourceType(m_mediaSourceType)); - m_frameCount = kPrerollNumFrames; - } - if (MediaSourceType::AUDIO != mediaSourceType && MediaSourceType::VIDEO != mediaSourceType && - MediaSourceType::SUBTITLE != mediaSourceType) - { - RIALTO_SERVER_LOG_ERROR("Unable to initialize NeedMediaData - unknown mediaSourceType: %s", - common::convertMediaSourceType(m_mediaSourceType)); - m_isValid = false; - return; - } - try - { - m_maxMediaBytes = - shmBuffer.getMaxDataLen(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, sessionId, mediaSourceType) - - getMaxMetadataBytes(); - auto metadataOffset = - shmBuffer.getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::GENERIC, sessionId, mediaSourceType); - auto mediadataOffset = metadataOffset + getMaxMetadataBytes(); - m_shmInfo = std::make_shared( - MediaPlayerShmInfo{getMaxMetadataBytes(), metadataOffset, mediadataOffset, m_maxMediaBytes}); - m_isValid = true; - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Unable to construct NeedMediaData message for %s - %s", - common::convertMediaSourceType(m_mediaSourceType), e.what()); - m_isValid = false; - } -} - -bool NeedMediaData::send() const -{ - auto client = m_client.lock(); - if (client && m_isValid) - { - client->notifyNeedMediaData(m_sourceId, m_frameCount, - m_activeRequests.insert(m_mediaSourceType, m_maxMediaBytes), m_shmInfo); - return true; - } - return false; -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/SharedMemoryBuffer.cpp b/middleware/rialto-client/media/server/main/source/SharedMemoryBuffer.cpp deleted file mode 100644 index 75805b751..000000000 --- a/middleware/rialto-client/media/server/main/source/SharedMemoryBuffer.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "RialtoServerLogging.h" -#include "SharedMemoryBuffer.h" -#include "TypeConverters.h" - -#if !defined(SYS_memfd_create) -#if defined(__NR_memfd_create) -#define SYS_memfd_create __NR_memfd_create -#elif defined(__arm__) -#define SYS_memfd_create 385 -#endif -#endif - -#if !defined(MFD_CLOEXEC) -#define MFD_CLOEXEC 0x0001U -#endif - -#if !defined(MFD_ALLOW_SEALING) -#define MFD_ALLOW_SEALING 0x0002U -#endif - -#if !defined(F_ADD_SEALS) -#if !defined(F_LINUX_SPECIFIC_BASE) -#define F_LINUX_SPECIFIC_BASE 1024 -#endif -#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) -#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) - -#define F_SEAL_SEAL 0x0001 -#define F_SEAL_SHRINK 0x0002 -#define F_SEAL_GROW 0x0004 -#define F_SEAL_WRITE 0x0008 -#endif - -namespace -{ -const char *kMemoryBufferName{"rialto_avbuf"}; -constexpr int kNoIdAssigned{-1}; -constexpr uint32_t kVideoRegionSize = 7 * 1024 * 1024; // 7MB -constexpr uint32_t kAudioRegionSize = 1 * 1024 * 1024; // 1MB -constexpr uint32_t kSubtitleRegionSize = 256 * 1024; // 256kB -constexpr uint32_t kWebAudioRegionSize = 10 * 1024; // 10KB - -std::vector -calculatePartitionSize(firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType playbackType, int num) -{ - if (firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::GENERIC == playbackType) - { - // As (for now) resolution of playback (for example HD or UHD) is not known, partitions have the same size. - firebolt::rialto::server::SharedMemoryBuffer::Partition singlePlaybackDataBuffer{kNoIdAssigned, kAudioRegionSize, - kVideoRegionSize, - kSubtitleRegionSize}; - return std::vector(num, singlePlaybackDataBuffer); - } - else if (firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO == playbackType) - { - firebolt::rialto::server::SharedMemoryBuffer::Partition webAudioDataBuffer{kNoIdAssigned, kWebAudioRegionSize, 0}; - return std::vector(num, webAudioDataBuffer); - } - else - { - return std::vector(); - } -} - -const char *toString(const firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType &type) -{ - switch (type) - { - case firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::GENERIC: - { - return "GENERIC"; - } - case firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO: - { - return "WEB_AUDIO"; - } - } - return "UNKNOWN"; -} -} // namespace - -namespace firebolt::rialto::server -{ -std::unique_ptr ISharedMemoryBufferFactory::createFactory() -{ - return std::make_unique(); -} - -std::shared_ptr -SharedMemoryBufferFactory::createSharedMemoryBuffer(unsigned numOfPlaybacks, unsigned numOfWebAudioPlayers) const -{ - return std::make_shared(numOfPlaybacks, numOfWebAudioPlayers); -} - -SharedMemoryBuffer::SharedMemoryBuffer(unsigned numOfPlaybacks, unsigned numOfWebAudioPlayers) - : m_genericPartitions{calculatePartitionSize(MediaPlaybackType::GENERIC, numOfPlaybacks)}, - m_webAudioPartitions{calculatePartitionSize(MediaPlaybackType::WEB_AUDIO, numOfWebAudioPlayers)}, - m_dataBufferLen{0}, m_dataBufferFd{-1}, m_dataBuffer{nullptr} -{ - int fd = syscall(SYS_memfd_create, kMemoryBufferName, MFD_CLOEXEC | MFD_ALLOW_SEALING); - if (fd < 0) - { - RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to create memory buffer"); - } - else - { - const size_t kBufferSize{calculateBufferSize()}; - if (ftruncate(fd, static_cast(kBufferSize)) == -1) - { - RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to resize memfd"); - } - else if (fcntl(fd, F_ADD_SEALS, (F_SEAL_SEAL | F_SEAL_GROW | F_SEAL_SHRINK)) == -1) - { - RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to seal memfd"); - } - else - { - void *addr = mmap(nullptr, kBufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (addr != MAP_FAILED) - { - m_dataBufferLen = kBufferSize; - m_dataBufferFd = fd; - m_dataBuffer = reinterpret_cast(addr); - RIALTO_SERVER_LOG_INFO("Shared Memory Buffer size: %d, ptr: %p", m_dataBufferLen, m_dataBuffer); - } - } - - if (m_dataBufferFd == -1) - { - if (close(fd) != 0) - RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to close fd"); - } - } - - if (m_dataBufferFd == -1) - { - RIALTO_SERVER_LOG_ERROR("Shared Memory Buffer initialization failed"); - throw std::runtime_error("Shared Memory Buffer initialization failed"); - } -} - -SharedMemoryBuffer::~SharedMemoryBuffer() -{ - RIALTO_SERVER_LOG_INFO("Destroying Shared Memory Buffer"); - if (m_dataBufferFd != -1) - { - if (munmap(m_dataBuffer, m_dataBufferLen) != 0) - RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to unmap buffer"); - if (close(m_dataBufferFd) != 0) - RIALTO_SERVER_LOG_SYS_ERROR(errno, "failed to close data buffer fd"); - - m_dataBufferLen = 0; - m_dataBufferFd = -1; - m_dataBuffer = nullptr; - } -} - -bool SharedMemoryBuffer::mapPartition(MediaPlaybackType playbackType, int id) -{ - std::vector *partitions = getPlaybackTypePartition(playbackType); - if (!partitions) - { - RIALTO_SERVER_LOG_ERROR("Cannot map the partition for playback type %s with id: %d", toString(playbackType), id); - return false; - } - - auto partition = std::find_if(partitions->begin(), partitions->end(), [id](const auto &p) { return p.id == id; }); - if (partition != partitions->end()) - { - RIALTO_SERVER_LOG_DEBUG("Skip to map shm partition for id: %d. - partition already assigned", id); - return true; - } - auto freePartition = - std::find_if(partitions->begin(), partitions->end(), [](const auto &p) { return p.id == kNoIdAssigned; }); - if (freePartition == partitions->end()) - { - RIALTO_SERVER_LOG_ERROR("Failed to map Shm partition for id: %d. No free partition available.", id); - return false; - } - freePartition->id = id; - return true; -} - -bool SharedMemoryBuffer::unmapPartition(MediaPlaybackType playbackType, int id) -{ - std::vector *partitions = getPlaybackTypePartition(playbackType); - if (!partitions) - { - RIALTO_SERVER_LOG_ERROR("Cannot unmap the partition for playback type %s with id: %d", toString(playbackType), - id); - return false; - } - - auto partition = std::find_if(partitions->begin(), partitions->end(), [id](const auto &p) { return p.id == id; }); - if (partition == partitions->end()) - { - RIALTO_SERVER_LOG_WARN("Failed to unmap Shm partition for id: %d. - partition could not be found", id); - return false; - } - partition->id = kNoIdAssigned; - return true; -} - -bool SharedMemoryBuffer::clearData(MediaPlaybackType playbackType, int id, const MediaSourceType &mediaSourceType) const -{ - const std::vector *kPartitions = getPlaybackTypePartition(playbackType); - if (!kPartitions) - { - RIALTO_SERVER_LOG_ERROR("Cannot clear the %s data for playback type %s with id: %d", - common::convertMediaSourceType(mediaSourceType), toString(playbackType), id); - return false; - } - - auto partition = std::find_if(kPartitions->begin(), kPartitions->end(), [id](const auto &p) { return p.id == id; }); - if (partition == kPartitions->end()) - { - RIALTO_SERVER_LOG_WARN("Failed to clear %s data for playback type %s with id: %d. - partition could not be " - "found", - common::convertMediaSourceType(mediaSourceType), toString(playbackType), id); - return false; - } - std::uint8_t *partitionDataPtr = nullptr; - if (!getDataPtrForPartition(playbackType, id, &partitionDataPtr)) - { - RIALTO_SERVER_LOG_ERROR("Failed to clear %s data for playback type %s with id: %d. - could not get partition " - "data " - "ptr", - common::convertMediaSourceType(mediaSourceType), toString(playbackType), id); - return false; - } - - if (MediaSourceType::VIDEO == mediaSourceType) - { - std::uint8_t *videoData = partitionDataPtr; - memset(videoData, 0x00, partition->dataBufferVideoLen); - return true; - } - if (MediaSourceType::AUDIO == mediaSourceType) - { - std::uint8_t *audioData = partitionDataPtr + partition->dataBufferVideoLen; - memset(audioData, 0x00, partition->dataBufferAudioLen); - return true; - } - if (MediaSourceType::SUBTITLE == mediaSourceType) - { - std::uint8_t *subtitleoData = partitionDataPtr + partition->dataBufferVideoLen + partition->dataBufferAudioLen; - memset(subtitleoData, 0x00, partition->dataBufferSubtitleLen); - return true; - } - - return false; -} - -std::uint32_t SharedMemoryBuffer::getDataOffset(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const -{ - std::uint8_t *buffer = getDataPtr(playbackType, id, mediaSourceType); - if (!buffer) - { - throw std::runtime_error("Buffer not found for playback type " + std::string(toString(playbackType)) + - " with id: " + std::to_string(id)); - } - return buffer - m_dataBuffer; -} - -std::uint32_t SharedMemoryBuffer::getMaxDataLen(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const -{ - const std::vector *kPartitions = getPlaybackTypePartition(playbackType); - if (!kPartitions) - { - RIALTO_SERVER_LOG_ERROR("Cannot get the max data length for playback type %s with id: %d type: %s", - toString(playbackType), id, common::convertMediaSourceType(mediaSourceType)); - return false; - } - - auto partition = std::find_if(kPartitions->begin(), kPartitions->end(), [id](const auto &p) { return p.id == id; }); - if (partition == kPartitions->end()) - { - RIALTO_SERVER_LOG_WARN("Failed to get buffer length for playback type %s with id: %d. type: %s- partition " - "could not be " - "found", - toString(playbackType), id, common::convertMediaSourceType(mediaSourceType)); - return 0; - } - - if (MediaSourceType::VIDEO == mediaSourceType) - { - return partition->dataBufferVideoLen; - } - if (MediaSourceType::AUDIO == mediaSourceType) - { - return partition->dataBufferAudioLen; - } - if (MediaSourceType::SUBTITLE == mediaSourceType) - { - return partition->dataBufferSubtitleLen; - } - - return 0; -} - -std::uint8_t *SharedMemoryBuffer::getDataPtr(MediaPlaybackType playbackType, int id, - const MediaSourceType &mediaSourceType) const -{ - const std::vector *kPartitions = getPlaybackTypePartition(playbackType); - if (!kPartitions) - { - RIALTO_SERVER_LOG_ERROR("Cannot get the buffer offset for playback type %s with id: %d, type: %s", - toString(playbackType), id, common::convertMediaSourceType(mediaSourceType)); - return nullptr; - } - - auto partition = std::find_if(kPartitions->begin(), kPartitions->end(), [id](const auto &p) { return p.id == id; }); - if (partition == kPartitions->end()) - { - RIALTO_SERVER_LOG_WARN("Failed to get buffer offset for playback type %s with id: %d, type: %s. - partition " - "could not be " - "found", - toString(playbackType), id, common::convertMediaSourceType(mediaSourceType)); - return nullptr; - } - std::uint8_t *partitionDataPtr = nullptr; - if (!getDataPtrForPartition(playbackType, id, &partitionDataPtr)) - { - RIALTO_SERVER_LOG_ERROR("Failed to get buffer offset for playback type %s with id: %d. - could not get " - "partition data ptr", - toString(playbackType), id); - return nullptr; - } - - if ((MediaSourceType::VIDEO == mediaSourceType) && (0 != partition->dataBufferVideoLen)) - { - return partitionDataPtr; - } - if ((MediaSourceType::AUDIO == mediaSourceType) && (0 != partition->dataBufferAudioLen)) - { - return partitionDataPtr + partition->dataBufferVideoLen; - } - if ((MediaSourceType::SUBTITLE == mediaSourceType) && (0 != partition->dataBufferSubtitleLen)) - { - return partitionDataPtr + partition->dataBufferVideoLen + partition->dataBufferAudioLen; - } - - return nullptr; -} - -int SharedMemoryBuffer::getFd() const -{ - return m_dataBufferFd; -} - -std::uint32_t SharedMemoryBuffer::getSize() const -{ - return m_dataBufferLen; -} - -std::uint8_t *SharedMemoryBuffer::getBuffer() const -{ - return m_dataBuffer; -} - -size_t SharedMemoryBuffer::calculateBufferSize() const -{ - size_t genericSum = - std::accumulate(m_genericPartitions.begin(), m_genericPartitions.end(), 0, [](size_t sum, const Partition &p) - { return sum + p.dataBufferAudioLen + p.dataBufferVideoLen + p.dataBufferSubtitleLen; }); - size_t webAudioSum = std::accumulate(m_webAudioPartitions.begin(), m_webAudioPartitions.end(), 0, - [](size_t sum, const Partition &p) - { return sum + p.dataBufferAudioLen + p.dataBufferVideoLen; }); - return genericSum + webAudioSum; -} - -bool SharedMemoryBuffer::getDataPtrForPartition(MediaPlaybackType playbackType, int id, std::uint8_t **ptr) const -{ - std::uint8_t *result = m_dataBuffer; - - for (const auto &partition : m_genericPartitions) - { - if ((MediaPlaybackType::GENERIC == playbackType) && (partition.id == id)) - { - *ptr = result; - return true; - } - result += (partition.dataBufferVideoLen + partition.dataBufferAudioLen + partition.dataBufferSubtitleLen); - } - - for (const auto &partition : m_webAudioPartitions) - { - if ((MediaPlaybackType::WEB_AUDIO == playbackType) && (partition.id == id)) - { - *ptr = result; - return true; - } - result += (partition.dataBufferVideoLen + partition.dataBufferAudioLen + partition.dataBufferSubtitleLen); - } - - RIALTO_SERVER_LOG_ERROR("Could not find the data ptr for playback type %s with id: %d", toString(playbackType), id); - return false; -} -const std::vector * -SharedMemoryBuffer::getPlaybackTypePartition(MediaPlaybackType playbackType) const -{ - if (firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::GENERIC == playbackType) - { - return &m_genericPartitions; - } - else if (firebolt::rialto::server::ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO == playbackType) - { - return &m_webAudioPartitions; - } - else - { - RIALTO_SERVER_LOG_ERROR("Invalid playback type"); - return nullptr; - } -} - -std::vector *SharedMemoryBuffer::getPlaybackTypePartition(MediaPlaybackType playbackType) -{ - return const_cast *>( - const_cast(this)->getPlaybackTypePartition(playbackType)); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/TextTrackAccessor.cpp b/middleware/rialto-client/media/server/main/source/TextTrackAccessor.cpp deleted file mode 100644 index a04b8c9c5..000000000 --- a/middleware/rialto-client/media/server/main/source/TextTrackAccessor.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "TextTrackAccessor.h" - -#include -#include -#include - -namespace firebolt::rialto::server -{ -ITextTrackAccessorFactory &ITextTrackAccessorFactory::getFactory() -{ - static TextTrackAccessorFactory factory; - return factory; -} - -std::shared_ptr TextTrackAccessorFactory::getTextTrackAccessor() const -try -{ - static std::shared_ptr textTrackAccessor{ - std::make_shared(firebolt::rialto::wrappers::ITextTrackPluginWrapperFactory::getFactory() - ->getTextTrackPluginWrapper(), - firebolt::rialto::wrappers::IThunderWrapperFactory::getFactory() - ->getThunderWrapper())}; - - return textTrackAccessor; -} -catch (const std::exception &e) -{ - return nullptr; -} - -TextTrackAccessor::TextTrackAccessor( - const std::shared_ptr &textTrackPluginWrapper, - const std::shared_ptr &thunderWrapper) - : m_textTrackPluginWrapper{textTrackPluginWrapper}, m_thunderWrapper{thunderWrapper} -{ - if (!createTextTrackControlInterface()) - { - RIALTO_SERVER_LOG_ERROR("Failed to create TextTrack interfaces"); - throw std::runtime_error("Failed to create TextTrack interfaces"); - } -} - -TextTrackAccessor::~TextTrackAccessor() {} - -std::optional TextTrackAccessor::openSession(const std::string &displayName) -{ - uint32_t sessionId = {}; - uint32_t result = m_textTrackWrapper->openSession(displayName, sessionId); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_MIL("TextTrack session %u created with display '%s'", sessionId, displayName.c_str()); - return sessionId; - } - - RIALTO_SERVER_LOG_ERROR("Failed to create TextTrack session with display '%s'; error '%s'", displayName.c_str(), - m_thunderWrapper->errorToString(result)); - return std::nullopt; -} - -bool TextTrackAccessor::closeSession(uint32_t sessionId) -{ - uint32_t result = m_textTrackWrapper->closeSession(sessionId); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_MIL("TextTrack session %u closed", sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to close TextTrack session %u; error %s", sessionId, - m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::pause(uint32_t sessionId) -{ - uint32_t result = m_textTrackWrapper->pauseSession(sessionId); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_INFO("TextTrack session %u paused", sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to pause TextTrack session %u; error %s", sessionId, - m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::play(uint32_t sessionId) -{ - uint32_t result = m_textTrackWrapper->resumeSession(sessionId); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_INFO("TextTrack session %u resumed", sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to resume TextTrack session %u; error %s", sessionId, - m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::mute(uint32_t sessionId, bool mute) -{ - if (mute) - { - uint32_t result = m_textTrackWrapper->muteSession(sessionId); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_INFO("TextTrack session %u muted", sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to mute TextTrack session %u; error %s", sessionId, - m_thunderWrapper->errorToString(result)); - } - else - { - uint32_t result = m_textTrackWrapper->unmuteSession(sessionId); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_INFO("TextTrack session %u unmuted", sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to unmute TextTrack session %u; error %s", sessionId, - m_thunderWrapper->errorToString(result)); - } - - return false; -} - -bool TextTrackAccessor::setPosition(uint32_t sessionId, uint64_t mediaTimestampMs) -{ - uint32_t result = m_textTrackWrapper->sendSessionTimestamp(sessionId, mediaTimestampMs); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_INFO("TextTrack session %u set position to %" PRIu64, sessionId, mediaTimestampMs); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to set position of TextTrack session %u to %" PRIu64 "; error %s", sessionId, - mediaTimestampMs, m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::sendData(uint32_t sessionId, const std::string &data, DataType datatype, int64_t displayOffsetMs) -{ - firebolt::rialto::wrappers::ITextTrackWrapper::DataType wrapperDataType{}; - if (datatype == DataType::WebVTT) - { - wrapperDataType = firebolt::rialto::wrappers::ITextTrackWrapper::DataType::WEBVTT; - } - else if (datatype == DataType::TTML) - { - wrapperDataType = firebolt::rialto::wrappers::ITextTrackWrapper::DataType::TTML; - } - else if (datatype == DataType::CC) - { - RIALTO_SERVER_LOG_WARN("Data received for ClosedCaptions. It should not happen."); - return false; - } - else - { - RIALTO_SERVER_LOG_ERROR("Unknown data type"); - return false; - } - - const uint32_t result = m_textTrackWrapper->sendSessionData(sessionId, wrapperDataType, displayOffsetMs, data); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_DEBUG("Sending data to TextTrack session %u was successful; size %zu", sessionId, data.size()); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to send data to TextTrack session %u; error %s", sessionId, - m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::createTextTrackControlInterface() -{ - if (!m_textTrackPluginWrapper) - { - RIALTO_SERVER_LOG_ERROR("TextTrackPlugin is null!"); - return false; - } - - uint32_t openResult = m_textTrackPluginWrapper->open(); - - if (m_thunderWrapper->isSuccessful(openResult)) - { - if (m_textTrackPluginWrapper->isOperational()) - { - m_textTrackWrapper = m_textTrackPluginWrapper->interface(); - if (m_textTrackWrapper) - { - RIALTO_SERVER_LOG_INFO("Created TextTrack interface"); - return true; - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to create TextTrack interface"); - } - } - else - { - RIALTO_SERVER_LOG_ERROR("TextTrack plugin is NOT operational"); - } - } - else - { - RIALTO_SERVER_LOG_ERROR("Failed to open TextTrack plugin; error '%s'", - m_thunderWrapper->errorToString(openResult)); - } - - return false; -} - -bool TextTrackAccessor::setSessionWebVTTSelection(uint32_t sessionId) -{ - uint32_t result = m_textTrackWrapper->setSessionWebVTTSelection(sessionId); - - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_INFO("Setting WebVTT selection for session %u was successful", sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to set WebVTT selection for session %u; error %s", sessionId, - m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::setSessionTTMLSelection(uint32_t sessionId) -{ - uint32_t result = m_textTrackWrapper->setSessionTTMLSelection(sessionId); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_INFO("Setting TTML selection for session %u was successful", sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to set TTML selection for session %u; error %s", sessionId, - m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::setSessionCCSelection(uint32_t sessionId, const std::string &service) -{ - uint32_t result = m_textTrackWrapper->setSessionClosedCaptionsService(sessionId, service); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_INFO("Setting CC selection service '%s' for session %u was successful", service.c_str(), - sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to set CC selection service '%s' for session %u; error %s", service.c_str(), - sessionId, m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::resetSession(uint32_t sessionId) -{ - uint32_t result = m_textTrackWrapper->resetSession(sessionId); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_MIL("Resseting session %u was successful", sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to reset session %u; error %s", sessionId, m_thunderWrapper->errorToString(result)); - return false; -} - -bool TextTrackAccessor::associateVideoDecoder(uint32_t sessionId, const std::string &videoDecoder) -{ - uint32_t result = m_textTrackWrapper->associateVideoDecoder(sessionId, videoDecoder); - if (m_thunderWrapper->isSuccessful(result)) - { - RIALTO_SERVER_LOG_MIL("Associating video decoder '%s' with session %u was successful", videoDecoder.c_str(), - sessionId); - return true; - } - - RIALTO_SERVER_LOG_ERROR("Failed to associate video decoder '%s' with session %u; error %s", videoDecoder.c_str(), - sessionId, m_thunderWrapper->errorToString(result)); - return false; -} - -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/TextTrackSession.cpp b/middleware/rialto-client/media/server/main/source/TextTrackSession.cpp deleted file mode 100644 index fe0f45d46..000000000 --- a/middleware/rialto-client/media/server/main/source/TextTrackSession.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "TextTrackSession.h" -#include "ITextTrackAccessor.h" -#include "RialtoServerLogging.h" -#include - -namespace firebolt::rialto::server -{ -ITextTrackSessionFactory &ITextTrackSessionFactory::getFactory() -{ - static TextTrackSessionFactory factory; - return factory; -} - -std::unique_ptr TextTrackSessionFactory::createTextTrackSession(const std::string &display) const -{ - return std::make_unique(display, ITextTrackAccessorFactory::getFactory()); -} - -TextTrackSession::TextTrackSession(const std::string &displayName, - const ITextTrackAccessorFactory &textTrackAccessorFactory) -{ - m_textTrackAccessor = textTrackAccessorFactory.getTextTrackAccessor(); - if (!m_textTrackAccessor) - { - RIALTO_SERVER_LOG_ERROR("Failed to get TextTrackAccessor"); - throw std::runtime_error("Failed to get TextTrackAccessor"); - } - - std::optional sessionId = m_textTrackAccessor->openSession(displayName); - if (!sessionId) - { - RIALTO_SERVER_LOG_ERROR("Failed to create TextTrack session"); - throw std::runtime_error("Failed to create TextTrack session"); - } - - m_sessionId = sessionId.value(); -} - -TextTrackSession::~TextTrackSession() -{ - m_textTrackAccessor->closeSession(m_sessionId); -} - -bool TextTrackSession::resetSession(bool isMuted) -{ - // There is no direct way to clear TextTrack's data. The only option is to reset the session, but that also resets - // the data type and mute values - if (!m_textTrackAccessor->resetSession(m_sessionId)) - { - return false; - } - - bool wasDataTypeSelected = false; - if (m_dataType == ITextTrackAccessor::DataType::WebVTT) - { - wasDataTypeSelected = setSessionWebVTTSelection(); - } - else if (m_dataType == ITextTrackAccessor::DataType::TTML) - { - wasDataTypeSelected = setSessionTTMLSelection(); - } - else if (m_dataType == ITextTrackAccessor::DataType::CC) - { - if (m_ccService.has_value()) - { - wasDataTypeSelected = setSessionCCSelection(m_ccService.value()); - if (m_videoDecoderId.has_value()) - { - wasDataTypeSelected = associateVideoDecoder(m_videoDecoderId.value()); - } - } - else - { - RIALTO_SERVER_LOG_ERROR("CC service not set"); - return false; - } - } - - if (!wasDataTypeSelected) - { - return false; - } - - // changing the data type resets the mute value in TextTrack to its default (false), so we need to set mute - // after selecting the data type - return mute(isMuted); -} - -bool TextTrackSession::pause() -{ - return m_textTrackAccessor->pause(m_sessionId); -} - -bool TextTrackSession::play() -{ - return m_textTrackAccessor->play(m_sessionId); -} - -bool TextTrackSession::mute(bool mute) -{ - return m_textTrackAccessor->mute(m_sessionId, mute); -} - -bool TextTrackSession::setPosition(uint64_t mediaTimestampMs) -{ - return m_textTrackAccessor->setPosition(m_sessionId, mediaTimestampMs); -} - -bool TextTrackSession::sendData(const std::string &data, int64_t displayOffsetMs) -{ - return m_textTrackAccessor->sendData(m_sessionId, data, m_dataType, displayOffsetMs); -} - -bool TextTrackSession::setSessionWebVTTSelection() -{ - m_dataType = ITextTrackAccessor::DataType::WebVTT; - m_ccService = std::optional(); - return m_textTrackAccessor->setSessionWebVTTSelection(m_sessionId); -} - -bool TextTrackSession::setSessionTTMLSelection() -{ - m_dataType = ITextTrackAccessor::DataType::TTML; - m_ccService = std::optional(); - return m_textTrackAccessor->setSessionTTMLSelection(m_sessionId); -} - -bool TextTrackSession::setSessionCCSelection(const std::string &service) -{ - m_dataType = ITextTrackAccessor::DataType::CC; - m_ccService = service; - return m_textTrackAccessor->setSessionCCSelection(m_sessionId, service); -} - -bool TextTrackSession::associateVideoDecoder(uint64_t decoderId) -{ - m_videoDecoderId = decoderId; - std::string decoderIdStr = std::to_string(decoderId); - return m_textTrackAccessor->associateVideoDecoder(m_sessionId, decoderIdStr); -} - -bool TextTrackSession::isClosedCaptions() const -{ - return m_dataType == ITextTrackAccessor::DataType::CC; -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/main/source/WebAudioPlayerServerInternal.cpp b/middleware/rialto-client/media/server/main/source/WebAudioPlayerServerInternal.cpp deleted file mode 100644 index ae383012d..000000000 --- a/middleware/rialto-client/media/server/main/source/WebAudioPlayerServerInternal.cpp +++ /dev/null @@ -1,577 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "RialtoServerLogging.h" -#include "WebAudioPlayerServerInternal.h" - -namespace -{ -constexpr uint32_t kPreferredFrames{640}; -constexpr std::chrono::milliseconds kWriteDataTimeMs{100}; -} // namespace - -namespace firebolt::rialto -{ -std::shared_ptr IWebAudioPlayerFactory::createFactory() -{ - return server::IWebAudioPlayerServerInternalFactory::createFactory(); -} -}; // namespace firebolt::rialto - -namespace firebolt::rialto::server -{ -std::shared_ptr IWebAudioPlayerServerInternalFactory::createFactory() -{ - std::shared_ptr factory; - - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player factory, reason: %s", e.what()); - } - - return factory; -} - -std::unique_ptr -WebAudioPlayerServerInternalFactory::createWebAudioPlayer(std::weak_ptr client, - const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config) const -{ - RIALTO_SERVER_LOG_ERROR( - "This function can't be used by rialto server. Please use createWebAudioPlayerServerInternal"); - return nullptr; -} - -std::unique_ptr WebAudioPlayerServerInternalFactory::createWebAudioPlayerServerInternal( - std::weak_ptr client, const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config, const std::shared_ptr &shmBuffer, int handle, - const std::shared_ptr &mainThreadFactory, - const std::shared_ptr &gstPlayerFactory, - std::weak_ptr timerFactory) const -{ - std::unique_ptr webAudioPlayer; - try - { - webAudioPlayer = std::make_unique(client, audioMimeType, priority, config, - shmBuffer, handle, mainThreadFactory, - gstPlayerFactory, timerFactory); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the web audio player, reason: %s", e.what()); - } - - return webAudioPlayer; -} - -WebAudioPlayerServerInternal::WebAudioPlayerServerInternal( - std::weak_ptr client, const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr webAudioConfig, const std::shared_ptr &shmBuffer, - int handle, const std::shared_ptr &mainThreadFactory, - const std::shared_ptr &gstPlayerFactory, std::weak_ptr timerFactory) - : m_webAudioPlayerClient(client), m_shmBuffer{shmBuffer}, m_priority{priority}, m_shmId{handle}, m_shmPtr{nullptr}, - m_partitionOffset{0}, m_maxDataLength{0}, m_availableBuffer{}, m_expectWriteBuffer{false}, - m_timerFactory{timerFactory}, m_bytesPerFrame{0}, m_isEosRequested{false} -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (audioMimeType == "audio/x-raw") - { - std::shared_ptr kConfig = webAudioConfig.lock(); - if (kConfig == nullptr) - { - throw std::runtime_error("Config is null for 'audio/x-raw'"); - } - m_bytesPerFrame = kConfig->pcm.channels * (kConfig->pcm.sampleSize / CHAR_BIT); - if (m_bytesPerFrame == 0) - { - throw std::runtime_error("Bytes per frame cannot be 0, channels " + std::to_string(kConfig->pcm.channels) + - ", sampleSize " + std::to_string(kConfig->pcm.sampleSize)); - } - } - else - { - throw std::runtime_error("Mimetype '" + audioMimeType + "' not supported"); - } - - m_mainThread = mainThreadFactory->getMainThread(); - if (!m_mainThread) - { - throw std::runtime_error("Failed to get the main thread"); - } - m_mainThreadClientId = m_mainThread->registerClient(); - - bool result = false; - auto task = [&]() { result = initWebAudioPlayerInternal(audioMimeType, webAudioConfig, gstPlayerFactory); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - if (!result) - { - throw std::runtime_error("WebAudioPlayerServerInternal construction failed"); - } -} - -bool WebAudioPlayerServerInternal::initWebAudioPlayerInternal( - const std::string &audioMimeType, std::weak_ptr config, - const std::shared_ptr &gstPlayerFactory) -{ - if (!m_shmBuffer->mapPartition(ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO, m_shmId)) - { - RIALTO_SERVER_LOG_ERROR("Unable to map shm partition"); - return false; - } - - if (!(m_shmPtr = m_shmBuffer->getBuffer())) - { - RIALTO_SERVER_LOG_ERROR("Failed to get the data pointer for the shared memory"); - return false; - } - - try - { - m_partitionOffset = m_shmBuffer->getDataOffset(ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO, m_shmId, - MediaSourceType::AUDIO); - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("Failed to get the data pointer of the partition"); - return false; - } - - if (!(m_maxDataLength = m_shmBuffer->getMaxDataLen(ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO, m_shmId, - MediaSourceType::AUDIO))) - { - RIALTO_SERVER_LOG_ERROR("Failed to get the length of the partition"); - return false; - } - - if (!initGstWebAudioPlayer(audioMimeType, config, gstPlayerFactory)) - { - RIALTO_SERVER_LOG_ERROR("Failed to initalise the GstPlayer"); - return false; - } - - // Set the available bytes - m_availableBuffer.lengthMain = m_maxDataLength; - m_availableBuffer.offsetMain = m_partitionOffset; - m_availableBuffer.offsetWrap = m_partitionOffset; - - return true; -} - -WebAudioPlayerServerInternal::~WebAudioPlayerServerInternal() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() - { - if (m_writeDataTimer && (m_writeDataTimer->isActive())) - { - m_writeDataTimer->cancel(); - } - - if (!m_shmBuffer->unmapPartition(ISharedMemoryBuffer::MediaPlaybackType::WEB_AUDIO, m_shmId)) - { - RIALTO_SERVER_LOG_ERROR("Unable to unmap shm partition"); - } - - m_shmBuffer.reset(); - m_mainThread->unregisterClient(m_mainThreadClientId); - }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} - -bool WebAudioPlayerServerInternal::play() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() { m_gstPlayer->play(); }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); - - return true; -} - -bool WebAudioPlayerServerInternal::pause() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() { m_gstPlayer->pause(); }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); - - return true; -} - -bool WebAudioPlayerServerInternal::setEos() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() - { - if (0 != getQueuedFramesInShm()) - { - m_isEosRequested = true; - } - else - { - m_gstPlayer->setEos(); - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); - - return true; -} - -bool WebAudioPlayerServerInternal::getBufferAvailable(uint32_t &availableFrames, - std::shared_ptr &webAudioShmInfo) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - if (!webAudioShmInfo) - { - RIALTO_SERVER_LOG_ERROR("WebAudioShmInfo is null"); - return false; - } - - auto task = [&]() - { - *webAudioShmInfo = m_availableBuffer; - availableFrames = (m_availableBuffer.lengthMain + m_availableBuffer.lengthWrap) / m_bytesPerFrame; - - // A new getBufferAvailable shall overwrite the previous if writeBuffer is not called inbetween - m_expectWriteBuffer = true; - }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - - return true; -} - -bool WebAudioPlayerServerInternal::getBufferDelay(uint32_t &delayFrames) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool status = false; - auto task = [&]() - { - // Gstreamer returns a uint64, so check the value first - uint64_t queuedFrames = (m_gstPlayer->getQueuedBytes() / m_bytesPerFrame) + getQueuedFramesInShm(); - if (queuedFrames > std::numeric_limits::max()) - { - RIALTO_SERVER_LOG_ERROR("Queued frames are larger than the max uint32_t"); - } - else - { - delayFrames = static_cast(queuedFrames); - status = true; - } - }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - return status; -} - -bool WebAudioPlayerServerInternal::writeBuffer(const uint32_t numberOfFrames, void *data) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result = false; - auto task = [&]() - { - // data can be ignored, the frames should be written to the shared memory - result = writeBufferInternal(numberOfFrames); - }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - - return result; -} - -bool WebAudioPlayerServerInternal::writeBufferInternal(const uint32_t numberOfFrames) -{ - if (!m_expectWriteBuffer) - { - RIALTO_SERVER_LOG_ERROR("No getBufferAvailable to match with this writeBuffer call"); - return false; - } - m_expectWriteBuffer = false; - - // Cancel timer - if (m_writeDataTimer && (m_writeDataTimer->isActive())) - { - m_writeDataTimer->cancel(); - m_writeDataTimer = nullptr; - } - - // Write stored frames first - uint32_t numberOfBytesToWrite = numberOfFrames * m_bytesPerFrame; - if (!writeStoredBuffers()) - { - // Update the available buffer with the new data that will not be written to gst - updateAvailableBuffer(numberOfBytesToWrite, 0); - m_writeDataTimer = - m_timerFactory->createTimer(kWriteDataTimeMs, - std::bind(&WebAudioPlayerServerInternal::handleWriteDataTimer, this)); - return true; - } - - if (0 == numberOfFrames) - { - // No frames to write to gst - return true; - } - - // Write new frames - uint8_t *mainPtr = m_shmPtr + m_availableBuffer.offsetMain; - uint8_t *wrapPtr = m_shmPtr + m_availableBuffer.offsetWrap; - uint32_t mainLength = 0; - uint32_t wrapLength = 0; - if (numberOfBytesToWrite <= m_availableBuffer.lengthMain) - { - mainLength = numberOfBytesToWrite; - } - else - { - mainLength = m_availableBuffer.lengthMain; - wrapLength = numberOfBytesToWrite - mainLength; - } - - uint32_t newBytesWritten = m_gstPlayer->writeBuffer(mainPtr, mainLength, wrapPtr, wrapLength); - updateAvailableBuffer(numberOfBytesToWrite, newBytesWritten); - if (newBytesWritten != numberOfBytesToWrite) - { - m_writeDataTimer = - m_timerFactory->createTimer(kWriteDataTimeMs, - std::bind(&WebAudioPlayerServerInternal::handleWriteDataTimer, this)); - } - - return true; -} - -bool WebAudioPlayerServerInternal::writeStoredBuffers() -{ - uint8_t *mainPtr = nullptr; - uint32_t mainLength = 0; - uint8_t *wrapPtr = nullptr; - uint32_t wrapLength = 0; - - if (m_availableBuffer.lengthWrap + m_availableBuffer.lengthMain == m_maxDataLength) - { - // No data stored - return true; - } - else if (m_availableBuffer.lengthWrap != 0) - { - // Data stored in the shared memory has not wrapped, data only stored in the middle of the shared memory region - uint32_t startOfDataOffset = m_availableBuffer.offsetWrap + m_availableBuffer.lengthWrap; - mainPtr = m_shmPtr + startOfDataOffset; - mainLength = m_availableBuffer.offsetMain - startOfDataOffset; - } - else - { - // Data stored in the shared memory has wrapped, data stored at the end and start of the shared memory region - uint32_t startOfDataOffset = m_availableBuffer.offsetMain + m_availableBuffer.lengthMain; - mainPtr = m_shmPtr + startOfDataOffset; - mainLength = m_maxDataLength - (startOfDataOffset - m_partitionOffset); - // Wrapped data stored at the start of the shared memory region up to where the availableBuffer starts - wrapPtr = m_shmPtr + m_partitionOffset; - wrapLength = m_availableBuffer.offsetMain - m_partitionOffset; - } - - uint32_t storedBytesWritten = m_gstPlayer->writeBuffer(mainPtr, mainLength, wrapPtr, wrapLength); - - // Update available buffer with the bytes written to gst. - // Bytes written to shm is 0 becuase they have already been handled. - updateAvailableBuffer(0, storedBytesWritten); - - if (storedBytesWritten == mainLength + wrapLength) - { - // All data written to gstreamer - if (m_isEosRequested) - { - m_gstPlayer->setEos(); - m_isEosRequested = false; - } - return true; - } - - return false; -} - -void WebAudioPlayerServerInternal::updateAvailableBuffer(uint32_t bytesWrittenToShm, uint32_t bytesWrittenToGst) -{ - if (bytesWrittenToShm <= m_availableBuffer.lengthMain) - { - // Data written to the shared memory has not wrapped - uint32_t offetRelativeToPartition = m_availableBuffer.offsetMain - m_partitionOffset; - uint32_t storedDataLengthAtEndOfShm = m_maxDataLength - (offetRelativeToPartition + m_availableBuffer.lengthMain); - - m_availableBuffer.offsetMain = m_availableBuffer.offsetMain + bytesWrittenToShm; - if (bytesWrittenToGst <= storedDataLengthAtEndOfShm) - { - // Data written to gst has not wrapped, data written is taken from the main buffer only - m_availableBuffer.lengthMain = m_availableBuffer.lengthMain - bytesWrittenToShm + bytesWrittenToGst; - } - else - { - // Data written to gst has wrapped, data written is taken from the main buffer and wrapped buffer - m_availableBuffer.lengthMain = m_availableBuffer.lengthMain - bytesWrittenToShm + storedDataLengthAtEndOfShm; - m_availableBuffer.lengthWrap = m_availableBuffer.lengthWrap + - (bytesWrittenToGst - storedDataLengthAtEndOfShm); - } - } - else - { - // Data written to the shared memory has wrapped, available buffer should now point to where the wrapped buffer was - uint32_t newDataLengthAtEndOfShm = m_availableBuffer.lengthMain; - - m_availableBuffer.offsetMain = m_availableBuffer.offsetWrap + (bytesWrittenToShm - m_availableBuffer.lengthMain); - uint32_t newOffetRelativeToPartition = m_availableBuffer.offsetMain - m_partitionOffset; - if (bytesWrittenToGst <= m_availableBuffer.lengthMain) - { - // Data written to gstreamer has not wrapped, data written is taken from the main buffer only - m_availableBuffer.lengthMain = (m_availableBuffer.lengthWrap - newOffetRelativeToPartition) + - bytesWrittenToGst; - m_availableBuffer.lengthWrap = 0; - } - else - { - // Data written to gstreamer has wrapped, data written is taken from the main buffer and wrapped buffer - m_availableBuffer.lengthMain = m_maxDataLength - newOffetRelativeToPartition; - m_availableBuffer.lengthWrap = bytesWrittenToGst - newDataLengthAtEndOfShm; - } - } -} - -bool WebAudioPlayerServerInternal::getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, - bool &supportDeferredPlay) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - // Can be called from any thread - maximumFrames = m_maxDataLength / m_bytesPerFrame; - preferredFrames = std::min(kPreferredFrames, maximumFrames); - supportDeferredPlay = true; - - return true; -} - -bool WebAudioPlayerServerInternal::setVolume(double volume) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, volume]() { m_gstPlayer->setVolume(volume); }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); - - return true; -} - -bool WebAudioPlayerServerInternal::getVolume(double &volume) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - bool result = false; - auto task = [&]() { result = m_gstPlayer->getVolume(volume); }; - - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); - - return result; -} - -std::weak_ptr WebAudioPlayerServerInternal::getClient() -{ - return m_webAudioPlayerClient; -} - -void WebAudioPlayerServerInternal::notifyState(WebAudioPlayerState state) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&, state]() - { - if (m_webAudioPlayerClient) - { - m_webAudioPlayerClient->notifyState(state); - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -bool WebAudioPlayerServerInternal::initGstWebAudioPlayer(const std::string &audioMimeType, - std::weak_ptr config, - const std::shared_ptr &gstPlayerFactory) -{ - m_gstPlayer = gstPlayerFactory->createGstWebAudioPlayer(this, m_priority); - if (!m_gstPlayer) - { - RIALTO_SERVER_LOG_ERROR("Failed to load gstreamer player"); - return false; - } - - m_gstPlayer->setCaps(audioMimeType, config); - - return true; -} - -void WebAudioPlayerServerInternal::handleWriteDataTimer() -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() - { - if (!writeStoredBuffers()) - { - // Not all data was written to gstreamer, restart the timer - m_writeDataTimer = - m_timerFactory->createTimer(kWriteDataTimeMs, - std::bind(&WebAudioPlayerServerInternal::handleWriteDataTimer, this)); - } - else - { - m_writeDataTimer = nullptr; - } - }; - - m_mainThread->enqueueTask(m_mainThreadClientId, task); -} - -uint32_t WebAudioPlayerServerInternal::getQueuedFramesInShm() -{ - return (m_maxDataLength - (m_availableBuffer.lengthMain + m_availableBuffer.lengthWrap)) / m_bytesPerFrame; -} - -void WebAudioPlayerServerInternal::ping(std::unique_ptr &&heartbeatHandler) -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); - - auto task = [&]() { m_gstPlayer->ping(std::move(heartbeatHandler)); }; - m_mainThread->enqueueTaskAndWait(m_mainThreadClientId, task); -} -}; // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/service/CMakeLists.txt b/middleware/rialto-client/media/server/service/CMakeLists.txt deleted file mode 100644 index bfd31be96..000000000 --- a/middleware/rialto-client/media/server/service/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2022 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Find includes in corresponding build directories -set( CMAKE_INCLUDE_CURRENT_DIR ON ) -add_library ( - RialtoServerService STATIC - - source/ApplicationSessionServer.cpp - source/PlaybackService.cpp - source/CdmService.cpp - source/ControlService.cpp - source/SessionServerManager.cpp - source/MediaPipelineService.cpp - source/WebAudioPlayerService.cpp -) -set_target_properties ( - RialtoServerService - PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" POSITION_INDEPENDENT_CODE ON -) -target_include_directories ( - RialtoServerService - - PUBLIC - include - - PRIVATE - $ - $ - $ - $ - $ - $ - ${GStreamerApp_INCLUDE_DIRS} -) -target_link_libraries ( - RialtoServerService - - PRIVATE - RialtoLogging - RialtoServerMain - RialtoServerIpc -) diff --git a/middleware/rialto-client/media/server/service/include/IApplicationSessionServer.h b/middleware/rialto-client/media/server/service/include/IApplicationSessionServer.h deleted file mode 100644 index 875d2e940..000000000 --- a/middleware/rialto-client/media/server/service/include/IApplicationSessionServer.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_I_APPLICATION_SESSION_SERVER_H_ -#define FIREBOLT_RIALTO_SERVER_I_APPLICATION_SESSION_SERVER_H_ - -#include - -namespace firebolt::rialto::server -{ -class IApplicationSessionServer; -class IApplicationSessionServerFactory -{ -public: - virtual ~IApplicationSessionServerFactory() = default; - static std::unique_ptr getFactory(); - virtual std::unique_ptr createApplicationSessionServer() const = 0; -}; - -class IApplicationSessionServer -{ -public: - virtual ~IApplicationSessionServer() = default; - virtual bool init(int argc, char *argv[]) = 0; - virtual void startService() = 0; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_I_APPLICATION_SESSION_SERVER_H_ diff --git a/middleware/rialto-client/media/server/service/include/ICdmService.h b/middleware/rialto-client/media/server/service/include/ICdmService.h deleted file mode 100644 index cd0a491f7..000000000 --- a/middleware/rialto-client/media/server/service/include/ICdmService.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_CDM_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_I_CDM_SERVICE_H_ - -#include "IHeartbeatProcedure.h" -#include "IMediaKeysCapabilities.h" -#include "IMediaKeysServerInternal.h" -#include "MediaCommon.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class ICdmService -{ -public: - ICdmService() = default; - virtual ~ICdmService() = default; - - ICdmService(const ICdmService &) = delete; - ICdmService(ICdmService &&) = delete; - ICdmService &operator=(const ICdmService &) = delete; - ICdmService &operator=(ICdmService &&) = delete; - - virtual bool switchToActive() = 0; - virtual void switchToInactive() = 0; - - virtual bool createMediaKeys(int mediaKeysHandle, std::string keySystem) = 0; - virtual bool destroyMediaKeys(int mediaKeysHandle) = 0; - virtual MediaKeyErrorStatus createKeySession(int mediaKeysHandle, KeySessionType sessionType, - const std::shared_ptr &client, bool isLDL, - int32_t &keySessionId) = 0; - virtual MediaKeyErrorStatus generateRequest(int mediaKeysHandle, int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) = 0; - virtual MediaKeyErrorStatus loadSession(int mediaKeysHandle, int32_t keySessionId) = 0; - virtual MediaKeyErrorStatus updateSession(int mediaKeysHandle, int32_t keySessionId, - const std::vector &responseData) = 0; - virtual MediaKeyErrorStatus closeKeySession(int mediaKeysHandle, int32_t keySessionId) = 0; - virtual MediaKeyErrorStatus removeKeySession(int mediaKeysHandle, int32_t keySessionId) = 0; - virtual MediaKeyErrorStatus getCdmKeySessionId(int mediaKeysHandle, int32_t keySessionId, - std::string &cdmKeySessionId) = 0; - virtual bool containsKey(int mediaKeysHandle, int32_t keySessionId, const std::vector &keyId) = 0; - virtual MediaKeyErrorStatus setDrmHeader(int mediaKeysHandle, int32_t keySessionId, - const std::vector &requestData) = 0; - virtual MediaKeyErrorStatus deleteDrmStore(int mediaKeysHandle) = 0; - virtual MediaKeyErrorStatus deleteKeyStore(int mediaKeysHandle) = 0; - virtual MediaKeyErrorStatus getDrmStoreHash(int mediaKeysHandle, std::vector &drmStoreHash) = 0; - virtual MediaKeyErrorStatus getKeyStoreHash(int mediaKeysHandle, std::vector &keyStoreHash) = 0; - virtual MediaKeyErrorStatus getLdlSessionsLimit(int mediaKeysHandle, uint32_t &ldlLimit) = 0; - virtual MediaKeyErrorStatus getLastDrmError(int mediaKeysHandle, int32_t keySessionId, uint32_t &errorCode) = 0; - virtual MediaKeyErrorStatus getDrmTime(int mediaKeysHandle, uint64_t &drmTime) = 0; - virtual MediaKeyErrorStatus releaseKeySession(int mediaKeysHandle, int32_t keySessionId) = 0; - virtual MediaKeyErrorStatus getMetricSystemData(int mediaKeysHandle, std::vector &buffer) = 0; - - virtual std::vector getSupportedKeySystems() = 0; - virtual bool supportsKeySystem(const std::string &keySystem) = 0; - virtual bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) = 0; - virtual bool isServerCertificateSupported(const std::string &keySystem) = 0; - - virtual void ping(const std::shared_ptr &heartbeatProcedure) = 0; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_CDM_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/include/IControlService.h b/middleware/rialto-client/media/server/service/include/IControlService.h deleted file mode 100644 index 705885123..000000000 --- a/middleware/rialto-client/media/server/service/include/IControlService.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_CONTROL_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_I_CONTROL_SERVICE_H_ - -#include "ControlCommon.h" -#include "IControlClientServerInternal.h" -#include "IHeartbeatProcedure.h" -#include -#include - -namespace firebolt::rialto::server::service -{ -class IControlService -{ -public: - IControlService() = default; - virtual ~IControlService() = default; - - IControlService(const IControlService &) = delete; - IControlService(IControlService &&) = delete; - IControlService &operator=(const IControlService &) = delete; - IControlService &operator=(IControlService &&) = delete; - - virtual void addControl(int controlId, const std::shared_ptr &client) = 0; - virtual void removeControl(int controlId) = 0; - virtual bool ack(int controlId, std::uint32_t id) = 0; - virtual void setApplicationState(const ApplicationState &state) = 0; - virtual bool ping(const std::shared_ptr &heartbeatProcedure) = 0; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_CONTROL_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/include/IMediaPipelineService.h b/middleware/rialto-client/media/server/service/include/IMediaPipelineService.h deleted file mode 100644 index 2c456f1b7..000000000 --- a/middleware/rialto-client/media/server/service/include/IMediaPipelineService.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_MEDIA_PIPELINE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_I_MEDIA_PIPELINE_SERVICE_H_ - -#include "IHeartbeatProcedure.h" -#include "IMediaPipeline.h" -#include "MediaCommon.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class IMediaPipelineService -{ -public: - IMediaPipelineService() = default; - virtual ~IMediaPipelineService() = default; - - IMediaPipelineService(const IMediaPipelineService &) = delete; - IMediaPipelineService(IMediaPipelineService &&) = delete; - IMediaPipelineService &operator=(const IMediaPipelineService &) = delete; - IMediaPipelineService &operator=(IMediaPipelineService &&) = delete; - - virtual bool createSession(int sessionId, const std::shared_ptr &mediaPipelineClient, - std::uint32_t maxWidth, std::uint32_t maxHeight) = 0; - virtual bool destroySession(int sessionId) = 0; - virtual bool load(int sessionId, MediaType type, const std::string &mimeType, const std::string &url) = 0; - virtual bool attachSource(int sessionId, const std::unique_ptr &source) = 0; - virtual bool removeSource(int sessionId, std::int32_t sourceId) = 0; - virtual bool allSourcesAttached(int sessionId) = 0; - virtual bool play(int sessionId) = 0; - virtual bool pause(int sessionId) = 0; - virtual bool stop(int sessionId) = 0; - virtual bool setPlaybackRate(int sessionId, double rate) = 0; - virtual bool setPosition(int sessionId, std::int64_t position) = 0; - virtual bool getPosition(int sessionId, std::int64_t &position) = 0; - virtual bool setImmediateOutput(int sessionId, int32_t sourceId, bool immediateOutput) = 0; - virtual bool getImmediateOutput(int sessionId, int32_t sourceId, bool &immediateOutput) = 0; - virtual bool getStats(int sessionId, int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; - virtual bool setVideoWindow(int sessionId, std::uint32_t x, std::uint32_t y, std::uint32_t width, - std::uint32_t height) = 0; - virtual bool haveData(int sessionId, MediaSourceStatus status, std::uint32_t numFrames, - std::uint32_t needDataRequestId) = 0; - virtual bool renderFrame(int sessionId) = 0; - virtual bool setVolume(int sessionId, double targetVolume, uint32_t volumeDuration, EaseType easeType) = 0; - virtual bool getVolume(int sessionId, double &volume) = 0; - virtual bool setMute(int sessionId, std::int32_t sourceId, bool mute) = 0; - virtual bool getMute(int sessionId, std::int32_t sourceId, bool &mute) = 0; - virtual bool setTextTrackIdentifier(int sessionId, const std::string &textTrackIdentifier) = 0; - virtual bool getTextTrackIdentifier(int sessionId, std::string &textTrackIdentifier) = 0; - virtual bool setLowLatency(int sessionId, bool lowLatency) = 0; - virtual bool setSync(int sessionId, bool sync) = 0; - virtual bool getSync(int sessionId, bool &sync) = 0; - virtual bool setSyncOff(int sessionId, bool syncOff) = 0; - virtual bool setStreamSyncMode(int sessionId, int32_t sourceId, int32_t streamSyncMode) = 0; - virtual bool getStreamSyncMode(int sessionId, int32_t &streamSyncMode) = 0; - virtual bool flush(int sessionId, std::int32_t sourceId, bool resetTime, bool &isAsync) = 0; - virtual bool setSourcePosition(int sessionId, int32_t sourceId, int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) = 0; - virtual bool setSubtitleOffset(int sessionId, int32_t sourceId, int64_t position) = 0; - virtual bool processAudioGap(int sessionId, int64_t position, uint32_t duration, int64_t discontinuityGap, - bool audioAac) = 0; - virtual bool setBufferingLimit(int sessionId, uint32_t limitBufferingMs) = 0; - virtual bool getBufferingLimit(int sessionId, uint32_t &limitBufferingMs) = 0; - virtual bool setUseBuffering(int sessionId, bool useBuffering) = 0; - virtual bool getUseBuffering(int sessionId, bool &useBuffering) = 0; - virtual std::vector getSupportedMimeTypes(MediaSourceType type) = 0; - virtual bool isMimeTypeSupported(const std::string &mimeType) = 0; - virtual std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) = 0; - virtual void ping(const std::shared_ptr &heartbeatProcedure) = 0; - virtual bool switchSource(int sessionId, const std::unique_ptr &source) = 0; - virtual bool isVideoMaster(bool &isVideoMaster) = 0; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_MEDIA_PIPELINE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/include/IPlaybackService.h b/middleware/rialto-client/media/server/service/include/IPlaybackService.h deleted file mode 100644 index 98b99fecc..000000000 --- a/middleware/rialto-client/media/server/service/include/IPlaybackService.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_PLAYBACK_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_I_PLAYBACK_SERVICE_H_ - -#include "IMediaPipelineService.h" -#include "ISharedMemoryBuffer.h" -#include "IWebAudioPlayerService.h" -#include "MediaCommon.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class IPlaybackService -{ -public: - IPlaybackService() = default; - virtual ~IPlaybackService() = default; - - IPlaybackService(const IPlaybackService &) = delete; - IPlaybackService(IPlaybackService &&) = delete; - IPlaybackService &operator=(const IPlaybackService &) = delete; - IPlaybackService &operator=(IPlaybackService &&) = delete; - - virtual bool switchToActive() = 0; - virtual void switchToInactive() = 0; - virtual void setMaxPlaybacks(int maxPlaybacks) = 0; - virtual void setMaxWebAudioPlayers(int maxWebAudio) = 0; - virtual void setClientDisplayName(const std::string &clientDisplayName) const = 0; - virtual void setResourceManagerAppName(const std::string &appName) const = 0; - - virtual bool isActive() const = 0; - virtual bool getSharedMemory(int32_t &fd, uint32_t &size) const = 0; - virtual int getMaxPlaybacks() const = 0; - virtual int getMaxWebAudioPlayers() const = 0; - virtual std::shared_ptr getShmBuffer() const = 0; - virtual IMediaPipelineService &getMediaPipelineService() const = 0; - virtual IWebAudioPlayerService &getWebAudioPlayerService() const = 0; - virtual void ping(const std::shared_ptr &heartbeatProcedure) const = 0; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_PLAYBACK_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/include/ISessionServerManager.h b/middleware/rialto-client/media/server/service/include/ISessionServerManager.h deleted file mode 100644 index 9f3e4beb3..000000000 --- a/middleware/rialto-client/media/server/service/include/ISessionServerManager.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_SESSION_SERVER_MANAGER_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_I_SESSION_SERVER_MANAGER_H_ - -#include "IAckSender.h" -#include "RialtoLogging.h" -#include "SessionServerCommon.h" -#include -#include - -namespace firebolt::rialto::server::service -{ -class ISessionServerManager -{ -public: - ISessionServerManager() = default; - virtual ~ISessionServerManager() = default; - - ISessionServerManager(const ISessionServerManager &) = delete; - ISessionServerManager(ISessionServerManager &&) = delete; - ISessionServerManager &operator=(const ISessionServerManager &) = delete; - ISessionServerManager &operator=(ISessionServerManager &&) = delete; - - virtual bool initialize(int argc, char *argv[]) = 0; - virtual void startService() = 0; - virtual bool configureIpc(const std::string &socketName, unsigned int socketPermissions, - const std::string &socketOwner, const std::string &socketGroup) = 0; - virtual bool configureIpc(int32_t socketFd) = 0; - virtual bool configureServices(const common::SessionServerState &state, - const common::MaxResourceCapabilitites &maxResource, - const std::string &clientDisplayName, const std::string &appName) = 0; - virtual bool setState(const common::SessionServerState &state) = 0; - virtual void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, - RIALTO_DEBUG_LEVEL sessionServerLogLevels, RIALTO_DEBUG_LEVEL ipcLogLevels, - RIALTO_DEBUG_LEVEL serverManagerLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) = 0; - virtual bool ping(std::int32_t id, const std::shared_ptr &ackSender) = 0; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_SESSION_SERVER_MANAGER_H_ diff --git a/middleware/rialto-client/media/server/service/include/IWebAudioPlayerService.h b/middleware/rialto-client/media/server/service/include/IWebAudioPlayerService.h deleted file mode 100644 index 133d4c5d7..000000000 --- a/middleware/rialto-client/media/server/service/include/IWebAudioPlayerService.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_I_WEB_AUDIO_PLAYER_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_I_WEB_AUDIO_PLAYER_SERVICE_H_ - -#include "IHeartbeatProcedure.h" -#include "IWebAudioPlayerClient.h" -#include "MediaCommon.h" -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class IWebAudioPlayerService -{ -public: - IWebAudioPlayerService() = default; - virtual ~IWebAudioPlayerService() = default; - - IWebAudioPlayerService(const IWebAudioPlayerService &) = delete; - IWebAudioPlayerService(IWebAudioPlayerService &&) = delete; - IWebAudioPlayerService &operator=(const IWebAudioPlayerService &) = delete; - IWebAudioPlayerService &operator=(IWebAudioPlayerService &&) = delete; - - virtual bool createWebAudioPlayer(int handle, const std::shared_ptr &webAudioPlayerClient, - const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config) = 0; - virtual bool destroyWebAudioPlayer(int handle) = 0; - virtual bool play(int handle) = 0; - virtual bool pause(int handle) = 0; - virtual bool setEos(int handle) = 0; - virtual bool getBufferAvailable(int handle, uint32_t &availableFrames, - std::shared_ptr &webAudioShmInfo) = 0; - virtual bool getBufferDelay(int handle, uint32_t &delayFrames) = 0; - virtual bool writeBuffer(int handle, const uint32_t numberOfFrames, void *data) = 0; - virtual bool getDeviceInfo(int handle, uint32_t &preferredFrames, uint32_t &maximumFrames, - bool &supportDeferredPlay) = 0; - virtual bool setVolume(int handle, double volume) = 0; - virtual bool getVolume(int handle, double &volume) = 0; - virtual void ping(const std::shared_ptr &heartbeatProcedure) = 0; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_I_WEB_AUDIO_PLAYER_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.cpp b/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.cpp deleted file mode 100644 index b3de0f8cb..000000000 --- a/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ApplicationSessionServer.h" - -namespace firebolt::rialto::server -{ -std::unique_ptr IApplicationSessionServerFactory::getFactory() -{ - return std::make_unique(); -} - -std::unique_ptr ApplicationSessionServerFactory::createApplicationSessionServer() const -{ - return std::make_unique(); -} - -bool ApplicationSessionServer::init(int argc, char *argv[]) -{ - return m_serviceManager.initialize(argc, argv); -} - -void ApplicationSessionServer::startService() -{ - m_serviceManager.startService(); -} -} // namespace firebolt::rialto::server diff --git a/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.h b/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.h deleted file mode 100644 index f9c02020a..000000000 --- a/middleware/rialto-client/media/server/service/source/ApplicationSessionServer.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_APPLICATION_SESSION_SERVER_H_ -#define FIREBOLT_RIALTO_SERVER_APPLICATION_SESSION_SERVER_H_ - -#include "CdmService.h" -#include "ControlService.h" -#include "IApplicationSessionServer.h" -#include "IControlServerInternal.h" -#include "IHeartbeatProcedure.h" -#include "IMediaKeysCapabilities.h" -#include "IMediaKeysServerInternal.h" -#include "IMediaPipelineCapabilities.h" -#include "IMediaPipelineServerInternal.h" -#include "ISharedMemoryBuffer.h" -#include "IWebAudioPlayerServerInternal.h" -#include "IpcFactory.h" -#include "PlaybackService.h" -#include "SessionServerManager.h" -#include - -namespace firebolt::rialto::server -{ -class ApplicationSessionServerFactory : public IApplicationSessionServerFactory -{ -public: - ApplicationSessionServerFactory() = default; - ~ApplicationSessionServerFactory() override = default; - - std::unique_ptr createApplicationSessionServer() const override; -}; - -class ApplicationSessionServer : public IApplicationSessionServer -{ -public: - ApplicationSessionServer() = default; - ~ApplicationSessionServer() override = default; - - bool init(int argc, char *argv[]) override; - void startService() override; - -private: - firebolt::rialto::server::ipc::IpcFactory m_ipcFactory; - firebolt::rialto::server::service::ControlService m_controlService{ - firebolt::rialto::server::IControlServerInternalFactory::createFactory()}; - firebolt::rialto::server::service::CdmService - m_cdmService{firebolt::rialto::server::IMediaKeysServerInternalFactory::createFactory(), - firebolt::rialto::IMediaKeysCapabilitiesFactory::createFactory()}; - firebolt::rialto::server::service::PlaybackService - m_playbackService{firebolt::rialto::server::IMediaPipelineServerInternalFactory::createFactory(), - firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory(), - firebolt::rialto::server::IWebAudioPlayerServerInternalFactory::createFactory(), - firebolt::rialto::server::ISharedMemoryBufferFactory::createFactory(), m_cdmService}; - firebolt::rialto::server::service::SessionServerManager - m_serviceManager{m_ipcFactory, m_playbackService, m_cdmService, m_controlService, - firebolt::rialto::server::IHeartbeatProcedureFactory::createFactory()}; -}; -} // namespace firebolt::rialto::server - -#endif // FIREBOLT_RIALTO_SERVER_APPLICATION_SESSION_SERVER_H_ diff --git a/middleware/rialto-client/media/server/service/source/CdmService.cpp b/middleware/rialto-client/media/server/service/source/CdmService.cpp deleted file mode 100644 index faba4a3fc..000000000 --- a/middleware/rialto-client/media/server/service/source/CdmService.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include - -#include "CdmService.h" -#include "RialtoServerLogging.h" - -namespace firebolt::rialto::server::service -{ -CdmService::CdmService(std::shared_ptr &&mediaKeysFactory, - std::shared_ptr &&mediaKeysCapabilitiesFactory) - : m_mediaKeysFactory{mediaKeysFactory}, m_mediaKeysCapabilitiesFactory{mediaKeysCapabilitiesFactory}, - m_isActive{false} -{ - RIALTO_SERVER_LOG_DEBUG("CdmService is constructed"); -} - -CdmService::~CdmService() -{ - RIALTO_SERVER_LOG_DEBUG("CdmService is destructed"); -} - -bool CdmService::switchToActive() -{ - RIALTO_SERVER_LOG_INFO("Switching SessionServer to Active state."); - m_isActive = true; - return true; -} - -void CdmService::switchToInactive() -{ - RIALTO_SERVER_LOG_INFO("Switching SessionServer to Inactive state. Cleaning resources..."); - m_isActive = false; - - { - std::lock_guard lock{m_mediaKeysMutex}; - m_mediaKeys.clear(); - } -} - -bool CdmService::createMediaKeys(int mediaKeysHandle, std::string keySystem) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to create new media keys handle: %d", mediaKeysHandle); - if (!m_isActive) - { - RIALTO_SERVER_LOG_ERROR("Skip to create media keys handle: %d - Session Server in Inactive state", - mediaKeysHandle); - return false; - } - - { - std::lock_guard lock{m_mediaKeysMutex}; - if (m_mediaKeys.find(mediaKeysHandle) != m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d already exists", mediaKeysHandle); - return false; - } - m_mediaKeys.emplace(std::make_pair(mediaKeysHandle, m_mediaKeysFactory->createMediaKeysServerInternal(keySystem))); - if (!m_mediaKeys.at(mediaKeysHandle)) - { - RIALTO_SERVER_LOG_ERROR("Could not create MediaKeys for media keys handle: %d", mediaKeysHandle); - m_mediaKeys.erase(mediaKeysHandle); - return false; - } - } - - RIALTO_SERVER_LOG_INFO("New media keys handle: %d created", mediaKeysHandle); - return true; -} - -bool CdmService::destroyMediaKeys(int mediaKeysHandle) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to destroy media keys handle: %d", mediaKeysHandle); - - { - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return false; - } - m_mediaKeys.erase(mediaKeysIter); - } - - RIALTO_SERVER_LOG_INFO("Media keys handle: %d destroyed", mediaKeysHandle); - return true; -} - -MediaKeyErrorStatus CdmService::createKeySession(int mediaKeysHandle, KeySessionType sessionType, - const std::shared_ptr &client, bool isLDL, - int32_t &keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to create key session: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - - MediaKeyErrorStatus status = mediaKeysIter->second->createKeySession(sessionType, client, isLDL, keySessionId); - if (MediaKeyErrorStatus::OK == status) - { - if (m_mediaKeysClients.find(keySessionId) != m_mediaKeysClients.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys client for key session: %d already exists", keySessionId); - static_cast(removeKeySessionInternal(mediaKeysHandle, keySessionId)); - return MediaKeyErrorStatus::FAIL; - } - m_mediaKeysClients.emplace(std::make_pair(keySessionId, client)); - } - - return status; -} - -MediaKeyErrorStatus CdmService::generateRequest(int mediaKeysHandle, int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to generate request: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->generateRequest(keySessionId, initDataType, initData); -} - -MediaKeyErrorStatus CdmService::loadSession(int mediaKeysHandle, int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to load session: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->loadSession(keySessionId); -} - -MediaKeyErrorStatus CdmService::updateSession(int mediaKeysHandle, int32_t keySessionId, - const std::vector &responseData) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to update session: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->updateSession(keySessionId, responseData); -} - -MediaKeyErrorStatus CdmService::closeKeySession(int mediaKeysHandle, int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to close key session: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->closeKeySession(keySessionId); -} - -MediaKeyErrorStatus CdmService::removeKeySession(int mediaKeysHandle, int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to remove key session: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - return removeKeySessionInternal(mediaKeysHandle, keySessionId); -} - -MediaKeyErrorStatus CdmService::removeKeySessionInternal(int mediaKeysHandle, int32_t keySessionId) -{ - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - - MediaKeyErrorStatus status = mediaKeysIter->second->removeKeySession(keySessionId); - if (MediaKeyErrorStatus::OK == status) - { - auto mediaKeysClientsIter = m_mediaKeysClients.find(keySessionId); - if (mediaKeysClientsIter != m_mediaKeysClients.end()) - { - m_mediaKeysClients.erase(mediaKeysClientsIter); - } - } - - return status; -} - -MediaKeyErrorStatus CdmService::getCdmKeySessionId(int mediaKeysHandle, int32_t keySessionId, std::string &cdmKeySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to get cdm key session id: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - - MediaKeyErrorStatus status = mediaKeysIter->second->getCdmKeySessionId(keySessionId, cdmKeySessionId); - return status; -} - -bool CdmService::containsKey(int mediaKeysHandle, int32_t keySessionId, const std::vector &keyId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to check if key is present: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return false; - } - - return mediaKeysIter->second->containsKey(keySessionId, keyId); -} - -MediaKeyErrorStatus CdmService::setDrmHeader(int mediaKeysHandle, int32_t keySessionId, - const std::vector &requestData) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to set drm header: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - - return mediaKeysIter->second->setDrmHeader(keySessionId, requestData); -} - -MediaKeyErrorStatus CdmService::deleteDrmStore(int mediaKeysHandle) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to delete drm store: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->deleteDrmStore(); -} - -MediaKeyErrorStatus CdmService::deleteKeyStore(int mediaKeysHandle) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to delete key store: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - - return mediaKeysIter->second->deleteKeyStore(); -} - -MediaKeyErrorStatus CdmService::getDrmStoreHash(int mediaKeysHandle, std::vector &drmStoreHash) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to get drm store hash: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->getDrmStoreHash(drmStoreHash); -} - -MediaKeyErrorStatus CdmService::getKeyStoreHash(int mediaKeysHandle, std::vector &keyStoreHash) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to get key store hash: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->getKeyStoreHash(keyStoreHash); -} - -MediaKeyErrorStatus CdmService::getLdlSessionsLimit(int mediaKeysHandle, uint32_t &ldlLimit) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to get ldl sessions limit: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->getLdlSessionsLimit(ldlLimit); -} - -MediaKeyErrorStatus CdmService::getLastDrmError(int mediaKeysHandle, int32_t keySessionId, uint32_t &errorCode) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to get last drm error: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->getLastDrmError(keySessionId, errorCode); -} - -MediaKeyErrorStatus CdmService::getDrmTime(int mediaKeysHandle, uint64_t &drmTime) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to get drm time: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->getDrmTime(drmTime); -} - -MediaKeyErrorStatus CdmService::releaseKeySession(int mediaKeysHandle, int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to release key session: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->releaseKeySession(keySessionId); -} - -std::vector CdmService::getSupportedKeySystems() -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to getSupportedKeySystems"); - - if (!m_isActive) - { - RIALTO_SERVER_LOG_ERROR("Skip to get supported key systems: Session Server in Inactive state"); - return {}; - } - - auto mediaKeysCapabilities = m_mediaKeysCapabilitiesFactory->getMediaKeysCapabilities(); - if (!mediaKeysCapabilities) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the mediaKeysCapabilities object"); - return {}; - } - return mediaKeysCapabilities->getSupportedKeySystems(); -} - -bool CdmService::supportsKeySystem(const std::string &keySystem) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to supportsKeySystem"); - - if (!m_isActive) - { - RIALTO_SERVER_LOG_ERROR("Skip to get supported key systems: Session Server in Inactive state"); - return false; - } - - auto mediaKeysCapabilities = m_mediaKeysCapabilitiesFactory->getMediaKeysCapabilities(); - if (!mediaKeysCapabilities) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the mediaKeysCapabilities object"); - return false; - } - return mediaKeysCapabilities->supportsKeySystem(keySystem); -} - -bool CdmService::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to getSupportedKeySystemVersion"); - - if (!m_isActive) - { - RIALTO_SERVER_LOG_ERROR("Skip to get supported key systems: Session Server in Inactive state"); - return false; - } - - auto mediaKeysCapabilities = m_mediaKeysCapabilitiesFactory->getMediaKeysCapabilities(); - if (!mediaKeysCapabilities) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the mediaKeysCapabilities object"); - return false; - } - return mediaKeysCapabilities->getSupportedKeySystemVersion(keySystem, version); -} - -bool CdmService::isServerCertificateSupported(const std::string &keySystem) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to isServerCertificateSupported"); - - if (!m_isActive) - { - RIALTO_SERVER_LOG_ERROR("Skip to check if server cert is supported: Session Server in Inactive state"); - return false; - } - - auto mediaKeysCapabilities = m_mediaKeysCapabilitiesFactory->getMediaKeysCapabilities(); - if (!mediaKeysCapabilities) - { - RIALTO_SERVER_LOG_ERROR("Failed to create the mediaKeysCapabilities object"); - return false; - } - return mediaKeysCapabilities->isServerCertificateSupported(keySystem); -} - -MediaKeyErrorStatus CdmService::decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to decrypt, key session id: %d", keySessionId); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), - [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->decrypt(keySessionId, encrypted, caps); -} - -bool CdmService::isPlayreadyKeySystem(int32_t keySessionId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to check if key system is Playready, key session id: %d", keySessionId); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), - [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); - return false; - } - return mediaKeysIter->second->isPlayreadyKeySystem(keySessionId); -} - -MediaKeyErrorStatus CdmService::selectKeyId(int32_t keySessionId, const std::vector &keyId) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to select key id, key session id: %d", keySessionId); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), - [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->selectKeyId(keySessionId, keyId); -} - -void CdmService::incrementSessionIdUsageCounter(int32_t keySessionId) -{ - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), - [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); - return; - } - - mediaKeysIter->second->incrementSessionIdUsageCounter(keySessionId); -} - -void CdmService::decrementSessionIdUsageCounter(int32_t keySessionId) -{ - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = std::find_if(m_mediaKeys.begin(), m_mediaKeys.end(), - [&](const auto &iter) { return iter.second->hasSession(keySessionId); }); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle for mksId: %d does not exists", keySessionId); - return; - } - - mediaKeysIter->second->decrementSessionIdUsageCounter(keySessionId); -} - -void CdmService::ping(const std::shared_ptr &heartbeatProcedure) -{ - std::lock_guard lock{m_mediaKeysMutex}; - for (const auto &mediaKeyPair : m_mediaKeys) - { - auto &mediaKeys = mediaKeyPair.second; - mediaKeys->ping(heartbeatProcedure->createHandler()); - } -} - -MediaKeyErrorStatus CdmService::getMetricSystemData(int mediaKeysHandle, std::vector &buffer) -{ - RIALTO_SERVER_LOG_DEBUG("CdmService requested to get metric system data: %d", mediaKeysHandle); - - std::lock_guard lock{m_mediaKeysMutex}; - auto mediaKeysIter = m_mediaKeys.find(mediaKeysHandle); - if (mediaKeysIter == m_mediaKeys.end()) - { - RIALTO_SERVER_LOG_ERROR("Media keys handle: %d does not exists", mediaKeysHandle); - return MediaKeyErrorStatus::FAIL; - } - return mediaKeysIter->second->getMetricSystemData(buffer); -} -} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/CdmService.h b/middleware/rialto-client/media/server/service/source/CdmService.h deleted file mode 100644 index 32abdc216..000000000 --- a/middleware/rialto-client/media/server/service/source/CdmService.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_CDM_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_CDM_SERVICE_H_ - -#include "ICdmService.h" -#include "IDecryptionService.h" -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class CdmService : public ICdmService, public IDecryptionService -{ -public: - CdmService(std::shared_ptr &&mediaKeysFactory, - std::shared_ptr &&mediaKeysCapabilitiesFactory); - virtual ~CdmService(); - - bool switchToActive() override; - void switchToInactive() override; - - bool createMediaKeys(int mediaKeysHandle, std::string keySystem) override; - bool destroyMediaKeys(int mediaKeysHandle) override; - MediaKeyErrorStatus createKeySession(int mediaKeysHandle, KeySessionType sessionType, - const std::shared_ptr &client, bool isLDL, - int32_t &keySessionId) override; - MediaKeyErrorStatus generateRequest(int mediaKeysHandle, int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) override; - MediaKeyErrorStatus loadSession(int mediaKeysHandle, int32_t keySessionId) override; - MediaKeyErrorStatus updateSession(int mediaKeysHandle, int32_t keySessionId, - const std::vector &responseData) override; - MediaKeyErrorStatus closeKeySession(int mediaKeysHandle, int32_t keySessionId) override; - MediaKeyErrorStatus removeKeySession(int mediaKeysHandle, int32_t keySessionId) override; - MediaKeyErrorStatus getCdmKeySessionId(int mediaKeysHandle, int32_t keySessionId, - std::string &cdmKeySessionId) override; - bool containsKey(int mediaKeysHandle, int32_t keySessionId, const std::vector &keyId) override; - MediaKeyErrorStatus setDrmHeader(int mediaKeysHandle, int32_t keySessionId, - const std::vector &requestData) override; - MediaKeyErrorStatus deleteDrmStore(int mediaKeysHandle) override; - MediaKeyErrorStatus deleteKeyStore(int mediaKeysHandle) override; - MediaKeyErrorStatus getDrmStoreHash(int mediaKeysHandle, std::vector &drmStoreHash) override; - MediaKeyErrorStatus getKeyStoreHash(int mediaKeysHandle, std::vector &keyStoreHash) override; - MediaKeyErrorStatus getLdlSessionsLimit(int mediaKeysHandle, uint32_t &ldlLimit) override; - MediaKeyErrorStatus getLastDrmError(int mediaKeysHandle, int32_t keySessionId, uint32_t &errorCode) override; - MediaKeyErrorStatus getDrmTime(int mediaKeysHandle, uint64_t &drmTime) override; - MediaKeyErrorStatus releaseKeySession(int mediaKeysHandle, int32_t keySessionId) override; - MediaKeyErrorStatus getMetricSystemData(int mediaKeysHandle, std::vector &buffer) override; - - std::vector getSupportedKeySystems() override; - bool supportsKeySystem(const std::string &keySystem) override; - bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) override; - bool isServerCertificateSupported(const std::string &keySystem) override; - MediaKeyErrorStatus decrypt(int32_t keySessionId, GstBuffer *encrypted, GstCaps *caps) override; - bool isPlayreadyKeySystem(int32_t keySessionId) override; - MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) override; - void incrementSessionIdUsageCounter(int32_t keySessionId) override; - void decrementSessionIdUsageCounter(int32_t keySessionId) override; - void ping(const std::shared_ptr &heartbeatProcedure) override; - -private: - std::shared_ptr m_mediaKeysFactory; - std::shared_ptr m_mediaKeysCapabilitiesFactory; - std::atomic m_isActive; - std::map> m_mediaKeys; - std::map> m_mediaKeysClients; - std::mutex m_mediaKeysMutex; - - MediaKeyErrorStatus removeKeySessionInternal(int mediaKeysHandle, int32_t keySessionId); -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_CDM_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/ControlService.cpp b/middleware/rialto-client/media/server/service/source/ControlService.cpp deleted file mode 100644 index 1e25eea24..000000000 --- a/middleware/rialto-client/media/server/service/source/ControlService.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ControlService.h" -#include "IHeartbeatProcedure.h" -#include "RialtoServerLogging.h" -#include - -namespace firebolt::rialto::server::service -{ -ControlService::ControlService(const std::shared_ptr &controlServerInternalFactory) - : m_currentState{ApplicationState::UNKNOWN}, m_controlServerInternalFactory{controlServerInternalFactory} -{ - RIALTO_SERVER_LOG_DEBUG("entry:"); -} - -void ControlService::addControl(int controlId, const std::shared_ptr &client) -{ - RIALTO_SERVER_LOG_INFO("Creating new Control with id: %d", controlId); - auto controlServerInternal{m_controlServerInternalFactory->createControlServerInternal(controlId, client)}; - std::unique_lock lock{m_mutex}; - controlServerInternal->setApplicationState(m_currentState); - m_controls.emplace(controlId, controlServerInternal); -} - -void ControlService::removeControl(int controlId) -{ - RIALTO_SERVER_LOG_INFO("Removing Control with id: %d", controlId); - std::unique_lock lock{m_mutex}; - m_controls.erase(controlId); -} - -bool ControlService::ack(int controlId, std::uint32_t id) -{ - std::unique_lock lock{m_mutex}; - auto controlIter = m_controls.find(controlId); - if (m_controls.end() == controlIter) - { - RIALTO_SERVER_LOG_ERROR("Control with id: %d not found", controlId); - return false; - } - controlIter->second->ack(id); - return true; -} - -void ControlService::setApplicationState(const ApplicationState &state) -{ - std::unique_lock lock{m_mutex}; - m_currentState = state; - for (const auto &control : m_controls) - { - control.second->setApplicationState(state); - } -} - -bool ControlService::ping(const std::shared_ptr &heartbeatProcedure) -{ - std::unique_lock lock{m_mutex}; - for (const auto &control : m_controls) - { - control.second->ping(heartbeatProcedure->createHandler()); - } - return true; -} -} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/ControlService.h b/middleware/rialto-client/media/server/service/source/ControlService.h deleted file mode 100644 index ad5ea7ea8..000000000 --- a/middleware/rialto-client/media/server/service/source/ControlService.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_CONTROL_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_CONTROL_SERVICE_H_ - -#include "IControlServerInternal.h" -#include "IControlService.h" -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class ControlService : public IControlService -{ -public: - explicit ControlService(const std::shared_ptr &controlServerInternalFactory); - ~ControlService() override = default; - - void addControl(int controlId, const std::shared_ptr &client) override; - void removeControl(int controlId) override; - bool ack(int controlId, std::uint32_t id) override; - void setApplicationState(const ApplicationState &state) override; - bool ping(const std::shared_ptr &heartbeatProcedure) override; - -private: - std::mutex m_mutex; - ApplicationState m_currentState; - std::shared_ptr m_controlServerInternalFactory; - std::map> m_controls; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_CONTROL_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/MediaPipelineService.cpp b/middleware/rialto-client/media/server/service/source/MediaPipelineService.cpp deleted file mode 100644 index ad4023747..000000000 --- a/middleware/rialto-client/media/server/service/source/MediaPipelineService.cpp +++ /dev/null @@ -1,671 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaPipelineService.h" -#include "IMediaPipelineServerInternal.h" -#include "RialtoServerLogging.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -MediaPipelineService::MediaPipelineService( - IPlaybackService &playbackService, std::shared_ptr &&mediaPipelineFactory, - std::shared_ptr &&mediaPipelineCapabilitiesFactory, - IDecryptionService &decryptionService) - : m_playbackService{playbackService}, m_mediaPipelineFactory{mediaPipelineFactory}, - m_mediaPipelineCapabilities{mediaPipelineCapabilitiesFactory->createMediaPipelineCapabilities()}, - m_decryptionService{decryptionService} -{ - if (!m_mediaPipelineCapabilities) - { - throw std::runtime_error("Could not create Media Pipeline Capabilities"); - } - - RIALTO_SERVER_LOG_DEBUG("MediaPipelineService is constructed"); -} - -MediaPipelineService::~MediaPipelineService() -{ - RIALTO_SERVER_LOG_DEBUG("MediaPipelineService is destructed"); -} - -void MediaPipelineService::clearMediaPipelines() -{ - std::lock_guard lock{m_mediaPipelineMutex}; - m_mediaPipelines.clear(); -} - -bool MediaPipelineService::createSession(int sessionId, const std::shared_ptr &mediaPipelineClient, - std::uint32_t maxWidth, std::uint32_t maxHeight) -{ - RIALTO_SERVER_LOG_DEBUG("MediaPipelineService requested to create new session with id: %d", sessionId); - if (!m_playbackService.isActive()) - { - RIALTO_SERVER_LOG_ERROR("Skip to create session with id: %d - Session Server in Inactive state", sessionId); - return false; - } - - { - std::lock_guard lock{m_mediaPipelineMutex}; - if (m_mediaPipelines.size() == static_cast(m_playbackService.getMaxPlaybacks())) - { - RIALTO_SERVER_LOG_ERROR("Unable to create a session with id: %d. Max session number reached.", sessionId); - return false; - } - if (m_mediaPipelines.find(sessionId) != m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d already exists", sessionId); - return false; - } - auto shmBuffer = m_playbackService.getShmBuffer(); - m_mediaPipelines.emplace( - std::make_pair(sessionId, - m_mediaPipelineFactory->createMediaPipelineServerInternal(mediaPipelineClient, - VideoRequirements{maxWidth, maxHeight}, - sessionId, shmBuffer, - m_decryptionService))); - if (!m_mediaPipelines.at(sessionId)) - { - RIALTO_SERVER_LOG_ERROR("Could not create MediaPipeline for session with id: %d", sessionId); - m_mediaPipelines.erase(sessionId); - return false; - } - } - - RIALTO_SERVER_LOG_INFO("New session with id: %d created", sessionId); - return true; -} - -bool MediaPipelineService::destroySession(int sessionId) -{ - RIALTO_SERVER_LOG_DEBUG("MediaPipelineService requested to destroy session with id: %d", sessionId); - { - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - m_mediaPipelines.erase(mediaPipelineIter); - } - RIALTO_SERVER_LOG_INFO("Session with id: %d destroyed", sessionId); - return true; -} - -bool MediaPipelineService::load(int sessionId, MediaType type, const std::string &mimeType, const std::string &url) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to load session with id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->load(type, mimeType, url); -} - -bool MediaPipelineService::attachSource(int sessionId, const std::unique_ptr &source) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to attach source, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->attachSource(source); -} - -bool MediaPipelineService::removeSource(int sessionId, std::int32_t sourceId) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to remove source, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->removeSource(sourceId); -} - -bool MediaPipelineService::allSourcesAttached(int sessionId) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService notified that all sources were attached, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->allSourcesAttached(); -} - -bool MediaPipelineService::play(int sessionId) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to play, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->play(); -} - -bool MediaPipelineService::pause(int sessionId) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to pause, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->pause(); -} - -bool MediaPipelineService::stop(int sessionId) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to stop, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->stop(); -} - -bool MediaPipelineService::setPlaybackRate(int sessionId, double rate) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to set playback rate, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->setPlaybackRate(rate); -} - -bool MediaPipelineService::setPosition(int sessionId, std::int64_t position) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to set position, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->setPosition(position); -} - -bool MediaPipelineService::getPosition(int sessionId, std::int64_t &position) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to get position, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->getPosition(position); -} - -bool MediaPipelineService::setImmediateOutput(int sessionId, int32_t sourceId, bool immediateOutput) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to setImmediateOutput, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->setImmediateOutput(sourceId, immediateOutput); -} - -bool MediaPipelineService::getImmediateOutput(int sessionId, int32_t sourceId, bool &immediateOutput) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to getImmediateOutput, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->getImmediateOutput(sourceId, immediateOutput); -} - -bool MediaPipelineService::getStats(int sessionId, int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to get stats, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->getStats(sourceId, renderedFrames, droppedFrames); -} - -bool MediaPipelineService::setVideoWindow(int sessionId, std::uint32_t x, std::uint32_t y, std::uint32_t width, - std::uint32_t height) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to set video window, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->setVideoWindow(x, y, width, height); -} - -bool MediaPipelineService::haveData(int sessionId, MediaSourceStatus status, std::uint32_t numFrames, - std::uint32_t needDataRequestId) -{ - RIALTO_SERVER_LOG_DEBUG("New data available, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->haveData(status, numFrames, needDataRequestId); -} - -bool MediaPipelineService::renderFrame(int sessionId) -{ - RIALTO_SERVER_LOG_DEBUG("Render frame requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->renderFrame(); -} -bool MediaPipelineService::setVolume(int sessionId, double targetVolume, uint32_t volumeDuration, EaseType easeType) -{ - RIALTO_SERVER_LOG_DEBUG("Set volume requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->setVolume(targetVolume, volumeDuration, easeType); -} - -bool MediaPipelineService::getVolume(int sessionId, double &volume) -{ - RIALTO_SERVER_LOG_DEBUG("Get volume requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->getVolume(volume); -} - -bool MediaPipelineService::setMute(int sessionId, std::int32_t sourceId, bool mute) -{ - RIALTO_SERVER_LOG_DEBUG("Set mute requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setMute(sourceId, mute); -} - -bool MediaPipelineService::getMute(int sessionId, std::int32_t sourceId, bool &mute) -{ - RIALTO_SERVER_LOG_DEBUG("Get mute requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->getMute(sourceId, mute); -} - -bool MediaPipelineService::setTextTrackIdentifier(int sessionId, const std::string &textTrackIdentifier) -{ - RIALTO_SERVER_LOG_DEBUG("Set text track identifier requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setTextTrackIdentifier(textTrackIdentifier); -} - -bool MediaPipelineService::getTextTrackIdentifier(int sessionId, std::string &textTrackIdentifier) -{ - RIALTO_SERVER_LOG_DEBUG("Get text track identifier requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->getTextTrackIdentifier(textTrackIdentifier); -} - -bool MediaPipelineService::setLowLatency(int sessionId, bool lowLatency) -{ - RIALTO_SERVER_LOG_DEBUG("Set low latency requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setLowLatency(lowLatency); -} - -bool MediaPipelineService::setSync(int sessionId, bool sync) -{ - RIALTO_SERVER_LOG_DEBUG("Set sync requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setSync(sync); -} - -bool MediaPipelineService::getSync(int sessionId, bool &sync) -{ - RIALTO_SERVER_LOG_DEBUG("Get sync requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->getSync(sync); -} - -bool MediaPipelineService::setSyncOff(int sessionId, bool syncOff) -{ - RIALTO_SERVER_LOG_DEBUG("Set sync off requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setSyncOff(syncOff); -} - -bool MediaPipelineService::setStreamSyncMode(int sessionId, int32_t sourceId, int32_t streamSyncMode) -{ - RIALTO_SERVER_LOG_DEBUG("Set stream sync mode requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setStreamSyncMode(sourceId, streamSyncMode); -} - -bool MediaPipelineService::getStreamSyncMode(int sessionId, int32_t &streamSyncMode) -{ - RIALTO_SERVER_LOG_DEBUG("Get stream sync mode requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->getStreamSyncMode(streamSyncMode); -} - -bool MediaPipelineService::flush(int sessionId, std::int32_t sourceId, bool resetTime, bool &isAsync) -{ - RIALTO_SERVER_LOG_DEBUG("Flush requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->flush(sourceId, resetTime, isAsync); -} - -bool MediaPipelineService::setSourcePosition(int sessionId, int32_t sourceId, int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) -{ - RIALTO_SERVER_LOG_DEBUG("Set Source Position requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition); -} - -bool MediaPipelineService::setSubtitleOffset(int sessionId, int32_t sourceId, int64_t position) -{ - RIALTO_SERVER_LOG_DEBUG("Set Subtitle Offset requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setSubtitleOffset(sourceId, position); -} - -bool MediaPipelineService::processAudioGap(int sessionId, int64_t position, uint32_t duration, int64_t discontinuityGap, - bool audioAac) -{ - RIALTO_SERVER_LOG_DEBUG("Process Audio Gap requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->processAudioGap(position, duration, discontinuityGap, audioAac); -} - -bool MediaPipelineService::setBufferingLimit(int sessionId, uint32_t limitBufferingMs) -{ - RIALTO_SERVER_LOG_DEBUG("Set buffering limit requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setBufferingLimit(limitBufferingMs); -} - -bool MediaPipelineService::getBufferingLimit(int sessionId, uint32_t &limitBufferingMs) -{ - RIALTO_SERVER_LOG_DEBUG("Get buffering limit requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->getBufferingLimit(limitBufferingMs); -} - -bool MediaPipelineService::setUseBuffering(int sessionId, bool useBuffering) -{ - RIALTO_SERVER_LOG_DEBUG("Set use buffering requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->setUseBuffering(useBuffering); -} - -bool MediaPipelineService::getUseBuffering(int sessionId, bool &useBuffering) -{ - RIALTO_SERVER_LOG_DEBUG("Get use buffering requested, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exist", sessionId); - return false; - } - return mediaPipelineIter->second->getUseBuffering(useBuffering); -} - -bool MediaPipelineService::switchSource(int sessionId, const std::unique_ptr &source) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested to switch source, session id: %d", sessionId); - - std::lock_guard lock{m_mediaPipelineMutex}; - auto mediaPipelineIter = m_mediaPipelines.find(sessionId); - if (mediaPipelineIter == m_mediaPipelines.end()) - { - RIALTO_SERVER_LOG_ERROR("Session with id: %d does not exists", sessionId); - return false; - } - return mediaPipelineIter->second->switchSource(source); -} - -bool MediaPipelineService::isVideoMaster(bool &isVideoMaster) -{ - RIALTO_SERVER_LOG_INFO("MediaPipelineService requested check if video is master"); - - return m_mediaPipelineCapabilities->isVideoMaster(isVideoMaster); -} - -std::vector MediaPipelineService::getSupportedMimeTypes(MediaSourceType type) -{ - return m_mediaPipelineCapabilities->getSupportedMimeTypes(type); -} - -bool MediaPipelineService::isMimeTypeSupported(const std::string &mimeType) -{ - return m_mediaPipelineCapabilities->isMimeTypeSupported(mimeType); -} - -std::vector MediaPipelineService::getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) -{ - return m_mediaPipelineCapabilities->getSupportedProperties(mediaType, propertyNames); -} - -void MediaPipelineService::ping(const std::shared_ptr &heartbeatProcedure) -{ - RIALTO_SERVER_LOG_DEBUG("Ping requested"); - std::lock_guard lock{m_mediaPipelineMutex}; - for (const auto &mediaPipelinePair : m_mediaPipelines) - { - auto &mediaPipeline = mediaPipelinePair.second; - mediaPipeline->ping(heartbeatProcedure->createHandler()); - } -} - -} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/MediaPipelineService.h b/middleware/rialto-client/media/server/service/source/MediaPipelineService.h deleted file mode 100644 index da925551f..000000000 --- a/middleware/rialto-client/media/server/service/source/MediaPipelineService.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_MEDIA_PIPELINE_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_MEDIA_PIPELINE_SERVICE_H_ - -#include "IDecryptionService.h" -#include "IMediaPipelineCapabilities.h" -#include "IMediaPipelineServerInternal.h" -#include "IMediaPipelineService.h" -#include "IPlaybackService.h" -#include "ISharedMemoryBuffer.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class MediaPipelineService : public IMediaPipelineService -{ -public: - MediaPipelineService(IPlaybackService &playbackService, - std::shared_ptr &&mediaPipelineFactory, - std::shared_ptr &&mediaPipelineCapabilitiesFactory, - IDecryptionService &decryptionService); - ~MediaPipelineService() override; - MediaPipelineService(const MediaPipelineService &) = delete; - MediaPipelineService(MediaPipelineService &&) = delete; - MediaPipelineService &operator=(const MediaPipelineService &) = delete; - MediaPipelineService &operator=(MediaPipelineService &&) = delete; - - bool createSession(int sessionId, const std::shared_ptr &mediaPipelineClient, - std::uint32_t maxWidth, std::uint32_t maxHeight) override; - bool destroySession(int sessionId) override; - bool load(int sessionId, MediaType type, const std::string &mimeType, const std::string &url) override; - bool attachSource(int sessionId, const std::unique_ptr &source) override; - bool removeSource(int sessionId, std::int32_t sourceId) override; - bool allSourcesAttached(int sessionId) override; - bool play(int sessionId) override; - bool pause(int sessionId) override; - bool stop(int sessionId) override; - bool setPlaybackRate(int sessionId, double rate) override; - bool setPosition(int sessionId, std::int64_t position) override; - bool getPosition(int sessionId, std::int64_t &position) override; - bool setImmediateOutput(int sessionId, int32_t sourceId, bool immediateOutput) override; - bool getImmediateOutput(int sessionId, int32_t sourceId, bool &immediateOutput) override; - bool getStats(int sessionId, int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; - bool setVideoWindow(int sessionId, std::uint32_t x, std::uint32_t y, std::uint32_t width, - std::uint32_t height) override; - bool haveData(int sessionId, MediaSourceStatus status, std::uint32_t numFrames, - std::uint32_t needDataRequestId) override; - bool renderFrame(int sessionId) override; - bool setVolume(int sessionId, double targetVolume, uint32_t volumeDuration, EaseType easeType) override; - bool getVolume(int sessionId, double &volume) override; - bool setMute(int sessionId, std::int32_t sourceId, bool mute) override; - bool getMute(int sessionId, std::int32_t sourceId, bool &mute) override; - bool setTextTrackIdentifier(int sessionId, const std::string &textTrackIdentifier) override; - bool getTextTrackIdentifier(int sessionId, std::string &textTrackIdentifier) override; - bool setLowLatency(int sessionId, bool lowLatency) override; - bool setSync(int sessionId, bool sync) override; - bool getSync(int sessionId, bool &sync) override; - bool setSyncOff(int sessionId, bool syncOff) override; - bool setStreamSyncMode(int sessionId, int32_t sourceId, int32_t streamSyncMode) override; - bool getStreamSyncMode(int sessionId, int32_t &streamSyncMode) override; - bool flush(int sessionId, std::int32_t sourceId, bool resetTime, bool &isAsync) override; - bool setSourcePosition(int sessionId, int32_t sourceId, int64_t position, bool resetTime, double appliedRate, - uint64_t stopPosition) override; - bool setSubtitleOffset(int sessionId, int32_t sourceId, int64_t position) override; - bool processAudioGap(int sessionId, int64_t position, uint32_t duration, int64_t discontinuityGap, - bool audioAac) override; - bool setBufferingLimit(int sessionId, uint32_t limitBufferingMs) override; - bool getBufferingLimit(int sessionId, uint32_t &limitBufferingMs) override; - bool setUseBuffering(int sessionId, bool useBuffering) override; - bool getUseBuffering(int sessionId, bool &useBuffering) override; - bool switchSource(int sessionId, const std::unique_ptr &source) override; - bool isVideoMaster(bool &isVideoMaster) override; - std::vector getSupportedMimeTypes(MediaSourceType type) override; - bool isMimeTypeSupported(const std::string &mimeType) override; - std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) override; - void ping(const std::shared_ptr &heartbeatProcedure) override; - - void clearMediaPipelines(); - -private: - IPlaybackService &m_playbackService; - std::shared_ptr m_mediaPipelineFactory; - std::shared_ptr m_mediaPipelineCapabilities; - IDecryptionService &m_decryptionService; - std::map> m_mediaPipelines; - std::mutex m_mediaPipelineMutex; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_MEDIA_PIPELINE_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/PlaybackService.cpp b/middleware/rialto-client/media/server/service/source/PlaybackService.cpp deleted file mode 100644 index 121e85730..000000000 --- a/middleware/rialto-client/media/server/service/source/PlaybackService.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "PlaybackService.h" -#include "IMediaPipelineServerInternal.h" -#include "IWebAudioPlayerServerInternal.h" -#include "RialtoServerLogging.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -PlaybackService::PlaybackService(std::shared_ptr &&mediaPipelineFactory, - std::shared_ptr &&mediaPipelineCapabilitiesFactory, - std::shared_ptr &&webAudioPlayerFactory, - std::unique_ptr &&shmBufferFactory, - IDecryptionService &decryptionService) - : m_shmBufferFactory{std::move(shmBufferFactory)}, m_isActive{false}, m_maxPlaybacks{0}, m_maxWebAudioPlayers{0}, - m_mediaPipelineService{std::make_unique(*this, std::move(mediaPipelineFactory), - std::move(mediaPipelineCapabilitiesFactory), - decryptionService)}, - m_webAudioPlayerService{std::make_unique(*this, std::move(webAudioPlayerFactory))} -{ - RIALTO_SERVER_LOG_DEBUG("PlaybackService is constructed"); -} - -PlaybackService::~PlaybackService() -{ - RIALTO_SERVER_LOG_DEBUG("PlaybackService is destructed"); -} - -bool PlaybackService::switchToActive() -{ - try - { - RIALTO_SERVER_LOG_INFO("Switching SessionServer to Active state."); - m_shmBuffer = m_shmBufferFactory->createSharedMemoryBuffer(m_maxPlaybacks, m_maxWebAudioPlayers); - m_isActive = true; - return true; - } - catch (const std::exception &e) - { - RIALTO_SERVER_LOG_ERROR("SessionServer failed to switch to active: %s", e.what()); - m_isActive = false; - return false; - } -} - -void PlaybackService::switchToInactive() -{ - RIALTO_SERVER_LOG_INFO("Switching SessionServer to Inactive state. Cleaning resources..."); - m_isActive = false; - m_mediaPipelineService->clearMediaPipelines(); - m_webAudioPlayerService->clearWebAudioPlayers(); - m_shmBuffer.reset(); -} - -void PlaybackService::setMaxPlaybacks(int maxPlaybacks) -{ - // Method called during initialization only (before setting any state), no need to execute it on a task thread. - m_maxPlaybacks = maxPlaybacks; -} - -void PlaybackService::setMaxWebAudioPlayers(int maxWebAudio) -{ - // Method called during initialization only (before setting any state), no need to execute it on a task thread. - m_maxWebAudioPlayers = maxWebAudio; -} - -void PlaybackService::setClientDisplayName(const std::string &clientDisplayName) const -{ - // Method called during initialization only (before setting any state), no need to execute it on a task thread. - if (!clientDisplayName.empty()) - { - setenv("WAYLAND_DISPLAY", clientDisplayName.c_str(), 1); - } -} - -void PlaybackService::setResourceManagerAppName(const std::string &appName) const -{ - // Method called during initialization only (before setting any state), no need to execute it on a task thread. - if (!appName.empty()) - { - setenv("ESSRMGR_APPID", appName.c_str(), 1); - } -} - -bool PlaybackService::getSharedMemory(int32_t &fd, uint32_t &size) const -{ - auto shmBuffer = m_shmBuffer; - - if (!shmBuffer) - { - return false; - } - fd = shmBuffer->getFd(); - size = shmBuffer->getSize(); - return true; -} - -bool PlaybackService::isActive() const -{ - return m_isActive; -} - -int PlaybackService::getMaxPlaybacks() const -{ - return m_maxPlaybacks; -} - -int PlaybackService::getMaxWebAudioPlayers() const -{ - return m_maxWebAudioPlayers; -} - -std::shared_ptr PlaybackService::getShmBuffer() const -{ - return m_shmBuffer; -} - -IMediaPipelineService &PlaybackService::getMediaPipelineService() const -{ - return *m_mediaPipelineService; -} - -IWebAudioPlayerService &PlaybackService::getWebAudioPlayerService() const -{ - return *m_webAudioPlayerService; -} - -void PlaybackService::ping(const std::shared_ptr &heartbeatProcedure) const -{ - m_mediaPipelineService->ping(heartbeatProcedure); - m_webAudioPlayerService->ping(heartbeatProcedure); -} -} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/PlaybackService.h b/middleware/rialto-client/media/server/service/source/PlaybackService.h deleted file mode 100644 index 16d63cc44..000000000 --- a/middleware/rialto-client/media/server/service/source/PlaybackService.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_PLAYBACK_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_PLAYBACK_SERVICE_H_ - -#include "IDecryptionService.h" -#include "IHeartbeatProcedure.h" -#include "IMediaPipelineCapabilities.h" -#include "IMediaPipelineServerInternal.h" -#include "IPlaybackService.h" -#include "ISharedMemoryBuffer.h" -#include "IWebAudioPlayerServerInternal.h" -#include "MediaPipelineService.h" -#include "WebAudioPlayerService.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class PlaybackService : public IPlaybackService -{ -public: - PlaybackService(std::shared_ptr &&mediaPipelineFactory, - std::shared_ptr &&mediaPipelineCapabilitiesFactory, - std::shared_ptr &&webAudioPlayerFactory, - std::unique_ptr &&shmBufferFactory, - IDecryptionService &decryptionService); - ~PlaybackService() override; - PlaybackService(const PlaybackService &) = delete; - PlaybackService(PlaybackService &&) = delete; - PlaybackService &operator=(const PlaybackService &) = delete; - PlaybackService &operator=(PlaybackService &&) = delete; - - bool switchToActive() override; - void switchToInactive() override; - void setMaxPlaybacks(int maxPlaybacks) override; - void setMaxWebAudioPlayers(int maxWebAudio) override; - void setClientDisplayName(const std::string &clientDisplayName) const override; - void setResourceManagerAppName(const std::string &clientDisplayName) const override; - - bool isActive() const override; - bool getSharedMemory(int32_t &fd, uint32_t &size) const override; - int getMaxPlaybacks() const override; - int getMaxWebAudioPlayers() const override; - std::shared_ptr getShmBuffer() const override; - IMediaPipelineService &getMediaPipelineService() const override; - IWebAudioPlayerService &getWebAudioPlayerService() const override; - void ping(const std::shared_ptr &heartbeatProcedure) const override; - -private: - std::unique_ptr m_shmBufferFactory; - std::atomic m_isActive; - std::atomic m_maxPlaybacks; - std::atomic m_maxWebAudioPlayers; - std::shared_ptr m_shmBuffer; - std::unique_ptr m_mediaPipelineService; - std::unique_ptr m_webAudioPlayerService; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_PLAYBACK_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/SessionServerManager.cpp b/middleware/rialto-client/media/server/service/source/SessionServerManager.cpp deleted file mode 100644 index d05bbfcd4..000000000 --- a/middleware/rialto-client/media/server/service/source/SessionServerManager.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "SessionServerManager.h" -#include "IApplicationManagementServer.h" -#include "IIpcFactory.h" -#include "ISessionManagementServer.h" -#include "RialtoServerLogging.h" - -#include -#include -#include - -namespace -{ -inline bool isNumber(const std::string &text) -{ - return std::find_if(text.begin(), text.end(), [](const auto &letter) { return !std::isdigit(letter); }) == text.end(); -} -} // namespace - -namespace firebolt::rialto::server::service -{ -SessionServerManager::SessionServerManager(const ipc::IIpcFactory &ipcFactory, IPlaybackService &playbackService, - ICdmService &cdmService, IControlService &controlService, - std::unique_ptr &&heartbeatProcedureFactory) - : m_playbackService{playbackService}, m_cdmService{cdmService}, m_controlService{controlService}, - m_heartbeatProcedureFactory{std::move(heartbeatProcedureFactory)}, - m_applicationManagementServer{ipcFactory.createApplicationManagementServer(*this)}, - m_sessionManagementServer{ipcFactory.createSessionManagementServer(playbackService, cdmService, controlService)}, - m_isServiceRunning{true}, m_currentState{common::SessionServerState::UNINITIALIZED} -{ - RIALTO_SERVER_LOG_INFO("Starting Rialto Server Service"); -} - -SessionServerManager::~SessionServerManager() -{ - RIALTO_SERVER_LOG_INFO("Stopping Rialto Server Service"); - - // The following reset() will ensure that the thread ApplicationManagementServer::m_ipcServerThread - // isn't currently calling any methods within this class (while it is being destructed) - // Particularly, the mentioned thread is responsible for calling the method - // SessionServerManager::switchToNotRunning() which then triggers a call to this destuctor - // after it calls stopService() - m_applicationManagementServer.reset(); - - stopService(); -} - -bool SessionServerManager::initialize(int argc, char *argv[]) -try -{ - if (argc != 2) - { - RIALTO_SERVER_LOG_ERROR("Wrong number of arguments. Rialto Server Service will close now."); - return false; - } - std::string socketStr{argv[1]}; - if (!isNumber(socketStr)) - { - RIALTO_SERVER_LOG_ERROR("Rialto App Management socket is not a number."); - return false; - } - if (!m_applicationManagementServer->initialize(std::stoi(socketStr))) - { - RIALTO_SERVER_LOG_ERROR("Initialization of Application Management server failed."); - return false; - } - m_applicationManagementServer->start(); - return m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::UNINITIALIZED); -} -catch (const std::exception &e) -{ - RIALTO_SERVER_LOG_ERROR("Exception caught during service initialization: %s", e.what()); - return false; -} - -void SessionServerManager::startService() -{ - std::unique_lock lock{m_serviceMutex}; - m_serviceCv.wait(lock, [this]() { return !m_isServiceRunning; }); -} - -void SessionServerManager::stopService() -{ - std::unique_lock lock{m_serviceMutex}; - if (m_isServiceRunning) - { - m_isServiceRunning = false; - m_serviceCv.notify_one(); - } -} - -bool SessionServerManager::configureIpc(const std::string &socketName, unsigned int socketPermissions, - const std::string &socketOwner, const std::string &socketGroup) -{ - if (!m_sessionManagementServer->initialize(socketName, socketPermissions, socketOwner, socketGroup)) - { - RIALTO_SERVER_LOG_ERROR("configureIpc failed - SessionManagementServer failed to initialize"); - return false; - } - return true; -} - -bool SessionServerManager::configureIpc(int32_t socketFd) -{ - if (!m_sessionManagementServer->initialize(socketFd)) - { - RIALTO_SERVER_LOG_ERROR("configureIpc failed - SessionManagementServer failed to initialize"); - return false; - } - return true; -} - -bool SessionServerManager::configureServices(const common::SessionServerState &state, - const common::MaxResourceCapabilitites &maxResource, - const std::string &clientDisplayName, const std::string &appName) -{ - m_sessionManagementServer->start(); - m_playbackService.setMaxPlaybacks(maxResource.maxPlaybacks); - m_playbackService.setMaxWebAudioPlayers(maxResource.maxWebAudioPlayers); - m_playbackService.setClientDisplayName(clientDisplayName); - m_playbackService.setResourceManagerAppName(appName); - return setState(state); -} - -bool SessionServerManager::setState(const common::SessionServerState &state) -{ - switch (state) - { - case common::SessionServerState::ACTIVE: - { - return switchToActive(); - } - case common::SessionServerState::INACTIVE: - { - return switchToInactive(); - } - case common::SessionServerState::NOT_RUNNING: - { - return switchToNotRunning(); - } - default: - { - RIALTO_SERVER_LOG_ERROR("SetState failed - unsupported state"); - m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::ERROR); - } - } - return false; -} - -void SessionServerManager::setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, - RIALTO_DEBUG_LEVEL sessionServerLogLevels, RIALTO_DEBUG_LEVEL ipcLogLevels, - RIALTO_DEBUG_LEVEL serverManagerLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) -{ - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_DEFAULT, defaultLogLevels); - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_CLIENT, clientLogLevels); - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_SERVER, sessionServerLogLevels); - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_IPC, ipcLogLevels); - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_SERVER_MANAGER, serverManagerLogLevels); - firebolt::rialto::logging::setLogLevels(RIALTO_COMPONENT_COMMON, commonLogLevels); - m_sessionManagementServer->setLogLevels(defaultLogLevels, clientLogLevels, ipcLogLevels, commonLogLevels); -} - -bool SessionServerManager::ping(std::int32_t id, const std::shared_ptr &ackSender) -{ - auto heartbeatProcedure{m_heartbeatProcedureFactory->createHeartbeatProcedure(ackSender, id)}; - - // Check all rialto server internal threads - m_cdmService.ping(heartbeatProcedure); - m_playbackService.ping(heartbeatProcedure); - - // Check all Rialto Clients - return m_controlService.ping(heartbeatProcedure); -} - -bool SessionServerManager::switchToActive() -{ - if (m_currentState.load() == common::SessionServerState::ACTIVE) - { - RIALTO_SERVER_LOG_DEBUG("Session server already in Active state."); - return true; - } - if (!m_playbackService.switchToActive()) - { - RIALTO_SERVER_LOG_ERROR("Player service failed to switch to active state"); - return false; - } - if (!m_cdmService.switchToActive()) - { - RIALTO_SERVER_LOG_ERROR("Cdm service failed to switch to active state"); - m_playbackService.switchToInactive(); - return false; - } - if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::ACTIVE)) - { - m_controlService.setApplicationState(ApplicationState::RUNNING); - m_currentState.store(common::SessionServerState::ACTIVE); - RIALTO_SERVER_LOG_MIL("RialtoServer state is ACTIVE now"); - return true; - } - m_playbackService.switchToInactive(); - m_cdmService.switchToInactive(); - return false; -} - -bool SessionServerManager::switchToInactive() -{ - if (m_currentState.load() == common::SessionServerState::INACTIVE) - { - RIALTO_SERVER_LOG_DEBUG("Session server already in Inactive state."); - return true; - } - m_playbackService.switchToInactive(); - m_cdmService.switchToInactive(); - if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::INACTIVE)) - { - m_controlService.setApplicationState(ApplicationState::INACTIVE); - m_currentState.store(common::SessionServerState::INACTIVE); - RIALTO_SERVER_LOG_MIL("RialtoServer state is INACTIVE now"); - return true; - } - if (m_currentState.load() == common::SessionServerState::ACTIVE) - { - if (!m_playbackService.switchToActive()) - { - RIALTO_SERVER_LOG_WARN("Player service failed to switch to active state"); - } - if (!m_cdmService.switchToActive()) - { - RIALTO_SERVER_LOG_WARN("Cdm service failed to switch to active state"); - } - } - return false; -} - -bool SessionServerManager::switchToNotRunning() -{ - RIALTO_SERVER_LOG_MIL("RialtoServer state switch to NOT_RUNNING requested"); - if (m_currentState.load() == common::SessionServerState::NOT_RUNNING) - { - RIALTO_SERVER_LOG_DEBUG("Session server already in NotRunning state."); - return true; - } - // Free resources before sending notification to ServerManager - m_playbackService.switchToInactive(); - m_cdmService.switchToInactive(); - m_controlService.setApplicationState(ApplicationState::UNKNOWN); - - bool result{true}; - if (m_applicationManagementServer->sendStateChangedEvent(common::SessionServerState::NOT_RUNNING)) - { - m_currentState.store(common::SessionServerState::NOT_RUNNING); - } - else - { - result = false; - } - - // stopService() needs to be the last command of this method. - // It triggers destruction of SessionServerManager and therefore - // some member variables may not be valid after this command - stopService(); // This HAS TO BE LAST (see above) - return result; -} -} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/SessionServerManager.h b/middleware/rialto-client/media/server/service/source/SessionServerManager.h deleted file mode 100644 index 899475e8c..000000000 --- a/middleware/rialto-client/media/server/service/source/SessionServerManager.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_SESSION_SERVER_MANAGER_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_SESSION_SERVER_MANAGER_H_ - -#include "IApplicationManagementServer.h" -#include "ICdmService.h" -#include "IControlService.h" -#include "IHeartbeatProcedure.h" -#include "IIpcFactory.h" -#include "IPlaybackService.h" -#include "ISessionManagementServer.h" -#include "ISessionServerManager.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class SessionServerManager : public ISessionServerManager -{ -public: - SessionServerManager(const ipc::IIpcFactory &ipcFactory, IPlaybackService &playbackService, ICdmService &cdmService, - IControlService &controlService, - std::unique_ptr &&heartbeatProcedureFactory); - ~SessionServerManager() override; - SessionServerManager(const SessionServerManager &) = delete; - SessionServerManager(SessionServerManager &&) = delete; - SessionServerManager &operator=(const SessionServerManager &) = delete; - SessionServerManager &operator=(SessionServerManager &&) = delete; - - bool initialize(int argc, char *argv[]) override; - void startService() override; - bool configureIpc(const std::string &socketName, unsigned int socketPermissions, const std::string &socketOwner, - const std::string &socketGroup) override; - bool configureIpc(int32_t socketFd) override; - bool configureServices(const common::SessionServerState &state, const common::MaxResourceCapabilitites &maxResource, - const std::string &clientDisplayName, const std::string &appName) override; - bool setState(const common::SessionServerState &state) override; - void setLogLevels(RIALTO_DEBUG_LEVEL defaultLogLevels, RIALTO_DEBUG_LEVEL clientLogLevels, - RIALTO_DEBUG_LEVEL sessionServerLogLevels, RIALTO_DEBUG_LEVEL ipcLogLevels, - RIALTO_DEBUG_LEVEL serverManagerLogLevels, RIALTO_DEBUG_LEVEL commonLogLevels) override; - bool ping(std::int32_t id, const std::shared_ptr &ackSender) override; - -private: - bool switchToActive(); - bool switchToInactive(); - bool switchToNotRunning(); - void stopService(); - -private: - IPlaybackService &m_playbackService; - ICdmService &m_cdmService; - IControlService &m_controlService; - std::unique_ptr m_heartbeatProcedureFactory; - std::unique_ptr m_applicationManagementServer; - std::unique_ptr m_sessionManagementServer; - std::mutex m_serviceMutex; - std::condition_variable m_serviceCv; - bool m_isServiceRunning; - std::atomic m_currentState; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_SESSION_SERVER_MANAGER_H_ diff --git a/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.cpp b/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.cpp deleted file mode 100644 index 5e15aef01..000000000 --- a/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WebAudioPlayerService.h" -#include "IGstWebAudioPlayer.h" -#include "IMainThread.h" -#include "ITimer.h" -#include "IWebAudioPlayer.h" -#include "IWebAudioPlayerServerInternal.h" -#include "RialtoServerLogging.h" -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -WebAudioPlayerService::WebAudioPlayerService(IPlaybackService &playbackService, - std::shared_ptr &&webAudioPlayerFactory) - : m_playbackService{playbackService}, m_webAudioPlayerFactory{webAudioPlayerFactory} -{ - RIALTO_SERVER_LOG_DEBUG("WebAudioPlayerService is constructed"); -} - -WebAudioPlayerService::~WebAudioPlayerService() -{ - RIALTO_SERVER_LOG_DEBUG("WebAudioPlayerService is destructed"); -} - -void WebAudioPlayerService::clearWebAudioPlayers() -{ - std::lock_guard lock{m_webAudioPlayerMutex}; - m_webAudioPlayers.clear(); -} - -bool WebAudioPlayerService::createWebAudioPlayer(int handle, - const std::shared_ptr &webAudioPlayerClient, - const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config) -{ - RIALTO_SERVER_LOG_DEBUG("WebAudioPlayerService requested to create new WebAudioPlayer with id: %d", handle); - if (!m_playbackService.isActive()) - { - RIALTO_SERVER_LOG_ERROR("Skip create WebAudioPlayer with id: %d - Session Server in Inactive state", handle); - return false; - } - - { - std::lock_guard lock{m_webAudioPlayerMutex}; - if (m_webAudioPlayers.size() == static_cast(m_playbackService.getMaxWebAudioPlayers())) - { - RIALTO_SERVER_LOG_ERROR("Unable to create WebAudioPlayer with id: %d. Max instance number reached.", handle); - return false; - } - if (m_webAudioPlayers.find(handle) != m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d already exists", handle); - return false; - } - auto shmBuffer = m_playbackService.getShmBuffer(); - - m_webAudioPlayers.emplace( - std::make_pair(handle, m_webAudioPlayerFactory - ->createWebAudioPlayerServerInternal(webAudioPlayerClient, audioMimeType, - priority, config, shmBuffer, handle, - IMainThreadFactory::createFactory(), - IGstWebAudioPlayerFactory::getFactory(), - common::ITimerFactory::getFactory()))); - if (!m_webAudioPlayers.at(handle)) - { - RIALTO_SERVER_LOG_ERROR("Could not create WebAudioPlayer for handle: %d", handle); - m_webAudioPlayers.erase(handle); - return false; - } - } - - RIALTO_SERVER_LOG_INFO("New WebAudioPlayer: %d created", handle); - return true; -} - -bool WebAudioPlayerService::destroyWebAudioPlayer(int handle) -{ - RIALTO_SERVER_LOG_DEBUG("WebAudioPlayerService requested to destroy WebAudioPlayer with handle: %d", handle); - { - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - m_webAudioPlayers.erase(webAudioPlayerIter); - } - RIALTO_SERVER_LOG_INFO("WebAudioPlayer: %d destroyed", handle); - return true; -} - -bool WebAudioPlayerService::play(int handle) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to play WebAudioPlayer with handle: %d", handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->play(); -} - -bool WebAudioPlayerService::pause(int handle) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to pause WebAudioPlayer with handle: %d", handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->pause(); -} - -bool WebAudioPlayerService::setEos(int handle) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to setEos WebAudioPlayer with handle: %d", handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->setEos(); -} - -bool WebAudioPlayerService::getBufferAvailable(int handle, uint32_t &availableFrames, - std::shared_ptr &webAudioShmInfo) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to getBufferAvailable WebAudioPlayer with handle: %d", - handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->getBufferAvailable(availableFrames, webAudioShmInfo); -} - -bool WebAudioPlayerService::getBufferDelay(int handle, uint32_t &delayFrames) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to getBufferDelay WebAudioPlayer with handle: %d", handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->getBufferDelay(delayFrames); -} - -bool WebAudioPlayerService::writeBuffer(int handle, const uint32_t numberOfFrames, void *data) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to writeBuffer WebAudioPlayer with handle: %d", handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->writeBuffer(numberOfFrames, data); -} - -bool WebAudioPlayerService::getDeviceInfo(int handle, uint32_t &preferredFrames, uint32_t &maximumFrames, - bool &supportDeferredPlay) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to getDeviceInfo WebAudioPlayer with handle: %d", handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay); -} - -bool WebAudioPlayerService::setVolume(int handle, double volume) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to setVolume WebAudioPlayer with handle: %d", handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->setVolume(volume); -} - -bool WebAudioPlayerService::getVolume(int handle, double &volume) -{ - RIALTO_SERVER_LOG_INFO("WebAudioPlayerService requested to getVolume WebAudioPlayer with handle: %d", handle); - - std::lock_guard lock{m_webAudioPlayerMutex}; - auto webAudioPlayerIter = m_webAudioPlayers.find(handle); - if (webAudioPlayerIter == m_webAudioPlayers.end()) - { - RIALTO_SERVER_LOG_ERROR("WebAudioPlayer with handle: %d does not exists", handle); - return false; - } - return webAudioPlayerIter->second->getVolume(volume); -} - -void WebAudioPlayerService::ping(const std::shared_ptr &heartbeatProcedure) -{ - RIALTO_SERVER_LOG_DEBUG("Ping requested"); - std::lock_guard lock{m_webAudioPlayerMutex}; - for (const auto &webAudioPlayersPair : m_webAudioPlayers) - { - auto &webAudioPlayer = webAudioPlayersPair.second; - webAudioPlayer->ping(heartbeatProcedure->createHandler()); - } -} -} // namespace firebolt::rialto::server::service diff --git a/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.h b/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.h deleted file mode 100644 index 04b2c5511..000000000 --- a/middleware/rialto-client/media/server/service/source/WebAudioPlayerService.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_SERVER_SERVICE_WEB_AUDIO_PLAYER_SERVICE_H_ -#define FIREBOLT_RIALTO_SERVER_SERVICE_WEB_AUDIO_PLAYER_SERVICE_H_ - -#include "IPlaybackService.h" -#include "IWebAudioPlayerServerInternal.h" -#include "IWebAudioPlayerService.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto::server::service -{ -class WebAudioPlayerService : public IWebAudioPlayerService -{ -public: - WebAudioPlayerService(IPlaybackService &playbackService, - std::shared_ptr &&webAudioPlayerFactory); - ~WebAudioPlayerService() override; - WebAudioPlayerService(const WebAudioPlayerService &) = delete; - WebAudioPlayerService(WebAudioPlayerService &&) = delete; - WebAudioPlayerService &operator=(const WebAudioPlayerService &) = delete; - WebAudioPlayerService &operator=(WebAudioPlayerService &&) = delete; - - bool createWebAudioPlayer(int handle, const std::shared_ptr &webAudioPlayerClient, - const std::string &audioMimeType, const uint32_t priority, - std::weak_ptr config) override; - bool destroyWebAudioPlayer(int handle) override; - bool play(int handle) override; - bool pause(int handle) override; - bool setEos(int handle) override; - bool getBufferAvailable(int handle, uint32_t &availableFrames, - std::shared_ptr &webAudioShmInfo) override; - bool getBufferDelay(int handle, uint32_t &delayFrames) override; - bool writeBuffer(int handle, const uint32_t numberOfFrames, void *data) override; - bool getDeviceInfo(int handle, uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override; - bool setVolume(int handle, double volume) override; - bool getVolume(int handle, double &volume) override; - void ping(const std::shared_ptr &heartbeatProcedure) override; - - void clearWebAudioPlayers(); - -private: - IPlaybackService &m_playbackService; - std::shared_ptr m_webAudioPlayerFactory; - std::map> m_webAudioPlayers; - std::mutex m_webAudioPlayerMutex; -}; -} // namespace firebolt::rialto::server::service - -#endif // FIREBOLT_RIALTO_SERVER_SERVICE_WEB_AUDIO_PLAYER_SERVICE_H_ diff --git a/middleware/rialto-client/media/server/service/source/main.cpp b/middleware/rialto-client/media/server/service/source/main.cpp deleted file mode 100644 index 4442a7764..000000000 --- a/middleware/rialto-client/media/server/service/source/main.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "IApplicationSessionServer.h" -#include "IGstInitialiser.h" -#include "RialtoServerLogging.h" - -// NOLINT(build/filename_format) - -int main(int argc, char *argv[]) -{ - const char kSrcRev[] = SRCREV; - const char kTags[] = TAGS; - - if (std::strlen(kSrcRev) > 0) - { - if (std::strlen(kTags) > 0) - { - RIALTO_SERVER_LOG_MIL("Release Tag(s): %s (Commit ID: %s)", kTags, kSrcRev); - } - else - { - RIALTO_SERVER_LOG_MIL("Release Tag(s): No Release Tags! (Commit ID: %s)", kSrcRev); - } - } - else - { - RIALTO_SERVER_LOG_WARN("Failed to get git commit ID!"); - } - - firebolt::rialto::server::IGstInitialiser::instance().initialise(&argc, &argv); - - auto appSessionServer = - firebolt::rialto::server::IApplicationSessionServerFactory::getFactory()->createApplicationSessionServer(); - - if (!appSessionServer->init(argc, argv)) - { - return EXIT_FAILURE; - } - appSessionServer->startService(); - -#ifdef FREE_MEM_BEFORE_EXIT - RIALTO_SERVER_LOG_INFO("Calling ShutdownProtobufLibrary"); - google::protobuf::ShutdownProtobufLibrary(); -#endif - - return EXIT_SUCCESS; -} diff --git a/middleware/rialto-gstreamer/source/BufferParser.cpp b/middleware/rialto-gstreamer/source/BufferParser.cpp deleted file mode 100644 index 1a150a36b..000000000 --- a/middleware/rialto-gstreamer/source/BufferParser.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "BufferParser.h" -#include "GStreamerEMEUtils.h" -#include "GStreamerUtils.h" -#include "GstreamerCatLog.h" -#include -#include -#include -#include - -using namespace firebolt::rialto; -#define GST_CAT_DEFAULT rialtoGStreamerCat - -std::unique_ptr BufferParser::parseBuffer(const GstRefSample &sample, GstBuffer *buffer, - GstMapInfo map, int streamId) -{ - int64_t timeStamp = static_cast(GST_BUFFER_PTS(buffer)); - int64_t duration = static_cast(GST_BUFFER_DURATION(buffer)); - GstCaps *caps = sample.getCaps(); - GstStructure *structure = gst_caps_get_structure(caps, 0); - - std::unique_ptr mseData = - parseSpecificPartOfBuffer(buffer, streamId, structure, timeStamp, duration); - - mseData->setData(map.size, map.data); - - addCodecDataToSegment(mseData, structure); - addProtectionMetadataToSegment(mseData, buffer, map, structure); - addDisplayOffsetToSegment(mseData, GST_BUFFER_OFFSET(buffer)); - - return mseData; -} - -void BufferParser::addProtectionMetadataToSegment(std::unique_ptr &segment, - GstBuffer *buffer, const GstMapInfo &map, GstStructure *structure) -{ - EncryptionFormat encryptionFormat = EncryptionFormat::CLEAR; - BufferProtectionMetadata metadata; - ProcessProtectionMetadata(buffer, metadata); - - std::string mediaType = gst_structure_get_name(structure); - if (mediaType == "application/x-cenc") - { - encryptionFormat = EncryptionFormat::CENC; - } - else if (mediaType == "application/x-webm-enc") - { - encryptionFormat = EncryptionFormat::WEBM; - } - - // For WEBM encrypted sample without partitioning: add subsample which contains only encrypted data. - // More details: https://www.webmproject.org/docs/webm-encryption/#45-full-sample-encrypted-block-format - // For CENC see CENC specification, section 9.2 - if ((encryptionFormat == EncryptionFormat::WEBM) || (encryptionFormat == EncryptionFormat::CENC)) - { - if ((metadata.encrypted) && (metadata.subsamples.size() == 0)) - { - metadata.subsamples.push_back(std::make_pair((uint32_t)0, (uint32_t)map.size)); - } - } - - if (metadata.encrypted) - { - GST_DEBUG("encrypted: %d mksId: %d key len: %zu iv len: %zu SUBSAMPLES: %zu, initWithLast15: %u", - metadata.encrypted, metadata.mediaKeySessionId, metadata.kid.size(), metadata.iv.size(), - metadata.subsamples.size(), metadata.initWithLast15); - - segment->setEncrypted(true); - segment->setMediaKeySessionId(metadata.mediaKeySessionId); - segment->setKeyId(metadata.kid); - segment->setInitVector(metadata.iv); - segment->setInitWithLast15(metadata.initWithLast15); - segment->setCipherMode(metadata.cipherMode); - if (metadata.encryptionPatternSet) - { - segment->setEncryptionPattern(metadata.cryptBlocks, metadata.skipBlocks); - } - - size_t subSampleCount = metadata.subsamples.size(); - for (size_t subSampleIdx = 0; subSampleIdx < subSampleCount; ++subSampleIdx) - { - GST_DEBUG("SUBSAMPLE: %zu/%zu C: %d E: %d", subSampleIdx, subSampleCount, - metadata.subsamples[subSampleIdx].first, metadata.subsamples[subSampleIdx].second); - segment->addSubSample(metadata.subsamples[subSampleIdx].first, metadata.subsamples[subSampleIdx].second); - } - } -} - -void BufferParser::addCodecDataToSegment(std::unique_ptr &segment, - GstStructure *structure) -{ - const GValue *codec_data; - codec_data = gst_structure_get_value(structure, "codec_data"); - if (codec_data) - { - GstBuffer *buf = gst_value_get_buffer(codec_data); - if (buf) - { - GstMappedBuffer mappedBuf(buf, GST_MAP_READ); - if (mappedBuf) - { - auto codecData = std::make_shared(); - codecData->data = std::vector(mappedBuf.data(), mappedBuf.data() + mappedBuf.size()); - codecData->type = firebolt::rialto::CodecDataType::BUFFER; - segment->setCodecData(codecData); - } - else - { - GST_ERROR("Failed to read codec_data"); - } - return; - } - const gchar *str = g_value_get_string(codec_data); - if (str) - { - auto codecData = std::make_shared(); - codecData->data = std::vector(str, str + std::strlen(str)); - codecData->type = firebolt::rialto::CodecDataType::STRING; - segment->setCodecData(codecData); - } - } -} - -void BufferParser::addDisplayOffsetToSegment(std::unique_ptr &segment, - guint64 displayOffset) -{ - if (GST_BUFFER_OFFSET_NONE != displayOffset) - { - segment->setDisplayOffset(displayOffset); - } -} - -std::unique_ptr -AudioBufferParser::parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, - int64_t timeStamp, int64_t duration) -{ - gint sampleRate = 0; - gint numberOfChannels = 0; - guint64 clippingStart = 0; - guint64 clippingEnd = 0; - gst_structure_get_int(structure, "rate", &sampleRate); - gst_structure_get_int(structure, "channels", &numberOfChannels); - - const GstAudioClippingMeta *clippingMeta = gst_buffer_get_audio_clipping_meta(buffer); - if (clippingMeta) - { - clippingStart = clippingMeta->start; - clippingEnd = clippingMeta->end; - } - - GST_LOG("New audio frame; buffer %p, pts=%" PRId64 " duration=%" PRId64 - " sampleRate=%d numberOfChannels=%d, clippingStart=%" PRIu64 ", clippingEnd=%" PRIu64, - buffer, timeStamp, duration, sampleRate, numberOfChannels, clippingStart, clippingEnd); - - std::unique_ptr mseData = - std::make_unique(streamId, timeStamp, duration, sampleRate, numberOfChannels, - clippingStart, clippingEnd); - - return mseData; -} - -std::unique_ptr -VideoBufferParser::parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, - int64_t timeStamp, int64_t duration) -{ - gint width = 0; - gint height = 0; - firebolt::rialto::Fraction frameRate{firebolt::rialto::kUndefinedSize, firebolt::rialto::kUndefinedSize}; - gst_structure_get_int(structure, "width", &width); - gst_structure_get_int(structure, "height", &height); - gst_structure_get_fraction(structure, "framerate", &frameRate.numerator, &frameRate.denominator); - - GST_LOG("New video frame; buffer %p, pts=%" PRId64 " duration=%" PRId64 " width=%d height=%d framerate=%d/%d", - buffer, timeStamp, duration, width, height, frameRate.numerator, frameRate.denominator); - - std::unique_ptr mseData = - std::make_unique(streamId, timeStamp, duration, width, height, frameRate); - - return mseData; -} - -std::unique_ptr -SubtitleBufferParser::parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, - int64_t timeStamp, int64_t duration) -{ - std::unique_ptr mseData = - std::make_unique(streamId, MediaSourceType::SUBTITLE, timeStamp, duration); - - return mseData; -} diff --git a/middleware/rialto-gstreamer/source/BufferParser.h b/middleware/rialto-gstreamer/source/BufferParser.h deleted file mode 100644 index cd5e9b244..000000000 --- a/middleware/rialto-gstreamer/source/BufferParser.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef BUFFERPARSER_H -#define BUFFERPARSER_H - -#include "GStreamerUtils.h" -#include -#include - -class BufferParser -{ - enum class EncryptionFormat - { - CLEAR, - CENC, - WEBM - }; - -public: - std::unique_ptr - parseBuffer(const GstRefSample &sample, GstBuffer *buffer, GstMapInfo map, int streamId); - -private: - virtual std::unique_ptr - parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, int64_t timeStamp, - int64_t duration) = 0; - - void addProtectionMetadataToSegment(std::unique_ptr &segment, - GstBuffer *buffer, const GstMapInfo &map, GstStructure *structure); - void addCodecDataToSegment(std::unique_ptr &segment, - GstStructure *structure); - void addDisplayOffsetToSegment(std::unique_ptr &segment, - guint64 displayOffset); -}; - -class AudioBufferParser : public BufferParser -{ -private: - std::unique_ptr - parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, int64_t timeStamp, - int64_t duration) override; -}; - -class VideoBufferParser : public BufferParser -{ -private: - std::unique_ptr - parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, int64_t timeStamp, - int64_t duration) override; -}; - -class SubtitleBufferParser : public BufferParser -{ -private: - std::unique_ptr - parseSpecificPartOfBuffer(GstBuffer *buffer, int streamId, GstStructure *structure, int64_t timeStamp, - int64_t duration) override; -}; - -#endif // BUFFERPARSER_H diff --git a/middleware/rialto-gstreamer/source/CMakeLists.txt b/middleware/rialto-gstreamer/source/CMakeLists.txt deleted file mode 100644 index 241350de7..000000000 --- a/middleware/rialto-gstreamer/source/CMakeLists.txt +++ /dev/null @@ -1,96 +0,0 @@ -# Copyright (C) 2023 -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; -# version 2.1 of the License. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -# RIALTO-197: deprecated-declarations error in the latest stable2 for gstreamer. -# Should be removed once the issue is fixed. -add_compile_options( - "-Wno-deprecated-declarations" -) - -find_package(Rialto 1.0 REQUIRED) -find_package(ocdmRialto 1.0 REQUIRED) - -add_library(gstrialtosinks - - SHARED - GstreamerCatLog.cpp - RialtoGStreamerMSEVideoSink.cpp - RialtoGStreamerMSEAudioSink.cpp - RialtoGStreamerWebAudioSink.cpp - RialtoGStreamerMSESubtitleSink.cpp - GStreamerUtils.cpp - GStreamerEMEUtils.cpp - GStreamerMSEUtils.cpp - GStreamerMSEMediaPlayerClient.cpp - GStreamerWebAudioPlayerClient.cpp - MessageQueue.cpp - PullModeAudioPlaybackDelegate.cpp - PullModePlaybackDelegate.cpp - PullModeSubtitlePlaybackDelegate.cpp - PullModeVideoPlaybackDelegate.cpp - PushModeAudioPlaybackDelegate.cpp - RialtoGSteamerPlugin.cpp - RialtoGStreamerMSEBaseSink.cpp - MediaPlayerManager.cpp - Timer.cpp - BufferParser.cpp - LogToGstHandler.cpp - ) - -target_include_directories(gstrialtosinks - PUBLIC - $ - - PRIVATE - ${RIALTO_INCLUDE_DIR} - ${RIALTOOCDM_INCLUDE_DIR} - ${GSTREAMER_APP_INCLUDE_DIRS} - ) - -target_link_libraries(gstrialtosinks - PUBLIC - ${GSTREAMER_APP_LIBRARIES} - - PRIVATE - Rialto::ocdmRialto - Rialto::RialtoClient - Threads::Threads - ) - -#needed by GST_PLUGIN_DEFINE -target_compile_options(gstrialtosinks - PRIVATE - -DPACKAGE="gstrialtosinks" - -DVERSION="1.0" - ) - -set_target_properties(gstrialtosinks - PROPERTIES LINK_FLAGS "-Wl,--unresolved-symbols=report-all" - ) - -find_package(EthanLog) -if (RIALTO_ENABLE_ETHAN_LOG AND EthanLog_FOUND) - message(STATUS "EthanLog is enabled") - target_compile_definitions(gstrialtosinks PRIVATE USE_ETHANLOG) - target_link_libraries(gstrialtosinks PRIVATE EthanLog::EthanLog) -else () - message(STATUS "EthanLog is disabled") -endif () - -install( - TARGETS gstrialtosinks - DESTINATION lib/gstreamer-1.0 - ) diff --git a/middleware/rialto-gstreamer/source/Constants.h b/middleware/rialto-gstreamer/source/Constants.h deleted file mode 100644 index 8edf84a5a..000000000 --- a/middleware/rialto-gstreamer/source/Constants.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2024 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once -#include - -#include - -constexpr double kDefaultVolume{1.0}; -constexpr uint32_t kDefaultVolumeDuration{0}; -constexpr firebolt::rialto::EaseType kDefaultEaseType{firebolt::rialto::EaseType::EASE_LINEAR}; -constexpr bool kDefaultMute{false}; -constexpr bool kDefaultLowLatency{false}; -constexpr bool kDefaultSync{false}; -constexpr bool kDefaultSyncOff{false}; -constexpr int32_t kDefaultStreamSyncMode{0}; -constexpr uint32_t kDefaultFadeVolume{0}; -constexpr const char *kDefaultAudioFade = "100,0,L"; -constexpr uint32_t kDefaultBufferingLimit{750}; -constexpr bool kDefaultUseBuffering{false}; diff --git a/middleware/rialto-gstreamer/source/ControlBackend.h b/middleware/rialto-gstreamer/source/ControlBackend.h deleted file mode 100644 index abd6b9733..000000000 --- a/middleware/rialto-gstreamer/source/ControlBackend.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include -#include -#include - -#include "ControlBackendInterface.h" -#include "IControl.h" - -namespace firebolt::rialto::client -{ -class ControlBackend final : public ControlBackendInterface -{ - class ControlClient : public IControlClient - { - public: - explicit ControlClient(ControlBackend &backend) : mBackend{backend} {} - ~ControlClient() override = default; - void notifyApplicationState(ApplicationState state) override - { - GST_INFO("ApplicationStateChanged received by rialto sink"); - mBackend.onApplicationStateChanged(state); - } - - private: - ControlBackend &mBackend; - }; - -public: - ControlBackend() - : m_rialtoClientState{ApplicationState::UNKNOWN}, m_controlClient{std::make_shared(*this)}, - m_control{IControlFactory::createFactory()->createControl()} - { - if (!m_control) - { - GST_ERROR("Unable to create control"); - return; - } - if (!m_control->registerClient(m_controlClient, m_rialtoClientState)) - { - GST_ERROR("Unable to register client"); - return; - } - } - - ~ControlBackend() final { m_control.reset(); } - - void removeControlBackend() override { m_control.reset(); } - - bool waitForRunning() override - { - std::unique_lock lock{m_mutex}; - if (ApplicationState::RUNNING == m_rialtoClientState) - { - return true; - } - m_stateCv.wait_for(lock, std::chrono::seconds{1}, - [&]() { return m_rialtoClientState == ApplicationState::RUNNING; }); - return ApplicationState::RUNNING == m_rialtoClientState; - } - -private: - void onApplicationStateChanged(ApplicationState state) - { - GST_INFO("Rialto Client application state changed to: %s", - state == ApplicationState::RUNNING ? "Active" : "Inactive/Unknown"); - std::unique_lock lock{m_mutex}; - m_rialtoClientState = state; - m_stateCv.notify_one(); - } - -private: - ApplicationState m_rialtoClientState; - std::shared_ptr m_controlClient; - std::shared_ptr m_control; - std::mutex m_mutex; - std::condition_variable m_stateCv; -}; -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/ControlBackendInterface.h b/middleware/rialto-gstreamer/source/ControlBackendInterface.h deleted file mode 100644 index 1d74933ae..000000000 --- a/middleware/rialto-gstreamer/source/ControlBackendInterface.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "ControlCommon.h" - -namespace firebolt::rialto::client -{ -class ControlBackendInterface -{ -public: - virtual ~ControlBackendInterface() = default; - virtual void removeControlBackend() = 0; - virtual bool waitForRunning() = 0; -}; -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/GStreamerEMEUtils.cpp b/middleware/rialto-gstreamer/source/GStreamerEMEUtils.cpp deleted file mode 100644 index e05d44e5d..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerEMEUtils.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include - -#include "GStreamerEMEUtils.h" -#include "GStreamerUtils.h" -#include "GstreamerCatLog.h" -#include "RialtoGStreamerEMEProtectionMetadata.h" - -#define GST_CAT_DEFAULT rialtoGStreamerCat -void getEncryptedFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata) -{ - gboolean encrypted = FALSE; - gst_structure_get_boolean(protectionMeta->info, "encrypted", &encrypted); - metadata.encrypted = encrypted; -} - -void getMediaKeySessionIdFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, - BufferProtectionMetadata &metadata) -{ - gint mediaKeySessionId = 0; - gst_structure_get_int(protectionMeta->info, "mks_id", &mediaKeySessionId); - metadata.mediaKeySessionId = mediaKeySessionId; -} - -void getKIDFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata) -{ - const GValue *value = gst_structure_get_value(protectionMeta->info, "kid"); - if (value) - { - GstBuffer *keyIDBuffer = gst_value_get_buffer(value); - if (keyIDBuffer) - { - GstMappedBuffer mappedKeyID(keyIDBuffer, GST_MAP_READ); - if (mappedKeyID) - { - metadata.kid = std::vector(mappedKeyID.data(), mappedKeyID.data() + mappedKeyID.size()); - } - } - } -} - -void getIVFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata) -{ - unsigned ivSize = 0; - gst_structure_get_uint(protectionMeta->info, "iv_size", &ivSize); - if (!ivSize && !g_strcmp0(gst_structure_get_string(protectionMeta->info, "cipher-mode"), "cbcs")) - { - // in case of cbcs, the same initialization vector is used to decrypt all the blocks - gst_structure_get_uint(protectionMeta->info, "constant_iv_size", &ivSize); - } - const GValue *value = gst_structure_get_value(protectionMeta->info, "iv"); - if (value) - { - GstBuffer *ivBuffer = gst_value_get_buffer(value); - if (ivBuffer) - { - GstMappedBuffer mappedIV(ivBuffer, GST_MAP_READ); - if (mappedIV && (ivSize == mappedIV.size())) - { - metadata.iv = std::vector(mappedIV.data(), mappedIV.data() + mappedIV.size()); - } - } - } -} - -void getSubSamplesFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, BufferProtectionMetadata &metadata) -{ - unsigned int subSampleCount = 0; - gst_structure_get_uint(protectionMeta->info, "subsample_count", &subSampleCount); - - if (subSampleCount) - { - const GValue *value = gst_structure_get_value(protectionMeta->info, "subsamples"); - if (value) - { - GstBuffer *subSamplesBuffer = gst_value_get_buffer(value); - if (subSamplesBuffer) - { - GstMappedBuffer mappedSubSamples(subSamplesBuffer, GST_MAP_READ); - if (mappedSubSamples && - ((mappedSubSamples.size() / (sizeof(int16_t) + sizeof(int32_t))) == subSampleCount)) - { - std::vector subSamples(mappedSubSamples.data(), - mappedSubSamples.data() + mappedSubSamples.size()); - //'senc' atom - // unsigned int(16) subsample_count; - //{ - // unsigned int(16) BytesOfClearData; - // unsigned int(32) BytesOfEncryptedData; - //}[subsample_count] - size_t subSampleOffset = 0; - for (unsigned int subSampleIdx = 0; subSampleIdx < subSampleCount; ++subSampleIdx) - { - uint16_t bytesOfClearData = (uint16_t)subSamples[subSampleOffset] << 8 | - (uint16_t)subSamples[subSampleOffset + 1]; - uint32_t bytesOfEncryptedData = (uint32_t)subSamples[subSampleOffset + 2] << 24 | - (uint32_t)subSamples[subSampleOffset + 3] << 16 | - (uint32_t)subSamples[subSampleOffset + 4] << 8 | - (uint32_t)subSamples[subSampleOffset + 5]; - metadata.subsamples.push_back( - std::make_pair((uint32_t)bytesOfClearData, (uint32_t)bytesOfEncryptedData)); - subSampleOffset += sizeof(int16_t) + sizeof(int32_t); - } - } - } - } - } -} - -void getInitWithLast15FromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, - BufferProtectionMetadata &metadata) -{ - guint initWithLast15 = 0; - gst_structure_get_uint(protectionMeta->info, "init_with_last_15", &initWithLast15); - metadata.initWithLast15 = initWithLast15; -} - -void getEncryptionSchemeFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, - BufferProtectionMetadata &metadata) -{ - const char *cipherModeBuf = gst_structure_get_string(protectionMeta->info, "cipher-mode"); - GST_INFO("Retrieved encryption scheme '%s' from protection metadata.", cipherModeBuf ? cipherModeBuf : "unknown"); - if (g_strcmp0(cipherModeBuf, "cbcs") == 0) - { - metadata.cipherMode = firebolt::rialto::CipherMode::CBCS; - } - else if (g_strcmp0(cipherModeBuf, "cenc") == 0) - { - metadata.cipherMode = firebolt::rialto::CipherMode::CENC; - } - else if (g_strcmp0(cipherModeBuf, "cbc1") == 0) - { - metadata.cipherMode = firebolt::rialto::CipherMode::CBC1; - } - else if (g_strcmp0(cipherModeBuf, "cens") == 0) - { - metadata.cipherMode = firebolt::rialto::CipherMode::CENS; - } - else - { - if (cipherModeBuf) - { - GST_ERROR("Unknown encryption scheme '%s'!", cipherModeBuf); - } - else - { - GST_ERROR("Missing encryption scheme!"); - } - metadata.cipherMode = firebolt::rialto::CipherMode::UNKNOWN; - } -} - -void getEncryptionPatternFromProtectionMetadata(GstRialtoProtectionMetadata *protectionMeta, - BufferProtectionMetadata &metadata) -{ - if (gst_structure_get_uint(protectionMeta->info, "crypt_byte_block", &metadata.cryptBlocks) == false) - { - GST_INFO("Failed to get crypt_byte_block value!"); - return; - } - if (gst_structure_get_uint(protectionMeta->info, "skip_byte_block", &metadata.skipBlocks) == false) - { - GST_INFO("Failed to get skip_byte_block value!"); - return; - } - - GST_INFO("Successful retrieval of 'crypt_byte_block' and 'skip_byte_block'."); - metadata.encryptionPatternSet = true; -} - -void ProcessProtectionMetadata(GstBuffer *buffer, BufferProtectionMetadata &metadata) -{ - if (buffer == nullptr) - return; - - GstRialtoProtectionMetadata *protectionMeta = reinterpret_cast( - gst_buffer_get_meta(buffer, GST_RIALTO_PROTECTION_METADATA_GET_TYPE)); - if (protectionMeta) - { - getEncryptedFromProtectionMetadata(protectionMeta, metadata); - if (metadata.encrypted) - { - getMediaKeySessionIdFromProtectionMetadata(protectionMeta, metadata); - getKIDFromProtectionMetadata(protectionMeta, metadata); - getIVFromProtectionMetadata(protectionMeta, metadata); - getSubSamplesFromProtectionMetadata(protectionMeta, metadata); - getInitWithLast15FromProtectionMetadata(protectionMeta, metadata); - getEncryptionSchemeFromProtectionMetadata(protectionMeta, metadata); - getEncryptionPatternFromProtectionMetadata(protectionMeta, metadata); - } - } -} diff --git a/middleware/rialto-gstreamer/source/GStreamerEMEUtils.h b/middleware/rialto-gstreamer/source/GStreamerEMEUtils.h deleted file mode 100644 index 5a5a2b5aa..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerEMEUtils.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once -#include -#include -#include - -#include -#include - -struct BufferProtectionMetadata -{ - BufferProtectionMetadata() : encrypted(false) {} - - bool encrypted{false}; - int mediaKeySessionId{-1}; - std::vector iv; - std::vector kid; - // vector of bytesOfClearData, bytesOfEncryptedData - std::vector> subsamples; - uint32_t initWithLast15{0}; - - // Encryption scheme - firebolt::rialto::CipherMode cipherMode{firebolt::rialto::CipherMode::UNKNOWN}; - uint32_t cryptBlocks{0}; - uint32_t skipBlocks{0}; - bool encryptionPatternSet{false}; -}; - -void ProcessProtectionMetadata(GstBuffer *buffer, BufferProtectionMetadata &metadata); diff --git a/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.cpp b/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.cpp deleted file mode 100644 index f330f102d..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.cpp +++ /dev/null @@ -1,1280 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "GStreamerMSEMediaPlayerClient.h" -#include "Constants.h" -#include "GstreamerCatLog.h" -#include "RialtoGStreamerMSEBaseSink.h" -#include "RialtoGStreamerMSEBaseSinkPrivate.h" -#include "RialtoGStreamerMSEVideoSink.h" - -#include -#include -#include - -namespace -{ -// The start time of segment might differ from the first sample which is injected. -// That difference should not be bigger than 1 video / audio frame. -// 1 second is probably erring on the side of caution, but should not have side effect. -const int64_t segmentStartMaximumDiff = 1000000000; -const int32_t UNKNOWN_STREAMS_NUMBER = -1; - -const char *toString(const firebolt::rialto::PlaybackError &error) -{ - switch (error) - { - case firebolt::rialto::PlaybackError::DECRYPTION: - return "DECRYPTION"; - case firebolt::rialto::PlaybackError::UNKNOWN: - return "UNKNOWN"; - } - return "UNKNOWN"; -} -const char *toString(const firebolt::rialto::MediaSourceType &src) -{ - switch (src) - { - case firebolt::rialto::MediaSourceType::AUDIO: - return "AUDIO"; - case firebolt::rialto::MediaSourceType::VIDEO: - return "VIDEO"; - case firebolt::rialto::MediaSourceType::SUBTITLE: - return "SUBTITLE"; - case firebolt::rialto::MediaSourceType::UNKNOWN: - return "UNKNOWN"; - } - return "UNKNOWN"; -} -} // namespace -#define GST_CAT_DEFAULT rialtoGStreamerCat -GStreamerMSEMediaPlayerClient::GStreamerMSEMediaPlayerClient( - const std::shared_ptr &messageQueueFactory, - const std::shared_ptr &MediaPlayerClientBackend, - const uint32_t maxVideoWidth, const uint32_t maxVideoHeight) - : m_backendQueue{messageQueueFactory->createMessageQueue()}, m_messageQueueFactory{messageQueueFactory}, - m_clientBackend(MediaPlayerClientBackend), m_duration(0), m_audioStreams{UNKNOWN_STREAMS_NUMBER}, - m_videoStreams{UNKNOWN_STREAMS_NUMBER}, m_subtitleStreams{UNKNOWN_STREAMS_NUMBER}, - m_videoRectangle{0, 0, 1920, 1080}, m_streamingStopped(false), - m_maxWidth(maxVideoWidth == 0 ? DEFAULT_MAX_VIDEO_WIDTH : maxVideoWidth), - m_maxHeight(maxVideoHeight == 0 ? DEFAULT_MAX_VIDEO_HEIGHT : maxVideoHeight) -{ - m_backendQueue->start(); -} - -GStreamerMSEMediaPlayerClient::~GStreamerMSEMediaPlayerClient() -{ - stopStreaming(); -} - -void GStreamerMSEMediaPlayerClient::stopStreaming() -{ - if (!m_streamingStopped) - { - m_backendQueue->stop(); - - for (auto &source : m_attachedSources) - { - source.second.m_bufferPuller->stop(); - } - - m_streamingStopped = true; - } -} - -// Deletes client backend -> this deletes mediapipeline object -void GStreamerMSEMediaPlayerClient::destroyClientBackend() -{ - m_clientBackend.reset(); -} - -void GStreamerMSEMediaPlayerClient::notifyDuration(int64_t duration) -{ - m_backendQueue->postMessage(std::make_shared(duration, m_duration)); -} - -void GStreamerMSEMediaPlayerClient::notifyPosition(int64_t position) -{ - m_backendQueue->postMessage(std::make_shared(position, m_attachedSources)); -} - -void GStreamerMSEMediaPlayerClient::notifyNativeSize(uint32_t width, uint32_t height, double aspect) {} - -void GStreamerMSEMediaPlayerClient::notifyNetworkState(firebolt::rialto::NetworkState state) {} - -void GStreamerMSEMediaPlayerClient::notifyPlaybackState(firebolt::rialto::PlaybackState state) -{ - m_backendQueue->postMessage(std::make_shared(state, this)); -} - -void GStreamerMSEMediaPlayerClient::notifyVideoData(bool hasData) {} - -void GStreamerMSEMediaPlayerClient::notifyAudioData(bool hasData) {} - -void GStreamerMSEMediaPlayerClient::notifyNeedMediaData( - int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, - const std::shared_ptr & /*shmInfo*/) -{ - m_backendQueue->postMessage(std::make_shared(sourceId, frameCount, needDataRequestId, this)); - - return; -} - -void GStreamerMSEMediaPlayerClient::notifyCancelNeedMediaData(int sourceId) {} - -void GStreamerMSEMediaPlayerClient::notifyQos(int32_t sourceId, const firebolt::rialto::QosInfo &qosInfo) -{ - m_backendQueue->postMessage(std::make_shared(sourceId, qosInfo, this)); -} - -void GStreamerMSEMediaPlayerClient::notifyBufferUnderflow(int32_t sourceId) -{ - m_backendQueue->postMessage(std::make_shared(sourceId, this)); -} - -void GStreamerMSEMediaPlayerClient::notifyPlaybackError(int32_t sourceId, firebolt::rialto::PlaybackError error) -{ - m_backendQueue->postMessage(std::make_shared(sourceId, error, this)); -} - -void GStreamerMSEMediaPlayerClient::notifySourceFlushed(int32_t sourceId) -{ - m_backendQueue->postMessage(std::make_shared(sourceId, this)); -} - -void GStreamerMSEMediaPlayerClient::getPositionDo(int64_t *position, int32_t sourceId) -{ - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - *position = -1; - return; - } - - if (m_clientBackend && m_clientBackend->getPosition(*position)) - { - sourceIt->second.m_position = *position; - } - else - { - *position = sourceIt->second.m_position; - } -} - -int64_t GStreamerMSEMediaPlayerClient::getPosition(int32_t sourceId) -{ - int64_t position; - m_backendQueue->callInEventLoop([&]() { getPositionDo(&position, sourceId); }); - return position; -} - -bool GStreamerMSEMediaPlayerClient::setImmediateOutput(int32_t sourceId, bool immediateOutput) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setImmediateOutput(sourceId, immediateOutput); }); - return status; -} - -bool GStreamerMSEMediaPlayerClient::getImmediateOutput(int32_t sourceId, bool &immediateOutput) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getImmediateOutput(sourceId, immediateOutput); }); - return status; -} - -bool GStreamerMSEMediaPlayerClient::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() - { status = m_clientBackend->getStats(sourceId, renderedFrames, droppedFrames); }); - return status; -} - -bool GStreamerMSEMediaPlayerClient::createBackend() -{ - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - if (!m_clientBackend) - { - GST_ERROR("Client backend is NULL"); - result = false; - return; - } - m_clientBackend->createMediaPlayerBackend(shared_from_this(), m_maxWidth, m_maxHeight); - - if (m_clientBackend->isMediaPlayerBackendCreated()) - { - std::string utf8url = "mse://1"; - firebolt::rialto::MediaType mediaType = firebolt::rialto::MediaType::MSE; - if (!m_clientBackend->load(mediaType, "", utf8url)) - { - GST_ERROR("Could not load RialtoClient"); - return; - } - result = true; - } - else - { - GST_ERROR("Media player backend could not be created"); - } - }); - - return result; -} - -StateChangeResult GStreamerMSEMediaPlayerClient::play(int32_t sourceId) -{ - StateChangeResult result = StateChangeResult::NOT_ATTACHED; - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - GST_ERROR("Cannot play - there's no attached source with id %d", sourceId); - result = StateChangeResult::NOT_ATTACHED; - return; - } - - if (m_serverPlaybackState == firebolt::rialto::PlaybackState::PLAYING) - { - GST_INFO("Server is already playing"); - sourceIt->second.m_state = ClientState::PLAYING; - - if (checkIfAllAttachedSourcesInStates({ClientState::PLAYING})) - { - m_clientState = ClientState::PLAYING; - } - - result = StateChangeResult::SUCCESS_SYNC; - return; - } - - sourceIt->second.m_state = ClientState::AWAITING_PLAYING; - - if (m_clientState == ClientState::PAUSED) - { - // If one source is AWAITING_PLAYING, the other source can still be PLAYING. - // This happends when we are switching out audio. - if (checkIfAllAttachedSourcesInStates({ClientState::AWAITING_PLAYING, ClientState::PLAYING})) - { - GST_INFO("Sending play command"); - m_clientBackend->play(); - m_clientState = ClientState::AWAITING_PLAYING; - } - else - { - GST_DEBUG("Not all sources are ready to play"); - } - } - else - { - GST_WARNING("Not in PAUSED state in %u state", static_cast(m_clientState)); - } - - result = StateChangeResult::SUCCESS_ASYNC; - sourceIt->second.m_delegate->postAsyncStart(); - }); - - return result; -} - -StateChangeResult GStreamerMSEMediaPlayerClient::pause(int32_t sourceId) -{ - StateChangeResult result = StateChangeResult::NOT_ATTACHED; - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - GST_WARNING("Cannot pause - there's no attached source with id %d", sourceId); - - result = StateChangeResult::NOT_ATTACHED; - return; - } - - if (m_serverPlaybackState == firebolt::rialto::PlaybackState::PAUSED && - m_clientState != ClientState::AWAITING_PLAYING && m_clientState != ClientState::AWAITING_PAUSED) - { - // if the server is already paused and we are not in async, we don't need to send pause command - GST_INFO("Server is already paused"); - sourceIt->second.m_state = ClientState::PAUSED; - - if (checkIfAllAttachedSourcesInStates({ClientState::PAUSED})) - { - m_clientState = ClientState::PAUSED; - } - - result = StateChangeResult::SUCCESS_SYNC; - } - else - { - sourceIt->second.m_state = ClientState::AWAITING_PAUSED; - - bool shouldPause = false; - if (m_clientState == ClientState::READY) - { - if (checkIfAllAttachedSourcesInStates({ClientState::AWAITING_PAUSED})) - { - shouldPause = true; - } - else - { - GST_DEBUG("Not all attached sources are ready to pause"); - } - } - else if (m_clientState == ClientState::AWAITING_PLAYING || m_clientState == ClientState::PLAYING) - { - shouldPause = true; - } - else - { - GST_DEBUG("Cannot pause in %u state", static_cast(m_clientState)); - } - - if (shouldPause) - { - GST_INFO("Sending pause command in %u state", static_cast(m_clientState)); - m_clientBackend->pause(); - m_clientState = ClientState::AWAITING_PAUSED; - } - - result = StateChangeResult::SUCCESS_ASYNC; - sourceIt->second.m_delegate->postAsyncStart(); - } - }); - - return result; -} - -void GStreamerMSEMediaPlayerClient::stop() -{ - m_backendQueue->callInEventLoop([&]() { m_clientBackend->stop(); }); -} - -void GStreamerMSEMediaPlayerClient::setPlaybackRate(double rate) -{ - m_backendQueue->callInEventLoop([&]() { m_clientBackend->setPlaybackRate(rate); }); -} - -void GStreamerMSEMediaPlayerClient::flush(int32_t sourceId, bool resetTime) -{ - m_backendQueue->callInEventLoop( - [&]() - { - bool async{true}; - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - GST_ERROR("Cannot flush - there's no attached source with id %d", sourceId); - return; - } - if (!m_clientBackend->flush(sourceId, resetTime, async)) - { - GST_ERROR("Flush operation failed for source with id %d", sourceId); - return; - } - sourceIt->second.m_isFlushing = true; - sourceIt->second.m_bufferPuller->stop(); - - if (async) - { - GST_INFO("Flush request sent for async source %d. Sink will lose state now", sourceId); - sourceIt->second.m_delegate->lostState(); - - sourceIt->second.m_state = ClientState::AWAITING_PAUSED; - if (m_clientState == ClientState::PLAYING) - { - m_clientState = ClientState::AWAITING_PLAYING; - } - else if (m_clientState == ClientState::PAUSED) - { - m_clientState = ClientState::AWAITING_PAUSED; - } - } - }); -} - -void GStreamerMSEMediaPlayerClient::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, - double appliedRate, uint64_t stopPosition) -{ - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - GST_ERROR("Cannot Set Source Position - there's no attached source with id %d", sourceId); - return; - } - if (!m_clientBackend->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition)) - { - GST_ERROR("Set Source Position operation failed for source with id %d", sourceId); - return; - } - sourceIt->second.m_position = position; - }); -} - -void GStreamerMSEMediaPlayerClient::setSubtitleOffset(int32_t sourceId, int64_t position) -{ - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - GST_ERROR("Cannot Set Subtitle Offset - there's no attached source with id %d", sourceId); - return; - } - if (!m_clientBackend->setSubtitleOffset(sourceId, position)) - { - GST_ERROR("Set Subtitle Offset operation failed for source with id %d", sourceId); - return; - } - }); -} - -void GStreamerMSEMediaPlayerClient::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, - bool audioAac) -{ - m_backendQueue->callInEventLoop( - [&]() - { - if (!m_clientBackend->processAudioGap(position, duration, discontinuityGap, audioAac)) - { - GST_ERROR("Process Audio Gap operation failed"); - return; - } - }); -} - -bool GStreamerMSEMediaPlayerClient::attachSource(std::unique_ptr &source, - RialtoMSEBaseSink *rialtoSink, - const std::shared_ptr &delegate) -{ - if (source->getType() != firebolt::rialto::MediaSourceType::AUDIO && - source->getType() != firebolt::rialto::MediaSourceType::VIDEO && - source->getType() != firebolt::rialto::MediaSourceType::SUBTITLE) - { - GST_WARNING_OBJECT(rialtoSink, "Invalid source type %u", static_cast(source->getType())); - return false; - } - - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - result = m_clientBackend->attachSource(source); - - if (result) - { - std::shared_ptr bufferParser; - if (source->getType() == firebolt::rialto::MediaSourceType::AUDIO) - { - bufferParser = std::make_shared(); - } - else if (source->getType() == firebolt::rialto::MediaSourceType::VIDEO) - { - bufferParser = std::make_shared(); - } - else if (source->getType() == firebolt::rialto::MediaSourceType::SUBTITLE) - { - bufferParser = std::make_shared(); - } - - std::shared_ptr bufferPuller = std::make_shared(m_messageQueueFactory, - GST_ELEMENT_CAST(rialtoSink), - bufferParser, delegate); - - if (m_attachedSources.find(source->getId()) == m_attachedSources.end()) - { - m_attachedSources.emplace(source->getId(), - AttachedSource(rialtoSink, bufferPuller, delegate, source->getType())); - - delegate->setSourceId(source->getId()); - bufferPuller->start(); - } - } - - sendAllSourcesAttachedIfPossibleInternal(); - }); - - return result; -} - -void GStreamerMSEMediaPlayerClient::sendAllSourcesAttachedIfPossible() -{ - m_backendQueue->callInEventLoop([&]() { sendAllSourcesAttachedIfPossibleInternal(); }); -} - -void GStreamerMSEMediaPlayerClient::sendAllSourcesAttachedIfPossibleInternal() -{ - if (!m_wasAllSourcesAttachedSent && areAllStreamsAttached()) - { - // RialtoServer doesn't support dynamic source attachment. - // It means that when we notify that all sources were attached, we cannot add any more sources in the current session - GST_INFO("All sources attached"); - m_clientBackend->allSourcesAttached(); - m_wasAllSourcesAttachedSent = true; - m_clientState = ClientState::READY; - - // In playbin3 streams, confirmation about number of available sources comes after attaching the source, - // so we need to check if all sources are ready to pause - if (checkIfAllAttachedSourcesInStates({ClientState::AWAITING_PAUSED})) - { - GST_INFO("Sending pause command, because all attached sources are ready to pause"); - m_clientBackend->pause(); - m_clientState = ClientState::AWAITING_PAUSED; - } - } -} - -void GStreamerMSEMediaPlayerClient::removeSource(int32_t sourceId) -{ - m_backendQueue->callInEventLoop( - [&]() - { - if (!m_clientBackend->removeSource(sourceId)) - { - GST_WARNING("Remove source %d failed", sourceId); - } - m_attachedSources.erase(sourceId); - }); -} - -void GStreamerMSEMediaPlayerClient::handlePlaybackStateChange(firebolt::rialto::PlaybackState state) -{ - GST_DEBUG("Received state change to state %u", static_cast(state)); - m_backendQueue->callInEventLoop( - [&]() - { - m_serverPlaybackState = state; - switch (state) - { - case firebolt::rialto::PlaybackState::PAUSED: - case firebolt::rialto::PlaybackState::PLAYING: - { - if (state == firebolt::rialto::PlaybackState::PAUSED && m_clientState == ClientState::AWAITING_PAUSED) - { - m_clientState = ClientState::PAUSED; - } - else if (state == firebolt::rialto::PlaybackState::PLAYING && - m_clientState == ClientState::AWAITING_PLAYING) - { - m_clientState = ClientState::PLAYING; - } - else if (state == firebolt::rialto::PlaybackState::PLAYING && - m_clientState == ClientState::AWAITING_PAUSED) - { - GST_WARNING("Outdated Playback State change to PLAYING received. Discarding..."); - break; - } - - for (auto &source : m_attachedSources) - { - if (state == firebolt::rialto::PlaybackState::PAUSED && - source.second.m_state == ClientState::AWAITING_PAUSED) - { - source.second.m_state = ClientState::PAUSED; - } - else if (state == firebolt::rialto::PlaybackState::PLAYING && - source.second.m_state == ClientState::AWAITING_PLAYING) - { - source.second.m_state = ClientState::PLAYING; - } - source.second.m_delegate->handleStateChanged(state); - } - - break; - } - case firebolt::rialto::PlaybackState::END_OF_STREAM: - { - for (const auto &source : m_attachedSources) - { - source.second.m_delegate->handleEos(); - } - } - break; - case firebolt::rialto::PlaybackState::SEEK_DONE: - { - GST_WARNING("firebolt::rialto::PlaybackState::SEEK_DONE notification not supported"); - break; - } - case firebolt::rialto::PlaybackState::FAILURE: - { - for (const auto &source : m_attachedSources) - { - source.second.m_delegate->handleError("Rialto server playback failed"); - } - for (auto &source : m_attachedSources) - { - source.second.m_position = 0; - } - - break; - } - break; - default: - break; - } - }); -} - -void GStreamerMSEMediaPlayerClient::handleSourceFlushed(int32_t sourceId) -{ - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - GST_ERROR("Cannot finish flush - there's no attached source with id %d", sourceId); - return; - } - if (!sourceIt->second.m_isFlushing) - { - GST_ERROR("Cannot finish flush - source with id %d is not flushing!", sourceId); - return; - } - sourceIt->second.m_isFlushing = false; - sourceIt->second.m_bufferPuller->start(); - sourceIt->second.m_delegate->handleFlushCompleted(); - }); -} - -void GStreamerMSEMediaPlayerClient::setVideoRectangle(const std::string &rectangleString) -{ - m_backendQueue->callInEventLoop( - [&]() - { - if (!m_clientBackend || !m_clientBackend->isMediaPlayerBackendCreated()) - { - GST_WARNING("Missing RialtoClient backend - can't set video window now"); - return; - } - - if (rectangleString.empty()) - { - GST_WARNING("Empty video rectangle string"); - return; - } - - Rectangle rect = {0, 0, 0, 0}; - if (sscanf(rectangleString.c_str(), "%u,%u,%u,%u", &rect.x, &rect.y, &rect.width, &rect.height) != 4) - { - GST_WARNING("Invalid video rectangle values"); - return; - } - - m_clientBackend->setVideoWindow(rect.x, rect.y, rect.width, rect.height); - m_videoRectangle = rect; - }); -} - -std::string GStreamerMSEMediaPlayerClient::getVideoRectangle() -{ - char rectangle[64]; - m_backendQueue->callInEventLoop( - [&]() - { - sprintf(rectangle, "%u,%u,%u,%u", m_videoRectangle.x, m_videoRectangle.y, m_videoRectangle.width, - m_videoRectangle.height); - }); - - return std::string(rectangle); -} - -bool GStreamerMSEMediaPlayerClient::renderFrame(int32_t sourceId) -{ - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - result = m_clientBackend->renderFrame(); - if (result) - { - // RialtoServer's video sink should drop PAUSED state due to skipping prerolled buffer in PAUSED state - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt != m_attachedSources.end()) - { - sourceIt->second.m_delegate->lostState(); - } - } - }); - return result; -} - -void GStreamerMSEMediaPlayerClient::setVolume(double targetVolume, uint32_t volumeDuration, - firebolt::rialto::EaseType easeType) -{ - m_backendQueue->callInEventLoop([&]() { m_clientBackend->setVolume(targetVolume, volumeDuration, easeType); }); -} - -bool GStreamerMSEMediaPlayerClient::getVolume(double &volume) -{ - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getVolume(volume); }); - return status; -} - -void GStreamerMSEMediaPlayerClient::setMute(bool mute, int32_t sourceId) -{ - m_backendQueue->callInEventLoop([&]() { m_clientBackend->setMute(mute, sourceId); }); -} - -bool GStreamerMSEMediaPlayerClient::getMute(int sourceId) -{ - bool mute{false}; - m_backendQueue->callInEventLoop([&]() { m_clientBackend->getMute(mute, sourceId); }); - - return mute; -} - -void GStreamerMSEMediaPlayerClient::setTextTrackIdentifier(const std::string &textTrackIdentifier) -{ - m_backendQueue->callInEventLoop([&]() { m_clientBackend->setTextTrackIdentifier(textTrackIdentifier); }); -} - -std::string GStreamerMSEMediaPlayerClient::getTextTrackIdentifier() -{ - std::string getTextTrackIdentifier; - m_backendQueue->callInEventLoop([&]() { m_clientBackend->getTextTrackIdentifier(getTextTrackIdentifier); }); - return getTextTrackIdentifier; -} - -bool GStreamerMSEMediaPlayerClient::setLowLatency(bool lowLatency) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setLowLatency(lowLatency); }); - return status; -} - -bool GStreamerMSEMediaPlayerClient::setSync(bool sync) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setSync(sync); }); - return status; -} - -bool GStreamerMSEMediaPlayerClient::getSync(bool &sync) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getSync(sync); }); - return status; -} - -bool GStreamerMSEMediaPlayerClient::setSyncOff(bool syncOff) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setSyncOff(syncOff); }); - return status; -} - -bool GStreamerMSEMediaPlayerClient::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setStreamSyncMode(sourceId, streamSyncMode); }); - return status; -} - -bool GStreamerMSEMediaPlayerClient::getStreamSyncMode(int32_t &streamSyncMode) -{ - if (!m_clientBackend) - { - return false; - } - - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getStreamSyncMode(streamSyncMode); }); - return status; -} - -ClientState GStreamerMSEMediaPlayerClient::getClientState() -{ - ClientState state{ClientState::IDLE}; - m_backendQueue->callInEventLoop([&]() { state = m_clientState; }); - return state; -} - -void GStreamerMSEMediaPlayerClient::handleStreamCollection(int32_t audioStreams, int32_t videoStreams, - int32_t subtitleStreams) -{ - m_backendQueue->callInEventLoop( - [&]() - { - if (m_audioStreams == UNKNOWN_STREAMS_NUMBER) - m_audioStreams = audioStreams; - if (m_videoStreams == UNKNOWN_STREAMS_NUMBER) - m_videoStreams = videoStreams; - if (m_subtitleStreams == UNKNOWN_STREAMS_NUMBER) - m_subtitleStreams = subtitleStreams; - - GST_INFO("Updated number of streams. New streams' numbers; video=%d, audio=%d, text=%d", m_videoStreams, - m_audioStreams, m_subtitleStreams); - }); -} - -void GStreamerMSEMediaPlayerClient::setBufferingLimit(uint32_t limitBufferingMs) -{ - if (!m_clientBackend) - { - return; - } - m_backendQueue->callInEventLoop([&]() { m_clientBackend->setBufferingLimit(limitBufferingMs); }); -} - -uint32_t GStreamerMSEMediaPlayerClient::getBufferingLimit() -{ - if (!m_clientBackend) - { - return kDefaultBufferingLimit; - } - - uint32_t result{kDefaultBufferingLimit}; - m_backendQueue->callInEventLoop([&]() { m_clientBackend->getBufferingLimit(result); }); - return result; -} - -void GStreamerMSEMediaPlayerClient::setUseBuffering(bool useBuffering) -{ - if (!m_clientBackend) - { - return; - } - m_backendQueue->callInEventLoop([&]() { m_clientBackend->setUseBuffering(useBuffering); }); -} - -bool GStreamerMSEMediaPlayerClient::getUseBuffering() -{ - if (!m_clientBackend) - { - return kDefaultUseBuffering; - } - - bool result{kDefaultUseBuffering}; - m_backendQueue->callInEventLoop([&]() { m_clientBackend->getUseBuffering(result); }); - return result; -} - -bool GStreamerMSEMediaPlayerClient::switchSource(const std::unique_ptr &source) -{ - bool result = false; - m_backendQueue->callInEventLoop([&]() { result = m_clientBackend->switchSource(source); }); - - return result; -} - -bool GStreamerMSEMediaPlayerClient::checkIfAllAttachedSourcesInStates(const std::vector &states) -{ - return std::all_of(m_attachedSources.begin(), m_attachedSources.end(), [states](const auto &source) - { return std::find(states.begin(), states.end(), source.second.m_state) != states.end(); }); -} - -bool GStreamerMSEMediaPlayerClient::areAllStreamsAttached() -{ - int32_t attachedVideoSources = 0; - int32_t attachedAudioSources = 0; - int32_t attachedSubtitleSources = 0; - for (auto &source : m_attachedSources) - { - if (source.second.getType() == firebolt::rialto::MediaSourceType::VIDEO) - { - attachedVideoSources++; - } - else if (source.second.getType() == firebolt::rialto::MediaSourceType::AUDIO) - { - attachedAudioSources++; - } - else if (source.second.getType() == firebolt::rialto::MediaSourceType::SUBTITLE) - { - attachedSubtitleSources++; - } - } - - return attachedVideoSources == m_videoStreams && attachedAudioSources == m_audioStreams && - attachedSubtitleSources == m_subtitleStreams; -} - -bool GStreamerMSEMediaPlayerClient::requestPullBuffer(int streamId, size_t frameCount, unsigned int needDataRequestId) -{ - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(streamId); - if (sourceIt == m_attachedSources.end()) - { - GST_ERROR("There's no attached source with id %d", streamId); - - result = false; - return; - } - result = sourceIt->second.m_bufferPuller->requestPullBuffer(streamId, frameCount, needDataRequestId, this); - }); - - return result; -} - -bool GStreamerMSEMediaPlayerClient::handleQos(int sourceId, firebolt::rialto::QosInfo qosInfo) -{ - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - result = false; - return; - } - sourceIt->second.m_delegate->handleQos(qosInfo.processed, qosInfo.dropped); - result = true; - }); - - return result; -} - -bool GStreamerMSEMediaPlayerClient::handleBufferUnderflow(int sourceId) -{ - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - result = false; - return; - } - - rialto_mse_base_handle_rialto_server_sent_buffer_underflow(sourceIt->second.m_rialtoSink); - - result = true; - }); - - return result; -} - -bool GStreamerMSEMediaPlayerClient::handlePlaybackError(int sourceId, firebolt::rialto::PlaybackError error) -{ - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - auto sourceIt = m_attachedSources.find(sourceId); - if (sourceIt == m_attachedSources.end()) - { - result = false; - return; - } - - // Even though rialto has only reported a non-fatal error, still fail the pipeline from rialto-gstreamer - GST_ERROR("Received Playback error '%s', posting error on %s sink", toString(error), - toString(sourceIt->second.getType())); - if (firebolt::rialto::PlaybackError::DECRYPTION == error) - { - sourceIt->second.m_delegate->handleError("Rialto dropped a frame that failed to decrypt", - GST_STREAM_ERROR_DECRYPT); - } - else - { - sourceIt->second.m_delegate->handleError("Rialto server playback failed"); - } - - result = true; - }); - - return result; -} - -firebolt::rialto::AddSegmentStatus GStreamerMSEMediaPlayerClient::addSegment( - unsigned int needDataRequestId, const std::unique_ptr &mediaSegment) -{ - // rialto client's addSegment call is MT safe, so it's ok to call it from the Puller's thread - return m_clientBackend->addSegment(needDataRequestId, mediaSegment); -} - -BufferPuller::BufferPuller(const std::shared_ptr &messageQueueFactory, GstElement *rialtoSink, - const std::shared_ptr &bufferParser, - const std::shared_ptr &delegate) - : m_queue{messageQueueFactory->createMessageQueue()}, m_rialtoSink(rialtoSink), m_bufferParser(bufferParser), - m_delegate{delegate} -{ -} - -void BufferPuller::start() -{ - m_queue->start(); -} - -void BufferPuller::stop() -{ - m_queue->stop(); -} - -bool BufferPuller::requestPullBuffer(int sourceId, size_t frameCount, unsigned int needDataRequestId, - GStreamerMSEMediaPlayerClient *player) -{ - return m_queue->postMessage(std::make_shared(sourceId, frameCount, needDataRequestId, m_rialtoSink, - m_bufferParser, *m_queue, player, m_delegate)); -} - -HaveDataMessage::HaveDataMessage(firebolt::rialto::MediaSourceStatus status, int sourceId, - unsigned int needDataRequestId, GStreamerMSEMediaPlayerClient *player) - : m_status(status), m_sourceId(sourceId), m_needDataRequestId(needDataRequestId), m_player(player) -{ -} - -void HaveDataMessage::handle() -{ - if (m_player->m_attachedSources.find(m_sourceId) == m_player->m_attachedSources.end()) - { - GST_WARNING("Source id %d is invalid", m_sourceId); - return; - } - - m_player->m_clientBackend->haveData(m_status, m_needDataRequestId); -} - -PullBufferMessage::PullBufferMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, - GstElement *rialtoSink, const std::shared_ptr &bufferParser, - IMessageQueue &pullerQueue, GStreamerMSEMediaPlayerClient *player, - const std::shared_ptr &delegate) - : m_sourceId(sourceId), m_frameCount(frameCount), m_needDataRequestId(needDataRequestId), m_rialtoSink(rialtoSink), - m_bufferParser(bufferParser), m_pullerQueue(pullerQueue), m_player(player), m_delegate{delegate} -{ -} - -void PullBufferMessage::handle() -{ - bool isEos = false; - unsigned int addedSegments = 0; - - for (unsigned int frame = 0; frame < m_frameCount; ++frame) - { - if (!m_delegate->isReadyToSendData()) - { - GST_INFO_OBJECT(m_rialtoSink, "Not ready to send data - segment or eos not received yet"); - break; - } - GstRefSample sample = m_delegate->getFrontSample(); - if (!sample) - { - if (m_delegate->isEos()) - { - isEos = true; - } - else - { - // it's not a critical issue. It might be caused by receiving too many need data requests. - GST_INFO_OBJECT(m_rialtoSink, "Could not get a sample"); - } - break; - } - - // we pass GstMapInfo's pointers on data buffers to RialtoClient - // so we need to hold it until RialtoClient copies them to shm - GstBuffer *buffer = sample.getBuffer(); - GstMapInfo map; - if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) - { - GST_ERROR_OBJECT(m_rialtoSink, "Could not map buffer"); - m_delegate->popSample(); - continue; - } - - std::unique_ptr mseData = - m_bufferParser->parseBuffer(sample, buffer, map, m_sourceId); - if (!mseData) - { - GST_ERROR_OBJECT(m_rialtoSink, "No data returned from the parser"); - gst_buffer_unmap(buffer, &map); - m_delegate->popSample(); - continue; - } - - firebolt::rialto::AddSegmentStatus addSegmentStatus = m_player->addSegment(m_needDataRequestId, mseData); - if (addSegmentStatus == firebolt::rialto::AddSegmentStatus::NO_SPACE) - { - gst_buffer_unmap(buffer, &map); - GST_INFO_OBJECT(m_rialtoSink, "There's no space to add sample"); - break; - } - - gst_buffer_unmap(buffer, &map); - m_delegate->popSample(); - addedSegments++; - } - - firebolt::rialto::MediaSourceStatus status = firebolt::rialto::MediaSourceStatus::OK; - if (isEos) - { - status = firebolt::rialto::MediaSourceStatus::EOS; - } - else if (addedSegments == 0) - { - status = firebolt::rialto::MediaSourceStatus::NO_AVAILABLE_SAMPLES; - } - - m_player->m_backendQueue->postMessage( - std::make_shared(status, m_sourceId, m_needDataRequestId, m_player)); -} - -NeedDataMessage::NeedDataMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, - GStreamerMSEMediaPlayerClient *player) - : m_sourceId(sourceId), m_frameCount(frameCount), m_needDataRequestId(needDataRequestId), m_player(player) -{ -} - -void NeedDataMessage::handle() -{ - if (!m_player->requestPullBuffer(m_sourceId, m_frameCount, m_needDataRequestId)) - { - GST_ERROR("Failed to pull buffer for sourceId=%d and NeedDataRequestId %u", m_sourceId, m_needDataRequestId); - m_player->m_backendQueue->postMessage( - std::make_shared(firebolt::rialto::MediaSourceStatus::ERROR, m_sourceId, - m_needDataRequestId, m_player)); - } -} - -PlaybackStateMessage::PlaybackStateMessage(firebolt::rialto::PlaybackState state, GStreamerMSEMediaPlayerClient *player) - : m_state(state), m_player(player) -{ -} - -void PlaybackStateMessage::handle() -{ - m_player->handlePlaybackStateChange(m_state); -} - -QosMessage::QosMessage(int sourceId, firebolt::rialto::QosInfo qosInfo, GStreamerMSEMediaPlayerClient *player) - : m_sourceId(sourceId), m_qosInfo(qosInfo), m_player(player) -{ -} - -void QosMessage::handle() -{ - if (!m_player->handleQos(m_sourceId, m_qosInfo)) - { - GST_ERROR("Failed to handle qos for sourceId=%d", m_sourceId); - } -} - -BufferUnderflowMessage::BufferUnderflowMessage(int sourceId, GStreamerMSEMediaPlayerClient *player) - : m_sourceId(sourceId), m_player(player) -{ -} - -void BufferUnderflowMessage::handle() -{ - if (!m_player->handleBufferUnderflow(m_sourceId)) - { - GST_ERROR("Failed to handle buffer underflow for sourceId=%d", m_sourceId); - } -} - -PlaybackErrorMessage::PlaybackErrorMessage(int sourceId, firebolt::rialto::PlaybackError error, - GStreamerMSEMediaPlayerClient *player) - : m_sourceId(sourceId), m_error(error), m_player(player) -{ -} - -void PlaybackErrorMessage::handle() -{ - if (!m_player->handlePlaybackError(m_sourceId, m_error)) - { - GST_ERROR("Failed to handle playback error for sourceId=%d, error %s", m_sourceId, toString(m_error)); - } -} - -SetPositionMessage::SetPositionMessage(int64_t newPosition, std::unordered_map &attachedSources) - : m_newPosition(newPosition), m_attachedSources(attachedSources) -{ -} - -void SetPositionMessage::handle() -{ - for (auto &source : m_attachedSources) - { - source.second.setPosition(m_newPosition); - } -} - -SetDurationMessage::SetDurationMessage(int64_t newDuration, int64_t &targetDuration) - : m_newDuration(newDuration), m_targetDuration(targetDuration) -{ -} - -void SetDurationMessage::handle() -{ - m_targetDuration = m_newDuration; -} - -SourceFlushedMessage::SourceFlushedMessage(int32_t sourceId, GStreamerMSEMediaPlayerClient *player) - : m_sourceId{sourceId}, m_player{player} -{ -} - -void SourceFlushedMessage::handle() -{ - m_player->handleSourceFlushed(m_sourceId); -} diff --git a/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.h b/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.h deleted file mode 100644 index 3c91a1a52..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerMSEMediaPlayerClient.h +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "BufferParser.h" -#include "Constants.h" -#include "IMediaPipeline.h" -#include "IMessageQueue.h" -#include "IPullModePlaybackDelegate.h" -#include "MediaCommon.h" -#include "MediaPlayerClientBackendInterface.h" -#include "RialtoGStreamerMSEBaseSink.h" - -#define DEFAULT_MAX_VIDEO_WIDTH 3840 -#define DEFAULT_MAX_VIDEO_HEIGHT 2160 - -class GStreamerMSEMediaPlayerClient; - -enum class ClientState -{ - IDLE, - READY, - AWAITING_PAUSED, - PAUSED, - AWAITING_PLAYING, - PLAYING -}; - -class BufferPuller -{ -public: - BufferPuller(const std::shared_ptr &messageQueueFactory, GstElement *rialtoSink, - const std::shared_ptr &bufferParser, - const std::shared_ptr &delegate); - - void start(); - void stop(); - bool requestPullBuffer(int sourceId, size_t frameCount, unsigned int needDataRequestId, - GStreamerMSEMediaPlayerClient *player); - -private: - std::unique_ptr m_queue; - GstElement *m_rialtoSink; - std::shared_ptr m_bufferParser; - std::shared_ptr m_delegate; -}; - -class AttachedSource -{ - friend class GStreamerMSEMediaPlayerClient; - -public: - AttachedSource(RialtoMSEBaseSink *rialtoSink, std::shared_ptr puller, - const std::shared_ptr &delegate, firebolt::rialto::MediaSourceType type, - ClientState state = ClientState::READY) - : m_rialtoSink(rialtoSink), m_bufferPuller(puller), m_delegate{delegate}, m_type(type), m_state(state) - { - } - - firebolt::rialto::MediaSourceType getType() const { return m_type; } - void setPosition(int64_t position) { m_position = position; } - -private: - RialtoMSEBaseSink *m_rialtoSink; - std::shared_ptr m_bufferPuller; - std::shared_ptr m_delegate; - std::unordered_set m_ongoingNeedDataRequests; - firebolt::rialto::MediaSourceType m_type = firebolt::rialto::MediaSourceType::UNKNOWN; - int64_t m_position = 0; - bool m_isFlushing = false; - ClientState m_state = ClientState::READY; -}; - -class HaveDataMessage : public Message -{ -public: - HaveDataMessage(firebolt::rialto::MediaSourceStatus status, int sourceId, unsigned int needDataRequestId, - GStreamerMSEMediaPlayerClient *player); - void handle() override; - -private: - firebolt::rialto::MediaSourceStatus m_status; - int m_sourceId; - unsigned int m_needDataRequestId; - GStreamerMSEMediaPlayerClient *m_player; -}; - -class PullBufferMessage : public Message -{ -public: - PullBufferMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, GstElement *rialtoSink, - const std::shared_ptr &bufferParser, IMessageQueue &pullerQueue, - GStreamerMSEMediaPlayerClient *player, const std::shared_ptr &delegate); - void handle() override; - -private: - int m_sourceId; - size_t m_frameCount; - unsigned int m_needDataRequestId; - GstElement *m_rialtoSink; - std::shared_ptr m_bufferParser; - IMessageQueue &m_pullerQueue; - GStreamerMSEMediaPlayerClient *m_player; - std::shared_ptr m_delegate; -}; - -class NeedDataMessage : public Message -{ -public: - NeedDataMessage(int sourceId, size_t frameCount, unsigned int needDataRequestId, - GStreamerMSEMediaPlayerClient *player); - void handle() override; - -private: - int m_sourceId; - size_t m_frameCount; - unsigned int m_needDataRequestId; - GStreamerMSEMediaPlayerClient *m_player; -}; - -class PlaybackStateMessage : public Message -{ -public: - PlaybackStateMessage(firebolt::rialto::PlaybackState state, GStreamerMSEMediaPlayerClient *player); - void handle() override; - -private: - firebolt::rialto::PlaybackState m_state; - GStreamerMSEMediaPlayerClient *m_player; -}; - -class QosMessage : public Message -{ -public: - QosMessage(int sourceId, firebolt::rialto::QosInfo qosInfo, GStreamerMSEMediaPlayerClient *player); - void handle() override; - -private: - int m_sourceId; - firebolt::rialto::QosInfo m_qosInfo; - GStreamerMSEMediaPlayerClient *m_player; -}; - -class BufferUnderflowMessage : public Message -{ -public: - BufferUnderflowMessage(int sourceId, GStreamerMSEMediaPlayerClient *player); - void handle() override; - -private: - int m_sourceId; - GStreamerMSEMediaPlayerClient *m_player; -}; - -class PlaybackErrorMessage : public Message -{ -public: - PlaybackErrorMessage(int sourceId, firebolt::rialto::PlaybackError error, GStreamerMSEMediaPlayerClient *player); - void handle() override; - -private: - int m_sourceId; - firebolt::rialto::PlaybackError m_error; - GStreamerMSEMediaPlayerClient *m_player; -}; - -class SetPositionMessage : public Message -{ -public: - SetPositionMessage(int64_t newPosition, std::unordered_map &attachedSources); - void handle() override; - -private: - int64_t m_newPosition; - std::unordered_map &m_attachedSources; -}; - -class SetDurationMessage : public Message -{ -public: - SetDurationMessage(int64_t newDuration, int64_t &targetDuration); - void handle() override; - -private: - int64_t m_newDuration; - int64_t &m_targetDuration; -}; - -class SourceFlushedMessage : public Message -{ -public: - SourceFlushedMessage(int32_t sourceId, GStreamerMSEMediaPlayerClient *player); - void handle() override; - -private: - int32_t m_sourceId; - GStreamerMSEMediaPlayerClient *m_player; -}; - -enum class StateChangeResult -{ - SUCCESS_ASYNC, - SUCCESS_SYNC, - NOT_ATTACHED -}; - -class GStreamerMSEMediaPlayerClient : public firebolt::rialto::IMediaPipelineClient, - public std::enable_shared_from_this -{ - friend class NeedDataMessage; - friend class PullBufferMessage; - friend class HaveDataMessage; - friend class QosMessage; - -public: - GStreamerMSEMediaPlayerClient( - const std::shared_ptr &messageQueueFactory, - const std::shared_ptr &MediaPlayerClientBackend, - const uint32_t maxVideoWidth, const uint32_t maxVideoHeight); - virtual ~GStreamerMSEMediaPlayerClient(); - - void notifyDuration(int64_t duration) override; - void notifyPosition(int64_t position) override; - void notifyNativeSize(uint32_t width, uint32_t height, double aspect) override; - void notifyNetworkState(firebolt::rialto::NetworkState state) override; - void notifyPlaybackState(firebolt::rialto::PlaybackState state) override; - void notifyVideoData(bool hasData) override; - void notifyAudioData(bool hasData) override; - void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, - const std::shared_ptr &shmInfo) override; - void notifyCancelNeedMediaData(int32_t sourceId) override; - void notifyQos(int32_t sourceId, const firebolt::rialto::QosInfo &qosInfo) override; - void notifyBufferUnderflow(int32_t sourceId) override; - void notifyPlaybackError(int32_t sourceId, firebolt::rialto::PlaybackError error) override; - void notifySourceFlushed(int32_t sourceId) override; - - void getPositionDo(int64_t *position, int32_t sourceId); - int64_t getPosition(int32_t sourceId); - bool setImmediateOutput(int32_t sourceId, bool immediateOutput); - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput); - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames); - - firebolt::rialto::AddSegmentStatus - addSegment(unsigned int needDataRequestId, - const std::unique_ptr &mediaSegment); - - bool createBackend(); - StateChangeResult play(int32_t sourceId); - StateChangeResult pause(int32_t sourceId); - void stop(); - void setPlaybackRate(double rate); - void flush(int32_t sourceId, bool resetTime); - void setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate = 1.0, - uint64_t stopPosition = GST_CLOCK_TIME_NONE); - void setSubtitleOffset(int32_t sourceId, int64_t position); - void processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac); - - bool attachSource(std::unique_ptr &source, - RialtoMSEBaseSink *rialtoSink, const std::shared_ptr &delegate); - void removeSource(int32_t sourceId); - void handlePlaybackStateChange(firebolt::rialto::PlaybackState state); - void handleSourceFlushed(int32_t sourceId); - void sendAllSourcesAttachedIfPossible(); - - void setVideoRectangle(const std::string &rectangleString); - std::string getVideoRectangle(); - - bool requestPullBuffer(int streamId, size_t frameCount, unsigned int needDataRequestId); - bool handleQos(int sourceId, firebolt::rialto::QosInfo qosInfo); - bool handleBufferUnderflow(int sourceId); - bool handlePlaybackError(int sourceId, firebolt::rialto::PlaybackError error); - void stopStreaming(); - void destroyClientBackend(); - bool renderFrame(int32_t sourceId); - void setVolume(double targetVolume, uint32_t volumeDuration, firebolt::rialto::EaseType easeType); - bool getVolume(double &volume); - void setMute(bool mute, int32_t sourceId); - bool getMute(int sourceId); - void setTextTrackIdentifier(const std::string &textTrackIdentifier); - std::string getTextTrackIdentifier(); - bool setLowLatency(bool lowLatency); - bool setSync(bool sync); - bool getSync(bool &sync); - bool setSyncOff(bool syncOff); - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode); - bool getStreamSyncMode(int32_t &streamSyncMode); - ClientState getClientState(); - void handleStreamCollection(int32_t audioStreams, int32_t videoStreams, int32_t subtitleStreams); - void setBufferingLimit(uint32_t limitBufferingMs); - uint32_t getBufferingLimit(); - void setUseBuffering(bool useBuffering); - bool getUseBuffering(); - bool switchSource(const std::unique_ptr &source); - -private: - bool areAllStreamsAttached(); - void sendAllSourcesAttachedIfPossibleInternal(); - bool checkIfAllAttachedSourcesInStates(const std::vector &states); - - std::unique_ptr m_backendQueue; - std::shared_ptr m_messageQueueFactory; - std::shared_ptr m_clientBackend; - int64_t m_position; - int64_t m_duration; - std::mutex m_playerMutex; - std::unordered_map m_attachedSources; - bool m_wasAllSourcesAttachedSent = false; - int32_t m_audioStreams; - int32_t m_videoStreams; - int32_t m_subtitleStreams; - - struct Rectangle - { - unsigned int x, y, width, height; - } m_videoRectangle; - - firebolt::rialto::PlaybackState m_serverPlaybackState = firebolt::rialto::PlaybackState::IDLE; - ClientState m_clientState = ClientState::IDLE; - // To check if the backend message queue and pulling of data to serve backend is stopped or not - bool m_streamingStopped; - - const uint32_t m_maxWidth; - const uint32_t m_maxHeight; -}; diff --git a/middleware/rialto-gstreamer/source/GStreamerMSEUtils.cpp b/middleware/rialto-gstreamer/source/GStreamerMSEUtils.cpp deleted file mode 100644 index 1eeadc104..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerMSEUtils.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "GStreamerMSEUtils.h" -#include "GStreamerUtils.h" -#include "GstreamerCatLog.h" - -#include -#include -#include -#include - -#define GST_CAT_DEFAULT rialtoGStreamerCat - -void rialto_mse_sink_setup_supported_caps(GstElementClass *elementClass, - const std::vector &supportedMimeTypes) -{ - static const std::unordered_map> kMimeToCaps = - {{"audio/mp4", {"audio/mpeg, mpegversion=1", "audio/mpeg, mpegversion=2", "audio/mpeg, mpegversion=4"}}, - {"audio/mp3", {"audio/mpeg, mpegversion=1", "audio/mpeg, mpegversion=2"}}, - {"audio/aac", {"audio/mpeg, mpegversion=2", "audio/mpeg, mpegversion=4"}}, - {"audio/x-eac3", {"audio/x-ac3", "audio/x-eac3"}}, - {"audio/x-opus", {"audio/x-opus"}}, - {"audio/b-wav", {"audio/b-wav"}}, - {"audio/x-flac", {"audio/x-flac"}}, - {"audio/x-raw", {"audio/x-raw"}}, - {"video/h264", {"video/x-h264"}}, - {"video/h265", {"video/x-h265"}}, - {"video/x-av1", {"video/x-av1"}}, - {"video/x-vp9", {"video/x-vp9"}}, - {"text/vtt", {"text/vtt", "application/x-subtitle-vtt"}}, - {"text/ttml", {"application/ttml+xml"}}, - {"text/cc", - {"closedcaption/x-cea-608", "closedcaption/x-cea-708", "application/x-cea-608", "application/x-cea-708", - "application/x-subtitle-cc"}}}; - - std::unordered_set addedCaps; // keep track what caps were added to avoid duplicates - GstCaps *caps = gst_caps_new_empty(); - for (const std::string &mime : supportedMimeTypes) - { - auto mimeToCapsIt = kMimeToCaps.find(mime); - if (mimeToCapsIt != kMimeToCaps.end()) - { - for (const std::string &capsStr : mimeToCapsIt->second) - { - if (addedCaps.find(capsStr) == addedCaps.end()) - { - GST_INFO("Caps '%s' is supported", capsStr.c_str()); - GstCaps *newCaps = gst_caps_from_string(capsStr.c_str()); - gst_caps_append(caps, newCaps); - addedCaps.insert(capsStr); - } - } - } - else - { - GST_WARNING("Mime '%s' is not supported", mime.c_str()); - } - } - - GstPadTemplate *sinktempl = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps); - gst_element_class_add_pad_template(elementClass, sinktempl); - gst_caps_unref(caps); -} - -std::optional rialto_mse_sink_convert_layout(const gchar *layoutStr) -{ - if (g_strcmp0(layoutStr, "interleaved") == 0) - { - return firebolt::rialto::Layout::INTERLEAVED; - } - if (g_strcmp0(layoutStr, "non-interleaved") == 0) - { - return firebolt::rialto::Layout::NON_INTERLEAVED; - } - return std::nullopt; -} - -std::optional rialto_mse_sink_convert_format(const gchar *formatStr) -{ - static const std::unordered_map - kStringToFormat{{"S8", firebolt::rialto::Format::S8}, - {"U8", firebolt::rialto::Format::U8}, - {"S16LE", firebolt::rialto::Format::S16LE}, - {"S16BE", firebolt::rialto::Format::S16BE}, - {"U16LE", firebolt::rialto::Format::U16LE}, - {"U16BE", firebolt::rialto::Format::U16BE}, - {"S24_32LE", firebolt::rialto::Format::S24_32LE}, - {"S24_32BE", firebolt::rialto::Format::S24_32BE}, - {"U24_32LE", firebolt::rialto::Format::U24_32LE}, - {"U24_32BE", firebolt::rialto::Format::U24_32BE}, - {"S32LE", firebolt::rialto::Format::S32LE}, - {"S32BE", firebolt::rialto::Format::S32BE}, - {"U32LE", firebolt::rialto::Format::U32LE}, - {"U32BE", firebolt::rialto::Format::U32BE}, - {"S24LE", firebolt::rialto::Format::S24LE}, - {"S24BE", firebolt::rialto::Format::S24BE}, - {"U24LE", firebolt::rialto::Format::U24LE}, - {"U24BE", firebolt::rialto::Format::U24BE}, - {"S20LE", firebolt::rialto::Format::S20LE}, - {"S20BE", firebolt::rialto::Format::S20BE}, - {"U20LE", firebolt::rialto::Format::U20LE}, - {"U20BE", firebolt::rialto::Format::U20BE}, - {"S18LE", firebolt::rialto::Format::S18LE}, - {"S18BE", firebolt::rialto::Format::S18BE}, - {"U18LE", firebolt::rialto::Format::U18LE}, - {"U18BE", firebolt::rialto::Format::U18BE}, - {"F32LE", firebolt::rialto::Format::F32LE}, - {"F32BE", firebolt::rialto::Format::F32BE}, - {"F64LE", firebolt::rialto::Format::F64LE}, - {"F64BE", firebolt::rialto::Format::F64BE}}; - const auto it = kStringToFormat.find(formatStr); - if (it != kStringToFormat.end()) - { - return it->second; - } - return std::nullopt; -} - -std::shared_ptr get_codec_data(const GstStructure *structure) -{ - const GValue *codec_data = gst_structure_get_value(structure, "codec_data"); - if (codec_data) - { - GstBuffer *buf = gst_value_get_buffer(codec_data); - if (buf) - { - GstMappedBuffer mappedBuf(buf, GST_MAP_READ); - if (mappedBuf) - { - auto codecData = std::make_shared(); - codecData->data = std::vector(mappedBuf.data(), mappedBuf.data() + mappedBuf.size()); - codecData->type = firebolt::rialto::CodecDataType::BUFFER; - return codecData; - } - else - { - GST_ERROR("Failed to read codec_data"); - return nullptr; - } - } - const gchar *str = g_value_get_string(codec_data); - if (str) - { - auto codecData = std::make_shared(); - codecData->data = std::vector(str, str + std::strlen(str)); - codecData->type = firebolt::rialto::CodecDataType::STRING; - return codecData; - } - } - - return nullptr; -} - -firebolt::rialto::SegmentAlignment get_segment_alignment(const GstStructure *s) -{ - const gchar *alignment = gst_structure_get_string(s, "alignment"); - if (alignment) - { - GST_DEBUG("Alignment found %s", alignment); - if (strcmp(alignment, "au") == 0) - { - return firebolt::rialto::SegmentAlignment::AU; - } - else if (strcmp(alignment, "nal") == 0) - { - return firebolt::rialto::SegmentAlignment::NAL; - } - } - - return firebolt::rialto::SegmentAlignment::UNDEFINED; -} - -bool get_dv_profile(const GstStructure *s, uint32_t &dvProfile) -{ - gboolean isDolbyVisionEnabled = false; - if (gst_structure_get_boolean(s, "dovi-stream", &isDolbyVisionEnabled) && isDolbyVisionEnabled) - { - if (gst_structure_get_uint(s, "dv_profile", &dvProfile)) - { - return true; - } - } - return false; -} - -firebolt::rialto::StreamFormat get_stream_format(const GstStructure *structure) -{ - const gchar *streamFormat = gst_structure_get_string(structure, "stream-format"); - firebolt::rialto::StreamFormat format = firebolt::rialto::StreamFormat::UNDEFINED; - if (streamFormat) - { - static const std::unordered_map stringToStreamFormatMap = - {{"raw", firebolt::rialto::StreamFormat::RAW}, - {"avc", firebolt::rialto::StreamFormat::AVC}, - {"byte-stream", firebolt::rialto::StreamFormat::BYTE_STREAM}, - {"hvc1", firebolt::rialto::StreamFormat::HVC1}, - {"hev1", firebolt::rialto::StreamFormat::HEV1}}; - - auto strToStreamFormatIt = stringToStreamFormatMap.find(streamFormat); - if (strToStreamFormatIt != stringToStreamFormatMap.end()) - { - format = strToStreamFormatIt->second; - } - } - - return format; -} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/GStreamerMSEUtils.h b/middleware/rialto-gstreamer/source/GStreamerMSEUtils.h deleted file mode 100644 index 38a80363e..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerMSEUtils.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef GSTREAMERMSEUTILS_H -#define GSTREAMERMSEUTILS_H - -#include - -#include - -#include -#include -#include -#include -void rialto_mse_sink_setup_supported_caps(GstElementClass *elementClass, - const std::vector &supportedMimeType); -std::optional rialto_mse_sink_convert_layout(const gchar *layoutStr); -std::optional rialto_mse_sink_convert_format(const gchar *formatStr); -std::shared_ptr get_codec_data(const GstStructure *structure); -firebolt::rialto::SegmentAlignment get_segment_alignment(const GstStructure *s); -bool get_dv_profile(const GstStructure *s, uint32_t &dvProfile); -firebolt::rialto::StreamFormat get_stream_format(const GstStructure *structure); -#endif // GSTREAMERMSEUTILS_H diff --git a/middleware/rialto-gstreamer/source/GStreamerUtils.cpp b/middleware/rialto-gstreamer/source/GStreamerUtils.cpp deleted file mode 100644 index b9e3c1fa6..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerUtils.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "GStreamerUtils.h" - -#define GST_CAT_DEFAULT rialtoGStreamerCat - -GstMappedBuffer::GstMappedBuffer(GstBuffer *buffer, GstMapFlags flags) - : m_buffer(buffer), m_isMapped(gst_buffer_map(m_buffer, &m_info, flags)) -{ -} - -GstMappedBuffer::~GstMappedBuffer() -{ - if (m_isMapped) - { - gst_buffer_unmap(m_buffer, &m_info); - } -} - -uint8_t *GstMappedBuffer::data() -{ - if (m_isMapped) - { - return static_cast(m_info.data); - } - else - { - return nullptr; - } -} - -size_t GstMappedBuffer::size() const -{ - if (m_isMapped) - { - return static_cast(m_info.size); - } - else - { - return 0; - } -} - -GstMappedBuffer::operator bool() const -{ - return m_isMapped; -} - -GstRefSample::GstRefSample(GstSample *sample) : m_sample{sample ? gst_sample_ref(sample) : nullptr} {} - -GstRefSample::~GstRefSample() -{ - if (m_sample) - { - gst_sample_unref(m_sample); - } -} - -GstRefSample::operator bool() const -{ - return m_sample; -} - -GstBuffer *GstRefSample::getBuffer() const -{ - return gst_sample_get_buffer(m_sample); -} - -GstCaps *GstRefSample::getCaps() const -{ - return gst_sample_get_caps(m_sample); -} diff --git a/middleware/rialto-gstreamer/source/GStreamerUtils.h b/middleware/rialto-gstreamer/source/GStreamerUtils.h deleted file mode 100644 index dc0fe96b5..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerUtils.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef GSTREAMERUTILS_H -#define GSTREAMERUTILS_H - -#include -#include - -class GstMappedBuffer -{ -public: - explicit GstMappedBuffer(GstBuffer *buffer, GstMapFlags flags); - ~GstMappedBuffer(); - uint8_t *data(); - size_t size() const; - explicit operator bool() const; - -private: - GstBuffer *m_buffer; - GstMapInfo m_info; - bool m_isMapped; -}; - -class GstRefSample -{ -public: - explicit GstRefSample(GstSample *sample = nullptr); - GstRefSample(const GstRefSample &) = delete; - GstRefSample(GstRefSample &&) = delete; - GstRefSample &operator=(const GstRefSample &) = delete; - GstRefSample &operator=(GstRefSample &&) = delete; - ~GstRefSample(); - explicit operator bool() const; - GstBuffer *getBuffer() const; - GstCaps *getCaps() const; - -private: - GstSample *m_sample; -}; -#endif // GSTREAMERUTILS_H \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.cpp b/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.cpp deleted file mode 100644 index a71a5be6b..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.cpp +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "GStreamerWebAudioPlayerClient.h" -#include "GstreamerCatLog.h" - -#include - -#include -#include -#include -#include - -#define GST_CAT_DEFAULT rialtoGStreamerCat - -namespace -{ -constexpr std::size_t kMaxQueueSize{40}; -bool parseGstStructureFormat(const std::string &format, uint32_t &sampleSize, bool &isBigEndian, bool &isSigned, - bool &isFloat) -{ - if (format.size() != 5) - { - return false; - } - std::string sampleSizeStr = format.substr(1, 2); - char *pEnd = NULL; - errno = 0; - sampleSize = strtoul(sampleSizeStr.c_str(), &pEnd, 10); - if (errno == ERANGE) - { - return false; - } - - isBigEndian = format.substr(3) == "BE"; - - switch (format[0]) - { - case 'S': - isSigned = true; - isFloat = false; - break; - case 'U': - isSigned = false; - isFloat = false; - break; - case 'F': - isSigned = false; - isFloat = true; - break; - default: - return false; - break; - } - return true; -} - -bool operator!=(const firebolt::rialto::WebAudioPcmConfig &lac, const firebolt::rialto::WebAudioPcmConfig &rac) -{ - return lac.rate != rac.rate || lac.channels != rac.channels || lac.sampleSize != rac.sampleSize || - lac.isBigEndian != rac.isBigEndian || lac.isSigned != rac.isSigned || lac.isFloat != rac.isFloat; -} -} // namespace - -GStreamerWebAudioPlayerClient::GStreamerWebAudioPlayerClient( - std::unique_ptr &&webAudioClientBackend, - std::unique_ptr &&backendQueue, IPlaybackDelegate &delegate, - std::shared_ptr timerFactory) - : m_backendQueue{std::move(backendQueue)}, m_clientBackend{std::move(webAudioClientBackend)}, m_isOpen{false}, - m_dataBuffers{}, m_timerFactory{timerFactory}, m_pushSamplesTimer{nullptr}, m_preferredFrames{0}, - m_maximumFrames{0}, m_supportDeferredPlay{false}, m_isEos{false}, m_frameSize{0}, m_mimeType{}, m_config{{}}, - m_delegate{delegate} -{ - m_backendQueue->start(); -} - -GStreamerWebAudioPlayerClient::~GStreamerWebAudioPlayerClient() -{ - m_backendQueue->stop(); -} - -bool GStreamerWebAudioPlayerClient::open(GstCaps *caps) -{ - GST_DEBUG("entry:"); - - bool result = false; - GstStructure *structure = gst_caps_get_structure(caps, 0); - std::string audioMimeType = gst_structure_get_name(structure); - const auto spacePosition = audioMimeType.find(' '); - if (spacePosition != std::string::npos) - { - audioMimeType.resize(spacePosition); - } - const gchar *formatCStr{gst_structure_get_string(structure, "format")}; - std::string format{formatCStr ? formatCStr : ""}; - firebolt::rialto::WebAudioPcmConfig pcm; - gint tmp; - - if (format.empty()) - { - GST_ERROR("Format not found in caps"); - return result; - } - - if (!gst_structure_get_int(structure, "rate", &tmp)) - { - GST_ERROR("Rate not found in caps"); - return result; - } - pcm.rate = tmp; - - if (!gst_structure_get_int(structure, "channels", &tmp)) - { - GST_ERROR("Rate not found in caps"); - return result; - } - pcm.channels = tmp; - - if (!parseGstStructureFormat(format, pcm.sampleSize, pcm.isBigEndian, pcm.isSigned, pcm.isFloat)) - { - GST_ERROR("Can't parse format or it is not supported: %s", format.c_str()); - return result; - } - - m_backendQueue->callInEventLoop( - [&]() - { - // "configWorkaround" is used because there doesn't seem to be an easy way to use - // make_shared in conjunction with an initalizer list, and adding a constructor to - // WebAudioConfig stops initalizer lists (used elsewhere in the code) from working... - firebolt::rialto::WebAudioConfig configWorkaround{pcm}; - std::shared_ptr config = - std::make_shared(configWorkaround); - - // Only recreate player if the config has changed - if (!m_isOpen || isNewConfig(audioMimeType, config)) - { - if (m_isOpen) - { - // Destroy the previously created player - m_clientBackend->destroyWebAudioBackend(); - } - - uint32_t priority = 1; - if (m_clientBackend->createWebAudioBackend(shared_from_this(), audioMimeType, priority, config)) - { - if (!m_clientBackend->getDeviceInfo(m_preferredFrames, m_maximumFrames, m_supportDeferredPlay)) - { - GST_ERROR("GetDeviceInfo failed, could not process samples"); - } - m_frameSize = (pcm.sampleSize * pcm.channels) / CHAR_BIT; - m_isOpen = true; - - // Store config - m_config.pcm = pcm; - m_mimeType = audioMimeType; - } - else - { - GST_ERROR("Could not create web audio backend"); - m_isOpen = false; - } - result = m_isOpen; - } - }); - - return result; -} - -bool GStreamerWebAudioPlayerClient::close() -{ - GST_DEBUG("entry:"); - - m_backendQueue->callInEventLoop( - [&]() - { - m_clientBackend->destroyWebAudioBackend(); - m_pushSamplesTimer.reset(); - m_isOpen = false; - }); - - return true; -} - -bool GStreamerWebAudioPlayerClient::play() -{ - GST_DEBUG("entry:"); - - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - if (m_isOpen) - { - result = m_clientBackend->play(); - } - else - { - GST_ERROR("No web audio backend"); - } - }); - - return result; -} - -bool GStreamerWebAudioPlayerClient::pause() -{ - GST_DEBUG("entry:"); - - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - if (m_isOpen) - { - result = m_clientBackend->pause(); - } - else - { - GST_ERROR("No web audio backend"); - } - }); - - return result; -} - -bool GStreamerWebAudioPlayerClient::setEos() -{ - GST_DEBUG("entry:"); - - bool result = false; - m_backendQueue->callInEventLoop( - [&]() - { - if (m_isOpen && !m_isEos) - { - m_isEos = true; - if (m_dataBuffers.empty()) - { - result = m_clientBackend->setEos(); - } - else - { - pushSamples(); - result = true; - } - } - else - { - GST_DEBUG("No web audio backend, valid scenario"); - } - }); - - return result; -} - -bool GStreamerWebAudioPlayerClient::isOpen() -{ - GST_DEBUG("entry:"); - - bool result = false; - m_backendQueue->callInEventLoop([&]() { result = m_isOpen; }); - - return result; -} - -void GStreamerWebAudioPlayerClient::notifyPushSamplesTimerExpired() -{ - m_backendQueue->scheduleInEventLoop([&]() { pushSamples(); }); -} - -bool GStreamerWebAudioPlayerClient::notifyNewSample(GstBuffer *buf) -{ - GST_DEBUG("entry:"); - - bool result = false; - - { - std::unique_lock lock{m_queueSizeMutex}; - m_queueSizeCv.wait(lock, [&]() { return m_dataBuffers.size() < kMaxQueueSize; }); - } - - m_backendQueue->callInEventLoop( - [&]() - { - if (buf) - { - if (m_pushSamplesTimer) - { - m_pushSamplesTimer->cancel(); - m_pushSamplesTimer.reset(); - } - { - std::unique_lock lock{m_queueSizeMutex}; - m_dataBuffers.push(buf); - } - pushSamples(); - result = true; - } - }); - - return result; -} - -void GStreamerWebAudioPlayerClient::pushSamples() -{ - GST_DEBUG("entry:"); - if (!m_isOpen || m_dataBuffers.empty()) - { - return; - } - - uint32_t availableFrames = 0u; - do - { - if (!m_clientBackend->getBufferAvailable(availableFrames)) - { - GST_ERROR("getBufferAvailable failed, could not process the samples"); - // clear the queue if getBufferAvailable failed - std::queue empty; - std::unique_lock lock{m_queueSizeMutex}; - std::swap(m_dataBuffers, empty); - m_queueSizeCv.notify_one(); - } - else if (0 != availableFrames) - { - bool writeFailure = false; - GstBuffer *buffer = m_dataBuffers.front(); - gsize bufferSize = gst_buffer_get_size(buffer); - auto framesToWrite = std::min(availableFrames, static_cast(bufferSize / m_frameSize)); - if (framesToWrite > 0) - { - GstMapInfo bufferMap; - if (!gst_buffer_map(buffer, &bufferMap, GST_MAP_READ)) - { - GST_ERROR("Could not map audio buffer, discarding buffer!"); - writeFailure = true; - } - else - { - if (!m_clientBackend->writeBuffer(framesToWrite, bufferMap.data)) - { - GST_ERROR("Could not map audio buffer, discarding buffer!"); - writeFailure = true; - } - gst_buffer_unmap(buffer, &bufferMap); - } - } - - if ((!writeFailure) && (framesToWrite * m_frameSize < bufferSize)) - { - // Handle any leftover data - uint32_t leftoverData = bufferSize - (availableFrames * m_frameSize); - gst_buffer_resize(buffer, framesToWrite * m_frameSize, leftoverData); - if ((leftoverData / m_frameSize == 0) && (m_dataBuffers.size() > 1)) - { - // If the leftover data is smaller than a frame, it must be processed with the next buffer - std::unique_lock lock{m_queueSizeMutex}; - m_dataBuffers.pop(); - m_dataBuffers.front() = gst_buffer_append(buffer, m_dataBuffers.front()); - gst_buffer_unref(buffer); - m_queueSizeCv.notify_one(); - } - } - else - { - std::unique_lock lock{m_queueSizeMutex}; - m_dataBuffers.pop(); - gst_buffer_unref(buffer); - m_queueSizeCv.notify_one(); - } - } - } while (!m_dataBuffers.empty() && availableFrames != 0); - - // If we still have samples stored that could not be pushed - // This avoids any stoppages in the pushing of samples to the server if the consumption of - // samples is slow. - if (m_dataBuffers.size()) - { - m_pushSamplesTimer = - m_timerFactory->createTimer(std::chrono::milliseconds(10), [this]() { notifyPushSamplesTimerExpired(); }); - } - else if (m_isEos) - { - m_clientBackend->setEos(); - } -} - -bool GStreamerWebAudioPlayerClient::isNewConfig(const std::string &audioMimeType, - std::weak_ptr webAudioConfig) -{ - if (audioMimeType != m_mimeType) - { - return true; - } - - if (audioMimeType != "audio/x-raw") - { - GST_ERROR("Cannot compare none pcm config"); - return true; - } - - std::shared_ptr config = webAudioConfig.lock(); - if (!config || config->pcm != m_config.pcm) - { - return true; - } - - return false; -} - -void GStreamerWebAudioPlayerClient::notifyState(firebolt::rialto::WebAudioPlayerState state) -{ - switch (state) - { - case firebolt::rialto::WebAudioPlayerState::END_OF_STREAM: - { - GST_INFO("Notify end of stream."); - m_delegate.handleEos(); - m_isEos = false; - break; - } - case firebolt::rialto::WebAudioPlayerState::FAILURE: - { - std::string errMessage = "Rialto server webaudio playback failed"; - GST_ERROR("%s", errMessage.c_str()); - m_delegate.handleError(errMessage); - break; - } - case firebolt::rialto::WebAudioPlayerState::IDLE: - { - m_delegate.handleStateChanged(firebolt::rialto::PlaybackState::IDLE); - break; - } - case firebolt::rialto::WebAudioPlayerState::PLAYING: - { - m_delegate.handleStateChanged(firebolt::rialto::PlaybackState::PLAYING); - break; - } - case firebolt::rialto::WebAudioPlayerState::PAUSED: - { - m_delegate.handleStateChanged(firebolt::rialto::PlaybackState::PAUSED); - break; - } - case firebolt::rialto::WebAudioPlayerState::UNKNOWN: - default: - { - GST_WARNING("Web audio player sent unknown state"); - break; - } - } -} - -bool GStreamerWebAudioPlayerClient::setVolume(double volume) -{ - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->setVolume(volume); }); - return status; -} - -bool GStreamerWebAudioPlayerClient::getVolume(double &volume) -{ - bool status{false}; - m_backendQueue->callInEventLoop([&]() { status = m_clientBackend->getVolume(volume); }); - return status; -} diff --git a/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.h b/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.h deleted file mode 100644 index 9aea04049..000000000 --- a/middleware/rialto-gstreamer/source/GStreamerWebAudioPlayerClient.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "Constants.h" -#include "IMessageQueue.h" -#include "IPlaybackDelegate.h" -#include "ITimer.h" -#include "MediaCommon.h" -#include "WebAudioClientBackendInterface.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -class GStreamerWebAudioPlayerClient : public firebolt::rialto::IWebAudioPlayerClient, - public std::enable_shared_from_this -{ -public: - /** - * @brief Constructor. - * - * @param[in] callbacks : The callbacks for the sink. - */ - GStreamerWebAudioPlayerClient( - std::unique_ptr &&webAudioClientBackend, - std::unique_ptr &&backendQueue, IPlaybackDelegate &delegate, - std::shared_ptr timerFactory); - - /** - * @brief Destructor. - */ - virtual ~GStreamerWebAudioPlayerClient(); - - /** - * @brief Extracts the sample info from the gstreamer capabilities - * and opens the web audio. - * - * @param[in] caps : Sample gstreamer capabilities. - * - * @retval true on success. - */ - bool open(GstCaps *caps); - - /** - * @brief Closes the web audio player. - * - * @retval true on success. - */ - bool close(); - - /** - * @brief Play the web audio. - * - * @retval true on success. - */ - bool play(); - - /** - * @brief Pause the web audio. - * - * @retval true on success. - */ - bool pause(); - - /** - * @brief Notify EOS. - * - * @retval true on success. - */ - bool setEos(); - - /** - * @brief Get the volume. - * - * @param[out] volume : The volume level - * - * @retval true on success. - */ - bool getVolume(double &volume); - - /** - * @brief Set the volume. - * - * @param[in] volume : The volume level - * - * @retval true on success. - */ - bool setVolume(double volume); - - /** - * @brief Whether the backend has been opened or not. - * - * @retval true if open. - */ - bool isOpen(); - - /** - * @brief Notifies that there is a new sample in gstreamer. - * - * @param[in] buf : The new sample buffer. - * - * @retval true on success. - */ - bool notifyNewSample(GstBuffer *buf); - - /** - * @brief Notify push sample timer expiry. - */ - void notifyPushSamplesTimerExpired(); - - /** - * @brief Implements the player state change notification. - * - * @param[in] state : The new playback state. - */ - void notifyState(firebolt::rialto::WebAudioPlayerState state) override; - -private: - /** - * @brief Perform the next push operation. - * - * The samples are pushed only when there is the available buffer - * in RialtoServer. - */ - void pushSamples(); - - /** - * @brief Checks the config against that previously stored in the object. - * - * @retval true if this is a new config. - */ - bool isNewConfig(const std::string &audioMimeType, std::weak_ptr config); - - /** - * @brief Backend message queue. - */ - std::unique_ptr m_backendQueue; - - /** - * @brief The web audio client backend interface. - */ - std::unique_ptr m_clientBackend; - - /** - * @brief Whether the web audio backend is currently open. - */ - std::atomic m_isOpen; - - /** - * @brief Vector to store the gst sample buffers. - */ - std::queue m_dataBuffers; - - /** - * @brief The timer factory. - */ - std::shared_ptr m_timerFactory; - - /** - * @brief The push samples timer. - */ - std::unique_ptr m_pushSamplesTimer; - - /** - * @brief The preferred number of frames to be written. - */ - uint32_t m_preferredFrames; - - /** - * @brief The maximum number of frames that can be written. - */ - uint32_t m_maximumFrames; - - /** - * @brief Whether defered play is supported. - */ - bool m_supportDeferredPlay; - - /** - * @brief Whether the sink element has received EOS. - */ - bool m_isEos; - - /** - * @brief The number of bytes in the frame. - */ - uint32_t m_frameSize; - - /** - * @brief The mutex protecting m_dataBuffers size reads - */ - std::mutex m_queueSizeMutex; - - /** - * @brief The condition variable used to block webaudio chain function - * when m_dataBuffers queue size is too large - */ - std::condition_variable m_queueSizeCv; - - /** - * @brief The current web audio player mime type. - */ - std::string m_mimeType; - - /** - * @brief The current web audio player config. - */ - firebolt::rialto::WebAudioConfig m_config; - - /** - * @brief The reference to delegate object. - */ - IPlaybackDelegate &m_delegate; -}; diff --git a/middleware/rialto-gstreamer/source/GstreamerCatLog.cpp b/middleware/rialto-gstreamer/source/GstreamerCatLog.cpp deleted file mode 100644 index 911d0c8d9..000000000 --- a/middleware/rialto-gstreamer/source/GstreamerCatLog.cpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2024 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "GstreamerCatLog.h" -#include - -GST_DEBUG_CATEGORY(rialtoGStreamerCat); diff --git a/middleware/rialto-gstreamer/source/GstreamerCatLog.h b/middleware/rialto-gstreamer/source/GstreamerCatLog.h deleted file mode 100644 index 9940113cc..000000000 --- a/middleware/rialto-gstreamer/source/GstreamerCatLog.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2024 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef GSTREAMER_CAT_LOG_H -#define GSTREAMER_CAT_LOG_H - -#include - -GST_DEBUG_CATEGORY_EXTERN(rialtoGStreamerCat); - -inline void init_gst_debug_category() -{ - GST_DEBUG_CATEGORY_INIT(rialtoGStreamerCat, "rialtogstreamer", 0, "Messages from non-gstreamer objects"); -} - -#endif // GSTREAMER_CAT_LOG_H \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/IMessageQueue.h b/middleware/rialto-gstreamer/source/IMessageQueue.h deleted file mode 100644 index 1f956b8c8..000000000 --- a/middleware/rialto-gstreamer/source/IMessageQueue.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include -#include - -class Message -{ -public: - virtual ~Message() {} - virtual void handle() = 0; - virtual void skip() {}; -}; - -class IMessageQueue -{ -public: - virtual ~IMessageQueue() = default; - virtual void start() = 0; - virtual void stop() = 0; - virtual void clear() = 0; - virtual std::shared_ptr waitForMessage() = 0; - virtual bool postMessage(const std::shared_ptr &msg) = 0; - virtual void processMessages() = 0; - virtual bool scheduleInEventLoop(const std::function &func) = 0; - virtual bool callInEventLoop(const std::function &func) = 0; -}; - -class IMessageQueueFactory -{ -public: - virtual ~IMessageQueueFactory() = default; - static std::shared_ptr createFactory(); - virtual std::unique_ptr createMessageQueue() const = 0; -}; diff --git a/middleware/rialto-gstreamer/source/IPlaybackDelegate.h b/middleware/rialto-gstreamer/source/IPlaybackDelegate.h deleted file mode 100644 index 5c927d131..000000000 --- a/middleware/rialto-gstreamer/source/IPlaybackDelegate.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "GStreamerUtils.h" -#include "MediaCommon.h" -#include -#include -#include - -class IPlaybackDelegate -{ -public: - enum class Property - { - // PullModePlaybackDelegate Properties - IsSinglePathStream, - NumberOfStreams, - HasDrm, - Stats, - - // PullModeAudioPlaybackDelegate Properties - Volume, - Mute, - Gap, - LowLatency, - Sync, - SyncOff, - StreamSyncMode, - AudioFade, - FadeVolume, - LimitBufferingMs, - UseBuffering, - Async, - - // PullModeVideoPlaybackDelegate Properties - WindowSet, - MaxVideoWidth, - MaxVideoHeight, - FrameStepOnPreroll, - ImmediateOutput, - SyncmodeStreaming, - ShowVideoWindow, - - // PullModeSubtitlePlaybackDelegate Properties - TextTrackIdentifier, - WindowId, - - // PushModeAudioPlaybackDelegate Properties - TsOffset, - }; - - IPlaybackDelegate() = default; - virtual ~IPlaybackDelegate() = default; - - IPlaybackDelegate(const IPlaybackDelegate &) = delete; - IPlaybackDelegate(IPlaybackDelegate &&) = delete; - IPlaybackDelegate &operator=(const IPlaybackDelegate &) = delete; - IPlaybackDelegate &operator=(IPlaybackDelegate &&) = delete; - - virtual void handleEos() = 0; - virtual void handleStateChanged(firebolt::rialto::PlaybackState state) = 0; - virtual void handleError(const std::string &message, gint code = 0) = 0; - virtual void handleQos(uint64_t processed, uint64_t dropped) const = 0; - - virtual GstStateChangeReturn changeState(GstStateChange transition) = 0; - virtual void postAsyncStart() = 0; - virtual void setProperty(const Property &type, const GValue *value) = 0; - virtual void getProperty(const Property &type, GValue *value) = 0; - virtual std::optional handleQuery(GstQuery *query) const = 0; - virtual gboolean handleSendEvent(GstEvent *event) = 0; - virtual gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) = 0; - virtual GstFlowReturn handleBuffer(GstBuffer *buffer) = 0; -}; diff --git a/middleware/rialto-gstreamer/source/IPullModePlaybackDelegate.h b/middleware/rialto-gstreamer/source/IPullModePlaybackDelegate.h deleted file mode 100644 index a60f36f71..000000000 --- a/middleware/rialto-gstreamer/source/IPullModePlaybackDelegate.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "IPlaybackDelegate.h" - -class IPullModePlaybackDelegate : public IPlaybackDelegate -{ -public: - IPullModePlaybackDelegate() = default; - ~IPullModePlaybackDelegate() override = default; - - IPullModePlaybackDelegate(const IPullModePlaybackDelegate &) = delete; - IPullModePlaybackDelegate(IPullModePlaybackDelegate &&) = delete; - IPullModePlaybackDelegate &operator=(const IPullModePlaybackDelegate &) = delete; - IPullModePlaybackDelegate &operator=(IPullModePlaybackDelegate &&) = delete; - - virtual void setSourceId(int32_t sourceId) = 0; - virtual void handleFlushCompleted() = 0; - virtual GstRefSample getFrontSample() const = 0; - virtual void popSample() = 0; - virtual bool isEos() const = 0; - virtual void lostState() = 0; - virtual bool isReadyToSendData() const = 0; -}; diff --git a/middleware/rialto-gstreamer/source/ITimer.h b/middleware/rialto-gstreamer/source/ITimer.h deleted file mode 100644 index 3947634e6..000000000 --- a/middleware/rialto-gstreamer/source/ITimer.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef I_TIMER_H_ -#define I_TIMER_H_ - -#include -#include -#include - -class ITimer; - -enum class TimerType -{ - ONE_SHOT, - PERIODIC -}; - -/** - * @brief ITimerFactory factory class, returns a concrete implementation of ITimer - */ -class ITimerFactory -{ -public: - ITimerFactory() = default; - virtual ~ITimerFactory() = default; - - /** - * @brief Gets the ITimerFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr getFactory(); - - /** - * @brief Creates an ITimer object. - * - * @param[in] timeout : Timeout after which callback will be called - * @param[in] callback : Function which is called after timeout - * @param[in] timerType : Type of timer - * - * @retval the new timer instance or null on error. - */ - virtual std::unique_ptr createTimer(const std::chrono::milliseconds &timeout, - const std::function &callback, - TimerType timerType = TimerType::ONE_SHOT) const = 0; -}; - -class ITimer -{ -public: - ITimer() = default; - virtual ~ITimer() = default; - - ITimer(const ITimer &) = delete; - ITimer &operator=(const ITimer &) = delete; - ITimer(ITimer &&) = delete; - ITimer &operator=(ITimer &&) = delete; - - /** - * @brief Cancels the timer - */ - virtual void cancel() = 0; - - /** - * @brief Checks if timer is active - * - * @retval true if timer is active, false otherwise - */ - virtual bool isActive() const = 0; -}; - -#endif // I_TIMER_H_ diff --git a/middleware/rialto-gstreamer/source/LogToGstHandler.cpp b/middleware/rialto-gstreamer/source/LogToGstHandler.cpp deleted file mode 100644 index b7bbf77fa..000000000 --- a/middleware/rialto-gstreamer/source/LogToGstHandler.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2024 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -// -// This allows, for example, passing the following environment variable -// to the client app which will enable rialto logging via gstreamer... -// GST_DEBUG=6 -// - -#include - -#include "LogToGstHandler.h" - -#ifdef USE_ETHANLOG - -#include - -#define SYSTEM_LOG_FATAL(filename, function, line, ...) ethanlog(ETHAN_LOG_FATAL, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_ERROR(filename, function, line, ...) ethanlog(ETHAN_LOG_ERROR, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_WARN(filename, function, line, ...) \ - ethanlog(ETHAN_LOG_WARNING, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_MIL(filename, function, line, ...) \ - ethanlog(ETHAN_LOG_MILESTONE, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_INFO(filename, function, line, ...) ethanlog(ETHAN_LOG_INFO, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_DEBUG(filename, function, line, ...) ethanlog(ETHAN_LOG_DEBUG, filename, function, line, __VA_ARGS__) - -#else - -#include - -#define SYSTEM_LOG_FATAL(filename, function, line, ...) GST_CAT_ERROR(kGstRialtoCategory, __VA_ARGS__) -#define SYSTEM_LOG_ERROR(filename, function, line, ...) GST_CAT_ERROR(kGstRialtoCategory, __VA_ARGS__) -#define SYSTEM_LOG_WARN(filename, function, line, ...) GST_CAT_WARNING(kGstRialtoCategory, __VA_ARGS__) -#define SYSTEM_LOG_MIL(filename, function, line, ...) GST_CAT_INFO(kGstRialtoCategory, __VA_ARGS__) -#define SYSTEM_LOG_INFO(filename, function, line, ...) GST_CAT_INFO(kGstRialtoCategory, __VA_ARGS__) -#define SYSTEM_LOG_DEBUG(filename, function, line, ...) GST_CAT_DEBUG(kGstRialtoCategory, __VA_ARGS__) - -namespace -{ -GST_DEBUG_CATEGORY_STATIC(kGstRialtoCategory); -const char *kCategory = "rialto"; -}; // namespace - -#endif - -using namespace firebolt::rialto; - -LogToGstHandler::LogToGstHandler() -{ -#ifndef USE_ETHANLOG - GST_DEBUG_CATEGORY_INIT(kGstRialtoCategory, kCategory, 0, "Messages from rialto client library"); -#endif -} - -LogToGstHandler::~LogToGstHandler() {} - -void LogToGstHandler::log(Level level, const std::string &file, int line, const std::string &function, - const std::string &message) -{ - std::string toReport; - toReport += "M:" + file; - toReport += " F:" + function; - toReport += " L:" + std::to_string(line); - toReport += " > " + message; - - switch (level) - { - case Level::Fatal: - SYSTEM_LOG_FATAL(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); - break; - - case Level::Error: - SYSTEM_LOG_ERROR(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); - break; - - case Level::Warning: - SYSTEM_LOG_WARN(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); - break; - - case Level::Milestone: - SYSTEM_LOG_MIL(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); - break; - - case Level::Info: - SYSTEM_LOG_INFO(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); - break; - - case Level::Debug: - SYSTEM_LOG_DEBUG(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); - break; - - case Level::External: - default: - SYSTEM_LOG_INFO(file.c_str(), function.c_str(), line, "%s", toReport.c_str()); - break; - } -} diff --git a/middleware/rialto-gstreamer/source/LogToGstHandler.h b/middleware/rialto-gstreamer/source/LogToGstHandler.h deleted file mode 100644 index f73d541f6..000000000 --- a/middleware/rialto-gstreamer/source/LogToGstHandler.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2024 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef FIREBOLT_RIALTO_LOG_HANDLER_H_ -#define FIREBOLT_RIALTO_LOG_HANDLER_H_ - -#include "IClientLogHandler.h" - -namespace firebolt::rialto -{ -class LogToGstHandler : public IClientLogHandler -{ -public: - LogToGstHandler(); - ~LogToGstHandler(); - - void log(Level level, const std::string &file, int line, const std::string &function, const std::string &message); -}; -} // namespace firebolt::rialto -#endif // FIREBOLT_RIALTO_RIALTO_LOG_HANDLER_H_ diff --git a/middleware/rialto-gstreamer/source/MediaPlayerClientBackend.h b/middleware/rialto-gstreamer/source/MediaPlayerClientBackend.h deleted file mode 100644 index 8f9164c09..000000000 --- a/middleware/rialto-gstreamer/source/MediaPlayerClientBackend.h +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "MediaPlayerClientBackendInterface.h" -#include -#include -#include - -namespace firebolt::rialto::client -{ -class MediaPlayerClientBackend final : public MediaPlayerClientBackendInterface -{ -public: - MediaPlayerClientBackend() : m_mediaPlayerBackend(nullptr) {} - ~MediaPlayerClientBackend() final { m_mediaPlayerBackend.reset(); } - - void createMediaPlayerBackend(std::weak_ptr client, uint32_t maxWidth, uint32_t maxHeight) override - { - firebolt::rialto::VideoRequirements videoRequirements; - videoRequirements.maxWidth = maxWidth; - videoRequirements.maxHeight = maxHeight; - - m_mediaPlayerBackend = - firebolt::rialto::IMediaPipelineFactory::createFactory()->createMediaPipeline(client, videoRequirements); - - if (!m_mediaPlayerBackend) - { - GST_ERROR("Could not create media player backend"); - return; - } - } - - bool isMediaPlayerBackendCreated() const override { return static_cast(m_mediaPlayerBackend); } - - bool attachSource(std::unique_ptr &source) override - { - return m_mediaPlayerBackend->attachSource(source); - } - - bool removeSource(int32_t id) override { return m_mediaPlayerBackend->removeSource(id); } - - bool allSourcesAttached() override { return m_mediaPlayerBackend->allSourcesAttached(); } - - bool load(firebolt::rialto::MediaType type, const std::string &mimeType, const std::string &url) override - { - return m_mediaPlayerBackend->load(type, mimeType, url); - } - - bool play() override { return m_mediaPlayerBackend->play(); } - bool pause() override { return m_mediaPlayerBackend->pause(); } - bool stop() override { return m_mediaPlayerBackend->stop(); } - bool haveData(firebolt::rialto::MediaSourceStatus status, unsigned int needDataRequestId) override - { - return m_mediaPlayerBackend->haveData(status, needDataRequestId); - } - bool setPlaybackRate(double rate) override { return m_mediaPlayerBackend->setPlaybackRate(rate); } - bool setVideoWindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height) override - { - return m_mediaPlayerBackend->setVideoWindow(x, y, width, height); - } - - firebolt::rialto::AddSegmentStatus - addSegment(unsigned int needDataRequestId, - const std::unique_ptr &mediaSegment) override - { - return m_mediaPlayerBackend->addSegment(needDataRequestId, mediaSegment); - } - - bool getPosition(int64_t &position) override { return m_mediaPlayerBackend->getPosition(position); } - - bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override - { - return m_mediaPlayerBackend->setImmediateOutput(sourceId, immediateOutput); - } - - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override - { - return m_mediaPlayerBackend->getImmediateOutput(sourceId, immediateOutput); - } - - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override - { - return m_mediaPlayerBackend->getStats(sourceId, renderedFrames, droppedFrames); - } - - bool renderFrame() override { return m_mediaPlayerBackend->renderFrame(); } - - bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override - { - return m_mediaPlayerBackend->setVolume(targetVolume, volumeDuration, easeType); - } - - bool getVolume(double ¤tVolume) override { return m_mediaPlayerBackend->getVolume(currentVolume); } - - bool setMute(bool mute, int sourceId) override { return m_mediaPlayerBackend->setMute(sourceId, mute); } - - bool getMute(bool &mute, int sourceId) override { return m_mediaPlayerBackend->getMute(sourceId, mute); } - - bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override - { - return m_mediaPlayerBackend->setTextTrackIdentifier(textTrackIdentifier); - } - - bool getTextTrackIdentifier(std::string &textTrackIdentifier) override - { - return m_mediaPlayerBackend->getTextTrackIdentifier(textTrackIdentifier); - } - - bool setLowLatency(bool lowLatency) override { return m_mediaPlayerBackend->setLowLatency(lowLatency); } - - bool setSync(bool sync) override { return m_mediaPlayerBackend->setSync(sync); } - - bool getSync(bool &sync) override { return m_mediaPlayerBackend->getSync(sync); } - - bool setSyncOff(bool syncOff) override { return m_mediaPlayerBackend->setSyncOff(syncOff); } - - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override - { - return m_mediaPlayerBackend->setStreamSyncMode(sourceId, streamSyncMode); - } - - bool getStreamSyncMode(int32_t &streamSyncMode) override - { - return m_mediaPlayerBackend->getStreamSyncMode(streamSyncMode); - } - - bool flush(int32_t sourceId, bool resetTime, bool &async) override - { - return m_mediaPlayerBackend->flush(sourceId, resetTime, async); - } - - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate = 1.0, - uint64_t stopPosition = GST_CLOCK_TIME_NONE) override - { - return m_mediaPlayerBackend->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition); - } - - bool setSubtitleOffset(int32_t sourceId, int64_t position) override - { - return m_mediaPlayerBackend->setSubtitleOffset(sourceId, position); - } - - - bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override - { - return m_mediaPlayerBackend->processAudioGap(position, duration, discontinuityGap, audioAac); - } - - bool setBufferingLimit(uint32_t limitBufferingMs) override - { - return m_mediaPlayerBackend->setBufferingLimit(limitBufferingMs); - } - - bool getBufferingLimit(uint32_t &limitBufferingMs) override - { - return m_mediaPlayerBackend->getBufferingLimit(limitBufferingMs); - } - - bool setUseBuffering(bool useBuffering) override { return m_mediaPlayerBackend->setUseBuffering(useBuffering); } - - bool getUseBuffering(bool &useBuffering) override { return m_mediaPlayerBackend->getUseBuffering(useBuffering); } - - bool switchSource(const std::unique_ptr &source) override - { - return m_mediaPlayerBackend->switchSource(source); - } - -private: - std::unique_ptr m_mediaPlayerBackend; -}; -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/MediaPlayerClientBackendInterface.h b/middleware/rialto-gstreamer/source/MediaPlayerClientBackendInterface.h deleted file mode 100644 index 4206581e9..000000000 --- a/middleware/rialto-gstreamer/source/MediaPlayerClientBackendInterface.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include -#include - -#include - -namespace firebolt::rialto::client -{ -class MediaPlayerClientBackendInterface -{ -public: - virtual ~MediaPlayerClientBackendInterface() = default; - virtual void createMediaPlayerBackend(std::weak_ptr client, uint32_t maxWidth, - uint32_t maxHeight) = 0; - virtual bool isMediaPlayerBackendCreated() const = 0; - virtual bool attachSource(std::unique_ptr &source) = 0; - virtual bool removeSource(int32_t id) = 0; - virtual bool allSourcesAttached() = 0; - virtual bool load(firebolt::rialto::MediaType type, const std::string &mimeType, const std::string &url) = 0; - virtual bool play() = 0; - virtual bool pause() = 0; - virtual bool stop() = 0; - virtual bool haveData(firebolt::rialto::MediaSourceStatus status, unsigned int needDataRequestId) = 0; - virtual bool setPlaybackRate(double rate) = 0; - virtual bool setVideoWindow(unsigned int x, unsigned int y, unsigned int width, unsigned int height) = 0; - virtual firebolt::rialto::AddSegmentStatus - addSegment(unsigned int needDataRequestId, - const std::unique_ptr &mediaSegment) = 0; - virtual bool getPosition(int64_t &position) = 0; - virtual bool setImmediateOutput(int32_t sourceId, bool immediateOutput) = 0; - virtual bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) = 0; - virtual bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; - virtual bool renderFrame() = 0; - virtual bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) = 0; - virtual bool getVolume(double ¤tVolume) = 0; - virtual bool setMute(bool mute, int sourceId) = 0; - virtual bool getMute(bool &mute, int sourceId) = 0; - virtual bool setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; - virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; - virtual bool setLowLatency(bool lowLatency) = 0; - virtual bool setSync(bool sync) = 0; - virtual bool getSync(bool &sync) = 0; - virtual bool setSyncOff(bool syncOff) = 0; - virtual bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) = 0; - virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; - virtual bool flush(int32_t sourceId, bool resetTime, bool &async) = 0; - virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate = 1.0, - uint64_t stopPosition = GST_CLOCK_TIME_NONE) = 0; - virtual bool setSubtitleOffset(int32_t sourceId, int64_t position) = 0; - virtual bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; - virtual bool setBufferingLimit(uint32_t limitBufferingMs) = 0; - virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; - virtual bool setUseBuffering(bool useBuffering) = 0; - virtual bool getUseBuffering(bool &useBuffering) = 0; - virtual bool switchSource(const std::unique_ptr &source) = 0; -}; -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/MediaPlayerManager.cpp b/middleware/rialto-gstreamer/source/MediaPlayerManager.cpp deleted file mode 100644 index 2c7d8c63f..000000000 --- a/middleware/rialto-gstreamer/source/MediaPlayerManager.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "MediaPlayerManager.h" -#include "GstreamerCatLog.h" -#include "IMessageQueue.h" -#include "MediaPlayerClientBackend.h" - -std::mutex MediaPlayerManager::m_mediaPlayerClientsMutex; -std::map MediaPlayerManager::m_mediaPlayerClientsInfo; -#define GST_CAT_DEFAULT rialtoGStreamerCat -MediaPlayerManager::MediaPlayerManager() : m_currentGstBinParent(nullptr) {} - -MediaPlayerManager::~MediaPlayerManager() -{ - releaseMediaPlayerClient(); -} - -bool MediaPlayerManager::attachMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth, - const uint32_t maxVideoHeight) -{ - if (!m_client.lock()) - { - createMediaPlayerClient(gstBinParent, maxVideoWidth, maxVideoHeight); - } - else if (gstBinParent != m_currentGstBinParent) - { - // New parent gst bin, release old client and create new - releaseMediaPlayerClient(); - createMediaPlayerClient(gstBinParent, maxVideoWidth, maxVideoHeight); - } - - if (!m_client.lock()) - { - GST_ERROR("Failed to attach the media player client"); - return false; - } - else - { - return true; - } -} - -std::shared_ptr MediaPlayerManager::getMediaPlayerClient() const -{ - return m_client.lock(); -} - -bool MediaPlayerManager::hasControl() -{ - if (m_client.lock()) - { - std::lock_guard guard(m_mediaPlayerClientsMutex); - - auto it = m_mediaPlayerClientsInfo.find(m_currentGstBinParent); - if (it != m_mediaPlayerClientsInfo.end()) - { - if (it->second.controller == this) - { - return true; - } - else - { // in case there's no controller anymore - return acquireControl(it->second); - } - } - else - { - GST_WARNING("Could not find the attached media player client"); - } - } - else - { - GST_WARNING("No media player client attached"); - } - - return false; -} - -void MediaPlayerManager::releaseMediaPlayerClient() -{ - if (m_client.lock()) - { - std::lock_guard guard(m_mediaPlayerClientsMutex); - - auto it = m_mediaPlayerClientsInfo.find(m_currentGstBinParent); - if (it != m_mediaPlayerClientsInfo.end()) - { - it->second.refCount--; - if (it->second.refCount == 0) - { - it->second.client->stop(); - it->second.client->stopStreaming(); - it->second.client->destroyClientBackend(); - m_mediaPlayerClientsInfo.erase(it); - } - else - { - if (it->second.controller == this) - it->second.controller = nullptr; - } - m_client.reset(); - m_currentGstBinParent = nullptr; - } - else - { - GST_ERROR("Could not find the attached media player client"); - } - } -} - -bool MediaPlayerManager::acquireControl(MediaPlayerClientInfo &mediaPlayerClientInfo) -{ - if (mediaPlayerClientInfo.controller == nullptr) - { - mediaPlayerClientInfo.controller = this; - return true; - } - - return false; -} - -void MediaPlayerManager::createMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth, - const uint32_t maxVideoHeight) -{ - std::lock_guard guard(m_mediaPlayerClientsMutex); - - auto it = m_mediaPlayerClientsInfo.find(gstBinParent); - if (it != m_mediaPlayerClientsInfo.end()) - { - it->second.refCount++; - m_client = it->second.client; - m_currentGstBinParent = gstBinParent; - } - else - { - std::shared_ptr clientBackend = - std::make_shared(); - std::shared_ptr client = - std::make_shared(IMessageQueueFactory::createFactory(), clientBackend, - maxVideoWidth, maxVideoHeight); - - if (client->createBackend()) - { - // Store the new client in global map - MediaPlayerClientInfo newClientInfo; - newClientInfo.client = client; - newClientInfo.controller = this; - newClientInfo.refCount = 1; - m_mediaPlayerClientsInfo.insert( - std::pair(gstBinParent, newClientInfo)); - - // Store client info in object - m_client = client; - m_currentGstBinParent = gstBinParent; - } - else - { - GST_ERROR("Failed to create the media player client backend"); - return; - } - } -} diff --git a/middleware/rialto-gstreamer/source/MediaPlayerManager.h b/middleware/rialto-gstreamer/source/MediaPlayerManager.h deleted file mode 100644 index a2272f6ec..000000000 --- a/middleware/rialto-gstreamer/source/MediaPlayerManager.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef MEDIAPLAYERMANAGER_H -#define MEDIAPLAYERMANAGER_H - -#include "GStreamerMSEMediaPlayerClient.h" -#include - -class MediaPlayerManager -{ -public: - MediaPlayerManager(); - ~MediaPlayerManager(); - - std::shared_ptr getMediaPlayerClient() const; - bool attachMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth = 0, - const uint32_t maxVideoHeight = 0); - void releaseMediaPlayerClient(); - bool hasControl(); - -private: - struct MediaPlayerClientInfo - { - std::shared_ptr client; - void *controller; - uint32_t refCount; - }; - - void createMediaPlayerClient(const GstObject *gstBinParent, const uint32_t maxVideoWidth, - const uint32_t maxVideoHeight); - bool acquireControl(MediaPlayerClientInfo &mediaPlayerClientInfo); - - std::weak_ptr m_client; - const GstObject *m_currentGstBinParent; - - static std::mutex m_mediaPlayerClientsMutex; - static std::map m_mediaPlayerClientsInfo; -}; - -#endif // MEDIAPLAYERMANAGER_H \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/MessageQueue.cpp b/middleware/rialto-gstreamer/source/MessageQueue.cpp deleted file mode 100644 index 40ab2b87b..000000000 --- a/middleware/rialto-gstreamer/source/MessageQueue.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "MessageQueue.h" -#include "GstreamerCatLog.h" -#define GST_CAT_DEFAULT rialtoGStreamerCat -CallInEventLoopMessage::CallInEventLoopMessage(const std::function &func) : m_func(func), m_done{false} {} - -void CallInEventLoopMessage::handle() -{ - std::unique_lock lock(m_callInEventLoopMutex); - m_func(); - m_done = true; - m_callInEventLoopCondVar.notify_all(); -} - -void CallInEventLoopMessage::skip() -{ - std::unique_lock lock(m_callInEventLoopMutex); - m_done = true; - m_callInEventLoopCondVar.notify_all(); -} - -void CallInEventLoopMessage::wait() -{ - std::unique_lock lock(m_callInEventLoopMutex); - m_callInEventLoopCondVar.wait(lock, [this]() { return m_done; }); -} - -ScheduleInEventLoopMessage::ScheduleInEventLoopMessage(const std::function &func) : m_func(func) {} - -void ScheduleInEventLoopMessage::handle() -{ - m_func(); -} - -std::shared_ptr IMessageQueueFactory::createFactory() -{ - return std::make_shared(); -} - -std::unique_ptr MessageQueueFactory::createMessageQueue() const -{ - return std::make_unique(); -} - -namespace rialto -{ -MessageQueue::MessageQueue() : m_running(false) {} - -MessageQueue::~MessageQueue() -{ - doStop(); -} - -void MessageQueue::start() -{ - if (m_running) - { - // queue is running - return; - } - m_running = true; - std::thread startThread(&MessageQueue::processMessages, this); - m_workerThread.swap(startThread); -} - -void MessageQueue::stop() -{ - doStop(); -} - -void MessageQueue::clear() -{ - doClear(); -} - -std::shared_ptr MessageQueue::waitForMessage() -{ - std::unique_lock lock(m_mutex); - while (m_queue.empty()) - { - m_condVar.wait(lock); - } - std::shared_ptr message = m_queue.front(); - m_queue.pop_front(); - return message; -} - -bool MessageQueue::postMessage(const std::shared_ptr &msg) -{ - const std::lock_guard lock(m_mutex); - if (!m_running) - { - GST_ERROR("Message queue is not running"); - return false; - } - m_queue.push_back(msg); - m_condVar.notify_all(); - - return true; -} - -void MessageQueue::processMessages() -{ - do - { - std::shared_ptr message = waitForMessage(); - message->handle(); - } while (m_running); -} - -bool MessageQueue::scheduleInEventLoop(const std::function &func) -{ - auto message = std::make_shared(func); - if (!postMessage(message)) - { - return false; - } - - return true; -} - -bool MessageQueue::callInEventLoop(const std::function &func) -{ - return callInEventLoopInternal(func); -} - -bool MessageQueue::callInEventLoopInternal(const std::function &func) -{ - if (std::this_thread::get_id() != m_workerThread.get_id()) - { - auto message = std::make_shared(func); - if (!postMessage(message)) - { - return false; - } - message->wait(); - } - else - { - func(); - } - - return true; -} - -void MessageQueue::doStop() -{ - if (!m_running) - { - // queue is not running - return; - } - callInEventLoopInternal([this]() { m_running = false; }); - - if (m_workerThread.joinable()) - m_workerThread.join(); - - doClear(); -} - -void MessageQueue::doClear() -{ - std::unique_lock lock(m_mutex); - while (!m_queue.empty()) - { - m_queue.front()->skip(); - m_queue.pop_front(); - } -} -} // namespace rialto diff --git a/middleware/rialto-gstreamer/source/MessageQueue.h b/middleware/rialto-gstreamer/source/MessageQueue.h deleted file mode 100644 index f6d22538a..000000000 --- a/middleware/rialto-gstreamer/source/MessageQueue.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "IMessageQueue.h" -#include -#include -#include -#include -#include -#include -#include - -class CallInEventLoopMessage : public Message -{ -public: - explicit CallInEventLoopMessage(const std::function &func); - void handle() override; - void skip() override; - void wait(); - -private: - const std::function m_func; - std::mutex m_callInEventLoopMutex; - std::condition_variable m_callInEventLoopCondVar; - bool m_done; -}; - -class ScheduleInEventLoopMessage : public Message -{ -public: - explicit ScheduleInEventLoopMessage(const std::function &func); - void handle() override; - -private: - const std::function m_func; -}; - -class MessageQueueFactory : public IMessageQueueFactory -{ -public: - std::unique_ptr createMessageQueue() const override; -}; -namespace rialto -{ -class MessageQueue : public IMessageQueue -{ -public: - MessageQueue(); - ~MessageQueue(); - - void start() override; - void stop() override; - void clear() override; - // Wait for a message to appear on the queue. - std::shared_ptr waitForMessage() override; - // Posts a message to the queue. - bool postMessage(const std::shared_ptr &msg) override; - void processMessages() override; - bool scheduleInEventLoop(const std::function &func) override; - bool callInEventLoop(const std::function &func) override; - -protected: - void doStop(); - void doClear(); - // We need to have a non-virtual method, which can be called in class destructor - bool callInEventLoopInternal(const std::function &func); - -protected: - std::condition_variable m_condVar; - std::mutex m_mutex; - std::deque> m_queue; - std::thread m_workerThread; - bool m_running; -}; -} // namespace rialto diff --git a/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.cpp deleted file mode 100644 index eee0f8693..000000000 --- a/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.cpp +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "PullModeAudioPlaybackDelegate.h" -#include "GStreamerMSEUtils.h" -#include "GstreamerCatLog.h" -#include -#include -#include - -#define GST_CAT_DEFAULT rialtoGStreamerCat - -namespace -{ -firebolt::rialto::EaseType convertCharToEaseType(char easeTypeChar) -{ - switch (easeTypeChar) - { - case 'L': - return firebolt::rialto::EaseType::EASE_LINEAR; - case 'I': - return firebolt::rialto::EaseType::EASE_IN_CUBIC; - case 'O': - return firebolt::rialto::EaseType::EASE_OUT_CUBIC; - default: - return firebolt::rialto::EaseType::EASE_LINEAR; - } -} -} // namespace - -PullModeAudioPlaybackDelegate::PullModeAudioPlaybackDelegate(GstElement *sink) : PullModePlaybackDelegate(sink) -{ - m_mediaSourceType = firebolt::rialto::MediaSourceType::AUDIO; -} - -GstStateChangeReturn PullModeAudioPlaybackDelegate::changeState(GstStateChange transition) -{ - switch (transition) - { - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - if (!attachToMediaClientAndSetStreamsNumber()) - { - return GST_STATE_CHANGE_FAILURE; - } - - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - GST_ERROR_OBJECT(m_sink, "MediaPlayerClient is nullptr"); - return GST_STATE_CHANGE_FAILURE; - } - if (m_isVolumeQueued) - { - client->setVolume(m_targetVolume, kDefaultVolumeDuration, kDefaultEaseType); - m_isVolumeQueued = false; - } - if (m_isAudioFadeQueued) - { - AudioFadeConfig audioFadeConfig; - { - std::lock_guard lock(m_audioFadeConfigMutex); - audioFadeConfig = m_audioFadeConfig; - } - client->setVolume(audioFadeConfig.volume, audioFadeConfig.duration, audioFadeConfig.easeType); - m_isAudioFadeQueued = false; - } - break; - } - default: - break; - } - return PullModePlaybackDelegate::changeState(transition); -} - -gboolean PullModeAudioPlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) -{ - switch (GST_EVENT_TYPE(event)) - { - case GST_EVENT_CAPS: - { - GstCaps *caps{nullptr}; - gst_event_parse_caps(event, &caps); - if (m_sourceAttached) - { - GST_INFO_OBJECT(m_sink, "Source already attached. Skip calling attachSource"); - break; - } - - GST_INFO_OBJECT(m_sink, "Attaching AUDIO source with caps %" GST_PTR_FORMAT, caps); - - std::unique_ptr asource = createMediaSource(caps); - if (asource) - { - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if ((!client) || (!client->attachSource(asource, RIALTO_MSE_BASE_SINK(m_sink), shared_from_this()))) - { - GST_ERROR_OBJECT(m_sink, "Failed to attach AUDIO source"); - } - else - { - m_sourceAttached = true; - - if (m_isMuteQueued) - { - client->setMute(m_mute, m_sourceId); - m_isMuteQueued = false; - } - if (m_isLowLatencyQueued) - { - if (!client->setLowLatency(m_lowLatency)) - { - GST_ERROR_OBJECT(m_sink, "Could not set queued low-latency"); - } - m_isLowLatencyQueued = false; - } - if (m_isSyncQueued) - { - if (!client->setSync(m_sync)) - { - GST_ERROR_OBJECT(m_sink, "Could not set queued sync"); - } - m_isSyncQueued = false; - } - if (m_isSyncOffQueued) - { - if (!client->setSyncOff(m_syncOff)) - { - GST_ERROR_OBJECT(m_sink, "Could not set queued sync-off"); - } - m_isSyncOffQueued = false; - } - if (m_isStreamSyncModeQueued) - { - if (!client->setStreamSyncMode(m_sourceId, m_streamSyncMode)) - { - GST_ERROR_OBJECT(m_sink, "Could not set queued stream-sync-mode"); - } - m_isStreamSyncModeQueued = false; - } - if (m_isBufferingLimitQueued) - { - client->setBufferingLimit(m_bufferingLimit); - m_isBufferingLimitQueued = false; - } - if (m_isUseBufferingQueued) - { - client->setUseBuffering(m_useBuffering); - m_isUseBufferingQueued = false; - } - // check if READY -> PAUSED was requested before source was attached - if (GST_STATE_NEXT(m_sink) == GST_STATE_PAUSED) - { - client->pause(m_sourceId); - } - } - } - else - { - GST_ERROR_OBJECT(m_sink, "Failed to create AUDIO source"); - } - break; - } - case GST_EVENT_CUSTOM_DOWNSTREAM: - case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: - { - if (gst_event_has_name(event, "switch-source")) - { - GST_DEBUG_OBJECT(m_sink, "Switch source event received"); - const GstStructure *structure{gst_event_get_structure(event)}; - const GValue *value = gst_structure_get_value(structure, "caps"); - if (!value) - { - GST_ERROR_OBJECT(m_sink, "Caps not available in switch-source event"); - break; - } - const GstCaps *caps = gst_value_get_caps(value); - GstCaps *mutableCaps = gst_caps_copy(caps); - std::unique_ptr asource = createMediaSource(mutableCaps); - gst_caps_unref(mutableCaps); - if (!asource) - { - GST_ERROR_OBJECT(m_sink, "Not able to parse caps"); - break; - } - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if ((!client) || (!client->switchSource(asource))) - { - GST_ERROR_OBJECT(m_sink, "Failed to switch AUDIO source"); - } - } - break; - } - default: - break; - } - return PullModePlaybackDelegate::handleEvent(pad, parent, event); -} - -void PullModeAudioPlaybackDelegate::getProperty(const Property &type, GValue *value) -{ - std::shared_ptr client{m_mediaPlayerManager.getMediaPlayerClient()}; - - switch (type) - { - case IPlaybackDelegate::Property::Volume: - { - double volume; - if (client) - { - if (client->getVolume(volume)) - m_targetVolume = volume; - else - volume = m_targetVolume; // Use last known volume - } - else - { - volume = m_targetVolume; - } - g_value_set_double(value, volume); - break; - } - case IPlaybackDelegate::Property::Mute: - { - if (!client) - { - g_value_set_boolean(value, m_mute); - return; - } - g_value_set_boolean(value, client->getMute(m_sourceId)); - break; - } - case IPlaybackDelegate::Property::Sync: - { - if (!client) - { - g_value_set_boolean(value, m_sync); - return; - } - - bool sync{kDefaultSync}; - if (!client->getSync(sync)) - { - GST_ERROR_OBJECT(m_sink, "Could not get sync"); - } - g_value_set_boolean(value, sync); - break; - } - case IPlaybackDelegate::Property::StreamSyncMode: - { - if (!client) - { - g_value_set_int(value, m_streamSyncMode); - return; - } - - int32_t streamSyncMode{kDefaultStreamSyncMode}; - if (!client->getStreamSyncMode(streamSyncMode)) - { - GST_ERROR_OBJECT(m_sink, "Could not get stream-sync-mode"); - } - g_value_set_int(value, streamSyncMode); - break; - } - case IPlaybackDelegate::Property::FadeVolume: - { - double volume{}; - if (!client || !client->getVolume(volume)) - { - g_value_set_uint(value, kDefaultFadeVolume); - return; - } - g_value_set_uint(value, static_cast(volume * 100.0)); - break; - } - case IPlaybackDelegate::Property::LimitBufferingMs: - { - if (!client) - { - g_value_set_uint(value, m_bufferingLimit); - return; - } - g_value_set_uint(value, client->getBufferingLimit()); - break; - } - case IPlaybackDelegate::Property::UseBuffering: - { - if (!client) - { - g_value_set_boolean(value, m_useBuffering); - return; - } - g_value_set_boolean(value, client->getUseBuffering()); - break; - } - case IPlaybackDelegate::Property::Async: - { - // Rialto MSE Audio sink is always async - g_value_set_boolean(value, TRUE); - break; - } - default: - { - PullModePlaybackDelegate::getProperty(type, value); - break; - } - } -} - -void PullModeAudioPlaybackDelegate::setProperty(const Property &type, const GValue *value) -{ - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - - switch (type) - { - case IPlaybackDelegate::Property::Volume: - { - m_targetVolume = g_value_get_double(value); - if (!client || !m_sourceAttached) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue volume setting"); - m_isVolumeQueued = true; - return; - } - client->setVolume(m_targetVolume, kDefaultVolumeDuration, kDefaultEaseType); - break; - } - case IPlaybackDelegate::Property::Mute: - { - m_mute = g_value_get_boolean(value); - if (!client || !m_sourceAttached) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue mute setting"); - m_isMuteQueued = true; - return; - } - client->setMute(m_mute, m_sourceId); - break; - } - case IPlaybackDelegate::Property::Gap: - { - gint64 position{0}, discontinuityGap{0}; - guint duration{0}; - gboolean audioAac{FALSE}; - - GstStructure *gapData = GST_STRUCTURE_CAST(g_value_get_boxed(value)); - if (!gst_structure_get_int64(gapData, "position", &position)) - { - GST_WARNING_OBJECT(m_sink, "Set gap: position is missing!"); - } - if (!gst_structure_get_uint(gapData, "duration", &duration)) - { - GST_WARNING_OBJECT(m_sink, "Set gap: duration is missing!"); - } - if (!gst_structure_get_int64(gapData, "discontinuity-gap", &discontinuityGap)) - { - GST_WARNING_OBJECT(m_sink, "Set gap: discontinuity gap is missing!"); - } - if (!gst_structure_get_boolean(gapData, "audio-aac", &audioAac)) - { - GST_WARNING_OBJECT(m_sink, "Set gap: audio aac is missing!"); - } - - GST_DEBUG_OBJECT(m_sink, "Processing audio gap."); - client->processAudioGap(position, duration, discontinuityGap, audioAac); - break; - } - case IPlaybackDelegate::Property::LowLatency: - { - m_lowLatency = g_value_get_boolean(value); - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue low latency setting"); - m_isLowLatencyQueued = true; - return; - } - - if (!client->setLowLatency(m_lowLatency)) - { - GST_ERROR_OBJECT(m_sink, "Could not set low-latency"); - } - break; - } - case IPlaybackDelegate::Property::Sync: - { - m_sync = g_value_get_boolean(value); - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue sync setting"); - m_isSyncQueued = true; - return; - } - - if (!client->setSync(m_sync)) - { - GST_ERROR_OBJECT(m_sink, "Could not set sync"); - } - break; - } - case IPlaybackDelegate::Property::SyncOff: - { - m_syncOff = g_value_get_boolean(value); - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue sync off setting"); - m_isSyncOffQueued = true; - return; - } - - if (!client->setSyncOff(m_syncOff)) - { - GST_ERROR_OBJECT(m_sink, "Could not set sync-off"); - } - break; - } - case IPlaybackDelegate::Property::StreamSyncMode: - { - m_streamSyncMode = g_value_get_int(value); - if (!client || !m_sourceAttached) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue stream sync mode setting"); - m_isStreamSyncModeQueued = true; - return; - } - - if (!client->setStreamSyncMode(m_sourceId, m_streamSyncMode)) - { - GST_ERROR_OBJECT(m_sink, "Could not set stream-sync-mode"); - } - break; - } - case IPlaybackDelegate::Property::AudioFade: - { - const gchar *audioFadeStr = g_value_get_string(value); - - uint32_t fadeVolume = static_cast(kDefaultVolume * 100); - uint32_t duration = kDefaultVolumeDuration; - char easeTypeChar = 'L'; - - int parsedItems = sscanf(audioFadeStr, "%u,%u,%c", &fadeVolume, &duration, &easeTypeChar); - - if (parsedItems == 0) - { - GST_ERROR_OBJECT(m_sink, "Failed to parse any values from audio fade string: %s.", audioFadeStr); - return; - } - else if (parsedItems == 1 || parsedItems == 2) - { - GST_WARNING_OBJECT(m_sink, "Partially parsed audio fade string: %s. Continuing with values: fadeVolume=%u, duration=%u, easeTypeChar=%c", - audioFadeStr, fadeVolume, duration, easeTypeChar); - } - - if (fadeVolume > 100) - { - GST_WARNING_OBJECT(m_sink, "Fade volume is greater than 100. Setting it to 100."); - fadeVolume = 100; - } - double volume = fadeVolume / 100.0; - - firebolt::rialto::EaseType easeType = convertCharToEaseType(easeTypeChar); - - { - std::lock_guard lock(m_audioFadeConfigMutex); - m_audioFadeConfig.volume = volume; - m_audioFadeConfig.duration = duration; - m_audioFadeConfig.easeType = easeType; - } - - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue audio fade setting"); - m_isAudioFadeQueued = true; - return; - } - - client->setVolume(volume, duration, easeType); - break; - } - case IPlaybackDelegate::Property::LimitBufferingMs: - { - m_bufferingLimit = g_value_get_uint(value); - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue buffering limit setting"); - m_isBufferingLimitQueued = true; - return; - } - - client->setBufferingLimit(m_bufferingLimit); - break; - } - case IPlaybackDelegate::Property::UseBuffering: - { - m_useBuffering = g_value_get_boolean(value); - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue use buffering setting"); - m_isUseBufferingQueued = true; - return; - } - - client->setUseBuffering(m_useBuffering); - break; - } - case IPlaybackDelegate::Property::Async: - { - if (FALSE == g_value_get_boolean(value)) - { - GST_WARNING_OBJECT(m_sink, "Cannot set ASYNC to false - not supported"); - } - break; - } - default: - { - PullModePlaybackDelegate::setProperty(type, value); - break; - } - } -} - -void PullModeAudioPlaybackDelegate::handleQos(uint64_t processed, uint64_t dropped) const -{ - GstBus *bus = gst_element_get_bus(m_sink); - /* Hardcode isLive to FALSE and set invalid timestamps */ - GstMessage *message = gst_message_new_qos(GST_OBJECT(m_sink), FALSE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, - GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); - gst_message_set_qos_stats(message, GST_FORMAT_DEFAULT, processed, dropped); - gst_bus_post(bus, message); - gst_object_unref(bus); -} - -std::unique_ptr -PullModeAudioPlaybackDelegate::createMediaSource(GstCaps *caps) const -{ - GstStructure *structure = gst_caps_get_structure(caps, 0); - const gchar *structName = gst_structure_get_name(structure); - - firebolt::rialto::AudioConfig audioConfig{}; - firebolt::rialto::SegmentAlignment alignment{get_segment_alignment(structure)}; - std::shared_ptr codecData{get_codec_data(structure)}; - firebolt::rialto::StreamFormat format{get_stream_format(structure)}; - - if (structName) - { - std::string mimeType{}; - if (g_str_has_prefix(structName, "audio/mpeg") || g_str_has_prefix(structName, "audio/x-eac3") || - g_str_has_prefix(structName, "audio/x-ac3")) - { - gint sample_rate{0}; - gint number_of_channels{0}; - gst_structure_get_int(structure, "rate", &sample_rate); - gst_structure_get_int(structure, "channels", &number_of_channels); - - audioConfig = firebolt::rialto::AudioConfig{static_cast(number_of_channels), - static_cast(sample_rate), - {}}; - - if (g_str_has_prefix(structName, "audio/mpeg")) - { - gint mpegversion{0}; - gint layer{0}; - gst_structure_get_int(structure, "mpegversion", &mpegversion); - gst_structure_get_int(structure, "layer", &layer); - if (1 == mpegversion && 3 == layer) - { - mimeType = "audio/mp3"; - } - else - { - mimeType = "audio/mp4"; - } - } - else - { - mimeType = "audio/x-eac3"; - } - } - else if (g_str_has_prefix(structName, "audio/x-opus")) - { - mimeType = "audio/x-opus"; - guint32 sampleRate{48000}; - guint8 numberOfChannels{}, streams{}, stereoStreams{}, channelMappingFamily{}; - guint8 channelMapping[256]{}; - guint16 preSkip{0}; - gint16 gain{0}; - if (gst_codec_utils_opus_parse_caps(caps, &sampleRate, &numberOfChannels, &channelMappingFamily, &streams, - &stereoStreams, channelMapping)) - { - GstBuffer *idHeader{}; - idHeader = gst_codec_utils_opus_create_header(sampleRate, numberOfChannels, channelMappingFamily, - streams, stereoStreams, channelMapping, preSkip, gain); - std::vector codecSpecificConfig{}; - GstMapInfo lsMap{}; - if (gst_buffer_map(idHeader, &lsMap, GST_MAP_READ)) - { - codecSpecificConfig.assign(lsMap.data, lsMap.data + lsMap.size); - gst_buffer_unmap(idHeader, &lsMap); - } - else - { - GST_ERROR_OBJECT(m_sink, "Failed to read opus header details from a GstBuffer!"); - } - gst_buffer_unref(idHeader); - - audioConfig = firebolt::rialto::AudioConfig{numberOfChannels, sampleRate, codecSpecificConfig}; - } - else - { - GST_ERROR("Failed to parse opus caps!"); - return nullptr; - } - } - else if (g_str_has_prefix(structName, "audio/b-wav") || g_str_has_prefix(structName, "audio/x-raw")) - { - gint sampleRate{0}; - gint numberOfChannels{0}; - std::optional channelMask; - gst_structure_get_int(structure, "rate", &sampleRate); - gst_structure_get_int(structure, "channels", &numberOfChannels); - std::optional layout = - rialto_mse_sink_convert_layout(gst_structure_get_string(structure, "layout")); - std::optional rialtoFormat = - rialto_mse_sink_convert_format(gst_structure_get_string(structure, "format")); - const GValue *channelMaskValue = gst_structure_get_value(structure, "channel-mask"); - if (channelMaskValue) - { - channelMask = gst_value_get_bitmask(channelMaskValue); - } - - if (g_str_has_prefix(structName, "audio/b-wav")) - { - mimeType = "audio/b-wav"; - } - else - { - mimeType = "audio/x-raw"; - } - - audioConfig = firebolt::rialto::AudioConfig{static_cast(numberOfChannels), - static_cast(sampleRate), - {}, - rialtoFormat, - layout, - channelMask}; - } - else if (g_str_has_prefix(structName, "audio/x-flac")) - { - mimeType = "audio/x-flac"; - gint sampleRate{0}; - gint numberOfChannels{0}; - gst_structure_get_int(structure, "rate", &sampleRate); - gst_structure_get_int(structure, "channels", &numberOfChannels); - std::vector> streamHeaderVec; - const GValue *streamheader = gst_structure_get_value(structure, "streamheader"); - if (streamheader) - { - for (guint i = 0; i < gst_value_array_get_size(streamheader); ++i) - { - const GValue *headerValue = gst_value_array_get_value(streamheader, i); - GstBuffer *headerBuffer = gst_value_get_buffer(headerValue); - if (headerBuffer) - { - GstMappedBuffer mappedBuf(headerBuffer, GST_MAP_READ); - if (mappedBuf) - { - streamHeaderVec.push_back( - std::vector(mappedBuf.data(), mappedBuf.data() + mappedBuf.size())); - } - } - } - } - std::optional framed; - gboolean framedValue{FALSE}; - if (gst_structure_get_boolean(structure, "framed", &framedValue)) - { - framed = framedValue; - } - - audioConfig = firebolt::rialto::AudioConfig{static_cast(numberOfChannels), - static_cast(sampleRate), - {}, - std::nullopt, - std::nullopt, - std::nullopt, - streamHeaderVec, - framed}; - } - else - { - GST_INFO_OBJECT(m_sink, "%s audio media source created", structName); - mimeType = structName; - } - - return std::make_unique(mimeType, m_hasDrm, audioConfig, - alignment, format, codecData); - } - - GST_ERROR_OBJECT(m_sink, "Empty caps' structure name! Failed to set mime type for audio media source."); - return nullptr; -} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.h b/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.h deleted file mode 100644 index 7e4c2be6e..000000000 --- a/middleware/rialto-gstreamer/source/PullModeAudioPlaybackDelegate.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "PullModePlaybackDelegate.h" - -struct AudioFadeConfig -{ - double volume; - uint32_t duration; - firebolt::rialto::EaseType easeType; -}; - -class PullModeAudioPlaybackDelegate : public PullModePlaybackDelegate, - public std::enable_shared_from_this -{ -public: - explicit PullModeAudioPlaybackDelegate(GstElement *sink); - ~PullModeAudioPlaybackDelegate() override = default; - - GstStateChangeReturn changeState(GstStateChange transition) override; - gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; - void getProperty(const Property &type, GValue *value) override; - void setProperty(const Property &type, const GValue *value) override; - void handleQos(uint64_t processed, uint64_t dropped) const override; - -private: - std::unique_ptr createMediaSource(GstCaps *caps) const; - -private: - std::atomic m_targetVolume{kDefaultVolume}; - std::atomic_bool m_mute{kDefaultMute}; - std::atomic_bool m_isVolumeQueued{false}; - std::atomic_bool m_isMuteQueued{false}; - std::atomic_bool m_lowLatency{kDefaultLowLatency}; - std::atomic_bool m_isLowLatencyQueued{false}; - std::atomic_bool m_sync{kDefaultSync}; - std::atomic_bool m_isSyncQueued{false}; - std::atomic_bool m_syncOff{kDefaultSyncOff}; - std::atomic_bool m_isSyncOffQueued{false}; - std::atomic m_streamSyncMode{kDefaultStreamSyncMode}; - std::atomic_bool m_isStreamSyncModeQueued{false}; - AudioFadeConfig m_audioFadeConfig{}; - std::mutex m_audioFadeConfigMutex{}; - std::atomic_bool m_isAudioFadeQueued{false}; - std::atomic m_bufferingLimit{kDefaultBufferingLimit}; - std::atomic_bool m_isBufferingLimitQueued{false}; - std::atomic_bool m_useBuffering{kDefaultUseBuffering}; - std::atomic_bool m_isUseBufferingQueued{false}; -}; \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.cpp deleted file mode 100644 index 1171ee1db..000000000 --- a/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.cpp +++ /dev/null @@ -1,962 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "PullModePlaybackDelegate.h" -#include "ControlBackend.h" -#include "GstreamerCatLog.h" -#include "RialtoGStreamerMSEBaseSink.h" -#include "RialtoGStreamerMSEBaseSinkPrivate.h" - -#define GST_CAT_DEFAULT rialtoGStreamerCat - -namespace -{ -GstObject *getOldestGstBinParent(GstElement *element) -{ - GstObject *parent = gst_object_get_parent(GST_OBJECT_CAST(element)); - GstObject *result = GST_OBJECT_CAST(element); - if (parent) - { - if (GST_IS_BIN(parent)) - { - result = getOldestGstBinParent(GST_ELEMENT_CAST(parent)); - } - gst_object_unref(parent); - } - - return result; -} - -unsigned getGstPlayFlag(const char *nick) -{ - GFlagsClass *flagsClass = static_cast(g_type_class_ref(g_type_from_name("GstPlayFlags"))); - GFlagsValue *flag = g_flags_get_value_by_nick(flagsClass, nick); - return flag ? flag->value : 0; -} - -bool getNStreamsFromParent(GstObject *parentObject, gint &n_video, gint &n_audio, gint &n_text) -{ - if (g_object_class_find_property(G_OBJECT_GET_CLASS(parentObject), "n-video") && - g_object_class_find_property(G_OBJECT_GET_CLASS(parentObject), "n-audio") && - g_object_class_find_property(G_OBJECT_GET_CLASS(parentObject), "n-text")) - { - g_object_get(parentObject, "n-video", &n_video, "n-audio", &n_audio, "n-text", &n_text, nullptr); - - if (g_object_class_find_property(G_OBJECT_GET_CLASS(parentObject), "flags")) - { - guint flags = 0; - g_object_get(parentObject, "flags", &flags, nullptr); - n_video = (flags & getGstPlayFlag("video")) ? n_video : 0; - n_audio = (flags & getGstPlayFlag("audio")) ? n_audio : 0; - n_text = (flags & getGstPlayFlag("text")) ? n_text : 0; - } - - return true; - } - - return false; -} -} // namespace - -PullModePlaybackDelegate::PullModePlaybackDelegate(GstElement *sink) : m_sink{sink} -{ - RialtoMSEBaseSink *baseSink = RIALTO_MSE_BASE_SINK(sink); - m_sinkPad = baseSink->priv->m_sinkPad; - m_rialtoControlClient = std::make_unique(); - gst_segment_init(&m_lastSegment, GST_FORMAT_TIME); -} - -PullModePlaybackDelegate::~PullModePlaybackDelegate() -{ - if (m_caps) - gst_caps_unref(m_caps); - clearBuffersUnlocked(); -} - -void PullModePlaybackDelegate::clearBuffersUnlocked() -{ - m_isFlushOngoing = true; - m_needDataCondVariable.notify_all(); - while (!m_samples.empty()) - { - GstSample *sample = m_samples.front(); - m_samples.pop(); - gst_sample_unref(sample); - } -} - -void PullModePlaybackDelegate::setSourceId(int32_t sourceId) -{ - std::unique_lock lock{m_sinkMutex}; - m_sourceId = sourceId; -} - -void PullModePlaybackDelegate::handleEos() -{ - GstState currentState = GST_STATE(m_sink); - if ((currentState != GST_STATE_PAUSED) && (currentState != GST_STATE_PLAYING)) - { - GST_ERROR_OBJECT(m_sink, "Sink cannot post a EOS message in state '%s', posting an error instead", - gst_element_state_get_name(currentState)); - - const char *errMessage = "Rialto sinks received EOS in non-playing state"; - GError *gError{g_error_new_literal(GST_STREAM_ERROR, 0, errMessage)}; - gst_element_post_message(m_sink, gst_message_new_error(GST_OBJECT_CAST(m_sink), gError, errMessage)); - g_error_free(gError); - } - else if (!m_isFlushOngoing) - { - gst_element_post_message(m_sink, gst_message_new_eos(GST_OBJECT_CAST(m_sink))); - } - else - { - GST_WARNING_OBJECT(m_sink, "Skip sending eos message - flush is ongoing..."); - } -} - -void PullModePlaybackDelegate::handleFlushCompleted() -{ - GST_INFO_OBJECT(m_sink, "Flush completed"); - std::unique_lock lock(m_flushMutex); - m_flushCondVariable.notify_all(); -} - -void PullModePlaybackDelegate::handleStateChanged(firebolt::rialto::PlaybackState state) -{ - GstState current = GST_STATE(m_sink); - GstState next = GST_STATE_NEXT(m_sink); - GstState pending = GST_STATE_PENDING(m_sink); - GstState postNext = next == pending ? GST_STATE_VOID_PENDING : pending; - - GST_DEBUG_OBJECT(m_sink, - "Received server's state change to %u. Sink's states are: current state: %s next state: %s " - "pending state: %s, last return state %s", - static_cast(state), gst_element_state_get_name(current), - gst_element_state_get_name(next), gst_element_state_get_name(pending), - gst_element_state_change_return_get_name(GST_STATE_RETURN(m_sink))); - - if (m_isStateCommitNeeded) - { - if ((state == firebolt::rialto::PlaybackState::PAUSED && next == GST_STATE_PAUSED) || - (state == firebolt::rialto::PlaybackState::PLAYING && next == GST_STATE_PLAYING)) - { - GST_STATE(m_sink) = next; - GST_STATE_NEXT(m_sink) = postNext; - GST_STATE_PENDING(m_sink) = GST_STATE_VOID_PENDING; - GST_STATE_RETURN(m_sink) = GST_STATE_CHANGE_SUCCESS; - - GST_INFO_OBJECT(m_sink, "Async state transition to state %s done", gst_element_state_get_name(next)); - - gst_element_post_message(m_sink, - gst_message_new_state_changed(GST_OBJECT_CAST(m_sink), current, next, pending)); - postAsyncDone(); - } - /* Immediately transition to PLAYING when prerolled and PLAY is requested */ - else if (state == firebolt::rialto::PlaybackState::PAUSED && current == GST_STATE_PAUSED && - next == GST_STATE_PLAYING) - { - GST_INFO_OBJECT(m_sink, "Async state transition to PAUSED done. Transitioning to PLAYING"); - changeState(GST_STATE_CHANGE_PAUSED_TO_PLAYING); - } - } -} - -GstStateChangeReturn PullModePlaybackDelegate::changeState(GstStateChange transition) -{ - GstState current_state = GST_STATE_TRANSITION_CURRENT(transition); - GstState next_state = GST_STATE_TRANSITION_NEXT(transition); - GST_INFO_OBJECT(m_sink, "State change: (%s) -> (%s)", gst_element_state_get_name(current_state), - gst_element_state_get_name(next_state)); - - GstStateChangeReturn status = GST_STATE_CHANGE_SUCCESS; - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - - switch (transition) - { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!m_sinkPad) - { - GST_ERROR_OBJECT(m_sink, "Cannot start, because there's no sink pad"); - return GST_STATE_CHANGE_FAILURE; - } - if (!m_rialtoControlClient->waitForRunning()) - { - GST_ERROR_OBJECT(m_sink, "Control: Rialto client cannot reach running state"); - return GST_STATE_CHANGE_FAILURE; - } - GST_INFO_OBJECT(m_sink, "Control: Rialto client reached running state"); - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - if (!client) - { - GST_ERROR_OBJECT(m_sink, "Cannot get the media player client object"); - return GST_STATE_CHANGE_FAILURE; - } - - m_isFlushOngoing = false; - - StateChangeResult result = client->pause(m_sourceId); - if (result == StateChangeResult::SUCCESS_ASYNC || result == StateChangeResult::NOT_ATTACHED) - { - // NOT_ATTACHED is not a problem here, because source will be attached later when GST_EVENT_CAPS is received - if (result == StateChangeResult::NOT_ATTACHED) - { - postAsyncStart(); - } - status = GST_STATE_CHANGE_ASYNC; - } - - break; - } - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - { - if (!client) - { - GST_ERROR_OBJECT(m_sink, "Cannot get the media player client object"); - return GST_STATE_CHANGE_FAILURE; - } - - StateChangeResult result = client->play(m_sourceId); - if (result == StateChangeResult::SUCCESS_ASYNC) - { - status = GST_STATE_CHANGE_ASYNC; - } - else if (result == StateChangeResult::NOT_ATTACHED) - { - GST_ERROR_OBJECT(m_sink, "Failed to change state to playing"); - return GST_STATE_CHANGE_FAILURE; - } - - break; - } - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - { - if (!client) - { - GST_ERROR_OBJECT(m_sink, "Cannot get the media player client object"); - return GST_STATE_CHANGE_FAILURE; - } - - StateChangeResult result = client->pause(m_sourceId); - if (result == StateChangeResult::SUCCESS_ASYNC) - { - status = GST_STATE_CHANGE_ASYNC; - } - else if (result == StateChangeResult::NOT_ATTACHED) - { - GST_ERROR_OBJECT(m_sink, "Failed to change state to paused"); - return GST_STATE_CHANGE_FAILURE; - } - - break; - } - case GST_STATE_CHANGE_PAUSED_TO_READY: - if (!client) - { - GST_ERROR_OBJECT(m_sink, "Cannot get the media player client object"); - return GST_STATE_CHANGE_FAILURE; - } - - if (m_isStateCommitNeeded) - { - GST_DEBUG_OBJECT(m_sink, "Sending async_done in PAUSED->READY transition"); - postAsyncDone(); - } - - client->removeSource(m_sourceId); - { - std::lock_guard lock(m_sinkMutex); - clearBuffersUnlocked(); - m_sourceAttached = false; - } - break; - case GST_STATE_CHANGE_READY_TO_NULL: - // Playback will be stopped once all sources are finished and ref count - // of the media pipeline object reaches 0 - m_mediaPlayerManager.releaseMediaPlayerClient(); - m_rialtoControlClient->removeControlBackend(); - break; - default: - break; - } - - return status; -} - -void PullModePlaybackDelegate::handleError(const std::string &message, gint code) -{ - GError *gError{g_error_new_literal(GST_STREAM_ERROR, code, message.c_str())}; - gst_element_post_message(GST_ELEMENT_CAST(m_sink), - gst_message_new_error(GST_OBJECT_CAST(m_sink), gError, message.c_str())); - g_error_free(gError); -} - -void PullModePlaybackDelegate::postAsyncStart() -{ - m_isStateCommitNeeded = true; - gst_element_post_message(GST_ELEMENT_CAST(m_sink), gst_message_new_async_start(GST_OBJECT(m_sink))); -} - -void PullModePlaybackDelegate::postAsyncDone() -{ - m_isStateCommitNeeded = false; - gst_element_post_message(m_sink, gst_message_new_async_done(GST_OBJECT_CAST(m_sink), GST_CLOCK_TIME_NONE)); -} - -void PullModePlaybackDelegate::setProperty(const Property &type, const GValue *value) -{ - switch (type) - { - case Property::IsSinglePathStream: - { - std::lock_guard lock(m_sinkMutex); - m_isSinglePathStream = g_value_get_boolean(value) != FALSE; - break; - } - case Property::NumberOfStreams: - { - std::lock_guard lock(m_sinkMutex); - m_numOfStreams = g_value_get_int(value); - break; - } - case Property::HasDrm: - { - std::lock_guard lock(m_sinkMutex); - m_hasDrm = g_value_get_boolean(value) != FALSE; - break; - } - default: - { - break; - } - } -} - -void PullModePlaybackDelegate::getProperty(const Property &type, GValue *value) -{ - switch (type) - { - case Property::IsSinglePathStream: - { - std::lock_guard lock(m_sinkMutex); - g_value_set_boolean(value, m_isSinglePathStream ? TRUE : FALSE); - break; - } - case Property::NumberOfStreams: - { - std::lock_guard lock(m_sinkMutex); - g_value_set_int(value, m_numOfStreams); - break; - } - case Property::HasDrm: - { - std::lock_guard lock(m_sinkMutex); - g_value_set_boolean(value, m_hasDrm ? TRUE : FALSE); - break; - } - case Property::Stats: - { - std::lock_guard lock(m_sinkMutex); - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - GST_ERROR_OBJECT(m_sink, "Could not get the media player client"); - break; - } - - guint64 totalVideoFrames{0}; - guint64 droppedVideoFrames{0}; - if (client->getStats(m_sourceId, totalVideoFrames, droppedVideoFrames)) - { - GstStructure *stats{gst_structure_new("stats", "rendered", G_TYPE_UINT64, totalVideoFrames, "dropped", - G_TYPE_UINT64, droppedVideoFrames, nullptr)}; - g_value_set_pointer(value, stats); - } - else - { - GST_ERROR_OBJECT(m_sink, "No stats returned from client"); - } - } - default: - { - break; - } - } -} - -std::optional PullModePlaybackDelegate::handleQuery(GstQuery *query) const -{ - GST_DEBUG_OBJECT(m_sink, "handling query '%s'", GST_QUERY_TYPE_NAME(query)); - switch (GST_QUERY_TYPE(query)) - { - case GST_QUERY_SEEKING: - { - GstFormat fmt; - gst_query_parse_seeking(query, &fmt, NULL, NULL, NULL); - gst_query_set_seeking(query, fmt, FALSE, 0, -1); - return TRUE; - } - case GST_QUERY_POSITION: - { - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - return FALSE; - } - - GstFormat fmt; - gst_query_parse_position(query, &fmt, NULL); - switch (fmt) - { - case GST_FORMAT_TIME: - { - gint64 position = client->getPosition(m_sourceId); - GST_DEBUG_OBJECT(m_sink, "Queried position is %" GST_TIME_FORMAT, GST_TIME_ARGS(position)); - if (position < 0) - { - return FALSE; - } - - gst_query_set_position(query, fmt, position); - break; - } - default: - break; - } - return TRUE; - } - case GST_QUERY_SEGMENT: - { - std::lock_guard lock(m_sinkMutex); - GstFormat format{m_lastSegment.format}; - gint64 start{static_cast(gst_segment_to_stream_time(&m_lastSegment, format, m_lastSegment.start))}; - gint64 stop{0}; - if (m_lastSegment.stop == GST_CLOCK_TIME_NONE) - { - stop = m_lastSegment.duration; - } - else - { - stop = gst_segment_to_stream_time(&m_lastSegment, format, m_lastSegment.stop); - } - gst_query_set_segment(query, m_lastSegment.rate, format, start, stop); - return TRUE; - } - default: - break; - } - return std::nullopt; -} - -gboolean PullModePlaybackDelegate::handleSendEvent(GstEvent *event) -{ - GST_DEBUG_OBJECT(m_sink, "handling event '%s'", GST_EVENT_TYPE_NAME(event)); - bool shouldForwardUpstream = GST_EVENT_IS_UPSTREAM(event); - - switch (GST_EVENT_TYPE(event)) - { - case GST_EVENT_SEEK: - { - gdouble rate{1.0}; - GstFormat seekFormat{GST_FORMAT_UNDEFINED}; - GstSeekFlags flags{GST_SEEK_FLAG_NONE}; - GstSeekType startType{GST_SEEK_TYPE_NONE}, stopType{GST_SEEK_TYPE_NONE}; - gint64 start{0}, stop{0}; - if (event) - { - gst_event_parse_seek(event, &rate, &seekFormat, &flags, &startType, &start, &stopType, &stop); - - if (flags & GST_SEEK_FLAG_FLUSH) - { - if (seekFormat == GST_FORMAT_TIME && startType == GST_SEEK_TYPE_END) - { - GST_ERROR_OBJECT(m_sink, "GST_SEEK_TYPE_END seek is not supported"); - gst_event_unref(event); - return FALSE; - } - // Update last segment - if (seekFormat == GST_FORMAT_TIME) - { - gboolean update{FALSE}; - std::lock_guard lock(m_sinkMutex); - gst_segment_do_seek(&m_lastSegment, rate, seekFormat, flags, startType, start, stopType, stop, - &update); - } - } -#if GST_CHECK_VERSION(1, 18, 0) - else if (flags & GST_SEEK_FLAG_INSTANT_RATE_CHANGE) - { - gdouble rateMultiplier = rate / m_lastSegment.rate; - GstEvent *rateChangeEvent = gst_event_new_instant_rate_change(rateMultiplier, (GstSegmentFlags)flags); - gst_event_set_seqnum(rateChangeEvent, gst_event_get_seqnum(event)); - gst_event_unref(event); - if (gst_pad_send_event(m_sinkPad, rateChangeEvent) != TRUE) - { - GST_ERROR_OBJECT(m_sink, "Sending instant rate change failed."); - return FALSE; - } - return TRUE; - } -#endif - else - { - GST_WARNING_OBJECT(m_sink, "Seek with flags 0x%X is not supported", flags); - gst_event_unref(event); - return FALSE; - } - } - break; - } -#if GST_CHECK_VERSION(1, 18, 0) - case GST_EVENT_INSTANT_RATE_SYNC_TIME: - { - double rate{0.0}; - GstClockTime runningTime{GST_CLOCK_TIME_NONE}, upstreamRunningTime{GST_CLOCK_TIME_NONE}; - guint32 seqnum = gst_event_get_seqnum(event); - gst_event_parse_instant_rate_sync_time(event, &rate, &runningTime, &upstreamRunningTime); - - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if ((client) && (m_mediaPlayerManager.hasControl())) - { - GST_DEBUG_OBJECT(m_sink, "Instant playback rate change: %.2f", rate); - m_currentInstantRateChangeSeqnum = seqnum; - client->setPlaybackRate(rate); - } - break; - } -#endif - default: - break; - } - - if (shouldForwardUpstream) - { - bool result = gst_pad_push_event(m_sinkPad, event); - if (!result) - { - GST_DEBUG_OBJECT(m_sink, "forwarding upstream event '%s' failed", GST_EVENT_TYPE_NAME(event)); - } - - return result; - } - - gst_event_unref(event); - return TRUE; -} - -gboolean PullModePlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) -{ - GST_DEBUG_OBJECT(m_sink, "handling event %" GST_PTR_FORMAT, event); - switch (GST_EVENT_TYPE(event)) - { - case GST_EVENT_SEGMENT: - { - copySegment(event); - setSegment(); - break; - } - case GST_EVENT_EOS: - { - std::lock_guard lock(m_sinkMutex); - m_isEos = true; - break; - } - case GST_EVENT_CAPS: - { - GstCaps *caps; - gst_event_parse_caps(event, &caps); - { - std::lock_guard lock(m_sinkMutex); - if (m_caps) - { - if (!gst_caps_is_equal(caps, m_caps)) - { - gst_caps_unref(m_caps); - m_caps = gst_caps_copy(caps); - } - } - else - { - m_caps = gst_caps_copy(caps); - } - } - break; - } - case GST_EVENT_SINK_MESSAGE: - { - GstMessage *message = nullptr; - gst_event_parse_sink_message(event, &message); - - if (message) - { - gst_element_post_message(m_sink, message); - } - - break; - } - case GST_EVENT_CUSTOM_DOWNSTREAM: - case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: - { - if (gst_event_has_name(event, "custom-instant-rate-change")) - { - GST_DEBUG_OBJECT(m_sink, "Change rate event received"); - changePlaybackRate(event); - } - break; - } - case GST_EVENT_FLUSH_START: - { - startFlushing(); - break; - } - case GST_EVENT_FLUSH_STOP: - { - gboolean resetTime{FALSE}; - gst_event_parse_flush_stop(event, &resetTime); - - stopFlushing(resetTime); - break; - } - case GST_EVENT_STREAM_COLLECTION: - { - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - gst_event_unref(event); - return FALSE; - } - int32_t videoStreams{0}, audioStreams{0}, textStreams{0}; - GstStreamCollection *streamCollection{nullptr}; - gst_event_parse_stream_collection(event, &streamCollection); - guint streamsSize = gst_stream_collection_get_size(streamCollection); - for (guint i = 0; i < streamsSize; ++i) - { - auto *stream = gst_stream_collection_get_stream(streamCollection, i); - auto type = gst_stream_get_stream_type(stream); - if (type & GST_STREAM_TYPE_AUDIO) - { - ++audioStreams; - } - else if (type & GST_STREAM_TYPE_VIDEO) - { - ++videoStreams; - } - else if (type & GST_STREAM_TYPE_TEXT) - { - ++textStreams; - } - } - gst_object_unref(streamCollection); - client->handleStreamCollection(audioStreams, videoStreams, textStreams); - client->sendAllSourcesAttachedIfPossible(); - break; - } -#if GST_CHECK_VERSION(1, 18, 0) - case GST_EVENT_INSTANT_RATE_CHANGE: - { - guint32 seqnum = gst_event_get_seqnum(event); - if (m_lastInstantRateChangeSeqnum == seqnum || m_currentInstantRateChangeSeqnum.load() == seqnum) - { - /* Ignore if we already received the instant-rate-sync-time event from the pipeline */ - GST_DEBUG_OBJECT(m_sink, "Instant rate change event with seqnum %u already handled. Ignoring...", seqnum); - break; - } - - m_lastInstantRateChangeSeqnum = seqnum; - gdouble rate{0.0}; - GstSegmentFlags flags{GST_SEGMENT_FLAG_NONE}; - gst_event_parse_instant_rate_change(event, &rate, &flags); - GstMessage *msg = gst_message_new_instant_rate_request(GST_OBJECT_CAST(m_sink), rate); - gst_message_set_seqnum(msg, seqnum); - gst_element_post_message(m_sink, msg); - break; - } -#endif - default: - break; - } - - gst_event_unref(event); - - return TRUE; -} - -void PullModePlaybackDelegate::copySegment(GstEvent *event) -{ - std::lock_guard lock(m_sinkMutex); - gst_event_copy_segment(event, &m_lastSegment); -} - -void PullModePlaybackDelegate::setSegment() -{ - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - GST_ERROR_OBJECT(m_sink, "Could not get the media player client"); - return; - } - const bool kResetTime{m_lastSegment.flags == GST_SEGMENT_FLAG_RESET}; - int64_t position = static_cast(m_lastSegment.start); - client->setSourcePosition(m_sourceId, position, kResetTime, m_lastSegment.applied_rate, m_lastSegment.stop); - m_segmentSet = true; -} - -void PullModePlaybackDelegate::changePlaybackRate(GstEvent *event) -{ - const GstStructure *structure{gst_event_get_structure(event)}; - gdouble playbackRate{1.0}; - if (gst_structure_get_double(structure, "rate", &playbackRate) == TRUE) - { - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (client && m_mediaPlayerManager.hasControl()) - { - GST_DEBUG_OBJECT(m_sink, "Instant playback rate change: %.2f", playbackRate); - client->setPlaybackRate(playbackRate); - } - } -} - -void PullModePlaybackDelegate::startFlushing() -{ - std::lock_guard lock(m_sinkMutex); - if (!m_isFlushOngoing) - { - GST_INFO_OBJECT(m_sink, "Starting flushing"); - if (m_isEos) - { - GST_DEBUG_OBJECT(m_sink, "Flush will clear EOS state."); - m_isEos = false; - } - m_isFlushOngoing = true; - m_segmentSet = false; - clearBuffersUnlocked(); - } -} - -void PullModePlaybackDelegate::stopFlushing(bool resetTime) -{ - GST_INFO_OBJECT(m_sink, "Stopping flushing"); - flushServer(resetTime); - std::lock_guard lock(m_sinkMutex); - m_isFlushOngoing = false; - - if (resetTime) - { - GST_DEBUG_OBJECT(m_sink, "sending reset_time message"); - gst_element_post_message(m_sink, gst_message_new_reset_time(GST_OBJECT_CAST(m_sink), 0)); - } -} - -void PullModePlaybackDelegate::flushServer(bool resetTime) -{ - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - GST_ERROR_OBJECT(m_sink, "Could not get the media player client"); - return; - } - - std::unique_lock lock(m_flushMutex); - GST_INFO_OBJECT(m_sink, "Flushing sink with sourceId %d", m_sourceId.load()); - client->flush(m_sourceId, resetTime); - if (m_sourceAttached) - { - m_flushCondVariable.wait(lock); - } - else - { - GST_DEBUG_OBJECT(m_sink, "Skip waiting for flush finish - source not attached yet."); - } -} - -GstFlowReturn PullModePlaybackDelegate::handleBuffer(GstBuffer *buffer) -{ - constexpr size_t kMaxInternalBuffersQueueSize = 24; - GST_LOG_OBJECT(m_sink, "Handling buffer %p with PTS %" GST_TIME_FORMAT, buffer, - GST_TIME_ARGS(GST_BUFFER_PTS(buffer))); - - std::unique_lock lock(m_sinkMutex); - - if (m_samples.size() >= kMaxInternalBuffersQueueSize) - { - GST_DEBUG_OBJECT(m_sink, "Waiting for more space in buffers queue\n"); - m_needDataCondVariable.wait(lock); - } - - if (m_isFlushOngoing) - { - GST_DEBUG_OBJECT(m_sink, "Discarding buffer which was received during flushing"); - gst_buffer_unref(buffer); - return GST_FLOW_FLUSHING; - } - - GstSample *sample = gst_sample_new(buffer, m_caps, &m_lastSegment, nullptr); - if (sample) - m_samples.push(sample); - else - GST_ERROR_OBJECT(m_sink, "Failed to create a sample"); - - gst_buffer_unref(buffer); - - return GST_FLOW_OK; -} - -GstRefSample PullModePlaybackDelegate::getFrontSample() const -{ - std::lock_guard lock(m_sinkMutex); - if (!m_samples.empty()) - { - GstSample *sample = m_samples.front(); - GstBuffer *buffer = gst_sample_get_buffer(sample); - GST_LOG_OBJECT(m_sink, "Pulling buffer %p with PTS %" GST_TIME_FORMAT, buffer, - GST_TIME_ARGS(GST_BUFFER_PTS(buffer))); - - return GstRefSample{sample}; - } - - return GstRefSample{}; -} - -void PullModePlaybackDelegate::popSample() -{ - std::lock_guard lock(m_sinkMutex); - if (!m_samples.empty()) - { - gst_sample_unref(m_samples.front()); - m_samples.pop(); - } - m_needDataCondVariable.notify_all(); -} - -bool PullModePlaybackDelegate::isEos() const -{ - std::lock_guard lock(m_sinkMutex); - return m_samples.empty() && m_isEos; -} - -bool PullModePlaybackDelegate::isReadyToSendData() const -{ - std::lock_guard lock(m_sinkMutex); - return m_isEos || m_segmentSet; -} - -void PullModePlaybackDelegate::lostState() -{ - m_isStateCommitNeeded = true; - gst_element_lost_state(m_sink); -} - -bool PullModePlaybackDelegate::attachToMediaClientAndSetStreamsNumber(const uint32_t maxVideoWidth, - const uint32_t maxVideoHeight) -{ - GstObject *parentObject = getOldestGstBinParent(m_sink); - if (!m_mediaPlayerManager.attachMediaPlayerClient(parentObject, maxVideoWidth, maxVideoHeight)) - { - GST_ERROR_OBJECT(m_sink, "Cannot attach the MediaPlayerClient"); - return false; - } - - gchar *parentObjectName = gst_object_get_name(parentObject); - GST_INFO_OBJECT(m_sink, "Attached media player client with parent %s(%p)", parentObjectName, parentObject); - g_free(parentObjectName); - - return setStreamsNumber(parentObject); -} - -bool PullModePlaybackDelegate::setStreamsNumber(GstObject *parentObject) -{ - int32_t videoStreams{-1}, audioStreams{-1}, subtitleStreams{-1}; - - GstContext *context = gst_element_get_context(m_sink, "streams-info"); - if (context) - { - GST_DEBUG_OBJECT(m_sink, "Getting number of streams from \"streams-info\" context"); - - guint n_video{0}, n_audio{0}, n_text{0}; - - const GstStructure *streamsInfoStructure = gst_context_get_structure(context); - gst_structure_get_uint(streamsInfoStructure, "video-streams", &n_video); - gst_structure_get_uint(streamsInfoStructure, "audio-streams", &n_audio); - gst_structure_get_uint(streamsInfoStructure, "text-streams", &n_text); - - if (n_video > std::numeric_limits::max() || n_audio > std::numeric_limits::max() || - n_text > std::numeric_limits::max()) - { - GST_ERROR_OBJECT(m_sink, "Number of streams is too big, video=%u, audio=%u, text=%u", n_video, n_audio, - n_text); - gst_context_unref(context); - return false; - } - - videoStreams = n_video; - audioStreams = n_audio; - subtitleStreams = n_text; - - gst_context_unref(context); - } - else if (getNStreamsFromParent(parentObject, videoStreams, audioStreams, subtitleStreams)) - { - GST_DEBUG_OBJECT(m_sink, "Got number of streams from playbin2 properties"); - } - else - { - // The default value of streams is V:1, A:1, S:0 - // Changing the default setting via properties is considered as DEPRECATED - subtitleStreams = 0; - std::lock_guard lock{m_sinkMutex}; - if (m_mediaSourceType == firebolt::rialto::MediaSourceType::VIDEO) - { - videoStreams = m_numOfStreams; - if (m_isSinglePathStream) - { - audioStreams = 0; - subtitleStreams = 0; - } - } - else if (m_mediaSourceType == firebolt::rialto::MediaSourceType::AUDIO) - { - audioStreams = m_numOfStreams; - if (m_isSinglePathStream) - { - videoStreams = 0; - subtitleStreams = 0; - } - } - else if (m_mediaSourceType == firebolt::rialto::MediaSourceType::SUBTITLE) - { - subtitleStreams = m_numOfStreams; - if (m_isSinglePathStream) - { - videoStreams = 0; - audioStreams = 0; - } - } - } - - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - GST_ERROR_OBJECT(m_sink, "MediaPlayerClient is nullptr"); - return false; - } - - client->handleStreamCollection(audioStreams, videoStreams, subtitleStreams); - - return true; -} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.h b/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.h deleted file mode 100644 index 5b3fc86d1..000000000 --- a/middleware/rialto-gstreamer/source/PullModePlaybackDelegate.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "IPullModePlaybackDelegate.h" -#include - -#include - -#include "ControlBackendInterface.h" -#include "MediaPlayerManager.h" -#include -#include -#include -#include -#include - -class PullModePlaybackDelegate : public IPullModePlaybackDelegate -{ -protected: - explicit PullModePlaybackDelegate(GstElement *sink); - ~PullModePlaybackDelegate() override; - -public: - void setSourceId(int32_t sourceId) override; - - void handleEos() override; - void handleFlushCompleted() override; - void handleStateChanged(firebolt::rialto::PlaybackState state) override; - void handleError(const std::string &message, gint code = 0) override; - GstStateChangeReturn changeState(GstStateChange transition) override; - void postAsyncStart() override; - void setProperty(const Property &type, const GValue *value) override; - void getProperty(const Property &type, GValue *value) override; - std::optional handleQuery(GstQuery *query) const override; - gboolean handleSendEvent(GstEvent *event) override; - gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; - GstFlowReturn handleBuffer(GstBuffer *buffer) override; - GstRefSample getFrontSample() const override; - void popSample() override; - bool isEos() const override; - void lostState() override; - bool isReadyToSendData() const override; - -protected: - bool attachToMediaClientAndSetStreamsNumber(const uint32_t maxVideoWidth = 0, const uint32_t maxVideoHeight = 0); - -private: - void clearBuffersUnlocked(); - void postAsyncDone(); - void copySegment(GstEvent *event); - void setSegment(); - void changePlaybackRate(GstEvent *event); - void startFlushing(); - void stopFlushing(bool resetTime); - void flushServer(bool resetTime); - bool setStreamsNumber(GstObject *parentObject); - -protected: - GstElement *m_sink{nullptr}; - GstPad *m_sinkPad{nullptr}; - GstSegment m_lastSegment{}; - GstCaps *m_caps{nullptr}; - - std::atomic m_sourceId{-1}; - std::queue m_samples{}; - bool m_isEos{false}; - std::atomic m_segmentSet{false}; - std::atomic m_isFlushOngoing{false}; - std::atomic m_isStateCommitNeeded{false}; - mutable std::mutex m_sinkMutex{}; - - std::condition_variable m_needDataCondVariable{}; - std::condition_variable m_flushCondVariable{}; - std::mutex m_flushMutex{}; - - MediaPlayerManager m_mediaPlayerManager{}; - std::unique_ptr m_rialtoControlClient{}; - std::atomic m_sourceAttached{false}; - bool m_isSinglePathStream{false}; - int32_t m_numOfStreams{1}; - std::atomic m_hasDrm{true}; - std::atomic m_isAsync{false}; - firebolt::rialto::PlaybackState m_serverPlaybackState{firebolt::rialto::PlaybackState::UNKNOWN}; - firebolt::rialto::MediaSourceType m_mediaSourceType{firebolt::rialto::MediaSourceType::UNKNOWN}; - guint32 m_lastInstantRateChangeSeqnum{GST_SEQNUM_INVALID}; - std::atomic m_currentInstantRateChangeSeqnum{GST_SEQNUM_INVALID}; -}; \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.cpp deleted file mode 100644 index f32b816e4..000000000 --- a/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "PullModeSubtitlePlaybackDelegate.h" -#include "GstreamerCatLog.h" - -#define GST_CAT_DEFAULT rialtoGStreamerCat - -PullModeSubtitlePlaybackDelegate::PullModeSubtitlePlaybackDelegate(GstElement *sink) : PullModePlaybackDelegate(sink) -{ - m_mediaSourceType = firebolt::rialto::MediaSourceType::SUBTITLE; - m_isAsync = false; -} - -GstStateChangeReturn PullModeSubtitlePlaybackDelegate::changeState(GstStateChange transition) -{ - switch (transition) - { - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - if (!attachToMediaClientAndSetStreamsNumber()) - { - return GST_STATE_CHANGE_FAILURE; - } - } - default: - break; - } - return PullModePlaybackDelegate::changeState(transition); -} - -gboolean PullModeSubtitlePlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) -{ - switch (GST_EVENT_TYPE(event)) - { - case GST_EVENT_CAPS: - { - GstCaps *caps; - gst_event_parse_caps(event, &caps); - if (m_sourceAttached) - { - GST_INFO_OBJECT(m_sink, "Source already attached. Skip calling attachSource"); - break; - } - - GST_INFO_OBJECT(m_sink, "Attaching SUBTITLE source with caps %" GST_PTR_FORMAT, caps); - - std::unique_ptr subtitleSource{createMediaSource(caps)}; - if (subtitleSource) - { - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if ((!client) || (!client->attachSource(subtitleSource, RIALTO_MSE_BASE_SINK(m_sink), shared_from_this()))) - { - GST_ERROR_OBJECT(m_sink, "Failed to attach SUBTITLE source"); - } - else - { - m_sourceAttached = true; - if (m_isMuteQueued) - { - client->setMute(m_isMuted, m_sourceId); - m_isMuteQueued = false; - } - - { - std::unique_lock lock{m_mutex}; - if (m_isTextTrackIdentifierQueued) - { - client->setTextTrackIdentifier(m_textTrackIdentifier); - m_isTextTrackIdentifierQueued = false; - } - - if (m_queuedOffset) - { - GST_DEBUG_OBJECT(m_sink, "Setting subtitle offset to: %" GST_TIME_FORMAT, - GST_TIME_ARGS(m_queuedOffset.value())); - client->setSubtitleOffset(m_sourceId, m_queuedOffset.value()); - m_queuedOffset.reset(); - } - } - - // check if READY -> PAUSED was requested before source was attached - if (GST_STATE_NEXT(m_sink) == GST_STATE_PAUSED) - { - client->pause(m_sourceId); - } - } - } - else - { - GST_ERROR_OBJECT(m_sink, "Failed to create SUBTITLE source"); - } - - break; - } - case GST_EVENT_CUSTOM_DOWNSTREAM: - case GST_EVENT_CUSTOM_DOWNSTREAM_OOB: - { - if (gst_event_has_name(event, "set-pts-offset")) - { - GST_DEBUG_OBJECT(m_sink, "Set pts offset event received"); - const GstStructure *structure{gst_event_get_structure(event)}; - guint64 ptsOffset{GST_CLOCK_TIME_NONE}; - if (gst_structure_get_uint64(structure, "pts-offset", &ptsOffset) == TRUE) - { - std::unique_lock lock{m_sinkMutex}; - - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client || !m_sourceAttached) - { - GST_DEBUG_OBJECT(m_sink, "offset setting enqueued"); - m_queuedOffset = static_cast(ptsOffset); - } - else - { - GST_DEBUG_OBJECT(m_sink, "Setting subtitle offset to: %" GST_TIME_FORMAT, GST_TIME_ARGS(ptsOffset)); - client->setSubtitleOffset(m_sourceId, ptsOffset); - } - } - else - { - GST_WARNING_OBJECT(m_sink, "Unable to set pts offset. Value not present"); - } - } - break; - } - default: - break; - } - return PullModePlaybackDelegate::handleEvent(pad, parent, event); -} - -void PullModeSubtitlePlaybackDelegate::getProperty(const Property &type, GValue *value) -{ - std::shared_ptr client{m_mediaPlayerManager.getMediaPlayerClient()}; - - switch (type) - { - case Property::Mute: - { - if (!client) - { - g_value_set_boolean(value, m_isMuted); - return; - } - g_value_set_boolean(value, client->getMute(m_sourceId)); - break; - } - case Property::TextTrackIdentifier: - { - { - std::unique_lock lock{m_mutex}; - if (!client) - { - g_value_set_string(value, m_textTrackIdentifier.c_str()); - return; - } - } - g_value_set_string(value, client->getTextTrackIdentifier().c_str()); - - break; - } - case Property::WindowId: - { - g_value_set_uint(value, m_videoId); - break; - } - case Property::Async: - { - g_value_set_boolean(value, m_isAsync); - break; - } - default: - { - PullModePlaybackDelegate::getProperty(type, value); - break; - } - } -} - -void PullModeSubtitlePlaybackDelegate::setProperty(const Property &type, const GValue *value) -{ - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - - switch (type) - { - case Property::Mute: - m_isMuted = g_value_get_boolean(value); - if (!client || !m_sourceAttached) - { - m_isMuteQueued = true; - return; - } - - client->setMute(m_isMuted, m_sourceId); - - break; - case Property::TextTrackIdentifier: - { - const gchar *textTrackIdentifier = g_value_get_string(value); - if (!textTrackIdentifier) - { - GST_WARNING_OBJECT(m_sink, "TextTrackIdentifier string not valid"); - break; - } - - std::unique_lock lock{m_mutex}; - m_textTrackIdentifier = std::string(textTrackIdentifier); - if (!client || !m_sourceAttached) - { - GST_DEBUG_OBJECT(m_sink, "Text track identifier setting enqueued"); - m_isTextTrackIdentifierQueued = true; - } - else - { - client->setTextTrackIdentifier(m_textTrackIdentifier); - } - - break; - } - case Property::WindowId: - { - m_videoId = g_value_get_uint(value); - break; - } - case Property::Async: - { - m_isAsync = g_value_get_boolean(value); - break; - } - default: - { - PullModePlaybackDelegate::setProperty(type, value); - break; - } - } -} - -void PullModeSubtitlePlaybackDelegate::handleQos(uint64_t processed, uint64_t dropped) const -{ - GstBus *bus = gst_element_get_bus(m_sink); - /* Hardcode isLive to FALSE and set invalid timestamps */ - GstMessage *message = gst_message_new_qos(GST_OBJECT(m_sink), FALSE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, - GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); - - gst_message_set_qos_stats(message, GST_FORMAT_BUFFERS, processed, dropped); - gst_bus_post(bus, message); - gst_object_unref(bus); -} - -std::unique_ptr -PullModeSubtitlePlaybackDelegate::createMediaSource(GstCaps *caps) const -{ - GstStructure *structure = gst_caps_get_structure(caps, 0); - const gchar *mimeName = gst_structure_get_name(structure); - if (mimeName) - { - std::string mimeType{}; - if (g_str_has_prefix(mimeName, "text/vtt") || g_str_has_prefix(mimeName, "application/x-subtitle-vtt")) - { - mimeType = "text/vtt"; - } - else if (g_str_has_prefix(mimeName, "application/ttml+xml")) - { - mimeType = "text/ttml"; - } - else if (g_str_has_prefix(mimeName, "closedcaption/x-cea-608") || - g_str_has_prefix(mimeName, "closedcaption/x-cea-708") || - g_str_has_prefix(mimeName, "application/x-cea-608") || - g_str_has_prefix(mimeName, "application/x-cea-708") || - g_str_has_prefix(mimeName, "application/x-subtitle-cc")) - { - mimeType = "text/cc"; - } - else - { - mimeType = mimeName; - } - - GST_INFO_OBJECT(m_sink, "%s subtitle media source created", mimeType.c_str()); - return std::make_unique(mimeType, m_textTrackIdentifier); - } - else - { - GST_ERROR_OBJECT(m_sink, - "Empty caps' structure name! Failed to set mime type when constructing subtitle media source"); - } - - return nullptr; -} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.h b/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.h deleted file mode 100644 index e5b810637..000000000 --- a/middleware/rialto-gstreamer/source/PullModeSubtitlePlaybackDelegate.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "PullModePlaybackDelegate.h" -#include -#include -#include - -class PullModeSubtitlePlaybackDelegate : public PullModePlaybackDelegate, - public std::enable_shared_from_this -{ -public: - explicit PullModeSubtitlePlaybackDelegate(GstElement *sink); - ~PullModeSubtitlePlaybackDelegate() override = default; - - GstStateChangeReturn changeState(GstStateChange transition) override; - gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; - void getProperty(const Property &type, GValue *value) override; - void setProperty(const Property &type, const GValue *value) override; - void handleQos(uint64_t processed, uint64_t dropped) const override; - -private: - std::unique_ptr createMediaSource(GstCaps *caps) const; - -private: - std::mutex m_mutex; - std::string m_textTrackIdentifier{}; - bool m_isTextTrackIdentifierQueued{false}; - std::atomic m_isMuted{false}; - bool m_isMuteQueued{false}; - uint32_t m_videoId{0}; - std::optional m_queuedOffset{}; -}; diff --git a/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.cpp deleted file mode 100644 index 8bc36a0da..000000000 --- a/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "PullModeVideoPlaybackDelegate.h" -#include "GStreamerEMEUtils.h" -#include "GStreamerMSEUtils.h" -#include "GstreamerCatLog.h" - -#define GST_CAT_DEFAULT rialtoGStreamerCat - -PullModeVideoPlaybackDelegate::PullModeVideoPlaybackDelegate(GstElement *sink) : PullModePlaybackDelegate(sink) -{ - m_mediaSourceType = firebolt::rialto::MediaSourceType::VIDEO; - m_isAsync = true; -} - -GstStateChangeReturn PullModeVideoPlaybackDelegate::changeState(GstStateChange transition) -{ - switch (transition) - { - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - if (!attachToMediaClientAndSetStreamsNumber(m_maxWidth, m_maxHeight)) - { - return GST_STATE_CHANGE_FAILURE; - } - - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - GST_ERROR_OBJECT(m_sink, "MediaPlayerClient is nullptr"); - return GST_STATE_CHANGE_FAILURE; - } - - std::unique_lock lock{m_propertyMutex}; - if (m_rectangleSettingQueued) - { - GST_DEBUG_OBJECT(m_sink, "Set queued video rectangle"); - m_rectangleSettingQueued = false; - client->setVideoRectangle(m_videoRectangle); - } - break; - } - default: - break; - } - return PullModePlaybackDelegate::changeState(transition); -} - -gboolean PullModeVideoPlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) -{ - switch (GST_EVENT_TYPE(event)) - { - case GST_EVENT_CAPS: - { - GstCaps *caps{nullptr}; - gst_event_parse_caps(event, &caps); - if (m_sourceAttached) - { - GST_INFO_OBJECT(m_sink, "Source already attached. Skip calling attachSource"); - break; - } - - GST_INFO_OBJECT(m_sink, "Attaching VIDEO source with caps %" GST_PTR_FORMAT, caps); - - std::unique_ptr vsource = createMediaSource(caps); - if (vsource) - { - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - if ((!client) || (!client->attachSource(vsource, RIALTO_MSE_BASE_SINK(m_sink), shared_from_this()))) - { - GST_ERROR_OBJECT(m_sink, "Failed to attach VIDEO source"); - } - else - { - m_sourceAttached = true; - - // check if READY -> PAUSED was requested before source was attached - if (GST_STATE_NEXT(m_sink) == GST_STATE_PAUSED) - { - client->pause(m_sourceId); - } - std::unique_lock lock{m_propertyMutex}; - if (m_immediateOutputQueued) - { - GST_DEBUG_OBJECT(m_sink, "Set queued immediate-output"); - m_immediateOutputQueued = false; - if (!client->setImmediateOutput(m_sourceId, m_immediateOutput)) - { - GST_ERROR_OBJECT(m_sink, "Could not set immediate-output"); - } - } - if (m_syncmodeStreamingQueued) - { - GST_DEBUG_OBJECT(m_sink, "Set queued syncmode-streaming"); - m_syncmodeStreamingQueued = false; - if (!client->setStreamSyncMode(m_sourceId, m_syncmodeStreaming)) - { - GST_ERROR_OBJECT(m_sink, "Could not set syncmode-streaming"); - } - } - if (m_videoMuteQueued) - { - GST_DEBUG_OBJECT(m_sink, "Set queued show-video-window"); - m_videoMuteQueued = false; - client->setMute(m_videoMute, m_sourceId); - } - } - } - else - { - GST_ERROR_OBJECT(m_sink, "Failed to create VIDEO source"); - } - - break; - } - default: - break; - } - return PullModePlaybackDelegate::handleEvent(pad, parent, event); -} - -void PullModeVideoPlaybackDelegate::getProperty(const Property &type, GValue *value) -{ - switch (type) - { - case Property::WindowSet: - { - std::unique_lock lock{m_propertyMutex}; - auto client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - // Return the default value and - // queue a setting event (for the default value) so that it will become true when - // the client connects... - GST_DEBUG_OBJECT(m_sink, "Return default rectangle setting, and queue an event to set the default upon " - "client connect"); - m_rectangleSettingQueued = true; - g_value_set_string(value, m_videoRectangle.c_str()); - } - else - { - lock.unlock(); - g_value_set_string(value, client->getVideoRectangle().c_str()); - } - break; - } - case Property::MaxVideoWidth: - { - g_value_set_uint(value, m_maxWidth); - break; - } - case Property::MaxVideoHeight: - { - g_value_set_uint(value, m_maxHeight); - break; - } - case Property::FrameStepOnPreroll: - { - g_value_set_boolean(value, m_stepOnPrerollEnabled); - break; - } - case Property::ImmediateOutput: - { - std::unique_lock lock{m_propertyMutex}; - auto client = m_mediaPlayerManager.getMediaPlayerClient(); - if (!client) - { - // Return the default value and - // queue a setting event (for the default value) so that it will become true when - // the client connects... - GST_DEBUG_OBJECT(m_sink, "Return default immediate-output setting, and queue an event to set the default " - "upon client connect"); - m_immediateOutputQueued = true; - g_value_set_boolean(value, m_immediateOutput); - } - else - { - bool immediateOutput{m_immediateOutput}; - lock.unlock(); - if (!client->getImmediateOutput(m_sourceId, immediateOutput)) - { - GST_ERROR_OBJECT(m_sink, "Could not get immediate-output"); - } - g_value_set_boolean(value, immediateOutput); - } - break; - } - default: - { - PullModePlaybackDelegate::getProperty(type, value); - break; - } - } -} - -void PullModeVideoPlaybackDelegate::setProperty(const Property &type, const GValue *value) -{ - std::shared_ptr client = m_mediaPlayerManager.getMediaPlayerClient(); - switch (type) - { - case Property::WindowSet: - { - const gchar *rectangle = g_value_get_string(value); - if (!rectangle) - { - GST_WARNING_OBJECT(m_sink, "Rectangle string not valid"); - break; - } - std::string videoRectangle{rectangle}; - std::unique_lock lock{m_propertyMutex}; - m_videoRectangle = videoRectangle; - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Rectangle setting enqueued"); - m_rectangleSettingQueued = true; - } - else - { - lock.unlock(); - client->setVideoRectangle(videoRectangle); - } - break; - } - case Property::MaxVideoWidth: - m_maxWidth = g_value_get_uint(value); - break; - case Property::MaxVideoHeight: - m_maxHeight = g_value_get_uint(value); - break; - case Property::FrameStepOnPreroll: - { - bool stepOnPrerollEnabled = g_value_get_boolean(value); - if (client && stepOnPrerollEnabled && !m_stepOnPrerollEnabled) - { - GST_INFO_OBJECT(m_sink, "Frame stepping on preroll"); - client->renderFrame(m_sourceId); - } - m_stepOnPrerollEnabled = stepOnPrerollEnabled; - break; - } - case Property::ImmediateOutput: - { - bool immediateOutput = (g_value_get_boolean(value) != FALSE); - std::unique_lock lock{m_propertyMutex}; - m_immediateOutput = immediateOutput; - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Immediate output setting enqueued"); - m_immediateOutputQueued = true; - } - else - { - lock.unlock(); - if (!client->setImmediateOutput(m_sourceId, immediateOutput)) - { - GST_ERROR_OBJECT(m_sink, "Could not set immediate-output"); - } - } - break; - } - case Property::SyncmodeStreaming: - { - bool syncmodeStreaming = (g_value_get_boolean(value) != FALSE); - std::unique_lock lock{m_propertyMutex}; - m_syncmodeStreaming = syncmodeStreaming; - if (!client) - { - GST_DEBUG_OBJECT(m_sink, "Syncmode streaming setting enqueued"); - m_syncmodeStreamingQueued = true; - } - else - { - lock.unlock(); - if (!client->setStreamSyncMode(m_sourceId, syncmodeStreaming)) - { - GST_ERROR_OBJECT(m_sink, "Could not set syncmode-streaming"); - } - } - break; - } - case Property::ShowVideoWindow: - { - bool videoMute = (g_value_get_boolean(value) == FALSE); - std::unique_lock lock{m_propertyMutex}; - m_videoMute = videoMute; - if (!client || !m_sourceAttached) - { - GST_DEBUG_OBJECT(m_sink, "Show video window setting enqueued"); - m_videoMuteQueued = true; - } - else - { - lock.unlock(); - client->setMute(videoMute, m_sourceId); - } - break; - } - default: - { - PullModePlaybackDelegate::setProperty(type, value); - break; - } - } -} - -void PullModeVideoPlaybackDelegate::handleQos(uint64_t processed, uint64_t dropped) const -{ - GstBus *bus = gst_element_get_bus(m_sink); - /* Hardcode isLive to FALSE and set invalid timestamps */ - GstMessage *message = gst_message_new_qos(GST_OBJECT(m_sink), FALSE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, - GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); - - gst_message_set_qos_stats(message, GST_FORMAT_BUFFERS, processed, dropped); - gst_bus_post(bus, message); - gst_object_unref(bus); -} - -std::unique_ptr -PullModeVideoPlaybackDelegate::createMediaSource(GstCaps *caps) const -{ - GstStructure *structure = gst_caps_get_structure(caps, 0); - const gchar *strct_name = gst_structure_get_name(structure); - - firebolt::rialto::SegmentAlignment alignment = get_segment_alignment(structure); - std::shared_ptr codecData = get_codec_data(structure); - firebolt::rialto::StreamFormat format = get_stream_format(structure); - - gint width{0}; - gint height{0}; - gst_structure_get_int(structure, "width", &width); - gst_structure_get_int(structure, "height", &height); - - if (strct_name) - { - std::string mimeType{}; - if (g_str_has_prefix(strct_name, "video/x-h264")) - { - mimeType = "video/h264"; - } - else if (g_str_has_prefix(strct_name, "video/x-h265")) - { - mimeType = "video/h265"; - - uint32_t dolbyVisionProfile{0}; - if (get_dv_profile(structure, dolbyVisionProfile)) - { - return std::make_unique(mimeType, - dolbyVisionProfile, - m_hasDrm, width, - height, alignment, - format, codecData); - } - } - else - { - mimeType = strct_name; - } - - GST_INFO_OBJECT(m_sink, "%s video media source created", mimeType.c_str()); - return std::make_unique(mimeType, m_hasDrm, width, height, - alignment, format, codecData); - } - else - { - GST_ERROR_OBJECT(m_sink, - "Empty caps' structure name! Failed to set mime type when constructing video media source"); - } - - return nullptr; -} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.h b/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.h deleted file mode 100644 index a9bb5b652..000000000 --- a/middleware/rialto-gstreamer/source/PullModeVideoPlaybackDelegate.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "PullModePlaybackDelegate.h" - -class PullModeVideoPlaybackDelegate : public PullModePlaybackDelegate, - public std::enable_shared_from_this -{ -public: - explicit PullModeVideoPlaybackDelegate(GstElement *sink); - ~PullModeVideoPlaybackDelegate() override = default; - - GstStateChangeReturn changeState(GstStateChange transition) override; - gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; - void getProperty(const Property &type, GValue *value) override; - void setProperty(const Property &type, const GValue *value) override; - void handleQos(uint64_t processed, uint64_t dropped) const override; - -private: - std::unique_ptr createMediaSource(GstCaps *caps) const; - -private: - uint32_t m_maxWidth{0}; - uint32_t m_maxHeight{0}; - bool m_stepOnPrerollEnabled{false}; - - std::mutex m_propertyMutex{}; - // START of variables locked by propertyMutex - // rectangle properties - std::string m_videoRectangle{"0,0,1920,1080"}; - bool m_rectangleSettingQueued{false}; - // immediate output properties - bool m_immediateOutput{false}; - bool m_immediateOutputQueued{false}; - bool m_syncmodeStreaming{false}; - bool m_syncmodeStreamingQueued{false}; - bool m_videoMute{false}; - bool m_videoMuteQueued{false}; - // END of variables locked by propertyMutex -}; \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.cpp b/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.cpp deleted file mode 100644 index 57eafbf8c..000000000 --- a/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "PushModeAudioPlaybackDelegate.h" -#include "ControlBackend.h" -#include "GStreamerWebAudioPlayerClient.h" -#include "GstreamerCatLog.h" -#include "MessageQueue.h" -#include "WebAudioClientBackend.h" - -#define GST_CAT_DEFAULT rialtoGStreamerCat - -PushModeAudioPlaybackDelegate::PushModeAudioPlaybackDelegate(GstElement *sink) - : m_sink{sink}, m_rialtoControlClient{std::make_unique()}, - m_webAudioClient{ - std::make_shared(std::make_unique(), - std::make_unique(), *this, - ITimerFactory::getFactory())} -{ -} - -PushModeAudioPlaybackDelegate::~PushModeAudioPlaybackDelegate() -{ - m_webAudioClient.reset(); -} - -void PushModeAudioPlaybackDelegate::handleEos() -{ - GstState currentState = GST_STATE(m_sink); - if ((currentState != GST_STATE_PAUSED) && (currentState != GST_STATE_PLAYING)) - { - GST_ERROR_OBJECT(m_sink, "Sink cannot post a EOS message in state '%s', posting an error instead", - gst_element_state_get_name(currentState)); - - const char *errMessage = "Web audio sink received EOS in non-playing state"; - GError *gError{g_error_new_literal(GST_STREAM_ERROR, 0, errMessage)}; - gst_element_post_message(GST_ELEMENT_CAST(m_sink), - gst_message_new_error(GST_OBJECT_CAST(m_sink), gError, errMessage)); - g_error_free(gError); - } - else - { - gst_element_post_message(GST_ELEMENT_CAST(m_sink), gst_message_new_eos(GST_OBJECT_CAST(m_sink))); - } -} - -void PushModeAudioPlaybackDelegate::handleStateChanged(firebolt::rialto::PlaybackState state) -{ - GstState current = GST_STATE(m_sink); - GstState next = GST_STATE_NEXT(m_sink); - GstState pending = GST_STATE_PENDING(m_sink); - - GST_DEBUG_OBJECT(m_sink, - "Received server's state change to %u. Sink's states are: current state: %s next state: %s " - "pending state: %s, last return state %s", - static_cast(state), gst_element_state_get_name(current), - gst_element_state_get_name(next), gst_element_state_get_name(pending), - gst_element_state_change_return_get_name(GST_STATE_RETURN(m_sink))); - - if (m_isStateCommitNeeded && ((state == firebolt::rialto::PlaybackState::PAUSED && next == GST_STATE_PAUSED) || - (state == firebolt::rialto::PlaybackState::PLAYING && next == GST_STATE_PLAYING))) - { - GstState postNext = next == pending ? GST_STATE_VOID_PENDING : pending; - GST_STATE(m_sink) = next; - GST_STATE_NEXT(m_sink) = postNext; - GST_STATE_PENDING(m_sink) = GST_STATE_VOID_PENDING; - GST_STATE_RETURN(m_sink) = GST_STATE_CHANGE_SUCCESS; - - GST_INFO_OBJECT(m_sink, "Async state transition to state %s done", gst_element_state_get_name(next)); - - gst_element_post_message(GST_ELEMENT_CAST(m_sink), - gst_message_new_state_changed(GST_OBJECT_CAST(m_sink), current, next, pending)); - postAsyncDone(); - } -} - -void PushModeAudioPlaybackDelegate::handleError(const std::string &message, gint code) -{ - GError *gError{g_error_new_literal(GST_STREAM_ERROR, code, message.c_str())}; - gst_element_post_message(GST_ELEMENT_CAST(m_sink), - gst_message_new_error(GST_OBJECT_CAST(m_sink), gError, message.c_str())); - g_error_free(gError); -} - -void PushModeAudioPlaybackDelegate::handleQos(uint64_t processed, uint64_t dropped) const {} - -GstStateChangeReturn PushModeAudioPlaybackDelegate::changeState(GstStateChange transition) -{ - GstPad *sinkPad = gst_element_get_static_pad(GST_ELEMENT_CAST(m_sink), "sink"); - - GstState current_state = GST_STATE_TRANSITION_CURRENT(transition); - GstState next_state = GST_STATE_TRANSITION_NEXT(transition); - GST_INFO_OBJECT(m_sink, "State change: (%s) -> (%s)", gst_element_state_get_name(current_state), - gst_element_state_get_name(next_state)); - - GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS; - switch (transition) - { - case GST_STATE_CHANGE_NULL_TO_READY: - { - GST_DEBUG_OBJECT(m_sink, "GST_STATE_CHANGE_NULL_TO_READY"); - - if (!m_rialtoControlClient->waitForRunning()) - { - GST_ERROR_OBJECT(m_sink, "Rialto client cannot reach running state"); - result = GST_STATE_CHANGE_FAILURE; - } - break; - } - case GST_STATE_CHANGE_READY_TO_PAUSED: - { - GST_DEBUG("GST_STATE_CHANGE_READY_TO_PAUSED"); - break; - } - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - { - GST_DEBUG_OBJECT(m_sink, "GST_STATE_CHANGE_PAUSED_TO_PLAYING"); - if (!m_webAudioClient->isOpen()) - { - GST_INFO_OBJECT(m_sink, "Delay playing until the caps are recieved and the player is opened"); - m_isPlayingDelayed = true; - result = GST_STATE_CHANGE_ASYNC; - postAsyncStart(); - } - else - { - if (!m_webAudioClient->play()) - { - GST_ERROR_OBJECT(m_sink, "Failed to play web audio"); - result = GST_STATE_CHANGE_FAILURE; - } - else - { - result = GST_STATE_CHANGE_ASYNC; - postAsyncStart(); - } - } - break; - } - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - { - GST_DEBUG_OBJECT(m_sink, "GST_STATE_CHANGE_PLAYING_TO_PAUSED"); - if (!m_webAudioClient->pause()) - { - GST_ERROR_OBJECT(m_sink, "Failed to pause web audio"); - result = GST_STATE_CHANGE_FAILURE; - } - else - { - result = GST_STATE_CHANGE_ASYNC; - postAsyncStart(); - } - break; - } - case GST_STATE_CHANGE_PAUSED_TO_READY: - { - GST_DEBUG_OBJECT(m_sink, "GST_STATE_CHANGE_PAUSED_TO_READY"); - if (!m_webAudioClient->close()) - { - GST_ERROR_OBJECT(m_sink, "Failed to close web audio"); - result = GST_STATE_CHANGE_FAILURE; - } - break; - } - case GST_STATE_CHANGE_READY_TO_NULL: - { - GST_DEBUG("GST_STATE_CHANGE_READY_TO_NULL"); - - m_rialtoControlClient->removeControlBackend(); - } - default: - break; - } - - gst_object_unref(sinkPad); - - return result; -} - -void PushModeAudioPlaybackDelegate::postAsyncStart() -{ - m_isStateCommitNeeded = true; - gst_element_post_message(GST_ELEMENT_CAST(m_sink), gst_message_new_async_start(GST_OBJECT(m_sink))); -} - -void PushModeAudioPlaybackDelegate::setProperty(const Property &type, const GValue *value) -{ - switch (type) - { - case Property::TsOffset: - { - GST_INFO_OBJECT(m_sink, "ts-offset property not supported, RialtoWebAudioSink does not require the " - "synchronisation of sources"); - break; - } - case Property::Volume: - { - m_volume = g_value_get_double(value); - if (!m_webAudioClient || !m_webAudioClient->isOpen()) - { - GST_DEBUG_OBJECT(m_sink, "Enqueue volume setting"); - m_isVolumeQueued = true; - return; - } - if (!m_webAudioClient->setVolume(m_volume)) - { - GST_ERROR_OBJECT(m_sink, "Failed to set volume"); - } - break; - } - default: - { - break; - } - } -} - -void PushModeAudioPlaybackDelegate::getProperty(const Property &type, GValue *value) -{ - switch (type) - { - case Property::TsOffset: - { - GST_INFO_OBJECT(m_sink, "ts-offset property not supported, RialtoWebAudioSink does not require the " - "synchronisation of sources"); - break; - } - case Property::Volume: - { - double volume{0.0}; - if (m_webAudioClient && m_webAudioClient->isOpen()) - { - if (m_webAudioClient->getVolume(volume)) - m_volume = volume; - else - volume = m_volume; // Use last known volume - } - else - { - volume = m_volume; - } - g_value_set_double(value, volume); - break; - } - default: - { - break; - } - } -} - -std::optional PushModeAudioPlaybackDelegate::handleQuery(GstQuery *query) const -{ - return std::nullopt; -} - -gboolean PushModeAudioPlaybackDelegate::handleSendEvent(GstEvent *event) -{ - switch (GST_EVENT_TYPE(event)) - { - case GST_EVENT_CAPS: - { - GstCaps *caps; - gst_event_parse_caps(event, &caps); - GST_INFO_OBJECT(m_sink, "Attaching AUDIO source with caps %" GST_PTR_FORMAT, caps); - } - default: - break; - } - gst_event_unref(event); - return TRUE; -} - -gboolean PushModeAudioPlaybackDelegate::handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) -{ - gboolean result = FALSE; - switch (GST_EVENT_TYPE(event)) - { - case GST_EVENT_EOS: - { - GST_DEBUG_OBJECT(m_sink, "GST_EVENT_EOS"); - result = m_webAudioClient->setEos(); - break; - } - case GST_EVENT_CAPS: - { - GstCaps *caps; - gst_event_parse_caps(event, &caps); - GST_INFO_OBJECT(m_sink, "Opening WebAudio with caps %" GST_PTR_FORMAT, caps); - - if (!m_webAudioClient->open(caps)) - { - GST_ERROR_OBJECT(m_sink, "Failed to open web audio"); - } - else - { - result = TRUE; - if (m_isVolumeQueued) - { - if (!m_webAudioClient->setVolume(m_volume)) - { - GST_ERROR_OBJECT(m_sink, "Failed to set volume"); - result = FALSE; - } - else - { - m_isVolumeQueued = false; - } - } - if (m_isPlayingDelayed) - { - if (!m_webAudioClient->play()) - { - GST_ERROR_OBJECT(m_sink, "Failed to play web audio"); - result = FALSE; - } - else - { - m_isPlayingDelayed = false; - } - } - } - break; - } - default: - return gst_pad_event_default(pad, parent, event); - } - gst_event_unref(event); - return result; -} - -GstFlowReturn PushModeAudioPlaybackDelegate::handleBuffer(GstBuffer *buffer) -{ - if (m_webAudioClient->notifyNewSample(buffer)) - { - return GST_FLOW_OK; - } - else - { - GST_ERROR_OBJECT(m_sink, "Failed to push sample"); - return GST_FLOW_ERROR; - } -} - -void PushModeAudioPlaybackDelegate::postAsyncDone() -{ - m_isStateCommitNeeded = false; - gst_element_post_message(GST_ELEMENT_CAST(m_sink), - gst_message_new_async_done(GST_OBJECT_CAST(m_sink), GST_CLOCK_TIME_NONE)); -} \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.h b/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.h deleted file mode 100644 index a1b1359e0..000000000 --- a/middleware/rialto-gstreamer/source/PushModeAudioPlaybackDelegate.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2025 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "Constants.h" -#include "ControlBackendInterface.h" -#include "GStreamerWebAudioPlayerClient.h" -#include "IPlaybackDelegate.h" -#include -#include -#include - -class PushModeAudioPlaybackDelegate : public IPlaybackDelegate -{ -public: - explicit PushModeAudioPlaybackDelegate(GstElement *sink); - ~PushModeAudioPlaybackDelegate() override; - - void handleEos() override; - void handleStateChanged(firebolt::rialto::PlaybackState state) override; - void handleError(const std::string &message, gint code = 0) override; - void handleQos(uint64_t processed, uint64_t dropped) const override; - GstStateChangeReturn changeState(GstStateChange transition) override; - void postAsyncStart() override; - void setProperty(const Property &type, const GValue *value) override; - void getProperty(const Property &type, GValue *value) override; - std::optional handleQuery(GstQuery *query) const override; - gboolean handleSendEvent(GstEvent *event) override; - gboolean handleEvent(GstPad *pad, GstObject *parent, GstEvent *event) override; - GstFlowReturn handleBuffer(GstBuffer *buffer) override; - -private: - void postAsyncDone(); - -private: - GstElement *m_sink; - std::unique_ptr m_rialtoControlClient; - std::shared_ptr m_webAudioClient; - bool m_isPlayingDelayed{false}; - std::atomic m_isStateCommitNeeded{false}; - std::atomic m_volume{kDefaultVolume}; - std::atomic m_isVolumeQueued{false}; -}; \ No newline at end of file diff --git a/middleware/rialto-gstreamer/source/RialtoGSteamerPlugin.cpp b/middleware/rialto-gstreamer/source/RialtoGSteamerPlugin.cpp deleted file mode 100644 index ef0978595..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGSteamerPlugin.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "GstreamerCatLog.h" -#include "RialtoGStreamerMSEAudioSink.h" -#include "RialtoGStreamerMSESubtitleSink.h" -#include "RialtoGStreamerMSEVideoSink.h" -#include "RialtoGStreamerWebAudioSink.h" -#include -#include - -#ifndef PACKAGE -#define PACKAGE "rialto-gstreamer" -#endif - -static gboolean rialto_mse_sinks_init(GstPlugin *plugin) -{ - init_gst_debug_category(); - - const char kSrcRev[] = "N"; - const char kTags[] = "N"; - - if (std::strlen(kSrcRev) > 0) - { - if (std::strlen(kTags) > 0) - { - GST_INFO("Release Tag(s): %s (Commit ID: %s)", kTags, kSrcRev); - } - else - { - GST_INFO("Release Tag(s): No Release Tags! (Commit ID: %s)", kSrcRev); - } - } - else - { - GST_WARNING("Failed to get git commit ID!"); - } - - const char *socketPathStr = getenv("RIALTO_SOCKET_PATH"); - guint sinkRank = socketPathStr ? std::numeric_limits::max() : 0; - - const char *sinkRankStr = getenv("RIALTO_SINKS_RANK"); - if (sinkRankStr) - { - char *end; - unsigned long val = strtoul(sinkRankStr, &end, 10); - if (*end != '\0' || errno == ERANGE) - GST_WARNING("Failed to parse 'RIALTO_SINKS_RANK' env variable - '%s'", sinkRankStr); - else - sinkRank = val; - } - - if (sinkRank == 0) - { - GST_INFO("sinkRank has a value of 0"); - return true; - } - - GST_INFO("Registering plugins with rank %u", sinkRank); - - return gst_element_register(plugin, "rialtomsevideosink", sinkRank, RIALTO_TYPE_MSE_VIDEO_SINK) && - gst_element_register(plugin, "rialtomseaudiosink", sinkRank, RIALTO_TYPE_MSE_AUDIO_SINK) && - gst_element_register(plugin, "rialtomsesubtitlesink", sinkRank, RIALTO_TYPE_MSE_SUBTITLE_SINK) && - gst_element_register(plugin, "rialtowebaudiosink", sinkRank, RIALTO_TYPE_WEB_AUDIO_SINK); -} - -GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, rialtosinks, "Sinks which communicate with RialtoServer", - rialto_mse_sinks_init, "1.0", "LGPL", PACKAGE, "https://gstreamer.net") diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.cpp deleted file mode 100644 index 105d002c7..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include - -#include -#include - -#include "GStreamerMSEUtils.h" -#include "IMediaPipelineCapabilities.h" -#include "PullModeAudioPlaybackDelegate.h" -#include "PushModeAudioPlaybackDelegate.h" -#include "RialtoGStreamerMSEAudioSink.h" -#include "RialtoGStreamerMSEBaseSinkPrivate.h" - -using namespace firebolt::rialto::client; - -GST_DEBUG_CATEGORY_STATIC(RialtoMSEAudioSinkDebug); -#define GST_CAT_DEFAULT RialtoMSEAudioSinkDebug - -#define rialto_mse_audio_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE(RialtoMSEAudioSink, rialto_mse_audio_sink, RIALTO_TYPE_MSE_BASE_SINK, - G_IMPLEMENT_INTERFACE(GST_TYPE_STREAM_VOLUME, NULL) - GST_DEBUG_CATEGORY_INIT(RialtoMSEAudioSinkDebug, "rialtomseaudiosink", 0, - "rialto mse audio sink")); - -enum -{ - PROP_0, - PROP_VOLUME, - PROP_MUTE, - PROP_GAP, - PROP_LOW_LATENCY, - PROP_SYNC, - PROP_SYNC_OFF, - PROP_STREAM_SYNC_MODE, - PROP_AUDIO_FADE, - PROP_FADE_VOLUME, - PROP_LIMIT_BUFFERING_MS, - PROP_USE_BUFFERING, - PROP_ASYNC, - PROP_WEBAUDIO, - PROP_LAST -}; - -static GstStateChangeReturn rialto_mse_audio_sink_change_state(GstElement *element, GstStateChange transition) -{ - RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(element); - if (GST_STATE_CHANGE_NULL_TO_READY == transition) - { - if (PlaybackMode::Pull == sink->priv->m_playbackMode) - { - GST_INFO_OBJECT(sink, "RialtoMSEAudioSink state change to READY. Initializing Pull Mode delegate"); - rialto_mse_base_sink_initialise_delegate(sink, std::make_shared(element)); - } - else // Push playback mode - { - GST_INFO_OBJECT(sink, "RialtoMSEAudioSink state change to READY. Initializing Push Mode delegate"); - rialto_mse_base_sink_initialise_delegate(sink, std::make_shared(element)); - } - } - - GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); - if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) - { - GST_WARNING_OBJECT(sink, "State change failed"); - return result; - } - - return result; -} - -static void rialto_mse_audio_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) -{ - RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(object); - switch (propId) - { - case PROP_VOLUME: - { - g_value_set_double(value, kDefaultVolume); - rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::Volume, value); - break; - } - case PROP_MUTE: - { - g_value_set_boolean(value, kDefaultMute); - rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::Mute, value); - break; - } - case PROP_SYNC: - { - g_value_set_boolean(value, kDefaultSync); - rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::Sync, value); - break; - } - case PROP_STREAM_SYNC_MODE: - { - g_value_set_int(value, kDefaultStreamSyncMode); - rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::StreamSyncMode, value); - break; - } - case PROP_FADE_VOLUME: - { - g_value_set_uint(value, kDefaultFadeVolume); - rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::FadeVolume, value); - break; - } - case PROP_LIMIT_BUFFERING_MS: - { - g_value_set_uint(value, kDefaultBufferingLimit); - rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::LimitBufferingMs, value); - break; - } - case PROP_USE_BUFFERING: - { - g_value_set_boolean(value, kDefaultUseBuffering); - rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::UseBuffering, value); - break; - } - case PROP_ASYNC: - { - g_value_set_boolean(value, TRUE); - rialto_mse_base_sink_handle_get_property(sink, IPlaybackDelegate::Property::Async, value); - break; - } - case PROP_WEBAUDIO: - { - g_value_set_boolean(value, (sink->priv->m_playbackMode == PlaybackMode::Push)); - break; - } - default: - { - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } - } -} - -static void rialto_mse_audio_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) -{ - RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(object); - switch (propId) - { - case PROP_VOLUME: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Volume, value); - break; - } - case PROP_MUTE: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Mute, value); - break; - } - case PROP_GAP: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Gap, value); - break; - } - case PROP_LOW_LATENCY: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::LowLatency, value); - break; - } - case PROP_SYNC: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Sync, value); - break; - } - case PROP_SYNC_OFF: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::SyncOff, value); - break; - } - case PROP_STREAM_SYNC_MODE: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::StreamSyncMode, value); - break; - } - case PROP_AUDIO_FADE: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::AudioFade, value); - break; - } - case PROP_LIMIT_BUFFERING_MS: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::LimitBufferingMs, value); - break; - } - case PROP_USE_BUFFERING: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::UseBuffering, value); - break; - } - case PROP_ASYNC: - { - rialto_mse_base_sink_handle_set_property(sink, IPlaybackDelegate::Property::Async, value); - break; - } - case PROP_WEBAUDIO: - { - if (GST_STATE(sink) > GST_STATE_NULL) - { - GST_ERROR_OBJECT(object, "Playback mode set too late - sink is not in NULL state"); - break; - } - if (TRUE == g_value_get_boolean(value)) - { - sink->priv->m_playbackMode = PlaybackMode::Push; - } - else - { - sink->priv->m_playbackMode = PlaybackMode::Pull; - } - break; - } - default: - { - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } - } -} - -static void rialto_mse_audio_sink_init(RialtoMSEAudioSink *sink) -{ - RialtoMSEBaseSinkPrivate *priv = sink->parent.priv; - - if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink))) - { - GST_ERROR_OBJECT(sink, "Failed to initialise AUDIO sink. Sink pad initialisation failed."); - return; - } - - gst_pad_set_chain_function(priv->m_sinkPad, rialto_mse_base_sink_chain); - gst_pad_set_event_function(priv->m_sinkPad, rialto_mse_base_sink_event); -} - -static void rialto_mse_audio_sink_class_init(RialtoMSEAudioSinkClass *klass) -{ - GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); - GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); - gobjectClass->get_property = rialto_mse_audio_sink_get_property; - gobjectClass->set_property = rialto_mse_audio_sink_set_property; - elementClass->change_state = rialto_mse_audio_sink_change_state; - - g_object_class_install_property(gobjectClass, PROP_VOLUME, - g_param_spec_double("volume", "Volume", "Volume of this stream", 0, 1.0, - kDefaultVolume, - GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property(gobjectClass, PROP_MUTE, - g_param_spec_boolean("mute", "Mute", "Mute status of this stream", kDefaultMute, - GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property(gobjectClass, PROP_GAP, - g_param_spec_boxed("gap", "Gap", "Audio Gap", GST_TYPE_STRUCTURE, - (GParamFlags)(G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property(gobjectClass, PROP_USE_BUFFERING, - g_param_spec_boolean("use-buffering", - "Use buffering", "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds", - kDefaultUseBuffering, G_PARAM_READWRITE)); - g_object_class_install_property(gobjectClass, PROP_ASYNC, - g_param_spec_boolean("async", "Async", "Asynchronous mode", FALSE, G_PARAM_READWRITE)); - g_object_class_install_property(gobjectClass, PROP_WEBAUDIO, - g_param_spec_boolean("web-audio", - "Webaudio mode", "Enable webaudio mode. Property should be set before NULL->READY transition", - FALSE, G_PARAM_READWRITE)); - - std::unique_ptr mediaPlayerCapabilities = - firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities(); - if (mediaPlayerCapabilities) - { - std::vector supportedMimeTypes = - mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::AUDIO); - - rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes); - - const std::string kLowLatencyPropertyName{"low-latency"}; - const std::string kSyncPropertyName{"sync"}; - const std::string kSyncOffPropertyName{"sync-off"}; - const std::string kStreamSyncModePropertyName{"stream-sync-mode"}; - const std::string kAudioFadePropertyName{"audio-fade"}; - const std::string kFadeVolumePropertyName{"fade-volume"}; - const std::string kBufferingLimitPropertyName{"limit-buffering-ms"}; - const std::vector kPropertyNamesToSearch{kLowLatencyPropertyName, kSyncPropertyName, - kSyncOffPropertyName, kStreamSyncModePropertyName, - kBufferingLimitPropertyName, kAudioFadePropertyName, - kFadeVolumePropertyName}; - std::vector supportedProperties{ - mediaPlayerCapabilities->getSupportedProperties(firebolt::rialto::MediaSourceType::AUDIO, - kPropertyNamesToSearch)}; - - for (auto it = supportedProperties.begin(); it != supportedProperties.end(); ++it) - { - if (kLowLatencyPropertyName == *it) - { - g_object_class_install_property(gobjectClass, PROP_LOW_LATENCY, - g_param_spec_boolean(kLowLatencyPropertyName.c_str(), - "low latency", "Turn on low latency mode, for use with gaming (no audio decoding, no a/v sync)", - kDefaultLowLatency, GParamFlags(G_PARAM_WRITABLE))); - } - else if (kSyncPropertyName == *it) - { - g_object_class_install_property(gobjectClass, PROP_SYNC, - g_param_spec_boolean(kSyncPropertyName.c_str(), "sync", "Clock sync", - kDefaultSync, GParamFlags(G_PARAM_READWRITE))); - } - else if (kSyncOffPropertyName == *it) - { - g_object_class_install_property(gobjectClass, PROP_SYNC_OFF, - g_param_spec_boolean(kSyncOffPropertyName.c_str(), - "sync off", "Turn on free running audio. Must be set before pipeline is PLAYING state.", - kDefaultSyncOff, GParamFlags(G_PARAM_WRITABLE))); - } - else if (kStreamSyncModePropertyName == *it) - { - g_object_class_install_property(gobjectClass, PROP_STREAM_SYNC_MODE, - g_param_spec_int(kStreamSyncModePropertyName.c_str(), - "stream sync mode", "1 - Frame to decode frame will immediately proceed next frame sync, 0 - Frame decoded with no frame sync", - 0, G_MAXINT, kDefaultStreamSyncMode, - GParamFlags(G_PARAM_READWRITE))); - } - else if (kAudioFadePropertyName == *it) - { - g_object_class_install_property(gobjectClass, PROP_AUDIO_FADE, - g_param_spec_string(kAudioFadePropertyName.c_str(), - "audio fade", "Start audio fade (vol[0-100],duration ms,easetype[(L)inear,Cubic(I)n,Cubic(O)ut])", - kDefaultAudioFade, GParamFlags(G_PARAM_WRITABLE))); - } - else if (kFadeVolumePropertyName == *it) - { - g_object_class_install_property(gobjectClass, PROP_FADE_VOLUME, - g_param_spec_uint(kFadeVolumePropertyName.c_str(), "fade volume", - "Get current fade volume", 0, 100, kDefaultFadeVolume, - G_PARAM_READABLE)); - } - else if (kBufferingLimitPropertyName == *it) - { - constexpr uint32_t kMaxValue{20000}; - g_object_class_install_property(gobjectClass, PROP_LIMIT_BUFFERING_MS, - g_param_spec_uint("limit-buffering-ms", - "limit buffering ms", "Set millisecond threshold used if limit_buffering is set. Changing this value does not enable/disable limit_buffering", - 0, kMaxValue, kDefaultBufferingLimit, - G_PARAM_READWRITE)); - } - else - { - GST_ERROR("Unexpected property %s returned from rialto", it->c_str()); - } - } - } - else - { - GST_ERROR("Failed to get supported mime types for AUDIO"); - } - - gst_element_class_set_details_simple(elementClass, "Rialto Audio Sink", "Decoder/Audio/Sink/Audio", - "Communicates with Rialto Server", " "); -} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.h deleted file mode 100644 index 9e7b3e800..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEAudioSink.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "GStreamerMSEMediaPlayerClient.h" -#include "RialtoGStreamerMSEBaseSink.h" -#include -#include - -G_BEGIN_DECLS - -#define RIALTO_TYPE_MSE_AUDIO_SINK (rialto_mse_audio_sink_get_type()) -#define RIALTO_MSE_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_MSE_AUDIO_SINK, RialtoMSEAudioSink)) -#define RIALTO_MSE_AUDIO_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_MSE_AUDIO_SINK, RialtoMSEAudioSinkClass)) -#define RIALTO_IS_MSE_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_MSE_AUDIO_SINK)) -#define RIALTO_IS_MSE_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_MSE_AUDIO_SINK)) - -typedef struct _RialtoMSEAudioSink RialtoMSEAudioSink; -typedef struct _RialtoMSEAudioSinkClass RialtoMSEAudioSinkClass; - -struct _RialtoMSEAudioSink -{ - RialtoMSEBaseSink parent; -}; - -struct _RialtoMSEAudioSinkClass -{ - RialtoMSEBaseSinkClass parent_class; -}; - -GType rialto_mse_audio_sink_get_type(void); - -void rialto_mse_audio_sink_set_client_backend(GstElement *sink, - const std::shared_ptr &mediaPlayerClient); -G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.cpp deleted file mode 100644 index 31f1e2dc8..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.cpp +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#define USE_GLIB 1 - -#include -#include - -#include - -#include "ControlBackend.h" -#include "GStreamerUtils.h" -#include "IClientLogControl.h" -#include "IMediaPipeline.h" -#include "LogToGstHandler.h" -#include "RialtoGStreamerMSEBaseSink.h" -#include "RialtoGStreamerMSEBaseSinkPrivate.h" - -GST_DEBUG_CATEGORY_STATIC(RialtoMSEBaseSinkDebug); -#define GST_CAT_DEFAULT RialtoMSEBaseSinkDebug - -#define rialto_mse_base_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE(RialtoMSEBaseSink, rialto_mse_base_sink, GST_TYPE_ELEMENT, - G_ADD_PRIVATE(RialtoMSEBaseSink) - GST_DEBUG_CATEGORY_INIT(RialtoMSEBaseSinkDebug, "rialtomsebasesink", 0, - "rialto mse base sink")); - -enum -{ - PROP_0, - PROP_IS_SINGLE_PATH_STREAM, - PROP_N_STREAMS, - PROP_HAS_DRM, - PROP_STATS, - PROP_LAST -}; - -enum -{ - SIGNAL_UNDERFLOW, - SIGNAL_LAST -}; - -static guint g_signals[SIGNAL_LAST] = {0}; - -void rialto_mse_base_sink_initialise_delegate(RialtoMSEBaseSink *sink, const std::shared_ptr &delegate) -{ - std::unique_lock lock{sink->priv->m_sinkMutex}; - sink->priv->m_delegate = delegate; - - for (auto &[type, value] : sink->priv->m_queuedProperties) - { - delegate->setProperty(type, &value); - g_value_unset(&value); - } - sink->priv->m_queuedProperties.clear(); -} - -static std::shared_ptr rialto_mse_base_sink_get_delegate(RialtoMSEBaseSink *sink) -{ - std::unique_lock lock{sink->priv->m_sinkMutex}; - if (!sink->priv->m_delegate) - { - GST_ERROR_OBJECT(sink, "Sink delegate not initialized"); - } - return sink->priv->m_delegate; -} - -static gboolean rialto_mse_base_sink_send_event(GstElement *element, GstEvent *event) -{ - if (auto delegate = rialto_mse_base_sink_get_delegate(RIALTO_MSE_BASE_SINK(element))) - { - return delegate->handleSendEvent(event); - } - return FALSE; -} - -gboolean rialto_mse_base_sink_event(GstPad *pad, GstObject *parent, GstEvent *event) -{ - if (auto delegate = rialto_mse_base_sink_get_delegate(RIALTO_MSE_BASE_SINK(parent))) - { - return delegate->handleEvent(pad, parent, event); - } - return FALSE; -} - -GstFlowReturn rialto_mse_base_sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buf) -{ - if (auto delegate = rialto_mse_base_sink_get_delegate(RIALTO_MSE_BASE_SINK(parent))) - { - return delegate->handleBuffer(buf); - } - return GST_FLOW_ERROR; -} - -static gboolean rialto_mse_base_sink_query(GstElement *element, GstQuery *query) -{ - RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(element); - if (auto delegate = rialto_mse_base_sink_get_delegate(sink)) - { - std::optional result{delegate->handleQuery(query)}; - if (result.has_value()) - { - return result.value(); - } - GstElement *parent = GST_ELEMENT(&sink->parent); - return GST_ELEMENT_CLASS(parent_class)->query(parent, query); - } - return FALSE; -} - -static GstStateChangeReturn rialto_mse_base_sink_change_state(GstElement *element, GstStateChange transition) -{ - RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(element); - if (auto delegate = rialto_mse_base_sink_get_delegate(sink)) - { - GstStateChangeReturn status = delegate->changeState(transition); - if (GST_STATE_CHANGE_FAILURE != status) - { - if (GST_STATE_CHANGE_READY_TO_NULL == transition) - { - sink->priv->m_delegate.reset(); - } - GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); - if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) - { - GST_WARNING_OBJECT(sink, "State change failed"); - return result; - } - else if (result == GST_STATE_CHANGE_ASYNC) - { - return GST_STATE_CHANGE_ASYNC; - } - } - return status; - } - return GST_STATE_CHANGE_FAILURE; -} - -void rialto_mse_base_sink_handle_get_property(RialtoMSEBaseSink *sink, const IPlaybackDelegate::Property &property, - GValue *value) -{ - if (auto delegate = rialto_mse_base_sink_get_delegate(sink)) - { - delegate->getProperty(property, value); - } - else // Copy queued value if present - { - std::unique_lock lock{sink->priv->m_sinkMutex}; - if (sink->priv->m_queuedProperties.find(property) != sink->priv->m_queuedProperties.end()) - { - g_value_copy(&sink->priv->m_queuedProperties[property], value); - } - } -} - -void rialto_mse_base_sink_handle_set_property(RialtoMSEBaseSink *sink, const IPlaybackDelegate::Property &property, - const GValue *value) -{ - if (auto delegate = rialto_mse_base_sink_get_delegate(sink)) - { - delegate->setProperty(property, value); - } - else - { - std::unique_lock lock{sink->priv->m_sinkMutex}; - sink->priv->m_queuedProperties[property] = G_VALUE_INIT; - g_value_init(&(sink->priv->m_queuedProperties[property]), G_VALUE_TYPE(value)); - g_value_copy(value, &(sink->priv->m_queuedProperties[property])); - } -} - -static void rialto_mse_base_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) -{ - switch (propId) - { - case PROP_IS_SINGLE_PATH_STREAM: - // Set default value if it can't be acquired - g_value_set_boolean(value, FALSE); - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::IsSinglePathStream, value); - break; - case PROP_N_STREAMS: - // Set default value if it can't be acquired - g_value_set_int(value, 1); - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::NumberOfStreams, value); - break; - case PROP_HAS_DRM: - // Set default value if it can't be acquired - g_value_set_boolean(value, TRUE); - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::HasDrm, - value); - break; - case PROP_STATS: - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Stats, value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } -} - -static void rialto_mse_base_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) -{ - switch (propId) - { - case PROP_IS_SINGLE_PATH_STREAM: - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::IsSinglePathStream, value); - break; - case PROP_N_STREAMS: - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::NumberOfStreams, value); - break; - case PROP_HAS_DRM: - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::HasDrm, - value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } -} - -void rialto_mse_base_handle_rialto_server_sent_buffer_underflow(RialtoMSEBaseSink *sink) -{ - GST_WARNING_OBJECT(sink, "Sending underflow signal"); - // send 2 last parameters just to be compatible with RDK's buffer-underflow-callback signal signature - g_signal_emit(G_OBJECT(sink), g_signals[SIGNAL_UNDERFLOW], 0, 0, nullptr); -} - -bool rialto_mse_base_sink_initialise_sinkpad(RialtoMSEBaseSink *sink) -{ - GstPadTemplate *pad_template = - gst_element_class_get_pad_template(GST_ELEMENT_CLASS(G_OBJECT_GET_CLASS(sink)), "sink"); - if (!pad_template) - { - GST_ERROR_OBJECT(sink, "Could not find sink pad template"); - return false; - } - - GstPad *sinkPad = gst_pad_new_from_template(pad_template, "sink"); - if (!sinkPad) - { - GST_ERROR_OBJECT(sink, "Could not create sinkpad"); - return false; - } - - gst_element_add_pad(GST_ELEMENT_CAST(sink), sinkPad); - sink->priv->m_sinkPad = sinkPad; - - return true; -} - -static void rialto_mse_base_sink_init(RialtoMSEBaseSink *sink) -{ - GST_INFO_OBJECT(sink, "Init: %" GST_PTR_FORMAT, sink); - sink->priv = static_cast(rialto_mse_base_sink_get_instance_private(sink)); - new (sink->priv) RialtoMSEBaseSinkPrivate(); - - GST_OBJECT_FLAG_SET(sink, GST_ELEMENT_FLAG_SINK); -} - -static void rialto_mse_base_sink_finalize(GObject *object) -{ - RialtoMSEBaseSink *sink = RIALTO_MSE_BASE_SINK(object); - RialtoMSEBaseSinkPrivate *priv = sink->priv; - GST_INFO_OBJECT(sink, "Finalize: %" GST_PTR_FORMAT " %" GST_PTR_FORMAT, sink, priv); - - priv->~RialtoMSEBaseSinkPrivate(); - GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); -} - -static void rialto_mse_base_sink_class_init(RialtoMSEBaseSinkClass *klass) -{ - std::shared_ptr logToGstHandler = - std::make_shared(); - if (!firebolt::rialto::IClientLogControlFactory::createFactory()->createClientLogControl().registerLogHandler(logToGstHandler, - true)) - { - GST_ERROR("Unable to preRegister log handler"); - } - - GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); - GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); - - gst_element_class_set_metadata(elementClass, "Rialto MSE base sink", "Generic", "A sink for Rialto", " "); - - gobjectClass->finalize = rialto_mse_base_sink_finalize; - gobjectClass->get_property = rialto_mse_base_sink_get_property; - gobjectClass->set_property = rialto_mse_base_sink_set_property; - elementClass->query = rialto_mse_base_sink_query; - elementClass->send_event = rialto_mse_base_sink_send_event; - elementClass->change_state = rialto_mse_base_sink_change_state; - - g_signals[SIGNAL_UNDERFLOW] = g_signal_new("buffer-underflow-callback", G_TYPE_FROM_CLASS(klass), - (GSignalFlags)(G_SIGNAL_RUN_LAST), 0, nullptr, nullptr, - g_cclosure_marshal_VOID__UINT_POINTER, G_TYPE_NONE, 2, G_TYPE_UINT, - G_TYPE_POINTER); - - g_object_class_install_property(gobjectClass, PROP_IS_SINGLE_PATH_STREAM, - g_param_spec_boolean("single-path-stream", "single path stream", - "is single path stream", FALSE, GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_N_STREAMS, - g_param_spec_int("streams-number", "streams number", "streams number", 1, G_MAXINT, - 1, GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_HAS_DRM, - g_param_spec_boolean("has-drm", "has drm", "has drm", TRUE, - GParamFlags(G_PARAM_READWRITE))); - g_object_class_install_property(gobjectClass, PROP_STATS, - g_param_spec_pointer("stats", NULL, "pointer to a gst_structure", - GParamFlags(G_PARAM_READABLE))); -} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.h deleted file mode 100644 index 714fb57c2..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSink.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "GStreamerUtils.h" -#include "IPlaybackDelegate.h" -#include -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define RIALTO_TYPE_MSE_BASE_SINK (rialto_mse_base_sink_get_type()) -#define RIALTO_MSE_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_MSE_BASE_SINK, RialtoMSEBaseSink)) -#define RIALTO_MSE_BASE_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_MSE_BASE_SINK, RialtoMSEBaseSinkClass)) -#define RIALTO_IS_MSE_BASE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_MSE_BASE_SINK)) -#define RIALTO_IS_MSE_BASE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_MSE_BASE_SINK)) - -typedef struct _RialtoMSEBaseSink RialtoMSEBaseSink; -typedef struct _RialtoMSEBaseSinkClass RialtoMSEBaseSinkClass; -typedef struct _RialtoMSEBaseSinkPrivate RialtoMSEBaseSinkPrivate; - -struct _RialtoMSEBaseSink -{ - GstElement parent; - RialtoMSEBaseSinkPrivate *priv; -}; - -struct _RialtoMSEBaseSinkClass -{ - GstElementClass parent_class; -}; - -namespace firebolt::rialto::client -{ -class MediaPlayerBackend; -} - -GType rialto_mse_base_sink_get_type(void); - -void rialto_mse_base_sink_initialise_delegate(RialtoMSEBaseSink *sink, - const std::shared_ptr &delegate); -void rialto_mse_base_sink_handle_get_property(RialtoMSEBaseSink *sink, const IPlaybackDelegate::Property &property, - GValue *value); -void rialto_mse_base_sink_handle_set_property(RialtoMSEBaseSink *sink, const IPlaybackDelegate::Property &property, - const GValue *value); - -GstFlowReturn rialto_mse_base_sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buf); -gboolean rialto_mse_base_sink_event(GstPad *pad, GstObject *parent, GstEvent *event); -bool rialto_mse_base_sink_initialise_sinkpad(RialtoMSEBaseSink *sink); - -void rialto_mse_base_handle_rialto_server_sent_buffer_underflow(RialtoMSEBaseSink *sink); - -G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSinkPrivate.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSinkPrivate.h deleted file mode 100644 index 2b0d6eb26..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEBaseSinkPrivate.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include - -#include - -#include "ControlBackendInterface.h" -#include "IPlaybackDelegate.h" -#include "MediaPlayerManager.h" -#include -#include -#include -#include -#include -#include - -enum class PlaybackMode -{ - Pull, - Push -}; - -G_BEGIN_DECLS - -struct _RialtoMSEBaseSinkPrivate -{ - _RialtoMSEBaseSinkPrivate() = default; - ~_RialtoMSEBaseSinkPrivate() = default; - - GstPad *m_sinkPad{nullptr}; - std::mutex m_sinkMutex; - std::shared_ptr m_delegate{nullptr}; - std::map m_queuedProperties{}; - std::atomic m_playbackMode{PlaybackMode::Pull}; -}; -G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.cpp deleted file mode 100644 index 646258e06..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2024 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -#include "GStreamerEMEUtils.h" -#include "GStreamerMSEUtils.h" -#include "IMediaPipelineCapabilities.h" -#include "PullModeSubtitlePlaybackDelegate.h" -#include "RialtoGStreamerMSEBaseSinkPrivate.h" -#include "RialtoGStreamerMSESubtitleSink.h" - -using namespace firebolt::rialto::client; - -GST_DEBUG_CATEGORY_STATIC(RialtoMSESubtitleSinkDebug); -#define GST_CAT_DEFAULT RialtoMSESubtitleSinkDebug - -#define rialto_mse_subtitle_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE(RialtoMSESubtitleSink, rialto_mse_subtitle_sink, RIALTO_TYPE_MSE_BASE_SINK, - GST_DEBUG_CATEGORY_INIT(RialtoMSESubtitleSinkDebug, "rialtomsesubtitlesink", 0, - "rialto mse subtitle sink")); - -enum -{ - PROP_0, - PROP_MUTE, - PROP_TEXT_TRACK_IDENTIFIER, - PROP_WINDOW_ID, - PROP_ASYNC, - PROP_LAST -}; - -static GstStateChangeReturn rialto_mse_subtitle_sink_change_state(GstElement *element, GstStateChange transition) -{ - RialtoMSESubtitleSink *sink = RIALTO_MSE_SUBTITLE_SINK(element); - - if (GST_STATE_CHANGE_NULL_TO_READY == transition) - { - GST_INFO_OBJECT(sink, "RialtoMSESubtitleSink state change to READY. Initializing delegate"); - rialto_mse_base_sink_initialise_delegate(RIALTO_MSE_BASE_SINK(sink), - std::make_shared(element)); - } - - GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); - if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) - { - GST_WARNING_OBJECT(sink, "State change failed"); - return result; - } - - return result; -} - -static void rialto_mse_subtitle_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) -{ - switch (propId) - { - case PROP_MUTE: - { - g_value_set_boolean(value, FALSE); // Set default value first - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Mute, value); - break; - } - case PROP_TEXT_TRACK_IDENTIFIER: - { - g_value_set_string(value, ""); // Set default value first - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::TextTrackIdentifier, value); - break; - } - case PROP_WINDOW_ID: - { - g_value_set_uint(value, 0); // Set default value first - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowId, - value); - break; - } - case PROP_ASYNC: - { - g_value_set_boolean(value, FALSE); // Set default value first - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Async, value); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } -} - -static void rialto_mse_subtitle_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) -{ - switch (propId) - { - case PROP_MUTE: - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Mute, value); - break; - case PROP_TEXT_TRACK_IDENTIFIER: - { - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::TextTrackIdentifier, value); - break; - } - case PROP_WINDOW_ID: - { - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowId, - value); - break; - } - case PROP_ASYNC: - { - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::Async, value); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } -} - -static void rialto_mse_subtitle_sink_init(RialtoMSESubtitleSink *sink) -{ - RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv; - - if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink))) - { - GST_ERROR_OBJECT(sink, "Failed to initialise SUBTITLE sink. Sink pad initialisation failed."); - return; - } - - gst_pad_set_chain_function(basePriv->m_sinkPad, rialto_mse_base_sink_chain); - gst_pad_set_event_function(basePriv->m_sinkPad, rialto_mse_base_sink_event); -} - -static void rialto_mse_subtitle_sink_class_init(RialtoMSESubtitleSinkClass *klass) -{ - GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); - GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); - gobjectClass->get_property = rialto_mse_subtitle_sink_get_property; - gobjectClass->set_property = rialto_mse_subtitle_sink_set_property; - elementClass->change_state = rialto_mse_subtitle_sink_change_state; - - g_object_class_install_property(gobjectClass, PROP_MUTE, - g_param_spec_boolean("mute", "Mute", "Mute subtitles", FALSE, G_PARAM_READWRITE)); - - g_object_class_install_property(gobjectClass, PROP_TEXT_TRACK_IDENTIFIER, - g_param_spec_string("text-track-identifier", "Text Track Identifier", - "Identifier of text track. Valid input for service is " - "\"CC[1-4]\", \"TEXT[1-4]\", \"SERVICE[1-64]\"", - nullptr, GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_WINDOW_ID, - g_param_spec_uint("window-id", "Window ID", "Id of window (placeholder)", 0, 256, 0, - GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_ASYNC, - g_param_spec_boolean("async", "Async", "Asynchronous mode", FALSE, G_PARAM_READWRITE)); - - std::unique_ptr mediaPlayerCapabilities = - firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities(); - if (mediaPlayerCapabilities) - { - std::vector supportedMimeTypes = - mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::SUBTITLE); - - rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes); - } - else - { - GST_ERROR("Failed to get supported mime types for Subtitle"); - } - - gst_element_class_set_details_simple(elementClass, "Rialto Subtitle Sink", "Parser/Subtitle/Sink/Subtitle", - "Communicates with Rialto Server", " "); -} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.h deleted file mode 100644 index 3e6e5813d..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSESubtitleSink.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2024 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "GStreamerMSEMediaPlayerClient.h" -#include "RialtoGStreamerMSEBaseSink.h" -#include -#include - -G_BEGIN_DECLS - -#define RIALTO_TYPE_MSE_SUBTITLE_SINK (rialto_mse_subtitle_sink_get_type()) -#define RIALTO_MSE_SUBTITLE_SINK(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_MSE_SUBTITLE_SINK, RialtoMSESubtitleSink)) -#define RIALTO_MSE_SUBTITLE_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_MSE_SUBTITLE_SINK, RialtoMSESubtitleSinkClass)) -#define RIALTO_IS_MSE_SUBTITLE_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_MSE_SUBTITLE_SINK)) -#define RIALTO_IS_MSE_SUBTITLE_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_MSE_SUBTITLE_SINK)) - -typedef struct _RialtoMSESubtitleSink RialtoMSESubtitleSink; -typedef struct _RialtoMSESubtitleSinkClass RialtoMSESubtitleSinkClass; - -struct _RialtoMSESubtitleSink -{ - RialtoMSEBaseSink parent; -}; - -struct _RialtoMSESubtitleSinkClass -{ - RialtoMSEBaseSinkClass parent_class; -}; - -GType rialto_mse_subtitle_sink_get_type(void); - -void rialto_mse_subtitle_sink_set_client_backend(GstElement *sink, - const std::shared_ptr &mediaPlayerClient); -G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.cpp deleted file mode 100644 index 2bf231d6d..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.cpp +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include - -#include "GStreamerEMEUtils.h" -#include "GStreamerMSEUtils.h" -#include "IMediaPipelineCapabilities.h" -#include "PullModeVideoPlaybackDelegate.h" -#include "RialtoGStreamerMSEBaseSinkPrivate.h" -#include "RialtoGStreamerMSEVideoSink.h" - -using namespace firebolt::rialto::client; - -GST_DEBUG_CATEGORY_STATIC(RialtoMSEVideoSinkDebug); -#define GST_CAT_DEFAULT RialtoMSEVideoSinkDebug - -#define rialto_mse_video_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE(RialtoMSEVideoSink, rialto_mse_video_sink, RIALTO_TYPE_MSE_BASE_SINK, - GST_DEBUG_CATEGORY_INIT(RialtoMSEVideoSinkDebug, "rialtomsevideosink", 0, - "rialto mse video sink")); - -enum -{ - PROP_0, - PROP_WINDOW_SET, - PROP_MAX_VIDEO_WIDTH, - PROP_MAX_VIDEO_HEIGHT, - PROP_MAX_VIDEO_WIDTH_DEPRECATED, - PROP_MAX_VIDEO_HEIGHT_DEPRECATED, - PROP_FRAME_STEP_ON_PREROLL, - PROP_IMMEDIATE_OUTPUT, - PROP_SYNCMODE_STREAMING, - PROP_SHOW_VIDEO_WINDOW, - PROP_IS_MASTER, - PROP_LAST -}; - -static GstStateChangeReturn rialto_mse_video_sink_change_state(GstElement *element, GstStateChange transition) -{ - RialtoMSEVideoSink *sink = RIALTO_MSE_VIDEO_SINK(element); - if (GST_STATE_CHANGE_NULL_TO_READY == transition) - { - GST_INFO_OBJECT(sink, "RialtoMSEVideoSink state change to READY. Initializing delegate"); - rialto_mse_base_sink_initialise_delegate(RIALTO_MSE_BASE_SINK(sink), - std::make_shared(element)); - } - GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); - if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) - { - GST_WARNING_OBJECT(sink, "State change failed"); - return result; - } - - return result; -} - -static void rialto_mse_video_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) -{ - switch (propId) - { - case PROP_WINDOW_SET: - { - g_value_set_string(value, "0,0,1920,1080"); // Set default value - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowSet, - value); - break; - } - case PROP_MAX_VIDEO_WIDTH_DEPRECATED: - GST_WARNING_OBJECT(object, "MaxVideoWidth property is deprecated. Use 'max-video-width' instead"); - case PROP_MAX_VIDEO_WIDTH: - { - g_value_set_uint(value, 0); // Set default value - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::MaxVideoWidth, value); - break; - } - case PROP_MAX_VIDEO_HEIGHT_DEPRECATED: - GST_WARNING_OBJECT(object, "MaxVideoHeight property is deprecated. Use 'max-video-height' instead"); - case PROP_MAX_VIDEO_HEIGHT: - { - g_value_set_uint(value, 0); // Set default value - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::MaxVideoHeight, value); - break; - } - case PROP_FRAME_STEP_ON_PREROLL: - { - g_value_set_boolean(value, FALSE); // Set default value - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::FrameStepOnPreroll, value); - break; - } - case PROP_IMMEDIATE_OUTPUT: - { - g_value_set_boolean(value, FALSE); // Set default value - rialto_mse_base_sink_handle_get_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::ImmediateOutput, value); - break; - } - case PROP_IS_MASTER: - { - g_value_set_boolean(value, TRUE); // Set default value - std::unique_ptr mediaPlayerCapabilities = - firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities(); - bool isMaster{false}; - if (mediaPlayerCapabilities && mediaPlayerCapabilities->isVideoMaster(isMaster)) - { - g_value_set_boolean(value, isMaster); - } - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } -} - -static void rialto_mse_video_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) -{ - switch (propId) - { - case PROP_WINDOW_SET: - { - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), IPlaybackDelegate::Property::WindowSet, - value); - break; - } - case PROP_MAX_VIDEO_WIDTH: - case PROP_MAX_VIDEO_WIDTH_DEPRECATED: - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::MaxVideoWidth, value); - break; - case PROP_MAX_VIDEO_HEIGHT: - case PROP_MAX_VIDEO_HEIGHT_DEPRECATED: - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::MaxVideoHeight, value); - break; - case PROP_FRAME_STEP_ON_PREROLL: - { - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::FrameStepOnPreroll, value); - break; - } - case PROP_IMMEDIATE_OUTPUT: - { - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::ImmediateOutput, value); - break; - } - case PROP_SYNCMODE_STREAMING: - { - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::SyncmodeStreaming, value); - break; - } - case PROP_SHOW_VIDEO_WINDOW: - { - rialto_mse_base_sink_handle_set_property(RIALTO_MSE_BASE_SINK(object), - IPlaybackDelegate::Property::ShowVideoWindow, value); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } -} - -static void rialto_mse_video_sink_init(RialtoMSEVideoSink *sink) -{ - RialtoMSEBaseSinkPrivate *basePriv = sink->parent.priv; - - if (!rialto_mse_base_sink_initialise_sinkpad(RIALTO_MSE_BASE_SINK(sink))) - { - GST_ERROR_OBJECT(sink, "Failed to initialise VIDEO sink. Sink pad initialisation failed."); - return; - } - - gst_pad_set_chain_function(basePriv->m_sinkPad, rialto_mse_base_sink_chain); - gst_pad_set_event_function(basePriv->m_sinkPad, rialto_mse_base_sink_event); -} - -static void rialto_mse_video_sink_class_init(RialtoMSEVideoSinkClass *klass) -{ - GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); - GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); - gobjectClass->get_property = rialto_mse_video_sink_get_property; - gobjectClass->set_property = rialto_mse_video_sink_set_property; - elementClass->change_state = rialto_mse_video_sink_change_state; - - g_object_class_install_property(gobjectClass, PROP_WINDOW_SET, - g_param_spec_string("rectangle", "rectangle", "Window Set Format: x,y,width,height", - nullptr, GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_WIDTH, - g_param_spec_uint("max-video-width", - "max video width", "Maximum width of video frames to be decoded. Should only be set for video only streams.", - 0, 3840, DEFAULT_MAX_VIDEO_WIDTH, GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_HEIGHT, - g_param_spec_uint("max-video-height", - "max video height", "Maximum height of video frames to be decoded. should only be set for video only streams.", - 0, 2160, DEFAULT_MAX_VIDEO_HEIGHT, GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_WIDTH_DEPRECATED, - g_param_spec_uint("maxVideoWidth", "maxVideoWidth", "[DEPRECATED] Use max-video-width", - 0, 3840, DEFAULT_MAX_VIDEO_WIDTH, GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_MAX_VIDEO_HEIGHT_DEPRECATED, - g_param_spec_uint("maxVideoHeight", "maxVideoHeight", "[DEPRECATED] max-video-height", - 0, 2160, DEFAULT_MAX_VIDEO_HEIGHT, GParamFlags(G_PARAM_READWRITE))); - - g_object_class_install_property(gobjectClass, PROP_FRAME_STEP_ON_PREROLL, - g_param_spec_boolean("frame-step-on-preroll", "frame step on preroll", - "allow frame stepping on preroll into pause", FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property(gobjectClass, PROP_IS_MASTER, - g_param_spec_boolean("is-master", "is master", - "Checks if the platform is video master", TRUE, - G_PARAM_READABLE)); - - std::unique_ptr mediaPlayerCapabilities = - firebolt::rialto::IMediaPipelineCapabilitiesFactory::createFactory()->createMediaPipelineCapabilities(); - if (mediaPlayerCapabilities) - { - std::vector supportedMimeTypes = - mediaPlayerCapabilities->getSupportedMimeTypes(firebolt::rialto::MediaSourceType::VIDEO); - - rialto_mse_sink_setup_supported_caps(elementClass, supportedMimeTypes); - - const std::string kImmediateOutputPropertyName{"immediate-output"}; - const std::string kSyncmodeStreamingPropertyName{"syncmode-streaming"}; - const std::string kShowVideoWindowPropertyName{"show-video-window"}; - const std::vector kPropertyNamesToSearch{kImmediateOutputPropertyName, - kSyncmodeStreamingPropertyName, - kShowVideoWindowPropertyName}; - std::vector supportedProperties{ - mediaPlayerCapabilities->getSupportedProperties(firebolt::rialto::MediaSourceType::VIDEO, - kPropertyNamesToSearch)}; - - for (const auto &propertyName : supportedProperties) - { - if (kImmediateOutputPropertyName == propertyName) - { - g_object_class_install_property(gobjectClass, PROP_IMMEDIATE_OUTPUT, - g_param_spec_boolean(kImmediateOutputPropertyName.c_str(), - "immediate output", "immediate output", TRUE, - GParamFlags(G_PARAM_READWRITE))); - } - else if (kSyncmodeStreamingPropertyName == propertyName) - { - g_object_class_install_property(gobjectClass, PROP_SYNCMODE_STREAMING, - g_param_spec_boolean("syncmode-streaming", "Streaming Sync Mode", - "Enable/disable OTT streaming sync mode", FALSE, - G_PARAM_WRITABLE)); - } - else if (kShowVideoWindowPropertyName == propertyName) - { - g_object_class_install_property(gobjectClass, PROP_SHOW_VIDEO_WINDOW, - g_param_spec_boolean(kShowVideoWindowPropertyName.c_str(), - "make video window visible", - "true: visible, false: hidden", TRUE, - G_PARAM_WRITABLE)); - } - } - } - else - { - GST_ERROR("Failed to get supported mime types for VIDEO"); - } - - gst_element_class_set_details_simple(elementClass, "Rialto Video Sink", "Decoder/Video/Sink/Video", - "Communicates with Rialto Server", " "); -} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.h deleted file mode 100644 index 989981ffc..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerMSEVideoSink.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2022 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "GStreamerMSEMediaPlayerClient.h" -#include "RialtoGStreamerMSEBaseSink.h" -#include -#include - -G_BEGIN_DECLS - -#define RIALTO_TYPE_MSE_VIDEO_SINK (rialto_mse_video_sink_get_type()) -#define RIALTO_MSE_VIDEO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_MSE_VIDEO_SINK, RialtoMSEVideoSink)) -#define RIALTO_MSE_VIDEO_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_MSE_VIDEO_SINK, RialtoMSEVideoSinkClass)) -#define RIALTO_IS_MSE_VIDEO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_MSE_VIDEO_SINK)) -#define RIALTO_IS_MSE_VIDEO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_MSE_VIDEO_SINK)) - -typedef struct _RialtoMSEVideoSink RialtoMSEVideoSink; -typedef struct _RialtoMSEVideoSinkClass RialtoMSEVideoSinkClass; - -struct _RialtoMSEVideoSink -{ - RialtoMSEBaseSink parent; -}; - -struct _RialtoMSEVideoSinkClass -{ - RialtoMSEBaseSinkClass parent_class; -}; - -GType rialto_mse_video_sink_get_type(void); - -void rialto_mse_video_sink_set_client_backend(GstElement *sink, - const std::shared_ptr &mediaPlayerClient); -G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.cpp b/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.cpp deleted file mode 100644 index 98dbad2fe..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -#include "Constants.h" -#include "PushModeAudioPlaybackDelegate.h" -#include "RialtoGStreamerWebAudioSink.h" - -using namespace firebolt::rialto::client; - -GST_DEBUG_CATEGORY_STATIC(RialtoWebAudioSinkDebug); -#define GST_CAT_DEFAULT RialtoWebAudioSinkDebug - -#define rialto_web_audio_sink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE(RialtoWebAudioSink, rialto_web_audio_sink, GST_TYPE_ELEMENT, - G_ADD_PRIVATE(RialtoWebAudioSink) - GST_DEBUG_CATEGORY_INIT(RialtoWebAudioSinkDebug, "rialtowebaudiosink", 0, - "rialto web audio sink")); -enum -{ - PROP_0, - PROP_TS_OFFSET, - PROP_VOLUME, - PROP_LAST -}; - -void rialto_web_audio_sink_initialise_delegate(RialtoWebAudioSink *sink, - const std::shared_ptr &delegate) -{ - std::unique_lock lock{sink->priv->m_sinkMutex}; - sink->priv->m_delegate = delegate; - - for (auto &[type, value] : sink->priv->m_queuedProperties) - { - delegate->setProperty(type, &value); - g_value_unset(&value); - } - sink->priv->m_queuedProperties.clear(); -} - -static std::shared_ptr rialto_web_audio_sink_get_delegate(RialtoWebAudioSink *sink) -{ - std::unique_lock lock{sink->priv->m_sinkMutex}; - if (!sink->priv->m_delegate) - { - GST_ERROR_OBJECT(sink, "Sink delegate not initialized"); - } - return sink->priv->m_delegate; -} - -static void rialto_web_audio_sink_handle_get_property(RialtoWebAudioSink *sink, - const IPlaybackDelegate::Property &property, GValue *value) -{ - if (auto delegate = rialto_web_audio_sink_get_delegate(sink)) - { - delegate->getProperty(property, value); - } - else // Copy queued value if present - { - std::unique_lock lock{sink->priv->m_sinkMutex}; - if (sink->priv->m_queuedProperties.find(property) != sink->priv->m_queuedProperties.end()) - { - g_value_copy(&sink->priv->m_queuedProperties[property], value); - } - } -} - -static void rialto_web_audio_sink_handle_set_property(RialtoWebAudioSink *sink, - const IPlaybackDelegate::Property &property, const GValue *value) -{ - if (auto delegate = rialto_web_audio_sink_get_delegate(sink)) - { - delegate->setProperty(property, value); - } - else - { - std::unique_lock lock{sink->priv->m_sinkMutex}; - sink->priv->m_queuedProperties[property] = G_VALUE_INIT; - g_value_init(&(sink->priv->m_queuedProperties[property]), G_VALUE_TYPE(value)); - g_value_copy(value, &(sink->priv->m_queuedProperties[property])); - } -} - -static gboolean rialto_web_audio_sink_send_event(GstElement *element, GstEvent *event) -{ - RialtoWebAudioSink *sink = RIALTO_WEB_AUDIO_SINK(element); - if (auto delegate = rialto_web_audio_sink_get_delegate(sink)) - { - return delegate->handleSendEvent(event); - } - return FALSE; -} - -static GstStateChangeReturn rialto_web_audio_sink_change_state(GstElement *element, GstStateChange transition) -{ - RialtoWebAudioSink *sink = RIALTO_WEB_AUDIO_SINK(element); - if (GST_STATE_CHANGE_NULL_TO_READY == transition) - { - GST_INFO_OBJECT(sink, "RialtoWebAudioSink state change to READY. Initializing delegate"); - rialto_web_audio_sink_initialise_delegate(sink, std::make_shared(element)); - } - if (auto delegate = rialto_web_audio_sink_get_delegate(sink)) - { - GstStateChangeReturn status = delegate->changeState(transition); - if (GST_STATE_CHANGE_FAILURE != status) - { - GstStateChangeReturn result = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); - if (G_UNLIKELY(result == GST_STATE_CHANGE_FAILURE)) - { - GST_WARNING_OBJECT(sink, "State change failed"); - return result; - } - else if (result == GST_STATE_CHANGE_ASYNC) - { - return GST_STATE_CHANGE_ASYNC; - } - } - return status; - } - return GST_STATE_CHANGE_FAILURE; -} - -static gboolean rialto_web_audio_sink_event(GstPad *pad, GstObject *parent, GstEvent *event) -{ - if (auto delegate = rialto_web_audio_sink_get_delegate(RIALTO_WEB_AUDIO_SINK(parent))) - { - return delegate->handleEvent(pad, parent, event); - } - return FALSE; -} - -static void rialto_web_audio_sink_get_property(GObject *object, guint propId, GValue *value, GParamSpec *pspec) -{ - switch (propId) - { - case PROP_TS_OFFSET: - { - rialto_web_audio_sink_handle_get_property(RIALTO_WEB_AUDIO_SINK(object), IPlaybackDelegate::Property::TsOffset, - value); - } - - case PROP_VOLUME: - { - g_value_set_double(value, kDefaultVolume); - rialto_web_audio_sink_handle_get_property(RIALTO_WEB_AUDIO_SINK(object), IPlaybackDelegate::Property::Volume, - value); - break; - } - - default: - { - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } - } -} - -static void rialto_web_audio_sink_set_property(GObject *object, guint propId, const GValue *value, GParamSpec *pspec) -{ - switch (propId) - { - case PROP_TS_OFFSET: - { - rialto_web_audio_sink_handle_set_property(RIALTO_WEB_AUDIO_SINK(object), IPlaybackDelegate::Property::TsOffset, - value); - break; - } - - case PROP_VOLUME: - { - rialto_web_audio_sink_handle_set_property(RIALTO_WEB_AUDIO_SINK(object), IPlaybackDelegate::Property::Volume, - value); - break; - } - - default: - { - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, pspec); - break; - } - } -} - -static GstFlowReturn rialto_web_audio_sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buf) -{ - if (auto delegate = rialto_web_audio_sink_get_delegate(RIALTO_WEB_AUDIO_SINK(parent))) - { - return delegate->handleBuffer(buf); - } - return GST_FLOW_ERROR; -} - -static void rialto_web_audio_sink_setup_supported_caps(GstElementClass *elementClass) -{ - GstCaps *caps = gst_caps_from_string("audio/x-raw"); - GstPadTemplate *sinktempl = gst_pad_template_new("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps); - gst_element_class_add_pad_template(elementClass, sinktempl); - gst_caps_unref(caps); -} - -static bool rialto_web_audio_sink_initialise_sinkpad(RialtoWebAudioSink *sink) -{ - GstPadTemplate *pad_template = - gst_element_class_get_pad_template(GST_ELEMENT_CLASS(G_OBJECT_GET_CLASS(sink)), "sink"); - if (!pad_template) - { - GST_ERROR_OBJECT(sink, "Could not find sink pad template"); - return false; - } - - GstPad *sinkPad = gst_pad_new_from_template(pad_template, "sink"); - if (!sinkPad) - { - GST_ERROR_OBJECT(sink, "Could not create sinkpad"); - return false; - } - - gst_element_add_pad(GST_ELEMENT_CAST(sink), sinkPad); - - gst_pad_set_event_function(sinkPad, rialto_web_audio_sink_event); - gst_pad_set_chain_function(sinkPad, rialto_web_audio_sink_chain); - - return true; -} - -static void rialto_web_audio_sink_init(RialtoWebAudioSink *sink) -{ - GST_INFO_OBJECT(sink, "Init: %" GST_PTR_FORMAT, sink); - sink->priv = static_cast(rialto_web_audio_sink_get_instance_private(sink)); - new (sink->priv) RialtoWebAudioSinkPrivate(); - - GST_OBJECT_FLAG_SET(sink, GST_ELEMENT_FLAG_SINK); - if (!rialto_web_audio_sink_initialise_sinkpad(sink)) - { - GST_ERROR_OBJECT(sink, "Failed to initialise AUDIO sink. Sink pad initialisation failed."); - return; - } -} - -static void rialto_web_audio_sink_finalize(GObject *object) -{ - RialtoWebAudioSink *sink = RIALTO_WEB_AUDIO_SINK(object); - RialtoWebAudioSinkPrivate *priv = sink->priv; - GST_INFO_OBJECT(sink, "Finalize: %" GST_PTR_FORMAT " %" GST_PTR_FORMAT, sink, priv); - - priv->~RialtoWebAudioSinkPrivate(); - - GST_CALL_PARENT(G_OBJECT_CLASS, finalize, (object)); -} - -static void rialto_web_audio_sink_class_init(RialtoWebAudioSinkClass *klass) -{ - GObjectClass *gobjectClass = G_OBJECT_CLASS(klass); - GstElementClass *elementClass = GST_ELEMENT_CLASS(klass); - - gst_element_class_set_metadata(elementClass, "Rialto Web Audio sink", "Generic", "A sink for Rialto Web Audio", - " "); - - gobjectClass->finalize = rialto_web_audio_sink_finalize; - gobjectClass->get_property = rialto_web_audio_sink_get_property; - gobjectClass->set_property = rialto_web_audio_sink_set_property; - - elementClass->change_state = rialto_web_audio_sink_change_state; - elementClass->send_event = rialto_web_audio_sink_send_event; - - g_object_class_install_property(gobjectClass, PROP_TS_OFFSET, - g_param_spec_int64("ts-offset", - "ts-offset", "Not supported, RialtoWebAudioSink does not require the synchronisation of sources", - G_MININT64, G_MAXINT64, 0, - GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - g_object_class_install_property(gobjectClass, PROP_VOLUME, - g_param_spec_double("volume", "Volume", "Volume of this stream", 0, 1.0, - kDefaultVolume, - GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - - rialto_web_audio_sink_setup_supported_caps(elementClass); - - gst_element_class_set_details_simple(elementClass, "Rialto Web Audio Sink", "Decoder/Audio/Sink/Audio", - "Communicates with Rialto Server", " "); -} diff --git a/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.h b/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.h deleted file mode 100644 index 8a7bc12a3..000000000 --- a/middleware/rialto-gstreamer/source/RialtoGStreamerWebAudioSink.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once - -#include "IPlaybackDelegate.h" -#include -#include -#include - -G_BEGIN_DECLS - -#define RIALTO_TYPE_WEB_AUDIO_SINK (rialto_web_audio_sink_get_type()) -#define RIALTO_WEB_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), RIALTO_TYPE_WEB_AUDIO_SINK, RialtoWebAudioSink)) -#define RIALTO_WEB_AUDIO_SINK_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), RIALTO_TYPE_WEB_AUDIO_SINK, RialtoWebAudioSinkClass)) -#define RIALTO_IS_WEB_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), RIALTO_TYPE_WEB_AUDIO_SINK)) -#define RIALTO_IS_WEB_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), RIALTO_TYPE_WEB_AUDIO_SINK)) - -typedef struct _RialtoWebAudioSink RialtoWebAudioSink; -typedef struct _RialtoWebAudioSinkClass RialtoWebAudioSinkClass; -typedef struct _RialtoWebAudioSinkPrivate RialtoWebAudioSinkPrivate; - -struct _RialtoWebAudioSinkPrivate -{ - std::mutex m_sinkMutex; - std::shared_ptr m_delegate{nullptr}; - std::map m_queuedProperties{}; -}; - -struct _RialtoWebAudioSink -{ - GstElement parent; - RialtoWebAudioSinkPrivate *priv; -}; - -struct _RialtoWebAudioSinkClass -{ - GstElementClass parent_class; -}; - -GType rialto_web_audio_sink_get_type(void); - -G_END_DECLS diff --git a/middleware/rialto-gstreamer/source/Timer.cpp b/middleware/rialto-gstreamer/source/Timer.cpp deleted file mode 100644 index 7ec54d7ee..000000000 --- a/middleware/rialto-gstreamer/source/Timer.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "Timer.h" -#include - -std::weak_ptr TimerFactory::m_factory; - -std::shared_ptr ITimerFactory::getFactory() -{ - std::shared_ptr factory = TimerFactory::m_factory.lock(); - - if (!factory) - { - try - { - factory = std::make_shared(); - } - catch (const std::exception &e) - { - GST_ERROR("Failed to create the timer factory, reason: %s", e.what()); - } - - TimerFactory::m_factory = factory; - } - - return factory; -} - -std::unique_ptr TimerFactory::createTimer(const std::chrono::milliseconds &timeout, - const std::function &callback, TimerType timerType) const -{ - return std::make_unique(timeout, callback, timerType); -} - -Timer::Timer(const std::chrono::milliseconds &timeout, const std::function &callback, TimerType timerType) - : m_active{true}, m_timeout{timeout}, m_callback{callback} -{ - m_thread = std::thread( - [this, timerType]() - { - do - { - std::unique_lock lock{m_mutex}; - if (!m_cv.wait_for(lock, m_timeout, [this]() { return !m_active; })) - { - if (m_active && m_callback) - { - lock.unlock(); - m_callback(); - } - } - } while (timerType == TimerType::PERIODIC && m_active); - m_active = false; - }); -} - -Timer::~Timer() -{ - doCancel(); -} - -void Timer::cancel() -{ - doCancel(); -} - -bool Timer::isActive() const -{ - return m_active; -} - -void Timer::doCancel() -{ - m_active = false; - - if (std::this_thread::get_id() != m_thread.get_id() && m_thread.joinable()) - { - m_cv.notify_one(); - m_thread.join(); - } -} diff --git a/middleware/rialto-gstreamer/source/Timer.h b/middleware/rialto-gstreamer/source/Timer.h deleted file mode 100644 index 3f6d767d4..000000000 --- a/middleware/rialto-gstreamer/source/Timer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef TIMER_H_ -#define TIMER_H_ - -#include "ITimer.h" - -#include -#include -#include -#include -#include - -/** - * @brief ITimerFactory factory class definition. - */ -class TimerFactory : public ITimerFactory -{ -public: - /** - * @brief Weak pointer to the singleton factory object. - */ - static std::weak_ptr m_factory; - - std::unique_ptr createTimer(const std::chrono::milliseconds &timeout, const std::function &callback, - TimerType timerType = TimerType::ONE_SHOT) const override; -}; - -class Timer : public ITimer -{ -public: - Timer(const std::chrono::milliseconds &timeout, const std::function &callback, - TimerType timerType = TimerType::ONE_SHOT); - ~Timer(); - Timer(const Timer &) = delete; - Timer(Timer &&) = delete; - Timer &operator=(const Timer &) = delete; - Timer &operator=(Timer &&) = delete; - - void cancel() override; - bool isActive() const override; - -private: - void doCancel(); - - std::atomic m_active; - std::chrono::milliseconds m_timeout; - std::function m_callback; - mutable std::mutex m_mutex; - std::thread m_thread; - std::condition_variable m_cv; -}; - -#endif // TIMER_H_ diff --git a/middleware/rialto-gstreamer/source/WebAudioClientBackend.h b/middleware/rialto-gstreamer/source/WebAudioClientBackend.h deleted file mode 100644 index 1f22a0a6b..000000000 --- a/middleware/rialto-gstreamer/source/WebAudioClientBackend.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2023 - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ -#pragma once - -#include "WebAudioClientBackendInterface.h" -#include -#include -#include -#include - -namespace firebolt::rialto::client -{ -class WebAudioClientBackend final : public WebAudioClientBackendInterface -{ -public: - WebAudioClientBackend() : m_webAudioPlayerBackend(nullptr) {} - ~WebAudioClientBackend() final { m_webAudioPlayerBackend.reset(); } - - bool createWebAudioBackend(std::weak_ptr client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config) override - { - m_webAudioPlayerBackend = - firebolt::rialto::IWebAudioPlayerFactory::createFactory()->createWebAudioPlayer(client, audioMimeType, - priority, config); - - if (!m_webAudioPlayerBackend) - { - GST_ERROR("Could not create web audio backend"); - return false; - } - return true; - } - void destroyWebAudioBackend() override { m_webAudioPlayerBackend.reset(); } - - bool play() override { return m_webAudioPlayerBackend->play(); } - bool pause() override { return m_webAudioPlayerBackend->pause(); } - bool setEos() override { return m_webAudioPlayerBackend->setEos(); } - bool getBufferAvailable(uint32_t &availableFrames) override - { - std::shared_ptr webAudioShmInfo; - return m_webAudioPlayerBackend->getBufferAvailable(availableFrames, webAudioShmInfo); - } - bool getBufferDelay(uint32_t &delayFrames) override { return m_webAudioPlayerBackend->getBufferDelay(delayFrames); } - bool writeBuffer(const uint32_t numberOfFrames, void *data) override - { - return m_webAudioPlayerBackend->writeBuffer(numberOfFrames, data); - } - bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) override - { - return m_webAudioPlayerBackend->getDeviceInfo(preferredFrames, maximumFrames, supportDeferredPlay); - } - bool setVolume(double volume) override { return m_webAudioPlayerBackend->setVolume(volume); } - bool getVolume(double &volume) override { return m_webAudioPlayerBackend->getVolume(volume); } - -private: - std::unique_ptr m_webAudioPlayerBackend; -}; -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-gstreamer/source/WebAudioClientBackendInterface.h b/middleware/rialto-gstreamer/source/WebAudioClientBackendInterface.h deleted file mode 100644 index 8cbac732f..000000000 --- a/middleware/rialto-gstreamer/source/WebAudioClientBackendInterface.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#pragma once -#include -#include - -namespace firebolt::rialto::client -{ -class WebAudioClientBackendInterface -{ -public: - virtual ~WebAudioClientBackendInterface() = default; - virtual bool createWebAudioBackend(std::weak_ptr client, const std::string &audioMimeType, - const uint32_t priority, std::weak_ptr config) = 0; - virtual void destroyWebAudioBackend() = 0; - - virtual bool play() = 0; - virtual bool pause() = 0; - virtual bool setEos() = 0; - virtual bool getBufferAvailable(uint32_t &availableFrames) = 0; - virtual bool getBufferDelay(uint32_t &delayFrames) = 0; - virtual bool writeBuffer(const uint32_t numberOfFrames, void *data) = 0; - virtual bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) = 0; - virtual bool setVolume(double volume) = 0; - virtual bool getVolume(double &volume) = 0; -}; -} // namespace firebolt::rialto::client diff --git a/middleware/rialto-ocdm/include/ActiveSessions.h b/middleware/rialto-ocdm/include/ActiveSessions.h deleted file mode 100644 index 5b87087cd..000000000 --- a/middleware/rialto-ocdm/include/ActiveSessions.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ACTIVE_SESSIONS_H_ -#define ACTIVE_SESSIONS_H_ - -#include "ICdmBackend.h" -#include "IMessageDispatcher.h" -#include "OpenCDMSession.h" -#include -#include -#include -#include -#include -#include -#include - -class ActiveSessions -{ -public: - static ActiveSessions &instance(); - - OpenCDMSession *create(const std::shared_ptr &cdm, - const std::shared_ptr &messageDispatcher, const LicenseType &sessionType, - OpenCDMSessionCallbacks *callbacks, void *context, const std::string &initDataType, - const std::vector &initData); - OpenCDMSession *get(const std::vector &keyId); - void remove(OpenCDMSession *session); - -private: - ActiveSessions() = default; - ~ActiveSessions() = default; - -private: - std::mutex m_mutex; - std::map m_activeSessions; -}; - -#endif // ACTIVE_SESSIONS_H_ diff --git a/middleware/rialto-ocdm/include/CdmBackend.h b/middleware/rialto-ocdm/include/CdmBackend.h deleted file mode 100644 index e8f8f9949..000000000 --- a/middleware/rialto-ocdm/include/CdmBackend.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef CDM_BACKEND_H_ -#define CDM_BACKEND_H_ - -#include "ICdmBackend.h" -#include "Logger.h" -#include "MessageDispatcher.h" -#include -#include -#include -#include -#include -#include -#include - -class CdmBackend : public ICdmBackend, public firebolt::rialto::IControlClient -{ -public: - CdmBackend(const std::string &keySystem, const std::shared_ptr &mediaKeysClient, - const std::shared_ptr &mediaKeysFactory); - ~CdmBackend() override = default; - - void notifyApplicationState(firebolt::rialto::ApplicationState state) override; - - bool initialize(const firebolt::rialto::ApplicationState &initialState) override; - - bool selectKeyId(int32_t keySessionId, const std::vector &keyId) override; - bool containsKey(int32_t keySessionId, const std::vector &keyId) override; - bool createKeySession(firebolt::rialto::KeySessionType sessionType, bool isLDL, int32_t &keySessionId) override; - bool generateRequest(int32_t keySessionId, firebolt::rialto::InitDataType initDataType, - const std::vector &initData) override; - bool loadSession(int32_t keySessionId) override; - bool updateSession(int32_t keySessionId, const std::vector &responseData) override; - bool setDrmHeader(int32_t keySessionId, const std::vector &requestData) override; - bool closeKeySession(int32_t keySessionId) override; - bool removeKeySession(int32_t keySessionId) override; - bool deleteDrmStore() override; - bool deleteKeyStore() override; - bool getDrmStoreHash(std::vector &drmStoreHash) override; - bool getKeyStoreHash(std::vector &keyStoreHash) override; - bool getLdlSessionsLimit(uint32_t &ldlLimit) override; - bool getLastDrmError(int32_t keySessionId, uint32_t &errorCode) override; - bool getDrmTime(uint64_t &drmTime) override; - bool getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) override; - bool releaseKeySession(int32_t keySessionId) override; - bool getMetricSystemData(std::vector &buffer) override; - -private: - bool createMediaKeys(); - -private: - Logger m_log; - std::mutex m_mutex; - std::condition_variable m_cv; - firebolt::rialto::ApplicationState m_appState; - const std::string m_keySystem; - std::shared_ptr m_mediaKeysClient; - std::shared_ptr m_mediaKeysFactory; - std::unique_ptr m_mediaKeys; -}; - -#endif // CDM_BACKEND_H_ diff --git a/middleware/rialto-ocdm/include/ICdmBackend.h b/middleware/rialto-ocdm/include/ICdmBackend.h deleted file mode 100644 index d0ce7668c..000000000 --- a/middleware/rialto-ocdm/include/ICdmBackend.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef I_CDM_BACKEND_H_ -#define I_CDM_BACKEND_H_ - -#include -#include -#include -#include -#include -#include -#include - -class ICdmBackend -{ -public: - virtual ~ICdmBackend() = default; - - virtual bool initialize(const firebolt::rialto::ApplicationState &initialState) = 0; - virtual bool selectKeyId(int32_t keySessionId, const std::vector &keyId) = 0; - virtual bool containsKey(int32_t keySessionId, const std::vector &keyId) = 0; - virtual bool createKeySession(firebolt::rialto::KeySessionType sessionType, bool isLDL, int32_t &keySessionId) = 0; - virtual bool generateRequest(int32_t keySessionId, firebolt::rialto::InitDataType initDataType, - const std::vector &initData) = 0; - virtual bool loadSession(int32_t keySessionId) = 0; - virtual bool updateSession(int32_t keySessionId, const std::vector &responseData) = 0; - virtual bool setDrmHeader(int32_t keySessionId, const std::vector &requestData) = 0; - virtual bool closeKeySession(int32_t keySessionId) = 0; - virtual bool removeKeySession(int32_t keySessionId) = 0; - virtual bool deleteDrmStore() = 0; - virtual bool deleteKeyStore() = 0; - virtual bool getDrmStoreHash(std::vector &drmStoreHash) = 0; - virtual bool getKeyStoreHash(std::vector &keyStoreHash) = 0; - virtual bool getLdlSessionsLimit(uint32_t &ldlLimit) = 0; - virtual bool getLastDrmError(int32_t keySessionId, uint32_t &errorCode) = 0; - virtual bool getDrmTime(uint64_t &drmTime) = 0; - virtual bool getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) = 0; - virtual bool releaseKeySession(int32_t keySessionId) = 0; - virtual bool getMetricSystemData(std::vector &buffer) = 0; -}; - -#endif // I_CDM_BACKEND_H_ diff --git a/middleware/rialto-ocdm/include/IMessageDispatcher.h b/middleware/rialto-ocdm/include/IMessageDispatcher.h deleted file mode 100644 index 9dceccde4..000000000 --- a/middleware/rialto-ocdm/include/IMessageDispatcher.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef I_MESSAGE_DISPATCHER_H_ -#define I_MESSAGE_DISPATCHER_H_ - -#include -#include - -class IMessageDispatcherClient -{ -public: - virtual ~IMessageDispatcherClient() = default; -}; - -class IMessageDispatcher -{ -public: - virtual ~IMessageDispatcher() = default; - virtual std::unique_ptr createClient(firebolt::rialto::IMediaKeysClient *client) = 0; -}; - -#endif // I_MESSAGE_DISPATCHER_H_ diff --git a/middleware/rialto-ocdm/include/Logger.h b/middleware/rialto-ocdm/include/Logger.h deleted file mode 100644 index 51b45466c..000000000 --- a/middleware/rialto-ocdm/include/Logger.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LOGGER_H_ -#define LOGGER_H_ - -#include -#include -#include -#include - -enum Severity -{ - fatal = 0, - error = 1, - warn = 2, - mil = 3, - info = 4, - debug = 5 -}; - -class LogFile -{ -public: - static LogFile &instance(); - bool write(const std::string &line); - bool isEnabled() const; - void reset(); - -private: - LogFile(); - ~LogFile(); - - void tryOpenFile(); - void tryCloseFile(); - -private: - std::fstream m_file; - std::mutex m_mutex; -}; - -class Logger; -class Flusher -{ -public: - Flusher(std::stringstream &stream, const std::string &componentName, const Severity &severity); - ~Flusher(); - - template Flusher &operator<<(const T &text) - { - m_stream << text; - return *this; - } - -private: - std::stringstream &m_stream; - Severity m_severity; -}; - -class Logger -{ -public: - explicit Logger(const std::string &componentName); - Flusher operator<<(const Severity &) const; - -private: - const std::string m_componentName; - mutable std::stringstream m_stream; -}; - -#endif // LOGGER_H_ diff --git a/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h b/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h deleted file mode 100644 index fe7184eac..000000000 --- a/middleware/rialto-ocdm/include/MediaKeysCapabilitiesBackend.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MEDIA_KEYS_CAPABILITIES_BACKEND_H_ -#define MEDIA_KEYS_CAPABILITIES_BACKEND_H_ - -#include -#include -#include -#include -#include - -class MediaKeysCapabilitiesBackend -{ -public: - static MediaKeysCapabilitiesBackend &instance(); - - std::vector getSupportedKeySystems(); - OpenCDMError supportsKeySystem(const std::string &keySystem); - bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version); - bool isServerCertificateSupported(const std::string &keySystem); - -private: - MediaKeysCapabilitiesBackend(); - ~MediaKeysCapabilitiesBackend(); - -private: - std::shared_ptr m_mediaKeysCapabilities; -}; - -#endif // MEDIA_KEYS_CAPABILITIES_BACKEND_H_ diff --git a/middleware/rialto-ocdm/include/MessageDispatcher.h b/middleware/rialto-ocdm/include/MessageDispatcher.h deleted file mode 100644 index dc051c634..000000000 --- a/middleware/rialto-ocdm/include/MessageDispatcher.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MESSAGE_DISPATCHER_H_ -#define MESSAGE_DISPATCHER_H_ - -#include "IMessageDispatcher.h" -#include -#include -#include -#include -#include - -class MessageDispatcher : public IMessageDispatcher, public firebolt::rialto::IMediaKeysClient -{ - class MessageDispatcherClient : public IMessageDispatcherClient - { - public: - MessageDispatcherClient(MessageDispatcher &dispatcher, firebolt::rialto::IMediaKeysClient *client); - ~MessageDispatcherClient() override; - - private: - MessageDispatcher &m_dispatcher; - firebolt::rialto::IMediaKeysClient *m_client; - }; - -public: - MessageDispatcher() = default; - ~MessageDispatcher() override = default; - - std::unique_ptr createClient(firebolt::rialto::IMediaKeysClient *client) override; - - void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, - const std::string &url) override; - void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) override; - void onKeyStatusesChanged(int32_t keySessionId, const firebolt::rialto::KeyStatusVector &keyStatuses) override; - -private: - void addClient(firebolt::rialto::IMediaKeysClient *client); - void removeClient(firebolt::rialto::IMediaKeysClient *client); - -private: - std::mutex m_mutex; - std::set m_clients; -}; - -#endif // MESSAGE_DISPATCHER_H_ diff --git a/middleware/rialto-ocdm/include/OpenCDMSession.h b/middleware/rialto-ocdm/include/OpenCDMSession.h deleted file mode 100644 index a681ed4e0..000000000 --- a/middleware/rialto-ocdm/include/OpenCDMSession.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OPENCDM_SESSION_H_ -#define OPENCDM_SESSION_H_ - -#include -#include -#include -#include -#include -#include -#include - -struct _GstCaps; -struct _GstBuffer; -typedef struct _GstCaps GstCaps; -typedef struct _GstBuffer GstBuffer; - -class OpenCDMSession -{ -public: - typedef std::function &license_renewal_message, uint64_t session_id)> LicenseRenewalCallback; - typedef std::function, firebolt::rialto::KeyStatus>> &key_statuses, - uint64_t session_id)> - KeyStatusesChangedCallback; - - OpenCDMSession() = default; - virtual ~OpenCDMSession() = default; - - virtual bool initialize() = 0; - virtual bool initialize(bool) = 0; - virtual bool generateRequest(const std::string &initDataType, const std::vector &initData, - const std::vector &cdmData) = 0; - virtual bool loadSession() = 0; - virtual bool updateSession(const std::vector &license) = 0; - virtual bool getChallengeData(std::vector &challengeData) = 0; - virtual bool containsKey(const std::vector &keyId) = 0; - virtual bool setDrmHeader(const std::vector &drmHeader) = 0; - virtual bool selectKeyId(const std::vector &keyId) = 0; - virtual void addProtectionMeta(GstBuffer *buffer, GstBuffer *subSample, const uint32_t subSampleCount, - GstBuffer *IV, GstBuffer *keyID, uint32_t initWithLast15) = 0; - virtual bool addProtectionMeta(GstBuffer *buffer) = 0; - virtual bool closeSession() = 0; - virtual bool removeSession() = 0; - virtual KeyStatus status(const std::vector &key) const = 0; - - virtual const std::string &getSessionId() const = 0; - virtual uint32_t getLastDrmError() const = 0; -}; - -#endif // OPENCDM_SESSION_H_ diff --git a/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h b/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h deleted file mode 100644 index f3c862d40..000000000 --- a/middleware/rialto-ocdm/include/OpenCDMSessionPrivate.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OPENCDM_SESSION_PRIVATE_H_ -#define OPENCDM_SESSION_PRIVATE_H_ - -#include "IMediaKeysClient.h" -#include "Logger.h" -#include "OpenCDMSession.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct _GstCaps; -struct _GstBuffer; -typedef struct _GstCaps GstCaps; -typedef struct _GstBuffer GstBuffer; - -class OpenCDMSessionPrivate : public OpenCDMSession, public firebolt::rialto::IMediaKeysClient -{ -public: - OpenCDMSessionPrivate(const std::shared_ptr &cdm, - const std::shared_ptr &messageDispatcher, const LicenseType &sessionType, - OpenCDMSessionCallbacks *callbacks, void *context, const std::string &initDataType, - const std::vector &initData); - ~OpenCDMSessionPrivate(); - - void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, - const std::string &url) override; - void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) override; - void onKeyStatusesChanged(int32_t keySessionId, const firebolt::rialto::KeyStatusVector &keyStatuses) override; - - bool initialize() override; - bool initialize(bool) override; - bool generateRequest(const std::string &initDataType, const std::vector &initData, - const std::vector &cdmData) override; - bool loadSession() override; - bool updateSession(const std::vector &license) override; - bool getChallengeData(std::vector &challengeData) override; - bool containsKey(const std::vector &keyId) override; - bool setDrmHeader(const std::vector &drmHeader) override; - bool selectKeyId(const std::vector &keyId) override; - void addProtectionMeta(GstBuffer *buffer, GstBuffer *subSample, const uint32_t subSampleCount, GstBuffer *IV, - GstBuffer *keyID, uint32_t initWithLast15) override; - bool addProtectionMeta(GstBuffer *buffer) override; - bool closeSession() override; - bool removeSession() override; - KeyStatus status(const std::vector &key) const override; - - const std::string &getSessionId() const override; - uint32_t getLastDrmError() const override; - -private: - void initializeCdmKeySessionId(); - void updateChallenge(const std::vector &challenge); - void releaseSession(); - -private: - Logger m_log; - std::mutex m_mutex; - std::condition_variable m_challengeCv; - void *m_context; - std::shared_ptr m_cdmBackend; - std::shared_ptr m_messageDispatcher; - std::unique_ptr m_messageDispatcherClient; - int32_t m_rialtoSessionId; - std::string m_cdmKeySessionId; - OpenCDMSessionCallbacks *m_callbacks; - firebolt::rialto::KeySessionType m_sessionType; - firebolt::rialto::InitDataType m_initDataType; - std::vector m_initData; - bool m_isInitialized; - std::vector m_challengeData; - std::vector m_playreadyKeyId; - std::map, firebolt::rialto::KeyStatus> m_keyStatuses; - - firebolt::rialto::KeySessionType getRialtoSessionType(const LicenseType licenseType); - firebolt::rialto::InitDataType getRialtoInitDataType(const std::string &type); -}; - -#endif // OPENCDM_SESSION_PRIVATE_H_ diff --git a/middleware/rialto-ocdm/include/OpenCDMSystem.h b/middleware/rialto-ocdm/include/OpenCDMSystem.h deleted file mode 100644 index e9726d635..000000000 --- a/middleware/rialto-ocdm/include/OpenCDMSystem.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OPENCDM_SYSTEM_H_ -#define OPENCDM_SYSTEM_H_ - -#include "OpenCDMSession.h" -#include -#include -#include -#include - -struct OpenCDMSystem -{ - OpenCDMSystem() = default; - virtual ~OpenCDMSystem() = default; - OpenCDMSystem(const OpenCDMSystem &) = default; - OpenCDMSystem(OpenCDMSystem &&) = default; - OpenCDMSystem &operator=(OpenCDMSystem &&) = default; - OpenCDMSystem &operator=(const OpenCDMSystem &) = default; - - virtual const std::string &keySystem() const = 0; - virtual const std::string &metadata() const = 0; - virtual OpenCDMSession *createSession(const LicenseType licenseType, OpenCDMSessionCallbacks *callbacks, - void *userData, const std::string &initDataType, - const std::vector &initData) const = 0; - virtual bool getDrmTime(uint64_t &drmTime) const = 0; - virtual bool getLdlSessionsLimit(uint32_t &ldlLimit) const = 0; - virtual bool getKeyStoreHash(std::vector &keyStoreHash) const = 0; - virtual bool getDrmStoreHash(std::vector &drmStoreHash) const = 0; - virtual bool deleteKeyStore() const = 0; - virtual bool deleteDrmStore() const = 0; - virtual bool getMetricSystemData(std::vector &buffer) const = 0; -}; - -#endif // OPENCDM_SYSTEM_H_ diff --git a/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h b/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h deleted file mode 100644 index ce447fdc2..000000000 --- a/middleware/rialto-ocdm/include/OpenCDMSystemPrivate.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OPENCDM_SYSTEM_PRIVATE_H_ -#define OPENCDM_SYSTEM_PRIVATE_H_ - -#include "CdmBackend.h" -#include "Logger.h" -#include "MessageDispatcher.h" -#include "OpenCDMSystem.h" -#include -#include -#include -#include - -OpenCDMSystem *createSystem(const char system[], const std::string &metadata); - -class OpenCDMSystemPrivate : public OpenCDMSystem -{ -public: - OpenCDMSystemPrivate(const std::string &system, const std::string &metadata, - const std::shared_ptr &messageDispatcher, - const std::shared_ptr &cdmBackend); - ~OpenCDMSystemPrivate(); - OpenCDMSystemPrivate(const OpenCDMSystemPrivate &) = default; - OpenCDMSystemPrivate(OpenCDMSystemPrivate &&) = default; - OpenCDMSystemPrivate &operator=(OpenCDMSystemPrivate &&) = default; - OpenCDMSystemPrivate &operator=(const OpenCDMSystemPrivate &) = default; - const std::string &keySystem() const; - const std::string &metadata() const; - OpenCDMSession *createSession(const LicenseType licenseType, OpenCDMSessionCallbacks *callbacks, void *userData, - const std::string &initDataType, const std::vector &initData) const; - bool getDrmTime(uint64_t &drmTime) const; - bool getLdlSessionsLimit(uint32_t &ldlLimit) const; - bool getKeyStoreHash(std::vector &keyStoreHash) const; - bool getDrmStoreHash(std::vector &drmStoreHash) const; - bool deleteKeyStore() const; - bool deleteDrmStore() const; - bool getMetricSystemData(std::vector &buffer) const; - -private: - Logger m_log; - std::string m_keySystem; - std::string m_metadata; - std::shared_ptr m_control; - std::shared_ptr m_messageDispatcher; - std::shared_ptr m_cdmBackend; -}; - -#endif // OPENCDM_SYSTEM_PRIVATE_H_ diff --git a/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h b/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h deleted file mode 100644 index 5352e6331..000000000 --- a/middleware/rialto-ocdm/include/RialtoGStreamerEMEProtectionMetadata.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef RIALTOG_STREAMEREME_PROTECTION_METADATA_H_ -#define RIALTOG_STREAMEREME_PROTECTION_METADATA_H_ - -#include - -G_BEGIN_DECLS - -#define GST_RIALTO_PROTECTION_METADATA_GET_TYPE (rialto_eme_protection_metadata_get_type()) -#define GST_RIALTO_PROTECTION_METADATA_INFO (rialto_mse_protection_metadata_get_info()) - -struct _GstRialtoProtectionMetadata -{ - GstMeta parent; - GstStructure *info; -}; - -typedef struct _GstRialtoProtectionMetadata GstRialtoProtectionMetadata; - -// NOLINTNEXTLINE(build/function_format) -GType rialto_eme_protection_metadata_get_type(); -// NOLINTNEXTLINE(build/function_format) -const GstMetaInfo *rialto_mse_protection_metadata_get_info(); -// NOLINTNEXTLINE(build/function_format) -GstRialtoProtectionMetadata *rialto_mse_add_protection_metadata(GstBuffer *gstBuffer, GstStructure *info); - -G_END_DECLS - -#endif // RIALTOG_STREAMEREME_PROTECTION_METADATA_H_ diff --git a/middleware/rialto-ocdm/source/ActiveSessions.cpp b/middleware/rialto-ocdm/source/ActiveSessions.cpp deleted file mode 100644 index 297ed20c9..000000000 --- a/middleware/rialto-ocdm/source/ActiveSessions.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ActiveSessions.h" -#include "OpenCDMSessionPrivate.h" -#include - -ActiveSessions &ActiveSessions::instance() -{ - static ActiveSessions activeSessions; - return activeSessions; -} - -OpenCDMSession *ActiveSessions::create(const std::shared_ptr &cdm, - const std::shared_ptr &messageDispatcher, - const LicenseType &sessionType, OpenCDMSessionCallbacks *callbacks, void *context, - const std::string &initDataType, const std::vector &initData) -{ - std::unique_lock lock{m_mutex}; - OpenCDMSession *newSession = - new OpenCDMSessionPrivate(cdm, messageDispatcher, sessionType, callbacks, context, initDataType, initData); - m_activeSessions.insert(std::make_pair(newSession, 1)); - return newSession; -} - -OpenCDMSession *ActiveSessions::get(const std::vector &keyId) -{ - std::unique_lock lock{m_mutex}; - auto sessionIter{std::find_if(m_activeSessions.begin(), m_activeSessions.end(), [&](const auto &iter) - { return iter.first->status(keyId) != KeyStatus::InternalError; })}; - if (sessionIter != m_activeSessions.end()) - { - ++sessionIter->second; - return sessionIter->first; - } - return nullptr; -} - -void ActiveSessions::remove(OpenCDMSession *session) -{ - std::unique_lock lock{m_mutex}; - auto sessionIter{m_activeSessions.find(session)}; - if (sessionIter != m_activeSessions.end()) - { - --sessionIter->second; - if (0 == sessionIter->second) - { - delete sessionIter->first; - m_activeSessions.erase(sessionIter); - } - } -} diff --git a/middleware/rialto-ocdm/source/CPPLINT.cfg b/middleware/rialto-ocdm/source/CPPLINT.cfg deleted file mode 100644 index 781dc1c70..000000000 --- a/middleware/rialto-ocdm/source/CPPLINT.cfg +++ /dev/null @@ -1,21 +0,0 @@ -# -# If not stated otherwise in this file or this component's LICENSE file the -# following copyright and licenses apply: -# -# Copyright 2023 -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# Exclude files with opencdm functions -exclude_files=open_* diff --git a/middleware/rialto-ocdm/source/CdmBackend.cpp b/middleware/rialto-ocdm/source/CdmBackend.cpp deleted file mode 100644 index 01b6605ad..000000000 --- a/middleware/rialto-ocdm/source/CdmBackend.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "CdmBackend.h" - -CdmBackend::CdmBackend(const std::string &keySystem, - const std::shared_ptr &mediaKeysClient, - const std::shared_ptr &mediaKeysFactory) - : m_log{"CdmBackend"}, m_appState{firebolt::rialto::ApplicationState::UNKNOWN}, m_keySystem{keySystem}, - m_mediaKeysClient{mediaKeysClient}, m_mediaKeysFactory{mediaKeysFactory} -{ -} - -void CdmBackend::notifyApplicationState(firebolt::rialto::ApplicationState state) -{ - std::unique_lock lock{m_mutex}; - if (state == m_appState) - { - return; - } - if (firebolt::rialto::ApplicationState::RUNNING == state) - { - m_log << info << "Rialto state changed to: RUNNING"; - if (createMediaKeys()) - { - m_appState = state; - m_cv.notify_one(); - } - } - else - { - m_log << info << "Rialto state changed to: INACTIVE"; - m_mediaKeys.reset(); - m_appState = state; - } -} - -bool CdmBackend::initialize(const firebolt::rialto::ApplicationState &initialState) -{ - std::unique_lock lock{m_mutex}; - if (firebolt::rialto::ApplicationState::UNKNOWN != m_appState) - { - // CdmBackend initialized by Rialto Client thread in notifyApplicationState() - return true; - } - if (firebolt::rialto::ApplicationState::RUNNING == initialState) - { - if (!createMediaKeys()) - { - return false; - } - } - m_log << info << "CdmBackend initialized in " - << (firebolt::rialto::ApplicationState::RUNNING == initialState ? "RUNNING" : "INACTIVE") << " state"; - m_appState = initialState; - return true; -} - -bool CdmBackend::selectKeyId(int32_t keySessionId, const std::vector &keyId) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->selectKeyId(keySessionId, keyId); -} - -bool CdmBackend::containsKey(int32_t keySessionId, const std::vector &keyId) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return m_mediaKeys->containsKey(keySessionId, keyId); -} - -bool CdmBackend::createKeySession(firebolt::rialto::KeySessionType sessionType, bool isLDL, int32_t &keySessionId) -{ - std::unique_lock lock{m_mutex}; - // Sometimes app tries to create session before reaching RUNNING state. We have to wait for it. - m_cv.wait_for(lock, std::chrono::seconds(1), - [this]() { return firebolt::rialto::ApplicationState::RUNNING == m_appState; }); - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == - m_mediaKeys->createKeySession(sessionType, m_mediaKeysClient, isLDL, keySessionId); -} - -bool CdmBackend::generateRequest(int32_t keySessionId, firebolt::rialto::InitDataType initDataType, - const std::vector &initData) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == - m_mediaKeys->generateRequest(keySessionId, initDataType, initData); -} - -bool CdmBackend::loadSession(int32_t keySessionId) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->loadSession(keySessionId); -} - -bool CdmBackend::updateSession(int32_t keySessionId, const std::vector &responseData) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->updateSession(keySessionId, responseData); -} - -bool CdmBackend::setDrmHeader(int32_t keySessionId, const std::vector &requestData) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->setDrmHeader(keySessionId, requestData); -} - -bool CdmBackend::closeKeySession(int32_t keySessionId) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->closeKeySession(keySessionId); -} - -bool CdmBackend::removeKeySession(int32_t keySessionId) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->removeKeySession(keySessionId); -} - -bool CdmBackend::deleteDrmStore() -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->deleteDrmStore(); -} - -bool CdmBackend::deleteKeyStore() -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->deleteKeyStore(); -} - -bool CdmBackend::getDrmStoreHash(std::vector &drmStoreHash) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getDrmStoreHash(drmStoreHash); -} - -bool CdmBackend::getKeyStoreHash(std::vector &keyStoreHash) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getKeyStoreHash(keyStoreHash); -} - -bool CdmBackend::getLdlSessionsLimit(uint32_t &ldlLimit) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getLdlSessionsLimit(ldlLimit); -} - -bool CdmBackend::getLastDrmError(int32_t keySessionId, uint32_t &errorCode) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getLastDrmError(keySessionId, errorCode); -} - -bool CdmBackend::getDrmTime(uint64_t &drmTime) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getDrmTime(drmTime); -} - -bool CdmBackend::getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getCdmKeySessionId(keySessionId, cdmKeySessionId); -} - -bool CdmBackend::releaseKeySession(int32_t keySessionId) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->releaseKeySession(keySessionId); -} - -bool CdmBackend::createMediaKeys() -{ - if (!m_mediaKeysFactory) - { - m_log << error << "Failed to initialize media keys - not possible to create factory"; - return false; - } - - m_mediaKeys = m_mediaKeysFactory->createMediaKeys(m_keySystem); - if (!m_mediaKeys) - { - m_log << error << "Failed to initialize media keys - not possible to create media keys"; - return false; - } - return true; -} - -bool CdmBackend::getMetricSystemData(std::vector &buffer) -{ - std::unique_lock lock{m_mutex}; - if (!m_mediaKeys) - { - return false; - } - return firebolt::rialto::MediaKeyErrorStatus::OK == m_mediaKeys->getMetricSystemData(buffer); -} diff --git a/middleware/rialto-ocdm/source/Logger.cpp b/middleware/rialto-ocdm/source/Logger.cpp deleted file mode 100644 index f49dde108..000000000 --- a/middleware/rialto-ocdm/source/Logger.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Logger.h" -#include -#include -#include -#include -#include - -#ifdef USE_ETHANLOG - -#include - -#define SYSTEM_LOG_FATAL(filename, function, line, ...) ethanlog(ETHAN_LOG_FATAL, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_ERROR(filename, function, line, ...) ethanlog(ETHAN_LOG_ERROR, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_WARN(filename, function, line, ...) \ - ethanlog(ETHAN_LOG_WARNING, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_MIL(filename, function, line, ...) \ - ethanlog(ETHAN_LOG_MILESTONE, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_INFO(filename, function, line, ...) ethanlog(ETHAN_LOG_INFO, filename, function, line, __VA_ARGS__) -#define SYSTEM_LOG_DEBUG(filename, function, line, ...) ethanlog(ETHAN_LOG_DEBUG, filename, function, line, __VA_ARGS__) - -#else - -#include - -#define SYSTEM_LOG_FATAL(filename, function, line, ...) syslog(LOG_CRIT, __VA_ARGS__) -#define SYSTEM_LOG_ERROR(filename, function, line, ...) syslog(LOG_ERR, __VA_ARGS__) -#define SYSTEM_LOG_WARN(filename, function, line, ...) syslog(LOG_WARNING, __VA_ARGS__) -#define SYSTEM_LOG_MIL(filename, function, line, ...) syslog(LOG_NOTICE, __VA_ARGS__) -#define SYSTEM_LOG_INFO(filename, function, line, ...) syslog(LOG_INFO, __VA_ARGS__) -#define SYSTEM_LOG_DEBUG(filename, function, line, ...) syslog(LOG_DEBUG, __VA_ARGS__) - -#endif - -namespace -{ -Severity getLogLevel() -{ - const char *debugVar = getenv("RIALTO_DEBUG"); - if (debugVar) - { - std::string varStr{debugVar}; - if ("0" == varStr) - return Severity::fatal; - if ("1" == varStr) - return Severity::error; - if ("2" == varStr) - return Severity::warn; - if ("3" == varStr) - return Severity::mil; - if ("4" == varStr) - return Severity::info; - if ("5" == varStr) - return Severity::debug; - } - return Severity::warn; -} - -bool isConsoleLogEnabled() -{ - const char *debugVar = getenv("RIALTO_CONSOLE_LOG"); - if (debugVar) - { - return std::string(debugVar) == "1"; - } - return false; -} - -std::string getRialtoLogPath() -{ - const char *logPathEnvVar = getenv("RIALTO_LOG_PATH"); - if (logPathEnvVar) - { - return std::string(logPathEnvVar); - } - return ""; -} - -std::string toString(const Severity &severity) -{ - if (Severity::fatal == severity) - return "ftl"; - if (Severity::error == severity) - return "err"; - if (Severity::warn == severity) - return "wrn"; - if (Severity::mil == severity) - return "mil"; - if (Severity::info == severity) - return "inf"; - if (Severity::debug == severity) - return "dbg"; - return "???"; -} - -} // namespace - -LogFile &LogFile::instance() -{ - static LogFile logFile; - return logFile; -} - -bool LogFile::write(const std::string &line) -{ - std::unique_lock lock{m_mutex}; - m_file << line << std::endl; - return true; -} - -bool LogFile::isEnabled() const -{ - return m_file.is_open(); -} - -void LogFile::reset() -{ - tryCloseFile(); - tryOpenFile(); -} - -LogFile::LogFile() -{ - tryOpenFile(); -} - -LogFile::~LogFile() -{ - tryCloseFile(); -} - -void LogFile::tryOpenFile() -{ - std::string logPath{getRialtoLogPath()}; - if (!logPath.empty()) - { - // Add suffix to have rialto client and rialto ocdm logs in separate files - logPath += ".ocdm"; - m_file = std::fstream(logPath, std::fstream::out); - } -} - -void LogFile::tryCloseFile() -{ - if (m_file.is_open()) - { - m_file.close(); - } -} - -Flusher::Flusher(std::stringstream &stream, const std::string &componentName, const Severity &severity) - : m_stream{stream}, m_severity{severity} -{ - if (LogFile::instance().isEnabled() || isConsoleLogEnabled()) - { - const std::chrono::time_point now = std::chrono::system_clock::now(); - const std::time_t t_c = std::chrono::system_clock::to_time_t(now); - m_stream << std::put_time(std::localtime(&t_c), "[%F %T]"); - } - m_stream << "[" << componentName << "][" << toString(severity) << "]: "; -} - -Flusher::~Flusher() -{ - if (getLogLevel() >= m_severity) - { - if (LogFile::instance().isEnabled()) - { - LogFile::instance().write(m_stream.str()); - } - else if (isConsoleLogEnabled()) - { - std::cout << m_stream.str() << std::endl; - } - else - { - switch (m_severity) - { - case Severity::fatal: - SYSTEM_LOG_FATAL(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); - break; - case Severity::error: - SYSTEM_LOG_ERROR(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); - break; - case Severity::warn: - SYSTEM_LOG_WARN(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); - break; - case Severity::mil: - SYSTEM_LOG_MIL(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); - break; - case Severity::info: - SYSTEM_LOG_INFO(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); - break; - case Severity::debug: - default: - SYSTEM_LOG_DEBUG(nullptr, nullptr, -1, "%s", m_stream.str().c_str()); - break; - } - } - } - m_stream.str(""); -} - -Logger::Logger(const std::string &componentName) : m_componentName{componentName} {} - -Flusher Logger::operator<<(const Severity &severity) const -{ - return Flusher(m_stream, m_componentName, severity); -} diff --git a/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp b/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp deleted file mode 100644 index 2fbe82dda..000000000 --- a/middleware/rialto-ocdm/source/MediaKeysCapabilitiesBackend.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MediaKeysCapabilitiesBackend.h" - -MediaKeysCapabilitiesBackend &MediaKeysCapabilitiesBackend::instance() -{ - static MediaKeysCapabilitiesBackend mkcBackend; - return mkcBackend; -} - -std::vector MediaKeysCapabilitiesBackend::getSupportedKeySystems() -{ - std::vector result{}; - if (m_mediaKeysCapabilities) - { - result = m_mediaKeysCapabilities->getSupportedKeySystems(); - } - return result; -} - -OpenCDMError MediaKeysCapabilitiesBackend::supportsKeySystem(const std::string &keySystem) -{ - OpenCDMError result{ERROR_FAIL}; - if (m_mediaKeysCapabilities) - { - result = ERROR_KEYSYSTEM_NOT_SUPPORTED; - if (m_mediaKeysCapabilities->supportsKeySystem(keySystem)) - { - result = ERROR_NONE; - } - } - return result; -} - -bool MediaKeysCapabilitiesBackend::getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) -{ - bool result{false}; - if (m_mediaKeysCapabilities) - { - result = m_mediaKeysCapabilities->getSupportedKeySystemVersion(keySystem, version); - } - return result; -} - -bool MediaKeysCapabilitiesBackend::isServerCertificateSupported(const std::string &keySystem) -{ - bool result{false}; - if (m_mediaKeysCapabilities) - { - result = m_mediaKeysCapabilities->isServerCertificateSupported(keySystem); - } - return result; -} - -MediaKeysCapabilitiesBackend::MediaKeysCapabilitiesBackend() -{ - std::shared_ptr factory = - firebolt::rialto::IMediaKeysCapabilitiesFactory::createFactory(); - if (factory) - { - m_mediaKeysCapabilities = factory->getMediaKeysCapabilities(); - } -} - -MediaKeysCapabilitiesBackend::~MediaKeysCapabilitiesBackend() -{ - m_mediaKeysCapabilities.reset(); -} diff --git a/middleware/rialto-ocdm/source/MessageDispatcher.cpp b/middleware/rialto-ocdm/source/MessageDispatcher.cpp deleted file mode 100644 index 2c3069ea6..000000000 --- a/middleware/rialto-ocdm/source/MessageDispatcher.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MessageDispatcher.h" - -MessageDispatcher::MessageDispatcherClient::MessageDispatcherClient(MessageDispatcher &dispatcher, - firebolt::rialto::IMediaKeysClient *client) - : m_dispatcher{dispatcher}, m_client{client} -{ - m_dispatcher.addClient(m_client); -} - -MessageDispatcher::MessageDispatcherClient::~MessageDispatcherClient() -{ - m_dispatcher.removeClient(m_client); -} - -std::unique_ptr MessageDispatcher::createClient(firebolt::rialto::IMediaKeysClient *client) -{ - return std::make_unique(*this, client); -} - -void MessageDispatcher::addClient(firebolt::rialto::IMediaKeysClient *client) -{ - std::unique_lock lock{m_mutex}; - m_clients.emplace(client); -} - -void MessageDispatcher::removeClient(firebolt::rialto::IMediaKeysClient *client) -{ - std::unique_lock lock{m_mutex}; - m_clients.erase(client); -} - -void MessageDispatcher::onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, - const std::string &url) -{ - std::unique_lock lock{m_mutex}; - for (auto *client : m_clients) - { - client->onLicenseRequest(keySessionId, licenseRequestMessage, url); - } -} - -void MessageDispatcher::onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) -{ - std::unique_lock lock{m_mutex}; - for (auto *client : m_clients) - { - client->onLicenseRenewal(keySessionId, licenseRenewalMessage); - } -} - -void MessageDispatcher::onKeyStatusesChanged(int32_t keySessionId, const firebolt::rialto::KeyStatusVector &keyStatuses) -{ - std::unique_lock lock{m_mutex}; - for (auto *client : m_clients) - { - client->onKeyStatusesChanged(keySessionId, keyStatuses); - } -} diff --git a/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp b/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp deleted file mode 100644 index ae4124a61..000000000 --- a/middleware/rialto-ocdm/source/OpenCDMSessionPrivate.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "OpenCDMSessionPrivate.h" -#include "RialtoGStreamerEMEProtectionMetadata.h" -#include -#include -#include - -namespace -{ -const KeyStatus convertKeyStatus(const firebolt::rialto::KeyStatus &keyStatus) -{ - switch (keyStatus) - { - case firebolt::rialto::KeyStatus::USABLE: - { - return Usable; - } - case firebolt::rialto::KeyStatus::EXPIRED: - { - return Expired; - } - case firebolt::rialto::KeyStatus::RELEASED: - { - return Released; - } - case firebolt::rialto::KeyStatus::OUTPUT_RESTRICTED: - { - return OutputRestricted; - } - case firebolt::rialto::KeyStatus::PENDING: - { - return StatusPending; - } - case firebolt::rialto::KeyStatus::INTERNAL_ERROR: - default: - { - return InternalError; - } - } -} - -const std::string kDefaultSessionId{"0"}; -} // namespace - -OpenCDMSessionPrivate::OpenCDMSessionPrivate(const std::shared_ptr &cdm, - const std::shared_ptr &messageDispatcher, - const LicenseType &sessionType, OpenCDMSessionCallbacks *callbacks, - void *context, const std::string &initDataType, - const std::vector &initData) - : m_log{"OpenCDMSessionPrivate"}, m_context(context), m_cdmBackend(cdm), m_messageDispatcher(messageDispatcher), - m_rialtoSessionId(firebolt::rialto::kInvalidSessionId), m_callbacks(callbacks), - m_sessionType(getRialtoSessionType(sessionType)), m_initDataType(getRialtoInitDataType(initDataType)), - m_initData(initData), m_isInitialized{false} -{ - m_log << debug << "constructed: " << static_cast(this); -} - -OpenCDMSessionPrivate::~OpenCDMSessionPrivate() -{ - m_log << debug << "destructed: " << static_cast(this); - if (m_isInitialized) - { - releaseSession(); - } -} - -bool OpenCDMSessionPrivate::initialize() -{ - return initialize(false); -} - -bool OpenCDMSessionPrivate::initialize(bool isLDL) -{ - if (!m_cdmBackend || !m_messageDispatcher) - { - m_log << error << "Cdm/message dispatcher is NULL or not initialized"; - return false; - } - if (!m_isInitialized) - { - if (!m_cdmBackend->createKeySession(m_sessionType, isLDL, m_rialtoSessionId)) - { - m_log << error << "Failed to create a session. Got drm error %u", getLastDrmError(); - return false; - } - m_messageDispatcherClient = m_messageDispatcher->createClient(this); - m_isInitialized = true; - m_log << info << "Successfully created a session"; - } - return true; -} - -bool OpenCDMSessionPrivate::generateRequest(const std::string &initDataType, const std::vector &initData, - const std::vector &cdmData) -{ - firebolt::rialto::InitDataType dataType = getRialtoInitDataType(initDataType); - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return false; - } - - if ((dataType != firebolt::rialto::InitDataType::UNKNOWN) && (-1 != m_rialtoSessionId)) - { - if (m_cdmBackend->generateRequest(m_rialtoSessionId, dataType, initData)) - { - m_log << info << "Successfully generated the request for the session"; - initializeCdmKeySessionId(); - return true; - } - else - { - m_log << error << "Failed to request for the session. Got drm error " << getLastDrmError(); - } - } - - return false; -} - -bool OpenCDMSessionPrivate::loadSession() -{ - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return false; - } - - if (-1 != m_rialtoSessionId) - { - if (m_cdmBackend->loadSession(m_rialtoSessionId)) - { - m_log << info << "Successfully loaded the session"; - return true; - } - else - { - m_log << error << "Failed to load the session. Got drm error " << getLastDrmError(); - } - } - return false; -} - -bool OpenCDMSessionPrivate::updateSession(const std::vector &license) -{ - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return false; - } - - if (-1 != m_rialtoSessionId) - { - if (m_cdmBackend->updateSession(m_rialtoSessionId, license)) - { - m_log << info << "Successfully updated the session"; - return true; - } - else - { - m_log << error << "Failed to update the session. Got drm error " << getLastDrmError(); - } - } - - return false; -} - -bool OpenCDMSessionPrivate::getChallengeData(std::vector &challengeData) -{ - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return false; - } - if ((m_initDataType != firebolt::rialto::InitDataType::UNKNOWN) && (-1 != m_rialtoSessionId)) - { - if (m_cdmBackend->generateRequest(m_rialtoSessionId, m_initDataType, m_initData)) - { - m_log << info << "Successfully generated the request for the session"; - initializeCdmKeySessionId(); - } - else - { - m_log << error << "Failed to request for the session. Got drm error " << getLastDrmError(); - return false; - } - } - else - { - return false; - } - std::unique_lock lock{m_mutex}; - m_challengeCv.wait_for(lock, std::chrono::seconds{1}, [this]() { return !m_challengeData.empty(); }); - challengeData = m_challengeData; - return !challengeData.empty(); -} - -void OpenCDMSessionPrivate::addProtectionMeta(GstBuffer *buffer, GstBuffer *subSample, const uint32_t subSampleCount, - GstBuffer *IV, GstBuffer *keyID, uint32_t initWithLast15) -{ - // Set key for Playready - GstBuffer *keyToApply = keyID; - bool shouldReleaseKey{false}; - if (keyID && 0 == gst_buffer_get_size(keyID) && !m_playreadyKeyId.empty()) - { - keyToApply = gst_buffer_new_allocate(nullptr, m_playreadyKeyId.size(), nullptr); - gst_buffer_fill(keyToApply, 0, m_playreadyKeyId.data(), m_playreadyKeyId.size()); - shouldReleaseKey = true; - } - - GstStructure *info = gst_structure_new("application/x-cenc", "encrypted", G_TYPE_BOOLEAN, TRUE, "mks_id", - G_TYPE_INT, m_rialtoSessionId, "kid", GST_TYPE_BUFFER, keyToApply, "iv_size", - G_TYPE_UINT, gst_buffer_get_size(IV), "iv", GST_TYPE_BUFFER, IV, - "subsample_count", G_TYPE_UINT, subSampleCount, "subsamples", GST_TYPE_BUFFER, - subSample, "encryption_scheme", G_TYPE_UINT, 0, // AES Counter - "init_with_last_15", G_TYPE_UINT, initWithLast15, NULL); - - GstProtectionMeta *protectionMeta = reinterpret_cast(gst_buffer_get_protection_meta(buffer)); - if (protectionMeta && protectionMeta->info) - { - const char *cipherModeBuf = gst_structure_get_string(protectionMeta->info, "cipher-mode"); - if (cipherModeBuf) - { - GST_INFO("Copy cipher mode [%s] and crypt/skipt byte blocks to protection metadata.", cipherModeBuf); - gst_structure_set(info, "cipher-mode", G_TYPE_STRING, cipherModeBuf, NULL); - - uint32_t patternCryptoBlocks = 0; - uint32_t patternClearBlocks = 0; - - if (gst_structure_get_uint(protectionMeta->info, "crypt_byte_block", &patternCryptoBlocks)) - { - gst_structure_set(info, "crypt_byte_block", G_TYPE_UINT, patternCryptoBlocks, NULL); - } - - if (gst_structure_get_uint(protectionMeta->info, "skip_byte_block", &patternClearBlocks)) - { - gst_structure_set(info, "skip_byte_block", G_TYPE_UINT, patternClearBlocks, NULL); - } - } - } - - rialto_mse_add_protection_metadata(buffer, info); - - if (shouldReleaseKey) - { - gst_buffer_unref(keyToApply); - } -} - -bool OpenCDMSessionPrivate::addProtectionMeta(GstBuffer *buffer) -{ - GstProtectionMeta *protectionMeta = reinterpret_cast(gst_buffer_get_protection_meta(buffer)); - if (!protectionMeta) - { - m_log << debug << "No protection meta added to the buffer"; - return false; - } - - GstStructure *info = gst_structure_copy(protectionMeta->info); - gst_structure_set(info, "mks_id", G_TYPE_INT, m_rialtoSessionId, NULL); - - if (!gst_structure_has_field_typed(info, "encrypted", G_TYPE_BOOLEAN)) - { - // Set encrypted - gst_structure_set(info, "encrypted", G_TYPE_BOOLEAN, TRUE, NULL); - } - - if (gst_structure_has_field_typed(info, "iv", GST_TYPE_BUFFER) && - !gst_structure_has_field_typed(info, "iv_size", G_TYPE_UINT)) - { - const GValue *value = gst_structure_get_value(info, "iv"); - if (value) - { - GstBuffer *ivBuffer = gst_value_get_buffer(value); - // Set iv size - gst_structure_set(info, "iv_size", G_TYPE_UINT, gst_buffer_get_size(ivBuffer), NULL); - } - } - - if (!gst_structure_has_field_typed(info, "encryption_scheme", G_TYPE_UINT)) - { - // Not used but required - gst_structure_set(info, "encryption_scheme", G_TYPE_UINT, 0, NULL); - } - - // Set key for Playready - if (!m_playreadyKeyId.empty()) - { - GstBuffer *keyID = gst_buffer_new_allocate(nullptr, m_playreadyKeyId.size(), nullptr); - gst_buffer_fill(keyID, 0, m_playreadyKeyId.data(), m_playreadyKeyId.size()); - gst_structure_set(info, "kid", GST_TYPE_BUFFER, keyID, NULL); - gst_buffer_unref(keyID); - } - - rialto_mse_add_protection_metadata(buffer, info); - - return true; -} - -bool OpenCDMSessionPrivate::closeSession() -{ - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return false; - } - - if (-1 != m_rialtoSessionId) - { - if (m_cdmBackend->closeKeySession(m_rialtoSessionId)) - { - m_log << info << "Successfully closed the session"; - m_messageDispatcherClient.reset(); - m_challengeData.clear(); - m_keyStatuses.clear(); - return true; - } - else - { - m_log << warn << "Failed to close the session."; - } - } - - return false; -} - -bool OpenCDMSessionPrivate::removeSession() -{ - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return false; - } - - if (-1 != m_rialtoSessionId) - { - if (m_cdmBackend->removeKeySession(m_rialtoSessionId)) - { - m_log << info << "Successfully removed the session"; - return true; - } - else - { - m_log << warn << "Failed to remove the session."; - } - } - - return false; -} - -void OpenCDMSessionPrivate::releaseSession() -{ - if (-1 != m_rialtoSessionId) - { - if (m_cdmBackend->releaseKeySession(m_rialtoSessionId)) - { - m_log << info << "Successfully released the session"; - } - else - { - m_log << warn << "Failed to release the session."; - } - } -} - -bool OpenCDMSessionPrivate::containsKey(const std::vector &keyId) -{ - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return false; - } - - if (-1 != m_rialtoSessionId) - { - return m_cdmBackend->containsKey(m_rialtoSessionId, keyId); - } - return false; -} - -bool OpenCDMSessionPrivate::setDrmHeader(const std::vector &drmHeader) -{ - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return false; - } - - if (-1 != m_rialtoSessionId) - { - return m_cdmBackend->setDrmHeader(m_rialtoSessionId, drmHeader); - } - return false; -} - -bool OpenCDMSessionPrivate::selectKeyId(const std::vector &keyId) -{ - m_log << debug << "Playready key selected."; - m_playreadyKeyId = keyId; - return true; -} - -void OpenCDMSessionPrivate::onLicenseRequest(int32_t keySessionId, - const std::vector &licenseRequestMessage, - const std::string &url) -{ - if (keySessionId == m_rialtoSessionId) - { - updateChallenge(licenseRequestMessage); - - if ((m_callbacks) && (m_callbacks->process_challenge_callback)) - { - m_callbacks->process_challenge_callback(this, m_context, url.c_str(), licenseRequestMessage.data(), - licenseRequestMessage.size()); - } - } -} - -void OpenCDMSessionPrivate::onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) -{ - if (keySessionId == m_rialtoSessionId) - { - updateChallenge(licenseRenewalMessage); - - if ((m_callbacks) && (m_callbacks->process_challenge_callback)) - { - m_callbacks->process_challenge_callback(this, m_context, "" /*URL*/, licenseRenewalMessage.data(), - licenseRenewalMessage.size()); - } - } -} - -void OpenCDMSessionPrivate::updateChallenge(const std::vector &challenge) -{ - std::unique_lock lock{m_mutex}; - m_challengeData = challenge; - m_challengeCv.notify_one(); -} - -void OpenCDMSessionPrivate::onKeyStatusesChanged(int32_t keySessionId, - const firebolt::rialto::KeyStatusVector &keyStatuses) -{ - if ((keySessionId == m_rialtoSessionId) && (m_callbacks) && (m_callbacks->key_update_callback)) - { - for (const std::pair, firebolt::rialto::KeyStatus> &keyStatus : keyStatuses) - { - // Update internal key statuses - m_keyStatuses[keyStatus.first] = keyStatus.second; - - const std::vector &key = keyStatus.first; - m_callbacks->key_update_callback(this, m_context, key.data(), key.size()); - } - - if (m_callbacks->keys_updated_callback) - { - m_callbacks->keys_updated_callback(this, m_context); - } - } -} - -KeyStatus OpenCDMSessionPrivate::status(const std::vector &key) const -{ - auto it = m_keyStatuses.find(key); - if (it != m_keyStatuses.end()) - { - return convertKeyStatus(it->second); - } - return KeyStatus::InternalError; -} - -const std::string &OpenCDMSessionPrivate::getSessionId() const -{ - return m_cdmKeySessionId; -} - -void OpenCDMSessionPrivate::initializeCdmKeySessionId() -{ - bool result{false}; - - if (-1 != m_rialtoSessionId) - { - result = m_cdmBackend->getCdmKeySessionId(m_rialtoSessionId, m_cdmKeySessionId); - } - if (!result) - { - m_cdmKeySessionId = kDefaultSessionId; - } -} - -uint32_t OpenCDMSessionPrivate::getLastDrmError() const -{ - uint32_t err = 0; - if (!m_cdmBackend) - { - m_log << error << "Cdm is NULL or not initialized"; - return -1; - } - - (void)m_cdmBackend->getLastDrmError(m_rialtoSessionId, err); - - return err; -} - -firebolt::rialto::KeySessionType OpenCDMSessionPrivate::getRialtoSessionType(const LicenseType licenseType) -{ - switch (licenseType) - { - case Temporary: - return firebolt::rialto::KeySessionType::TEMPORARY; - case PersistentUsageRecord: /// TODO: Rialto's equivalent?? - return firebolt::rialto::KeySessionType::UNKNOWN; - case PersistentLicense: - return firebolt::rialto::KeySessionType::PERSISTENT_LICENCE; - default: - return firebolt::rialto::KeySessionType::UNKNOWN; - } -} - -firebolt::rialto::InitDataType OpenCDMSessionPrivate::getRialtoInitDataType(const std::string &type) -{ - firebolt::rialto::InitDataType initDataType = firebolt::rialto::InitDataType::UNKNOWN; - - if (type == "cenc") - { - initDataType = firebolt::rialto::InitDataType::CENC; - } - else if (type == "webm") - { - initDataType = firebolt::rialto::InitDataType::WEBM; - } - else if (type == "drmheader") - { - initDataType = firebolt::rialto::InitDataType::DRMHEADER; - } - - return initDataType; -} diff --git a/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp b/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp deleted file mode 100644 index 801a52418..000000000 --- a/middleware/rialto-ocdm/source/OpenCDMSystemPrivate.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2023 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "OpenCDMSystemPrivate.h" -#include "ActiveSessions.h" -#include "IMediaKeys.h" -#include - -OpenCDMSystem *createSystem(const char system[], const std::string &metadata) -{ - const std::string kKeySystem{system}; - auto messageDispatcher{std::make_shared()}; - auto cdmBackend{std::make_shared(kKeySystem, messageDispatcher, - firebolt::rialto::IMediaKeysFactory::createFactory())}; - return new OpenCDMSystemPrivate(kKeySystem, metadata, messageDispatcher, cdmBackend); -} - -OpenCDMSystemPrivate::OpenCDMSystemPrivate(const std::string &system, const std::string &metadata, - const std::shared_ptr &messageDispatcher, - const std::shared_ptr &cdmBackend) - : m_log{"OpenCDMSystemPrivate"}, m_keySystem(system), m_metadata(metadata), - m_control{firebolt::rialto::IControlFactory::createFactory()->createControl()}, - m_messageDispatcher{messageDispatcher}, m_cdmBackend{cdmBackend} -{ - m_log << debug << "constructed: " << static_cast(this); - if (!m_control || !m_cdmBackend) - { - return; - } - firebolt::rialto::ApplicationState initialState{firebolt::rialto::ApplicationState::UNKNOWN}; - m_control->registerClient(m_cdmBackend, initialState); - m_cdmBackend->initialize(initialState); -} - -OpenCDMSystemPrivate::~OpenCDMSystemPrivate() -{ - m_log << debug << "destructed: " << static_cast(this); -} - -const std::string &OpenCDMSystemPrivate::keySystem() const -{ - return m_keySystem; -} - -const std::string &OpenCDMSystemPrivate::metadata() const -{ - return m_metadata; -} - -OpenCDMSession *OpenCDMSystemPrivate::createSession(const LicenseType licenseType, OpenCDMSessionCallbacks *callbacks, - void *userData, const std::string &initDataType, - const std::vector &initData) const -{ - return ActiveSessions::instance().create(m_cdmBackend, m_messageDispatcher, licenseType, callbacks, userData, - initDataType, initData); -} - -bool OpenCDMSystemPrivate::getDrmTime(uint64_t &drmTime) const -{ - if (!m_cdmBackend) - { - return false; - } - return m_cdmBackend->getDrmTime(drmTime); -} - -bool OpenCDMSystemPrivate::getLdlSessionsLimit(uint32_t &ldlLimit) const -{ - if (!m_cdmBackend) - { - return false; - } - return m_cdmBackend->getLdlSessionsLimit(ldlLimit); -} - -bool OpenCDMSystemPrivate::getKeyStoreHash(std::vector &keyStoreHash) const -{ - if (!m_cdmBackend) - { - return false; - } - return m_cdmBackend->getKeyStoreHash(keyStoreHash); -} - -bool OpenCDMSystemPrivate::getDrmStoreHash(std::vector &drmStoreHash) const -{ - if (!m_cdmBackend) - { - return false; - } - return m_cdmBackend->getDrmStoreHash(drmStoreHash); -} - -bool OpenCDMSystemPrivate::deleteKeyStore() const -{ - if (!m_cdmBackend) - { - return false; - } - return m_cdmBackend->deleteKeyStore(); -} - -bool OpenCDMSystemPrivate::deleteDrmStore() const -{ - if (!m_cdmBackend) - { - return false; - } - return m_cdmBackend->deleteDrmStore(); -} - -bool OpenCDMSystemPrivate::getMetricSystemData(std::vector &buffer) const -{ - if (!m_cdmBackend) - { - return false; - } - - return m_cdmBackend->getMetricSystemData(buffer); -} diff --git a/middleware/rialto-ocdm/source/RialtoFactoryStubs.cpp b/middleware/rialto-ocdm/source/RialtoFactoryStubs.cpp deleted file mode 100644 index 3c0a1804e..000000000 --- a/middleware/rialto-ocdm/source/RialtoFactoryStubs.cpp +++ /dev/null @@ -1,72 +0,0 @@ - -#include "IControl.h" -#include "IMediaKeys.h" -#include -#include -#include - -namespace firebolt::rialto -{ -// ---- IControl stub ---- - -class ControlFactoryStub : public IControlFactory -{ -public: - std::shared_ptr createControl() const override - { - struct ControlStub : public IControl - { - bool registerClient(std::weak_ptr /*client*/, ApplicationState &appState) override - { - // Leave application state UNKNOWN for stub - appState = ApplicationState::UNKNOWN; - return true; // pretend success - } - }; - return std::make_shared(); - } -}; - -std::shared_ptr IControlFactory::createFactory() -{ - return std::make_shared(); -} - -// ---- IMediaKeys stub ---- -class MediaKeysFactoryStub : public IMediaKeysFactory -{ -public: - std::unique_ptr createMediaKeys(const std::string & /*keySystem*/) const override - { - struct MediaKeysStub : public IMediaKeys - { - MediaKeyErrorStatus selectKeyId(int32_t /*keySessionId*/, const std::vector &/*keyId*/) override { return MediaKeyErrorStatus::FAIL; } - bool containsKey(int32_t /*keySessionId*/, const std::vector &/*keyId*/) override { return false; } - MediaKeyErrorStatus createKeySession(KeySessionType /*sessionType*/, std::weak_ptr /*client*/, bool /*isLDL*/, int32_t &keySessionId) override { keySessionId = -1; return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus generateRequest(int32_t /*keySessionId*/, InitDataType /*initDataType*/, const std::vector &/*initData*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus loadSession(int32_t /*keySessionId*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus updateSession(int32_t /*keySessionId*/, const std::vector &/*responseData*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus setDrmHeader(int32_t /*keySessionId*/, const std::vector &/*requestData*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus closeKeySession(int32_t /*keySessionId*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus removeKeySession(int32_t /*keySessionId*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus deleteDrmStore() override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus deleteKeyStore() override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus getDrmStoreHash(std::vector &/*drmStoreHash*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus getKeyStoreHash(std::vector &/*keyStoreHash*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) override { ldlLimit = 0; return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus getLastDrmError(int32_t /*keySessionId*/, uint32_t &errorCode) override { errorCode = 0; return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) override { drmTime = 0; return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus getCdmKeySessionId(int32_t /*keySessionId*/, std::string &cdmKeySessionId) override { cdmKeySessionId.clear(); return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus releaseKeySession(int32_t /*keySessionId*/) override { return MediaKeyErrorStatus::FAIL; } - MediaKeyErrorStatus getMetricSystemData(std::vector &/*buffer*/) override { return MediaKeyErrorStatus::FAIL; } - }; - return std::make_unique(); - } -}; - -std::shared_ptr IMediaKeysFactory::createFactory() -{ - return std::make_shared(); -} - -} // namespace firebolt::rialto diff --git a/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp b/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp deleted file mode 100644 index c6a02a204..000000000 --- a/middleware/rialto-ocdm/source/RialtoGStreamerEMEProtectionMetadata.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2024 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "RialtoGStreamerEMEProtectionMetadata.h" -#include - -// NOLINTNEXTLINE(build/function_format) -static gboolean rialto_eme_protection_metadata_init(GstMeta *meta, gpointer params, GstBuffer *buffer) -{ - // NOLINTNEXTLINE(readability/casting) - GstRialtoProtectionMetadata *emeta = reinterpret_cast(meta); - - emeta->info = NULL; - - return TRUE; -} - -// NOLINTNEXTLINE(build/function_format) -static gboolean rialto_eme_protection_metadata_free(GstMeta *meta, GstBuffer *buffer) -{ - // NOLINTNEXTLINE(readability/casting) - GstRialtoProtectionMetadata *emeta = reinterpret_cast(meta); - - if (emeta->info) - { - gst_structure_free(emeta->info); - emeta->info = nullptr; - } - - return TRUE; -} - -// NOLINTNEXTLINE(build/function_format) -GST_EXPORT GType rialto_eme_protection_metadata_get_type() -{ - static GType g_type{0}; - static const gchar *api_tags[] = {"rialto", "protection", NULL}; - - if (g_once_init_enter(&g_type)) - { - GType _type = gst_meta_api_type_register("GstRialtoProtectionMetadataAPI", api_tags); - g_once_init_leave(&g_type, _type); - } - return g_type; -} - -// NOLINTNEXTLINE(build/function_format) -const GstMetaInfo *rialto_mse_protection_metadata_get_info() -{ - static const GstMetaInfo *metainfo = NULL; - if (g_once_init_enter(&metainfo)) - { - const GstMetaInfo *gstMeta = - gst_meta_register(GST_RIALTO_PROTECTION_METADATA_GET_TYPE, "GstRialtoProtectionMetadata", - sizeof(GstRialtoProtectionMetadata), - (GstMetaInitFunction)rialto_eme_protection_metadata_init, - (GstMetaFreeFunction)rialto_eme_protection_metadata_free, (GstMetaTransformFunction)NULL); - - g_once_init_leave(&metainfo, gstMeta); - } - return metainfo; -} - -// NOLINTNEXTLINE(build/function_format) -GstRialtoProtectionMetadata *rialto_mse_add_protection_metadata(GstBuffer *gstBuffer, GstStructure *info) -{ - GstRialtoProtectionMetadata *metadata = reinterpret_cast( - gst_buffer_add_meta(gstBuffer, GST_RIALTO_PROTECTION_METADATA_INFO, NULL)); - metadata->info = info; - return metadata; -} diff --git a/middleware/rialto-ocdm/source/open_cdm.cpp b/middleware/rialto-ocdm/source/open_cdm.cpp deleted file mode 100644 index f2422796b..000000000 --- a/middleware/rialto-ocdm/source/open_cdm.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "ActiveSessions.h" -#include "Logger.h" -#include "MediaKeysCapabilitiesBackend.h" -#include "OpenCDMSession.h" -#include "OpenCDMSystemPrivate.h" -#include -#include - -namespace -{ -const Logger kLog{"open_cdm"}; - -bool isNetflixPlayreadyKeysystem(const std::string &keySystem) -{ - return keySystem.find("netflix") != std::string::npos; -} -} // namespace - -OpenCDMSystem *opencdm_create_system(const char keySystem[]) -{ - kLog << debug << __func__; - - const char kSrcRev[] = "NULL"; - const char kTags[] = "NULL"; - - if (std::strlen(kSrcRev) > 0) - { - if (std::strlen(kTags) > 0) - { - kLog << mil << "Release Tag(s): " << kTags << " (Commit ID: " << kSrcRev << ")"; - } - else - { - kLog << mil << "Release Tag(s): No Release Tags!" << " (Commit ID: " << kSrcRev << ")"; - } - } - else - { - kLog << warn << "Failed to get git commit ID!"; - } - - OpenCDMSystem *result = nullptr; - opencdm_create_system_extended(keySystem, &result); - - return result; -} - -OpenCDMError opencdm_create_system_extended(const char keySystem[], struct OpenCDMSystem **system) -{ - kLog << debug << __func__; - assert(system != nullptr); - - *system = createSystem(keySystem, ""); - - return ERROR_NONE; -} - -OpenCDMError opencdm_destruct_system(struct OpenCDMSystem *system) -{ - kLog << debug << __func__; - if (system) - { - delete system; - } - - return ERROR_NONE; -} - -OpenCDMError opencdm_is_type_supported(const char keySystem[], const char mimeType[]) -{ - kLog << debug << __func__; - return MediaKeysCapabilitiesBackend::instance().supportsKeySystem(std::string(keySystem)); -} - -OpenCDMError opencdm_system_get_metadata(struct OpenCDMSystem *system, char metadata[], uint16_t *metadataSize) -{ - kLog << debug << __func__; - if (!system || !metadataSize) - { - kLog << error << __func__ << ": System or metadataSize is NULL"; - return ERROR_FAIL; - } - *metadataSize = 0; - return ERROR_NONE; -} - -OpenCDMError opencdm_system_get_version(struct OpenCDMSystem *system, char versionStr[]) -{ - kLog << debug << __func__; - if (!system || !versionStr) - { - kLog << error << __func__ << ": System or versionStr is NULL"; - return ERROR_FAIL; - } - std::string version; - if (!MediaKeysCapabilitiesBackend::instance().getSupportedKeySystemVersion(system->keySystem(), version)) - { - return ERROR_FAIL; - } - - const size_t MAX_LEN = 64; - snprintf(versionStr, MAX_LEN, "%s", version.c_str()); - - return ERROR_NONE; -} - -OpenCDMError opencdm_system_get_drm_time(struct OpenCDMSystem *system, uint64_t *time) -{ - kLog << debug << __func__; - if (!time || !system) - { - kLog << error << "Ptr is null"; - return ERROR_FAIL; - } - if (!system->getDrmTime(*time)) - { - kLog << error << "Failed to get DRM Time"; - return ERROR_FAIL; - } - return ERROR_NONE; -} - -struct OpenCDMSession *opencdm_get_system_session(struct OpenCDMSystem *system, const uint8_t keyId[], - const uint8_t length, const uint32_t waitTime) -{ - kLog << debug << __func__; - return ActiveSessions::instance().get(std::vector(keyId, keyId + length)); -} - -OpenCDMError opencdm_system_set_server_certificate(struct OpenCDMSystem *system, const uint8_t serverCertificate[], - const uint16_t serverCertificateLength) -{ - kLog << debug << __func__; - return ERROR_NONE; -} - -struct OpenCDMSession *opencdm_get_session(const uint8_t keyId[], const uint8_t length, const uint32_t waitTime) -{ - kLog << debug << __func__; - return opencdm_get_system_session(nullptr, keyId, length, waitTime); -} - -OpenCDMError opencdm_construct_session(struct OpenCDMSystem *system, const LicenseType licenseType, - const char initDataType[], const uint8_t initData[], - const uint16_t initDataLength, const uint8_t CDMData[], - const uint16_t CDMDataLength, OpenCDMSessionCallbacks *callbacks, void *userData, - struct OpenCDMSession **session) -{ - kLog << debug << __func__; - if (!system) - { - kLog << error << "System is NULL or not initialized"; - return ERROR_FAIL; - } - std::string initializationDataType(initDataType); - std::vector initDataVec(reinterpret_cast(initData), - reinterpret_cast(initData) + initDataLength); - - OpenCDMSession *newSession = - system->createSession(licenseType, callbacks, userData, initializationDataType, initDataVec); - - if (!newSession) - { - return ERROR_INVALID_SESSION; - } - - if (!isNetflixPlayreadyKeysystem(system->keySystem())) - { - if (!newSession->initialize()) - { - kLog << error << "Failed to create session"; - ActiveSessions::instance().remove(newSession); - return ERROR_FAIL; - } - std::vector cdmDataVec(reinterpret_cast(CDMData), - reinterpret_cast(CDMData) + CDMDataLength); - - if (!newSession->generateRequest(initializationDataType, initDataVec, cdmDataVec /*not used yet*/)) - { - kLog << error << "Failed to generate request"; - - opencdm_session_close(newSession); - opencdm_destruct_session(newSession); - return ERROR_FAIL; - } - } - - *session = newSession; - - return ERROR_NONE; -} - -OpenCDMError opencdm_destruct_session(struct OpenCDMSession *session) -{ - kLog << debug << __func__; - if (session) - { - ActiveSessions::instance().remove(session); - return ERROR_NONE; - } - return ERROR_INVALID_SESSION; -} - -OpenCDMError opencdm_session_load(struct OpenCDMSession *session) -{ - kLog << debug << __func__; - OpenCDMError result = ERROR_INVALID_SESSION; - if (session) - { - if (session->loadSession()) - { - result = ERROR_NONE; - } - else - { - kLog << error << "Failed to load the session"; - result = ERROR_FAIL; - } - } - - return result; -} - -OpenCDMError opencdm_session_metadata(const struct OpenCDMSession *session, char metadata[], uint16_t *metadataSize) -{ - kLog << debug << __func__; - if (!session || !metadataSize) - { - kLog << error << __func__ << ": session or metadata size is null"; - return ERROR_FAIL; - } - *metadataSize = 0; - return ERROR_NONE; -} - -const char *opencdm_session_id(const struct OpenCDMSession *session) -{ - kLog << debug << __func__; - if (!session) - { - return nullptr; - } - return session->getSessionId().c_str(); -} - -const char *opencdm_session_buffer_id(const struct OpenCDMSession *session) -{ - kLog << debug << __func__; - return nullptr; -} - -uint32_t opencdm_session_has_key_id(struct OpenCDMSession *session, const uint8_t length, const uint8_t keyId[]) -{ - kLog << debug << __func__; - if (!session) - { - kLog << error << "Failed to check key id"; - return 0; - } - std::vector key(keyId, keyId + length); - return static_cast(session->containsKey(key)); -} - -KeyStatus opencdm_session_status(const struct OpenCDMSession *session, const uint8_t keyId[], uint8_t length) -{ - kLog << debug << __func__; - if (session && keyId && 0 != length) - { - std::vector key(keyId, keyId + length); - return session->status(key); - } - - return InternalError; -} - -uint32_t opencdm_session_error(const struct OpenCDMSession *session, const uint8_t keyId[], uint8_t length) -{ - kLog << warn << __func__ << " NOT IMPLEMENTED YET"; - return 0; -} - -OpenCDMError opencdm_session_system_error(const struct OpenCDMSession *session) -{ - kLog << debug << __func__; - if (!session) - { - kLog << error << __func__ << ": Failed to get session system error - session is null"; - return ERROR_FAIL; - } - uint32_t err = session->getLastDrmError(); - // Rialto doesn't implement it yet - switch (err) - { - default: - return ERROR_NONE; - } -} - -OpenCDMError opencdm_session_update(struct OpenCDMSession *session, const uint8_t keyMessage[], uint16_t keyLength) -{ - kLog << debug << __func__; - if (!session) - { - kLog << error << __func__ << ": Session is NULL"; - return ERROR_INVALID_SESSION; - } - if (!keyMessage || keyLength == 0) - { - kLog << error << __func__ << ": keyMessage is empty"; - return ERROR_FAIL; - } - std::vector license(keyMessage, keyMessage + keyLength); - if (!session->updateSession(license)) - { - kLog << error << "Failed to update the session"; - return ERROR_FAIL; - } - - return ERROR_NONE; -} - -OpenCDMError opencdm_session_remove(struct OpenCDMSession *session) -{ - kLog << debug << __func__; - OpenCDMError result = ERROR_INVALID_SESSION; - if (session) - { - if (session->removeSession()) - { - result = ERROR_NONE; - } - else - { - kLog << error << "Failed to remove the key session"; - result = ERROR_FAIL; - } - } - - return result; -} - -OpenCDMError opencdm_session_resetoutputprotection(struct OpenCDMSession *session) -{ - kLog << warn << __func__ << " NOT IMPLEMENTED YET"; - return ERROR_NONE; -} - -OpenCDMError opencdm_session_set_parameter(struct OpenCDMSession *session, const std::string &name, - const std::string &value) -{ - kLog << warn << __func__ << " NOT IMPLEMENTED YET"; - return ERROR_NONE; -} - -OpenCDMError opencdm_session_close(struct OpenCDMSession *session) -{ - kLog << debug << __func__; - OpenCDMError result = ERROR_INVALID_SESSION; - if (session) - { - if (session->closeSession()) - { - result = ERROR_NONE; - } - else - { - kLog << error << "Failed to close the key session"; - result = ERROR_FAIL; - } - } - - return result; -} - -OpenCDMBool opencdm_system_supports_server_certificate(struct OpenCDMSystem *system) -{ - kLog << debug << __func__; - if (MediaKeysCapabilitiesBackend::instance().isServerCertificateSupported(system->keySystem())) - { - return OpenCDMBool::OPENCDM_BOOL_TRUE; - } - return OpenCDMBool::OPENCDM_BOOL_FALSE; -} - -OpenCDMError opencdm_session_decrypt(struct OpenCDMSession *session, uint8_t encrypted[], - const uint32_t encryptedLength, const EncryptionScheme encScheme, - const EncryptionPattern pattern, const uint8_t *IV, uint16_t IVLength, - const uint8_t *keyId, const uint16_t keyIdLength, uint32_t initWithLast15) -{ - kLog << warn << __func__ << " not implemented"; - return ERROR_FAIL; -} - -OpenCDMError opencdm_get_metric_system_data(struct OpenCDMSystem *system, uint32_t *bufferLength, uint8_t *buffer) -{ - kLog << debug << __func__; - if (!system) - { - kLog << error << "System ptr is null"; - return ERROR_FAIL; - } - - if (!bufferLength) - { - kLog << error << "Buffer length ptr is null"; - return ERROR_FAIL; - } - - if (!buffer) - { - kLog << error << "Buffer ptr is null"; - return ERROR_FAIL; - } - - std::vector bufferVec; - if (!system->getMetricSystemData(bufferVec)) - { - kLog << error << "Failed to get metric system data"; - return ERROR_FAIL; - } - - if (*bufferLength < bufferVec.size()) - { - kLog << error << "Buffer is too small - return size " << bufferVec.size() << " does not fit in buffer of size " - << *bufferLength; - return ERROR_BUFFER_TOO_SMALL; - } - - std::memcpy(buffer, bufferVec.data(), bufferVec.size()); - *bufferLength = bufferVec.size(); - return ERROR_NONE; -} diff --git a/middleware/rialto-ocdm/source/open_cdm_adapter.cpp b/middleware/rialto-ocdm/source/open_cdm_adapter.cpp deleted file mode 100644 index 7916467a1..000000000 --- a/middleware/rialto-ocdm/source/open_cdm_adapter.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Logger.h" -#include "OpenCDMSession.h" -#include - -namespace -{ -const Logger kLog{"open_cdm_adapter"}; -} // namespace - -OpenCDMError opencdm_gstreamer_session_decrypt_ex(struct OpenCDMSession *session, GstBuffer *buffer, - GstBuffer *subSample, const uint32_t subSampleCount, GstBuffer *IV, - GstBuffer *keyID, uint32_t initWithLast15, GstCaps *caps) -{ - if (nullptr == session) - { - kLog << error << "Failed to decrypt - session is NULL"; - return ERROR_FAIL; - } - session->addProtectionMeta(buffer, subSample, subSampleCount, IV, keyID, initWithLast15); - return ERROR_NONE; -} - -OpenCDMError opencdm_gstreamer_session_decrypt(struct OpenCDMSession *session, GstBuffer *buffer, GstBuffer *subSample, - const uint32_t subSampleCount, GstBuffer *IV, GstBuffer *keyID, - uint32_t initWithLast15) -{ - return opencdm_gstreamer_session_decrypt_ex(session, buffer, subSample, subSampleCount, IV, keyID, initWithLast15, - nullptr); -} - -OpenCDMError opencdm_gstreamer_session_decrypt_buffer(struct OpenCDMSession *session, GstBuffer *buffer, GstCaps *caps) -{ - if (nullptr == session) - { - kLog << error << "Failed to decrypt - session is NULL"; - return ERROR_FAIL; - } - - if (!session->addProtectionMeta(buffer)) - { - kLog << error << "Failed to decrypt - could not append protection meta"; - return ERROR_FAIL; - } - - return ERROR_NONE; -} - -OpenCDMError opencdm_gstreamer_transform_caps(GstCaps **caps) -{ - return ERROR_NONE; -} diff --git a/middleware/rialto-ocdm/source/open_cdm_ext.cpp b/middleware/rialto-ocdm/source/open_cdm_ext.cpp deleted file mode 100644 index f59d6a87d..000000000 --- a/middleware/rialto-ocdm/source/open_cdm_ext.cpp +++ /dev/null @@ -1,285 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2022 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Logger.h" -#include "OpenCDMSession.h" -#include "OpenCDMSystem.h" -#include - -namespace -{ -const Logger kLog{"open_cdm_ext"}; -} // namespace - -OpenCDMError opencdm_system_ext_get_ldl_session_limit(struct OpenCDMSystem *system, uint32_t *ldlLimit) -{ - kLog << debug << __func__; - if (!system || !ldlLimit) - { - kLog << error << "Failed to get ldl session limit - System is NULL"; - return ERROR_FAIL; - } - - if (!system->getLdlSessionsLimit(*ldlLimit)) - { - kLog << error << "Failed to get LDL Session limit"; - return ERROR_FAIL; - } - return ERROR_NONE; -} - -uint32_t opencdm_system_ext_is_secure_stop_enabled(struct OpenCDMSystem *system) -{ - kLog << warn << "Secure stop not supported"; - return 0; -} - -OpenCDMError opencdm_system_ext_enable_secure_stop(struct OpenCDMSystem *system, uint32_t use) -{ - kLog << warn << "Secure stop not supported"; - return ERROR_FAIL; -} - -uint32_t opencdm_system_ext_reset_secure_stop(struct OpenCDMSystem *system) -{ - kLog << warn << "Reset secure stop not supported"; - return 0; -} - -OpenCDMError opencdm_system_ext_get_secure_stop_ids(struct OpenCDMSystem *system, uint8_t Ids[], uint16_t idsLength, - uint32_t *count) -{ - kLog << warn << "Failed to get secure stop ids - not supported"; - return ERROR_FAIL; -} - -OpenCDMError opencdm_system_ext_get_secure_stop(struct OpenCDMSystem *system, const uint8_t sessionID[], - uint32_t sessionIDLength, uint8_t rawData[], uint16_t *rawSize) -{ - kLog << warn << "Failed to get secure stop - not supported"; - return ERROR_FAIL; -} - -OpenCDMError opencdm_system_ext_commit_secure_stop(struct OpenCDMSystem *system, const uint8_t sessionID[], - uint32_t sessionIDLength, const uint8_t serverResponse[], - uint32_t serverResponseLength) -{ - kLog << warn << "Failed to commit secure stop - not supported"; - return ERROR_FAIL; -} - -OpenCDMError opencdm_get_key_store_hash_ext(struct OpenCDMSystem *system, uint8_t keyStoreHash[], - uint32_t keyStoreHashLength) -{ - kLog << debug << __func__; - if (!system || 0 == keyStoreHashLength) - { - kLog << error << "Failed to get key store hash - arguments are not valid"; - return ERROR_FAIL; - } - std::vector keyStoreHashVec; - if (!system->getKeyStoreHash(keyStoreHashVec)) - { - kLog << error << "Failed to get key store hash - operation failed"; - return ERROR_FAIL; - } - if (keyStoreHashVec.size() > keyStoreHashLength) - { - kLog << error << "Failed to get key store hash - return of size " << keyStoreHashVec.size() - << " does not fit in buffer of size " << keyStoreHashLength; - return ERROR_FAIL; - } - memcpy(keyStoreHash, keyStoreHashVec.data(), keyStoreHashVec.size()); - return ERROR_NONE; -} - -OpenCDMError opencdm_get_secure_store_hash_ext(struct OpenCDMSystem *system, uint8_t secureStoreHash[], - uint32_t secureStoreHashLength) -{ - kLog << debug << __func__; - if (!system || 0 == secureStoreHashLength) - { - kLog << error << "Failed to get secure store hash - arguments are not valid"; - return ERROR_FAIL; - } - std::vector secureStoreHashVec; - if (!system->getDrmStoreHash(secureStoreHashVec)) - { - kLog << error << "Failed to get secure store hash - operation failed"; - return ERROR_FAIL; - } - if (secureStoreHashVec.size() > secureStoreHashLength) - { - kLog << error << "Failed to get key store hash - return size " << secureStoreHashVec.size() - << " does not fit in buffer of size " << secureStoreHashLength; - return ERROR_FAIL; - } - memcpy(secureStoreHash, secureStoreHashVec.data(), secureStoreHashVec.size()); - return ERROR_NONE; -} - -OpenCDMError opencdm_delete_key_store(struct OpenCDMSystem *system) -{ - kLog << debug << __func__; - if (!system) - { - kLog << error << "Failed to delete key store - arguments are not valid"; - return ERROR_FAIL; - } - if (!system->deleteKeyStore()) - { - kLog << error << "Failed to delete key store - operation failed"; - return ERROR_FAIL; - } - return ERROR_NONE; -} - -OpenCDMError opencdm_delete_secure_store(struct OpenCDMSystem *system) -{ - kLog << debug << __func__; - if (!system) - { - kLog << error << "Failed to delete secure store - arguments are not valid"; - return ERROR_FAIL; - } - if (!system->deleteDrmStore()) - { - kLog << error << "Failed to delete secure store - operation failed"; - return ERROR_FAIL; - } - return ERROR_NONE; -} - -OpenCDMError opencdm_session_set_drm_header(struct OpenCDMSession *opencdmSession, const uint8_t drmHeader[], - uint32_t drmHeaderSize) -{ - kLog << debug << __func__; - if (nullptr == opencdmSession) - { - kLog << error << "Failed to set Drm Header - session is NULL"; - return ERROR_FAIL; - } - std::vector drmHeaderVec(drmHeader, drmHeader + drmHeaderSize); - if (!opencdmSession->setDrmHeader(drmHeaderVec)) - { - kLog << error << "Failed to set Drm Header - operation returned NOK status"; - return ERROR_FAIL; - } - return ERROR_NONE; -} - -OpenCDMError opencdm_session_get_challenge_data(struct OpenCDMSession *mOpenCDMSession, uint8_t *challenge, - uint32_t *challengeSize, uint32_t isLDL) -{ - kLog << debug << __func__; - if (nullptr == mOpenCDMSession || nullptr == challengeSize) - { - kLog << error << "Failed to get challenge data - arguments are not valid"; - return ERROR_FAIL; - } - if (!mOpenCDMSession->initialize(isLDL)) - { - kLog << error << "Failed to create session"; - return ERROR_FAIL; - } - std::vector challengeVec; - if (!mOpenCDMSession->getChallengeData(challengeVec)) - { - kLog << error << "Failed to get challenge data - operation returned NOK status"; - return ERROR_FAIL; - } - *challengeSize = challengeVec.size(); - if (nullptr != challenge) - { - memcpy(challenge, challengeVec.data(), challengeVec.size()); - } - return ERROR_NONE; -} - -OpenCDMError opencdm_session_cancel_challenge_data(struct OpenCDMSession *mOpenCDMSession) -{ - kLog << debug << __func__; - // MKS is destructed in opencdm_session_clean_decrypt_context - return ERROR_NONE; -} - -OpenCDMError opencdm_session_store_license_data(struct OpenCDMSession *openCDMSession, const uint8_t licenseData[], - uint32_t licenseDataSize, uint8_t *secureStopId) -{ - kLog << debug << __func__; - if (!openCDMSession) - { - kLog << error << "Failed to store license data - session is NULL"; - return ERROR_INVALID_SESSION; - } - if (!licenseData || 0 == licenseDataSize) - { - kLog << error << "Failed to store license data - data is null or empty"; - return ERROR_FAIL; - } - std::vector license(licenseData, licenseData + licenseDataSize); - - if (!openCDMSession->updateSession(license)) - { - kLog << error << "Failed to store license data - op failed"; - return ERROR_FAIL; - } - - return ERROR_NONE; -} - -OpenCDMError opencdm_session_select_key_id(struct OpenCDMSession *mOpenCDMSession, uint8_t keyLength, - const uint8_t keyId[]) -{ - kLog << debug << __func__; - if (!mOpenCDMSession || !keyId || 0 == keyLength) - { - kLog << error << "Failed to select key id - session or key is NULL"; - return ERROR_FAIL; - } - std::vector keyIdVec(keyId, keyId + keyLength); - if (!mOpenCDMSession->selectKeyId(keyIdVec)) - { - kLog << error << "Failed to select key id - operation returned NOK status"; - return ERROR_FAIL; - } - return ERROR_NONE; -} - -OpenCDMError opencdm_system_teardown(struct OpenCDMSystem *system) -{ - kLog << debug << __func__; - return ERROR_NONE; -} - -OpenCDMError opencdm_session_clean_decrypt_context(struct OpenCDMSession *mOpenCDMSession) -{ - kLog << debug << __func__; - if (!mOpenCDMSession) - { - kLog << error << "Failed to clean decrypt context - arguments are not valid"; - return ERROR_FAIL; - } - if (!mOpenCDMSession->closeSession()) - { - kLog << error << "Failed to close the session"; - return ERROR_FAIL; - } - return ERROR_NONE; -} diff --git a/rialto-master/media/public/include/ControlCommon.h b/rialto-master/media/public/include/ControlCommon.h deleted file mode 100644 index 133639fc4..000000000 --- a/rialto-master/media/public/include/ControlCommon.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_CONTROL_COMMON_H_ -#define FIREBOLT_RIALTO_CONTROL_COMMON_H_ - -/** - * @file ControlCommon.h - * - * The definition of the Control Common types - * - */ - -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief The application state. - */ -enum class ApplicationState -{ - UNKNOWN, - RUNNING, - INACTIVE -}; -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_CONTROL_COMMON_H_ diff --git a/rialto-master/media/public/include/IClientLogControl.h b/rialto-master/media/public/include/IClientLogControl.h deleted file mode 100644 index 311b7eb4d..000000000 --- a/rialto-master/media/public/include/IClientLogControl.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ -#define FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ - -/** - * @file IClientLogControl.h - * - * The definition of the IClientLogControl interface. - * - * Via this interface the logging of the Rialto Client can - * be redirected to a user specified call handler - */ - -#include -#include - -#include "ControlCommon.h" -#include "IClientLogHandler.h" -#include "IControlClient.h" - -namespace firebolt::rialto -{ -class IClientLogControl; - -/** - * @brief IClientLogControl factory class, returns a concrete implementation of IClientLogControl - */ -class IClientLogControlFactory -{ -public: - IClientLogControlFactory() = default; - virtual ~IClientLogControlFactory() = default; - - /** - * @brief Creates the IClientLogControlFactory - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IClientLogControl factory method, returns a concrete singleton implementation of IClientLogControl - * - * @retval the new IClientLogControl instance or null on error. - */ - virtual IClientLogControl &createClientLogControl() = 0; -}; - -/** - * @brief The definition of the IClientLogControl interface. - * - * This interface defines the public API for controlling Rialto client's - * log handling. This class is a singleton - * - */ -class IClientLogControl -{ -public: - IClientLogControl() = default; - virtual ~IClientLogControl() = default; - - IClientLogControl(const IClientLogControl &) = delete; - IClientLogControl &operator=(const IClientLogControl &) = delete; - IClientLogControl(IClientLogControl &&) = delete; - IClientLogControl &operator=(IClientLogControl &&) = delete; - - /** - * @brief Register a new log handler - * - * @param[in] handler : The user can pass in an object that will henceforth - * receive callbacks to it's log(...) method for rialto client log events. - * Please see IClientLogHandler for the parameters that log() must accept. - * To cancel callbacks then call this method again but pass a nullptr for - * the handler. - * @param[in] ignoreLogLevels : If true then the handler will receive ALL log level messages regardless of the - * currently configured log level - * - * @retval true if successful - */ - virtual bool registerLogHandler(const std::shared_ptr &handler, bool ignoreLogLevels) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_CLIENT_LOG_CONTROL_H_ diff --git a/rialto-master/media/public/include/IClientLogHandler.h b/rialto-master/media/public/include/IClientLogHandler.h deleted file mode 100644 index c93aad816..000000000 --- a/rialto-master/media/public/include/IClientLogHandler.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * @file ILogHandler.h - * - * This file comprises the class definition of ILogHandler. - * An interface, which provides API of custom server manager logging handler - */ - -#ifndef FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ -#define FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ - -/** - * @file IClientLogHandler.h - * - * The definition of the IClientLogHandler interface. - * - * This interface allows the user to define their own log handler for - * any messages generated by the rialto client library - */ - -#include - -namespace firebolt::rialto -{ -/** - * @brief IClientLogHandler allows the user to define their own log handler for - * any messages generated by the rialto client library - */ -class IClientLogHandler -{ -public: - IClientLogHandler() = default; - virtual ~IClientLogHandler() = default; - IClientLogHandler(const IClientLogHandler &) = delete; - IClientLogHandler &operator=(const IClientLogHandler &) = delete; - IClientLogHandler(IClientLogHandler &&) = delete; - IClientLogHandler &operator=(IClientLogHandler &&) = delete; - - /** - * @brief All possible log levels that could be used in the log callback - */ - - enum class Level - { - Fatal, - Error, - Warning, - Milestone, - Info, - Debug, - External - }; - - /** - * @brief A callback method for every log item generated by the rialto client library - * - * @param[in] level : The log level - * @param[in] file : The source code file where the log is defined - * @param[in] line : The line number within the file where the log is defined - * @param[in] function : The source code function within which the log is defined - * @param[in] message : The message of the log - */ - virtual void log(Level level, const std::string &file, int line, const std::string &function, - const std::string &message) = 0; -}; -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_CLIENT_LOG_HANDLER_H_ diff --git a/rialto-master/media/public/include/IControl.h b/rialto-master/media/public/include/IControl.h deleted file mode 100644 index 007bff7e9..000000000 --- a/rialto-master/media/public/include/IControl.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_CONTROL_H_ -#define FIREBOLT_RIALTO_I_CONTROL_H_ - -/** - * @file IControl.h - * - * The definition of the IControl interface. - * - * This interface defines the public API of Rialto for control of Rialto, - * including the IPC connection and shared memory. - */ - -#include -#include - -#include "ControlCommon.h" -#include "IControlClient.h" - -namespace firebolt::rialto -{ -class IControl; - -/** - * @brief IControl factory class, returns a concrete implementation of IControl - */ -class IControlFactory -{ -public: - IControlFactory() = default; - virtual ~IControlFactory() = default; - - /** - * @brief Creates a IControlFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IControl factory method, returns a concrete implementation of IControl - * - * @retval the new IControl instance or null on error. - */ - virtual std::shared_ptr createControl() const = 0; -}; - -/** - * @brief The definition of the IControl interface. - * - * This interface defines the public API for control of the ipc and shared memory. - * - */ -class IControl -{ -public: - IControl() = default; - virtual ~IControl() = default; - - IControl(const IControl &) = delete; - IControl &operator=(const IControl &) = delete; - IControl(IControl &&) = delete; - IControl &operator=(IControl &&) = delete; - - /** - * @brief Register new IControlClient. This method will hold a shared_ptr - * to the client until the destruction of the IControl object. - * At destruction the client will be unregistered and the - * shared_ptr will be released. - * - * @param[in] client : Client object for callbacks - * @param[out] appState : Current application state - * - * @retval true on success, false otherwise. - */ - virtual bool registerClient(std::weak_ptr client, ApplicationState &appState) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_CONTROL_H_ diff --git a/rialto-master/media/public/include/IControlClient.h b/rialto-master/media/public/include/IControlClient.h deleted file mode 100644 index 6b60b6e4c..000000000 --- a/rialto-master/media/public/include/IControlClient.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ -#define FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ - -/** - * @file IControlClient.h - * - * The definition of the IControlClient interface. - * - * This file comprises the definition of the IControlClient abstract - * class. This is the API by which a IControl implementation will - * pass notifications to its client. - */ - -#include "ControlCommon.h" - -namespace firebolt::rialto -{ -/** - * @brief The Rialto control client interface. - * - * This is The Rialto control client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the - * state of the rialto server. - */ -class IControlClient -{ -public: - /** - * @brief Virtual destructor - */ - virtual ~IControlClient() = default; - - /** - * @brief Notifies the client that rialto server reached new application state - * - * @param[in] state: The new application state. - */ - virtual void notifyApplicationState(ApplicationState state) = 0; -}; -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_CONTROL_CLIENT_H_ diff --git a/rialto-master/media/public/include/IMediaKeys.h b/rialto-master/media/public/include/IMediaKeys.h deleted file mode 100644 index 43cd1a718..000000000 --- a/rialto-master/media/public/include/IMediaKeys.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ -#define FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ - -/** - * @file IMediaKeys.h - * - * The definition of the IMediaKeys interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content. - */ - -#include -#include -#include - -#include "IMediaKeysClient.h" -#include "MediaCommon.h" - -namespace firebolt::rialto -{ -class IMediaKeys; - -/** - * @brief IMediaKeys factory class, returns a concrete implementation of IMediaKeys - */ -class IMediaKeysFactory -{ -public: - IMediaKeysFactory() = default; - virtual ~IMediaKeysFactory() = default; - - /** - * @brief Create a IMediaKeysFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMediaKeys factory method, returns a concrete implementation of IMediaKeys - * - * @param[in] keySystem : The key system for which to create a Media Keys instance. - * - * @retval the new media keys instance or null on error. - */ - virtual std::unique_ptr createMediaKeys(const std::string &keySystem) const = 0; -}; - -/** - * @brief The definition of the IMediaKeys interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content - * which should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaKeys -{ -public: - IMediaKeys() = default; - virtual ~IMediaKeys() = default; - - IMediaKeys(const IMediaKeys &) = delete; - IMediaKeys &operator=(const IMediaKeys &) = delete; - IMediaKeys(IMediaKeys &&) = delete; - IMediaKeys &operator=(IMediaKeys &&) = delete; - - /** - * @brief Selects the specified keyId for the key session. Netflix specific API. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] keyId : The key id to select. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus selectKeyId(int32_t keySessionId, const std::vector &keyId) = 0; - - /** - * @brief Returns true if the Key Session object contains the specified key. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] keyId : The key id. - * - * @retval true if it contains the key. - */ - virtual bool containsKey(int32_t keySessionId, const std::vector &keyId) = 0; - - /** - * @brief Creates a session and returns the session id. - * - * This method creates a new session and returns the session id in - * the specified string. Any other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] sessionType : The session type. - * @param[in] client : Client object for callbacks - * @param[in] isLDL : Is this an LDL - * @param[out] keySessionId: The key session id - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus createKeySession(KeySessionType sessionType, std::weak_ptr client, - bool isLDL, int32_t &keySessionId) = 0; - - /** - * @brief Generates a licence request. - * - * This method triggers generation of a licence request. If the session - * id does not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the - * session type or init data type is not supported a - * MediaKeyErrorStatus:NOT_SUPPORTED value is be returned. Any other - * errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] initDataType : The init data type. - * @param[in] initData : The init data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus generateRequest(int32_t keySessionId, InitDataType initDataType, - const std::vector &initData) = 0; - - /** - * @brief Loads an existing key session - * - * This method loads an existing key session. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the - * session type or init data type is not supported a - * MediaKeyErrorStatus:NOT_SUPPORTED value must be returned. If the session - * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any - * other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id for the session. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus loadSession(int32_t keySessionId) = 0; - - /** - * @brief Updates a key session's state. - * - * This method updates a session's state. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. If the session - * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any - * other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id for the session. - * @param[in] responseData : The license response data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus updateSession(int32_t keySessionId, const std::vector &responseData) = 0; - - /** - * @brief Set DRM Header for a key session - * - * This method updates a key session's DRM header. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned.If the session - * state is invalid an MediaKeyErrorStatus:INVALID_STATE is returned. Any - * other errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The session id for the session. - * @param[in] requestData : The request data. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus setDrmHeader(int32_t keySessionId, const std::vector &requestData) = 0; - - /** - * @brief Closes a key session - * - * This method closes an open session. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other - * errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus closeKeySession(int32_t keySessionId) = 0; - - /** - * @brief Removes a key session - * - * This method removes an open session. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other - * errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus removeKeySession(int32_t keySessionId) = 0; - - /** - * @brief Delete the DRM store for the object's key system - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus deleteDrmStore() = 0; - - /** - * @brief Delete the key store for the object's key system - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus deleteKeyStore() = 0; - - /** - * @brief Gets a hash of the DRM store for the object's key system - * - * @param[out] drmStoreHash : the hash value - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getDrmStoreHash(std::vector &drmStoreHash) = 0; - - /** - * @brief Gets a hash of the Key store for the object's key system - * - * @param[out] keyStoreHash : the hash value - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getKeyStoreHash(std::vector &keyStoreHash) = 0; - - /** - * @brief Get the limit on the number of ldl key sessions for the object's key system - * - * @param[out] ldlLimit : the limit on the number of ldl key sessions. - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getLdlSessionsLimit(uint32_t &ldlLimit) = 0; - - /** - * @brief Get the last cdm specific DRM error code - * - * @param[in] keySessionId : The key session id. - * @param[out] errorCode : the error code. - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getLastDrmError(int32_t keySessionId, uint32_t &errorCode) = 0; - - /** - * @brief Get the DRM system time for the object's key system - * - * @param[out] drmTime : the DRM system time - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getDrmTime(uint64_t &drmTime) = 0; - - /** - * @brief Get the internal CDM key session ID - * - * @param[in] keySessionId : The key session id for the session. - * @param[out] cdmKeySessionId : The internal CDM key session ID - * - * @retval the return status value. - */ - virtual MediaKeyErrorStatus getCdmKeySessionId(int32_t keySessionId, std::string &cdmKeySessionId) = 0; - - /** - * @brief Releases a key session - * - * This method releases an open session. If the session id does - * not exist an MediaKeyErrorStatus:BAD_SESSION_ID is returned. Any other - * errors will result in MediaKeyErrorStatus:FAIL. - * - * @param[in] keySessionId : The key session id. - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus releaseKeySession(int32_t keySessionId) = 0; - - /** - * @brief Get metrics for a DRM system - * - * @param[out] buffer : Buffer that can hold the metric data - * - * @retval an error status. - */ - virtual MediaKeyErrorStatus getMetricSystemData(std::vector &buffer) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_H_ diff --git a/rialto-master/media/public/include/IMediaKeysCapabilities.h b/rialto-master/media/public/include/IMediaKeysCapabilities.h deleted file mode 100644 index 41747e8b1..000000000 --- a/rialto-master/media/public/include/IMediaKeysCapabilities.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ - -/** - * @file IMediaKeysCapabilities.h - * - * The definition of the IMediaKeysCapabilities interface. - */ - -#include -#include -#include - -namespace firebolt::rialto -{ -class IMediaKeysCapabilities; - -/** - * @brief IMediaKeysCapabilities factory class, for getting the IMediaKeysCapabilities singleton object. - */ -class IMediaKeysCapabilitiesFactory -{ -public: - IMediaKeysCapabilitiesFactory() = default; - virtual ~IMediaKeysCapabilitiesFactory() = default; - - /** - * @brief Gets the IMediaKeysCapabilitiesFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Gets the IMediaKeysCapabilities singleton object. - * - * @retval the MediaKeysCapabilities instance or null on error. - */ - virtual std::shared_ptr getMediaKeysCapabilities() const = 0; -}; - -/** - * @brief The definition of the IMediaKeysCapabilities interface. - * - * This interface defines the public API of Rialto for querying EME decryption capabilities. - * It should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaKeysCapabilities -{ -public: - IMediaKeysCapabilities() = default; - virtual ~IMediaKeysCapabilities() = default; - - IMediaKeysCapabilities(const IMediaKeysCapabilities &) = delete; - IMediaKeysCapabilities &operator=(const IMediaKeysCapabilities &) = delete; - IMediaKeysCapabilities(IMediaKeysCapabilities &&) = delete; - IMediaKeysCapabilities &operator=(IMediaKeysCapabilities &&) = delete; - - /** - * @brief Returns the EME key systems supported by Rialto - * - * @retval The supported key systems. - */ - virtual std::vector getSupportedKeySystems() = 0; - - /** - * @brief Indicates if the specified key system is supported. - * - * This method should be called to ensure that the specified key - * system is supported by Rialto. - * - * @param[in] keySystem : The key system. - * - * @retval true if supported. - */ - virtual bool supportsKeySystem(const std::string &keySystem) = 0; - - /** - * @brief Returns version of supported key system - * - * @param[in] keySystem : The key system. - * @param[out] version : The supported version of the key system - * - * @retval true if operation was successful - */ - virtual bool getSupportedKeySystemVersion(const std::string &keySystem, std::string &version) = 0; - - /** - * @brief Gets support server certificate. - * - * Some DRMs (e.g. WideVine) use a system-wide server certificate. This method - * gets if system has support for that certificate. - * - * @param[in] keySystem : The key system. - * - * @retval true if server certificate is supported - */ - virtual bool isServerCertificateSupported(const std::string &keySystem) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_CAPABILITIES_H_ diff --git a/rialto-master/media/public/include/IMediaKeysClient.h b/rialto-master/media/public/include/IMediaKeysClient.h deleted file mode 100644 index c4aade608..000000000 --- a/rialto-master/media/public/include/IMediaKeysClient.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ -#define FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ - -/** - * @file IMediaKeysClient.h - * - * The definition of the IMediaKeysClient interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content. - * This is the Rialto media keys client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the state - * of a key session. - */ - -#include "MediaCommon.h" -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief The definition of the IMediaKeysClient interface. - * - * This interface defines the public API of Rialto for EME decryption of AV content - * which should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaKeysClient -{ -public: - /** - * @brief The virtual destructor. - */ - virtual ~IMediaKeysClient() {} - - /** - * @brief Notification that a license is required - * - * @param[in] keySessionId : The idea of the session triggering the callback - * @param[in] licenseRequestMessage : The license request message blob - * @param[in] url : URL to which the message should be sent or empty string - */ - virtual void onLicenseRequest(int32_t keySessionId, const std::vector &licenseRequestMessage, - const std::string &url) = 0; - - /** - * @brief Notification that a license renewal is required - * - * @param[in] keySessionId : The idea of the session triggering the callback - * @param[in] licenseRenewalMessage : The license renewal message blob - */ - virtual void onLicenseRenewal(int32_t keySessionId, const std::vector &licenseRenewalMessage) = 0; - - /** - * @brief Notification that the status of one or more keys in the key session has changed - * - * @param[in] keySessionId : The idea of the session triggering the callback - * @param[in] keyStatuses : Vector of key ID/key status pairs - */ - virtual void onKeyStatusesChanged(int32_t keySessionId, const KeyStatusVector &keyStatuses) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_KEYS_CLIENT_H_ diff --git a/rialto-master/media/public/include/IMediaPipeline.h b/rialto-master/media/public/include/IMediaPipeline.h deleted file mode 100644 index 47f2e3cb9..000000000 --- a/rialto-master/media/public/include/IMediaPipeline.h +++ /dev/null @@ -1,1530 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ -#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ - -/** - * @file IMediaPipeline.h - * - * The definition of the IMediaPipeline interface. - * - * This interface defines the public API of Rialto for playback of AV content. - */ - -#include - -#include -#include -#include -#include -#include - -#include "IMediaPipelineClient.h" -#include "MediaCommon.h" - -namespace firebolt::rialto -{ -class IMediaPipeline; - -/** - * @brief IMediaPipeline factory class, returns a concrete implementation of IMediaPipeline - */ -class IMediaPipelineFactory -{ -public: - IMediaPipelineFactory() = default; - virtual ~IMediaPipelineFactory() = default; - - /** - * @brief Create a IMediaPipelineFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IMediaPipeline factory method, returns a concrete implementation of IMediaPipeline - * - * @param[in] client : The Rialto media player client. - * @param[in] videoRequirements : The video decoder requirements for the MediaPipeline session - * - * @retval the new backend instance or null on error. - */ - virtual std::unique_ptr createMediaPipeline(std::weak_ptr client, - const VideoRequirements &videoRequirements) const = 0; -}; // IMediaPipelineFactory - -/** - * @brief The definition of the IMediaPipeline interface. - * - * This interface defines the public API of Rialto for playback of AV content which - * should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaPipeline -{ -public: - IMediaPipeline() = default; - virtual ~IMediaPipeline() = default; - - IMediaPipeline(const IMediaPipeline &) = delete; - IMediaPipeline &operator=(const IMediaPipeline &) = delete; - IMediaPipeline(IMediaPipeline &&) = delete; - IMediaPipeline &operator=(IMediaPipeline &&) = delete; - - /** - * @brief A class that represents a source of media data. - */ - class MediaSource - { - public: - /** - * @brief Virtual destructor. - */ - virtual ~MediaSource() {} - - /** - * @brief Create a copy - */ - virtual std::unique_ptr copy() const = 0; - - /** - * @brief Return the source type. - */ - virtual MediaSourceType getType() const { return MediaSourceType::UNKNOWN; } - - /** - * @brief Return the MIME type. - */ - std::string getMimeType() const { return m_mimeType; } - - /** - * @brief Return if source has drm - */ - bool getHasDrm() const { return m_hasDrm; } - - /** - * @brief Return the source config type. - */ - SourceConfigType getConfigType() const { return m_configType; } - - /** - * @brief Return the source id. - */ - int32_t getId() const { return m_id; } - - /** - * @brief Set the source id. - */ - void setId(int32_t id) { m_id = id; } - - protected: - /** - * @brief Default constructor. - * - * @param[in] configType : The source config type. - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - */ - explicit MediaSource(SourceConfigType configType = SourceConfigType::UNKNOWN, - const std::string &mimeType = std::string(), bool hasDrm = true) - : m_id(0), m_configType(configType), m_mimeType(mimeType), m_hasDrm(hasDrm) - { - } - /** - * @brief The source id. Parameter will be set by a successful call to attachSource() - */ - int32_t m_id; - - /** - * @brief The source config type. - */ - SourceConfigType m_configType; - - /** - * @brief The MIME type. - */ - std::string m_mimeType; - - /** - * @brief Parameter to check if encrypted frames will be used for this source. - */ - bool m_hasDrm; - }; // MediaSource - - /** - * @brief A class that represents media source audio and video derived from MediaSource class, which represents the - * source of media data - */ - class MediaSourceAV : public MediaSource - { - public: - ~MediaSourceAV() {} - std::unique_ptr copy() const { return std::make_unique(*this); } - - /** - * @brief Gets the segment alignment - */ - SegmentAlignment getSegmentAlignment() const { return m_alignment; } - - /** - * @brief Gets the codec data - */ - const std::shared_ptr &getCodecData() const { return m_codecData; } - - /** - * @brief Gets the stream format - */ - StreamFormat getStreamFormat() const { return m_streamFormat; } - - protected: - /** - * @brief Default constructor. - * - * @param[in] configType : The source config type. - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - explicit MediaSourceAV(SourceConfigType configType = SourceConfigType::UNKNOWN, - const std::string &mimeType = std::string(), bool hasDrm = true, - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSource(configType, mimeType, hasDrm), m_alignment(alignment), m_streamFormat(streamFormat), - m_codecData(codecData) - { - } - /** - * @brief The alignment of media segment - */ - SegmentAlignment m_alignment; - - /** - * @brief The stream format - */ - StreamFormat m_streamFormat; - - /** - * @brief Additional data for decoder - */ - std::shared_ptr m_codecData; - }; // MediaSourceAV - - /** - * @brief A class that represents media source audio derived from MediaSource class, which represents the source of - * media data - */ - - class MediaSourceAudio : public MediaSourceAV - { - public: - /** - * @brief Constructor for audio specific configuration. - * - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - * @param[in] audioConfig : The audio specific configuration. - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - MediaSourceAudio(const std::string &mimeType, bool hasDrm = true, const AudioConfig &audioConfig = AudioConfig(), - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSourceAV(SourceConfigType::AUDIO, mimeType, hasDrm, alignment, streamFormat, codecData), - m_audioConfig(audioConfig) - { - } - - ~MediaSourceAudio() {} - - MediaSourceType getType() const override { return MediaSourceType::AUDIO; } - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Gets the audio specific configuration - * - * @retval audio specific configuration - */ - const AudioConfig &getAudioConfig() const { return m_audioConfig; } - - protected: - /** - * @brief Variable that stores the audio specific configuration - */ - AudioConfig m_audioConfig; - }; // MediaSourceAudio - - /** - * @brief A class that represents media source video derived from MediaSource class, which represents the source of - * media data - */ - - class MediaSourceVideo : public MediaSourceAV - { - public: - /** - * @brief Constructor for video specific configuration. - * - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - * @param[in] width : The width of the video - * @param[in] height : The height of the video - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - MediaSourceVideo(const std::string &mimeType, bool hasDrm = true, - int32_t width = firebolt::rialto::kUndefinedSize, - int32_t height = firebolt::rialto::kUndefinedSize, - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSourceAV(SourceConfigType::VIDEO, mimeType, hasDrm, alignment, streamFormat, codecData), - m_width(width), m_height(height) - { - } - ~MediaSourceVideo() {} - - MediaSourceType getType() const override { return MediaSourceType::VIDEO; } - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Gets the width of the video - * - * @retval width of the video - */ - int32_t getWidth() const { return m_width; } - - /** - * @brief Gets the height of the video - * - * @retval height of the video - */ - int32_t getHeight() const { return m_height; } - - protected: - /** - * @brief Constructor for video specific configuration. - * - * @param[in] sourceConfigType : The source config type - * @param[in] mimeType : The mime type string. - * @param[in] hasDrm : Information if source will use drm - * @param[in] width : The width of the video - * @param[in] height : The height of the video - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - MediaSourceVideo(SourceConfigType sourceConfigType, const std::string &mimeType, bool hasDrm = true, - int32_t width = firebolt::rialto::kUndefinedSize, - int32_t height = firebolt::rialto::kUndefinedSize, - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSourceAV(sourceConfigType, mimeType, hasDrm, alignment, streamFormat, codecData), m_width(width), - m_height(height) - { - } - - private: - /** - * @brief The video width - */ - int m_width; - - /** - * @brief The video height - */ - int m_height; - }; // MediaSourceVideo - - /** - * @brief A class that represents media source video dolby vision derived from media source video data - */ - - class MediaSourceVideoDolbyVision : public MediaSourceVideo - { - public: - /** - * @brief Constructor for dolby vision specific configuration. - * - * @param[in] mimeType : The mime type string. - * @param[in] dolbyVisionProfile : The dolby vision profile - * @param[in] hasDrm : Information if source will use drm - * @param[in] width : The width of the video - * @param[in] height : The height of the video - * @param[in] alignment : The alignment of media segment. - * @param[in] streamFormat : The stream format - * @param[in] codecData : The additional data for decoder - */ - MediaSourceVideoDolbyVision(const std::string &mimeType, int32_t dolbyVisionProfile, bool hasDrm = true, - int32_t width = firebolt::rialto::kUndefinedSize, - int32_t height = firebolt::rialto::kUndefinedSize, - SegmentAlignment alignment = SegmentAlignment::UNDEFINED, - StreamFormat streamFormat = StreamFormat::UNDEFINED, - const std::shared_ptr &codecData = nullptr) - : MediaSourceVideo(SourceConfigType::VIDEO_DOLBY_VISION, mimeType, hasDrm, width, height, alignment, - streamFormat, codecData), - m_dolbyVisionProfile(dolbyVisionProfile) - { - } - ~MediaSourceVideoDolbyVision() {} - std::unique_ptr copy() const { return std::make_unique(*this); } - - /** - * @brief Gets the dolby vision profile - * - * @retval dolby vision profile - */ - uint32_t getDolbyVisionProfile() const { return m_dolbyVisionProfile; } - - protected: - /** - * @brief Variable that stores the Dolby Vision Profile - */ - uint32_t m_dolbyVisionProfile; - }; // MediaSourceVideoDolbyVision - - /** - * @brief A class that represents media source subtitle derived from media source video data - */ - class MediaSourceSubtitle : public MediaSource - { - public: - /** - * @brief Construct a new Media Source Subtitle object - * - * @param mimeType : The mime type string - * @param textTrackIdentifier : The text track identifier string - */ - MediaSourceSubtitle(const std::string &mimeType, const std::string &textTrackIdentifier) - : MediaSource(SourceConfigType::SUBTITLE, mimeType, false), m_textTrackIdentifier(textTrackIdentifier) - { - } - - ~MediaSourceSubtitle() {} - - MediaSourceType getType() const override { return MediaSourceType::SUBTITLE; } - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Get the Text Track Identifier object - * - * @return the text track identifier - */ - const std::string &getTextTrackIdentifier() const { return m_textTrackIdentifier; } - - protected: - /** - * @brief Variable that stores the text track identifier - */ - std::string m_textTrackIdentifier; - }; // MediaSourceSubtitle - - /** - * @brief A class that represents a media segment - */ - class MediaSegment - { - public: - /** - * @brief Default constructor. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] type : The source type. - * @param[in] timeStamp : The timestamp in nanoseconds. - * @param[in] duration : The duration in nanoseconds. - */ - MediaSegment(int32_t sourceId = 0, MediaSourceType type = MediaSourceType::UNKNOWN, int64_t timeStamp = 0, - int64_t duration = 0) - : m_sourceId(sourceId), m_type(type), m_data(nullptr), m_dataLength(0u), m_timeStamp(timeStamp), - m_duration(duration), m_encrypted(false), m_mediaKeySessionId(0), m_initWithLast15(0), - m_alignment(SegmentAlignment::UNDEFINED), m_cipherMode(CipherMode::UNKNOWN), m_crypt(0), m_skip(0), - m_encryptionPatternSet(false), m_displayOffset(std::nullopt) - { - } - - /** - * @brief Virtual destructor. - */ - virtual ~MediaSegment() {} - - /** - * @brief Makes a shallow copy of the segment - * - * @retval Shallow copy of the segment - */ - virtual std::unique_ptr copy() const { return std::make_unique(*this); } - - /** - * @brief Return the source id. - * - * @retval the source id. - */ - int32_t getId() const { return m_sourceId; } - - /** - * @brief The source type for the data. - * - * @retval the source type. - */ - MediaSourceType getType() const { return m_type; } - - /** - * @brief Returns a pointer to the data. - * - * @retval the data. - */ - const uint8_t *getData() const { return m_data; } - - /** - * @brief Returns a the data length. - * - * @retval the data. - */ - uint32_t getDataLength() const { return m_dataLength; } - - /** - * @brief Returns the time stamp. - * - * @retval the timestamp in nanoseconds. - */ - int64_t getTimeStamp() const { return m_timeStamp; } - - /** - * @brief Sets the time stamp (value in nanoseconds). - */ - void setTimeStamp(int64_t timeStamp) { m_timeStamp = timeStamp; } - - /** - * @brief Returns the duration. - * - * @retval the duration in nanoseconds. - */ - int64_t getDuration() const { return m_duration; } - - /** - * @brief Returns a pointer to the extra data. - * - * @retval the data. - */ - const std::vector &getExtraData() const { return m_extraData; } - - /** - * @brief Indicates that the data is encrypted. - * - * @retval true if the data is encrypted. - */ - bool isEncrypted() const { return m_encrypted; } - - /** - * @brief Returns the media key session id. Empty if unencrypted. - * - * @retval the media key session id. - */ - const int32_t getMediaKeySessionId() const { return m_mediaKeySessionId; } - - /** - * @brief Returns the key id. Empty if unencrypted. - * - * @retval the key id. - */ - const std::vector &getKeyId() const { return m_keyId; } - - /** - * @brief Returns the initialisation vector. Empty if unencrypted. - * - * @retval the initialisation vector. - */ - const std::vector &getInitVector() const { return m_initVector; } - - /** - * @brief Returns the sub samples. Empty if unencrypted. - * - * @retval the sub samples. - */ - const std::vector &getSubSamples() const { return m_subSamples; } - - /** - * @brief Returns the initWithLast15 value - * - * @retval the initWithLast15 value. - */ - const uint32_t getInitWithLast15() const { return m_initWithLast15; } - - /** - * @brief Returns the segment alignment - * - * @retval the segment alignment - */ - const SegmentAlignment getSegmentAlignment() const { return m_alignment; } - - /** - * @brief Gets the codec data - * - * @retval the codec data - */ - const std::shared_ptr &getCodecData() const { return m_codecData; } - - /** - * @brief Gets the cipher mode for common encryption - * - * @retval cipher mode uses for this sample - */ - const CipherMode &getCipherMode() const { return m_cipherMode; } - - /** - * @brief Gets the crypt & skip byte block for pattern encryption - * - * @param[out] crypt : Crypt byte block value - * @param[out] skip : Skip byte block value - * - * @retval if the encryption pattern has been set - */ - const bool getEncryptionPattern(uint32_t &crypt, uint32_t &skip) const - { - crypt = m_crypt; - skip = m_skip; - return m_encryptionPatternSet; - } - - /** - * @brief Gets the display offset - * - * @retval The offset in the source file of the beginning of the media segment. - */ - std::optional getDisplayOffset() const { return m_displayOffset; } - - protected: - /** - * @brief The source id. - */ - int32_t m_sourceId; - - /** - * @brief The source type. - */ - MediaSourceType m_type; - - /** - * @brief The data - */ - const uint8_t *m_data; - - /** - * @brief The data length - */ - uint32_t m_dataLength; - - /** - * @brief The time stamp. - */ - int64_t m_timeStamp; - - /** - * @brief The duration. - */ - int64_t m_duration; - - /** - * @brief Additional data for decoder - */ - std::shared_ptr m_codecData; - - /** - * @brief The data - */ - std::vector m_extraData; - - /** - * @brief Indicates the data is encrypted. - */ - bool m_encrypted; - - /** - * @brief Key session ID to use for decryption - only required for Netflix. - */ - int32_t m_mediaKeySessionId; - - /** - * @brief The encryption key id. - */ - std::vector m_keyId; - - /** - * @brief The encryption key initialisation vector. - */ - std::vector m_initVector; - - /** - * @brief The sub-sample pairs. - */ - std::vector m_subSamples; - - /** - * @brief Whether decryption context needs to be initialized with - * last 15 bytes. Currently this only applies to PlayReady DRM. - */ - uint32_t m_initWithLast15; - - /** - * @brief The alignment of media segment - */ - SegmentAlignment m_alignment; - - /** - * @brief Cipher mode of the sample. - */ - CipherMode m_cipherMode; - - /** - * @brief Crypt byte block value. - */ - uint32_t m_crypt; - - /** - * @brief Skip byte block value. - */ - uint32_t m_skip; - - /** - * @brief Whether the encryption pattern has been set. - */ - bool m_encryptionPatternSet; - - /** - * @brief The offset in the source file of the beginning of the media segment. - */ - std::optional m_displayOffset; - - public: - /** - * @brief Sets the segment data. - * - * @warning Note that the caller must guarantee that the buffer referenced by 'data' must remain - * valid until the corresponding call to haveData() has completed (at which point the data will - * have been copied out). - * - * @note This is for performance reasons to avoid multiple copies of AV data. A raw pointer is - * used for the same reason since most runtimes will expose a raw pointer to the data. - * - * @retval true on success. - */ - bool setData(uint32_t dataLength, const uint8_t *data) - { - m_dataLength = dataLength; - m_data = data; - return true; - } - - /** - * @brief Sets the extra data. - * - * @retval true on success. - */ - bool setExtraData(const std::vector &extraData) - { - m_extraData = extraData; - return true; - } - - /** - * @brief Sets the segment alignment - * - * @param[in] alignment : The new segment alignment - */ - void setSegmentAlignment(const SegmentAlignment &alignment) { m_alignment = alignment; } - - /** - * @brief Sets new codec_data for the segment. - * - * @note Should only be called if the codec data changes - * - * @param[in] codecData The updated codec data for the source - */ - void setCodecData(const std::shared_ptr &codecData) { m_codecData = codecData; } - - /** - * @brief Sets the encrypted flag. - * - * @param[in] encrypted : Set true to indicated encrypted data. - */ - void setEncrypted(bool encrypted) { m_encrypted = encrypted; } - - /** - * @brief Sets the media key session id. - * - * @param[in] mksId : the media key session id. - */ - void setMediaKeySessionId(int32_t mksId) { m_mediaKeySessionId = mksId; } - - /** - * @brief Sets the key id. - * - * @param[in] keyId : The key id. - */ - void setKeyId(const std::vector &keyId) { m_keyId = keyId; } - - /** - * @brief Sets the encryption initialisation vector. - * - * @param[in] initVector : The initialisation vector. - */ - void setInitVector(const std::vector &initVector) { m_initVector = initVector; } - - /** - * @brief Adds a sub-sample pair to the sub samples. - * - * @param[in] numClearBytes : The number of clear bytes. - * @param[in] numEncryptedBytes : The number of encrypted bytes. - */ - void addSubSample(size_t numClearBytes, size_t numEncryptedBytes) - { - m_subSamples.emplace_back(SubSamplePair{numClearBytes, numEncryptedBytes}); - } - - /** - * @brief Sets initWithLast15 value - * - * @param[in] initWithLast15 : initWithLast15 value - */ - void setInitWithLast15(uint32_t initWithLast15) { m_initWithLast15 = initWithLast15; } - - /** - * @brief Sets the cipher mode for common encryption. - * - * @param[in] cipherMode : Specifies cipher mode uses for this sample. - */ - void setCipherMode(CipherMode cipherMode) { m_cipherMode = cipherMode; } - - /** - * @brief Sets the crypt & skip byte block for pattern encryption - * - * @param[in] crypt : Crypt byte block value - * @param[in] skip : Skip byte block value - */ - void setEncryptionPattern(uint32_t crypt, uint32_t skip) - { - m_crypt = crypt; - m_skip = skip; - m_encryptionPatternSet = true; - } - - /** - * @brief Sets the display offset - * - * @param[in] displayOffset : The offset in the source file of the beginning of the media segment. - */ - void setDisplayOffset(uint64_t displayOffset) { m_displayOffset = displayOffset; } - - /** - * @brief Copies the data from other to this. - */ - void copy(const MediaSegment &other); - }; // MediaSegment - - /** - * @brief A class that represents media source audio data - */ - class MediaSegmentAudio : public MediaSegment - { - public: - /** - * @brief Default constructor. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] timeStamp : The timestamp in nanoseconds. - * @param[in] duration : The duration in nanoseconds. - * @param[in] sampleRate : The sample rate in samples per second. - * @param[in] numberOfChannels : The number of audio channels. - * @param[in] clippingStart : The amount of audio to clip from start of buffer - * @param[in] clippingEnd : The amount of audio to clip from end of buffer - */ - MediaSegmentAudio(int32_t sourceId = 0, int64_t timeStamp = 0, int64_t duration = 0, int32_t sampleRate = 0, - int32_t numberOfChannels = 0, uint64_t clippingStart = 0, uint64_t clippingEnd = 0) - : MediaSegment(sourceId, MediaSourceType::AUDIO, timeStamp, duration), m_sampleRate(sampleRate), - m_numberOfChannels(numberOfChannels), m_clippingStart(clippingStart), m_clippingEnd(clippingEnd) - { - } - - /** - * @brief Copy constructor. - */ - MediaSegmentAudio(const MediaSegmentAudio &other) : MediaSegment(other) - { - m_sampleRate = other.m_sampleRate; - m_numberOfChannels = other.m_numberOfChannels; - } - - /** - * @brief Makes a shallow copy of the segment - * - * @retval Shallow copy of the segment - */ - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Return the audio sample rate. - * - * @retval the sample rate in samples per second. - */ - int32_t getSampleRate() const { return m_sampleRate; } - - /** - * @brief Return the number of audio channels. - * - * @retval the number of channels. - */ - int32_t getNumberOfChannels() const { return m_numberOfChannels; } - - /** - * @brief Return the amount of audio to clip from start of buffer - * - * @retval the amount of audio to clip from start of buffer - */ - uint64_t getClippingStart() const { return m_clippingStart; } - - /** - * @brief Return the amount of audio to clip from end of buffer - * - * @retval the amount of audio to clip from end of buffer - */ - uint64_t getClippingEnd() const { return m_clippingEnd; } - - /** - * @brief Copy assignment operator. - * - * @retval the copy. - */ - MediaSegmentAudio &operator=(const MediaSegmentAudio &other) - { - copy(other); - return *this; - } - - protected: - /** - * @brief Copies the data from other to this. - */ - void copy(const MediaSegmentAudio &other); - - /** - * @brief The audio sample rate. - */ - int32_t m_sampleRate; - - /** - * @brief The number of audio channels. - */ - int32_t m_numberOfChannels; - - /** - * @brief The amount of audio to clip from start of buffer - */ - uint64_t m_clippingStart; - - /** - * @brief The amount of audio to clip from end of buffer - */ - uint64_t m_clippingEnd; - }; // MediaSegmentAudio - - /** - * @brief A class that represents media source video data - */ - class MediaSegmentVideo : public MediaSegment - { - public: - /** - * @brief Default constructor. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] timeStamp : The timestamp in nanoseconds. - * @param[in] duration : The duration in nanoseconds. - * @param[in] width : The video width in pixels. - * @param[in] height : The video height in pixels. - * @param[in] frameRate : The fractional framerate of the sample. - */ - MediaSegmentVideo(int32_t sourceId = 0, int64_t timeStamp = 0, int64_t duration = 0, - int32_t width = firebolt::rialto::kUndefinedSize, - int32_t height = firebolt::rialto::kUndefinedSize, - firebolt::rialto::Fraction frameRate = {firebolt::rialto::kUndefinedSize, - firebolt::rialto::kUndefinedSize}) - : MediaSegment(sourceId, MediaSourceType::VIDEO, timeStamp, duration), m_width(width), m_height(height), - m_frameRate(frameRate) - { - } - - /** - * @brief Copy constructor. - */ - MediaSegmentVideo(const MediaSegmentVideo &other) : MediaSegment(other) - { - m_width = other.m_width; - m_height = other.m_height; - m_frameRate = other.m_frameRate; - } - - /** - * @brief Makes a shallow copy of the segment - * - * @retval Shallow copy of the segment - */ - std::unique_ptr copy() const override { return std::make_unique(*this); } - - /** - * @brief Return the video width. - * - * @retval the video width in pixels. - */ - int32_t getWidth() const { return m_width; } - - /** - * @brief Return the video height. - * - * @retval the video height in pixels. - */ - int32_t getHeight() const { return m_height; } - - /** - * @brief Return the video frameRate. - * - * @retval the fractional framerate of the sample. - */ - firebolt::rialto::Fraction getFrameRate() const { return m_frameRate; } - - /** - * @brief Copy assignment operator. - * - * @retval the copy. - */ - MediaSegmentVideo &operator=(const MediaSegmentVideo &other) - { - copy(other); - return *this; - } - - protected: - /** - * @brief Copies the data from other to this. - */ - void copy(const MediaSegmentVideo &other); - - /** - * @brief The video width in pixels. - */ - int32_t m_width; - - /** - * @brief The video height in pixels. - */ - int32_t m_height; - - /** - * @brief The fractional framerate of the sample. - */ - firebolt::rialto::Fraction m_frameRate; - }; // MediaSegmentVideo - - /** - * @brief A vector that contains one or more media segments. - */ - typedef std::vector> MediaSegmentVector; - - /** - * @brief Returns the media player client. - * - * @retval The media player client. - */ - virtual std::weak_ptr getClient() = 0; - - /** - * @brief Loads the media and backend delegate. - * - * This method loads the media and backend appropriate for the media. - * The media type determines the backend delegate to use to play back - * the media. The MIME type confirms the type and CODECs for the media. - * The URL will comprise the media URL for types MediaType::URL and - * MediaType::HLS. For MediaType::MSE the URL will comprise a blob URL - * as the data is loaded by the browser. - * - * @param[in] type : The media type. - * @param[in] mimeType : The MIME type. - * @param[in] url : The URL. - */ - virtual bool load(MediaType type, const std::string &mimeType, const std::string &url) = 0; - - /** - * @brief Attaches a source stream to the backend. - * - * This method is called by Rialto Client to attach a media source stream to - * the backend. It is only called when Media Source Extensions are - * being used. I.e. if the MediaType value in load() is - * MediaType::MSE. - * - * @param[in] source : The source. - * - * @retval true on success. - */ - virtual bool attachSource(const std::unique_ptr &source) = 0; - - /** - * @brief Unattaches a source. - * - * This method is called by Rialto Client to detach a media source stream from - * the backend. It is only called when Media Source Extensions are - * being used. I.e. if the MediaType value in load() is - * MediaType::MSE. - * - * @param[in] id : The source id. Value should be set to the MediaSource.id returned after attachSource() - * - * @retval true on success. - */ - virtual bool removeSource(int32_t id) = 0; - - /** - * @brief Notifies Rialto Server that all sources were attached - * - * This method is called by Rialto Client to notify the RialtoServer - * that all sources were attached. - * - * Must be called, otherwise streaming cannot commence. - * Can be called only once. - * - * @retval true on success. - */ - virtual bool allSourcesAttached() = 0; - - /** - * @brief Starts playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request playback and then return. - * - * Once the backend is successfully playing it should notify the - * media player client of playback state - * IMediaPipelineClient::PlaybackState::PLAYING. - * - * @retval true on success. - */ - virtual bool play() = 0; - - /** - * @brief Pauses playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the playback pause and then return. - * - * Once the backend is successfully playing it should notify the - * media player client of playback state - *IMediaPipelineClient::PlaybackState::PAUSED. - * - * @retval true on success. - */ - virtual bool pause() = 0; - - /** - * @brief Stops playback of the media. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the playback stop and then return. - * - * Once the backend is successfully stopped it should notify the - * media player client of playback state - * IMediaPipelineClient::PlaybackState::STOPPED. - * - * @retval true on success. - */ - virtual bool stop() = 0; - - /** - * @brief Set the playback rate - * - * This method sets the playback rate. The supported playback rates - * are dependent upon the backend playback method. - * - * @param[in] rate : The playback rate. - * - * @retval true on success. - */ - virtual bool setPlaybackRate(double rate) = 0; - - /** - * @brief Set the playback position in nanoseconds. - * - * If playback has not started this method sets the start position - * for playback. If playback has started this method performs a seek. - * - * This method is considered to be asynchronous and MUST NOT block - * but should request the new playback position and then return. - * - * Once the backend is seeking it should notify the media player - * client of playback state - * IMediaPipelineClient::PlaybackState::SEEKING. When seeking has - * completed the state IMediaPipelineClient::PlaybackState::SEEK_DONE - * should be notified followed by - * IMediaPipelineClient::PlaybackState::PLAYING. - * - * @param[in] position : The playback position in nanoseconds. - * - * @retval true on success. - */ - virtual bool setPosition(int64_t position) = 0; - - /** - * @brief Get the playback position in nanoseconds. - * - * This method is sychronous, it returns current playback position - * - * @param[out] position : The playback position in nanoseconds - * - * @retval true on success. - */ - virtual bool getPosition(int64_t &position) = 0; - - /** - * @brief Get stats for this source. - * - * This method is sychronous, it returns dropped frames and rendered frames - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[out] renderedFrames : The number of rendered frames - * @param[out] droppedFrames : The number of dropped frames - * - * @retval true on success. - */ - virtual bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) = 0; - - /** - * @brief Sets the "Immediate Output" property for this source. - * - * This method is asynchronous, it will set the "Immediate Output" property - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] immediateOutput : Set immediate output mode on the sink - * - * @retval true on success. - */ - virtual bool setImmediateOutput(int32_t sourceId, bool immediateOutput) = 0; - - /** - * @brief Gets the "Immediate Output" property for this source. - * - * This method is sychronous, it gets the "Immediate Output" property - * - * @param[in] sourceId : The source id. Value should be get to the MediaSource.id returned after attachSource() - * @param[out] immediateOutput : Get immediate output mode on the sink - * - * @retval true on success. - */ - virtual bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) = 0; - - /** - * @brief Sets the coordinates of where the video should be displayed. - * - * @param[in] x : The x position in pixels. - * @param[in] y : The y position in pixels. - * @param[in] width : The width in pixels. - * @param[in] height : The height in pixels. - * - * @retval true on success. - */ - virtual bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) = 0; - - /** - * @brief Returns data requested using notifyNeedMediaData(). - * - * This method is called as a result of calling notifyNeedMediaData() on - * the media client. The status value indicates the success or - * otherwise of the request. The client must first call addSegment() for - * for each media segment to be sent. - * A status of MediaSourceStatus::OK indicates success and there will - * be data within the data vector. A status of MediaSourceStatus::EOS - * indicates success but the end of the stream was reached. Again - * there will be data in the vector. A status of - * MediaSourceStatus::ERROR indicates an error occurred and no data - * was returned. - * - * - * @param[in] status : The status - * @param[in] needDataRequestId : Need data request id - */ - virtual bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) = 0; - - /** - * @brief Adds a single segment to Rialto in response to notifyNeedData() - * - * This method is should be called by the client as a result of a notifyNeedData() - * notification. The client should call this API for each segment to be sent in - * response to the notification and then call haveData() when all segments - * have been 'added'. - * - * If the return code is NO_SPACE the segment has not been accepted but this is - * not an error. The client should retain the segment until the next notifyNeedData() - * is received for the source and immediately call haveData() to trigger Rialto - * to start processing the segments already added. - * - * @param[in] needDataRequestId : The status - * @param[in] mediaSegment : The data returned. - * - * @retval status of adding segment - */ - virtual AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) = 0; - - /** - * @brief Requests to render a prerolled frame - */ - virtual bool renderFrame() = 0; - - /** - * @brief Set the target volume level and transition duration with easing type. - * By default volume is set immediately if duration and type are not set. - * - * @param[in] targetVolume : Target volume level (0.0 - 1.0) - * @param[in] volumeDuration : (Optional) Duration of the volume transition in milliseconds - * @param[in] easeType : (Optional) Easing type for the volume transition - * - * @retval true on success, false otherwise. - */ - virtual bool setVolume(double targetVolume, uint32_t volumeDuration = 0, - EaseType easeType = EaseType::EASE_LINEAR) = 0; - - /** - * @brief Get current audio level. Fetches the current volume level for the pipeline. - * - * @param[out] currentVolume : Current volume level (range 0.0 - 1.0) - * - * @retval true on success, false otherwise. - */ - virtual bool getVolume(double ¤tVolume) = 0; - - /** - * @brief Set mute status of pipeline. - * - * Change mute status of media source - * - * @param[in] sourceId Source, which mute status should be changed - * @param[in] mute Desired mute state, true=muted, false=not muted - * - * @retval true on success false otherwise - */ - virtual bool setMute(int32_t sourceId, bool mute) = 0; - - /** - * @brief Get current mute status of the media source - * - * @param[in] sourceId Source, which mute status should be fetched - * @param[out] mute Current mute state - * - * @retval true on success false otherwise - */ - virtual bool getMute(int32_t sourceId, bool &mute) = 0; - - /** - * @brief Change Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - virtual bool setTextTrackIdentifier(const std::string &textTrackIdentifier) = 0; - - /** - * @brief Get Text Track Identifier - * - * @param[in] textTrackIdentifier Text track identifier of subtitle stream - * - * @retval true on success false otherwise - */ - virtual bool getTextTrackIdentifier(std::string &textTrackIdentifier) = 0; - - /** - * @brief Set low latency property on the audio sink. Default false. - * - * For use with gaming (no audio decoding, no a/v sync). - * - * @param[in] lowLatency : The low latency value to set. - * - * @retval true on success false otherwise - */ - virtual bool setLowLatency(bool lowLatency) = 0; - - /** - * @brief Set sync property on the audio sink. Default false. - * - * Syncs the stream on the clock. - * - * @param[in] sync : The sync value to set. - * - * @retval true on success false otherwise - */ - virtual bool setSync(bool sync) = 0; - - /** - * @brief Get sync property on the audio sink. - * - * @param[out] sync : Current sync value. - * - * @retval true on success false otherwise - */ - virtual bool getSync(bool &sync) = 0; - - /** - * @brief Set sync off property on the audio decoder. Default false. - * - * Turn on free running audio. Must be set before pipeline is PLAYING state. - * - * @param[in] syncOff : The sync off value to set. - * - * @retval true on success false otherwise - */ - virtual bool setSyncOff(bool syncOff) = 0; - - /** - * @brief Set stream sync mode property on the audio decoder or video filter. Default 0. - * - * 1 - Frame to decode frame will immediately proceed next frame sync. - * 0 - Frame decoded with no frame sync. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] streamSyncMode : The stream sync mode value to set. - * - * @retval true on success false otherwise - */ - virtual bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) = 0; - - /** - * @brief Get stream sync mode property on the audio decoder. - * - * @param[out] streamSyncMode : Current stream sync mode value. - * - * @retval true on success false otherwise - */ - virtual bool getStreamSyncMode(int32_t &streamSyncMode) = 0; - - /** - * @brief Flushes a source. - * - * This method is called by Rialto Client to flush out all queued data for a media source stream. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] resetTime : True if time should be reset - * @param[out] async : True if flushed source is asynchronous (will preroll after flush) - * - * @retval true on success. - */ - virtual bool flush(int32_t sourceId, bool resetTime, bool &async) = 0; - - /** - * @brief Set the source position in nanoseconds. - * - * This method sets the start position for a source. - * - * @param[in] sourceId : The source id. Value should be set to the MediaSource.id returned after attachSource() - * @param[in] position : The position in nanoseconds. - * @param[in] resetTime : True if time should be reset - * @param[in] appliedRate : The applied rate after seek. Default value is 1.0. - * @param[in] stopPosition : The position of last pushed buffer - * - * @retval true on success. - */ - virtual bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, - uint64_t stopPosition = kUndefinedPosition) = 0; - - virtual bool setSubtitleOffset(int32_t sourceId, int64_t position) = 0; - - /** - * @brief Process audio gap - * - * This method handles audio gap in order to avoid audio pops during transitions. - * - * @param[in] position : Audio pts fade position - * @param[in] duration : Audio pts fade duration - * @param[in] discontinuityGap : Audio discontinuity gap - * @param[in] audioAac : True if audio codec is AAC - * - * @retval true on success. - */ - virtual bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) = 0; - - /** - * @brief Set buffering limit - * - * This method enables/disables limit buffering and sets millisecond threshold used. - * Use kInvalidLimitBuffering to disable limit buffering - * - * @param[in] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - virtual bool setBufferingLimit(uint32_t limitBufferingMs) = 0; - - /** - * @brief Get buffering limit - * - * This method returns current value of buffering limit in milliseconds - * Method will return kInvalidLimitBuffering limit buffering is disabled - * - * @param[out] limitBufferingMs : buffering limit in ms - * - * @retval true on success. - */ - virtual bool getBufferingLimit(uint32_t &limitBufferingMs) = 0; - - /** - * @brief Enables/disables the buffering option - * - * This method enables the buffering option so that BUFFERING messages are - * emitted based on low-/high-percent thresholds. - * - * @param[in] useBuffering : true if buffering option enabled. - * - * @retval true on success. - */ - virtual bool setUseBuffering(bool useBuffering) = 0; - - /** - * @brief Checks, if buffering is enabled - * - * This method returns true, if buffering is enabled - * - * @param[out] useBuffering : true if buffering option is enabled. - * - * @retval true on success. - */ - virtual bool getUseBuffering(bool &useBuffering) = 0; - - /** - * @brief Switches a source stream. - * - * This method is called to switch a media source stream. - * - * @param[in] source : The source. - * - * @retval true on success. - */ - virtual bool switchSource(const std::unique_ptr &source) = 0; -}; // IMediaPipeline - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_H_ diff --git a/rialto-master/media/public/include/IMediaPipelineCapabilities.h b/rialto-master/media/public/include/IMediaPipelineCapabilities.h deleted file mode 100644 index 63a26c611..000000000 --- a/rialto-master/media/public/include/IMediaPipelineCapabilities.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ -#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ - -/** - * @file IMediaPipelineCapabilities.h - * - * The definition of the IMediaPipelineCapabilities interface. - */ - -#include "MediaCommon.h" -#include -#include -#include - -namespace firebolt::rialto -{ -class IMediaPipelineCapabilities; - -/** - * @brief IMediaPipelineCapabilities factory class, for getting the IMediaPipelineCapabilities object. - */ -class IMediaPipelineCapabilitiesFactory -{ -public: - IMediaPipelineCapabilitiesFactory() = default; - virtual ~IMediaPipelineCapabilitiesFactory() = default; - - /** - * @brief Gets the IMediaPipelineCapabilitiesFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief Creates the IMediaPipelineCapabilities object. - * - * @retval the MediaPipelineCapabilities instance or null on error. - */ - virtual std::unique_ptr createMediaPipelineCapabilities() const = 0; -}; - -/** - * @brief The definition of the IMediaPipelineCapabilities interface. - * - * This interface defines the public API of Rialto for querying EME decryption capabilities. - * It should be implemented by both Rialto Client & Rialto Server. - */ -class IMediaPipelineCapabilities -{ -public: - IMediaPipelineCapabilities() = default; - virtual ~IMediaPipelineCapabilities() = default; - - IMediaPipelineCapabilities(const IMediaPipelineCapabilities &) = delete; - IMediaPipelineCapabilities &operator=(const IMediaPipelineCapabilities &) = delete; - IMediaPipelineCapabilities(IMediaPipelineCapabilities &&) = delete; - IMediaPipelineCapabilities &operator=(IMediaPipelineCapabilities &&) = delete; - - /** - * @brief Returns the MSE mime types supported by Rialto for \a sourceType - * - * @param[in] sourceType : source type - * - * @retval The supported mime types. - */ - virtual std::vector getSupportedMimeTypes(MediaSourceType sourceType) = 0; - - /** - * @brief Indicates if the specified mime type is supported. - * - * This method should be called to ensure that the specified mime - * type is supported by Rialto. - * - * @param[in] mimeType : The mime type to check. - * - * @retval true if supported. - */ - virtual bool isMimeTypeSupported(const std::string &mimeType) = 0; - - /** - * @brief Check sinks and decoders for supported properties - * - * @param[in] mediaType : The media type to search. If set to UNKNOWN then both AUDIO and VIDEO are searched - * @param[in] propertyNames : A vector of property names to look for - * - * @retval Returns the subset of propertyNames that are supported by the mediaType - */ - virtual std::vector getSupportedProperties(MediaSourceType mediaType, - const std::vector &propertyNames) = 0; - - /** - * @brief Checks if the platform is video master. - * - * @param[out] isVideoMaster : The output value. True if video is master otherwise false. - * - * @retval true on success false otherwise - */ - virtual bool isVideoMaster(bool &isVideoMaster) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CAPABILITIES_H_ diff --git a/rialto-master/media/public/include/IMediaPipelineClient.h b/rialto-master/media/public/include/IMediaPipelineClient.h deleted file mode 100644 index 34dcac76a..000000000 --- a/rialto-master/media/public/include/IMediaPipelineClient.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ -#define FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ - -#include -#include -#include -#include - -/** - * @file IMediaPipelineClient.h - * - * The definition of the IMediaPipelineClient interface. - * - * This file comprises the definition of the IMediaPipelineClient abstract - * class. This is the API by which a IMediaPipeline implementation will - * pass notifications to its client. - */ - -namespace firebolt::rialto -{ -/* Values representing custom duration values, used by IMediaPipelineClient::notifyDuration() method*/ -/** - * @brief Stream duration is unknown or undefined - * - */ -constexpr int64_t kDurationUnknown{-1}; -/** - * @brief Stream duration is unending or live - */ -constexpr int64_t kDurationUnending{-2}; - -/** - * @brief The Rialto media player client interface. - * - * This is The Rialto media player client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the - * state of the player or that provides data for media playback. - */ -class IMediaPipelineClient -{ -public: - /** - * @brief Virtual destructor - */ - virtual ~IMediaPipelineClient() {} - - /** - * @brief Notifies the client of the total duration of the media. - * - * This method notifies the client of the total duration of the - * media in nanoseconds. If this is unknown or undefined then a value - * of kDurationUnknown. If the stream is unending, for example - * live, then a value of kDurationUnending should be used. - * - * @param[in] duration : The duration of the media in seconds. - */ - virtual void notifyDuration(int64_t duration) = 0; - - /** - * @brief Notifies the client of the current playback position. - * - * This method notifies the client of the current playback position - * in nanoseconds. - * - * When playing this should be called often enough to provide - * sufficient granularity of position reporting. Typically this will - * be every 0.25s. - * - * @param[in] position : The playback position in nanoseconds. - */ - virtual void notifyPosition(int64_t position) = 0; - - /** - * @brief Notifies the client of the native size of the video and - the pixel aspect ratio. - * - * This method should be called one or more times to reporting the - * native video size. If the video size changes the method should be - * called with the updated size or aspect ratio. - * - * @param[in] width : The width in pixels. - * @param[in] height : The height in pixels. - * @param[in] aspect : The pixel aspect ratio. - */ - virtual void notifyNativeSize(uint32_t width, uint32_t height, double aspect = 1.0) = 0; - - /** - * @brief Notifies the client of the network state. - * - * The network state reflects the state of the network. For backend - * streaming, this is important as the backend uses the network to obtain the media data directly. - * - * For streaming that uses the browser to obtain data, say Media Source - * Extensions playback, only the states NetworkState::IDLE, - * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be - * indicated by the backend. - * - * @param[in] state : The new network state. - */ - virtual void notifyNetworkState(NetworkState state) = 0; - - /** - * @brief Notifies the client of the playback state. - * - * The player will start IDLE. Once play() has been called the player - * will be PLAYING, or once pause() has been called the player will be - * PAUSED. A seek() request will result in SEEKING and once the seek - * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED - * state will be issued after a stop() request. - * - * @param[in] state : The new playback state. - */ - virtual void notifyPlaybackState(PlaybackState state) = 0; - - /** - * @brief Notifies the client that video data is available - * - * @param[in] hasData true if video data is available. - */ - virtual void notifyVideoData(bool hasData) = 0; - - /** - * @brief Notifies the client that audio data is available - * - * @param[in] hasData true if audio data is available. - */ - virtual void notifyAudioData(bool hasData) = 0; - - /** - * @brief Notifies the client that we need media data. - * - * This method notifies the client that we need media data from the - * client. This is only used when Media Source Extensions are used. - * In that case media is read by JavaScript and buffered by the - * browser before being passed to this API for decoding. - * - * You cannot request data if a data request is currently pending. - * - * The frames the client sends should meet the criteria: - * numFramesSent <= frameCount - * numBytesSent <= maxMediaBytes - * - * @param[in] sourceId : The source to read data from. - * @param[in] frameCount : The number of frames to read. - * @param[in] needDataRequestId : Need data request id. - * @param[in] shmInfo : Information for populating the shared memory (null if not applicable to the client). - */ - virtual void notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, - const std::shared_ptr &shmInfo) = 0; - - /** - * @brief Notifies the client to cancel any outstand need request. - * - * This method notifies the client to cancel any data request made using - * notifyNeedMediaData(). It is not an error to cancel a request for data - * when one is not pending. - * - * @param[in] sourceId : The source id to cancel the request for. - */ - virtual void notifyCancelNeedMediaData(int32_t sourceId) = 0; - - /** - * @brief Notifies the client of a Quality Of Service update from the Player. - * - * Notification shall be sent whenever a video/audio buffer drops a frame/sample. - * - * @param[in] sourceId : The id of the source that produced the Qos. - * @param[in] qosInfo : The information provided in the update. - */ - virtual void notifyQos(int32_t sourceId, const QosInfo &qosInfo) = 0; - - /** - * @brief Notifies the client that buffer underflow occurred. - * - * Notification shall be sent whenever a video/audio buffer underflow occurs - * - * @param[in] sourceId : The id of the source that produced the buffer underflow - */ - virtual void notifyBufferUnderflow(int32_t sourceId) = 0; - - /** - * @brief Notifies the client that a non-fatal error has occurred in the player. - * - * PlaybackState remains unchanged when an error occurs. - * - * @param[in] sourceId : The id of the source that produced the error. - * @param[in] error : The type of error that occured. - */ - virtual void notifyPlaybackError(int32_t sourceId, PlaybackError error) = 0; - - /** - * @brief Notifies the client that the source has been flushed. - * - * Notification shall be sent whenever a flush procedure is finished. - * - * @param[in] sourceId : The id of the source that has been flushed. - */ - virtual void notifySourceFlushed(int32_t sourceId) = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_MEDIA_PIPELINE_CLIENT_H_ diff --git a/rialto-master/media/public/include/IWebAudioPlayer.h b/rialto-master/media/public/include/IWebAudioPlayer.h deleted file mode 100644 index b61993910..000000000 --- a/rialto-master/media/public/include/IWebAudioPlayer.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ -#define FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ - -/** - * @file IWebAudioPlayer.h - * - * The definition of the IWebAudioPlayer interface. - * - * This interface defines the public API of Rialto for mixing PCM audio with - * current audio output. - */ - -#include -#include -#include - -#include "IWebAudioPlayerClient.h" -#include "MediaCommon.h" - -namespace firebolt::rialto -{ -class IWebAudioPlayer; - -/** - * @brief IWebAudioPlayer factory class, returns a concrete implementation of IWebAudioPlayer - */ -class IWebAudioPlayerFactory -{ -public: - IWebAudioPlayerFactory() = default; - virtual ~IWebAudioPlayerFactory() = default; - - /** - * @brief Create a IWebAudioPlayerFactory instance. - * - * @retval the factory instance or null on error. - */ - static std::shared_ptr createFactory(); - - /** - * @brief IWebAudioPlayer factory method, returns a concrete implementation of - * IWebAudioPlayer for playback of audio. - * - * @param[in] client: The Web Audio Player client - * @param[in] audioMimeType: The audio encoding format, currently only "audio/x-raw" (PCM) - * @param[in] priority: Priority value for this pipeline. - * @param[in] config: Additional type dependent configuration data or nullptr - * - * Some platforms have limited numbers of audio playbacks that can be mixed. The client application - * should therefore assign a priority to each audio player it creates, starting with priority 1 for - * the most important, priority 2 for the next etc. If a platform supports 'n' players, then any - * player with priority>n will appear to function normally by but the audio data will be silently - * discarded. - * - * @retval the new Web Audio Player instance or null on error. - */ - virtual std::unique_ptr createWebAudioPlayer(std::weak_ptr client, - const std::string &audioMimeType, - const uint32_t priority, - std::weak_ptr config) const = 0; -}; - -/** - * @brief The definition of the IWebAudioPlayer interface. - * - * This interface defines the public API of Rialto for mixing PCM audio with - * current audio output. It should be implemented by both Rialto Client & - * Rialto Server. - */ -class IWebAudioPlayer -{ -public: - IWebAudioPlayer() = default; - virtual ~IWebAudioPlayer() = default; - - IWebAudioPlayer(const IWebAudioPlayer &) = delete; - IWebAudioPlayer &operator=(const IWebAudioPlayer &) = delete; - IWebAudioPlayer(IWebAudioPlayer &&) = delete; - IWebAudioPlayer &operator=(IWebAudioPlayer &&) = delete; - - /** - * @brief Play the web audio. - * - * Sets the player to the PLAYING state (it is IDLE when created). - * - * @retval true on success. - */ - virtual bool play() = 0; - - /** - * @brief Pause the web audio. - * - * Sets the player to the PAUSED state (it is IDLE when created). - * - * @retval true on success. - */ - virtual bool pause() = 0; - - /** - * @brief Notify EOS. - * - * Notifies the player that no further frames will be provided. When - * all buffered frames are played the player will enter the EOS state. - * - * @retval true on success. - */ - virtual bool setEos() = 0; - - /** - * @brief Get the available frames. - * - * Gets the available buffer space for sending more frames. Client should not - * write more than the number of frames returned by this API. - * - * webAudioShmInfo is not required by the client application and can be ignored. - * - * @param[out] availableFrames : Number of frames available to be written. - * @param[out] webAudioShmInfo : Location in shm to write the data (Server only). - * - * @retval true on success. - */ - virtual bool getBufferAvailable(uint32_t &availableFrames, std::shared_ptr &webAudioShmInfo) = 0; - - /** - * @brief Get the delay frames. - * - * Gets the frame delay of the playback from Rialto. Frame delay is the number - * of frames left to play by the server. - * - * @param[out] delayFrames : Number of frames to be played. - * - * @retval true on success. - */ - virtual bool getBufferDelay(uint32_t &delayFrames) = 0; - - /** - * @brief Write audio frames - * - * Sends a buffer of audio data for playback - * - * @param[in] numberOfFrames : Number of frames of audio in 'data'. - * @param[in] data : Pointer to the data, byte length = numberOfFrames*sampleSize - * - * @retval true on success. - */ - virtual bool writeBuffer(const uint32_t numberOfFrames, void *data) = 0; - - /** - * @brief Get device information. - * - * Gets information for the web audio playback. - * This information is used to determine the preferred buffer size to commit, - * the maximum buffer size an application can commit and whether buffers can - * be committed before a Play request. - * - * @param[out] preferredFrames : preferred number of frames to be commited. - * @param[out] maximumFrames : Maximum number of frames that can be commited. - * @param[out] supportDeferredPlay : Whether defered play is supported. - * - * @retval true on success. - */ - virtual bool getDeviceInfo(uint32_t &preferredFrames, uint32_t &maximumFrames, bool &supportDeferredPlay) = 0; - - /** - * - * @brief Set level and transition of audio attenuation - * - * Sets the current volume for the pipeline (0.0 silent -> 1.0 full volume) - * - * @param[in] volume : Target volume level (0.0 - 1.0) - * - * @retval true on success false otherwise - */ - virtual bool setVolume(double volume) = 0; - - /** - * @brief Get current audio level - * - * Fetches the current volume level for the pipeline. - * - * @param[out] volume : Current volume level (range 0.0 - 1.0) - * - * @retval true on success false otherwise - */ - virtual bool getVolume(double &volume) = 0; - - /** - * @brief Returns the web audio player client. - * - * @retval The web audio player client. - */ - virtual std::weak_ptr getClient() = 0; -}; - -}; // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_H_ diff --git a/rialto-master/media/public/include/IWebAudioPlayerClient.h b/rialto-master/media/public/include/IWebAudioPlayerClient.h deleted file mode 100644 index 8820bf26c..000000000 --- a/rialto-master/media/public/include/IWebAudioPlayerClient.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ -#define FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ - -/** - * @file IWebAudioPlayerClient.h - * - * The definition of the IWebAudioPlayerClient interface. - * - * This is the API by which a IWebAudioPlayer implementation will - * pass notifications to its client. - */ - -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief The Rialto web audio client interface. - * - * This is The Rialto web audio player client abstract base class. It should be - * implemented by any object that wishes to be notified by changes in the - * state of the web audio player. - */ -class IWebAudioPlayerClient -{ -public: - /** - * @brief Virtual destructor - */ - virtual ~IWebAudioPlayerClient() {} - - /** - * @brief Notifies the client of the playback state. - * - * The player will start IDLE. Once play() has been called the player - * will be PLAYING. When pause() is call3d the player will be PAUSED. - * When no further frames available for playout and setEos() has been - * called the player will be END_OF_STREAM. - * - * @param[in] state : The new playback state. - */ - virtual void notifyState(WebAudioPlayerState state) = 0; -}; - -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_I_WEB_AUDIO_PLAYER_CLIENT_H_ diff --git a/rialto-master/media/public/include/MediaCommon.h b/rialto-master/media/public/include/MediaCommon.h deleted file mode 100644 index 2e783e032..000000000 --- a/rialto-master/media/public/include/MediaCommon.h +++ /dev/null @@ -1,468 +0,0 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FIREBOLT_RIALTO_MEDIA_COMMON_H_ -#define FIREBOLT_RIALTO_MEDIA_COMMON_H_ - -/** - * @file MediaCommon.h - * - * The definition of the Rialto Common types - * - */ - -#include -#include -#include -#include -#include -#include - -namespace firebolt::rialto -{ -/** - * @brief The value of an invalid key session. - */ -constexpr int32_t kInvalidSessionId{-1}; - -/** - * @brief The value of an invalid audio channels number. - */ -constexpr uint32_t kInvalidAudioChannels{0}; - -/** - * @brief The value of an invalid audio sampling rate. - */ -constexpr uint32_t kInvalidAudioSampleRate{0}; - -/** - * @brief The value of an undefined size - */ -constexpr int32_t kUndefinedSize{0}; - -/** - * @brief The value of an invalid limitBuffering - */ -constexpr uint32_t kInvalidLimitBuffering{std::numeric_limits::max()}; - -/** - * @brief The value of undefined position - */ -constexpr uint64_t kUndefinedPosition{std::numeric_limits::max()}; - -/** - * @brief The supported types of media source. - */ -enum class MediaSourceType -{ - UNKNOWN, - AUDIO, - VIDEO, - SUBTITLE -}; - -/** - * @brief Shows the types of source configuration. - */ -enum class SourceConfigType -{ - UNKNOWN, - AUDIO, - VIDEO, - VIDEO_DOLBY_VISION, - SUBTITLE -}; - -/** - * @brief The supported audio ease types. - */ -enum class AudioEaseType -{ - LINEAR = 0, - INCUBIC, - OUTCUBIC -}; - -/** - * @brief The media type of media to be played. - */ -enum class MediaType -{ - UNKNOWN, /**< Media type not known. */ - MSE /**< Media is MSE and will request data. */ -}; - -/** - * @brief The media source status. This is the status of the source - * after a read. - */ -enum class MediaSourceStatus -{ - OK, /**< Source data provided without error. */ - EOS, /**< Source reached the end of stream. */ - ERROR, /**< There was an error providing source data. */ - CODEC_CHANGED, /**< The codec has changed and the decoder must be reconfigured */ - NO_AVAILABLE_SAMPLES /**< Could not retrieve media samples. */ -}; - -/** - * @brief The Network State - * - * The network state reflects the state of the network. For backend - * streaming, say using MediaPipelineURLDelegate, this is important - * as the backend uses the network to obtain the media data directly. - * - * For streaming that uses the browser to obtain data, say Media Source - * Extensions playback, only the states NetworkState::IDLE, - * NetworkState::BUFFERED and NetworkState::DECODE_ERROR should be - * indicated by the backend. - */ -enum class NetworkState -{ - UNKNOWN, /**< An unknown or undefined network state. */ - IDLE, /**< The network is idle. */ - BUFFERING, /**< The network is buffering data before playing. */ - BUFFERING_PROGRESS, /**< The network is buffering data whilst playing. */ - BUFFERED, /**< All the data is buffered. */ - STALLED, /**< The network has stalled but may recover. */ - FORMAT_ERROR, /**< The data is the wrong format. */ - NETWORK_ERROR, /**< There has been a network error. Playback stops. */ - DECODE_ERROR /**< There has been a decode error of the data. */ -}; - -/** - * @brief The Playback State - * - * The player will start IDLE. Once play() has been called the player - * will be PLAYING, or once pause() has been called the player will be - * PAUSED. A seek() request will result in SEEKING and once the seek - * is complete SEEK_DONE will be issued followed by PLAYING. The STOPPED - * state will be issued after a stop() request. - */ -enum class PlaybackState -{ - UNKNOWN, /**< An unknown or undefined playback state. */ - IDLE, /**< The backend player is idle. */ - PLAYING, /**< The backend player is playing media. */ - PAUSED, /**< The backend player is paused. */ - SEEKING, /**< The backend player is seeking a new playback position. */ - SEEK_DONE, /**< The backend player has finished seek. */ - STOPPED, /**< The backend player has stopped playback. */ - END_OF_STREAM, /**< The backend player has got to the end of playback. */ - FAILURE /**< The backend player failed to set playback state. */ -}; - -/** - * @brief The Format of the audio samples. Used by the raw audio media types - */ -enum class Format -{ - S8, - U8, - S16LE, - S16BE, - U16LE, - U16BE, - S24_32LE, - S24_32BE, - U24_32LE, - U24_32BE, - S32LE, - S32BE, - U32LE, - U32BE, - S24LE, - S24BE, - U24LE, - U24BE, - S20LE, - S20BE, - U20LE, - U20BE, - S18LE, - S18BE, - U18LE, - U18BE, - F32LE, - F32BE, - F64LE, - F64BE -}; - -/** - * @brief The layout of channels within a buffer. Used by the raw audio media types - */ -enum class Layout -{ - INTERLEAVED, - NON_INTERLEAVED -}; - -/** - * @brief Audio specific configuration - */ -struct AudioConfig -{ - uint32_t numberOfChannels = kInvalidAudioChannels; /**< The number of channels. */ - uint32_t sampleRate = kInvalidAudioSampleRate; /**< The sampling rate.*/ - std::vector codecSpecificConfig; /**< The audio specific config. Zero length if no specific config*/ - std::optional format; /**< The Format of the audio samples.*/ - std::optional layout; /**< The layout of channels within a buffer.*/ - std::optional channelMask; /**< Bitmask of channel positions present. */ - std::vector> streamHeader; /**< Stream header. Zero length if not present.*/ - std::optional - framed; /**< True if each buffer passed through the pipeline contains a complete, self-contained media unit*/ -}; - -/** - * @brief AddSegmentStatus - * - * The add segment status. This is the status adding new segment to Rialto - */ -enum class AddSegmentStatus -{ - OK, /**< Segment accepted. */ - NO_SPACE, /**< Too many frames sent or Rialto does not currently have space for this segment. */ - ERROR /**< Unexpected error. */ -}; - -/** - * @brief A pair describing the clear and encrypted bytes - * in a sub-sample. - */ -struct SubSamplePair -{ - size_t numClearBytes; /**< The number of clear bytes in the sample. */ - size_t numEncryptedBytes; /**< The number of encrypted bytes in the sample. */ -}; - -/** - * @brief Video decoder requirements used to allocate a suitable decoder for a MediaPipeline session - */ -struct VideoRequirements -{ - uint32_t maxWidth; /**< Maximum width of video frames to be decoded. */ - uint32_t maxHeight; /**< Maximum height of video frames to be decoded. */ -}; - -/** - * @brief Information about the shared memory required for writting data. - */ -struct MediaPlayerShmInfo -{ - uint32_t maxMetadataBytes; /**< The maximum amount of metadata that can be written. */ - uint32_t metadataOffset; /**< The offset to write the metadata. */ - uint32_t mediaDataOffset; /**< The offset to write the media data. */ - uint32_t maxMediaBytes; /**< The maximum amount of mediadata that can be written. */ -}; - -/** - * @brief The information provided in a QOS update. - */ -struct QosInfo -{ - uint64_t processed; /**< The total number of video frames/audio samples processed since MediaPipeline:load. */ - uint64_t dropped; /**< The total number of video frames/audio samples dropped since MediaPipeline:load. */ -}; - -/** - * @brief The error return status for session management methods. - */ -enum class MediaKeyErrorStatus -{ - OK, /**< No error. */ - FAIL, /**< An unspecified error occurred. */ - BAD_SESSION_ID, /**< The session id is not recognised. */ - NOT_SUPPORTED, /**< The request parameters are not supported. */ - INVALID_STATE, /**< The object is in an invalid state for the operation. */ - INTERFACE_NOT_IMPLEMENTED, /**< The interface is not implemented. */ - BUFFER_TOO_SMALL /**< The size of the buffer is too small. */ -}; - -/** - * @brief The media key session type. - */ -enum class KeySessionType -{ - UNKNOWN, /**< The session type is unknown. */ - TEMPORARY, /**< The session is a temporary session. */ - PERSISTENT_LICENCE, /**< The session is a persistent session. */ - PERSISTENT_RELEASE_MESSAGE /**< The session's persistent licence should be released. */ -}; - -/** - * @brief The init data type. - */ -enum class InitDataType -{ - UNKNOWN, /**< The init data type is unknown. */ - CENC, /**< The init data is in CENC format. */ - KEY_IDS, /**< The init data is key ids. */ - WEBM, /**< The init data is in WEBM format. */ - DRMHEADER /**< The init data is in DrmHeader format. */ -}; - -/** - * @brief The key status. - */ -enum class KeyStatus -{ - USABLE, - EXPIRED, - OUTPUT_RESTRICTED, - PENDING, - INTERNAL_ERROR, - RELEASED -}; - -/** - * @brief The alignment of media segment - */ -enum class SegmentAlignment -{ - UNDEFINED, - NAL, - AU -}; - -/** - * @brief The Stream Format of media segment - */ -enum class StreamFormat -{ - UNDEFINED, - RAW, - AVC, - BYTE_STREAM, - HVC1, - HEV1 -}; - -/** - * @brief A vector of key ID/key status pairs. - */ -typedef std::vector, KeyStatus>> KeyStatusVector; - -/** - * @brief Information about the shared memory required for writting data for the web audio playback. - */ -struct WebAudioShmInfo -{ - uint32_t offsetMain; /**< The offset to start writing the audio data. */ - uint32_t lengthMain; /**< The maximum number of bytes to write at offsetMain. */ - uint32_t offsetWrap; /**< The offset to continue writing the audio data if buffer wrapped. */ - uint32_t lengthWrap; /**< The maximum number of bytes to write at offsetWrap. */ -}; - -/** - * @brief Pcm config information. - */ -struct WebAudioPcmConfig -{ - uint32_t rate; /**< Rate of web audio (Hz) */ - uint32_t channels; /**< Number of channels */ - uint32_t sampleSize; /**< Size of each sample (bits) */ - bool isBigEndian; /**< Specifies if sample is stored as big-endian or little-endian format */ - bool isSigned; /**< Specifies if samples are signed or unsigned */ - bool isFloat; /**< Specifies if samples are float values or interger values*/ -}; - -/** - * @brief Type dependent configuration data. - */ -union WebAudioConfig -{ - /** - * @brief PCM audio configuration. - */ - WebAudioPcmConfig pcm; -}; - -/** - * @brief The Web Audio Player State. - */ -enum class WebAudioPlayerState -{ - UNKNOWN, /**< An unknown or undefined playback state. */ - IDLE, /**< The player is ready to play media. */ - PLAYING, /**< The player is playing media. */ - PAUSED, /**< The player is has paused media playback. */ - END_OF_STREAM, /**< The player has got to the end of playback. */ - FAILURE /**< The player failed to set playback state. */ -}; - -/** - * @brief Cipher mode for common encryption, see https://www.iso.org/obp/ui/#iso:std:iso-iec:23001:-7:ed-3:v1:en - */ -enum class CipherMode -{ - UNKNOWN, - CENC, /* AES-CTR scheme */ - CBC1, /* AES-CBC scheme */ - CENS, /* AES-CTR subsample pattern encryption scheme */ - CBCS /* AES-CBC subsample pattern encryption scheme */ -}; - -/** - * @brief Fraction type. - */ -struct Fraction -{ - int32_t numerator; /**< The numerator */ - int32_t denominator; /**< The denominator */ -}; - -/** - * @brief Codec data type. - */ -enum class CodecDataType -{ - BUFFER, - STRING -}; - -/** - * @brief Codec data with type. - */ -struct CodecData -{ - std::vector data{}; /**< The codec data */ - CodecDataType type{CodecDataType::BUFFER}; /**< The codec data type */ -}; - -/** - * @brief None fatal asynchronous errors reported by the player. - */ -enum class PlaybackError -{ - UNKNOWN, - DECRYPTION, /* Player failed to decrypt a buffer and the frame has been dropped */ -}; - -/** - * @brief Ease type for audio volume changes. - */ -enum class EaseType -{ - EASE_LINEAR, - EASE_IN_CUBIC, - EASE_OUT_CUBIC -}; - -} // namespace firebolt::rialto - -#endif // FIREBOLT_RIALTO_MEDIA_COMMON_H_ diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index 88f108b78..b3e1418a5 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -1,104 +1,114 @@ - #include "rialto-gst-pipeline.h" #include #include +#include GstMediaPipeline::GstMediaPipeline() { - printf("constructing GstMediaPipeline (Rialto-backed)\n"); + std::cout << "Constructing GstMediaPipeline (Rialto public API)\n"; + if (!gst_is_initialized()) { - int argc = 0; char **argv = nullptr; gst_init(&argc, &argv); + int argc = 0; char **argv = nullptr; + gst_init(&argc, &argv); } + m_messageQueueFactory = IMessageQueueFactory::createFactory(); - m_clientBackend = std::make_shared(); - const uint32_t maxW = DEFAULT_MAX_VIDEO_WIDTH; - const uint32_t maxH = DEFAULT_MAX_VIDEO_HEIGHT; - m_mseClient = std::make_shared(m_messageQueueFactory, m_clientBackend, maxW, maxH); - if (!m_mseClient->createBackend()) - { - fprintf(stderr, "Failed to create Rialto media pipeline backend\n"); - } + m_rialtoClient = IClient::createClient(m_messageQueueFactory); } GstMediaPipeline::~GstMediaPipeline() { - printf("destructing GstMediaPipeline (Rialto-backed)\n"); - if (m_clientBackend) + std::cout << "Destructing GstMediaPipeline\n"; + if (m_rialtoClient) { - m_clientBackend->stop(); + m_rialtoClient->stop(); } - m_mseClient.reset(); - m_clientBackend.reset(); + m_rialtoClient.reset(); m_messageQueueFactory.reset(); } bool GstMediaPipeline::play() { - printf("play (Rialto backend)\n"); - if (!m_clientBackend) + if (!m_rialtoClient) { - fprintf(stderr, "play(): backend not created\n"); + std::cerr << "play(): Rialto client not initialized\n"; return false; } - return m_clientBackend->play(); + return m_rialtoClient->play(); } bool GstMediaPipeline::removeSource(int32_t id) { - if (!m_clientBackend) return false; - return m_clientBackend->removeSource(id); + if (!m_rialtoClient) return false; + return m_rialtoClient->removeSource(id); } bool GstMediaPipeline::allSourcesAttached() { - if (!m_clientBackend) return false; - return m_clientBackend->allSourcesAttached(); + if (!m_rialtoClient) return false; + return m_rialtoClient->allSourcesAttached(); } bool GstMediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url) -{ - if (!m_clientBackend) return false; - return m_clientBackend->load(type, mimeType, url); +{ + if (!m_rialtoClient) return false; + return m_rialtoClient->load(type, mimeType, url); } AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) { - if (!m_clientBackend) - { - return AddSegmentStatus::ERROR; - } - return m_clientBackend->addSegment(needDataRequestId, mediaSegment); + if (!m_rialtoClient) return AddSegmentStatus::ERROR; + return m_rialtoClient->addSegment(needDataRequestId, mediaSegment); } bool GstMediaPipeline::attachSource(const std::unique_ptr &source) { - if (!m_clientBackend) - { - fprintf(stderr, "attachSource(): backend not ready\n"); - return false; - } - if (!source) - { - fprintf(stderr, "attachSource(): null source\n"); - return false; - } - // Create a copy we can hand to backend (it may mutate id inside copy) + if (!m_rialtoClient || !source) return false; + std::unique_ptr temp = source->copy(); - if (!temp) - { - fprintf(stderr, "attachSource(): copy failed\n"); - return false; - } - bool ok = m_clientBackend->attachSource(temp); - if (!ok) - { - fprintf(stderr, "attachSource(): backend attach failed\n"); - return false; - } - // Propagate assigned id back to original + if (!temp) return false; + + bool ok = m_rialtoClient->attachSource(temp); + if (!ok) return false; + const int32_t assignedId = temp->getId(); const_cast(source.get())->setId(assignedId); - printf("attachSource() -> sourceId=%d (Rialto backend)\n", assignedId); + return true; } + +// Remaining IMediaPipeline methods just return default false or 0 +bool GstMediaPipeline::pause() { return m_rialtoClient ? m_rialtoClient->pause() : false; } +bool GstMediaPipeline::stop() { return m_rialtoClient ? m_rialtoClient->stop() : false; } +bool GstMediaPipeline::setPlaybackRate(double rate) { return false; } +bool GstMediaPipeline::setPosition(int64_t position) { return false; } +bool GstMediaPipeline::getPosition(int64_t &position) { position = 0; return false; } +bool GstMediaPipeline::getStats(int32_t, uint64_t &renderedFrames, uint64_t &droppedFrames) +{ renderedFrames = droppedFrames = 0; return false; } +bool GstMediaPipeline::setImmediateOutput(int32_t, bool) { return false; } +bool GstMediaPipeline::getImmediateOutput(int32_t, bool &) { return false; } +bool GstMediaPipeline::setVideoWindow(uint32_t, uint32_t, uint32_t, uint32_t) { return false; } +bool GstMediaPipeline::haveData(MediaSourceStatus, uint32_t) { return false; } +bool GstMediaPipeline::renderFrame() { return false; } +bool GstMediaPipeline::setVolume(double, uint32_t, EaseType) { return false; } +bool GstMediaPipeline::getTextTrackIdentifier(std::string &) { return false; } +bool GstMediaPipeline::setLowLatency(bool) { return false; } +bool GstMediaPipeline::setSync(bool) { return false; } +bool GstMediaPipeline::getSync(bool &) { return false; } +bool GstMediaPipeline::setSyncOff(bool) { return false; } +bool GstMediaPipeline::setStreamSyncMode(int32_t, int32_t) { return false; } +bool GstMediaPipeline::getStreamSyncMode(int32_t &) { return false; } +bool GstMediaPipeline::flush(int32_t, bool, bool &) { return false; } +bool GstMediaPipeline::setSourcePosition(int32_t, int64_t, bool, double, uint64_t) { return false; } +bool GstMediaPipeline::setSubtitleOffset(int32_t, int64_t) { return false; } +bool GstMediaPipeline::processAudioGap(int64_t, uint32_t, int64_t, bool) { return false; } +bool GstMediaPipeline::setBufferingLimit(uint32_t) { return false; } +bool GstMediaPipeline::getBufferingLimit(uint32_t &) { return false; } +bool GstMediaPipeline::setUseBuffering(bool) { return false; } +bool GstMediaPipeline::getUseBuffering(bool &) { return false; } +bool GstMediaPipeline::switchSource(const std::unique_ptr &) { return false; } +bool GstMediaPipeline::getVolume(double &) { return false; } +bool GstMediaPipeline::setMute(int32_t, bool) { return false; } +bool GstMediaPipeline::getMute(int32_t, bool &) { return false; } +bool GstMediaPipeline::setTextTrackIdentifier(const std::string &) { return false; } diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h index 8bfa9705e..4e61cffff 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.h +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -1,73 +1,69 @@ #ifndef GST_MEDIA_PIPELINE_H #define GST_MEDIA_PIPELINE_H -#include "IMediaPipeline.h" -// Rialto gstreamer client side helpers -#include "GStreamerMSEMediaPlayerClient.h" -#include "MediaPlayerClientBackend.h" -#include "IMessageQueue.h" +#include +#include +#include +#include #include using namespace firebolt::rialto; -class GstMediaPipeline:IMediaPipeline +class GstMediaPipeline : public IMediaPipeline { private: - // New Rialto-backed objects replacing manual playbin/appsrc construction - std::shared_ptr m_messageQueueFactory; // creates async queues used by client - std::shared_ptr m_clientBackend; // thin wrapper over IMediaPipeline - std::shared_ptr m_mseClient; // implements IMediaPipelineClient callbacks + std::shared_ptr m_rialtoClient; + std::shared_ptr m_messageQueueFactory; protected: - std::weak_ptr client; // legacy handle if external code sets it - std::weak_ptr getClient(){ return client; } + std::weak_ptr client; + std::weak_ptr getClient() { return client; } public: - // Legacy helper retained for compatibility (now unused) - void found_source( GObject *orig, GParamSpec *pspec, int sourceId ){}; GstMediaPipeline(); ~GstMediaPipeline(); - - bool pause(){ return false; }; - bool stop(){ return false; }; - bool setPlaybackRate(double rate){ return false; }; - bool setPosition(int64_t position){ return false; }; - bool getPosition(int64_t &position){ return false; }; - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames){ return false; }; - bool setImmediateOutput(int32_t sourceId, bool immediateOutput){ return false; }; - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput){ return false; }; - bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height){ return false; }; - bool haveData(MediaSourceStatus status, uint32_t needDataRequestId){ return false; }; - bool renderFrame(){ return false; }; - bool setVolume(double targetVolume, uint32_t volumeDuration = 0, EaseType easeType = EaseType::EASE_LINEAR){ return false; }; - bool getTextTrackIdentifier(std::string &textTrackIdentifier){ return false; }; - bool setLowLatency(bool lowLatency){ return false; }; - bool setSync(bool sync){ return false; }; - bool getSync(bool &sync){ return false; }; - bool setSyncOff(bool syncOff){ return false; }; - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode){ return false; }; - bool getStreamSyncMode(int32_t &streamSyncMode){ return false; }; - bool flush(int32_t sourceId, bool resetTime, bool &async){ return false; }; - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, uint64_t stopPosition = kUndefinedPosition){ return false; }; - bool setSubtitleOffset(int32_t sourceId, int64_t position){ return false; }; - bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac){ return false; }; - bool setBufferingLimit(uint32_t limitBufferingMs){ return false; }; - bool getBufferingLimit(uint32_t &limitBufferingMs){ return false; }; - bool setUseBuffering(bool useBuffering){ return false; }; - bool getUseBuffering(bool &useBuffering){ return false; }; - bool switchSource(const std::unique_ptr &source){ return false; }; - bool getVolume(double ¤tVolume){ return false; } - bool setMute(int32_t sourceId, bool mute){ return false; } - bool getMute(int32_t sourceId, bool &mute){ return false; } - bool setTextTrackIdentifier(const std::string &textTrackIdentifier){ return false; } - - // Rialto native pattern: attach source; after true, caller reads source->getId() - bool attachSource(const std::unique_ptr &source); - bool removeSource(int32_t id); - bool allSourcesAttached(); - bool load(MediaType type, const std::string &mimeType, const std::string &url); - bool play(); - AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment); + + // IMediaPipeline interface + bool pause() override; + bool stop() override; + bool setPlaybackRate(double rate) override; + bool setPosition(int64_t position) override; + bool getPosition(int64_t &position) override; + bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; + bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override; + bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override; + bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override; + bool renderFrame() override; + bool setVolume(double targetVolume, uint32_t volumeDuration = 0, EaseType easeType = EaseType::EASE_LINEAR) override; + bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; + bool setLowLatency(bool lowLatency) override; + bool setSync(bool sync) override; + bool getSync(bool &sync) override; + bool setSyncOff(bool syncOff) override; + bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; + bool getStreamSyncMode(int32_t &streamSyncMode) override; + bool flush(int32_t sourceId, bool resetTime, bool &async) override; + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, uint64_t stopPosition = kUndefinedPosition) override; + bool setSubtitleOffset(int32_t sourceId, int64_t position) override; + bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; + bool setBufferingLimit(uint32_t limitBufferingMs) override; + bool getBufferingLimit(uint32_t &limitBufferingMs) override; + bool setUseBuffering(bool useBuffering) override; + bool getUseBuffering(bool &useBuffering) override; + bool switchSource(const std::unique_ptr &source) override; + bool getVolume(double ¤tVolume) override; + bool setMute(int32_t sourceId, bool mute) override; + bool getMute(int32_t sourceId, bool &mute) override; + bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; + + // Rialto pattern: attach source; after true, caller reads source->getId() + bool attachSource(const std::unique_ptr &source) override; + bool removeSource(int32_t id) override; + bool allSourcesAttached() override; + bool load(MediaType type, const std::string &mimeType, const std::string &url) override; + bool play() override; + AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; }; #endif // GST_MEDIA_PIPELINE_H From 7f9d291cc3fc1f69cccc47e5732d12e9e7304b6e Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Thu, 27 Nov 2025 15:29:48 -0500 Subject: [PATCH 10/21] TEST-DO NOT MERGE Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-gst-pipeline.cpp | 77 +++++++-------------- test/gstTestHarness/rialto-gst-pipeline.h | 11 +-- 2 files changed, 26 insertions(+), 62 deletions(-) diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index b3e1418a5..4250aa544 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -1,91 +1,62 @@ #include "rialto-gst-pipeline.h" -#include -#include #include GstMediaPipeline::GstMediaPipeline() { - std::cout << "Constructing GstMediaPipeline (Rialto public API)\n"; + std::cout << "Constructing GstMediaPipeline (Rialto-managed, public API)\n"; - if (!gst_is_initialized()) - { - int argc = 0; char **argv = nullptr; - gst_init(&argc, &argv); - } - - m_messageQueueFactory = IMessageQueueFactory::createFactory(); - m_rialtoClient = IClient::createClient(m_messageQueueFactory); + // In Option 2, the pipeline should be obtained via the public API. + // This is a placeholder. In real usage, obtain the pipeline from a factory or inject it. + m_pipeline = nullptr; } GstMediaPipeline::~GstMediaPipeline() { std::cout << "Destructing GstMediaPipeline\n"; - if (m_rialtoClient) - { - m_rialtoClient->stop(); - } - m_rialtoClient.reset(); - m_messageQueueFactory.reset(); -} - -bool GstMediaPipeline::play() -{ - if (!m_rialtoClient) + if (m_pipeline) { - std::cerr << "play(): Rialto client not initialized\n"; - return false; + m_pipeline->stop(); } - return m_rialtoClient->play(); -} - -bool GstMediaPipeline::removeSource(int32_t id) -{ - if (!m_rialtoClient) return false; - return m_rialtoClient->removeSource(id); -} - -bool GstMediaPipeline::allSourcesAttached() -{ - if (!m_rialtoClient) return false; - return m_rialtoClient->allSourcesAttached(); + m_pipeline.reset(); } +// Rialto-managed methods delegate to IMediaPipeline if available +bool GstMediaPipeline::play() { return m_pipeline ? m_pipeline->play() : false; } +bool GstMediaPipeline::removeSource(int32_t id) { return m_pipeline ? m_pipeline->removeSource(id) : false; } +bool GstMediaPipeline::allSourcesAttached() { return m_pipeline ? m_pipeline->allSourcesAttached() : false; } bool GstMediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url) { - if (!m_rialtoClient) return false; - return m_rialtoClient->load(type, mimeType, url); + return m_pipeline ? m_pipeline->load(type, mimeType, url) : false; } -AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) +AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, + const std::unique_ptr &mediaSegment) { - if (!m_rialtoClient) return AddSegmentStatus::ERROR; - return m_rialtoClient->addSegment(needDataRequestId, mediaSegment); + return m_pipeline ? m_pipeline->addSegment(needDataRequestId, mediaSegment) : AddSegmentStatus::ERROR; } bool GstMediaPipeline::attachSource(const std::unique_ptr &source) { - if (!m_rialtoClient || !source) return false; + if (!m_pipeline || !source) return false; std::unique_ptr temp = source->copy(); if (!temp) return false; - bool ok = m_rialtoClient->attachSource(temp); + bool ok = m_pipeline->attachSource(temp); if (!ok) return false; const int32_t assignedId = temp->getId(); const_cast(source.get())->setId(assignedId); - return true; } -// Remaining IMediaPipeline methods just return default false or 0 -bool GstMediaPipeline::pause() { return m_rialtoClient ? m_rialtoClient->pause() : false; } -bool GstMediaPipeline::stop() { return m_rialtoClient ? m_rialtoClient->stop() : false; } -bool GstMediaPipeline::setPlaybackRate(double rate) { return false; } -bool GstMediaPipeline::setPosition(int64_t position) { return false; } +// All other IMediaPipeline methods: return false or default values +bool GstMediaPipeline::pause() { return false; } +bool GstMediaPipeline::stop() { return false; } +bool GstMediaPipeline::setPlaybackRate(double) { return false; } +bool GstMediaPipeline::setPosition(int64_t) { return false; } bool GstMediaPipeline::getPosition(int64_t &position) { position = 0; return false; } -bool GstMediaPipeline::getStats(int32_t, uint64_t &renderedFrames, uint64_t &droppedFrames) -{ renderedFrames = droppedFrames = 0; return false; } +bool GstMediaPipeline::getStats(int32_t, uint64_t &renderedFrames, uint64_t &droppedFrames) { renderedFrames = droppedFrames = 0; return false; } bool GstMediaPipeline::setImmediateOutput(int32_t, bool) { return false; } bool GstMediaPipeline::getImmediateOutput(int32_t, bool &) { return false; } bool GstMediaPipeline::setVideoWindow(uint32_t, uint32_t, uint32_t, uint32_t) { return false; } @@ -111,4 +82,4 @@ bool GstMediaPipeline::switchSource(const std::unique_ptr &) { retu bool GstMediaPipeline::getVolume(double &) { return false; } bool GstMediaPipeline::setMute(int32_t, bool) { return false; } bool GstMediaPipeline::getMute(int32_t, bool &) { return false; } -bool GstMediaPipeline::setTextTrackIdentifier(const std::string &) { return false; } +bool GstMediaPipeline::setTextTrackIdentifier(const std::string &) { return false; } \ No newline at end of file diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h index 4e61cffff..a2b9ab4b2 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.h +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -1,19 +1,14 @@ #ifndef GST_MEDIA_PIPELINE_H #define GST_MEDIA_PIPELINE_H -#include -#include -#include -#include -#include +#include "IMediaPipeline.h" using namespace firebolt::rialto; class GstMediaPipeline : public IMediaPipeline { private: - std::shared_ptr m_rialtoClient; - std::shared_ptr m_messageQueueFactory; + std::shared_ptr m_pipeline; // Rialto-managed pipeline protected: std::weak_ptr client; @@ -56,8 +51,6 @@ class GstMediaPipeline : public IMediaPipeline bool setMute(int32_t sourceId, bool mute) override; bool getMute(int32_t sourceId, bool &mute) override; bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; - - // Rialto pattern: attach source; after true, caller reads source->getId() bool attachSource(const std::unique_ptr &source) override; bool removeSource(int32_t id) override; bool allSourcesAttached() override; From 178c1fd4be4f40277af2caf392be72fbe981726a Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Thu, 27 Nov 2025 16:29:57 -0500 Subject: [PATCH 11/21] TEST - DO NOT MERGE Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 361 ++++++++++---------- test/gstTestHarness/rialto-gst-pipeline.cpp | 92 ++++- test/gstTestHarness/rialto-gst-pipeline.h | 10 +- 3 files changed, 271 insertions(+), 192 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 803134059..64d2316a8 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -1,17 +1,13 @@ -// -// main.cpp -// RialtoSim -// -// Created by Stroffolino, Philip on 9/19/25. -// #include #include #include #include +#include +#include #include "mp4demux.hpp" #include "rialto-gst-pipeline.h" -// Using Rialto pipeline only: define nanosecond conversion locally instead of relying on GST headers. +// Nanosecond conversion for timestamps static const int64_t NS_SECOND = 1000000000LL; static Mp4Demux trackAudio; @@ -22,206 +18,203 @@ static const char *gUserPathPtr; static int32_t sourceIdAudio; static int32_t sourceIdVideo; -void LoadAndDemuxSegment( Mp4Demux &mp4Demux, const char *path ) -{ // using generated bipbop content for initial test - // char fullpath[256]; - // snprintf( fullpath, sizeof(fullpath), "%.*s/Documents/r" "d" "k" "e/aamp_test_internal/test/VideoTestStream/bipbop-gen/%s", - // gUserPathLen, gUserPathPtr, path ); - char fullpath[512]; - snprintf(fullpath, sizeof(fullpath), "/tmp/data/bipbop-gen/%s", path); - printf( "loading rialtotest %s\n", fullpath ); - FILE *f = fopen(fullpath, "rb"); - assert( f ); - if( f ) - { - fseek( f,0,SEEK_END ); - long len = ftell(f); - if( len>0 ) - { - unsigned char *ptr = (unsigned char *)malloc(len); - assert( ptr ); - if( ptr ) - { - fseek( f, 0, SEEK_SET ); - size_t n = fread( ptr, 1, len, f ); - assert( n == len ); - if( n==len ) - { - mp4Demux.Parse( ptr, len ); - } - } - } - fclose( f ); - } +void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) +{ + char fullpath[512]; + snprintf(fullpath, sizeof(fullpath), "/tmp/data/bipbop-gen/%s", path); + printf("loading rialtotest %s\n", fullpath); + + FILE *f = fopen(fullpath, "rb"); + assert(f); + if (f) + { + fseek(f, 0, SEEK_END); + long len = ftell(f); + if (len > 0) + { + unsigned char *ptr = (unsigned char *)malloc(len); + assert(ptr); + if (ptr) + { + fseek(f, 0, SEEK_SET); + size_t n = fread(ptr, 1, len, f); + assert(n == len); + if (n == len) + { + mp4Demux.Parse(ptr, len); + } + free(ptr); + } + } + fclose(f); + } } -void ConfigureAudio( void ) +void ConfigureAudio() { - LoadAndDemuxSegment( trackAudio,"audio/init-stream0.m4s" ); - - bool hasDrm = false; - std::string mimeType; - StreamFormat streamFormat; - AudioConfig audioConfig; - audioConfig.numberOfChannels = trackAudio.audio.channel_count; - audioConfig.sampleRate = trackAudio.audio.samplerate; - - switch( trackAudio.codec_type ) - { - case MultiChar_Constant("esds"): - mimeType = "audio/mpeg"; - streamFormat = StreamFormat::RAW; - break; - case MultiChar_Constant("dec3"): - mimeType = "audio/x-eac3"; - streamFormat = StreamFormat::UNDEFINED; - break; - default: - assert(0); - break; - } - std::unique_ptr sourceAudio = std::make_unique( - mimeType, - hasDrm, - audioConfig, - SegmentAlignment::UNDEFINED, - streamFormat, - nullptr /* codecData*/ ); - // Attach; then read assigned id from source - bool okA = gstMediaPipeline->attachSource( sourceAudio ); - assert(okA); - sourceIdAudio = sourceAudio->getId(); + LoadAndDemuxSegment(trackAudio, "audio/init-stream0.m4s"); + + bool hasDrm = false; + std::string mimeType; + StreamFormat streamFormat; + AudioConfig audioConfig; + audioConfig.numberOfChannels = trackAudio.audio.channel_count; + audioConfig.sampleRate = trackAudio.audio.samplerate; + + switch (trackAudio.codec_type) + { + case MultiChar_Constant("esds"): + mimeType = "audio/mpeg"; + streamFormat = StreamFormat::RAW; + break; + case MultiChar_Constant("dec3"): + mimeType = "audio/x-eac3"; + streamFormat = StreamFormat::UNDEFINED; + break; + default: + assert(0); + } + + std::unique_ptr sourceAudio = + std::make_unique( + mimeType, hasDrm, audioConfig, SegmentAlignment::UNDEFINED, streamFormat, nullptr); + + bool okA = gstMediaPipeline->attachSource(sourceAudio); + // assert(okA); + + sourceIdAudio = sourceAudio->getId(); } -void ConfigureVideo( void ) +void ConfigureVideo() { - LoadAndDemuxSegment( trackVideo, "video/init-stream0.m4s" ); - - bool hasDrm = false; - std::string mimeType; - StreamFormat streamFormat; - int32_t width = trackVideo.video.width; - int32_t height = trackVideo.video.height; - SegmentAlignment alignment = SegmentAlignment::AU; - - switch( trackVideo.codec_type ) - { - case MultiChar_Constant("hvcC"): - mimeType = "video/x-h265"; - streamFormat = StreamFormat::HVC1; - break; - case MultiChar_Constant("avcC"): - mimeType = "video/x-h264"; - streamFormat = StreamFormat::AVC; - break; - default: - assert(0); - break; - } - CodecData codecData; - const char *codec_ptr = trackVideo.codec_data.c_str(); - codecData.data = std::vector( codec_ptr, &codec_ptr[trackVideo.codec_data.size()] ); - // Store derived video source in unique_ptr so it matches attachSource(const unique_ptr&) - std::unique_ptr sourceVideo = - std::make_unique( - mimeType, - hasDrm, - width, - height, - alignment, - streamFormat, - std::make_shared(codecData) ); - bool okV = gstMediaPipeline->attachSource( sourceVideo ); - assert(okV); - sourceIdVideo = sourceVideo->getId(); + LoadAndDemuxSegment(trackVideo, "video/init-stream0.m4s"); + + bool hasDrm = false; + std::string mimeType; + StreamFormat streamFormat; + int32_t width = trackVideo.video.width; + int32_t height = trackVideo.video.height; + SegmentAlignment alignment = SegmentAlignment::AU; + + switch (trackVideo.codec_type) + { + case MultiChar_Constant("hvcC"): + mimeType = "video/x-h265"; + streamFormat = StreamFormat::HVC1; + break; + case MultiChar_Constant("avcC"): + mimeType = "video/x-h264"; + streamFormat = StreamFormat::AVC; + break; + default: + assert(0); + } + + CodecData codecData; + const char *codec_ptr = trackVideo.codec_data.c_str(); + codecData.data = std::vector(codec_ptr, &codec_ptr[trackVideo.codec_data.size()]); + + std::unique_ptr sourceVideo = + std::make_unique( + mimeType, hasDrm, width, height, alignment, streamFormat, std::make_shared(codecData)); + + bool okV = gstMediaPipeline->attachSource(sourceVideo); + // assert(okV); + + sourceIdVideo = sourceVideo->getId(); } -void ConfigurenComplete() +void ConfigureComplete() { - gstMediaPipeline->allSourcesAttached(); + gstMediaPipeline->allSourcesAttached(); } -void InjectAudio( void ) +void InjectAudio() { - LoadAndDemuxSegment( trackAudio, "audio/chunk-stream0-00001.m4s"); - int count = trackAudio.count(); - printf( "adding %d audio frames\n", count ); - for( int i=0; i audioSegment = - std::make_unique( - sourceIdAudio, - (int64_t)(pts*NS_SECOND), // timestamp - (int64_t)(dur*NS_SECOND), - trackAudio.audio.samplerate, - trackAudio.audio.channel_count ); - size_t len = trackAudio.getLen(i); - uint8_t *data = new uint8_t[len]; - std::memcpy(data, trackAudio.getPtr(i),len); - audioSegment->setData( (uint32_t)len, data ); - std::unique_ptr segment = std::move(audioSegment); - AddSegmentStatus status = gstMediaPipeline->addSegment(0,segment); - assert( status == AddSegmentStatus::OK ); - } + LoadAndDemuxSegment(trackAudio, "audio/chunk-stream0-00001.m4s"); + int count = trackAudio.count(); + printf("adding %d audio frames\n", count); + + for (int i = 0; i < count; i++) + { + double pts = trackAudio.getPts(i); + double dur = trackAudio.getDuration(i); + + std::unique_ptr audioSegment = + std::make_unique( + sourceIdAudio, + (int64_t)(pts * NS_SECOND), + (int64_t)(dur * NS_SECOND), + trackAudio.audio.samplerate, + trackAudio.audio.channel_count); + + size_t len = trackAudio.getLen(i); + uint8_t *data = new uint8_t[len]; + std::memcpy(data, trackAudio.getPtr(i), len); + audioSegment->setData((uint32_t)len, data); + + AddSegmentStatus status = gstMediaPipeline->addSegment(0, audioSegment); + assert(status == AddSegmentStatus::OK); + } } -void InjectVideo( void ) +void InjectVideo() { - LoadAndDemuxSegment( trackVideo, "video/chunk-stream0-00001.m4s" ); - int count = trackVideo.count(); - printf( "adding %d video frames\n", count ); - for( int i=0; i videoSegment = - std::make_unique( - sourceIdVideo, - (int64_t)(pts*NS_SECOND), - (int64_t)(dur*NS_SECOND), - trackVideo.video.width, - trackVideo.video.height ); - size_t len = trackVideo.getLen(i); - uint8_t *data = new uint8_t[len]; - std::memcpy(data, trackVideo.getPtr(i),len); - videoSegment->setData( (uint32_t)len, data ); - std::unique_ptr segment = std::move(videoSegment); - AddSegmentStatus status = gstMediaPipeline->addSegment(0,segment); - assert( status == AddSegmentStatus::OK ); - } + LoadAndDemuxSegment(trackVideo, "video/chunk-stream0-00001.m4s"); + int count = trackVideo.count(); + printf("adding %d video frames\n", count); + + for (int i = 0; i < count; i++) + { + double pts = trackVideo.getPts(i); + double dur = trackVideo.getDuration(i); + + std::unique_ptr videoSegment = + std::make_unique( + sourceIdVideo, + (int64_t)(pts * NS_SECOND), + (int64_t)(dur * NS_SECOND), + trackVideo.video.width, + trackVideo.video.height); + + size_t len = trackVideo.getLen(i); + uint8_t *data = new uint8_t[len]; + std::memcpy(data, trackVideo.getPtr(i), len); + videoSegment->setData((uint32_t)len, data); + + AddSegmentStatus status = gstMediaPipeline->addSegment(0, videoSegment); + assert(status == AddSegmentStatus::OK); + } } int my_main(int argc, char **argv) { - const char *executablePath = argv[0]; - const char *prefix = "/Users/"; - size_t prefixLen = strlen(prefix); - gUserPathPtr = strstr(executablePath,prefix); - // assert( gUserPathPtr ); - const char *delim = strchr( &gUserPathPtr[prefixLen],'/' ); - // assert( delim ); - gUserPathLen = (int)(delim - gUserPathPtr); - - gstMediaPipeline = new GstMediaPipeline(); - gstMediaPipeline->play(); - ConfigureAudio(); - ConfigureVideo(); - ConfigurenComplete(); - InjectAudio(); - InjectVideo(); - - // Minimal sleep to allow any async Rialto operations; replace with real event loop if needed. - std::this_thread::sleep_for(std::chrono::seconds(2)); - return 0; + const char *executablePath = argv[0]; + const char *prefix = "/Users/"; + size_t prefixLen = strlen(prefix); + gUserPathPtr = strstr(executablePath, prefix); + const char *delim = strchr(&gUserPathPtr[prefixLen], '/'); + gUserPathLen = (int)(delim - gUserPathPtr); + + gstMediaPipeline = new GstMediaPipeline(); + gstMediaPipeline->play(); + + ConfigureAudio(); + ConfigureVideo(); + ConfigureComplete(); + + InjectAudio(); + InjectVideo(); + + std::this_thread::sleep_for(std::chrono::seconds(2)); + return 0; } int main(int argc, char **argv) { -#if defined(__APPLE__) && defined (__GST_MACOS_H__) - return gst_macos_main((GstMainFunc)my_main, argc, argv, nullptr); +#if defined(__APPLE__) && defined(__GST_MACOS_H__) + return gst_macos_main((GstMainFunc)my_main, argc, argv, nullptr); #else - return my_main(argc,argv); + return my_main(argc, argv); #endif } diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index 4250aa544..28fbccd04 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -1,13 +1,97 @@ #include "rialto-gst-pipeline.h" #include +#include + +class LocalGstPipeline : public firebolt::rialto::IMediaPipeline +{ +public: + LocalGstPipeline() : m_nextId(1) {} + ~LocalGstPipeline() override { stop(); } + + std::weak_ptr getClient() override + { + return std::weak_ptr(); + } + + bool play() override { return true; } + bool pause() override { return true; } + bool stop() override { return true; } + bool setPlaybackRate(double) override { return true; } + bool setPosition(int64_t) override { return true; } + bool getPosition(int64_t &position) override { position = 0; return true; } + bool getStats(int32_t, uint64_t &renderedFrames, uint64_t &droppedFrames) override { renderedFrames = droppedFrames = 0; return true; } + bool setImmediateOutput(int32_t, bool) override { return true; } + bool getImmediateOutput(int32_t, bool &) override { return true; } + bool setVideoWindow(uint32_t, uint32_t, uint32_t, uint32_t) override { return true; } + bool haveData(firebolt::rialto::MediaSourceStatus, uint32_t) override { return true; } + bool renderFrame() override { return true; } + bool setVolume(double, uint32_t, firebolt::rialto::EaseType) override { return true; } + bool getTextTrackIdentifier(std::string &) override { return true; } + bool setLowLatency(bool) override { return true; } + bool setSync(bool) override { return true; } + bool getSync(bool &) override { return true; } + bool setSyncOff(bool) override { return true; } + bool setStreamSyncMode(int32_t, int32_t) override { return true; } + bool getStreamSyncMode(int32_t &) override { return true; } + bool flush(int32_t, bool, bool &async) override { async = false; return true; } + bool setSourcePosition(int32_t, int64_t, bool, double, uint64_t) override { return true; } + bool setSubtitleOffset(int32_t, int64_t) override { return true; } + bool processAudioGap(int64_t, uint32_t, int64_t, bool) override { return true; } + bool setBufferingLimit(uint32_t) override { return true; } + bool getBufferingLimit(uint32_t &) override { return true; } + bool setUseBuffering(bool) override { return true; } + bool getUseBuffering(bool &) override { return true; } + bool switchSource(const std::unique_ptr &) override { return true; } + bool getVolume(double &) override { return true; } + bool setMute(int32_t, bool) override { return true; } + bool getMute(int32_t, bool &) override { return true; } + bool setTextTrackIdentifier(const std::string &) override { return true; } + + bool attachSource(const std::unique_ptr &source) override + { + if (!source) return false; + auto copy = source->copy(); + if (!copy) return false; + int32_t id = m_nextId++; + copy->setId(id); + const_cast(source.get())->setId(id); + m_sources.push_back(std::move(copy)); + return true; + } + + bool removeSource(int32_t id) override + { + for (auto it = m_sources.begin(); it != m_sources.end(); ++it) + { + if ((*it)->getId() == id) + { + m_sources.erase(it); + return true; + } + } + return false; + } + + bool allSourcesAttached() override { return true; } + + bool load(MediaType, const std::string &, const std::string &) override { return true; } + + AddSegmentStatus addSegment(uint32_t, const std::unique_ptr &mediaSegment) override + { + if (!mediaSegment) return AddSegmentStatus::ERROR; + return AddSegmentStatus::OK; + } + +private: + int32_t m_nextId; + std::vector> m_sources; +}; GstMediaPipeline::GstMediaPipeline() { std::cout << "Constructing GstMediaPipeline (Rialto-managed, public API)\n"; - - // In Option 2, the pipeline should be obtained via the public API. - // This is a placeholder. In real usage, obtain the pipeline from a factory or inject it. - m_pipeline = nullptr; + // Fallback to a local minimal pipeline if Rialto pipeline isn't injected + m_pipeline = std::make_shared(); } GstMediaPipeline::~GstMediaPipeline() diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h index a2b9ab4b2..24941edda 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.h +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -8,16 +8,18 @@ using namespace firebolt::rialto; class GstMediaPipeline : public IMediaPipeline { private: - std::shared_ptr m_pipeline; // Rialto-managed pipeline + std::shared_ptr m_pipeline; protected: std::weak_ptr client; - std::weak_ptr getClient() { return client; } public: GstMediaPipeline(); ~GstMediaPipeline(); + // REQUIRED override — must be public: + std::weak_ptr getClient() override { return client; } + // IMediaPipeline interface bool pause() override; bool stop() override; @@ -30,7 +32,7 @@ class GstMediaPipeline : public IMediaPipeline bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override; bool renderFrame() override; - bool setVolume(double targetVolume, uint32_t volumeDuration = 0, EaseType easeType = EaseType::EASE_LINEAR) override; + bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override; bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; bool setLowLatency(bool lowLatency) override; bool setSync(bool sync) override; @@ -39,7 +41,7 @@ class GstMediaPipeline : public IMediaPipeline bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; bool getStreamSyncMode(int32_t &streamSyncMode) override; bool flush(int32_t sourceId, bool resetTime, bool &async) override; - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime = false, double appliedRate = 1.0, uint64_t stopPosition = kUndefinedPosition) override; + bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, uint64_t stopPosition) override; bool setSubtitleOffset(int32_t sourceId, int64_t position) override; bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; bool setBufferingLimit(uint32_t limitBufferingMs) override; From 49874f52728f4574de6fe3af080e24a97c2ed8dd Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Thu, 27 Nov 2025 22:47:35 -0500 Subject: [PATCH 12/21] TEST - DO NOT MERGE Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 134 +++++------ test/gstTestHarness/rialto-gst-pipeline.cpp | 232 +++++++++----------- test/gstTestHarness/rialto-gst-pipeline.h | 102 +++++---- 3 files changed, 221 insertions(+), 247 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 64d2316a8..9e534a715 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -12,12 +12,14 @@ static const int64_t NS_SECOND = 1000000000LL; static Mp4Demux trackAudio; static Mp4Demux trackVideo; -static GstMediaPipeline *gstMediaPipeline; +static std::shared_ptr gstMediaPipeline; static int gUserPathLen; static const char *gUserPathPtr; static int32_t sourceIdAudio; static int32_t sourceIdVideo; +using namespace firebolt::rialto; + void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) { char fullpath[512]; @@ -41,7 +43,7 @@ void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) assert(n == len); if (n == len) { - mp4Demux.Parse(ptr, len); + mp4Demux.Parse(ptr, (uint32_t)len); } free(ptr); } @@ -53,75 +55,43 @@ void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) void ConfigureAudio() { LoadAndDemuxSegment(trackAudio, "audio/init-stream0.m4s"); + std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/init-stream0.m4s" << std::endl; - bool hasDrm = false; - std::string mimeType; - StreamFormat streamFormat; - AudioConfig audioConfig; - audioConfig.numberOfChannels = trackAudio.audio.channel_count; - audioConfig.sampleRate = trackAudio.audio.samplerate; - - switch (trackAudio.codec_type) - { - case MultiChar_Constant("esds"): - mimeType = "audio/mpeg"; - streamFormat = StreamFormat::RAW; - break; - case MultiChar_Constant("dec3"): - mimeType = "audio/x-eac3"; - streamFormat = StreamFormat::UNDEFINED; - break; - default: - assert(0); - } - - std::unique_ptr sourceAudio = - std::make_unique( - mimeType, hasDrm, audioConfig, SegmentAlignment::UNDEFINED, streamFormat, nullptr); + assert(trackAudio.tracks.size() == 1); + assert(trackAudio.tracks[0].type == MediaSourceType::Audio); - bool okA = gstMediaPipeline->attachSource(sourceAudio); - // assert(okA); + std::unique_ptr source = + std::make_unique( + trackAudio.tracks[0].type, + trackAudio.tracks[0].codec, + trackAudio.tracks[0].mimeType, + trackAudio.tracks[0].timeScale, + trackAudio.tracks[0].initializationData); - sourceIdAudio = sourceAudio->getId(); + assert(gstMediaPipeline->attachSource(source)); + sourceIdAudio = source->getId(); } void ConfigureVideo() { LoadAndDemuxSegment(trackVideo, "video/init-stream0.m4s"); - - bool hasDrm = false; - std::string mimeType; - StreamFormat streamFormat; - int32_t width = trackVideo.video.width; - int32_t height = trackVideo.video.height; - SegmentAlignment alignment = SegmentAlignment::AU; - - switch (trackVideo.codec_type) - { - case MultiChar_Constant("hvcC"): - mimeType = "video/x-h265"; - streamFormat = StreamFormat::HVC1; - break; - case MultiChar_Constant("avcC"): - mimeType = "video/x-h264"; - streamFormat = StreamFormat::AVC; - break; - default: - assert(0); - } - - CodecData codecData; - const char *codec_ptr = trackVideo.codec_data.c_str(); - codecData.data = std::vector(codec_ptr, &codec_ptr[trackVideo.codec_data.size()]); - - std::unique_ptr sourceVideo = - std::make_unique( - mimeType, hasDrm, width, height, alignment, streamFormat, std::make_shared(codecData)); - - bool okV = gstMediaPipeline->attachSource(sourceVideo); - // assert(okV); - - sourceIdVideo = sourceVideo->getId(); + std::cout << "loading rialtotest /tmp/data/bipbop-gen/video/init-stream0.m4s" << std::endl; + + assert(trackVideo.tracks.size() == 1); + assert(trackVideo.tracks[0].type == MediaSourceType::Video); + + std::unique_ptr source = + std::make_unique( + trackVideo.tracks[0].type, + trackVideo.tracks[0].codec, + trackVideo.tracks[0].mimeType, + trackVideo.tracks[0].timeScale, + trackVideo.tracks[0].initializationData, + trackVideo.tracks[0].video.width, + trackVideo.tracks[0].video.height); + + assert(gstMediaPipeline->attachSource(source)); + sourceIdVideo = source->getId(); } void ConfigureComplete() @@ -132,10 +102,10 @@ void ConfigureComplete() void InjectAudio() { LoadAndDemuxSegment(trackAudio, "audio/chunk-stream0-00001.m4s"); - int count = trackAudio.count(); - printf("adding %d audio frames\n", count); + std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/chunk-stream0-00001.m4s" << std::endl; + printf("adding %zu audio frames\n", trackAudio.getNbSegments()); - for (int i = 0; i < count; i++) + for (size_t i = 0; i < trackAudio.getNbSegments(); ++i) { double pts = trackAudio.getPts(i); double dur = trackAudio.getDuration(i); @@ -144,9 +114,7 @@ void InjectAudio() std::make_unique( sourceIdAudio, (int64_t)(pts * NS_SECOND), - (int64_t)(dur * NS_SECOND), - trackAudio.audio.samplerate, - trackAudio.audio.channel_count); + (int64_t)(dur * NS_SECOND)); size_t len = trackAudio.getLen(i); uint8_t *data = new uint8_t[len]; @@ -161,10 +129,10 @@ void InjectAudio() void InjectVideo() { LoadAndDemuxSegment(trackVideo, "video/chunk-stream0-00001.m4s"); - int count = trackVideo.count(); - printf("adding %d video frames\n", count); + std::cout << "loading rialtotest /tmp/data/bipbop-gen/video/chunk-stream0-00001.m4s" << std::endl; + printf("adding %zu video frames\n", trackVideo.getNbSegments()); - for (int i = 0; i < count; i++) + for (size_t i = 0; i < trackVideo.getNbSegments(); ++i) { double pts = trackVideo.getPts(i); double dur = trackVideo.getDuration(i); @@ -174,8 +142,8 @@ void InjectVideo() sourceIdVideo, (int64_t)(pts * NS_SECOND), (int64_t)(dur * NS_SECOND), - trackVideo.video.width, - trackVideo.video.height); + trackVideo.tracks[0].video.width, + trackVideo.tracks[0].video.height); size_t len = trackVideo.getLen(i); uint8_t *data = new uint8_t[len]; @@ -196,7 +164,18 @@ int my_main(int argc, char **argv) const char *delim = strchr(&gUserPathPtr[prefixLen], '/'); gUserPathLen = (int)(delim - gUserPathPtr); - gstMediaPipeline = new GstMediaPipeline(); + gstMediaPipeline = std::make_shared(); + if (!gstMediaPipeline->init()) + { + fprintf(stderr, "FATAL: Failed to initialize Rialto pipeline. Check logs/server status.\n"); + return -1; + } + + if (!gstMediaPipeline->setVideoWindow(0, 0, 1920, 1080)) + { + fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); + } + gstMediaPipeline->play(); ConfigureAudio(); @@ -206,7 +185,8 @@ int my_main(int argc, char **argv) InjectAudio(); InjectVideo(); - std::this_thread::sleep_for(std::chrono::seconds(2)); + gstMediaPipeline->stop(); + return 0; } @@ -217,4 +197,4 @@ int main(int argc, char **argv) #else return my_main(argc, argv); #endif -} +} \ No newline at end of file diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index 28fbccd04..ef7c5a019 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -1,169 +1,145 @@ #include "rialto-gst-pipeline.h" #include #include +#include +#include -class LocalGstPipeline : public firebolt::rialto::IMediaPipeline + +GstMediaPipeline::GstMediaPipeline() { -public: - LocalGstPipeline() : m_nextId(1) {} - ~LocalGstPipeline() override { stop(); } + std::cout << "Constructing GstMediaPipeline (Rialto-managed, public API)\n"; +} - std::weak_ptr getClient() override +GstMediaPipeline::~GstMediaPipeline() +{ + if (m_pipeline) { - return std::weak_ptr(); + m_pipeline->stop(); } +} - bool play() override { return true; } - bool pause() override { return true; } - bool stop() override { return true; } - bool setPlaybackRate(double) override { return true; } - bool setPosition(int64_t) override { return true; } - bool getPosition(int64_t &position) override { position = 0; return true; } - bool getStats(int32_t, uint64_t &renderedFrames, uint64_t &droppedFrames) override { renderedFrames = droppedFrames = 0; return true; } - bool setImmediateOutput(int32_t, bool) override { return true; } - bool getImmediateOutput(int32_t, bool &) override { return true; } - bool setVideoWindow(uint32_t, uint32_t, uint32_t, uint32_t) override { return true; } - bool haveData(firebolt::rialto::MediaSourceStatus, uint32_t) override { return true; } - bool renderFrame() override { return true; } - bool setVolume(double, uint32_t, firebolt::rialto::EaseType) override { return true; } - bool getTextTrackIdentifier(std::string &) override { return true; } - bool setLowLatency(bool) override { return true; } - bool setSync(bool) override { return true; } - bool getSync(bool &) override { return true; } - bool setSyncOff(bool) override { return true; } - bool setStreamSyncMode(int32_t, int32_t) override { return true; } - bool getStreamSyncMode(int32_t &) override { return true; } - bool flush(int32_t, bool, bool &async) override { async = false; return true; } - bool setSourcePosition(int32_t, int64_t, bool, double, uint64_t) override { return true; } - bool setSubtitleOffset(int32_t, int64_t) override { return true; } - bool processAudioGap(int64_t, uint32_t, int64_t, bool) override { return true; } - bool setBufferingLimit(uint32_t) override { return true; } - bool getBufferingLimit(uint32_t &) override { return true; } - bool setUseBuffering(bool) override { return true; } - bool getUseBuffering(bool &) override { return true; } - bool switchSource(const std::unique_ptr &) override { return true; } - bool getVolume(double &) override { return true; } - bool setMute(int32_t, bool) override { return true; } - bool getMute(int32_t, bool &) override { return true; } - bool setTextTrackIdentifier(const std::string &) override { return true; } - - bool attachSource(const std::unique_ptr &source) override - { - if (!source) return false; - auto copy = source->copy(); - if (!copy) return false; - int32_t id = m_nextId++; - copy->setId(id); - const_cast(source.get())->setId(id); - m_sources.push_back(std::move(copy)); - return true; - } - bool removeSource(int32_t id) override +bool GstMediaPipeline::init() +{ + + std::shared_ptr factory = IMediaPipelineFactory::createFactory(); + if (!factory) { - for (auto it = m_sources.begin(); it != m_sources.end(); ++it) - { - if ((*it)->getId() == id) - { - m_sources.erase(it); - return true; - } - } + std::cerr << "[GstMediaPipeline] ERROR: Failed to create IMediaPipelineFactory. Is libRialtoClient linked?\n"; return false; } - bool allSourcesAttached() override { return true; } + + VideoRequirements requirements = {1920, 1080}; - bool load(MediaType, const std::string &, const std::string &) override { return true; } + m_pipeline = factory->createMediaPipeline(weak_from_this(), requirements); - AddSegmentStatus addSegment(uint32_t, const std::unique_ptr &mediaSegment) override + if (!m_pipeline) { - if (!mediaSegment) return AddSegmentStatus::ERROR; - return AddSegmentStatus::OK; + std::cerr << "[GstMediaPipeline] ERROR: Failed to create Remote MediaPipeline. Is Rialto Server running?\n"; + return false; } -private: - int32_t m_nextId; - std::vector> m_sources; -}; + std::cout << "[GstMediaPipeline] SUCCESS: Rialto IPC Pipeline created.\n"; + return true; +} + -GstMediaPipeline::GstMediaPipeline() +bool GstMediaPipeline::play() { - std::cout << "Constructing GstMediaPipeline (Rialto-managed, public API)\n"; - // Fallback to a local minimal pipeline if Rialto pipeline isn't injected - m_pipeline = std::make_shared(); + return m_pipeline ? m_pipeline->play() : false; } -GstMediaPipeline::~GstMediaPipeline() +bool GstMediaPipeline::stop() { - std::cout << "Destructing GstMediaPipeline\n"; - if (m_pipeline) - { - m_pipeline->stop(); - } - m_pipeline.reset(); + return m_pipeline ? m_pipeline->stop() : false; +} + +bool GstMediaPipeline::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) +{ + std::cout << "[GstMediaPipeline] Forwarding setVideoWindow to Rialto Server: " << width << "x" << height << "\n"; + return m_pipeline ? m_pipeline->setVideoWindow(x, y, width, height) : false; +} + +bool GstMediaPipeline::attachSource(const std::unique_ptr &source) +{ + if (!m_pipeline || !source) return false; + + return m_pipeline->attachSource(source->copy()); +} + +bool GstMediaPipeline::removeSource(int32_t id) +{ + return m_pipeline ? m_pipeline->removeSource(id) : false; +} + +bool GstMediaPipeline::allSourcesAttached() +{ + return m_pipeline ? m_pipeline->allSourcesAttached() : false; } -// Rialto-managed methods delegate to IMediaPipeline if available -bool GstMediaPipeline::play() { return m_pipeline ? m_pipeline->play() : false; } -bool GstMediaPipeline::removeSource(int32_t id) { return m_pipeline ? m_pipeline->removeSource(id) : false; } -bool GstMediaPipeline::allSourcesAttached() { return m_pipeline ? m_pipeline->allSourcesAttached() : false; } bool GstMediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url) { return m_pipeline ? m_pipeline->load(type, mimeType, url) : false; } -AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, - const std::unique_ptr &mediaSegment) +AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) { return m_pipeline ? m_pipeline->addSegment(needDataRequestId, mediaSegment) : AddSegmentStatus::ERROR; } -bool GstMediaPipeline::attachSource(const std::unique_ptr &source) +// --- Callbacks from Rialto Server --- + +void GstMediaPipeline::notifyPlaybackState(PlaybackState state) { - if (!m_pipeline || !source) return false; + std::cout << "[Rialto Callback] PlaybackState: " << (int)state << "\n"; +} - std::unique_ptr temp = source->copy(); - if (!temp) return false; +void GstMediaPipeline::notifyPlaybackError(int32_t sourceId, PlaybackError error) +{ + std::cerr << "[Rialto Callback] ERROR on source " << sourceId << ": " << (int)error << "\n"; +} - bool ok = m_pipeline->attachSource(temp); - if (!ok) return false; +void GstMediaPipeline::notifyPosition(int64_t position) {} +void GstMediaPipeline::notifyNetworkState(NetworkState state) {} +void GstMediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo) {} +void GstMediaPipeline::notifyBufferUnderflow(int32_t sourceId) {} +void GstMediaPipeline::notifySourceFlushed(int32_t sourceId) {} - const int32_t assignedId = temp->getId(); - const_cast(source.get())->setId(assignedId); - return true; +void GstMediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, + uint32_t needDataRequestId, + const std::shared_ptr &mediaPlayerShmInfo) +{ + // std::cout << "[Rialto Callback] NeedData request: " << needDataRequestId << "\n"; } -// All other IMediaPipeline methods: return false or default values -bool GstMediaPipeline::pause() { return false; } -bool GstMediaPipeline::stop() { return false; } -bool GstMediaPipeline::setPlaybackRate(double) { return false; } -bool GstMediaPipeline::setPosition(int64_t) { return false; } -bool GstMediaPipeline::getPosition(int64_t &position) { position = 0; return false; } -bool GstMediaPipeline::getStats(int32_t, uint64_t &renderedFrames, uint64_t &droppedFrames) { renderedFrames = droppedFrames = 0; return false; } -bool GstMediaPipeline::setImmediateOutput(int32_t, bool) { return false; } -bool GstMediaPipeline::getImmediateOutput(int32_t, bool &) { return false; } -bool GstMediaPipeline::setVideoWindow(uint32_t, uint32_t, uint32_t, uint32_t) { return false; } -bool GstMediaPipeline::haveData(MediaSourceStatus, uint32_t) { return false; } -bool GstMediaPipeline::renderFrame() { return false; } -bool GstMediaPipeline::setVolume(double, uint32_t, EaseType) { return false; } -bool GstMediaPipeline::getTextTrackIdentifier(std::string &) { return false; } -bool GstMediaPipeline::setLowLatency(bool) { return false; } -bool GstMediaPipeline::setSync(bool) { return false; } -bool GstMediaPipeline::getSync(bool &) { return false; } -bool GstMediaPipeline::setSyncOff(bool) { return false; } -bool GstMediaPipeline::setStreamSyncMode(int32_t, int32_t) { return false; } -bool GstMediaPipeline::getStreamSyncMode(int32_t &) { return false; } -bool GstMediaPipeline::flush(int32_t, bool, bool &) { return false; } -bool GstMediaPipeline::setSourcePosition(int32_t, int64_t, bool, double, uint64_t) { return false; } -bool GstMediaPipeline::setSubtitleOffset(int32_t, int64_t) { return false; } -bool GstMediaPipeline::processAudioGap(int64_t, uint32_t, int64_t, bool) { return false; } -bool GstMediaPipeline::setBufferingLimit(uint32_t) { return false; } -bool GstMediaPipeline::getBufferingLimit(uint32_t &) { return false; } -bool GstMediaPipeline::setUseBuffering(bool) { return false; } -bool GstMediaPipeline::getUseBuffering(bool &) { return false; } -bool GstMediaPipeline::switchSource(const std::unique_ptr &) { return false; } -bool GstMediaPipeline::getVolume(double &) { return false; } -bool GstMediaPipeline::setMute(int32_t, bool) { return false; } -bool GstMediaPipeline::getMute(int32_t, bool &) { return false; } -bool GstMediaPipeline::setTextTrackIdentifier(const std::string &) { return false; } \ No newline at end of file +bool GstMediaPipeline::pause() { return m_pipeline ? m_pipeline->pause() : false; } +bool GstMediaPipeline::setPlaybackRate(double rate) { return m_pipeline ? m_pipeline->setPlaybackRate(rate) : false; } +bool GstMediaPipeline::setPosition(int64_t position) { return m_pipeline ? m_pipeline->setPosition(position) : false; } +bool GstMediaPipeline::getPosition(int64_t &position) { return m_pipeline ? m_pipeline->getPosition(position) : false; } +bool GstMediaPipeline::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) { return m_pipeline ? m_pipeline->getStats(sourceId, renderedFrames, droppedFrames) : false; } +bool GstMediaPipeline::setImmediateOutput(int32_t sourceId, bool immediateOutput) { return m_pipeline ? m_pipeline->setImmediateOutput(sourceId, immediateOutput) : false; } +bool GstMediaPipeline::getImmediateOutput(int32_t sourceId, bool &immediateOutput) { return m_pipeline ? m_pipeline->getImmediateOutput(sourceId, immediateOutput) : false; } +bool GstMediaPipeline::haveData(MediaSourceStatus status, uint32_t needDataRequestId) { return m_pipeline ? m_pipeline->haveData(status, needDataRequestId) : false; } +bool GstMediaPipeline::renderFrame() { return m_pipeline ? m_pipeline->renderFrame() : false; } +bool GstMediaPipeline::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) { return m_pipeline ? m_pipeline->setVolume(targetVolume, volumeDuration, easeType) : false; } +bool GstMediaPipeline::getTextTrackIdentifier(std::string &textTrackIdentifier) { return m_pipeline ? m_pipeline->getTextTrackIdentifier(textTrackIdentifier) : false; } +bool GstMediaPipeline::setLowLatency(bool lowLatency) { return m_pipeline ? m_pipeline->setLowLatency(lowLatency) : false; } +bool GstMediaPipeline::setSync(bool sync) { return m_pipeline ? m_pipeline->setSync(sync) : false; } +bool GstMediaPipeline::getSync(bool &sync) { return m_pipeline ? m_pipeline->getSync(sync) : false; } +bool GstMediaPipeline::setSyncOff(bool syncOff) { return m_pipeline ? m_pipeline->setSyncOff(syncOff) : false; } +bool GstMediaPipeline::setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) { return m_pipeline ? m_pipeline->setStreamSyncMode(sourceId, streamSyncMode) : false; } +bool GstMediaPipeline::getStreamSyncMode(int32_t &streamSyncMode) { return m_pipeline ? m_pipeline->getStreamSyncMode(streamSyncMode) : false; } +bool GstMediaPipeline::flush(int32_t sourceId, bool resetTime, bool &async) { return m_pipeline ? m_pipeline->flush(sourceId, resetTime, async) : false; } +bool GstMediaPipeline::setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, uint64_t stopPosition) { return m_pipeline ? m_pipeline->setSourcePosition(sourceId, position, resetTime, appliedRate, stopPosition) : false; } +bool GstMediaPipeline::setSubtitleOffset(int32_t sourceId, int64_t position) { return m_pipeline ? m_pipeline->setSubtitleOffset(sourceId, position) : false; } +bool GstMediaPipeline::processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) { return m_pipeline ? m_pipeline->processAudioGap(position, duration, discontinuityGap, audioAac) : false; } +bool GstMediaPipeline::setBufferingLimit(uint32_t limitBufferingMs) { return m_pipeline ? m_pipeline->setBufferingLimit(limitBufferingMs) : false; } +bool GstMediaPipeline::getBufferingLimit(uint32_t &limitBufferingMs) { return m_pipeline ? m_pipeline->getBufferingLimit(limitBufferingMs) : false; } +bool GstMediaPipeline::setUseBuffering(bool useBuffering) { return m_pipeline ? m_pipeline->setUseBuffering(useBuffering) : false; } +bool GstMediaPipeline::getUseBuffering(bool &useBuffering) { return m_pipeline ? m_pipeline->getUseBuffering(useBuffering) : false; } +bool GstMediaPipeline::switchSource(const std::unique_ptr &source) { return m_pipeline ? m_pipeline->switchSource(source->copy()) : false; } +bool GstMediaPipeline::getVolume(double ¤tVolume) { return m_pipeline ? m_pipeline->getVolume(currentVolume) : false; } +bool GstMediaPipeline::setMute(int32_t sourceId, bool mute) { return m_pipeline ? m_pipeline->setMute(sourceId, mute) : false; } +bool GstMediaPipeline::getMute(int32_t sourceId, bool &mute) { return m_pipeline ? m_pipeline->getMute(sourceId, mute) : false; } +bool GstMediaPipeline::setTextTrackIdentifier(const std::string &textTrackIdentifier) { return m_pipeline ? m_pipeline->setTextTrackIdentifier(textTrackIdentifier) : false; } \ No newline at end of file diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h index 24941edda..40249afac 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.h +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -1,64 +1,82 @@ #ifndef GST_MEDIA_PIPELINE_H #define GST_MEDIA_PIPELINE_H -#include "IMediaPipeline.h" +#include "IMediaPipeline.h" // Includes IMediaPipelineFactory +#include +#include +#include using namespace firebolt::rialto; -class GstMediaPipeline : public IMediaPipeline +class GstMediaPipeline : public IMediaPipeline, + public IMediaPipelineClient, + public std::enable_shared_from_this { private: - std::shared_ptr m_pipeline; - -protected: - std::weak_ptr client; + std::shared_ptr m_pipeline; public: GstMediaPipeline(); - ~GstMediaPipeline(); + ~GstMediaPipeline() override; - // REQUIRED override — must be public: - std::weak_ptr getClient() override { return client; } + + bool init(); - // IMediaPipeline interface - bool pause() override; + + std::weak_ptr getClient() override { return weak_from_this(); } + + void notifyNetworkState(NetworkState state) override; + void notifyPlaybackState(PlaybackState state) override; + void notifyPosition(int64_t position) override; + void notifyNeedMediaData(int32_t sourceId, size_t frameCount, + uint32_t needDataRequestId, + const std::shared_ptr &mediaPlayerShmInfo) override; + void notifyQos(int32_t sourceId, const QosInfo &qosInfo) override; + void notifyBufferUnderflow(int32_t sourceId) override; + void notifyPlaybackError(int32_t sourceId, PlaybackError error) override; + void notifySourceFlushed(int32_t sourceId) override; + + + bool play() override; bool stop() override; - bool setPlaybackRate(double rate) override; - bool setPosition(int64_t position) override; - bool getPosition(int64_t &position) override; - bool getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) override; - bool setImmediateOutput(int32_t sourceId, bool immediateOutput) override; - bool getImmediateOutput(int32_t sourceId, bool &immediateOutput) override; bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; - bool haveData(MediaSourceStatus status, uint32_t needDataRequestId) override; - bool renderFrame() override; - bool setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) override; - bool getTextTrackIdentifier(std::string &textTrackIdentifier) override; - bool setLowLatency(bool lowLatency) override; - bool setSync(bool sync) override; - bool getSync(bool &sync) override; - bool setSyncOff(bool syncOff) override; - bool setStreamSyncMode(int32_t sourceId, int32_t streamSyncMode) override; - bool getStreamSyncMode(int32_t &streamSyncMode) override; - bool flush(int32_t sourceId, bool resetTime, bool &async) override; - bool setSourcePosition(int32_t sourceId, int64_t position, bool resetTime, double appliedRate, uint64_t stopPosition) override; - bool setSubtitleOffset(int32_t sourceId, int64_t position) override; - bool processAudioGap(int64_t position, uint32_t duration, int64_t discontinuityGap, bool audioAac) override; - bool setBufferingLimit(uint32_t limitBufferingMs) override; - bool getBufferingLimit(uint32_t &limitBufferingMs) override; - bool setUseBuffering(bool useBuffering) override; - bool getUseBuffering(bool &useBuffering) override; - bool switchSource(const std::unique_ptr &source) override; - bool getVolume(double ¤tVolume) override; - bool setMute(int32_t sourceId, bool mute) override; - bool getMute(int32_t sourceId, bool &mute) override; - bool setTextTrackIdentifier(const std::string &textTrackIdentifier) override; bool attachSource(const std::unique_ptr &source) override; bool removeSource(int32_t id) override; bool allSourcesAttached() override; bool load(MediaType type, const std::string &mimeType, const std::string &url) override; - bool play() override; AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; + + + bool pause() override; + bool setPlaybackRate(double) override; + bool setPosition(int64_t) override; + bool getPosition(int64_t &p) override; + bool getStats(int32_t, uint64_t &r, uint64_t &d) override; + bool setImmediateOutput(int32_t, bool) override; + bool getImmediateOutput(int32_t, bool &) override; + bool haveData(MediaSourceStatus, uint32_t) override; + bool renderFrame() override; + bool setVolume(double, uint32_t, EaseType) override; + bool getTextTrackIdentifier(std::string &) override; + bool setLowLatency(bool) override; + bool setSync(bool) override; + bool getSync(bool &) override; + bool setSyncOff(bool) override; + bool setStreamSyncMode(int32_t, int32_t) override; + bool getStreamSyncMode(int32_t &) override; + bool flush(int32_t, bool, bool &) override; + bool setSourcePosition(int32_t, int64_t, bool, double, uint64_t) override; + bool setSubtitleOffset(int32_t, int64_t) override; + bool processAudioGap(int64_t, uint32_t, int64_t, bool) override; + bool setBufferingLimit(uint32_t) override; + bool getBufferingLimit(uint32_t &) override; + bool setUseBuffering(bool) override; + bool getUseBuffering(bool &) override; + bool switchSource(const std::unique_ptr &) override; + bool getVolume(double &) override; + bool setMute(int32_t, bool) override; + bool getMute(int32_t, bool &) override; + bool setTextTrackIdentifier(const std::string &) override; }; -#endif // GST_MEDIA_PIPELINE_H +#endif // GST_MEDIA_PIPELINE_H \ No newline at end of file From a27c350852c90719f564f84253d134033f4bc8f9 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Thu, 27 Nov 2025 23:43:39 -0500 Subject: [PATCH 13/21] TEST - DO NOT MERGE Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 59 ++++++++++++++----------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 9e534a715..2054b1ed9 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -7,11 +7,11 @@ #include "mp4demux.hpp" #include "rialto-gst-pipeline.h" -// Nanosecond conversion for timestamps static const int64_t NS_SECOND = 1000000000LL; static Mp4Demux trackAudio; static Mp4Demux trackVideo; + static std::shared_ptr gstMediaPipeline; static int gUserPathLen; static const char *gUserPathPtr; @@ -43,6 +43,7 @@ void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) assert(n == len); if (n == len) { + mp4Demux.Parse(ptr, (uint32_t)len); } free(ptr); @@ -57,19 +58,19 @@ void ConfigureAudio() LoadAndDemuxSegment(trackAudio, "audio/init-stream0.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/init-stream0.m4s" << std::endl; - assert(trackAudio.tracks.size() == 1); - assert(trackAudio.tracks[0].type == MediaSourceType::Audio); - + // The 'tracks' array is likely missing. Assuming direct member access: std::unique_ptr source = std::make_unique( - trackAudio.tracks[0].type, - trackAudio.tracks[0].codec, - trackAudio.tracks[0].mimeType, - trackAudio.tracks[0].timeScale, - trackAudio.tracks[0].initializationData); + MediaSourceType::Audio, + trackAudio.codec, + trackAudio.mimeType, + trackAudio.timeScale, + trackAudio.initializationData); + assert(gstMediaPipeline->attachSource(source)); - sourceIdAudio = source->getId(); + + sourceIdAudio = source->getId(); } void ConfigureVideo() @@ -77,20 +78,20 @@ void ConfigureVideo() LoadAndDemuxSegment(trackVideo, "video/init-stream0.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/video/init-stream0.m4s" << std::endl; - assert(trackVideo.tracks.size() == 1); - assert(trackVideo.tracks[0].type == MediaSourceType::Video); std::unique_ptr source = std::make_unique( - trackVideo.tracks[0].type, - trackVideo.tracks[0].codec, - trackVideo.tracks[0].mimeType, - trackVideo.tracks[0].timeScale, - trackVideo.tracks[0].initializationData, - trackVideo.tracks[0].video.width, - trackVideo.tracks[0].video.height); - + MediaSourceType::Video, + trackVideo.codec, + trackVideo.mimeType, + trackVideo.timeScale, + trackVideo.initializationData, + trackVideo.width, + trackVideo.height); + + // Using assert to attachSource returns a bool assert(gstMediaPipeline->attachSource(source)); + // Must move the unique_ptr out to get the ID, then detach it from 'source' sourceIdVideo = source->getId(); } @@ -103,9 +104,12 @@ void InjectAudio() { LoadAndDemuxSegment(trackAudio, "audio/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/chunk-stream0-00001.m4s" << std::endl; - printf("adding %zu audio frames\n", trackAudio.getNbSegments()); + + // Using getSegmentCount() instead of getNbSegments() or similar + size_t segmentCount = trackAudio.getSegmentCount(); + printf("adding %zu audio frames\n", segmentCount); - for (size_t i = 0; i < trackAudio.getNbSegments(); ++i) + for (size_t i = 0; i < segmentCount; ++i) { double pts = trackAudio.getPts(i); double dur = trackAudio.getDuration(i); @@ -130,9 +134,12 @@ void InjectVideo() { LoadAndDemuxSegment(trackVideo, "video/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/video/chunk-stream0-00001.m4s" << std::endl; - printf("adding %zu video frames\n", trackVideo.getNbSegments()); + + // Using getSegmentCount() instead of getNbSegments() or similar + size_t segmentCount = trackVideo.getSegmentCount(); + printf("adding %zu video frames\n", segmentCount); - for (size_t i = 0; i < trackVideo.getNbSegments(); ++i) + for (size_t i = 0; i < segmentCount; ++i) { double pts = trackVideo.getPts(i); double dur = trackVideo.getDuration(i); @@ -142,8 +149,8 @@ void InjectVideo() sourceIdVideo, (int64_t)(pts * NS_SECOND), (int64_t)(dur * NS_SECOND), - trackVideo.tracks[0].video.width, - trackVideo.tracks[0].video.height); + trackVideo.width, + trackVideo.height); size_t len = trackVideo.getLen(i); uint8_t *data = new uint8_t[len]; From fd103607b7408685ae09bfcd991c04a73460a789 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Thu, 27 Nov 2025 23:53:52 -0500 Subject: [PATCH 14/21] TEST - DO NOT MERGE Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 107 +++++++++++++------- test/gstTestHarness/rialto-gst-pipeline.cpp | 21 +--- test/gstTestHarness/rialto-gst-pipeline.h | 19 ++-- 3 files changed, 85 insertions(+), 62 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 2054b1ed9..43346f3b7 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "mp4demux.hpp" #include "rialto-gst-pipeline.h" @@ -11,7 +12,6 @@ static const int64_t NS_SECOND = 1000000000LL; static Mp4Demux trackAudio; static Mp4Demux trackVideo; - static std::shared_ptr gstMediaPipeline; static int gUserPathLen; static const char *gUserPathPtr; @@ -43,7 +43,6 @@ void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) assert(n == len); if (n == len) { - mp4Demux.Parse(ptr, (uint32_t)len); } free(ptr); @@ -58,41 +57,79 @@ void ConfigureAudio() LoadAndDemuxSegment(trackAudio, "audio/init-stream0.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/init-stream0.m4s" << std::endl; - // The 'tracks' array is likely missing. Assuming direct member access: - std::unique_ptr source = - std::make_unique( - MediaSourceType::Audio, - trackAudio.codec, - trackAudio.mimeType, - trackAudio.timeScale, - trackAudio.initializationData); + bool hasDrm = false; + std::string mimeType; + StreamFormat streamFormat = StreamFormat::AAC; + SegmentAlignment alignment = SegmentAlignment::AU; + switch( trackAudio.codec_type ) + { + case MultiChar_Constant("mp4a"): + mimeType = "audio/mp4"; + streamFormat = StreamFormat::AAC; + break; + default: + assert(0); + break; + } - assert(gstMediaPipeline->attachSource(source)); - - sourceIdAudio = source->getId(); + CodecData codecData; + const char *codec_ptr = trackAudio.codec_data.c_str(); + codecData.data = std::vector( codec_ptr, &codec_ptr[trackAudio.codec_data.size()] ); + + std::unique_ptr sourceAudio = + std::make_unique( + mimeType, + hasDrm, + alignment, + streamFormat, + trackAudio.audio.rate, + trackAudio.audio.channels, + std::make_shared(codecData) ); + + gstMediaPipeline->attachSource( std::move(sourceAudio), sourceIdAudio ); } void ConfigureVideo() { - LoadAndDemuxSegment(trackVideo, "video/init-stream0.m4s"); - std::cout << "loading rialtotest /tmp/data/bipbop-gen/video/init-stream0.m4s" << std::endl; - - - std::unique_ptr source = - std::make_unique( - MediaSourceType::Video, - trackVideo.codec, - trackVideo.mimeType, - trackVideo.timeScale, - trackVideo.initializationData, - trackVideo.width, - trackVideo.height); - - // Using assert to attachSource returns a bool - assert(gstMediaPipeline->attachSource(source)); - // Must move the unique_ptr out to get the ID, then detach it from 'source' - sourceIdVideo = source->getId(); + LoadAndDemuxSegment( trackVideo, "video/init-stream0.m4s" ); + + bool hasDrm = false; + std::string mimeType; + StreamFormat streamFormat; + int32_t width = trackVideo.video.width; + int32_t height = trackVideo.video.height; + SegmentAlignment alignment = SegmentAlignment::AU; + + switch( trackVideo.codec_type ) + { + case MultiChar_Constant("hvcC"): + mimeType = "video/x-h265"; + streamFormat = StreamFormat::HVC1; + break; + case MultiChar_Constant("avcC"): + mimeType = "video/x-h264"; + streamFormat = StreamFormat::AVC; + break; + default: + assert(0); + break; + } + CodecData codecData; + const char *codec_ptr = trackVideo.codec_data.c_str(); + codecData.data = std::vector( codec_ptr, &codec_ptr[trackVideo.codec_data.size()] ); + + std::unique_ptr sourceVideo = + std::make_unique( + mimeType, + hasDrm, + width, + height, + alignment, + streamFormat, + std::make_shared(codecData) ); + + gstMediaPipeline->attachSource( std::move(sourceVideo), sourceIdVideo ); } void ConfigureComplete() @@ -105,7 +142,6 @@ void InjectAudio() LoadAndDemuxSegment(trackAudio, "audio/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/chunk-stream0-00001.m4s" << std::endl; - // Using getSegmentCount() instead of getNbSegments() or similar size_t segmentCount = trackAudio.getSegmentCount(); printf("adding %zu audio frames\n", segmentCount); @@ -135,7 +171,6 @@ void InjectVideo() LoadAndDemuxSegment(trackVideo, "video/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/video/chunk-stream0-00001.m4s" << std::endl; - // Using getSegmentCount() instead of getNbSegments() or similar size_t segmentCount = trackVideo.getSegmentCount(); printf("adding %zu video frames\n", segmentCount); @@ -149,8 +184,8 @@ void InjectVideo() sourceIdVideo, (int64_t)(pts * NS_SECOND), (int64_t)(dur * NS_SECOND), - trackVideo.width, - trackVideo.height); + trackVideo.video.width, + trackVideo.video.height); size_t len = trackVideo.getLen(i); uint8_t *data = new uint8_t[len]; @@ -192,6 +227,8 @@ int my_main(int argc, char **argv) InjectAudio(); InjectVideo(); + std::this_thread::sleep_for(std::chrono::seconds(5)); + gstMediaPipeline->stop(); return 0; diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index ef7c5a019..b6dd2a234 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -4,7 +4,6 @@ #include #include - GstMediaPipeline::GstMediaPipeline() { std::cout << "Constructing GstMediaPipeline (Rialto-managed, public API)\n"; @@ -18,18 +17,14 @@ GstMediaPipeline::~GstMediaPipeline() } } - bool GstMediaPipeline::init() { - std::shared_ptr factory = IMediaPipelineFactory::createFactory(); if (!factory) { - std::cerr << "[GstMediaPipeline] ERROR: Failed to create IMediaPipelineFactory. Is libRialtoClient linked?\n"; + std::cerr << "[GstMediaPipeline] ERROR: Failed to create IMediaPipelineFactory.\n"; return false; } - - VideoRequirements requirements = {1920, 1080}; m_pipeline = factory->createMediaPipeline(weak_from_this(), requirements); @@ -44,6 +39,10 @@ bool GstMediaPipeline::init() return true; } +bool GstMediaPipeline::attachSource(std::unique_ptr &&source, int32_t &sourceId) +{ + return m_pipeline ? m_pipeline->attachSource(std::move(source), sourceId) : false; +} bool GstMediaPipeline::play() { @@ -61,13 +60,6 @@ bool GstMediaPipeline::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, ui return m_pipeline ? m_pipeline->setVideoWindow(x, y, width, height) : false; } -bool GstMediaPipeline::attachSource(const std::unique_ptr &source) -{ - if (!m_pipeline || !source) return false; - - return m_pipeline->attachSource(source->copy()); -} - bool GstMediaPipeline::removeSource(int32_t id) { return m_pipeline ? m_pipeline->removeSource(id) : false; @@ -88,8 +80,6 @@ AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const return m_pipeline ? m_pipeline->addSegment(needDataRequestId, mediaSegment) : AddSegmentStatus::ERROR; } -// --- Callbacks from Rialto Server --- - void GstMediaPipeline::notifyPlaybackState(PlaybackState state) { std::cout << "[Rialto Callback] PlaybackState: " << (int)state << "\n"; @@ -110,7 +100,6 @@ void GstMediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, uint32_t needDataRequestId, const std::shared_ptr &mediaPlayerShmInfo) { - // std::cout << "[Rialto Callback] NeedData request: " << needDataRequestId << "\n"; } bool GstMediaPipeline::pause() { return m_pipeline ? m_pipeline->pause() : false; } diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h index 40249afac..5918d9332 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.h +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -1,7 +1,7 @@ #ifndef GST_MEDIA_PIPELINE_H #define GST_MEDIA_PIPELINE_H -#include "IMediaPipeline.h" // Includes IMediaPipelineFactory +#include "IMediaPipeline.h" #include #include #include @@ -13,16 +13,14 @@ class GstMediaPipeline : public IMediaPipeline, public std::enable_shared_from_this { private: - std::shared_ptr m_pipeline; + std::shared_ptr m_pipeline; public: GstMediaPipeline(); ~GstMediaPipeline() override; - bool init(); - std::weak_ptr getClient() override { return weak_from_this(); } void notifyNetworkState(NetworkState state) override; @@ -36,17 +34,16 @@ class GstMediaPipeline : public IMediaPipeline, void notifyPlaybackError(int32_t sourceId, PlaybackError error) override; void notifySourceFlushed(int32_t sourceId) override; - - bool play() override; - bool stop() override; - bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; - bool attachSource(const std::unique_ptr &source) override; + bool attachSource(std::unique_ptr &&source, int32_t &sourceId) override; + bool attachSource(const std::unique_ptr &source) override { return false; } bool removeSource(int32_t id) override; bool allSourcesAttached() override; bool load(MediaType type, const std::string &mimeType, const std::string &url) override; AddSegmentStatus addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) override; - + bool play() override; + bool stop() override; + bool setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; bool pause() override; bool setPlaybackRate(double) override; bool setPosition(int64_t) override; @@ -79,4 +76,4 @@ class GstMediaPipeline : public IMediaPipeline, bool setTextTrackIdentifier(const std::string &) override; }; -#endif // GST_MEDIA_PIPELINE_H \ No newline at end of file +#endif \ No newline at end of file From 39afc4657d325c41c919a11d013b9fc982f5acc0 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Fri, 28 Nov 2025 00:01:45 -0500 Subject: [PATCH 15/21] TEST - DO NOT MERGE Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 41 ++++--- test/gstTestHarness/rialto-gst-pipeline.cpp | 128 +++++++++----------- test/gstTestHarness/rialto-gst-pipeline.h | 14 ++- 3 files changed, 92 insertions(+), 91 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 43346f3b7..53bf29c59 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -59,23 +59,32 @@ void ConfigureAudio() bool hasDrm = false; std::string mimeType; - StreamFormat streamFormat = StreamFormat::AAC; - SegmentAlignment alignment = SegmentAlignment::AU; + StreamFormat streamFormat; + AudioConfig audioConfig; + audioConfig.numberOfChannels = trackAudio.audio.channel_count; + audioConfig.sampleRate = trackAudio.audio.samplerate; + + // StreamFormat streamFormat = StreamFormat::AAC; + // SegmentAlignment alignment = SegmentAlignment::AU; switch( trackAudio.codec_type ) - { - case MultiChar_Constant("mp4a"): - mimeType = "audio/mp4"; - streamFormat = StreamFormat::AAC; - break; - default: - assert(0); - break; - } + { + case MultiChar_Constant("esds"): + mimeType = "audio/mpeg"; + streamFormat = StreamFormat::RAW; + break; + case MultiChar_Constant("dec3"): + mimeType = "audio/x-eac3"; + streamFormat = StreamFormat::UNDEFINED; + break; + default: + assert(0); + break; + } - CodecData codecData; - const char *codec_ptr = trackAudio.codec_data.c_str(); - codecData.data = std::vector( codec_ptr, &codec_ptr[trackAudio.codec_data.size()] ); + // CodecData codecData; + // const char *codec_ptr = trackAudio.codec_data.c_str(); + // codecData.data = std::vector( codec_ptr, &codec_ptr[trackAudio.codec_data.size()] ); std::unique_ptr sourceAudio = std::make_unique( @@ -142,7 +151,7 @@ void InjectAudio() LoadAndDemuxSegment(trackAudio, "audio/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/chunk-stream0-00001.m4s" << std::endl; - size_t segmentCount = trackAudio.getSegmentCount(); + size_t segmentCount = trackAudio.getNbSegments(); // Corrected function name printf("adding %zu audio frames\n", segmentCount); for (size_t i = 0; i < segmentCount; ++i) @@ -171,7 +180,7 @@ void InjectVideo() LoadAndDemuxSegment(trackVideo, "video/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/video/chunk-stream0-00001.m4s" << std::endl; - size_t segmentCount = trackVideo.getSegmentCount(); + size_t segmentCount = trackVideo.getNbSegments(); // Corrected function name printf("adding %zu video frames\n", segmentCount); for (size_t i = 0; i < segmentCount; ++i) diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index b6dd2a234..0a5d228b1 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -4,6 +4,8 @@ #include #include +using namespace firebolt::rialto; + GstMediaPipeline::GstMediaPipeline() { std::cout << "Constructing GstMediaPipeline (Rialto-managed, public API)\n"; @@ -19,89 +21,50 @@ GstMediaPipeline::~GstMediaPipeline() bool GstMediaPipeline::init() { - std::shared_ptr factory = IMediaPipelineFactory::createFactory(); - if (!factory) - { - std::cerr << "[GstMediaPipeline] ERROR: Failed to create IMediaPipelineFactory.\n"; - return false; - } - VideoRequirements requirements = {1920, 1080}; + // FIX: Calling createFactory() on IMediaPipelineFactory class, as it's not a member of IMediaPipeline. + std::shared_ptr factory = IMediaPipelineFactory::createFactory(); + if (!factory) return false; + VideoRequirements requirements = {}; + m_pipeline = factory->createMediaPipeline(weak_from_this(), requirements); - - if (!m_pipeline) - { - std::cerr << "[GstMediaPipeline] ERROR: Failed to create Remote MediaPipeline. Is Rialto Server running?\n"; - return false; - } - - std::cout << "[GstMediaPipeline] SUCCESS: Rialto IPC Pipeline created.\n"; - return true; -} - -bool GstMediaPipeline::attachSource(std::unique_ptr &&source, int32_t &sourceId) -{ - return m_pipeline ? m_pipeline->attachSource(std::move(source), sourceId) : false; -} - -bool GstMediaPipeline::play() -{ - return m_pipeline ? m_pipeline->play() : false; -} - -bool GstMediaPipeline::stop() -{ - return m_pipeline ? m_pipeline->stop() : false; -} - -bool GstMediaPipeline::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) -{ - std::cout << "[GstMediaPipeline] Forwarding setVideoWindow to Rialto Server: " << width << "x" << height << "\n"; - return m_pipeline ? m_pipeline->setVideoWindow(x, y, width, height) : false; -} - -bool GstMediaPipeline::removeSource(int32_t id) -{ - return m_pipeline ? m_pipeline->removeSource(id) : false; -} - -bool GstMediaPipeline::allSourcesAttached() -{ - return m_pipeline ? m_pipeline->allSourcesAttached() : false; -} - -bool GstMediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url) -{ - return m_pipeline ? m_pipeline->load(type, mimeType, url) : false; + + return m_pipeline != nullptr; } -AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) +bool GstMediaPipeline::attachSource(const std::unique_ptr &source) { - return m_pipeline ? m_pipeline->addSegment(needDataRequestId, mediaSegment) : AddSegmentStatus::ERROR; + return m_pipeline ? m_pipeline->attachSource(source) : false; } -void GstMediaPipeline::notifyPlaybackState(PlaybackState state) -{ - std::cout << "[Rialto Callback] PlaybackState: " << (int)state << "\n"; -} - -void GstMediaPipeline::notifyPlaybackError(int32_t sourceId, PlaybackError error) +bool GstMediaPipeline::attachSource(std::unique_ptr &&source, int32_t &sourceId) { - std::cerr << "[Rialto Callback] ERROR on source " << sourceId << ": " << (int)error << "\n"; -} - -void GstMediaPipeline::notifyPosition(int64_t position) {} -void GstMediaPipeline::notifyNetworkState(NetworkState state) {} -void GstMediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo) {} -void GstMediaPipeline::notifyBufferUnderflow(int32_t sourceId) {} -void GstMediaPipeline::notifySourceFlushed(int32_t sourceId) {} + if (!source) + { + sourceId = 0; + return false; + } + + bool ok = attachSource(source); -void GstMediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, - uint32_t needDataRequestId, - const std::shared_ptr &mediaPlayerShmInfo) -{ + if (ok) + { + sourceId = source->getId(); + } + else + { + sourceId = 0; + } + + return ok; } +bool GstMediaPipeline::play() { return m_pipeline ? m_pipeline->play() : false; } +bool GstMediaPipeline::stop() { return m_pipeline ? m_pipeline->stop() : false; } +bool GstMediaPipeline::removeSource(int32_t id) { return m_pipeline ? m_pipeline->removeSource(id) : false; } +bool GstMediaPipeline::allSourcesAttached() { return m_pipeline ? m_pipeline->allSourcesAttached() : false; } +bool GstMediaPipeline::load(MediaType type, const std::string &mimeType, const std::string &url) { return m_pipeline ? m_pipeline->load(type, mimeType, url) : false; } +AddSegmentStatus GstMediaPipeline::addSegment(uint32_t needDataRequestId, const std::unique_ptr &mediaSegment) { return m_pipeline ? m_pipeline->addSegment(needDataRequestId, mediaSegment) : AddSegmentStatus::ERROR; } bool GstMediaPipeline::pause() { return m_pipeline ? m_pipeline->pause() : false; } bool GstMediaPipeline::setPlaybackRate(double rate) { return m_pipeline ? m_pipeline->setPlaybackRate(rate) : false; } bool GstMediaPipeline::setPosition(int64_t position) { return m_pipeline ? m_pipeline->setPosition(position) : false; } @@ -109,6 +72,7 @@ bool GstMediaPipeline::getPosition(int64_t &position) { return m_pipeline ? m_pi bool GstMediaPipeline::getStats(int32_t sourceId, uint64_t &renderedFrames, uint64_t &droppedFrames) { return m_pipeline ? m_pipeline->getStats(sourceId, renderedFrames, droppedFrames) : false; } bool GstMediaPipeline::setImmediateOutput(int32_t sourceId, bool immediateOutput) { return m_pipeline ? m_pipeline->setImmediateOutput(sourceId, immediateOutput) : false; } bool GstMediaPipeline::getImmediateOutput(int32_t sourceId, bool &immediateOutput) { return m_pipeline ? m_pipeline->getImmediateOutput(sourceId, immediateOutput) : false; } +bool GstMediaPipeline::setVideoWindow(uint32_t x, uint32_t y, uint32_t width, uint32_t height) { return m_pipeline ? m_pipeline->setVideoWindow(x, y, width, height) : false; } bool GstMediaPipeline::haveData(MediaSourceStatus status, uint32_t needDataRequestId) { return m_pipeline ? m_pipeline->haveData(status, needDataRequestId) : false; } bool GstMediaPipeline::renderFrame() { return m_pipeline ? m_pipeline->renderFrame() : false; } bool GstMediaPipeline::setVolume(double targetVolume, uint32_t volumeDuration, EaseType easeType) { return m_pipeline ? m_pipeline->setVolume(targetVolume, volumeDuration, easeType) : false; } @@ -131,4 +95,22 @@ bool GstMediaPipeline::switchSource(const std::unique_ptr &source) bool GstMediaPipeline::getVolume(double ¤tVolume) { return m_pipeline ? m_pipeline->getVolume(currentVolume) : false; } bool GstMediaPipeline::setMute(int32_t sourceId, bool mute) { return m_pipeline ? m_pipeline->setMute(sourceId, mute) : false; } bool GstMediaPipeline::getMute(int32_t sourceId, bool &mute) { return m_pipeline ? m_pipeline->getMute(sourceId, mute) : false; } -bool GstMediaPipeline::setTextTrackIdentifier(const std::string &textTrackIdentifier) { return m_pipeline ? m_pipeline->setTextTrackIdentifier(textTrackIdentifier) : false; } \ No newline at end of file +bool GstMediaPipeline::setTextTrackIdentifier(const std::string &textTrackIdentifier) { return m_pipeline ? m_pipeline->setTextTrackIdentifier(textTrackIdentifier) : false; } + +// --- IMediaPipelineClient stubs --- + +void GstMediaPipeline::notifyPlaybackState(PlaybackState state) { } +void GstMediaPipeline::notifyPlaybackError(int32_t sourceId, PlaybackError error) { } +void GstMediaPipeline::notifyPosition(int64_t position) {} +void GstMediaPipeline::notifyNetworkState(NetworkState state) {} +void GstMediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo) {} +void GstMediaPipeline::notifyBufferUnderflow(int32_t sourceId) {} +void GstMediaPipeline::notifySourceFlushed(int32_t sourceId) {} +void GstMediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, + uint32_t needDataRequestId, + const std::shared_ptr &mediaPlayerShmInfo) {} +void GstMediaPipeline::notifyDuration(int64_t duration) {} +void GstMediaPipeline::notifyNativeSize(uint32_t width, uint32_t height, double aspect) {} +void GstMediaPipeline::notifyVideoData(bool hasData) {} +void GstMediaPipeline::notifyAudioData(bool hasData) {} +void GstMediaPipeline::notifyCancelNeedMediaData(int32_t sourceId) {} \ No newline at end of file diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h index 5918d9332..39af7d7ee 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.h +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -23,6 +23,7 @@ class GstMediaPipeline : public IMediaPipeline, std::weak_ptr getClient() override { return weak_from_this(); } + // IMediaPipelineClient Implementation (All required pure virtuals) void notifyNetworkState(NetworkState state) override; void notifyPlaybackState(PlaybackState state) override; void notifyPosition(int64_t position) override; @@ -33,9 +34,18 @@ class GstMediaPipeline : public IMediaPipeline, void notifyBufferUnderflow(int32_t sourceId) override; void notifyPlaybackError(int32_t sourceId, PlaybackError error) override; void notifySourceFlushed(int32_t sourceId) override; + void notifyDuration(int64_t duration) override; + void notifyNativeSize(uint32_t width, uint32_t height, double aspect = 1.0) override; + void notifyVideoData(bool hasData) override; + void notifyAudioData(bool hasData) override; + void notifyCancelNeedMediaData(int32_t sourceId) override; + + // IMediaPipeline Implementation + + + bool attachSource(const std::unique_ptr &source) override; + bool attachSource(std::unique_ptr &&source, int32_t &sourceId); - bool attachSource(std::unique_ptr &&source, int32_t &sourceId) override; - bool attachSource(const std::unique_ptr &source) override { return false; } bool removeSource(int32_t id) override; bool allSourcesAttached() override; bool load(MediaType type, const std::string &mimeType, const std::string &url) override; From 602cfe5bb24b6f6f79d545241d8e6673e7c0e2ed Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Mon, 1 Dec 2025 10:30:59 -0500 Subject: [PATCH 16/21] mp4demux count function ref fixed Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 68 +++++++++++++++------ test/gstTestHarness/rialto-gst-pipeline.cpp | 18 +++++- test/gstTestHarness/rialto-gst-pipeline.h | 14 +++++ 3 files changed, 78 insertions(+), 22 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 53bf29c59..5f90141ac 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -5,6 +5,9 @@ #include #include #include +#include +#include +#include #include "mp4demux.hpp" #include "rialto-gst-pipeline.h" @@ -20,6 +23,21 @@ static int32_t sourceIdVideo; using namespace firebolt::rialto; +uint32_t WaitForNeedDataRequest(int32_t sourceId, int timeoutMs = 5000) +{ + std::unique_lock lock(g_needDataMutex); + if (!g_needDataCv.wait_for(lock, std::chrono::milliseconds(timeoutMs), [sourceId]{ + return !g_needDataQueue.empty() && g_needDataQueue.front().sourceId == sourceId; + })) + { + return UINT32_MAX; + } + + uint32_t requestId = g_needDataQueue.front().requestId; + g_needDataQueue.pop(); + return requestId; +} + void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) { char fullpath[512]; @@ -86,15 +104,13 @@ void ConfigureAudio() // const char *codec_ptr = trackAudio.codec_data.c_str(); // codecData.data = std::vector( codec_ptr, &codec_ptr[trackAudio.codec_data.size()] ); - std::unique_ptr sourceAudio = - std::make_unique( - mimeType, - hasDrm, - alignment, - streamFormat, - trackAudio.audio.rate, - trackAudio.audio.channels, - std::make_shared(codecData) ); + std::unique_ptr sourceAudio = std::make_unique( + mimeType, + hasDrm, + audioConfig, + SegmentAlignment::UNDEFINED, + streamFormat, + nullptr /* codecData*/ ); gstMediaPipeline->attachSource( std::move(sourceAudio), sourceIdAudio ); } @@ -146,12 +162,13 @@ void ConfigureComplete() gstMediaPipeline->allSourcesAttached(); } -void InjectAudio() +void InjectAudio(int32_t needDataId) { LoadAndDemuxSegment(trackAudio, "audio/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/chunk-stream0-00001.m4s" << std::endl; - size_t segmentCount = trackAudio.getNbSegments(); // Corrected function name + // size_t segmentCount = trackAudio.getNbSegments(); + size_t segmentCount = trackAudio.count(); printf("adding %zu audio frames\n", segmentCount); for (size_t i = 0; i < segmentCount; ++i) @@ -170,17 +187,18 @@ void InjectAudio() std::memcpy(data, trackAudio.getPtr(i), len); audioSegment->setData((uint32_t)len, data); - AddSegmentStatus status = gstMediaPipeline->addSegment(0, audioSegment); + AddSegmentStatus status = gstMediaPipeline->addSegment(needDataId, audioSegment); assert(status == AddSegmentStatus::OK); } } -void InjectVideo() +void InjectVideo(int32_t needDataId) { LoadAndDemuxSegment(trackVideo, "video/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/video/chunk-stream0-00001.m4s" << std::endl; - size_t segmentCount = trackVideo.getNbSegments(); // Corrected function name + // size_t segmentCount = trackVideo.getNbSegments(); + size_t segmentCount = trackVideo.count(); printf("adding %zu video frames\n", segmentCount); for (size_t i = 0; i < segmentCount; ++i) @@ -201,7 +219,7 @@ void InjectVideo() std::memcpy(data, trackVideo.getPtr(i), len); videoSegment->setData((uint32_t)len, data); - AddSegmentStatus status = gstMediaPipeline->addSegment(0, videoSegment); + AddSegmentStatus status = gstMediaPipeline->addSegment(needDataId, videoSegment); assert(status == AddSegmentStatus::OK); } } @@ -227,18 +245,28 @@ int my_main(int argc, char **argv) fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); } - gstMediaPipeline->play(); + // MUST happen before any attachSource() to create a Rialto Gstreamer player + gstMediaPipeline->load(MediaType::MSE, "video/fmp4", "test://local"); // Dummy values ConfigureAudio(); ConfigureVideo(); ConfigureComplete(); - InjectAudio(); - InjectVideo(); + gstMediaPipeline->play(); + + uint32_t audioReqId = WaitForNeedDataRequest(sourceIdAudio); + uint32_t videoReqId = WaitForNeedDataRequest(sourceIdVideo); + + if (audioReqId != UINT32_MAX) + InjectAudio(audioReqId); + + if (videoReqId != UINT32_MAX) + InjectVideo(videoReqId); + - std::this_thread::sleep_for(std::chrono::seconds(5)); + // std::this_thread::sleep_for(std::chrono::seconds(5)); - gstMediaPipeline->stop(); + // gstMediaPipeline->stop(); return 0; } diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index 0a5d228b1..e76a4a336 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -3,6 +3,13 @@ #include #include #include +#include +#include +#include + +std::mutex g_needDataMutex; +std::condition_variable g_needDataCv; +std::queue g_needDataQueue; using namespace firebolt::rialto; @@ -106,9 +113,16 @@ void GstMediaPipeline::notifyNetworkState(NetworkState state) {} void GstMediaPipeline::notifyQos(int32_t sourceId, const QosInfo &qosInfo) {} void GstMediaPipeline::notifyBufferUnderflow(int32_t sourceId) {} void GstMediaPipeline::notifySourceFlushed(int32_t sourceId) {} + void GstMediaPipeline::notifyNeedMediaData(int32_t sourceId, size_t frameCount, - uint32_t needDataRequestId, - const std::shared_ptr &mediaPlayerShmInfo) {} + uint32_t needDataRequestId, + const std::shared_ptr &mediaPlayerShmInfo) +{ + std::lock_guard lock(g_needDataMutex); + g_needDataQueue.push({sourceId, needDataRequestId}); + g_needDataCv.notify_one(); +} + void GstMediaPipeline::notifyDuration(int64_t duration) {} void GstMediaPipeline::notifyNativeSize(uint32_t width, uint32_t height, double aspect) {} void GstMediaPipeline::notifyVideoData(bool hasData) {} diff --git a/test/gstTestHarness/rialto-gst-pipeline.h b/test/gstTestHarness/rialto-gst-pipeline.h index 39af7d7ee..0a65320a0 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.h +++ b/test/gstTestHarness/rialto-gst-pipeline.h @@ -6,6 +6,20 @@ #include #include +#include +#include +#include + +struct NeedDataRequestEvent +{ + int32_t sourceId; + uint32_t requestId; +}; + +extern std::mutex g_needDataMutex; +extern std::condition_variable g_needDataCv; +extern std::queue g_needDataQueue; + using namespace firebolt::rialto; class GstMediaPipeline : public IMediaPipeline, From 6df2d7e910fa2add8b0eed2949ebef8896547995 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Mon, 1 Dec 2025 19:22:18 -0500 Subject: [PATCH 17/21] Additional fixes Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 49 ++++++++++++++++----- test/gstTestHarness/rialto-gst-pipeline.cpp | 8 ++-- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 5f90141ac..37179fb3f 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -26,18 +26,43 @@ using namespace firebolt::rialto; uint32_t WaitForNeedDataRequest(int32_t sourceId, int timeoutMs = 5000) { std::unique_lock lock(g_needDataMutex); - if (!g_needDataCv.wait_for(lock, std::chrono::milliseconds(timeoutMs), [sourceId]{ - return !g_needDataQueue.empty() && g_needDataQueue.front().sourceId == sourceId; - })) + + // Wait until a matching event is in the queue + bool ok = g_needDataCv.wait_for(lock, std::chrono::milliseconds(timeoutMs), [&]{ + std::queue tmp = g_needDataQueue; + while (!tmp.empty()) { + if (tmp.front().sourceId == sourceId) + return true; + tmp.pop(); + } + return false; + }); + + if (!ok) { + fprintf(stderr, "ERROR: Timeout waiting for need-data for source %d\n", sourceId); return UINT32_MAX; } - uint32_t requestId = g_needDataQueue.front().requestId; - g_needDataQueue.pop(); + uint32_t requestId = UINT32_MAX; + size_t qSize = g_needDataQueue.size(); + for (size_t i = 0; i < qSize; ++i) { + NeedDataRequestEvent ev = g_needDataQueue.front(); + g_needDataQueue.pop(); + + if (ev.sourceId == sourceId && requestId == UINT32_MAX) { + requestId = ev.requestId; + + } else { + g_needDataQueue.push(ev); + } + } + return requestId; } + + void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) { char fullpath[512]; @@ -142,7 +167,7 @@ void ConfigureVideo() } CodecData codecData; const char *codec_ptr = trackVideo.codec_data.c_str(); - codecData.data = std::vector( codec_ptr, &codec_ptr[trackVideo.codec_data.size()] ); + codecData.data = std::vector( codec_ptr, codec_ptr + trackVideo.codec_data.size() ); std::unique_ptr sourceVideo = std::make_unique( @@ -240,13 +265,13 @@ int my_main(int argc, char **argv) return -1; } - if (!gstMediaPipeline->setVideoWindow(0, 0, 1920, 1080)) - { - fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); - } + // if (!gstMediaPipeline->setVideoWindow(0, 0, 1920, 1080)) + // { + // fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); + // } // MUST happen before any attachSource() to create a Rialto Gstreamer player - gstMediaPipeline->load(MediaType::MSE, "video/fmp4", "test://local"); // Dummy values + gstMediaPipeline->load(MediaType::MSE, "video/x-h265", "test://local"); // Dummy values ConfigureAudio(); ConfigureVideo(); @@ -264,7 +289,7 @@ int my_main(int argc, char **argv) InjectVideo(videoReqId); - // std::this_thread::sleep_for(std::chrono::seconds(5)); + // std::this_thread::sleep_for(std::chrono::seconds(3)); // gstMediaPipeline->stop(); diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index e76a4a336..9f6927bb2 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -32,9 +32,11 @@ bool GstMediaPipeline::init() std::shared_ptr factory = IMediaPipelineFactory::createFactory(); if (!factory) return false; - VideoRequirements requirements = {}; + constexpr std::uint32_t kWidth{1920}; + constexpr std::uint32_t kHeight{1080}; + VideoRequirements kRequirements{kWidth, kHeight}; - m_pipeline = factory->createMediaPipeline(weak_from_this(), requirements); + m_pipeline = factory->createMediaPipeline(weak_from_this(), kRequirements); return m_pipeline != nullptr; } @@ -52,7 +54,7 @@ bool GstMediaPipeline::attachSource(std::unique_ptr &&source, int32 return false; } - bool ok = attachSource(source); + bool ok = attachSource(std::move(source)); if (ok) { From 28c2e7d67b88c6193a5cebba519f32b586e35203 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Tue, 2 Dec 2025 17:44:23 -0500 Subject: [PATCH 18/21] 4K place holder added Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 12 ++++++------ test/gstTestHarness/rialto-gst-pipeline.cpp | 5 +++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 37179fb3f..86f96ae3b 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -265,10 +265,10 @@ int my_main(int argc, char **argv) return -1; } - // if (!gstMediaPipeline->setVideoWindow(0, 0, 1920, 1080)) - // { - // fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); - // } + if (!gstMediaPipeline->setVideoWindow(0, 0, 1920, 1080)) + { + fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); + } // MUST happen before any attachSource() to create a Rialto Gstreamer player gstMediaPipeline->load(MediaType::MSE, "video/x-h265", "test://local"); // Dummy values @@ -289,9 +289,9 @@ int my_main(int argc, char **argv) InjectVideo(videoReqId); - // std::this_thread::sleep_for(std::chrono::seconds(3)); + std::this_thread::sleep_for(std::chrono::seconds(7)); - // gstMediaPipeline->stop(); + gstMediaPipeline->stop(); return 0; } diff --git a/test/gstTestHarness/rialto-gst-pipeline.cpp b/test/gstTestHarness/rialto-gst-pipeline.cpp index 9f6927bb2..99fbe3f24 100644 --- a/test/gstTestHarness/rialto-gst-pipeline.cpp +++ b/test/gstTestHarness/rialto-gst-pipeline.cpp @@ -32,8 +32,9 @@ bool GstMediaPipeline::init() std::shared_ptr factory = IMediaPipelineFactory::createFactory(); if (!factory) return false; - constexpr std::uint32_t kWidth{1920}; - constexpr std::uint32_t kHeight{1080}; + constexpr std::uint32_t kWidth{3840}; + constexpr std::uint32_t kHeight{2160}; + VideoRequirements kRequirements{kWidth, kHeight}; m_pipeline = factory->createMediaPipeline(weak_from_this(), kRequirements); From 18670fdb984a4862718dbd1dad3b0a441679d229 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Tue, 2 Dec 2025 22:47:47 -0500 Subject: [PATCH 19/21] Load window reordered after load() Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 86f96ae3b..9724055c1 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -147,8 +147,8 @@ void ConfigureVideo() bool hasDrm = false; std::string mimeType; StreamFormat streamFormat; - int32_t width = trackVideo.video.width; - int32_t height = trackVideo.video.height; + // int32_t width = trackVideo.video.width; + // int32_t height = trackVideo.video.height; SegmentAlignment alignment = SegmentAlignment::AU; switch( trackVideo.codec_type ) @@ -168,6 +168,10 @@ void ConfigureVideo() CodecData codecData; const char *codec_ptr = trackVideo.codec_data.c_str(); codecData.data = std::vector( codec_ptr, codec_ptr + trackVideo.codec_data.size() ); + + //Temp hack + int32_t width = 1920; + int32_t height = 1080; std::unique_ptr sourceVideo = std::make_unique( @@ -265,14 +269,15 @@ int my_main(int argc, char **argv) return -1; } + + // MUST happen before any attachSource() to create a Rialto Gstreamer player + gstMediaPipeline->load(MediaType::MSE, "video/x-h265", "file:///tmp/data/bipbop-gen/video/chunk-stream0-00001.m4s"); // Temp + if (!gstMediaPipeline->setVideoWindow(0, 0, 1920, 1080)) { fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); } - // MUST happen before any attachSource() to create a Rialto Gstreamer player - gstMediaPipeline->load(MediaType::MSE, "video/x-h265", "test://local"); // Dummy values - ConfigureAudio(); ConfigureVideo(); ConfigureComplete(); From 2662710b3cce17773aad8b9781c948bde80003d4 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Wed, 3 Dec 2025 11:38:08 -0500 Subject: [PATCH 20/21] Manifest load added Signed-off-by: ryadav698 --- test/gstTestHarness/rialto-api-test.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 9724055c1..0ed191e0d 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -154,11 +154,11 @@ void ConfigureVideo() switch( trackVideo.codec_type ) { case MultiChar_Constant("hvcC"): - mimeType = "video/x-h265"; + mimeType = "video/h265"; streamFormat = StreamFormat::HVC1; break; case MultiChar_Constant("avcC"): - mimeType = "video/x-h264"; + mimeType = "video/h264"; streamFormat = StreamFormat::AVC; break; default: @@ -271,27 +271,27 @@ int my_main(int argc, char **argv) // MUST happen before any attachSource() to create a Rialto Gstreamer player - gstMediaPipeline->load(MediaType::MSE, "video/x-h265", "file:///tmp/data/bipbop-gen/video/chunk-stream0-00001.m4s"); // Temp + gstMediaPipeline->load(MediaType::MSE, "", "file:///tmp/data/bipbop-gen/main.mpd"); // Temp if (!gstMediaPipeline->setVideoWindow(0, 0, 1920, 1080)) { fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); } - ConfigureAudio(); - ConfigureVideo(); - ConfigureComplete(); + // ConfigureAudio(); + // ConfigureVideo(); + // ConfigureComplete(); gstMediaPipeline->play(); - uint32_t audioReqId = WaitForNeedDataRequest(sourceIdAudio); - uint32_t videoReqId = WaitForNeedDataRequest(sourceIdVideo); + // uint32_t audioReqId = WaitForNeedDataRequest(sourceIdAudio); + // uint32_t videoReqId = WaitForNeedDataRequest(sourceIdVideo); - if (audioReqId != UINT32_MAX) - InjectAudio(audioReqId); + // if (audioReqId != UINT32_MAX) + // InjectAudio(audioReqId); - if (videoReqId != UINT32_MAX) - InjectVideo(videoReqId); + // if (videoReqId != UINT32_MAX) + // InjectVideo(videoReqId); std::this_thread::sleep_for(std::chrono::seconds(7)); From c5a4efcbe96b8cf06b9b5c90eed8fbc342ac6f32 Mon Sep 17 00:00:00 2001 From: ryadav698 Date: Thu, 4 Dec 2025 09:06:48 -0500 Subject: [PATCH 21/21] Some hacks removed Signed-off-by: ryadav698 --- CMakeLists.txt | 16 ------------- test/gstTestHarness/rialto-api-test.cpp | 31 ++++++++++--------------- 2 files changed, 12 insertions(+), 35 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b4e13dcaa..9faf8b524 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -465,27 +465,11 @@ set(GSTTESTHARNESS_SOURCES find_path( RIALTO_INCLUDE_DIR NAMES IMediaPipeline.h PATH_SUFFIXES rialto) -# find_path(RIALTO_GSTREAMER_INCLUDE_DIR -# NAMES client/GStreamerMSEMediaPlayerClient.h -# PATH_SUFFIXES rialto-gstreamer -# ) - find_library( RIALTO_LIBRARY NAMES libRialtoClient.so RialtoClient ) -# find_library(RIALTO_SERVER_MANAGER -# NAMES RialtoServerManager libRialtoServerManager.so -# ) - -# find_library(RIALTO_OCDM -# NAMES ocdmRialto libocdmRialto.so -# ) - include( FindPackageHandleStandardArgs ) -# find_package_handle_standard_args( RIALTO DEFAULT_MSG -# RIALTO_LIBRARY RIALTO_INCLUDE_DIR RIALTO_SERVER_MANAGER RIALTO_OCDM ) - find_package_handle_standard_args( RIALTO DEFAULT_MSG RIALTO_LIBRARY RIALTO_INCLUDE_DIR ) diff --git a/test/gstTestHarness/rialto-api-test.cpp b/test/gstTestHarness/rialto-api-test.cpp index 0ed191e0d..a6aad1aa4 100644 --- a/test/gstTestHarness/rialto-api-test.cpp +++ b/test/gstTestHarness/rialto-api-test.cpp @@ -61,8 +61,6 @@ uint32_t WaitForNeedDataRequest(int32_t sourceId, int timeoutMs = 5000) return requestId; } - - void LoadAndDemuxSegment(Mp4Demux &mp4Demux, const char *path) { char fullpath[512]; @@ -147,8 +145,8 @@ void ConfigureVideo() bool hasDrm = false; std::string mimeType; StreamFormat streamFormat; - // int32_t width = trackVideo.video.width; - // int32_t height = trackVideo.video.height; + int32_t width = trackVideo.video.width; + int32_t height = trackVideo.video.height; SegmentAlignment alignment = SegmentAlignment::AU; switch( trackVideo.codec_type ) @@ -168,10 +166,6 @@ void ConfigureVideo() CodecData codecData; const char *codec_ptr = trackVideo.codec_data.c_str(); codecData.data = std::vector( codec_ptr, codec_ptr + trackVideo.codec_data.size() ); - - //Temp hack - int32_t width = 1920; - int32_t height = 1080; std::unique_ptr sourceVideo = std::make_unique( @@ -196,7 +190,6 @@ void InjectAudio(int32_t needDataId) LoadAndDemuxSegment(trackAudio, "audio/chunk-stream0-00001.m4s"); std::cout << "loading rialtotest /tmp/data/bipbop-gen/audio/chunk-stream0-00001.m4s" << std::endl; - // size_t segmentCount = trackAudio.getNbSegments(); size_t segmentCount = trackAudio.count(); printf("adding %zu audio frames\n", segmentCount); @@ -271,27 +264,27 @@ int my_main(int argc, char **argv) // MUST happen before any attachSource() to create a Rialto Gstreamer player - gstMediaPipeline->load(MediaType::MSE, "", "file:///tmp/data/bipbop-gen/main.mpd"); // Temp + gstMediaPipeline->load(MediaType::MSE, "video/mp4", "file:///tmp/data/bipbop-gen/video/chunk-stream0-00001.m4s"); // Temp if (!gstMediaPipeline->setVideoWindow(0, 0, 1920, 1080)) { fprintf(stderr, "Warning: Failed to set video window. Video may not appear.\n"); } - // ConfigureAudio(); - // ConfigureVideo(); - // ConfigureComplete(); + ConfigureAudio(); + ConfigureVideo(); + ConfigureComplete(); gstMediaPipeline->play(); - // uint32_t audioReqId = WaitForNeedDataRequest(sourceIdAudio); - // uint32_t videoReqId = WaitForNeedDataRequest(sourceIdVideo); + uint32_t audioReqId = WaitForNeedDataRequest(sourceIdAudio); + uint32_t videoReqId = WaitForNeedDataRequest(sourceIdVideo); - // if (audioReqId != UINT32_MAX) - // InjectAudio(audioReqId); + if (audioReqId != UINT32_MAX) + InjectAudio(audioReqId); - // if (videoReqId != UINT32_MAX) - // InjectVideo(videoReqId); + if (videoReqId != UINT32_MAX) + InjectVideo(videoReqId); std::this_thread::sleep_for(std::chrono::seconds(7));