Skip to content

Commit

Permalink
Video - rocDecode integration in rocAL (#253)
Browse files Browse the repository at this point in the history
* Add CMakeList changes

Requires VideoDemuxer to have .cpp file

* Add rocDecode utils files and cmake changes

* rocDecode integration for rocAL

* merge with tot

* Add initial support for rocDecode integration

* Add fix to decode sequences

* VideoDemuxer - support to return dts

* Support to seek exact frame

Facing seg fault

* Add intermediary buffers to copy

* Change the name of rocdec files

* Temporary rocDecode cmake changes

Add utils folder to rocAL hip to compile with rocDecode

* Fix CMake for rocDecode

* Minor fix

* Fix stride for rocdecode video decoder

* Revert "Temporary rocDecode cmake changes"

This reverts commit 21b0538.

* Introduce CMake for rocDecode

Revert additional changes

* Fix issues with CMake

* rocDecode Flush decoder after decoding each sequence

* Add changes to flush decoder after seek

* Add support in rocDecode to seek to exact frame using dts

* Add changes in API to pass device ID to video decoder

* Add stream synchronize

* Minor changes

* Minor change

* Change rocDecode to all caps in CMake

* Minor changes

* Minor CMake change

* Minor changes

* Introduce enable rocdecode flag in CMake

* Minor fix

* Minor changes

* Modify CMake to use only ROCM_PATH

* Use Pascal case for fn names in Video Decoder and other derived classes

* Fix CMakeLists

* Minor change

* Fix rocAL_hip CMakeLists for rocDecode

* Add decoder type argument to Video readers

* Fix video metadata reader

* Minor changes

* Move default constructor to class

* Minor fix

* Update CHANGELOG and docs

* Add link to rocDecode

* Update README with rocDecode installation instructions

* Update rocAL version

* Update README with rocDecode manual installation

---------

Co-authored-by: rrawther <[email protected]>
Co-authored-by: Sundar Rajan Vaithiyanathan <[email protected]>
Co-authored-by: Kiriti Gowda <[email protected]>
  • Loading branch information
4 people authored Feb 5, 2025
1 parent 57b6bcd commit 7ac767e
Show file tree
Hide file tree
Showing 33 changed files with 496 additions and 77 deletions.
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,27 @@

Full documentation for rocLibrary is available at [https://rocm.docs.amd.com/projects/rocAL/](https://rocm.docs.amd.com/projects/rocAL/en/latest/).

## rocAL 2.2.0 (unreleased)
## rocAL 2.3.0 (unreleased)

### Added
* Extended support to rocAL's video decoder to use rocDecode hardware decoder.

### Changed

### Removed

### Optimizations

### Resolved issues

### Known issues

### Upcoming changes

## rocAL 2.2.0

### Added
* Extended support to rocAL's video decoder to use rocDecode hardware decoder.

### Changed
* AMD Clang is now the default CXX and C compiler.
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED On)

# rocAL Version
set(VERSION "2.2.0")
set(VERSION "2.3.0")
# Set Project Version and Language
project(rocal VERSION ${VERSION} LANGUAGES CXX)

Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ rocAL can be currently used to perform the following operations either with rand
* Source: `https://github.com/Tencent/rapidjson.git`
* Tag: `master`

* [rocDecode](https://github.com/ROCm/rocDecode) - Manual install, Optional for source install, but required for package install
* Source : `https://github.com/ROCm/rocDecode.git`
* Tag : `develop`

> [!IMPORTANT]
> * Required compiler support
> * C++17
Expand Down
80 changes: 80 additions & 0 deletions cmake/FindrocDecode.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
################################################################################
#
# MIT License
#
# Copyright (c) 2025 Advanced Micro Devices, Inc.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
################################################################################

# ROCM Path
if(ROCM_PATH)
message("-- ${White}FindrocDecode: ROCM_PATH Set -- ${ROCM_PATH}${ColourReset}")
else()
set(ROCM_PATH /opt/rocm CACHE PATH "Default ROCm installation path")
endif()

# find rocDecode - library and headers
find_path(ROCDECODE_INCLUDE_DIR NAMES rocdecode.h PATHS ${ROCM_PATH}/include/rocdecode)
find_library(ROCDECODE_LIBRARY NAMES rocdecode HINTS ${ROCM_PATH}/lib)
mark_as_advanced(ROCDECODE_INCLUDE_DIR)
mark_as_advanced(ROCDECODE_LIBRARY)

if(ROCDECODE_INCLUDE_DIR AND ROCDECODE_LIBRARY)
message("-- ${White}FindrocDecode -- Using rocDecode: \n\tIncludes:${ROCDECODE_INCLUDE_DIR}\n\tLib:${ROCDECODE_LIBRARY}${ColourReset}")
set(ROCDECODE_FOUND TRUE)
else()
if(rocDecode_FIND_REQUIRED)
message(FATAL_ERROR "FindrocDecode -- Failed to find rocDecode Library")
endif()
message( "-- ${Yellow}NOTE: FindrocDecode failed to find rocDecode -- INSTALL rocDecode${ColourReset}" )
endif()

if(ROCDECODE_FOUND)
# Find rocDecode Version
file(READ "${ROCDECODE_INCLUDE_DIR}/rocdecode_version.h" ROCDECODE_VERSION_FILE)
string(REGEX MATCH "ROCDECODE_MAJOR_VERSION ([0-9]*)" _ ${ROCDECODE_VERSION_FILE})
set(ROCDECODE_VER_MAJOR ${CMAKE_MATCH_1})
string(REGEX MATCH "ROCDECODE_MINOR_VERSION ([0-9]*)" _ ${ROCDECODE_VERSION_FILE})
set(ROCDECODE_VER_MINOR ${CMAKE_MATCH_1})
string(REGEX MATCH "ROCDECODE_MICRO_VERSION ([0-9]*)" _ ${ROCDECODE_VERSION_FILE})
set(ROCDECODE_VER_MICRO ${CMAKE_MATCH_1})
message("-- ${White}Found rocDecode Version: ${ROCDECODE_VER_MAJOR}.${ROCDECODE_VER_MINOR}.${ROCDECODE_VER_MICRO}${ColourReset}")
mark_as_advanced(ROCDECODE_VER_MAJOR)
mark_as_advanced(ROCDECODE_VER_MINOR)
mark_as_advanced(ROCDECODE_VER_MICRO)
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
rocDecode
FOUND_VAR
ROCDECODE_FOUND
REQUIRED_VARS
ROCDECODE_INCLUDE_DIR
ROCDECODE_LIBRARY
)

set(ROCDECODE_FOUND ${ROCDECODE_FOUND} CACHE INTERNAL "")
set(ROCDECODE_INCLUDE_DIR ${ROCDECODE_INCLUDE_DIR} CACHE INTERNAL "")
set(ROCDECODE_LIBRARY ${ROCDECODE_LIBRARY} CACHE INTERNAL "")
set(ROCDECODE_VER_MAJOR ${ROCDECODE_VER_MAJOR} CACHE INTERNAL "")
set(ROCDECODE_VER_MINOR ${ROCDECODE_VER_MINOR} CACHE INTERNAL "")
set(ROCDECODE_VER_MICRO ${ROCDECODE_VER_MICRO} CACHE INTERNAL "")
1 change: 1 addition & 0 deletions docs/user_guide/ch1.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,6 @@ rocAL operators offer the flexibility to run on CPU or GPU for building hybrid p
| Image_raw | Decodes images in raw format |
| Image_random_crop | Decodes and randomly crops JPEG images |
| Image_slice | Decodes and slices JPEG images |
| Video | Decodes videos using FFmpeg/[rocDecode](https://github.com/ROCm/rocDecode) |

To see examples demonstrating the usage of decoders and readers, [click here](https://github.com/ROCm/rocAL/tree/master/docs/examples)
18 changes: 16 additions & 2 deletions rocAL/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ find_package(FFmpeg QUIET)
find_package(OpenCV QUIET)
find_package(SndFile QUIET)
find_package(LibTar QUIET)
find_package(rocDecode QUIET)

# HIP Backend
if(GPU_SUPPORT AND "${BACKEND}" STREQUAL "HIP")
Expand Down Expand Up @@ -268,7 +269,11 @@ if(${BUILD_ROCAL})
)

link_directories(${ROCM_PATH}/${CMAKE_INSTALL_LIBDIR})

#rocDecode
if ("${BACKEND}" STREQUAL "HIP" AND HIP_FOUND AND ROCDECODE_FOUND)
include_directories(${ROCDECODE_INCLUDE_DIR} ${ROCM_PATH}/share/rocdecode/utils/rocvideodecode)
set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} ${ROCDECODE_LIBRARY})
endif()
if("${BACKEND}" STREQUAL "HIP" AND HIP_FOUND)
link_directories(${HIP_PATH}/${CMAKE_INSTALL_LIBDIR})
include_directories(${ROCM_PATH}/${CMAKE_INSTALL_INCLUDEDIR} rocAL_hip)
Expand All @@ -281,14 +286,22 @@ if(${BUILD_ROCAL})
link_directories(${AMDRPP_LIBRARIES_DIRS} ${TurboJpeg_LIBRARIES_DIRS} ${PROTOBUF_LIBRARY_DIRS} /usr/local/lib/)

