From c2f21b955d4d2dcccbf165c791db151024c24186 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 8 Nov 2022 19:40:03 -0600 Subject: [PATCH] Implement foundation for HDR support Likely not functional for any decoder yet --- libgamestream/client.c | 4 +++- src/config.c | 4 ++++ src/main.c | 5 +++++ src/video/aml.c | 47 ++++++++++++++++++++---------------------- src/video/ffmpeg.c | 14 ++++++------- src/video/rk.c | 23 +++++++++------------ 6 files changed, 51 insertions(+), 46 deletions(-) diff --git a/libgamestream/client.c b/libgamestream/client.c index dc591cb6..b87192df 100644 --- a/libgamestream/client.c +++ b/libgamestream/client.c @@ -742,7 +742,9 @@ int gs_start_app(PSERVER_DATA server, STREAM_CONFIGURATION *config, int appId, b // used to use 60 here but that locked the frame rate to 60 FPS // on GFE 3.20.3. int fps = config->fps > 60 ? 0 : config->fps; - snprintf(url, sizeof(url), "https://%s:%u/launch?uniqueid=%s&uuid=%s&appid=%d&mode=%dx%dx%d&additionalStates=1&sops=%d&rikey=%s&rikeyid=%d&localAudioPlayMode=%d&surroundAudioInfo=%d&remoteControllersBitmap=%d&gcmap=%d", server->serverInfo.address, server->httpsPort, unique_id, uuid_str, appId, config->width, config->height, fps, sops, rikey_hex, rikeyid, localaudio, surround_info, gamepad_mask, gamepad_mask); + snprintf(url, sizeof(url), "https://%s:%u/launch?uniqueid=%s&uuid=%s&appid=%d&mode=%dx%dx%d&additionalStates=1&sops=%d&rikey=%s&rikeyid=%d&localAudioPlayMode=%d&surroundAudioInfo=%d&remoteControllersBitmap=%d&gcmap=%d%s", + server->serverInfo.address, server->httpsPort, unique_id, uuid_str, appId, config->width, config->height, fps, sops, rikey_hex, rikeyid, localaudio, surround_info, gamepad_mask, gamepad_mask, + config->enableHdr ? "&hdrMode=1&clientHdrCapVersion=0&clientHdrCapSupportedFlagsInUint32=0&clientHdrCapMetaDataId=NV_STATIC_METADATA_TYPE_1&clientHdrCapDisplayData=0x0x0x0x0x0x0x0x0x0x0" : ""); } else snprintf(url, sizeof(url), "https://%s:%u/resume?uniqueid=%s&uuid=%s&rikey=%s&rikeyid=%d&surroundAudioInfo=%d", server->serverInfo.address, server->httpsPort, unique_id, uuid_str, rikey_hex, rikeyid, surround_info); diff --git a/src/config.c b/src/config.c index 83906425..ebbc7564 100644 --- a/src/config.c +++ b/src/config.c @@ -74,6 +74,7 @@ static struct option long_options[] = { {"nomouseemulation", no_argument, NULL, '4'}, {"pin", required_argument, NULL, '5'}, {"port", required_argument, NULL, '6'}, + {"hdr", no_argument, NULL, '7'}, {0, 0, 0, 0}, }; @@ -252,6 +253,9 @@ static void parse_argument(int c, char* value, PCONFIGURATION config) { case '6': config->port = atoi(value); break; + case '7': + config->stream.enableHdr = true; + break; case 1: if (config->action == NULL) config->action = value; diff --git a/src/main.c b/src/main.c index 71fddac0..3c364044 100644 --- a/src/main.c +++ b/src/main.c @@ -202,6 +202,7 @@ static void help() { printf("\t-bitrate \tSpecify the bitrate in Kbps\n"); printf("\t-packetsize \tSpecify the maximum packetsize in bytes\n"); printf("\t-codec \t\tSelect used codec: auto/h264/h265 (default auto)\n"); + printf("\t-hdr\t\tEnable HDR streaming (experimental, requires host and device support)\n"); printf("\t-remote \t\t\tEnable optimizations for WAN streaming (default auto)\n"); printf("\t-app \t\tName of app to stream\n"); printf("\t-nosops\t\t\tDon't allow GFE to modify game settings\n"); @@ -316,6 +317,10 @@ int main(int argc, char* argv[]) { exit(-1); } config.stream.supportsHevc = config.codec != CODEC_H264 && (config.codec == CODEC_HEVC || platform_supports_hevc(system)); + if (config.stream.enableHdr && !config.stream.supportsHevc) { + fprintf(stderr, "HDR streaming requires HEVC codec\n"); + exit(-1); + } #ifdef HAVE_SDL if (system == SDL) diff --git a/src/video/aml.c b/src/video/aml.c index f36e3735..7126e3c6 100644 --- a/src/video/aml.c +++ b/src/video/aml.c @@ -42,31 +42,28 @@ int aml_setup(int videoFormat, int width, int height, int redrawRate, void* cont codecParam.noblock = 0; codecParam.am_sysinfo.param = 0; - switch (videoFormat) { - case VIDEO_FORMAT_H264: - if (width > 1920 || height > 1080) { - codecParam.video_type = VFORMAT_H264_4K2K; - codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_H264_4K2K; - } else { - codecParam.video_type = VFORMAT_H264; - codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_H264; - - // Workaround for decoding special case of C1, 1080p, H264 - int major, minor; - struct utsname name; - uname(&name); - int ret = sscanf(name.release, "%d.%d", &major, &minor); - if (!(major > 3 || (major == 3 && minor >= 14)) && width == 1920 && height == 1080) - codecParam.am_sysinfo.param = (void*) UCODE_IP_ONLY_PARAM; - } - break; - case VIDEO_FORMAT_H265: - codecParam.video_type = VFORMAT_HEVC; - codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_HEVC; - break; - default: - printf("Video format not supported\n"); - return -1; + if (videoFormat & VIDEO_FORMAT_MASK_H264) { + if (width > 1920 || height > 1080) { + codecParam.video_type = VFORMAT_H264_4K2K; + codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_H264_4K2K; + } else { + codecParam.video_type = VFORMAT_H264; + codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_H264; + + // Workaround for decoding special case of C1, 1080p, H264 + int major, minor; + struct utsname name; + uname(&name); + int ret = sscanf(name.release, "%d.%d", &major, &minor); + if (!(major > 3 || (major == 3 && minor >= 14)) && width == 1920 && height == 1080) + codecParam.am_sysinfo.param = (void*) UCODE_IP_ONLY_PARAM; + } + } else if (videoFormat & VIDEO_FORMAT_MASK_H265) { + codecParam.video_type = VFORMAT_HEVC; + codecParam.am_sysinfo.format = VIDEO_DEC_FORMAT_HEVC; + } else { + printf("Video format not supported\n"); + return -1; } codecParam.am_sysinfo.width = width; diff --git a/src/video/ffmpeg.c b/src/video/ffmpeg.c index 073673b6..6f8f899b 100644 --- a/src/video/ffmpeg.c +++ b/src/video/ffmpeg.c @@ -60,13 +60,13 @@ int ffmpeg_init(int videoFormat, int width, int height, int perf_lvl, int buffer } ffmpeg_decoder = perf_lvl & VAAPI_ACCELERATION ? VAAPI : SOFTWARE; - switch (videoFormat) { - case VIDEO_FORMAT_H264: - decoder = avcodec_find_decoder_by_name("h264"); - break; - case VIDEO_FORMAT_H265: - decoder = avcodec_find_decoder_by_name("hevc"); - break; + if (videoFormat & VIDEO_FORMAT_MASK_H264) { + decoder = avcodec_find_decoder_by_name("h264"); + } else if (videoFormat & VIDEO_FORMAT_MASK_H265) { + decoder = avcodec_find_decoder_by_name("hevc"); + } else { + printf("Video format not supported\n"); + return -1; } if (decoder == NULL) { diff --git a/src/video/rk.c b/src/video/rk.c index 473512b3..bcd69492 100644 --- a/src/video/rk.c +++ b/src/video/rk.c @@ -254,18 +254,15 @@ int rk_setup(int videoFormat, int width, int height, int redrawRate, void* conte int ret; int i; int j; - int format = 0; - - switch (videoFormat) { - case VIDEO_FORMAT_H264: - format = RK_H264; - break; - case VIDEO_FORMAT_H265: - format = RK_H265; - break; - default: - fprintf(stderr, "Video format not supported\n"); - return -1; + int format; + + if (videoFormat & VIDEO_FORMAT_MASK_H264) { + format = RK_H264; + } else if (videoFormat & VIDEO_FORMAT_MASK_H265) { + format = RK_H265; + } else { + fprintf(stderr, "Video format not supported\n"); + return -1; } MppCodingType mpp_type = (MppCodingType)format; @@ -328,7 +325,7 @@ int rk_setup(int videoFormat, int width, int height, int redrawRate, void* conte continue; } for (j = 0; j < ovr->count_formats; j++) { - if (ovr->formats[j] == DRM_FORMAT_NV12) { + if (ovr->formats[j] == ((videoFormat & VIDEO_FORMAT_MASK_10BIT) ? DRM_FORMAT_NV12_10 : DRM_FORMAT_NV12)) { break; } }