file(GLOB_RECURSE SOURCES "source/*.cpp")
add_library(${PROJECT_NAME} SHARED ${SOURCES} ${TF_PROTO_SRCS} ${TF_PROTO_HEADERS} ${CAFFE_PROTO_HEADERS} ${CAFFE_PROTO_SRCS} ${CAFFE2_PROTO_SRCS} ${CAFFE2_PROTO_HEADERS})
set(ROCDECODE_SRCS ${ROCM_PATH}/share/rocdecode/utils/rocvideodecode/roc_video_dec.cpp)
add_library(${PROJECT_NAME} SHARED ${SOURCES} ${TF_PROTO_SRCS} ${TF_PROTO_HEADERS} ${CAFFE_PROTO_HEADERS}
${CAFFE_PROTO_SRCS} ${CAFFE2_PROTO_SRCS} ${CAFFE2_PROTO_HEADERS} ${ROCDECODE_SRCS})

if("${BACKEND}" STREQUAL "HIP" AND HIP_FOUND)
add_dependencies(${PROJECT_NAME} rocAL_hip)
set(LINK_LIBRARY_LIST ${LINK_LIBRARY_LIST} $<TARGET_OBJECTS:rocAL_hip>)
target_compile_definitions(${PROJECT_NAME} PRIVATE __HIP_PLATFORM_AMD__)
target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_HIP=1)
target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_OPENCL=0)
if(ROCDECODE_FOUND)
include_directories(${ROCM_PATH}/share/rocdecode/utils)
target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_ROCDECODE=1)
else()
target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_ROCDECODE=0)
endif()
message("-- ${White}rocAL built with HIP Backend${ColourReset}")
elseif("${BACKEND}" STREQUAL "OPENCL" AND OPENCL_FOUND)
include_directories(${OpenCL_INCLUDE_DIRS} ${OpenCL_INCLUDE_DIRS}/Headers)
Expand Down Expand Up @@ -321,6 +334,7 @@ if(${BUILD_ROCAL})
target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_OPENCV=0)
message("-- ${Yellow}NOTE: rocAL built without OpenCV extension functionality${ColourReset}")
endif()

# FFMPEG
if(NOT FFMPEG_FOUND)
message("-- ${Yellow}NOTE: rocAL built without FFmpeg video decode functionality${ColourReset}")
Expand Down
16 changes: 12 additions & 4 deletions rocAL/include/api/rocal_api_data_loaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -623,12 +623,13 @@ extern "C" RocalTensor ROCAL_API_CALL rocalRawTFRecordSourceSingleShard(RocalCon
* \param [in] context Rocal context
* \param [in] source_path A NULL terminated char string pointing to the location on the disk. source_path can be a video file, folder containing videos or a text file
* \param [in] color_format The color format the frames will be decoded to.
* \param [in] rocal_decode_device Enables software or hardware decoding. Currently only software decoding is supported.
* \param [in] rocal_decode_device Enables software decoding(using FFmpeg) or hardware decoding(using FFmepg/rocDecode hardware decoder).
* \param [in] internal_shard_count Defines the parallelism level by internally sharding the input dataset and load/decode using multiple decoder/loader instances.
* \param [in] sequence_length: The number of frames in a sequence.
* \param [in] shuffle: to shuffle sequences.
* \param [in] is_output Determines if the user wants the loaded sequence of frames to be part of the output or not.
* \param [in] loop: repeat data loading.
* \param [in] rocal_decoder_type Determines the decoder_type, FFmepg or rocDecode
* \param [in] step: Frame interval between each sequence.
* \param [in] stride: Frame interval between frames in a sequence.
* \param [in] file_list_frame_num: Determines if the user wants to read frame number or timestamps if a text file is passed in the source_path.
Expand All @@ -644,6 +645,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSource(RocalContext context,
bool is_output = false,
bool shuffle = false,
bool loop = false,
RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW,
unsigned step = 0,
unsigned stride = 0,
bool file_list_frame_num = true,
Expand All @@ -654,13 +656,14 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSource(RocalContext context,
* \param [in] context Rocal context
* \param [in] source_path A NULL terminated char string pointing to the location on the disk. source_path can be a video file, folder containing videos or a text file
* \param [in] color_format The color format the frames will be decoded to.
* \param [in] rocal_decode_device Enables software or hardware decoding. Currently only software decoding is supported.
* \param [in] rocal_decode_device Enables software decoding(using FFmpeg) or hardware decoding(using FFmepg/rocDecode hardware decoder).
* \param [in] shard_id Shard id for this loader.
* \param [in] shard_count Total shard count.
* \param [in] sequence_length: The number of frames in a sequence.
* \param [in] shuffle: to shuffle sequences.
* \param [in] is_output Determines if the user wants the loaded sequence of frames to be part of the output or not.
* \param [in] loop: repeat data loading.
* \param [in] rocal_decoder_type Determines the decoder_type, FFmepg or rocDecode
* \param [in] step: Frame interval between each sequence.
* \param [in] stride: Frame interval between frames in a sequence.
* \param [in] file_list_frame_num: Determines if the user wants to read frame number or timestamps if a text file is passed in the source_path.
Expand All @@ -677,6 +680,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSourceSingleShard(RocalConte
bool shuffle = false,
bool is_output = false,
bool loop = false,
RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW,
unsigned step = 0,
unsigned stride = 0,
bool file_list_frame_num = true,
Expand All @@ -687,14 +691,15 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileSourceSingleShard(RocalConte
* \param [in] context Rocal context
* \param [in] source_path A NULL terminated char string pointing to the location on the disk. source_path can be a video file, folder containing videos or a text file
* \param [in] color_format The color format the frames will be decoded to.
* \param [in] rocal_decode_device Enables software or hardware decoding. Currently only software decoding is supported.
* \param [in] rocal_decode_device Enables software decoding(using FFmpeg) or hardware decoding(using FFmepg/rocDecode hardware decoder).
* \param [in] internal_shard_count Defines the parallelism level by internally sharding the input dataset and load/decode using multiple decoder/loader instances.
* \param [in] sequence_length: The number of frames in a sequence.
* \param [in] dest_width The output width of frames.
* \param [in] dest_height The output height of frames.
* \param [in] shuffle: to shuffle sequences.
* \param [in] is_output Determines if the user wants the loaded sequence of frames to be part of the output or not.
* \param [in] loop: repeat data loading.
* \param [in] rocal_decoder_type Determines the decoder_type, FFmepg or rocDecode
* \param [in] step: Frame interval between each sequence.
* \param [in] stride: Frame interval between frames in a sequence.
* \param [in] file_list_frame_num: Determines if the user wants to read frame number or timestamps if a text file is passed in the source_path.
Expand All @@ -712,6 +717,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileResize(RocalContext context,
bool shuffle = false,
bool is_output = false,
bool loop = false,
RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW,
unsigned step = 0,
unsigned stride = 0,
bool file_list_frame_num = true,
Expand All @@ -727,7 +733,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileResize(RocalContext context,
* \param [in] context Rocal context
* \param [in] source_path A NULL terminated char string pointing to the location on the disk. source_path can be a video file, folder containing videos or a text file
* \param [in] color_format The color format the frames will be decoded to.
* \param [in] rocal_decode_device Enables software or hardware decoding. Currently only software decoding is supported.
* \param [in] rocal_decode_device Enables software decoding(using FFmpeg) or hardware decoding(using FFmepg/rocDecode hardware decoder).
* \param [in] shard_id Shard id for this loader.
* \param [in] shard_count Total shard count.
* \param [in] sequence_length: The number of frames in a sequence.
Expand All @@ -736,6 +742,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileResize(RocalContext context,
* \param [in] shuffle: to shuffle sequences.
* \param [in] is_output Determines if the user wants the loaded sequence of frames to be part of the output or not.
* \param [in] loop: repeat data loading.
* \param [in] rocal_decoder_type Determines the decoder_type, FFmepg or rocDecode
* \param [in] step: Frame interval between each sequence.
* \param [in] stride: Frame interval between frames in a sequence.
* \param [in] file_list_frame_num: Determines if the user wants to read frame number or timestamps if a text file is passed in the source_path.
Expand All @@ -754,6 +761,7 @@ extern "C" RocalTensor ROCAL_API_CALL rocalVideoFileResizeSingleShard(RocalConte
bool shuffle = false,
bool is_output = false,
bool loop = false,
RocalDecoderType rocal_decoder_type = RocalDecoderType::ROCAL_DECODER_VIDEO_FFMPEG_SW,
unsigned step = 0,
unsigned stride = 0,
bool file_list_frame_num = true,
Expand Down
6 changes: 5 additions & 1 deletion rocAL/include/api/rocal_api_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,11 @@ enum RocalDecoderType {
/*! \brief AMD ROCAL_DECODER_AUDIO_GENERIC
* Uses SndFile library to read audio files
*/
ROCAL_DECODER_AUDIO_GENERIC = 5
ROCAL_DECODER_AUDIO_GENERIC = 5,
/*! \brief AMD ROCAL_DECODER_VIDEO_ROCDECODE
* Uses rocDecode library to decode videos on hardware
*/
ROCAL_DECODER_VIDEO_ROCDECODE = 6
};

enum RocalOutputMemType {
Expand Down
8 changes: 4 additions & 4 deletions rocAL/include/decoders/image/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ enum class DecoderType {
TURBO_JPEG = 0, //!< Can only decode
FUSED_TURBO_JPEG = 1, //!< FOR PARTIAL DECODING
OPENCV_DEC = 2, //!< for back_up decoding
HW_JPEG_DEC = 3,
HW_JPEG_DEC = 3, //!< for JPEG decoding using HW via FFMPEG
SKIP_DECODE = 4, //!< For skipping decoding in case of uncompressed data from reader
OVX_FFMPEG = 5, //!< Uses FFMPEG to decode video streams, can decode up to 4 video streams simultaneously
FFMPEG_SOFTWARE_DECODE = 6,
FFMPEG_HARDWARE_DECODE = 7,
FFMPEG_SW_DECODE = 5, //!< for video decoding using CPU and FFMPEG
FFMPEG_HW_DECODE = 6, //!< for video decoding using HW via FFMPEG
ROCDEC_VIDEO_DECODE = 7, //!< for video decoding using HW via rocDecode
AUDIO_SOFTWARE_DECODE = 8 //!< Uses sndfile to decode audio files
};

Expand Down
6 changes: 3 additions & 3 deletions rocAL/include/decoders/video/ffmpeg_video_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class FFmpegVideoDecoder : public VideoDecoder {
public:
//! Default constructor
FFmpegVideoDecoder();
VideoDecoder::Status Initialize(const char *src_filename) override;
VideoDecoder::Status Initialize(const char *src_filename, int device_id = 0) override;
VideoDecoder::Status Decode(unsigned char *output_buffer, unsigned seek_frame_number, size_t sequence_length, size_t stride, int out_width, int out_height, int out_stride, AVPixelFormat out_format) override;
int seek_frame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override;
void release() override;
int SeekFrame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override;
void Release() override;
~FFmpegVideoDecoder() override;

private:
Expand Down
6 changes: 3 additions & 3 deletions rocAL/include/decoders/video/hardware_video_decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class HardWareVideoDecoder : public VideoDecoder {
public:
//! Default constructor
HardWareVideoDecoder();
VideoDecoder::Status Initialize(const char *src_filename) override;
VideoDecoder::Status Initialize(const char *src_filename, int device_id = 0) override;
VideoDecoder::Status Decode(unsigned char *output_buffer, unsigned seek_frame_number, size_t sequence_length, size_t stride, int out_width, int out_height, int out_stride, AVPixelFormat out_format) override;
int seek_frame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override;
void release() override;
int SeekFrame(AVRational avg_frame_rate, AVRational time_base, unsigned frame_number) override;
void Release() override;
~HardWareVideoDecoder() override;

private:
Expand Down
Loading

0 comments on commit 7ac767e

Please sign in to comment.