From 73c0b10f6ac84d495ffb0451a9ef0d4790b76bb2 Mon Sep 17 00:00:00 2001 From: Aryan Salmanpour Date: Wed, 15 May 2024 13:44:51 -0400 Subject: [PATCH] Add/update comments to the code (#25) * Add/update comments to the code * update comments * Update comments --- api/rocjpeg.h | 435 ++++++++-------- samples/rocjpeg_samples_utils.h | 839 +++++++++++++++++-------------- src/rocjpeg_api.cpp | 167 +++--- src/rocjpeg_api_decoder_handle.h | 65 ++- src/rocjpeg_api_stream_handle.h | 43 +- src/rocjpeg_commons.h | 21 + src/rocjpeg_decoder.cpp | 133 ++++- src/rocjpeg_decoder.h | 145 +++++- src/rocjpeg_hip_kernels.cpp | 186 +++++++ src/rocjpeg_hip_kernels.h | 182 +++++++ src/rocjpeg_parser.cpp | 82 +++ src/rocjpeg_parser.h | 261 ++++++---- src/rocjpeg_vaapi_decoder.cpp | 188 ++++++- src/rocjpeg_vaapi_decoder.h | 239 +++++++-- 14 files changed, 2181 insertions(+), 805 deletions(-) diff --git a/api/rocjpeg.h b/api/rocjpeg.h index ab5f1e0e0c..6217cd56f4 100644 --- a/api/rocjpeg.h +++ b/api/rocjpeg.h @@ -27,49 +27,61 @@ THE SOFTWARE. #pragma once #include "hip/hip_runtime.h" -/*****************************************************************************************************************/ -//! \file rocjpeg.h -//! \brief The AMD rocJPEG Library. -//! \defgroup group_amd_rocjepg rocJPEG: AMD ROCm JPEG Decode API -//! \brief rocJPEG API is a toolkit to decode JPEG images using a hardware-accelerated JPEG decoder on AMD’s GPUs. -/******************************************************************************************************************/ +/** + * @file rocjpeg.h + * @brief The AMD rocJPEG Library. + * @defgroup group_amd_rocjepg rocJPEG: AMD ROCm JPEG Decode API + * @brief rocJPEG API is a toolkit to decode JPEG images using a hardware-accelerated JPEG decoder on AMD’s GPUs. +*/ #if defined(__cplusplus) extern "C" { #endif // __cplusplus - -//! \def -//! \ingroup group_amd_rocjpeg -//! Maximum number of channels rocJPEG supports +/** + * @def + * @ingroup group_amd_rocjpeg + * Maximum number of channels rocJPEG supports +*/ #define ROCJPEG_MAX_COMPONENT 4 -/*****************************************************/ -//! \enum RocJpegStatus -//! \ingroup group_amd_rocjpeg -//! rocJPEG return status enums -//! These enums are used in all API calls to rocJPEG -/*****************************************************/ +/** + * @enum RocJpegStatus + * @ingroup group_amd_rocjpeg + * @brief Enumeration representing the status codes for the rocJPEG library. + */ typedef enum { - ROCJPEG_STATUS_SUCCESS = 0, - ROCJPEG_STATUS_NOT_INITIALIZED = -1, - ROCJPEG_STATUS_INVALID_PARAMETER = -2, - ROCJPEG_STATUS_BAD_JPEG = -3, - ROCJPEG_STATUS_JPEG_NOT_SUPPORTED = -4, - ROCJPEG_STATUS_OUTOF_MEMORY = -5, - ROCJPEG_STATUS_EXECUTION_FAILED = -6, - ROCJPEG_STATUS_ARCH_MISMATCH = -7, - ROCJPEG_STATUS_INTERNAL_ERROR = -8, - ROCJPEG_STATUS_IMPLEMENTATION_NOT_SUPPORTED = -9, - ROCJPEG_STATUS_HW_JPEG_DECODER_NOT_SUPPORTED = -10, - ROCJPEG_STATUS_RUNTIME_ERROR = -11, - ROCJPEG_STATUS_NOT_IMPLEMENTED = -12, + ROCJPEG_STATUS_SUCCESS = 0, /**< The operation completed successfully. */ + ROCJPEG_STATUS_NOT_INITIALIZED = -1, /**< The rocJPEG library is not initialized. */ + ROCJPEG_STATUS_INVALID_PARAMETER = -2, /**< An invalid parameter was passed to a function. */ + ROCJPEG_STATUS_BAD_JPEG = -3, /**< The input JPEG data is corrupted or invalid. */ + ROCJPEG_STATUS_JPEG_NOT_SUPPORTED = -4, /**< The JPEG format is not supported. */ + ROCJPEG_STATUS_OUTOF_MEMORY = -5, /**< Out of memory error. */ + ROCJPEG_STATUS_EXECUTION_FAILED = -6, /**< The execution of a function failed. */ + ROCJPEG_STATUS_ARCH_MISMATCH = -7, /**< The architecture is not supported. */ + ROCJPEG_STATUS_INTERNAL_ERROR = -8, /**< Internal error occurred. */ + ROCJPEG_STATUS_IMPLEMENTATION_NOT_SUPPORTED = -9, /**< The requested implementation is not supported. */ + ROCJPEG_STATUS_HW_JPEG_DECODER_NOT_SUPPORTED = -10, /**< Hardware JPEG decoder is not supported. */ + ROCJPEG_STATUS_RUNTIME_ERROR = -11, /**< Runtime error occurred. */ + ROCJPEG_STATUS_NOT_IMPLEMENTED = -12, /**< The requested feature is not implemented. */ } RocJpegStatus; -/*****************************************************/ -//! \enum RocJpegChromaSubsampling -//! \ingroup group_amd_rocjpeg -//! RocJpegChromaSubsampling enum identifies image chroma subsampling values stored inside JPEG input stream -/*****************************************************/ +/** + * @enum RocJpegChromaSubsampling + * @ingroup group_amd_rocjpeg + * @brief Enum representing the chroma subsampling options for JPEG encoding/decoding. + * + * The `RocJpegChromaSubsampling` enum defines the available chroma subsampling options for JPEG encoding/decoding. + * Chroma subsampling refers to the reduction of color information in an image to reduce file size. + * + * The possible values are: + * - `ROCJPEG_CSS_444`: Full chroma resolution (4:4:4). + * - `ROCJPEG_CSS_440`: Chroma resolution reduced by half vertically (4:4:0). + * - `ROCJPEG_CSS_422`: Chroma resolution reduced by half horizontally (4:2:2). + * - `ROCJPEG_CSS_420`: Chroma resolution reduced by half both horizontally and vertically (4:2:0). + * - `ROCJPEG_CSS_411`: Chroma resolution reduced by a quarter horizontally (4:1:1). + * - `ROCJPEG_CSS_400`: No chroma information (4:0:0). + * - `ROCJPEG_CSS_UNKNOWN`: Unknown chroma subsampling. + */ typedef enum { ROCJPEG_CSS_444 = 0, ROCJPEG_CSS_440 = 1, @@ -80,205 +92,236 @@ typedef enum { ROCJPEG_CSS_UNKNOWN = -1 } RocJpegChromaSubsampling; -/*****************************************************/ -//! \struct RocJpegImage -//! \ingroup group_amd_rocjpeg -//! this structure is jpeg image descriptor used to return the decoded output image. User must allocate device -//! memories for each channel for this structure and pass it to the decoder API. -//! the decoder APIs then copies the decode image to this struct based on the requested output format (see RocJpegOutputFormat). -/*****************************************************/ +/** + * @struct RocJpegImage + * @ingroup group_amd_rocjpeg + * @brief Structure representing a JPEG image. + * + * This structure holds the information about a JPEG image, including the pointers to the image channels + * and the pitch (stride) of each channel. + */ typedef struct { - uint8_t* channel[ROCJPEG_MAX_COMPONENT]; - uint32_t pitch[ROCJPEG_MAX_COMPONENT]; // pitch of each channel + uint8_t* channel[ROCJPEG_MAX_COMPONENT]; /**< Pointers to the image channels. */ + uint32_t pitch[ROCJPEG_MAX_COMPONENT]; /**< Pitch (stride) of each channel. */ } RocJpegImage; -/*****************************************************/ -//! \enum RocJpegOutputFormat -//! \ingroup group_amd_rocjpeg -//! RocJpegOutputFormat enum specifies what type of output user wants for image decoding -/*****************************************************/ +/** + * @enum RocJpegOutputFormat + * @ingroup group_amd_rocjpeg + * @brief Enum representing the output format options for the RocJpegImage. + * + * The `RocJpegOutputFormat` enum specifies the different output formats that can be used when decoding a JPEG image using the VCN JPEG decoder. + * + * The available output formats are: + * - `ROCJPEG_OUTPUT_NATIVE`: Returns the native unchanged decoded YUV image from the VCN JPEG decoder. The channel arrangement depends on the chroma subsampling format. + * - `ROCJPEG_OUTPUT_YUV_PLANAR`: Extracts the Y, U, and V channels from the decoded YUV image and writes them into separate channels of the RocJpegImage. + * - `ROCJPEG_OUTPUT_Y`: Returns only the luma component (Y) and writes it to the first channel of the RocJpegImage. + * - `ROCJPEG_OUTPUT_RGB`: Converts the decoded image to interleaved RGB format using the VCN JPEG decoder or HIP kernels and writes it to the first channel of the RocJpegImage. + * - `ROCJPEG_OUTPUT_RGB_PLANAR`: Converts the decoded image to RGB PLANAR format using the VCN JPEG decoder or HIP kernels and writes the RGB channels to separate channels of the RocJpegImage. + * - `ROCJPEG_OUTPUT_FORMAT_MAX`: Maximum allowed value for the output format. + */ typedef enum { - // return native unchanged decoded YUV image from the VCN JPEG deocder. - // For ROCJPEG_CSS_444 write Y, U, and V to first, second, and third channels of RocJpegImage - // For ROCJPEG_CSS_422 write YUYV (packed) to first channel of RocJpegImage - // For ROCJPEG_CSS_420 write Y to first channel and UV (interleaved) to second channel of RocJpegImage - // For ROCJPEG_CSS_400 write Y to first channel of RocJpegImage + /**< return native unchanged decoded YUV image from the VCN JPEG deocder. + For ROCJPEG_CSS_444 write Y, U, and V to first, second, and third channels of RocJpegImage + For ROCJPEG_CSS_422 write YUYV (packed) to first channel of RocJpegImage + For ROCJPEG_CSS_420 write Y to first channel and UV (interleaved) to second channel of RocJpegImage + For ROCJPEG_CSS_400 write Y to first channel of RocJpegImage */ ROCJPEG_OUTPUT_NATIVE = 0, - // extract Y, U, and V channels from the decoded YUV image from the VCN JPEG deocder and write into first, second, and thrid channel of RocJpegImage. - // For ROCJPEG_CSS_400 write Y to first channel of RocJpegImage + /**< extract Y, U, and V channels from the decoded YUV image from the VCN JPEG deocder and write into first, second, and thrid channel of RocJpegImage. + For ROCJPEG_CSS_400 write Y to first channel of RocJpegImage */ ROCJPEG_OUTPUT_YUV_PLANAR = 1, - // return luma component (Y) and write to first channel of RocJpegImage + /**< return luma component (Y) and write to first channel of RocJpegImage */ ROCJPEG_OUTPUT_Y = 2, - // convert to interleaved RGB using VCN JPEG decoder (on MI300+) or using HIP kernels and write to first channel of RocJpegImage + /**< convert to interleaved RGB using VCN JPEG decoder (on MI300+) or using HIP kernels and write to first channel of RocJpegImage */ ROCJPEG_OUTPUT_RGB = 3, - // convert to RGB PLANAR using VCN JPEG decoder (on MI300+) or HIP kernels and write to first, second, and thrid channel of RocJpegImage. + /**< convert to RGB PLANAR using VCN JPEG decoder (on MI300+) or HIP kernels and write to first, second, and thrid channel of RocJpegImage. */ ROCJPEG_OUTPUT_RGB_PLANAR = 4, - // maximum allowed value - ROCJPEG_OUTPUT_FORMAT_MAX = 5 + ROCJPEG_OUTPUT_FORMAT_MAX = 5 /**< maximum allowed value */ } RocJpegOutputFormat; -/*****************************************************/ -//! \struct RocJpegDecodeParams -//! The RocJpegDecodeParams structure contains the decoding parameters that specify the RocJpegOutputFormat. -//! It also defines the crop rectangle for the region of interest (ROI) and the target width and height for the decoded picture to be resized. -//! Note that if both the crop rectangle and target dimensions are defined, cropping is done first, followed by resizing the resulting ROI to -//! the target dimension. -//! \ingroup group_amd_rocjpeg -/*****************************************************/ +/** + * @struct RocJpegDecodeParams + * @ingroup group_amd_rocjpeg + * @brief Structure containing parameters for JPEG decoding. + * + * This structure defines the parameters for decoding a JPEG image using the RocJpeg library. + * It specifies the output format, crop rectangle, and target dimensions for the decoded image. + * Note that if both the crop rectangle and target dimensions are defined, cropping is done first, + * followed by resizing the resulting ROI to the target dimension. + */ typedef struct { - RocJpegOutputFormat output_format; // Output data format. See RocJpegOutputFormat for description + RocJpegOutputFormat output_format; /**< Output data format. See RocJpegOutputFormat for description. */ struct { - int16_t left; - int16_t top; - int16_t right; - int16_t bottom; - } crop_rectangle; // (future use) Defines the region of interest (ROI) to be copied into the RocJpegImage output buffers. + int16_t left; /**< Left coordinate of the crop rectangle. */ + int16_t top; /**< Top coordinate of the crop rectangle. */ + int16_t right; /**< Right coordinate of the crop rectangle. */ + int16_t bottom; /**< Bottom coordinate of the crop rectangle. */ + } crop_rectangle; /**< (future use) Defines the region of interest (ROI) to be copied into the RocJpegImage output buffers. */ struct { - uint32_t width; - uint32_t height; - } target_dimension; // (future use) Defines the target width and height of the picture to be resized. Both should be even. - // if specified, allocate the RocJpegImage buffers based on these dimensions. + uint32_t width; /**< Target width of the picture to be resized. */ + uint32_t height; /**< Target height of the picture to be resized. */ + } target_dimension; /**< (future use) Defines the target width and height of the picture to be resized. Both should be even. + If specified, allocate the RocJpegImage buffers based on these dimensions. */ } RocJpegDecodeParams; -/*****************************************************/ -//! \enum RocJpegBackend -//! \ingroup group_amd_rocjpeg -//! RocJpegBackend enum specifies what type of backend to use for JPEG decoding -//! ROCJPEG_BACKEND_HARDWARE : supports baseline JPEG bitstream using VCN hardware-accelarted JPEG decoder -//! ROCJPEG_BACKEND_HYBRID : uses CPU for Huffman decode and GPU for IDCT using HIP kernesl. This mode doesn't use VCN JPEG hardware decoder -/*****************************************************/ +/** + * @enum RocJpegBackend + * @ingroup group_amd_rocjpeg + * @brief The backend options for the RocJpeg library. + * + * This enum defines the available backend options for the RocJpeg library. + * The backend can be either hardware or hybrid. + */ typedef enum { - ROCJPEG_BACKEND_HARDWARE = 0, - ROCJPEG_BACKEND_HYBRID = 1 + ROCJPEG_BACKEND_HARDWARE = 0, /**< Hardware backend option. */ + ROCJPEG_BACKEND_HYBRID = 1 /**< Hybrid backend option. */ } RocJpegBackend; - -/*****************************************************/ -//! The "opaque JPEG stream identifier" is a handle that is used to parse and store a JPEG stream. -//! This handle is created by calling "rocjpegStreamCreate". By using this handle, we only need to parse a JPEG stream -//! once by calling "rocJpegStreamParse" and can retrieve the stream's information in subsequent API calls such as "rocJpegGetImageInfo" and "rocJpegDecode" (see below). -/*****************************************************/ +/** + * @brief A handle representing a RocJpeg stream. + * + * The `RocJpegStreamHandle` is a pointer type used to represent a RocJpegStream instance. + * It is used as a handle to parse and store various parameters from a JPEG stream. + */ typedef void* RocJpegStreamHandle; -/*****************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegStreamCreate(RocJpegStreamHandle *jpeg_stream_handle); -//! \ingroup group_amd_rocjpeg -//! Create the rocJPEG stream parser handle. This handle is used to parse and retrieve the information from the JPEG stream. -//! IN/OUT jpeg_stream_handle: the rocjpeg stream handle. -/*****************************************************/ +/** + * @fn RocJpegStatus ROCJPEGAPI rocJpegStreamCreate(RocJpegStreamHandle *jpeg_stream_handle); + * @ingroup group_amd_rocjpeg + * @brief Creates a RocJpegStreamHandle for JPEG stream processing. + * + * This function creates a RocJpegStreamHandle, which is used for processing JPEG streams. + * The created handle is stored in the `jpeg_stream_handle` parameter. + * + * @param jpeg_stream_handle Pointer to a RocJpegStreamHandle variable that will hold the created handle. + * @return RocJpegStatus Returns the status of the operation. Possible values are: + * - ROCJPEG_STATUS_SUCCESS: The operation was successful. + * - ROCJPEG_STATUS_INVALID_ARGUMENT: The `jpeg_stream_handle` parameter is NULL. + * - ROCJPEG_STATUS_OUT_OF_MEMORY: Failed to allocate memory for the handle. + * - ROCJPEG_STATUS_UNKNOWN_ERROR: An unknown error occurred. + */ RocJpegStatus ROCJPEGAPI rocJpegStreamCreate(RocJpegStreamHandle *jpeg_stream_handle); -/*****************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegStreamParse(const unsigned char *data, size_t length, RocJpegStreamHandle jpeg_stream_handle); -//! \ingroup group_amd_rocjpeg -//! Parses a jpeg stream and stores the information from the stream to be used in subsequent API calls for retrieving the image information and decoding it. -//! IN data: Pointer to the buffer containing the jpeg stream data to be parsed. -//! IN length: Length of the jpeg image buffer. -//! IN/OUT jpeg_stream_handle: The jpeg stream parser handle that is used to parse and store the information from the input data buffer. -/*****************************************************/ +/** + * @fn RocJpegStatus ROCJPEGAPI rocJpegStreamParse(const unsigned char *data, size_t length, RocJpegStreamHandle jpeg_stream_handle); + * @ingroup group_amd_rocjpeg + * @brief Parses a JPEG stream. + * + * This function parses a JPEG stream represented by the `data` parameter of length `length`. + * The parsed stream is associated with the `jpeg_stream_handle` provided. + * + * @param data The pointer to the JPEG stream data. + * @param length The length of the JPEG stream data. + * @param jpeg_stream_handle The handle to the JPEG stream. + * @return The status of the JPEG stream parsing operation. + */ RocJpegStatus ROCJPEGAPI rocJpegStreamParse(const unsigned char *data, size_t length, RocJpegStreamHandle jpeg_stream_handle); -/*****************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegStreamDestroy(RocJpegStreamHandle jpeg_stream_handle); -//! \ingroup group_amd_rocjpeg -//! Release the stream parser object and resources. -//! IN/OUT jpeg_stream_handle: instance handle to release -/*****************************************************/ +/** + * @fn RocJpegStatus ROCJPEGAPI rocJpegStreamDestroy(RocJpegStreamHandle jpeg_stream_handle); + * @ingroup group_amd_rocjpeg + * @brief Destroys a RocJpegStreamHandle object and releases associated resources. + * + * This function destroys the RocJpegStreamHandle object specified by `jpeg_stream_handle` and releases any resources + * associated with it. After calling this function, the `jpeg_stream_handle` becomes invalid and should not be used + * anymore. + * + * @param jpeg_stream_handle The handle to the RocJpegStreamHandle object to be destroyed. + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if the operation is successful, or an error code + * if an error occurs. + */ RocJpegStatus ROCJPEGAPI rocJpegStreamDestroy(RocJpegStreamHandle jpeg_stream_handle); -/*****************************************************/ -// Opaque library handle identifier. -//! Used in subsequent API calls after rocJpegCreate -/*****************************************************/ +/** + * @brief A handle representing a RocJpeg instance. + * + * The `RocJpegHandle` is a pointer type used to represent a RocJpeg instance. + * It is used as a handle to perform various operations on the RocJpeg library. + */ typedef void *RocJpegHandle; -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegCreate(RocJpegBackend backend, int device_id, RocJpegHandle *handle); -//! \ingroup group_amd_rocjpeg -//! Create the decoder object based on backend and device_id. A handle to the created decoder is returned -//! Initalization of rocjpeg handle. This handle is used for all consecutive calls -//! IN backend : Backend to use. -//! IN device_id : the GPU device id for which a decoder should be created. For example, use 0 for the first GPU device, -//! and 1 for the second GPU device on the system, etc. -//! IN/OUT handle : rocjpeg handle, jpeg decoder instance to use for. -/*****************************************************************************************************/ +/** + * @fn RocJpegStatus ROCJPEGAPI rocJpegCreate(RocJpegBackend backend, int device_id, RocJpegHandle *handle); + * @ingroup group_amd_rocjpeg + * @brief Creates a RocJpegHandle for JPEG decoding. + * + * This function creates a RocJpegHandle for JPEG decoding using the specified backend and device ID. + * + * @param backend The backend to be used for JPEG decoding. + * @param device_id The ID of the device to be used for JPEG decoding. + * @param handle Pointer to a RocJpegHandle variable to store the created handle. + * @return The status of the operation. Returns ROCJPEG_STATUS_INVALID_PARAMETER if handle is nullptr, + * ROCJPEG_STATUS_NOT_INITIALIZED if the rocJPEG handle initialization fails, or the status + * returned by the InitializeDecoder function of the rocjpeg_decoder. + */ RocJpegStatus ROCJPEGAPI rocJpegCreate(RocJpegBackend backend, int device_id, RocJpegHandle *handle); -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegDestroy(RocJpegHandle handle); -//! \ingroup group_amd_rocjpeg -//! Release the decoder object and resources. -//! IN/OUT handle: instance handle to release -/*****************************************************************************************************/ +/** + * @fn RocJpegStatus ROCJPEGAPI rocJpegDestroy(RocJpegHandle handle); + * @ingroup group_amd_rocjpeg + * @brief Destroys a RocJpegHandle object. + * + * This function destroys the RocJpegHandle object pointed to by the given handle. + * It releases any resources associated with the handle and frees the memory. + * + * @param handle The handle to the RocJpegHandle object to be destroyed. + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if the handle was successfully destroyed, + * or ROCJPEG_STATUS_INVALID_PARAMETER if the handle is nullptr. + */ + RocJpegStatus ROCJPEGAPI rocJpegDestroy(RocJpegHandle handle); -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegGetImageInfo(RocJpegHandle handle, const uint8_t *data, size_t length, uint8_t *num_components, RocJpegChromaSubsampling *subsampling, uint32_t *widths, uint32_t *heights); -//! \ingroup group_amd_rocjpeg -//! Retrieve the image info, including channel, width and height of each component, and chroma subsampling. -//! If less than ROCJPEG_MAX_COMPONENT channels are encoded, then zeros would be set to absent channels information -//! If the image is 3-channel, all three groups are valid. -//! IN handle : rocJpeg handle -//! IN jpeg_stream_handle: The handle for the jpeg stream parser to retrieve information from a previously parsed jpeg stream. -//! OUT num_component : Number of channels in the decoded output image -//! OUT subsampling : Chroma subsampling used in this JPEG, see RocJpegChromaSubsampling. -//! OUT widths : pointer to ROCJPEG_MAX_COMPONENT of uint32_t, returns width of each channel. -//! OUT heights : pointer to ROCJPEG_MAX_COMPONENT of uint32_t, returns height of each channel. -//! \return ROCJPEG_STATUS_SUCCESS if successful -/*****************************************************************************************************/ +/** + * @fn RocJpegStatus ROCJPEGAPI rocJpegGetImageInfo(RocJpegHandle handle, RocJpegStreamHandle jpeg_stream_handle, uint8_t *num_components, RocJpegChromaSubsampling *subsampling, uint32_t *widths, uint32_t *heights); + * @ingroup group_amd_rocjpeg + * @brief Retrieves information about the JPEG image. + * + * This function retrieves the number of components, chroma subsampling, and dimensions (width and height) of the JPEG image + * specified by the `jpeg_stream_handle`. The information is stored in the provided output parameters `num_components`, + * `subsampling`, `widths`, and `heights`. + * + * @param handle The handle to the RocJpegDecoder instance. + * @param jpeg_stream_handle The handle to the RocJpegStream instance representing the JPEG image. + * @param num_components A pointer to an unsigned 8-bit integer that will store the number of components in the JPEG image. + * @param subsampling A pointer to a RocJpegChromaSubsampling enum that will store the chroma subsampling information. + * @param widths A pointer to an unsigned 32-bit integer array that will store the width of each component in the JPEG image. + * @param heights A pointer to an unsigned 32-bit integer array that will store the height of each component in the JPEG image. + * + * @return The RocJpegStatus indicating the success or failure of the operation. + * - ROCJPEG_STATUS_SUCCESS: The operation was successful. + * - ROCJPEG_STATUS_INVALID_PARAMETER: One or more input parameters are invalid. + * - ROCJPEG_STATUS_RUNTIME_ERROR: An exception occurred during the operation. + */ RocJpegStatus ROCJPEGAPI rocJpegGetImageInfo(RocJpegHandle handle, RocJpegStreamHandle jpeg_stream_handle, uint8_t *num_components, RocJpegChromaSubsampling *subsampling, uint32_t *widths, uint32_t *heights); -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegDecode(RocJpegHandle handle, const uint8_t *data, size_t length, RocJpegOutputFormat output_format, RocJpegImage *destination, hipStream_t stream); -//! \ingroup group_amd_rocjpeg -//! Decodes single image based on the backend used to create the rocJpeg handle in rocJpegCreate API. -//! Destination buffers should be large enough to be able to store output of specified format. These buffers should be pre-allocted by the user in the device memories. -//! For each color plane (channel) sizes could be retrieved for image using rocJpegGetImageInfo API -//! and minimum required memory buffer for each plane is plane_height * plane_pitch where plane_pitch >= plane_width for -//! planar output formats and plane_pitch >= plane_width * num_components for interleaved output format. -//! IN handle : rocJpeg handle -//! IN jpeg_stream_handle: The handle for the jpeg stream parser to retrieve information from a previously parsed jpeg stream and decode it. -//! IN decode_params : Decode parameters. See RocJpegDecodeParams for description -//! IN/OUT destination : Pointer to structure with information about output buffers. See RocJpegImage description. -//! \return ROCJPEG_STATUS_SUCCESS if successful -/*****************************************************************************************************/ +/** + * @fn RocJpegStatus ROCJPEGAPI rocJpegDecode(RocJpegHandle handle, RocJpegStreamHandle jpeg_stream_handle, const RocJpegDecodeParams *decode_params, RocJpegImage *destination); + * @ingroup group_amd_rocjpeg + * @brief Decodes a JPEG image using the rocJPEG library. + * + * This function decodes a JPEG image using the rocJPEG library. It takes a rocJpegHandle, a rocJpegStreamHandle, + * a pointer to RocJpegDecodeParams, and a pointer to RocJpegImage as input parameters. The function returns a + * RocJpegStatus indicating the success or failure of the decoding operation. + * + * @param handle The rocJpegHandle representing the rocJPEG decoder instance. + * @param jpeg_stream_handle The rocJpegStreamHandle representing the input JPEG stream. + * @param decode_params A pointer to RocJpegDecodeParams containing the decoding parameters. + * @param destination A pointer to RocJpegImage where the decoded image will be stored. + * @return A RocJpegStatus indicating the success or failure of the decoding operation. + */ + RocJpegStatus ROCJPEGAPI rocJpegDecode(RocJpegHandle handle, RocJpegStreamHandle jpeg_stream_handle, const RocJpegDecodeParams *decode_params, RocJpegImage *destination); -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegDecodeBatchedInitialize(RocJpegHandle handle, int batch_size, int max_cpu_threads, RocJpegOutputFormat output_format); -//! \ingroup group_amd_rocjpeg -//! Resets and initializes batch decoder for working on the batches of specified size -//! Should be called once for decoding batches of this specific size, also use to reset failed batches -//! IN/OUT handle : Library handle -//! IN batch_size : Size of the batch -//! IN max_cpu_threads : Maximum number of CPU threads that will be processing this batch -//! IN output_format : Output data format. Will be the same for every image in batch -//! \return ROCJPEG_STATUS_SUCCESS if successful -/*****************************************************************************************************/ -RocJpegStatus ROCJPEGAPI rocJpegDecodeBatchedInitialize(RocJpegHandle handle, int batch_size, int max_cpu_threads, RocJpegOutputFormat output_format); - -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegDecodeBatched(RocJpegHandle handle, const uint8_t *data, const size_t *lengths, RocJpegImage *destinations, hipStream_t stream); -//! \ingroup group_amd_rocjpeg -//! Decodes batch of images. Output buffers should be large enough to be able to store -//! outputs of specified format, see single image decoding description for details. Call to -//! rocjpegDecodeBatchedInitialize() is required prior to this call, batch size is expected to be the same as -//! parameter to this batch initialization function. -//! -//! IN/OUT handle : Library handle -//! INT/OUT jpeg_handle : Decoded jpeg image state handle -//! IN data : Array of size batch_size of pointers to the input buffers containing the jpeg images to be decoded. -//! IN lengths : Array of size batch_size with lengths of the jpeg images' buffers in the batch. -//! IN/OUT destinations : Array of size batch_size with pointers to structure with information about output buffers, -//! \return ROCJPEG_STATUS_SUCCESS if successful -/*****************************************************************************************************/ -RocJpegStatus ROCJPEGAPI rocJpegDecodeBatched(RocJpegHandle handle, const uint8_t *data, const size_t *lengths, RocJpegImage *destinations); - -/*****************************************************************************************************/ -//! \fn extern const char* ROCDECAPI rocJpegGetErrorName(RocJpegStatus rocjpeg_status); -//! \ingroup group_amd_rocjpeg -//! Return name of the specified error code in text form. -/*****************************************************************************************************/ +/** + * @fn extern const char* ROCDECAPI rocJpegGetErrorName(RocJpegStatus rocjpeg_status); + * @ingroup group_amd_rocjpeg + * @brief Retrieves the name of the error associated with the given RocJpegStatus. + * + * This function returns a string representation of the error associated with the given RocJpegStatus. + * + * @param rocjpeg_status The RocJpegStatus for which to retrieve the error name. + * @return A pointer to a constant character string representing the error name. + */ extern const char* ROCJPEGAPI rocJpegGetErrorName(RocJpegStatus rocjpeg_status); #if defined(__cplusplus) diff --git a/samples/rocjpeg_samples_utils.h b/samples/rocjpeg_samples_utils.h index 302e29ad46..db062d8ae8 100644 --- a/samples/rocjpeg_samples_utils.h +++ b/samples/rocjpeg_samples_utils.h @@ -54,416 +54,501 @@ THE SOFTWARE. } \ } +/** + * @class RocJpegUtils + * @brief Utility class for rocJPEG samples. + * + * This class provides utility functions for rocJPEG samples, such as parsing command line arguments, + * getting file paths, initializing HIP device, getting chroma subsampling string, getting channel pitch and sizes, + * getting output file extension, and saving images. + */ class RocJpegUtils { public: - RocJpegUtils() {}; + /** + * @brief Parses the command line arguments. + * + * This function parses the command line arguments and sets the corresponding variables. + * + * @param input_path The input path. + * @param output_file_path The output file path. + * @param save_images Flag indicating whether to save images. + * @param device_id The device ID. + * @param rocjpeg_backend The rocJPEG backend. + * @param decode_params The rocJPEG decode parameters. + * @param num_threads The number of threads. + * @param argc The number of command line arguments. + * @param argv The command line arguments. + */ static void ParseCommandLine(std::string &input_path, std::string &output_file_path, bool &save_images, int &device_id, - RocJpegBackend &rocjpeg_backend, RocJpegDecodeParams &decode_params, int *num_threads, int argc, char *argv[]); - static bool GetFilePaths(std::string &input_path, std::vector &file_paths, bool &is_dir, bool &is_file); - static bool InitHipDevice(int device_id); - void GetChromaSubsamplingStr(RocJpegChromaSubsampling subsampling, std::string &chroma_sub_sampling); - int GetChannelPitchAndSizes(RocJpegOutputFormat output_format, RocJpegChromaSubsampling subsampling, uint32_t *widths, uint32_t *heights, - uint32_t &num_channels, RocJpegImage &output_image, uint32_t *channel_sizes); - void GetOutputFileExt(RocJpegOutputFormat output_format, std::string &base_file_name, uint32_t image_width, uint32_t image_height, std::string &file_name_for_saving); - void SaveImage(std::string output_file_name, RocJpegImage *output_image, uint32_t img_width, uint32_t img_height, - RocJpegChromaSubsampling subsampling, RocJpegOutputFormat output_format); -private: - static void ShowHelpAndExit(const char *option = nullptr, bool show_threads = false); -}; - -void RocJpegUtils::ShowHelpAndExit(const char *option, bool show_threads) { - std::cout << "Options:\n" - "-i [input path] - input path to a single JPEG image or a directory containing JPEG images - [required]\n" - "-be [backend] - select rocJPEG backend (0 for hardware-accelerated JPEG decoding using VCN,\n" - " 1 for hybrid JPEG decoding using CPU and GPU HIP kernels (currently not supported)) [optional - default: 0]\n" - "-fmt [output format] - select rocJPEG output format for decoding, one of the [native, yuv, y, rgb, rgb_planar] - [optional - default: native]\n" - "-o [output path] - path to an output file or a path to a directory - write decoded images to a file or directory based on selected output format - [optional]\n" - "-d [device id] - specify the GPU device id for the desired device (use 0 for the first device, 1 for the second device, and so on) [optional - default: 0]\n"; - if (show_threads) { - std::cout << "-t [threads] - number of threads for parallel JPEG decoding - [optional - default: 2]\n"; - } - exit(0); -} - -void RocJpegUtils::ParseCommandLine(std::string &input_path, std::string &output_file_path, bool &save_images, int &device_id, - RocJpegBackend &rocjpeg_backend, RocJpegDecodeParams &decode_params, int *num_threads, int argc, char *argv[]) { - if(argc <= 1) { - ShowHelpAndExit("", num_threads != nullptr); - } - for (int i = 1; i < argc; i++) { - if (!strcmp(argv[i], "-h")) { + RocJpegBackend &rocjpeg_backend, RocJpegDecodeParams &decode_params, int *num_threads, int argc, char *argv[]) { + if(argc <= 1) { ShowHelpAndExit("", num_threads != nullptr); } - if (!strcmp(argv[i], "-i")) { - if (++i == argc) { - ShowHelpAndExit("-i", num_threads != nullptr); + for (int i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-h")) { + ShowHelpAndExit("", num_threads != nullptr); } - input_path = argv[i]; - continue; + if (!strcmp(argv[i], "-i")) { + if (++i == argc) { + ShowHelpAndExit("-i", num_threads != nullptr); + } + input_path = argv[i]; + continue; + } + if (!strcmp(argv[i], "-o")) { + if (++i == argc) { + ShowHelpAndExit("-o", num_threads != nullptr); + } + output_file_path = argv[i]; + save_images = true; + continue; + } + if (!strcmp(argv[i], "-d")) { + if (++i == argc) { + ShowHelpAndExit("-d", num_threads != nullptr); + } + device_id = atoi(argv[i]); + continue; + } + if (!strcmp(argv[i], "-be")) { + if (++i == argc) { + ShowHelpAndExit("-be", num_threads != nullptr); + } + rocjpeg_backend = static_cast(atoi(argv[i])); + continue; + } + if (!strcmp(argv[i], "-fmt")) { + if (++i == argc) { + ShowHelpAndExit("-fmt", num_threads != nullptr); + } + std::string selected_output_format = argv[i]; + if (selected_output_format == "native") { + decode_params.output_format = ROCJPEG_OUTPUT_NATIVE; + } else if (selected_output_format == "yuv") { + decode_params.output_format = ROCJPEG_OUTPUT_YUV_PLANAR; + } else if (selected_output_format == "y") { + decode_params.output_format = ROCJPEG_OUTPUT_Y; + } else if (selected_output_format == "rgb") { + decode_params.output_format = ROCJPEG_OUTPUT_RGB; + } else if (selected_output_format == "rgb_planar") { + decode_params.output_format = ROCJPEG_OUTPUT_RGB_PLANAR; + } else { + ShowHelpAndExit(argv[i], num_threads != nullptr); + } + continue; + } + if (!strcmp(argv[i], "-t")) { + if (++i == argc) { + ShowHelpAndExit("-t", num_threads != nullptr); + } + if (num_threads != nullptr) + *num_threads = atoi(argv[i]); + continue; + } + ShowHelpAndExit(argv[i], num_threads != nullptr); } - if (!strcmp(argv[i], "-o")) { - if (++i == argc) { - ShowHelpAndExit("-o", num_threads != nullptr); - } - output_file_path = argv[i]; - save_images = true; - continue; - } - if (!strcmp(argv[i], "-d")) { - if (++i == argc) { - ShowHelpAndExit("-d", num_threads != nullptr); - } - device_id = atoi(argv[i]); - continue; - } - if (!strcmp(argv[i], "-be")) { - if (++i == argc) { - ShowHelpAndExit("-be", num_threads != nullptr); - } - rocjpeg_backend = static_cast(atoi(argv[i])); - continue; - } - if (!strcmp(argv[i], "-fmt")) { - if (++i == argc) { - ShowHelpAndExit("-fmt", num_threads != nullptr); - } - std::string selected_output_format = argv[i]; - if (selected_output_format == "native") { - decode_params.output_format = ROCJPEG_OUTPUT_NATIVE; - } else if (selected_output_format == "yuv") { - decode_params.output_format = ROCJPEG_OUTPUT_YUV_PLANAR; - } else if (selected_output_format == "y") { - decode_params.output_format = ROCJPEG_OUTPUT_Y; - } else if (selected_output_format == "rgb") { - decode_params.output_format = ROCJPEG_OUTPUT_RGB; - } else if (selected_output_format == "rgb_planar") { - decode_params.output_format = ROCJPEG_OUTPUT_RGB_PLANAR; - } else { - ShowHelpAndExit(argv[i], num_threads != nullptr); - } - continue; - } - if (!strcmp(argv[i], "-t")) { - if (++i == argc) { - ShowHelpAndExit("-t", num_threads != nullptr); - } - if (num_threads != nullptr) - *num_threads = atoi(argv[i]); - continue; - } - ShowHelpAndExit(argv[i], num_threads != nullptr); } -} -bool RocJpegUtils::GetFilePaths(std::string &input_path, std::vector &file_paths, bool &is_dir, bool &is_file) { -#if __cplusplus >= 201703L && __has_include() - is_dir = std::filesystem::is_directory(input_path); - is_file = std::filesystem::is_regular_file(input_path); -#else - is_dir = std::experimental::filesystem::is_directory(input_path); - is_file = std::experimental::filesystem::is_regular_file(input_path); -#endif - if (is_dir) { -#if __cplusplus >= 201703L && __has_include() - for (const auto &entry : std::filesystem::directory_iterator(input_path)) -#else - for (const auto &entry : std::experimental::filesystem::directory_iterator(input_path)) -#endif - file_paths.push_back(entry.path()); - } else if (is_file) { - file_paths.push_back(input_path); - } else { - std::cerr << "ERROR: the input path is not valid!" << std::endl; - return false; + /** + * @brief Gets the file paths. + * + * This function gets the file paths based on the input path and sets the corresponding variables. + * + * @param input_path The input path. + * @param file_paths The vector to store the file paths. + * @param is_dir Flag indicating whether the input path is a directory. + * @param is_file Flag indicating whether the input path is a file. + * @return True if successful, false otherwise. + */ + static bool GetFilePaths(std::string &input_path, std::vector &file_paths, bool &is_dir, bool &is_file) { + #if __cplusplus >= 201703L && __has_include() + is_dir = std::filesystem::is_directory(input_path); + is_file = std::filesystem::is_regular_file(input_path); + #else + is_dir = std::experimental::filesystem::is_directory(input_path); + is_file = std::experimental::filesystem::is_regular_file(input_path); + #endif + if (is_dir) { + #if __cplusplus >= 201703L && __has_include() + for (const auto &entry : std::filesystem::directory_iterator(input_path)) + #else + for (const auto &entry : std::experimental::filesystem::directory_iterator(input_path)) + #endif + file_paths.push_back(entry.path()); + } else if (is_file) { + file_paths.push_back(input_path); + } else { + std::cerr << "ERROR: the input path is not valid!" << std::endl; + return false; + } + return true; } - return true; -} -bool RocJpegUtils::InitHipDevice(int device_id) { - int num_devices; - hipDeviceProp_t hip_dev_prop; - CHECK_HIP(hipGetDeviceCount(&num_devices)); - if (num_devices < 1) { - std::cerr << "ERROR: didn't find any GPU!" << std::endl; - return false; + /** + * @brief Initializes the HIP device. + * + * This function initializes the HIP device with the specified device ID. + * + * @param device_id The device ID. + * @return True if successful, false otherwise. + */ + static bool InitHipDevice(int device_id) { + int num_devices; + hipDeviceProp_t hip_dev_prop; + CHECK_HIP(hipGetDeviceCount(&num_devices)); + if (num_devices < 1) { + std::cerr << "ERROR: didn't find any GPU!" << std::endl; + return false; + } + if (device_id >= num_devices) { + std::cerr << "ERROR: the requested device_id is not found!" << std::endl; + return false; + } + CHECK_HIP(hipSetDevice(device_id)); + CHECK_HIP(hipGetDeviceProperties(&hip_dev_prop, device_id)); + + std::cout << "Using GPU device " << device_id << ": " << hip_dev_prop.name << "[" << hip_dev_prop.gcnArchName << "] on PCI bus " << + std::setfill('0') << std::setw(2) << std::right << std::hex << hip_dev_prop.pciBusID << ":" << std::setfill('0') << std::setw(2) << + std::right << std::hex << hip_dev_prop.pciDomainID << "." << hip_dev_prop.pciDeviceID << std::dec << std::endl; + + return true; } - if (device_id >= num_devices) { - std::cerr << "ERROR: the requested device_id is not found!" << std::endl; - return false; + + /** + * @brief Gets the chroma subsampling string. + * + * This function gets the chroma subsampling string based on the specified subsampling value. + * + * @param subsampling The chroma subsampling value. + * @param chroma_sub_sampling The string to store the chroma subsampling. + */ + void GetChromaSubsamplingStr(RocJpegChromaSubsampling subsampling, std::string &chroma_sub_sampling) { + switch (subsampling) { + case ROCJPEG_CSS_444: + chroma_sub_sampling = "YUV 4:4:4"; + break; + case ROCJPEG_CSS_440: + chroma_sub_sampling = "YUV 4:4:0"; + break; + case ROCJPEG_CSS_422: + chroma_sub_sampling = "YUV 4:2:2"; + break; + case ROCJPEG_CSS_420: + chroma_sub_sampling = "YUV 4:2:0"; + break; + case ROCJPEG_CSS_411: + chroma_sub_sampling = "YUV 4:1:1"; + break; + case ROCJPEG_CSS_400: + chroma_sub_sampling = "YUV 4:0:0"; + break; + case ROCJPEG_CSS_UNKNOWN: + chroma_sub_sampling = "UNKNOWN"; + break; + default: + chroma_sub_sampling = ""; + break; + } } - CHECK_HIP(hipSetDevice(device_id)); - CHECK_HIP(hipGetDeviceProperties(&hip_dev_prop, device_id)); - std::cout << "Using GPU device " << device_id << ": " << hip_dev_prop.name << "[" << hip_dev_prop.gcnArchName << "] on PCI bus " << - std::setfill('0') << std::setw(2) << std::right << std::hex << hip_dev_prop.pciBusID << ":" << std::setfill('0') << std::setw(2) << - std::right << std::hex << hip_dev_prop.pciDomainID << "." << hip_dev_prop.pciDeviceID << std::dec << std::endl; - - return true; -} - -void RocJpegUtils::GetChromaSubsamplingStr(RocJpegChromaSubsampling subsampling, std::string &chroma_sub_sampling) { - switch (subsampling) { - case ROCJPEG_CSS_444: - chroma_sub_sampling = "YUV 4:4:4"; - break; - case ROCJPEG_CSS_440: - chroma_sub_sampling = "YUV 4:4:0"; - break; - case ROCJPEG_CSS_422: - chroma_sub_sampling = "YUV 4:2:2"; - break; - case ROCJPEG_CSS_420: - chroma_sub_sampling = "YUV 4:2:0"; - break; - case ROCJPEG_CSS_411: - chroma_sub_sampling = "YUV 4:1:1"; - break; - case ROCJPEG_CSS_400: - chroma_sub_sampling = "YUV 4:0:0"; - break; - case ROCJPEG_CSS_UNKNOWN: - chroma_sub_sampling = "UNKNOWN"; - break; - default: - chroma_sub_sampling = ""; - break; - } -} - -int RocJpegUtils::GetChannelPitchAndSizes(RocJpegOutputFormat output_format, RocJpegChromaSubsampling subsampling, uint32_t *widths, uint32_t *heights, - uint32_t &num_channels, RocJpegImage &output_image, uint32_t *channel_sizes) { - switch (output_format) { - case ROCJPEG_OUTPUT_NATIVE: - switch (subsampling) { - case ROCJPEG_CSS_444: - num_channels = 3; - output_image.pitch[2] = output_image.pitch[1] = output_image.pitch[0] = widths[0]; - channel_sizes[2] = channel_sizes[1] = channel_sizes[0] = output_image.pitch[0] * heights[0]; - break; - case ROCJPEG_CSS_422: - num_channels = 1; - output_image.pitch[0] = widths[0] * 2; - channel_sizes[0] = output_image.pitch[0] * heights[0]; - break; - case ROCJPEG_CSS_420: - num_channels = 2; - output_image.pitch[1] = output_image.pitch[0] = widths[0]; - channel_sizes[0] = output_image.pitch[0] * heights[0]; - channel_sizes[1] = output_image.pitch[1] * (heights[0] >> 1); - break; - case ROCJPEG_CSS_400: + /** + * @brief Gets the channel pitch and sizes. + * + * This function gets the channel pitch and sizes based on the specified output format, chroma subsampling, + * output image, and channel sizes. + * + * @param output_format The output format. + * @param subsampling The chroma subsampling. + * @param widths The array to store the channel widths. + * @param heights The array to store the channel heights. + * @param num_channels The number of channels. + * @param output_image The output image. + * @param channel_sizes The array to store the channel sizes. + * @return The channel pitch. + */ + int GetChannelPitchAndSizes(RocJpegOutputFormat output_format, RocJpegChromaSubsampling subsampling, uint32_t *widths, uint32_t *heights, + uint32_t &num_channels, RocJpegImage &output_image, uint32_t *channel_sizes) { + switch (output_format) { + case ROCJPEG_OUTPUT_NATIVE: + switch (subsampling) { + case ROCJPEG_CSS_444: + num_channels = 3; + output_image.pitch[2] = output_image.pitch[1] = output_image.pitch[0] = widths[0]; + channel_sizes[2] = channel_sizes[1] = channel_sizes[0] = output_image.pitch[0] * heights[0]; + break; + case ROCJPEG_CSS_422: + num_channels = 1; + output_image.pitch[0] = widths[0] * 2; + channel_sizes[0] = output_image.pitch[0] * heights[0]; + break; + case ROCJPEG_CSS_420: + num_channels = 2; + output_image.pitch[1] = output_image.pitch[0] = widths[0]; + channel_sizes[0] = output_image.pitch[0] * heights[0]; + channel_sizes[1] = output_image.pitch[1] * (heights[0] >> 1); + break; + case ROCJPEG_CSS_400: + num_channels = 1; + output_image.pitch[0] = widths[0]; + channel_sizes[0] = output_image.pitch[0] * heights[0]; + break; + default: + std::cout << "Unknown chroma subsampling!" << std::endl; + return EXIT_FAILURE; + } + break; + case ROCJPEG_OUTPUT_YUV_PLANAR: + if (subsampling == ROCJPEG_CSS_400) { num_channels = 1; output_image.pitch[0] = widths[0]; channel_sizes[0] = output_image.pitch[0] * heights[0]; - break; - default: - std::cout << "Unknown chroma subsampling!" << std::endl; - return EXIT_FAILURE; - } - break; - case ROCJPEG_OUTPUT_YUV_PLANAR: - if (subsampling == ROCJPEG_CSS_400) { + } else { + num_channels = 3; + output_image.pitch[0] = widths[0]; + output_image.pitch[1] = widths[1]; + output_image.pitch[2] = widths[2]; + channel_sizes[0] = output_image.pitch[0] * heights[0]; + channel_sizes[1] = output_image.pitch[1] * heights[1]; + channel_sizes[2] = output_image.pitch[2] * heights[2]; + } + break; + case ROCJPEG_OUTPUT_Y: num_channels = 1; output_image.pitch[0] = widths[0]; channel_sizes[0] = output_image.pitch[0] * heights[0]; - } else { - num_channels = 3; - output_image.pitch[0] = widths[0]; - output_image.pitch[1] = widths[1]; - output_image.pitch[2] = widths[2]; + break; + case ROCJPEG_OUTPUT_RGB: + num_channels = 1; + output_image.pitch[0] = widths[0] * 3; channel_sizes[0] = output_image.pitch[0] * heights[0]; - channel_sizes[1] = output_image.pitch[1] * heights[1]; - channel_sizes[2] = output_image.pitch[2] * heights[2]; - } - break; - case ROCJPEG_OUTPUT_Y: - num_channels = 1; - output_image.pitch[0] = widths[0]; - channel_sizes[0] = output_image.pitch[0] * heights[0]; - break; - case ROCJPEG_OUTPUT_RGB: - num_channels = 1; - output_image.pitch[0] = widths[0] * 3; - channel_sizes[0] = output_image.pitch[0] * heights[0]; - break; - case ROCJPEG_OUTPUT_RGB_PLANAR: - num_channels = 3; - output_image.pitch[2] = output_image.pitch[1] = output_image.pitch[0] = widths[0]; - channel_sizes[2] = channel_sizes[1] = channel_sizes[0] = output_image.pitch[0] * heights[0]; - break; - default: - std::cout << "Unknown output format!" << std::endl; - return EXIT_FAILURE; - } - return EXIT_SUCCESS; -} - -void RocJpegUtils::GetOutputFileExt(RocJpegOutputFormat output_format, std::string &base_file_name, uint32_t image_width, uint32_t image_height, std::string &file_name_for_saving) { - std::string file_extension; - std::string::size_type const p(base_file_name.find_last_of('.')); - std::string file_name_no_ext = base_file_name.substr(0, p); - switch (output_format) { - case ROCJPEG_OUTPUT_NATIVE: - file_extension = "native"; - break; - case ROCJPEG_OUTPUT_YUV_PLANAR: - file_extension = "yuv"; - break; - case ROCJPEG_OUTPUT_Y: - file_extension = "y"; - break; - case ROCJPEG_OUTPUT_RGB: - file_extension = "rgb"; - break; - case ROCJPEG_OUTPUT_RGB_PLANAR: - file_extension = "rgb_planar"; - break; - default: - file_extension = ""; - break; - } - file_name_for_saving += "//" + file_name_no_ext + "_" + std::to_string(image_width) + "x" - + std::to_string(image_height) + "." + file_extension; -} - -void RocJpegUtils::SaveImage(std::string output_file_name, RocJpegImage *output_image, uint32_t img_width, uint32_t img_height, - RocJpegChromaSubsampling subsampling, RocJpegOutputFormat output_format) { - uint8_t *hst_ptr = nullptr; - FILE *fp; - hipError_t hip_status = hipSuccess; - - if (output_image == nullptr || output_image->channel[0] == nullptr || output_image->pitch[0] == 0) { - return; + break; + case ROCJPEG_OUTPUT_RGB_PLANAR: + num_channels = 3; + output_image.pitch[2] = output_image.pitch[1] = output_image.pitch[0] = widths[0]; + channel_sizes[2] = channel_sizes[1] = channel_sizes[0] = output_image.pitch[0] * heights[0]; + break; + default: + std::cout << "Unknown output format!" << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; } - uint32_t widths[ROCJPEG_MAX_COMPONENT] = {}; - uint32_t heights[ROCJPEG_MAX_COMPONENT] = {}; + /** + * @brief Gets the output file extension. + * + * This function gets the output file extension based on the specified output format, base file name, + * image width, image height, and file name for saving. + * + * @param output_format The output format. + * @param base_file_name The base file name. + * @param image_width The image width. + * @param image_height The image height. + * @param file_name_for_saving The string to store the file name for saving. + */ + void GetOutputFileExt(RocJpegOutputFormat output_format, std::string &base_file_name, uint32_t image_width, uint32_t image_height, std::string &file_name_for_saving) { + std::string file_extension; + std::string::size_type const p(base_file_name.find_last_of('.')); + std::string file_name_no_ext = base_file_name.substr(0, p); + switch (output_format) { + case ROCJPEG_OUTPUT_NATIVE: + file_extension = "native"; + break; + case ROCJPEG_OUTPUT_YUV_PLANAR: + file_extension = "yuv"; + break; + case ROCJPEG_OUTPUT_Y: + file_extension = "y"; + break; + case ROCJPEG_OUTPUT_RGB: + file_extension = "rgb"; + break; + case ROCJPEG_OUTPUT_RGB_PLANAR: + file_extension = "rgb_planar"; + break; + default: + file_extension = ""; + break; + } + file_name_for_saving += "//" + file_name_no_ext + "_" + std::to_string(image_width) + "x" + + std::to_string(image_height) + "." + file_extension; + } - switch (output_format) { - case ROCJPEG_OUTPUT_NATIVE: - switch (subsampling) { - case ROCJPEG_CSS_444: - widths[2] = widths[1] = widths[0] = img_width; - heights[2] = heights[1] = heights[0] = img_height; - break; - case ROCJPEG_CSS_422: - widths[0] = img_width * 2; - heights[0] = img_height; - break; - case ROCJPEG_CSS_420: - widths[1] = widths[0] = img_width; - heights[0] = img_height; - heights[1] = img_height >> 1; - break; - case ROCJPEG_CSS_400: - widths[0] = img_width; - heights[0] = img_height; - break; - default: - std::cout << "Unknown chroma subsampling!" << std::endl; - return; - } - break; - case ROCJPEG_OUTPUT_YUV_PLANAR: - switch (subsampling) { - case ROCJPEG_CSS_444: - widths[2] = widths[1] = widths[0] = img_width; - heights[2] = heights[1] = heights[0] = img_height; - break; - case ROCJPEG_CSS_422: - widths[0] = img_width; - widths[2] = widths[1] = widths[0] >> 1; - heights[2] = heights[1] = heights[0] = img_height; - break; - case ROCJPEG_CSS_420: - widths[0] = img_width; - widths[2] = widths[1] = widths[0] >> 1; - heights[0] = img_height; - heights[2] = heights[1] = img_height >> 1; - break; - case ROCJPEG_CSS_400: - widths[0] = img_width; - heights[0] = img_height; - break; - default: - std::cout << "Unknown chroma subsampling!" << std::endl; - return; - } - break; - case ROCJPEG_OUTPUT_Y: - widths[0] = img_width; - heights[0] = img_height; - break; - case ROCJPEG_OUTPUT_RGB: - widths[0] = img_width * 3; - heights[0] = img_height; - break; - case ROCJPEG_OUTPUT_RGB_PLANAR: - widths[2] = widths[1] = widths[0] = img_width; - heights[2] = heights[1] = heights[0] = img_height; - break; - default: - std::cout << "Unknown output format!" << std::endl; + /** + * @brief Saves the image. + * + * This function saves the image to the specified output file name based on the output image, image width, + * image height, chroma subsampling, and output format. + * + * @param output_file_name The output file name. + * @param output_image The output image. + * @param img_width The image width. + * @param img_height The image height. + * @param subsampling The chroma subsampling. + * @param output_format The output format. + */ + void SaveImage(std::string output_file_name, RocJpegImage *output_image, uint32_t img_width, uint32_t img_height, + RocJpegChromaSubsampling subsampling, RocJpegOutputFormat output_format) { + uint8_t *hst_ptr = nullptr; + FILE *fp; + hipError_t hip_status = hipSuccess; + + if (output_image == nullptr || output_image->channel[0] == nullptr || output_image->pitch[0] == 0) { return; - } - - uint32_t channel0_size = output_image->pitch[0] * heights[0]; - uint32_t channel1_size = output_image->pitch[1] * heights[1]; - uint32_t channel2_size = output_image->pitch[2] * heights[2]; - - uint32_t output_image_size = channel0_size + channel1_size + channel2_size; - - if (hst_ptr == nullptr) { - hst_ptr = new uint8_t [output_image_size]; - } - - CHECK_HIP(hipMemcpyDtoH((void *)hst_ptr, output_image->channel[0], channel0_size)); - - uint8_t *tmp_hst_ptr = hst_ptr; - fp = fopen(output_file_name.c_str(), "wb"); - if (fp) { - // write channel0 - if (widths[0] == output_image->pitch[0]) { - fwrite(hst_ptr, 1, channel0_size, fp); - } else { - for (int i = 0; i < heights[0]; i++) { - fwrite(tmp_hst_ptr, 1, widths[0], fp); - tmp_hst_ptr += output_image->pitch[0]; - } } - // write channel1 - if (channel1_size != 0 && output_image->channel[1] != nullptr) { - uint8_t *channel1_hst_ptr = hst_ptr + channel0_size; - CHECK_HIP(hipMemcpyDtoH((void *)channel1_hst_ptr, output_image->channel[1], channel1_size)); - if (widths[1] == output_image->pitch[1]) { - fwrite(channel1_hst_ptr, 1, channel1_size, fp); + + uint32_t widths[ROCJPEG_MAX_COMPONENT] = {}; + uint32_t heights[ROCJPEG_MAX_COMPONENT] = {}; + + switch (output_format) { + case ROCJPEG_OUTPUT_NATIVE: + switch (subsampling) { + case ROCJPEG_CSS_444: + widths[2] = widths[1] = widths[0] = img_width; + heights[2] = heights[1] = heights[0] = img_height; + break; + case ROCJPEG_CSS_422: + widths[0] = img_width * 2; + heights[0] = img_height; + break; + case ROCJPEG_CSS_420: + widths[1] = widths[0] = img_width; + heights[0] = img_height; + heights[1] = img_height >> 1; + break; + case ROCJPEG_CSS_400: + widths[0] = img_width; + heights[0] = img_height; + break; + default: + std::cout << "Unknown chroma subsampling!" << std::endl; + return; + } + break; + case ROCJPEG_OUTPUT_YUV_PLANAR: + switch (subsampling) { + case ROCJPEG_CSS_444: + widths[2] = widths[1] = widths[0] = img_width; + heights[2] = heights[1] = heights[0] = img_height; + break; + case ROCJPEG_CSS_422: + widths[0] = img_width; + widths[2] = widths[1] = widths[0] >> 1; + heights[2] = heights[1] = heights[0] = img_height; + break; + case ROCJPEG_CSS_420: + widths[0] = img_width; + widths[2] = widths[1] = widths[0] >> 1; + heights[0] = img_height; + heights[2] = heights[1] = img_height >> 1; + break; + case ROCJPEG_CSS_400: + widths[0] = img_width; + heights[0] = img_height; + break; + default: + std::cout << "Unknown chroma subsampling!" << std::endl; + return; + } + break; + case ROCJPEG_OUTPUT_Y: + widths[0] = img_width; + heights[0] = img_height; + break; + case ROCJPEG_OUTPUT_RGB: + widths[0] = img_width * 3; + heights[0] = img_height; + break; + case ROCJPEG_OUTPUT_RGB_PLANAR: + widths[2] = widths[1] = widths[0] = img_width; + heights[2] = heights[1] = heights[0] = img_height; + break; + default: + std::cout << "Unknown output format!" << std::endl; + return; + } + + uint32_t channel0_size = output_image->pitch[0] * heights[0]; + uint32_t channel1_size = output_image->pitch[1] * heights[1]; + uint32_t channel2_size = output_image->pitch[2] * heights[2]; + + uint32_t output_image_size = channel0_size + channel1_size + channel2_size; + + if (hst_ptr == nullptr) { + hst_ptr = new uint8_t [output_image_size]; + } + + CHECK_HIP(hipMemcpyDtoH((void *)hst_ptr, output_image->channel[0], channel0_size)); + + uint8_t *tmp_hst_ptr = hst_ptr; + fp = fopen(output_file_name.c_str(), "wb"); + if (fp) { + // write channel0 + if (widths[0] == output_image->pitch[0]) { + fwrite(hst_ptr, 1, channel0_size, fp); } else { - for (int i = 0; i < heights[1]; i++) { - fwrite(channel1_hst_ptr, 1, widths[1], fp); - channel1_hst_ptr += output_image->pitch[1]; + for (int i = 0; i < heights[0]; i++) { + fwrite(tmp_hst_ptr, 1, widths[0], fp); + tmp_hst_ptr += output_image->pitch[0]; } } - } - // write channel2 - if (channel2_size != 0 && output_image->channel[2] != nullptr) { - uint8_t *channel2_hst_ptr = hst_ptr + channel0_size + channel1_size; - CHECK_HIP(hipMemcpyDtoH((void *)channel2_hst_ptr, output_image->channel[2], channel2_size)); - if (widths[2] == output_image->pitch[2]) { - fwrite(channel2_hst_ptr, 1, channel2_size, fp); - } else { - for (int i = 0; i < heights[2]; i++) { - fwrite(channel2_hst_ptr, 1, widths[2], fp); - channel2_hst_ptr += output_image->pitch[2]; + // write channel1 + if (channel1_size != 0 && output_image->channel[1] != nullptr) { + uint8_t *channel1_hst_ptr = hst_ptr + channel0_size; + CHECK_HIP(hipMemcpyDtoH((void *)channel1_hst_ptr, output_image->channel[1], channel1_size)); + if (widths[1] == output_image->pitch[1]) { + fwrite(channel1_hst_ptr, 1, channel1_size, fp); + } else { + for (int i = 0; i < heights[1]; i++) { + fwrite(channel1_hst_ptr, 1, widths[1], fp); + channel1_hst_ptr += output_image->pitch[1]; + } } } + // write channel2 + if (channel2_size != 0 && output_image->channel[2] != nullptr) { + uint8_t *channel2_hst_ptr = hst_ptr + channel0_size + channel1_size; + CHECK_HIP(hipMemcpyDtoH((void *)channel2_hst_ptr, output_image->channel[2], channel2_size)); + if (widths[2] == output_image->pitch[2]) { + fwrite(channel2_hst_ptr, 1, channel2_size, fp); + } else { + for (int i = 0; i < heights[2]; i++) { + fwrite(channel2_hst_ptr, 1, widths[2], fp); + channel2_hst_ptr += output_image->pitch[2]; + } + } + } + fclose(fp); + } + + if (hst_ptr != nullptr) { + delete [] hst_ptr; + hst_ptr = nullptr; + tmp_hst_ptr = nullptr; } - fclose(fp); } - if (hst_ptr != nullptr) { - delete [] hst_ptr; - hst_ptr = nullptr; - tmp_hst_ptr = nullptr; +private: + /** + * @brief Shows the help message and exits. + * + * This function shows the help message and exits the program. + * + * @param option The option to display in the help message (optional). + * @param show_threads Flag indicating whether to show the number of threads in the help message. + */ + static void ShowHelpAndExit(const char *option = nullptr, bool show_threads = false) { + std::cout << "Options:\n" + "-i [input path] - input path to a single JPEG image or a directory containing JPEG images - [required]\n" + "-be [backend] - select rocJPEG backend (0 for hardware-accelerated JPEG decoding using VCN,\n" + " 1 for hybrid JPEG decoding using CPU and GPU HIP kernels (currently not supported)) [optional - default: 0]\n" + "-fmt [output format] - select rocJPEG output format for decoding, one of the [native, yuv, y, rgb, rgb_planar] - [optional - default: native]\n" + "-o [output path] - path to an output file or a path to a directory - write decoded images to a file or directory based on selected output format - [optional]\n" + "-d [device id] - specify the GPU device id for the desired device (use 0 for the first device, 1 for the second device, and so on) [optional - default: 0]\n"; + if (show_threads) { + std::cout << "-t [threads] - number of threads for parallel JPEG decoding - [optional - default: 2]\n"; + } + exit(0); } -} +}; #endif //ROC_JPEG_SAMPLES_COMMON \ No newline at end of file diff --git a/src/rocjpeg_api.cpp b/src/rocjpeg_api.cpp index c3e8f3b01d..07801265ff 100644 --- a/src/rocjpeg_api.cpp +++ b/src/rocjpeg_api.cpp @@ -24,11 +24,17 @@ THE SOFTWARE. #include "rocjpeg_api_decoder_handle.h" #include "rocjpeg_commons.h" -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegStreamCreate(RocJpegStreamHandle *jpeg_stream_handle) -//! \ingroup group_amd_rocjpeg -//! Create the rocJPEG stream parser handle. This handle is used to parse and retrieve the information from the JPEG stream. -/*****************************************************************************************************/ +/** + * @brief Creates a RocJpegStreamHandle for JPEG stream processing. + * + * This function creates a RocJpegStreamHandle, which is used for processing JPEG streams. + * The created handle is assigned to the provided jpeg_stream_handle pointer. + * + * @param jpeg_stream_handle A pointer to a RocJpegStreamHandle variable that will hold the created handle. + * @return RocJpegStatus The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if successful, + * ROCJPEG_STATUS_INVALID_PARAMETER if the jpeg_stream_handle pointer is nullptr, + * or ROCJPEG_STATUS_NOT_INITIALIZED if the rocJPEG stream handle failed to initialize. + */ RocJpegStatus ROCJPEGAPI rocJpegStreamCreate(RocJpegStreamHandle *jpeg_stream_handle) { if (jpeg_stream_handle == nullptr) { return ROCJPEG_STATUS_INVALID_PARAMETER; @@ -45,11 +51,20 @@ RocJpegStatus ROCJPEGAPI rocJpegStreamCreate(RocJpegStreamHandle *jpeg_stream_ha return ROCJPEG_STATUS_SUCCESS; } -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegStreamParse(const unsigned char *data, size_t length, RocJpegStreamHandle jpeg_stream_handle) -//! \ingroup group_amd_rocjpeg -//! Parses a jpeg stream and stores the information from the stream to be used in subsequent API calls for retrieving the image information and decoding it. -/*****************************************************************************************************/ +/** + * @brief Parses a JPEG stream. + * + * This function parses a JPEG stream represented by the input data and length, + * and updates the provided JPEG stream handle accordingly. + * + * @param data The pointer to the JPEG stream data. + * @param length The length of the JPEG stream data. + * @param jpeg_stream_handle The handle to the JPEG stream. + * @return The status of the JPEG stream parsing operation. + * - ROCJPEG_STATUS_SUCCESS if the parsing is successful. + * - ROCJPEG_STATUS_INVALID_PARAMETER if the input parameters are invalid. + * - ROCJPEG_STATUS_BAD_JPEG if the JPEG stream is invalid. + */ RocJpegStatus ROCJPEGAPI rocJpegStreamParse(const unsigned char *data, size_t length, RocJpegStreamHandle jpeg_stream_handle) { if (data == nullptr || jpeg_stream_handle == nullptr) { return ROCJPEG_STATUS_INVALID_PARAMETER; @@ -61,11 +76,13 @@ RocJpegStatus ROCJPEGAPI rocJpegStreamParse(const unsigned char *data, size_t le return ROCJPEG_STATUS_SUCCESS; } -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegStreamDestroy(RocJpegStreamHandle jpeg_stream_handle) -//! \ingroup group_amd_rocjpeg -//! Release the jpeg parser object and resources. -/*****************************************************************************************************/ +/** + * @brief Destroys a RocJpegStreamHandle object and releases associated resources. + * + * @param jpeg_stream_handle The handle to the RocJpegStreamHandle object to be destroyed. + * @return RocJpegStatus The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if successful, + * or ROCJPEG_STATUS_INVALID_PARAMETER if the input handle is nullptr. + */ RocJpegStatus ROCJPEGAPI rocJpegStreamDestroy(RocJpegStreamHandle jpeg_stream_handle) { if (jpeg_stream_handle == nullptr) { return ROCJPEG_STATUS_INVALID_PARAMETER; @@ -75,11 +92,18 @@ RocJpegStatus ROCJPEGAPI rocJpegStreamDestroy(RocJpegStreamHandle jpeg_stream_ha return ROCJPEG_STATUS_SUCCESS; } -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegCreate(RocJpegBackend backend, int device_id, RocJpegHandle *handle) -//! \ingroup group_amd_rocjpeg -//! Create the decoder object based on backend and device_id. A handle to the created decoder is returned -/*****************************************************************************************************/ +/** + * @brief Creates a RocJpegHandle for JPEG decoding. + * + * This function creates a RocJpegHandle for JPEG decoding using the specified backend and device ID. + * + * @param backend The backend to be used for JPEG decoding. + * @param device_id The ID of the device to be used for JPEG decoding. + * @param handle Pointer to a RocJpegHandle variable to store the created handle. + * @return The status of the operation. Returns ROCJPEG_STATUS_INVALID_PARAMETER if handle is nullptr, + * ROCJPEG_STATUS_NOT_INITIALIZED if the rocJPEG handle initialization fails, or the status + * returned by the InitializeDecoder function of the rocjpeg_decoder. + */ RocJpegStatus ROCJPEGAPI rocJpegCreate(RocJpegBackend backend, int device_id, RocJpegHandle *handle) { if (handle == nullptr) { return ROCJPEG_STATUS_INVALID_PARAMETER; @@ -95,11 +119,16 @@ RocJpegStatus ROCJPEGAPI rocJpegCreate(RocJpegBackend backend, int device_id, Ro return static_cast(rocjpeg_handle)->rocjpeg_decoder->InitializeDecoder(); } -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegDestroy(RocJpegHandle handle) -//! \ingroup group_amd_rocjpeg -//! Release the decoder object and resources. -/*****************************************************************************************************/ +/** + * @brief Destroys a RocJpegHandle object. + * + * This function destroys the RocJpegHandle object pointed to by the given handle. + * It releases any resources associated with the handle and frees the memory. + * + * @param handle The handle to the RocJpegHandle object to be destroyed. + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if the handle was successfully destroyed, + * or ROCJPEG_STATUS_INVALID_PARAMETER if the handle is nullptr. + */ RocJpegStatus ROCJPEGAPI rocJpegDestroy(RocJpegHandle handle) { if (handle == nullptr) { return ROCJPEG_STATUS_INVALID_PARAMETER; @@ -109,12 +138,25 @@ RocJpegStatus ROCJPEGAPI rocJpegDestroy(RocJpegHandle handle) { return ROCJPEG_STATUS_SUCCESS; } -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegGetImageInfo(RocJpegHandle handle, RocJpegStreamHandle jpeg_stream_handle, -//! int *num_components, RocJpegChromaSubsampling *subsampling, int *widths, int *heights) -//! \ingroup group_amd_rocjpeg -//! Retrieve the image info, including channel, width and height of each component, and chroma subsampling. -/*****************************************************************************************************/ +/** + * @brief Retrieves information about the JPEG image. + * + * This function retrieves the number of components, chroma subsampling, and dimensions (width and height) of the JPEG image + * specified by the `jpeg_stream_handle`. The information is stored in the provided output parameters `num_components`, + * `subsampling`, `widths`, and `heights`. + * + * @param handle The handle to the RocJpegDecoder instance. + * @param jpeg_stream_handle The handle to the RocJpegStream instance representing the JPEG image. + * @param num_components A pointer to an unsigned 8-bit integer that will store the number of components in the JPEG image. + * @param subsampling A pointer to a RocJpegChromaSubsampling enum that will store the chroma subsampling information. + * @param widths A pointer to an unsigned 32-bit integer array that will store the width of each component in the JPEG image. + * @param heights A pointer to an unsigned 32-bit integer array that will store the height of each component in the JPEG image. + * + * @return The RocJpegStatus indicating the success or failure of the operation. + * - ROCJPEG_STATUS_SUCCESS: The operation was successful. + * - ROCJPEG_STATUS_INVALID_PARAMETER: One or more input parameters are invalid. + * - ROCJPEG_STATUS_RUNTIME_ERROR: An exception occurred during the operation. + */ RocJpegStatus ROCJPEGAPI rocJpegGetImageInfo(RocJpegHandle handle, RocJpegStreamHandle jpeg_stream_handle, uint8_t *num_components, RocJpegChromaSubsampling *subsampling, uint32_t *widths, uint32_t *heights) { if (handle == nullptr || num_components == nullptr || @@ -134,16 +176,19 @@ RocJpegStatus ROCJPEGAPI rocJpegGetImageInfo(RocJpegHandle handle, RocJpegStream return rocjpeg_status; } -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegDecode(RocJpegHandle handle, RocJpegStreamHandle jpeg_stream_handle, const RocJpegDecodeParams *decode_params, RocJpegImage *destination); -//! \ingroup group_amd_rocjpeg -//! Decodes single image based on the backend used to create the rocJpeg handle in rocJpegCreate API. -//! Destination buffers should be large enough to be able to store output of specified format. -//! These buffers should be pre-allocted by the user in the device memories. -//! For each color plane (channel) sizes could be retrieved for image using rocJpegGetImageInfo API -//! and minimum required memory buffer for each plane is plane_height * plane_pitch where plane_pitch >= plane_width for -//! planar output formats and plane_pitch >= plane_width * num_components for interleaved output format. -/*****************************************************************************************************/ +/** + * @brief Decodes a JPEG image using the rocJPEG library. + * + * This function decodes a JPEG image using the rocJPEG library. It takes a rocJpegHandle, a rocJpegStreamHandle, + * a pointer to RocJpegDecodeParams, and a pointer to RocJpegImage as input parameters. The function returns a + * RocJpegStatus indicating the success or failure of the decoding operation. + * + * @param handle The rocJpegHandle representing the rocJPEG decoder instance. + * @param jpeg_stream_handle The rocJpegStreamHandle representing the input JPEG stream. + * @param decode_params A pointer to RocJpegDecodeParams containing the decoding parameters. + * @param destination A pointer to RocJpegImage where the decoded image will be stored. + * @return A RocJpegStatus indicating the success or failure of the decoding operation. + */ RocJpegStatus ROCJPEGAPI rocJpegDecode(RocJpegHandle handle, RocJpegStreamHandle jpeg_stream_handle, const RocJpegDecodeParams *decode_params, RocJpegImage *destination) { @@ -163,11 +208,14 @@ RocJpegStatus ROCJPEGAPI rocJpegDecode(RocJpegHandle handle, RocJpegStreamHandle return rocjpeg_status; } -/*****************************************************************************************************/ -//! \fn extern const char* ROCDECAPI rocJpegGetErrorName(RocJpegStatus rocjpeg_status); -//! \ingroup group_amd_rocjpeg -//! Return name of the specified error code in text form. -/*****************************************************************************************************/ +/** + * @brief Returns the error name corresponding to the given RocJpegStatus. + * + * This function takes a RocJpegStatus enum value and returns the corresponding error name as a string. + * + * @param rocjpeg_status The RocJpegStatus enum value. + * @return The error name as a string. + */ extern const char* ROCJPEGAPI rocJpegGetErrorName(RocJpegStatus rocjpeg_status) { switch (rocjpeg_status) { case ROCJPEG_STATUS_SUCCESS: @@ -199,29 +247,4 @@ extern const char* ROCJPEGAPI rocJpegGetErrorName(RocJpegStatus rocjpeg_status) default: return "UNKNOWN_ERROR"; } -} - -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegDecodeBatchedInitialize(RocJpegHandle handle, int batch_size, int max_cpu_threads, RocJpegOutputFormat output_format); -//! \ingroup group_amd_rocjpeg -//! Resets and initializes batch decoder for working on the batches of specified size -//! Should be called once for decoding batches of this specific size, also use to reset failed batches -//! \return ROCJPEG_STATUS_SUCCESS if successful -/*****************************************************************************************************/ -RocJpegStatus ROCJPEGAPI rocJpegDecodeBatchedInitialize(RocJpegHandle handle, int batch_size, int max_cpu_threads, RocJpegOutputFormat output_format) { - return ROCJPEG_STATUS_NOT_IMPLEMENTED; -} - - -/*****************************************************************************************************/ -//! \fn RocJpegStatus ROCJPEGAPI rocJpegDecodeBatched(RocJpegHandle handle, const uint8_t *data, const size_t *lengths, RocJpegImage *destinations, hipStream_t stream); -//! \ingroup group_amd_rocjpeg -//! Decodes batch of images. Output buffers should be large enough to be able to store -//! outputs of specified format, see single image decoding description for details. Call to -//! rocjpegDecodeBatchedInitialize() is required prior to this call, batch size is expected to be the same as -//! parameter to this batch initialization function. -//! \return ROCJPEG_STATUS_SUCCESS if successful -/*****************************************************************************************************/ -RocJpegStatus ROCJPEGAPI rocJpegDecodeBatched(RocJpegHandle handle, const uint8_t *data, const size_t *lengths, RocJpegImage *destinations) { - return ROCJPEG_STATUS_NOT_IMPLEMENTED; -} +} \ No newline at end of file diff --git a/src/rocjpeg_api_decoder_handle.h b/src/rocjpeg_api_decoder_handle.h index 6f1942cbcc..cab9b0134c 100644 --- a/src/rocjpeg_api_decoder_handle.h +++ b/src/rocjpeg_api_decoder_handle.h @@ -28,20 +28,61 @@ THE SOFTWARE. #include "rocjpeg_decoder.h" /** - * @brief RocJpegDecoderHandle class - * This class wraps around RocJpegDecoder to decode a JPEG stream. + * @brief The RocJpegDecoderHandle class represents a handle to the RocJpegDecoder object. + * + * This class provides a convenient way to manage the lifetime of a RocJpegDecoder object. + * It encapsulates the RocJpegDecoder object and provides error handling functionality. */ class RocJpegDecoderHandle { - public: - explicit RocJpegDecoderHandle(RocJpegBackend backend, int device_id) : rocjpeg_decoder(std::make_shared(backend, device_id)) {}; - ~RocJpegDecoderHandle() { ClearErrors(); } - std::shared_ptr rocjpeg_decoder; - bool NoError() { return error_.empty(); } - const char* ErrorMsg() { return error_.c_str(); } - void CaptureError(const std::string& err_msg) { error_ = err_msg; } - private: - void ClearErrors() { error_ = "";} - std::string error_; +public: + /** + * @brief Constructs a RocJpegDecoderHandle object with the specified backend and device ID. + * + * @param backend The backend to use for decoding. + * @param device_id The ID of the device to use for decoding. + */ + explicit RocJpegDecoderHandle(RocJpegBackend backend, int device_id) : rocjpeg_decoder(std::make_shared(backend, device_id)) {}; + + /** + * @brief Destructor for the RocJpegDecoderHandle class. + * + * Clears any errors associated with the handle. + */ + ~RocJpegDecoderHandle() { ClearErrors(); } + + /** + * @brief The RocJpegDecoder object associated with the handle. + */ + std::shared_ptr rocjpeg_decoder; + + /** + * @brief Checks if there are no errors associated with the handle. + * + * @return true if there are no errors, false otherwise. + */ + bool NoError() { return error_.empty(); } + + /** + * @brief Gets the error message associated with the handle. + * + * @return The error message as a C-style string. + */ + const char* ErrorMsg() { return error_.c_str(); } + + /** + * @brief Captures an error message for the handle. + * + * @param err_msg The error message to capture. + */ + void CaptureError(const std::string& err_msg) { error_ = err_msg; } + +private: + /** + * @brief Clears any errors associated with the handle. + */ + void ClearErrors() { error_ = ""; } + + std::string error_; }; #endif //ROC_JPEG_DECODER_HANDLE_H \ No newline at end of file diff --git a/src/rocjpeg_api_stream_handle.h b/src/rocjpeg_api_stream_handle.h index 2ca03fda6d..5ccde83186 100644 --- a/src/rocjpeg_api_stream_handle.h +++ b/src/rocjpeg_api_stream_handle.h @@ -29,20 +29,55 @@ THE SOFTWARE. #include "rocjpeg_parser.h" /** - * @brief RocJpegStreamParserHandle class - * This class wraps around RocJpegStreamParser to parse and store information from a JPEG stream. + * @brief The RocJpegStreamParserHandle class represents a handle to the RocJpegStreamParser object. + * + * This class provides a convenient way to manage the RocJpegStreamParser object by encapsulating it + * within a shared pointer. It also provides error handling functionality. */ class RocJpegStreamParserHandle { public: + /** + * @brief Constructs a RocJpegStreamParserHandle object. + * + * This constructor initializes the rocjpeg_stream member with a new instance of RocJpegStreamParser + * using std::make_shared. + */ explicit RocJpegStreamParserHandle() : rocjpeg_stream(std::make_shared()) {}; + + /** + * @brief Destroys the RocJpegStreamParserHandle object. + * + * This destructor clears any errors associated with the handle. + */ ~RocJpegStreamParserHandle() { ClearErrors(); } - std::shared_ptr rocjpeg_stream; + + std::shared_ptr rocjpeg_stream; /**< The RocJpegStreamParser object. */ + + /** + * @brief Checks if there are no errors associated with the handle. + * @return true if there are no errors, false otherwise. + */ bool NoError() { return error_.empty(); } + + /** + * @brief Gets the error message associated with the handle. + * @return The error message as a C-style string. + */ const char* ErrorMsg() { return error_.c_str(); } + + /** + * @brief Captures an error message. + * @param err_msg The error message to capture. + */ void CaptureError(const std::string& err_msg) { error_ = err_msg; } + private: + /** + * @brief Clears any errors associated with the handle. + */ void ClearErrors() { error_ = "";} - std::string error_; + + std::string error_; /**< The error message. */ }; #endif //ROC_JPEG_STREAM_HANDLE_H \ No newline at end of file diff --git a/src/rocjpeg_commons.h b/src/rocjpeg_commons.h index c0caa3bd60..bcc0563fce 100644 --- a/src/rocjpeg_commons.h +++ b/src/rocjpeg_commons.h @@ -77,12 +77,33 @@ static inline int align(int value, int alignment) { return (value + alignment - 1) & ~(alignment - 1); } +/** + * @brief Custom exception class for RocJpeg. + * + * This exception class is used to handle errors and exceptions that occur during RocJpeg operations. + * It inherits from the std::exception class and provides an implementation for the what() function. + */ class RocJpegException : public std::exception { public: + /** + * @brief Constructs a RocJpegException object with the specified error message. + * + * @param message The error message associated with the exception. + */ explicit RocJpegException(const std::string& message):message_(message){} + + /** + * @brief Returns a C-style string describing the exception. + * + * This function overrides the what() function from the std::exception class and returns + * the error message associated with the exception. + * + * @return A C-style string describing the exception. + */ virtual const char* what() const throw() override { return message_.c_str(); } + private: std::string message_; }; diff --git a/src/rocjpeg_decoder.cpp b/src/rocjpeg_decoder.cpp index cd0479c982..14d6b2d745 100644 --- a/src/rocjpeg_decoder.cpp +++ b/src/rocjpeg_decoder.cpp @@ -31,6 +31,18 @@ RocJpegDecoder::~RocJpegDecoder() { } } +/** + * @brief Initializes the HIP environment for the RocJpegDecoder. + * + * This function initializes the HIP environment for the RocJpegDecoder by setting the device, + * creating a HIP stream, and retrieving device properties. + * + * @param device_id The ID of the device to be used for decoding. + * @return The status of the initialization process. + * - ROCJPEG_STATUS_SUCCESS if the initialization is successful. + * - ROCJPEG_STATUS_NOT_INITIALIZED if no GPU device is found. + * - ROCJPEG_STATUS_INVALID_PARAMETER if the requested device_id is not found. + */ RocJpegStatus RocJpegDecoder::InitHIP(int device_id) { hipError_t hip_status = hipSuccess; CHECK_HIP(hipGetDeviceCount(&num_devices_)); @@ -48,6 +60,17 @@ RocJpegStatus RocJpegDecoder::InitHIP(int device_id) { return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Initializes the RocJpegDecoder. + * + * This function initializes the RocJpegDecoder by performing the following steps: + * 1. Initializes the HIP device. + * 2. If the backend is ROCJPEG_BACKEND_HARDWARE, initializes the VA-API JPEG decoder. + * + * @return The status of the initialization process. + * - ROCJPEG_STATUS_SUCCESS if the initialization is successful. + * - An error code if the initialization fails. + */ RocJpegStatus RocJpegDecoder::InitializeDecoder() { RocJpegStatus rocjpeg_status = ROCJPEG_STATUS_SUCCESS; rocjpeg_status = InitHIP(device_id_); @@ -67,6 +90,17 @@ RocJpegStatus RocJpegDecoder::InitializeDecoder() { return rocjpeg_status; } +/** + * @brief Decodes a JPEG image using the RocJpegDecoder. + * + * This function decodes a JPEG image from the provided JPEG stream handle and decode parameters, + * and stores the decoded image in the destination buffer. + * + * @param jpeg_stream_handle The handle to the JPEG stream. + * @param decode_params The decode parameters for the JPEG image. + * @param destination The destination buffer to store the decoded image. + * @return The status of the JPEG decoding operation. + */ RocJpegStatus RocJpegDecoder::Decode(RocJpegStreamHandle jpeg_stream_handle, const RocJpegDecodeParams *decode_params, RocJpegImage *destination) { std::lock_guard lock(mutex_); RocJpegStatus rocjpeg_status = ROCJPEG_STATUS_SUCCESS; @@ -123,11 +157,23 @@ RocJpegStatus RocJpegDecoder::Decode(RocJpegStreamHandle jpeg_stream_handle, con CHECK_HIP(hipStreamSynchronize(hip_stream_)); - return ROCJPEG_STATUS_SUCCESS; - } +/** + * @brief Retrieves the image information from the JPEG stream. + * + * This function retrieves the number of components, chroma subsampling, widths, and heights + * of the image from the given JPEG stream. + * + * @param jpeg_stream_handle The handle to the JPEG stream. + * @param num_components Pointer to store the number of components in the image. + * @param subsampling Pointer to store the chroma subsampling of the image. + * @param widths Array to store the widths of the image components. + * @param heights Array to store the heights of the image components. + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if successful, + * or ROCJPEG_STATUS_INVALID_PARAMETER if any of the input parameters are invalid. + */ RocJpegStatus RocJpegDecoder::GetImageInfo(RocJpegStreamHandle jpeg_stream_handle, uint8_t *num_components, RocJpegChromaSubsampling *subsampling, uint32_t *widths, uint32_t *heights){ std::lock_guard lock(mutex_); if (jpeg_stream_handle == nullptr || num_components == nullptr || subsampling == nullptr || widths == nullptr || heights == nullptr) { @@ -181,6 +227,18 @@ RocJpegStatus RocJpegDecoder::GetImageInfo(RocJpegStreamHandle jpeg_stream_handl return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Copies a channel from the `hip_interop_dev_mem` to the `destination` image. + * + * This function copies the channel specified by `channel_index` from the `hip_interop_dev_mem` to the `destination` image. + * The `channel_height` parameter specifies the height of the channel. + * + * @param hip_interop_dev_mem The `HipInteropDeviceMem` object containing the source channel data. + * @param channel_height The height of the channel to be copied. + * @param channel_index The index of the channel to be copied. + * @param destination The `RocJpegImage` object representing the destination image. + * @return The status of the operation. Returns `ROCJPEG_STATUS_SUCCESS` if the channel was copied successfully. + */ RocJpegStatus RocJpegDecoder::CopyChannel(HipInteropDeviceMem& hip_interop_dev_mem, uint16_t channel_height, uint8_t channel_index, RocJpegImage *destination) { if (hip_interop_dev_mem.pitch[channel_index] != 0 && destination->pitch[channel_index] != 0 && destination->channel[channel_index] != nullptr) { if (destination->pitch[channel_index] == hip_interop_dev_mem.pitch[channel_index]) { @@ -194,6 +252,18 @@ RocJpegStatus RocJpegDecoder::CopyChannel(HipInteropDeviceMem& hip_interop_dev_m return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Calculates the chroma height based on the surface format and picture height. + * + * This function takes the surface format, picture height, and a reference to the chroma height. + * It calculates the chroma height based on the surface format and assigns the result to the chroma_height parameter. + * + * @param surface_format The surface format of the image. + * @param picture_height The height of the picture. + * @param chroma_height A reference to the variable where the calculated chroma height will be stored. + * + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if successful, or ROCJPEG_STATUS_JPEG_NOT_SUPPORTED if the surface format is not supported. + */ RocJpegStatus RocJpegDecoder::GetChromaHeight(uint32_t surface_format, uint16_t picture_height, uint16_t &chroma_height) { switch (surface_format) { case VA_FOURCC_NV12: /*NV12: two-plane 8-bit YUV 4:2:0*/ @@ -214,6 +284,20 @@ RocJpegStatus RocJpegDecoder::GetChromaHeight(uint32_t surface_format, uint16_t return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Converts the color format of the input image to RGB format. + * + * This function converts the color format of the input image to RGB format based on the surface format + * specified in the `hip_interop_dev_mem` parameter. The converted image is stored in the `destination` + * parameter. + * + * @param hip_interop_dev_mem The HipInteropDeviceMem object containing the input image data. + * @param picture_width The width of the input image. + * @param picture_height The height of the input image. + * @param destination Pointer to the RocJpegImage object where the converted image will be stored. + * @return The status of the color conversion operation. Returns ROCJPEG_STATUS_SUCCESS if the conversion + * is successful. Returns ROCJPEG_STATUS_JPEG_NOT_SUPPORTED if the surface format is not supported. + */ RocJpegStatus RocJpegDecoder::ColorConvertToRGB(HipInteropDeviceMem& hip_interop_dev_mem, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { switch (hip_interop_dev_mem.surface_format) { case VA_FOURCC_444P: @@ -244,6 +328,21 @@ RocJpegStatus RocJpegDecoder::ColorConvertToRGB(HipInteropDeviceMem& hip_interop return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Converts the color format of the input image to RGB planar format. + * + * This function converts the color format of the input image to RGB planar format. + * The conversion is performed based on the surface format specified in the `hip_interop_dev_mem`. + * The converted image is stored in the `destination` RocJpegImage object. + * + * @param hip_interop_dev_mem The HipInteropDeviceMem object containing the input image data. + * @param picture_width The width of the input image. + * @param picture_height The height of the input image. + * @param destination Pointer to the RocJpegImage object where the converted image will be stored. + * @return RocJpegStatus The status of the color conversion operation. + * Returns ROCJPEG_STATUS_SUCCESS if the conversion is successful. + * Returns ROCJPEG_STATUS_JPEG_NOT_SUPPORTED if the surface format is not supported. + */ RocJpegStatus RocJpegDecoder::ColorConvertToRGBPlanar(HipInteropDeviceMem& hip_interop_dev_mem, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { switch (hip_interop_dev_mem.surface_format) { case VA_FOURCC_444P: @@ -276,6 +375,23 @@ RocJpegStatus RocJpegDecoder::ColorConvertToRGBPlanar(HipInteropDeviceMem& hip_i return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Retrieves the planar YUV output format from the input image. + * + * This function converts the input image data to planar YUV format based on the surface format of the input data. + * If the surface format is ROCJPEG_FOURCC_YUYV, the function extracts the packed YUYV data and copies them into the + * first, second, and third channels of the destination image. If the surface format is VA_FOURCC_NV12, the function + * extracts the interleaved UV channels and copies them into the second and third channels of the destination image. + * If the surface format is VA_FOURCC_444P, the function copies the luma channel and both chroma channels into the + * destination image. + * + * @param hip_interop_dev_mem The HipInteropDeviceMem object containing the input image data. + * @param picture_width The width of the input picture. + * @param picture_height The height of the input picture. + * @param chroma_height The height of the chroma channels. + * @param destination Pointer to the RocJpegImage object where the converted image data will be stored. + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if successful. + */ RocJpegStatus RocJpegDecoder::GetPlanarYUVOutputFormat(HipInteropDeviceMem& hip_interop_dev_mem, uint32_t picture_width, uint32_t picture_height, uint16_t chroma_height, RocJpegImage *destination) { if (hip_interop_dev_mem.surface_format == ROCJPEG_FOURCC_YUYV) { // Extract the packed YUYV and copy them into the first, second, and thrid channels of the destination. @@ -296,6 +412,19 @@ RocJpegStatus RocJpegDecoder::GetPlanarYUVOutputFormat(HipInteropDeviceMem& hip_ return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Retrieves the Y output format from the input YUV image. + * + * This function extracts the Y output format from the RocJpegDecoder based on the provided parameters. + * If the surface format is ROCJPEG_FOURCC_YUYV, it calls the ExtractYFromPackedYUYV function to extract the Y component + * from the packed YUYV format. Otherwise, it calls the CopyChannel function to copy the luma channel. + * + * @param hip_interop_dev_mem The HipInteropDeviceMem object containing the surface format and device memory. + * @param picture_width The width of the picture. + * @param picture_height The height of the picture. + * @param destination Pointer to the RocJpegImage object where the extracted Y component will be stored. + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if successful. + */ RocJpegStatus RocJpegDecoder::GetYOutputFormat(HipInteropDeviceMem& hip_interop_dev_mem, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination) { if (hip_interop_dev_mem.surface_format == ROCJPEG_FOURCC_YUYV) { ExtractYFromPackedYUYV(hip_stream_, picture_width, picture_height, destination->channel[0], destination->pitch[0], diff --git a/src/rocjpeg_decoder.h b/src/rocjpeg_decoder.h index 346ac7e5de..86048d496c 100644 --- a/src/rocjpeg_decoder.h +++ b/src/rocjpeg_decoder.h @@ -34,28 +34,131 @@ THE SOFTWARE. #include "rocjpeg_vaapi_decoder.h" #include "rocjpeg_hip_kernels.h" +/** + * @class RocJpegDecoder + * @brief The RocJpegDecoder class represents a JPEG decoder. + * + * This class provides methods to initialize the decoder, retrieve image information, + * and decode JPEG streams into RocJpegImage objects. + */ +/** + * @brief The RocJpegDecoder class is responsible for decoding JPEG images using a hardware-accelerated jpeg decoder. + */ class RocJpegDecoder { - public: - RocJpegDecoder(RocJpegBackend backend = ROCJPEG_BACKEND_HARDWARE, int device_id = 0); - ~RocJpegDecoder(); - RocJpegStatus InitializeDecoder(); - RocJpegStatus GetImageInfo(RocJpegStreamHandle jpeg_stream, uint8_t *num_components, RocJpegChromaSubsampling *subsampling, uint32_t *widths, uint32_t *heights); - RocJpegStatus Decode(RocJpegStreamHandle jpeg_stream, const RocJpegDecodeParams *decode_params, RocJpegImage *destination); - private: - RocJpegStatus InitHIP(int device_id); - RocJpegStatus GetChromaHeight(uint32_t surface_format, uint16_t picture_height, uint16_t &chroma_height); - RocJpegStatus CopyChannel(HipInteropDeviceMem& hip_interop, uint16_t channel_height, uint8_t channel_index, RocJpegImage *destination); - RocJpegStatus ColorConvertToRGB(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); - RocJpegStatus ColorConvertToRGBPlanar(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); - RocJpegStatus GetPlanarYUVOutputFormat(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, uint16_t chroma_height, RocJpegImage *destination); - RocJpegStatus GetYOutputFormat(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); - int num_devices_; - int device_id_; - hipDeviceProp_t hip_dev_prop_; - hipStream_t hip_stream_; - std::mutex mutex_; - RocJpegBackend backend_; - RocJpegVappiDecoder jpeg_vaapi_decoder_; +public: + /** + * @brief Constructs a RocJpegDecoder object. + * @param backend The ROCm backend to be used for decoding (default: ROCJPEG_BACKEND_HARDWARE). + * @param device_id The ID of the device to be used for decoding (default: 0). + */ + RocJpegDecoder(RocJpegBackend backend = ROCJPEG_BACKEND_HARDWARE, int device_id = 0); + + /** + * @brief Destroys the RocJpegDecoder object. + */ + ~RocJpegDecoder(); + + /** + * @brief Initializes the decoder. + * @return The status of the initialization process. + */ + RocJpegStatus InitializeDecoder(); + + /** + * @brief Retrieves information about the JPEG image. + * @param jpeg_stream The handle to the JPEG stream. + * @param num_components Pointer to store the number of color components in the image. + * @param subsampling Pointer to store the chroma subsampling information. + * @param widths Pointer to store the widths of the image components. + * @param heights Pointer to store the heights of the image components. + * @return The status of the operation. + */ + RocJpegStatus GetImageInfo(RocJpegStreamHandle jpeg_stream, uint8_t *num_components, RocJpegChromaSubsampling *subsampling, uint32_t *widths, uint32_t *heights); + + /** + * @brief Decodes the JPEG image. + * @param jpeg_stream The handle to the JPEG stream. + * @param decode_params The decoding parameters. + * @param destination Pointer to the destination image. + * @return The status of the decoding process. + */ + RocJpegStatus Decode(RocJpegStreamHandle jpeg_stream, const RocJpegDecodeParams *decode_params, RocJpegImage *destination); + +private: + /** + * @brief Initializes the HIP framework. + * @param device_id The ID of the device to be used for HIP operations. + * @return The status of the initialization process. + */ + RocJpegStatus InitHIP(int device_id); + + /** + * @brief Retrieves the height of the chroma channel. + * @param surface_format The surface format of the image. + * @param picture_height The height of the picture. + * @param chroma_height Reference to store the height of the chroma channel. + * @return The status of the operation. + */ + RocJpegStatus GetChromaHeight(uint32_t surface_format, uint16_t picture_height, uint16_t &chroma_height); + + /** + * @brief Copies a channel from the HIP interop device memory to the destination image. + * @param hip_interop The HIP interop device memory. + * @param channel_height The height of the channel. + * @param channel_index The index of the channel. + * @param destination Pointer to the destination image. + * @return The status of the operation. + */ + RocJpegStatus CopyChannel(HipInteropDeviceMem& hip_interop, uint16_t channel_height, uint8_t channel_index, RocJpegImage *destination); + + /** + * @brief Converts the image to RGB color space. + * @param hip_interop The HIP interop device memory. + * @param picture_width The width of the picture. + * @param picture_height The height of the picture. + * @param destination Pointer to the destination image. + * @return The status of the operation. + */ + RocJpegStatus ColorConvertToRGB(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); + + /** + * @brief Converts the image to RGB planar color space. + * @param hip_interop The HIP interop device memory. + * @param picture_width The width of the picture. + * @param picture_height The height of the picture. + * @param destination Pointer to the destination image. + * @return The status of the operation. + */ + RocJpegStatus ColorConvertToRGBPlanar(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); + + /** + * @brief Retrieves the output format for planar YUV images. + * @param hip_interop The HIP interop device memory. + * @param picture_width The width of the picture. + * @param picture_height The height of the picture. + * @param chroma_height The height of the chroma channel. + * @param destination Pointer to the destination image. + * @return The status of the operation. + */ + RocJpegStatus GetPlanarYUVOutputFormat(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, uint16_t chroma_height, RocJpegImage *destination); + + /** + * @brief Retrieves the output format for Y images. + * @param hip_interop The HIP interop device memory. + * @param picture_width The width of the picture. + * @param picture_height The height of the picture. + * @param destination Pointer to the destination image. + * @return The status of the operation. + */ + RocJpegStatus GetYOutputFormat(HipInteropDeviceMem& hip_interop, uint32_t picture_width, uint32_t picture_height, RocJpegImage *destination); + + int num_devices_; // Number of available devices + int device_id_; // ID of the device to be used + hipDeviceProp_t hip_dev_prop_; // HIP device properties + hipStream_t hip_stream_; // HIP stream + std::mutex mutex_; // Mutex for thread safety + RocJpegBackend backend_; // RocJpeg backend + RocJpegVappiDecoder jpeg_vaapi_decoder_; // RocJpeg VAAPI decoder object }; #endif //ROC_JPEG_DECODER_H_ \ No newline at end of file diff --git a/src/rocjpeg_hip_kernels.cpp b/src/rocjpeg_hip_kernels.cpp index 9b305b66c2..127a7de348 100644 --- a/src/rocjpeg_hip_kernels.cpp +++ b/src/rocjpeg_hip_kernels.cpp @@ -221,6 +221,20 @@ __global__ void ColorConvertYUV444ToRGBKernel(uint32_t dst_width, uint32_t dst_h } } +/** + * @brief Converts YUV444 image to RGB image. + * + * This function takes a YUV444 image and converts it to an RGB image using the ColorConvertYUV444ToRGBKernel HIP kernel. + * + * @param stream The HIP stream used for asynchronous execution of the kernel. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image Pointer to the destination RGB image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image buffer. + * @param src_yuv_image Pointer to the source YUV444 image buffer. + * @param src_yuv_image_stride_in_bytes The stride (in bytes) of the source YUV444 image buffer. + * @param src_u_image_offset The offset (in bytes) to the U component in the source YUV444 image buffer. + */ void ColorConvertYUV444ToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_yuv_image, uint32_t src_yuv_image_stride_in_bytes, uint32_t src_u_image_offset) { @@ -435,6 +449,22 @@ __global__ void ColorConvertYUV444ToRGBPlanarKernel(uint32_t dst_width, uint32_t } +/** + * @brief Converts YUV444 image to RGB planar format. + * + * This function takes a YUV444 image and converts it to RGB planar format using the ColorConvertYUV444ToRGBPlanarKernel HIP kernel. + * + * @param stream The HIP stream to be used for the kernel launch. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image_r Pointer to the destination red channel image. + * @param dst_image_g Pointer to the destination green channel image. + * @param dst_image_b Pointer to the destination blue channel image. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination image. + * @param src_yuv_image Pointer to the source YUV image. + * @param src_yuv_image_stride_in_bytes The stride (in bytes) of the source YUV image. + * @param src_u_image_offset The offset (in bytes) to the U channel in the source YUV image. + */ void ColorConvertYUV444ToRGBPlanar(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image_r, uint8_t *dst_image_g, uint8_t *dst_image_b, uint32_t dst_image_stride_in_bytes, const uint8_t *src_yuv_image, uint32_t src_yuv_image_stride_in_bytes, uint32_t src_u_image_offset) { @@ -639,6 +669,19 @@ __global__ void ColorConvertYUYVToRGBKernel(uint32_t dst_width, uint32_t dst_hei } } +/** + * @brief Converts YUYV image format to RGB image format. + * + * This function takes a YUYV image and converts it to RGB image format using ColorConvertYUYVToRGBKernel HIP kernel + * + * @param stream The HIP stream to associate the kernel launch with. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image Pointer to the destination RGB image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image buffer. + * @param src_image Pointer to the source YUYV image buffer. + * @param src_image_stride_in_bytes The stride (in bytes) of the source YUYV image buffer. + */ void ColorConvertYUYVToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes) { @@ -860,6 +903,26 @@ __global__ void ColorConvertYUYVToRGBPlanarKernel(uint32_t dst_width, uint32_t d } } +/** + * @brief Converts YUYV image format to RGB planar image format. + * + * This function takes a YUYV image and converts it to RGB planar image format + * using ColorConvertYUYVToRGBPlanarKernel HIP kernel. + * The YUYV image is represented as a packed format where each pixel consists of + * one luminance (Y) component and two chrominance (U and V) components. The RGB + * planar image format represents each color component (R, G, and B) in separate + * planes. + * + * @param stream The HIP stream to execute the kernel on. + * @param dst_width The width of the destination RGB planar image. + * @param dst_height The height of the destination RGB planar image. + * @param dst_image_r Pointer to the destination red (R) component image plane. + * @param dst_image_g Pointer to the destination green (G) component image plane. + * @param dst_image_b Pointer to the destination blue (B) component image plane. + * @param dst_image_stride_in_bytes The stride (in bytes) between consecutive rows of the destination image. + * @param src_image Pointer to the source YUYV image. + * @param src_image_stride_in_bytes The stride (in bytes) between consecutive rows of the source image. + */ void ColorConvertYUYVToRGBPlanar(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image_r, uint8_t *dst_image_g, uint8_t *dst_image_b, uint32_t dst_image_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes) { @@ -1081,6 +1144,21 @@ __global__ void ColorConvertNV12ToRGBKernel(uint32_t dst_width, uint32_t dst_hei } } +/** + * @brief Converts an NV12 image to RGB format. + * + * This function takes an NV12 image and converts it to RGB format using the ColorConvertNV12ToRGBKernel HIP kernel. + * + * @param stream The CUDA stream to use for the kernel execution. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image Pointer to the destination RGB image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image buffer. + * @param src_luma_image Pointer to the source luma (Y) image buffer. + * @param src_luma_image_stride_in_bytes The stride (in bytes) of the source luma (Y) image buffer. + * @param src_chroma_image Pointer to the source chroma (UV) image buffer. + * @param src_chroma_image_stride_in_bytes The stride (in bytes) of the source chroma (UV) image buffer. + */ void ColorConvertNV12ToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_luma_image, uint32_t src_luma_image_stride_in_bytes, @@ -1322,6 +1400,24 @@ __global__ void ColorConvertNV12ToRGBPlanarKernel(uint32_t dst_width, uint32_t d } } +/** + * @brief Converts an NV12 image to RGB planar format. + * + * This function takes an NV12 image and converts it to RGB planar format using the ColorConvertNV12ToRGBPlanarKernel HIP kernel. + * The resulting RGB planar image is stored in separate R, G, and B channels. + * + * @param stream The HIP stream to use for the kernel execution. + * @param dst_width The width of the destination RGB planar image. + * @param dst_height The height of the destination RGB planar image. + * @param dst_image_r Pointer to the destination R channel of the RGB planar image. + * @param dst_image_g Pointer to the destination G channel of the RGB planar image. + * @param dst_image_b Pointer to the destination B channel of the RGB planar image. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB planar image. + * @param src_luma_image Pointer to the source luma (Y) channel of the NV12 image. + * @param src_luma_image_stride_in_bytes The stride (in bytes) of the source luma (Y) channel. + * @param src_chroma_image Pointer to the source chroma (UV) channel of the NV12 image. + * @param src_chroma_image_stride_in_bytes The stride (in bytes) of the source chroma (UV) channel. + */ void ColorConvertNV12ToRGBPlanar(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image_r, uint8_t *dst_image_g, uint8_t *dst_image_b, uint32_t dst_image_stride_in_bytes, const uint8_t *src_luma_image, uint32_t src_luma_image_stride_in_bytes, @@ -1404,6 +1500,19 @@ __global__ void ColorConvertYUV400ToRGBKernel(uint32_t dst_width, uint32_t dst_h } } +/** + * @brief Converts a YUV400 image to RGB format. + * + * This function takes a YUV400 image and converts it to RGB format using the ColorConvertYUV400ToRGBKernel HIP kernel. + * + * @param stream The HIP stream to be used for the kernel execution. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image Pointer to the destination RGB image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image buffer. + * @param src_luma_image Pointer to the source YUV400 luma image buffer. + * @param src_luma_image_stride_in_bytes The stride (in bytes) of the source YUV400 luma image buffer. + */ void ColorConvertYUV400ToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_luma_image, uint32_t src_luma_image_stride_in_bytes){ @@ -1452,6 +1561,21 @@ __global__ void ColorConvertYUV400ToRGBPlanarKernel(uint32_t dst_width, uint32_t } } +/** + * @brief Converts a YUV400 image to RGB planar format. + * + * This function takes a YUV400 image and converts it to RGB planar format using the ColorConvertYUV400ToRGBPlanarKernel HIP kernel. + * + * @param stream The HIP stream on which the kernel function will be executed. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image_r Pointer to the destination red channel image. + * @param dst_image_g Pointer to the destination green channel image. + * @param dst_image_b Pointer to the destination blue channel image. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination image. + * @param src_luma_image Pointer to the source YUV400 luma image. + * @param src_luma_image_stride_in_bytes The stride (in bytes) of the source luma image. + */ void ColorConvertYUV400ToRGBPlanar(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image_r, uint8_t *dst_image_g, uint8_t *dst_image_b, uint32_t dst_image_stride_in_bytes, const uint8_t *src_luma_image, uint32_t src_luma_image_stride_in_bytes) { @@ -1499,6 +1623,19 @@ __global__ void ColorConvertRGBAToRGBKernel(uint32_t dst_width, uint32_t dst_hei *((DUINT6 *)(&dst_image[dst_idx])) = dst; } +/** + * @brief Converts an RGBA image to an RGB image. + * + * This function takes an RGBA image and converts it to an RGB image using the ColorConvertRGBAToRGBKernel HIP kernel + * + * @param stream The HIP stream to execute the kernel on. + * @param dst_width The width of the destination image. + * @param dst_height The height of the destination image. + * @param dst_image Pointer to the destination image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination image buffer. + * @param src_image Pointer to the source image buffer. + * @param src_image_stride_in_bytes The stride (in bytes) of the source image buffer. + */ void ColorConvertRGBAToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes) { int localThreads_x = 16; @@ -1537,6 +1674,21 @@ __global__ void ConvertInterleavedUVToPlanarUVKernel(uint32_t dst_width, uint32_ *((uint2 *)(&dst_image2[dst_idx])) = dst2; } +/** + * @brief Converts interleaved UV data to planar UV data. + * + * This function takes interleaved UV data and converts it to planar UV data + * using the ConvertInterleavedUVToPlanarUVKernel HIP kernel. + * + * @param stream The HIP stream to use for the kernel execution. + * @param dst_width The width of the destination image. + * @param dst_height The height of the destination image. + * @param dst_image1 Pointer to the destination image buffer for the first plane. + * @param dst_image2 Pointer to the destination image buffer for the second plane. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination image buffer. + * @param src_image1 Pointer to the source image buffer containing interleaved UV data. + * @param src_image1_stride_in_bytes The stride (in bytes) of the source image buffer. + */ void ConvertInterleavedUVToPlanarUV(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image1, uint8_t *dst_image2, uint32_t dst_image_stride_in_bytes, const uint8_t *src_image1, uint32_t src_image1_stride_in_bytes) { @@ -1571,6 +1723,21 @@ __global__ void ExtractYFromPackedYUYVKernel(uint32_t dst_width, uint32_t dst_he } } +/** + * @brief Extracts the Y component from a packed YUYV image and stores it in a separate buffer. + * + * This function takes a packed YUYV image and extracts the Y component (luma) from it. The extracted Y component is then + * stored in a separate buffer. The function operates on the GPU using HIP + * and requires a HIP stream for asynchronous execution. + * + * @param stream The HIP stream to be used for the kernel execution. + * @param dst_width The width of the destination buffer (in pixels). + * @param dst_height The height of the destination buffer (in pixels). + * @param destination_y Pointer to the destination buffer where the extracted Y component will be stored. + * @param dst_luma_stride_in_bytes The stride (in bytes) of the destination buffer. + * @param src_image Pointer to the source packed YUYV image. + * @param src_image_stride_in_bytes The stride (in bytes) of the source image. + */ void ExtractYFromPackedYUYV(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *destination_y, uint32_t dst_luma_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes) { int32_t local_threads_x = 16; @@ -1613,6 +1780,25 @@ __global__ void ConvertPackedYUYVToPlanarYUVKernel(uint32_t dst_width, uint32_t } } +/** + * @brief Converts a packed YUYV image to planar YUV format. + * + * This function takes a packed YUYV image and converts it to planar YUV format + * using the ConvertPackedYUYVToPlanarYUVKernel HIP kernel. + * The packed YUYV image consists of interleaved Y, U, Y, V samples, while the + * planar YUV format separates the Y, U, and V samples into separate planes. + * + * @param stream The HIP stream to associate the kernel launch with. + * @param dst_width The width of the destination image in pixels. + * @param dst_height The height of the destination image in pixels. + * @param destination_y Pointer to the destination Y plane. + * @param destination_u Pointer to the destination U plane. + * @param destination_v Pointer to the destination V plane. + * @param dst_luma_stride_in_bytes The stride (in bytes) of the destination luma plane. + * @param dst_chroma_stride_in_bytes The stride (in bytes) of the destination chroma planes. + * @param src_image Pointer to the source packed YUYV image. + * @param src_image_stride_in_bytes The stride (in bytes) of the source image. + */ void ConvertPackedYUYVToPlanarYUV(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *destination_y, uint8_t *destination_u, uint8_t *destination_v, uint32_t dst_luma_stride_in_bytes, uint32_t dst_chroma_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes) { diff --git a/src/rocjpeg_hip_kernels.h b/src/rocjpeg_hip_kernels.h index 9b3407be00..388f8293d8 100644 --- a/src/rocjpeg_hip_kernels.h +++ b/src/rocjpeg_hip_kernels.h @@ -27,27 +27,115 @@ THE SOFTWARE. #include +/** + * @brief Converts YUV444 image to RGB image. + * + * This function takes a YUV444 image and converts it to an RGB image. + * + * @param stream The HIP stream to be used for the conversion. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image Pointer to the destination RGB image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image buffer. + * @param src_yuv_image Pointer to the source YUV444 image buffer. + * @param src_yuv_image_stride_in_bytes The stride (in bytes) of the source YUV444 image buffer. + * @param src_u_image_offset The offset (in bytes) of the U component in the source YUV444 image buffer. + */ void ColorConvertYUV444ToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_yuv_image, uint32_t src_yuv_image_stride_in_bytes, uint32_t src_u_image_offset); +/** + * @brief Converts an image in YUYV format to RGB format. + * + * This function takes an image in YUYV format and converts it to RGB format. + * The converted image is stored in the destination buffer. + * + * @param stream The HIP stream to be used for the conversion. + * @param dst_width The width of the destination image in pixels. + * @param dst_height The height of the destination image in pixels. + * @param dst_image Pointer to the destination image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination image buffer. + * @param src_image Pointer to the source image buffer in YUYV format. + * @param src_image_stride_in_bytes The stride (in bytes) of the source image buffer. + */ void ColorConvertYUYVToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes); +/** + * @brief Converts an NV12 image to RGB format. + * + * This function takes an NV12 image, consisting of a luma (Y) plane and a chroma (UV) plane, + * and converts it to RGB format. The resulting RGB image is stored in the destination image buffer. + * + * @param stream The HIP stream to be used for the conversion. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image Pointer to the destination RGB image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image buffer. + * @param src_luma_image Pointer to the source luma (Y) plane of the NV12 image. + * @param src_luma_image_stride_in_bytes The stride (in bytes) of the source luma (Y) plane. + * @param src_chroma_image Pointer to the source chroma (UV) plane of the NV12 image. + * @param src_chroma_image_stride_in_bytes The stride (in bytes) of the source chroma (UV) plane. + */ void ColorConvertNV12ToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_luma_image, uint32_t src_luma_image_stride_in_bytes, const uint8_t *src_chroma_image, uint32_t src_chroma_image_stride_in_bytes); +/** + * @brief Converts a YUV400 image to RGB format. + * + * This function converts a YUV400 image to RGB format using the specified stream and parameters. + * + * @param stream The HIP stream to be used for the conversion. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image Pointer to the destination RGB image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image buffer. + * @param src_luma_image Pointer to the source YUV400 luma image buffer. + * @param src_luma_image_stride_in_bytes The stride (in bytes) of the source YUV400 luma image buffer. + */ void ColorConvertYUV400ToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_luma_image, uint32_t src_luma_image_stride_in_bytes); +/** + * @brief Converts an RGBA image to an RGB image. + * + * This function takes an input RGBA image and converts it to an output RGB image. + * The conversion is performed in parallel using the HIP framework. + * + * @param stream The HIP stream to be used for the conversion. + * @param dst_width The width of the output RGB image. + * @param dst_height The height of the output RGB image. + * @param dst_image Pointer to the output RGB image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the output RGB image buffer. + * @param src_image Pointer to the input RGBA image buffer. + * @param src_image_stride_in_bytes The stride (in bytes) of the input RGBA image buffer. + */ void ColorConvertRGBAToRGB(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image, uint32_t dst_image_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes); +/** + * @brief Converts YUV444 image to RGB planar format. + * + * This function takes a YUV444 image and converts it to RGB planar format. + * The resulting RGB image is stored in separate R, G, and B planes. + * + * @param stream The HIP stream to be used for the kernel execution. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image_r Pointer to the destination R plane of the RGB image. + * @param dst_image_g Pointer to the destination G plane of the RGB image. + * @param dst_image_b Pointer to the destination B plane of the RGB image. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image. + * @param src_yuv_image Pointer to the source YUV444 image. + * @param src_yuv_image_stride_in_bytes The stride (in bytes) of the source YUV444 image. + * @param src_u_image_offset The offset (in bytes) of the U plane in the source YUV444 image. + */ void ColorConvertYUV444ToRGBPlanar(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image_r, uint8_t *dst_image_g, uint8_t *dst_image_b, uint32_t dst_image_stride_in_bytes, const uint8_t *src_yuv_image, uint32_t src_yuv_image_stride_in_bytes, uint32_t src_u_image_offset); @@ -56,30 +144,124 @@ void ColorConvertYUYVToRGBPlanar(hipStream_t stream, uint32_t dst_width, uint32_ uint8_t *dst_image_r, uint8_t *dst_image_g, uint8_t *dst_image_b, uint32_t dst_image_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes); +/** + * @brief Converts an NV12 image to RGB planar format. + * + * This function takes an NV12 image and converts it to RGB planar format. The NV12 image consists of a luma (Y) plane followed by a packed chroma (UV) plane. + * The RGB planar format consists of separate R, G, and B planes. + * + * @param stream The HIP stream to be used for the conversion. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image_r Pointer to the destination R plane. + * @param dst_image_g Pointer to the destination G plane. + * @param dst_image_b Pointer to the destination B plane. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination RGB image. + * @param src_luma_image Pointer to the source luma (Y) plane. + * @param src_luma_image_stride_in_bytes The stride (in bytes) of the source luma (Y) plane. + * @param src_chroma_image Pointer to the source chroma (UV) plane. + * @param src_chroma_image_stride_in_bytes The stride (in bytes) of the source chroma (UV) plane. + */ void ColorConvertNV12ToRGBPlanar(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image_r, uint8_t *dst_image_g, uint8_t *dst_image_b, uint32_t dst_image_stride_in_bytes, const uint8_t *src_luma_image, uint32_t src_luma_image_stride_in_bytes, const uint8_t *src_chroma_image, uint32_t src_chroma_image_stride_in_bytes); +/** + * @brief Converts a YUV400 image to RGB planar format. + * + * This function takes a YUV400 image and converts it to RGB planar format. + * The resulting RGB image will have separate planes for red, green, and blue channels. + * + * @param stream The HIP stream to be used for the kernel execution. + * @param dst_width The width of the destination RGB image. + * @param dst_height The height of the destination RGB image. + * @param dst_image_r Pointer to the destination red channel plane. + * @param dst_image_g Pointer to the destination green channel plane. + * @param dst_image_b Pointer to the destination blue channel plane. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination image planes. + * @param src_luma_image Pointer to the source YUV400 luma image. + * @param src_luma_image_stride_in_bytes The stride (in bytes) of the source luma image. + */ void ColorConvertYUV400ToRGBPlanar(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image_r, uint8_t *dst_image_g, uint8_t *dst_image_b, uint32_t dst_image_stride_in_bytes, const uint8_t *src_luma_image, uint32_t src_luma_image_stride_in_bytes); +/** + * @brief Converts interleaved UV data to planar UV data. + * + * This function takes interleaved UV data from the source image and converts it to planar UV data, + * which is then stored in the destination images. The conversion is performed on the GPU using + * the specified stream. + * + * @param stream The HIP stream to be used for the conversion. + * @param dst_width The width of the destination images. + * @param dst_height The height of the destination images. + * @param dst_image1 Pointer to the first destination image buffer. + * @param dst_image2 Pointer to the second destination image buffer. + * @param dst_image_stride_in_bytes The stride (in bytes) of the destination image buffers. + * @param src_image1 Pointer to the source image buffer containing interleaved UV data. + * @param src_image1_stride_in_bytes The stride (in bytes) of the source image buffer. + */ void ConvertInterleavedUVToPlanarUV(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *dst_image1, uint8_t *dst_image2, uint32_t dst_image_stride_in_bytes, const uint8_t *src_image1, uint32_t src_image1_stride_in_bytes); +/** + * @brief Extracts the Y component from a packed YUYV image and stores it in a separate buffer. + * + * This function takes a packed YUYV image and extracts the Y component (luma) from it. The extracted Y component + * is then stored in a separate buffer. The dimensions of the destination buffer, as well as the stride of the + * source and destination buffers, should be provided. + * + * @param stream The HIP stream to be used for the operation. + * @param dst_width The width of the destination buffer. + * @param dst_height The height of the destination buffer. + * @param destination_y Pointer to the destination buffer where the extracted Y component will be stored. + * @param dst_luma_stride_in_bytes The stride (in bytes) of the destination buffer. + * @param src_image Pointer to the source YUYV image. + * @param src_image_stride_in_bytes The stride (in bytes) of the source YUYV image. + */ void ExtractYFromPackedYUYV(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *destination_y, uint32_t dst_luma_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes); +/** + * @brief Converts a packed YUYV image to planar YUV format. + * + * This function takes a packed YUYV image and converts it to planar YUV format. + * The resulting planar YUV image will have separate planes for Y, U, and V components. + * + * @param stream The HIP stream to associate the kernel execution with. + * @param dst_width The width of the destination image in pixels. + * @param dst_height The height of the destination image in pixels. + * @param destination_y Pointer to the destination Y plane. + * @param destination_u Pointer to the destination U plane. + * @param destination_v Pointer to the destination V plane. + * @param dst_luma_stride_in_bytes The stride (in bytes) between consecutive rows of the destination Y plane. + * @param dst_chroma_stride_in_bytes The stride (in bytes) between consecutive rows of the destination U and V planes. + * @param src_image Pointer to the source packed YUYV image. + * @param src_image_stride_in_bytes The stride (in bytes) between consecutive rows of the source image. + */ void ConvertPackedYUYVToPlanarYUV(hipStream_t stream, uint32_t dst_width, uint32_t dst_height, uint8_t *destination_y, uint8_t *destination_u, uint8_t *destination_v, uint32_t dst_luma_stride_in_bytes, uint32_t dst_chroma_stride_in_bytes, const uint8_t *src_image, uint32_t src_image_stride_in_bytes); +/** + * @brief Structure representing an array of 6 unsigned integers. + * + * This structure is used to store an array of 6 unsigned integers. + * The `data` member is an array of size 6 that holds the integer values. + */ typedef struct UINT6TYPE { uint data[6]; } DUINT6; +/** + * @brief Represents a struct that holds an array of 8 unsigned integers. + * + * This struct is used to store an array of 8 unsigned integers in the `data` member. + * It is typically used in the context of the `rocjpeg_hip_kernels` module. + */ typedef struct UINT8TYPE { uint data[8]; } DUINT8; diff --git a/src/rocjpeg_parser.cpp b/src/rocjpeg_parser.cpp index 3ecc1e8dac..8239d6d10c 100644 --- a/src/rocjpeg_parser.cpp +++ b/src/rocjpeg_parser.cpp @@ -31,6 +31,15 @@ RocJpegStreamParser::~RocJpegStreamParser() { stream_length_ = 0; } +/** + * @brief Parses a JPEG stream. + * + * This function parses a JPEG stream and extracts various markers and parameters from it. + * + * @param jpeg_stream A pointer to the JPEG stream. + * @param jpeg_stream_size The size of the JPEG stream in bytes. + * @return True if the JPEG stream was successfully parsed, false otherwise. + */ bool RocJpegStreamParser::ParseJpegStream(const uint8_t *jpeg_stream, uint32_t jpeg_stream_size) { std::lock_guard lock(mutex_); if (jpeg_stream == nullptr) { @@ -114,6 +123,13 @@ bool RocJpegStreamParser::ParseJpegStream(const uint8_t *jpeg_stream, uint32_t j return true; } +/** + * @brief Parses the Start of Image (SOI) marker in the JPEG stream. + * + * This function searches for the SOI marker (0xFFD8) in the JPEG stream and updates the stream pointer accordingly. + * + * @return true if the SOI marker is found and the stream pointer is updated, false otherwise. + */ bool RocJpegStreamParser::ParseSOI() { if (stream_ == nullptr) { return false; @@ -130,6 +146,17 @@ bool RocJpegStreamParser::ParseSOI() { return true; } +/** + * @brief Parses the Start of Frame (SOF) marker in the JPEG stream. + * + * This function reads and processes the SOF marker in the JPEG stream. It extracts + * information such as picture height, picture width, number of components, component + * IDs, sampling factors, and quantization table selectors. It also calculates the + * number of MCU (Minimum Coded Unit) blocks in the image and determines the chroma + * subsampling scheme. + * + * @return true if the SOF marker is successfully parsed, false otherwise. + */ bool RocJpegStreamParser::ParseSOF() { uint32_t component_id, sampling_factor; uint8_t quantiser_table_selector; @@ -179,6 +206,14 @@ bool RocJpegStreamParser::ParseSOF() { return true; } +/** + * @brief Parses the DQT (Define Quantization Table) segment of a JPEG stream. + * + * This function reads the quantization tables from the JPEG stream and stores them in the + * `jpeg_stream_parameters_.quantization_matrix_buffer` data structure. + * + * @return `true` if the DQT segment is successfully parsed, `false` otherwise. + */ bool RocJpegStreamParser::ParseDQT() { int32_t quantization_table_index = 0; const uint8_t *dqt_block_end; @@ -210,6 +245,14 @@ bool RocJpegStreamParser::ParseDQT() { return true; } +/** + * @brief Parses the Define Huffman Table (DHT) segment in the JPEG stream. + * + * This function reads and processes the DHT segment in the JPEG stream. It extracts the Huffman table + * information and stores it in the `jpeg_stream_parameters_.huffman_table_buffer` data structure. + * + * @return `true` if the DHT segment is successfully parsed, `false` otherwise. + */ bool RocJpegStreamParser::ParseDHT() { uint32_t count, i; int32_t length, index; @@ -269,6 +312,15 @@ bool RocJpegStreamParser::ParseDHT() { return true; } +/** + * @brief Parses the Start of Scan (SOS) marker in the JPEG stream. + * + * This function reads and processes the SOS marker in the JPEG stream. + * It extracts the component IDs and Huffman table selectors for each component, + * and performs various checks for validity. + * + * @return true if the SOS marker is successfully parsed, false otherwise. + */ bool RocJpegStreamParser::ParseSOS() { uint32_t component_id, table; @@ -311,6 +363,14 @@ bool RocJpegStreamParser::ParseSOS() { } +/** + * @brief Parses the Define Restart Interval (DRI) marker in the JPEG stream. + * + * This function reads the length field of the DRI marker and checks if it is valid. + * If the length is valid, it updates the restart interval value in the slice parameter buffer. + * + * @return true if the DRI marker is successfully parsed, false otherwise. + */ bool RocJpegStreamParser::ParseDRI() { uint32_t length; @@ -329,6 +389,14 @@ bool RocJpegStreamParser::ParseDRI() { return true; } +/** + * @brief Parses the End of Image (EOI) marker in the JPEG stream. + * + * This function searches for the EOI marker in the JPEG stream and updates the slice data buffer + * and slice data size in the jpeg_stream_parameters_ structure. + * + * @return true if the EOI marker is found and the slice data buffer is updated successfully, false otherwise. + */ bool RocJpegStreamParser::ParseEOI() { if (stream_ == nullptr) { @@ -347,6 +415,20 @@ bool RocJpegStreamParser::ParseEOI() { return true; } +/** + * @brief Determines the chroma subsampling format based on the given sampling factors. + * + * This function takes the horizontal and vertical sampling factors for each color component and determines + * the chroma subsampling format. It returns the corresponding `ChromaSubsampling` enum value. + * + * @param c1_h_sampling_factor The horizontal sampling factor for color component 1. + * @param c2_h_sampling_factor The horizontal sampling factor for color component 2. + * @param c3_h_sampling_factor The horizontal sampling factor for color component 3. + * @param c1_v_sampling_factor The vertical sampling factor for color component 1. + * @param c2_v_sampling_factor The vertical sampling factor for color component 2. + * @param c3_v_sampling_factor The vertical sampling factor for color component 3. + * @return The chroma subsampling format determined based on the given sampling factors. + */ ChromaSubsampling RocJpegStreamParser::GetChromaSubsampling(uint8_t c1_h_sampling_factor, uint8_t c2_h_sampling_factor, uint8_t c3_h_sampling_factor, uint8_t c1_v_sampling_factor, uint8_t c2_v_sampling_factor, uint8_t c3_v_sampling_factor) { diff --git a/src/rocjpeg_parser.h b/src/rocjpeg_parser.h index 612bb1f194..0a827519c6 100644 --- a/src/rocjpeg_parser.h +++ b/src/rocjpeg_parser.h @@ -38,98 +38,113 @@ THE SOFTWARE. #define DC_HUFFMAN_TABLE_VALUES_SIZE 12 #define swap_bytes(x) (((x)[0] << 8) | (x)[1]) -/***************************************************************/ -//! \enum enum JpegMarker -//! common JPEG markers -/***************************************************************/ +/** + * @brief Enumeration representing the common JPEG markers. + * + * The `JpegMarkers` enum defines the common JPEG markers used in a JPEG stream. + */ enum JpegMarkers { - SOI = 0xD8, /* Start Of Image */ - SOF = 0xC0, /* Start Of Frame for a baseline DCT-based JPEG. */ - DHT = 0xC4, /* Define Huffman Table */ - DQT = 0xDB, /* Define Quantization Table */ - DRI = 0xDD, /* Define Restart Interval */ - SOS = 0xDA, /* Start of Scan */ - EOI = 0xD9, /* End Of Image */ + SOI = 0xD8, /**< Start Of Image */ + SOF = 0xC0, /**< Start Of Frame for a baseline DCT-based JPEG. */ + DHT = 0xC4, /**< Define Huffman Table */ + DQT = 0xDB, /**< Define Quantization Table */ + DRI = 0xDD, /**< Define Restart Interval */ + SOS = 0xDA, /**< Start of Scan */ + EOI = 0xD9, /**< End Of Image */ }; -/***************************************************************/ -//! \struct Picture parameter for JPEG decoding. -//! This structure holds information from the frame -//! header and definitions from additional segments. - /**************************************************************/ +/** + * @brief Structure representing the picture parameter buffer. + * + * This structure contains information about the picture width, picture height, + * color components, color space, rotation, and reserved fields. + */ typedef struct PictureParameterBufferType { - uint16_t picture_width; - uint16_t picture_height; + uint16_t picture_width; /**< The width of the picture. */ + uint16_t picture_height; /**< The height of the picture. */ struct { - uint8_t component_id; - uint8_t h_sampling_factor; - uint8_t v_sampling_factor; - uint8_t quantiser_table_selector; - } components[255]; - uint8_t num_components; - uint8_t color_space; - uint32_t rotation; - uint32_t reserved[7]; + uint8_t component_id; /**< The ID of the color component. */ + uint8_t h_sampling_factor; /**< The horizontal sampling factor. */ + uint8_t v_sampling_factor; /**< The vertical sampling factor. */ + uint8_t quantiser_table_selector; /**< The quantiser table selector. */ + } components[255]; /**< Array of color components. */ + uint8_t num_components; /**< The number of color components. */ + uint8_t color_space; /**< The color space of the picture. */ + uint32_t rotation; /**< The rotation of the picture. */ + uint32_t reserved[7]; /**< Reserved fields. */ } PictureParameterBuffer; -/***************************************************************/ -//! \struct Quantization table for JPEG decoding. -//! This structure holds the quantization tables. -//! The maximum number of quatization tables is four. -//! The #load_quantization_table array can be used as a hint to notify -//! which table(s) has valid values. -//! The #quantiser_table values are specified in zig-zag scan order. -/***************************************************************/ +/** + * @brief Structure representing the quantization matrix buffer. + * + * This structure holds the quantization tables used in the JPEG decoding process. + * It consists of an array to indicate whether a quantization table is loaded or not, + * a 2D array to store the quantization tables, and a reserved field. + */ typedef struct QuantizationMatrixBufferType { - uint8_t load_quantiser_table[4]; - uint8_t quantiser_table[4][64]; - uint32_t reserved[4]; + uint8_t load_quantiser_table[4]; /**< Array indicating whether a quantization table is loaded or not. */ + uint8_t quantiser_table[4][64]; /**< 2D array to store the quantization tables. */ + uint32_t reserved[4]; /**< Reserved field. */ } QuantizationMatrixBuffer; -/***************************************************************/ -//! \struct Huffman table for JPEG decoding. -//! This structure holds the Huffman tables. -//! The maximum number of Huffman tables is two. -//! The #load_huffman_table array can be used as a hint to notify the -//! which table(s) has valid values. -/***************************************************************/ +/** + * @brief Struct representing a buffer for Huffman tables. + * + * This struct is used to store Huffman tables for JPEG decoding. + * It contains two sets of Huffman tables, each consisting of + * arrays for the number of DC codes, DC values, number of AC codes, + * AC values, and padding. + * + * The `load_huffman_table` array is used to indicate whether a + * particular Huffman table should be loaded or not. + * + * The `reserved` array is used for future expansion and is currently + * unused. + */ typedef struct HuffmanTableBufferType { - uint8_t load_huffman_table[2]; + uint8_t load_huffman_table[2]; /**< Array indicating which Huffman tables to load. */ struct { - uint8_t num_dc_codes[16]; - uint8_t dc_values[12]; - uint8_t num_ac_codes[16]; - uint8_t ac_values[162]; - uint8_t pad[2]; - } huffman_table[2]; - uint32_t reserved[4]; + uint8_t num_dc_codes[16]; /**< Array of the number of DC codes for each bit length. */ + uint8_t dc_values[12]; /**< Array of the DC values. */ + uint8_t num_ac_codes[16]; /**< Array of the number of AC codes for each bit length. */ + uint8_t ac_values[162]; /**< Array of the AC values. */ + uint8_t pad[2]; /**< Padding to align the structure. */ + } huffman_table[2]; /**< Array of two sets of Huffman tables. */ + uint32_t reserved[4]; /**< Reserved field for future use. */ } HuffmanTableBuffer; -/***************************************************************/ -//! \struct Slice parameter for JPEG decoding. -//! This structure holds information from the scan header, and -//! definitions from additional segments. -/***************************************************************/ +/** + * @brief Structure representing the slice parameter buffer. + * + * This structure contains information about the slice data, such as its size, offset, and flag. + * It also includes the horizontal and vertical position of the slice, as well as the component, + * DC table, and AC table selectors for each component. The number of components, restart interval, + * number of MCUs, and reserved fields are also included. + */ typedef struct SliceParameterBufferType { - uint32_t slice_data_size; - uint32_t slice_data_offset; - uint32_t slice_data_flag; - uint32_t slice_horizontal_position; - uint32_t slice_vertical_position; + uint32_t slice_data_size; /**< Size of the slice data. */ + uint32_t slice_data_offset; /**< Offset of the slice data. */ + uint32_t slice_data_flag; /**< Flag indicating the slice data. */ + uint32_t slice_horizontal_position; /**< Horizontal position of the slice. */ + uint32_t slice_vertical_position; /**< Vertical position of the slice. */ struct { - uint8_t component_selector; - uint8_t dc_table_selector; - uint8_t ac_table_selector; - } components[4]; - uint8_t num_components; - uint16_t restart_interval; - uint32_t num_mcus; - uint32_t reserved[4]; + uint8_t component_selector; /**< Component selector. */ + uint8_t dc_table_selector; /**< DC table selector. */ + uint8_t ac_table_selector; /**< AC table selector. */ + } components[4]; /**< Array of component selectors. */ + uint8_t num_components; /**< Number of components. */ + uint16_t restart_interval; /**< Restart interval. */ + uint32_t num_mcus; /**< Number of MCUs. */ + uint32_t reserved[4]; /**< Reserved fields. */ } SliceParameterBuffer; -/***************************************************************/ -//! \struct Enum identifies image chroma subsampling values stored inside JPEG input stream -/***************************************************************/ +/** + * @brief Enumeration representing the chroma subsampling formats. + * + * The `ChromaSubsampling` enum defines the possible chroma subsampling formats in a JPEG stream. + * Each value corresponds to a specific chroma subsampling format, such as 4:4:4, 4:2:0, etc. + * The `CSS_UNKNOWN` value is used to indicate an unknown or unsupported format. + */ typedef enum { CSS_444 = 0, CSS_440 = 1, @@ -140,10 +155,13 @@ typedef enum { CSS_UNKNOWN = -1 } ChromaSubsampling; -/***************************************************************/ -//! \struct Jpeg stream parameters. -//! This structure holds all information from a JPEG stream for decoding -/***************************************************************/ +/** + * @brief Structure representing the parameters for a JPEG stream. + * + * This structure contains various buffers and data required for processing a JPEG stream. + * It includes the picture parameter buffer, quantization matrix buffer, Huffman table buffer, + * slice parameter buffer, chroma subsampling information, and the slice data buffer. + */ typedef struct JpegParameterBuffersType { PictureParameterBuffer picture_parameter_buffer; QuantizationMatrixBuffer quantization_matrix_buffer; @@ -153,27 +171,102 @@ typedef struct JpegParameterBuffersType { const uint8_t* slice_data_buffer; } JpegStreamParameters; +/** + * @class RocJpegStreamParser + * @brief A class for parsing JPEG streams and extracting stream parameters. + * + * The RocJpegStreamParser class provides functionality to parse a JPEG stream and extract various parameters + * such as Start of Image (SOI), Start of Frame (SOF), Quantization Tables (DQT), Start of Scan (SOS), + * Huffman Tables (DHT), Define Restart Interval (DRI), and End of Image (EOI). It also provides a method to + * retrieve the parsed JPEG stream parameters. + */ class RocJpegStreamParser { public: + /** + * @brief Default constructor for RocJpegStreamParser. + */ RocJpegStreamParser(); + + /** + * @brief Destructor for RocJpegStreamParser. + */ ~RocJpegStreamParser(); + + /** + * @brief Parses a JPEG stream and extracts stream parameters. + * @param jpeg_stream The pointer to the JPEG stream. + * @param jpeg_stream_size The size of the JPEG stream. + * @return True if the parsing is successful, false otherwise. + */ bool ParseJpegStream(const uint8_t* jpeg_stream, uint32_t jpeg_stream_size); - const JpegStreamParameters* GetJpegStreamParameters() const {return &jpeg_stream_parameters_;}; + + /** + * @brief Retrieves the JPEG stream parameters. + * @return A pointer to the JpegStreamParameters object. + */ + const JpegStreamParameters* GetJpegStreamParameters() const { return &jpeg_stream_parameters_; }; + private: + /** + * @brief Parses the Start of Image (SOI) marker. + * @return True if the SOI marker is successfully parsed, false otherwise. + */ bool ParseSOI(); + + /** + * @brief Parses the Start of Frame (SOF) marker. + * @return True if the SOF marker is successfully parsed, false otherwise. + */ bool ParseSOF(); + + /** + * @brief Parses the Define Quantization Table (DQT) marker. + * @return True if the DQT marker is successfully parsed, false otherwise. + */ bool ParseDQT(); + + /** + * @brief Parses the Start of Scan (SOS) marker. + * @return True if the SOS marker is successfully parsed, false otherwise. + */ bool ParseSOS(); + + /** + * @brief Parses the Define Huffman Table (DHT) marker. + * @return True if the DHT marker is successfully parsed, false otherwise. + */ bool ParseDHT(); + + /** + * @brief Parses the Define Restart Interval (DRI) marker. + * @return True if the DRI marker is successfully parsed, false otherwise. + */ bool ParseDRI(); + + /** + * @brief Parses the End of Image (EOI) marker. + * @return True if the EOI marker is successfully parsed, false otherwise. + */ bool ParseEOI(); + + /** + * @brief Retrieves the chroma subsampling information. + * @param c1_h_sampling_factor The horizontal sampling factor for component 1. + * @param c2_h_sampling_factor The horizontal sampling factor for component 2. + * @param c3_h_sampling_factor The horizontal sampling factor for component 3. + * @param c1_v_sampling_factor The vertical sampling factor for component 1. + * @param c2_v_sampling_factor The vertical sampling factor for component 2. + * @param c3_v_sampling_factor The vertical sampling factor for component 3. + * @return The chroma subsampling information. + */ ChromaSubsampling GetChromaSubsampling(uint8_t c1_h_sampling_factor, uint8_t c2_h_sampling_factor, uint8_t c3_h_sampling_factor, uint8_t c1_v_sampling_factor, uint8_t c2_v_sampling_factor, uint8_t c3_v_sampling_factor); - const uint8_t *stream_; - const uint8_t *stream_end_; - uint32_t stream_length_; - JpegStreamParameters jpeg_stream_parameters_; - std::mutex mutex_; + + const uint8_t *stream_; ///< Pointer to the JPEG stream. + const uint8_t *stream_end_; ///< Pointer to the end of the JPEG stream. + uint32_t stream_length_; ///< Length of the JPEG stream. + JpegStreamParameters jpeg_stream_parameters_; ///< JPEG stream parameters. + std::mutex mutex_; ///< Mutex for thread safety. }; #endif // ROC_JPEG_PARSER_H_ \ No newline at end of file diff --git a/src/rocjpeg_vaapi_decoder.cpp b/src/rocjpeg_vaapi_decoder.cpp index 6e4bd126c1..22e9d5de93 100644 --- a/src/rocjpeg_vaapi_decoder.cpp +++ b/src/rocjpeg_vaapi_decoder.cpp @@ -22,6 +22,15 @@ THE SOFTWARE. #include "rocjpeg_vaapi_decoder.h" +/** + * @brief Default constructor for RocJpegVappiMemoryPool class. + * + * This constructor initializes the memory pool for different surface formats used in RocJpegVappiDecoder. + * It creates an empty vector for each surface format and stores it in the mem_pool_ map. + * + * @param None + * @return None + */ RocJpegVappiMemoryPool::RocJpegVappiMemoryPool() { std::vector surface_formats = {VA_RT_FORMAT_RGB32, VA_RT_FORMAT_RGBP, VA_RT_FORMAT_YUV444, VA_RT_FORMAT_YUV422, VA_RT_FORMAT_YUV420, VA_RT_FORMAT_YUV400}; @@ -30,6 +39,15 @@ std::vector surface_formats = {VA_RT_FORMAT_RGB32, VA_RT_FORMAT_RGBP, } } +/** + * @brief Releases the resources used by the RocJpegVappiMemoryPool. + * + * This function releases the VA-API contexts, surfaces, HIP device memory, and HIP external memory + * associated with the memory pool. It iterates over each entry in the memory pool and checks if + * the VA-API context ID, VA-API surface ID, HIP mapped device memory, or HIP external memory is + * non-zero. If so, it destroys the corresponding resource using the appropriate API function. + * Finally, it resets the HIP interop structure for each entry in the memory pool. + */ void RocJpegVappiMemoryPool::ReleaseResources() { VAStatus va_status; hipError_t hip_status; @@ -74,6 +92,18 @@ void RocJpegVappiMemoryPool::SetVaapiDisplay(const VADisplay& va_display) { va_display_ = va_display; } +/** + * @brief Adds a pool entry to the memory pool for a specific surface format. + * + * This function adds a pool entry to the memory pool for a specific surface format. + * If the memory pool for the given surface format is not full, the new entry is added to the pool. + * If the memory pool is full, the oldest entry is removed from the pool and replaced with the new entry. + * If the removed entry has associated resources (VA context, VA surface, HIP memory), they are destroyed and freed. + * + * @param surface_format The surface format for which the pool entry is being added. + * @param pool_entry The pool entry to be added. + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if the operation is successful. + */ RocJpegStatus RocJpegVappiMemoryPool::AddPoolEntry(uint32_t surface_format, const RocJpegVappiMemPoolEntry& pool_entry) { auto& entires = mem_pool_[surface_format]; if (entires.size() < entires.capacity()) { @@ -100,6 +130,14 @@ RocJpegStatus RocJpegVappiMemoryPool::AddPoolEntry(uint32_t surface_format, cons return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Retrieves a `RocJpegVappiMemPoolEntry` from the memory pool based on the specified surface format, image width, and image height. + * + * @param surface_format The surface format of the entry to retrieve. + * @param image_width The width of the image of the entry to retrieve. + * @param image_height The height of the image of the entry to retrieve. + * @return The matching `RocJpegVappiMemPoolEntry` if found, or a default-initialized entry if not found. + */ RocJpegVappiMemPoolEntry RocJpegVappiMemoryPool::GetEntry(uint32_t surface_format, uint32_t image_width, uint32_t image_height) { for (const auto& entry : mem_pool_[surface_format]) { if (entry.image_width == image_width && entry.image_height == image_height) { @@ -120,6 +158,20 @@ bool RocJpegVappiMemoryPool::FindSurfaceId(VASurfaceID surface_id) { return false; } +/** + * @brief Deletes a surface ID from the memory pool. + * + * This function deletes the specified surface ID from the memory pool. It performs the following actions: + * 1. If the surface ID has a valid context ID, it destroys the context associated with the surface ID. + * 2. It destroys the surface ID itself. + * 3. If the surface ID has a valid HIP mapped device memory, it frees the memory. + * 4. If the surface ID has a valid HIP external memory, it destroys the memory. + * 5. It clears the HIP interop structure associated with the surface ID. + * 6. It removes the entry from the memory pool. + * + * @param surface_id The surface ID to be deleted. + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if the surface ID was successfully deleted. + */ RocJpegStatus RocJpegVappiMemoryPool::DeleteSurfaceId(VASurfaceID surface_id) { for (auto& pair : mem_pool_) { auto& entries = pair.second; @@ -149,6 +201,21 @@ RocJpegStatus RocJpegVappiMemoryPool::DeleteSurfaceId(VASurfaceID surface_id) { return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Retrieves the HipInteropDeviceMem associated with a given VASurfaceID from the memory pool. + * + * This function searches the memory pool for the entry that matches the provided VASurfaceID. + * If a matching entry is found and the associated HipInteropDeviceMem is not already initialized, + * it initializes the HipInteropDeviceMem by exporting the VASurfaceID as a DRM prime surface handle, + * importing it as an external memory object, and getting the mapped buffer for the external memory. + * The function then updates the HipInteropDeviceMem with the surface format, width, height, offsets, + * pitches, and number of layers from the exported surface descriptor. + * + * @param surface_id The VASurfaceID to retrieve the HipInteropDeviceMem for. + * @param hip_interop [out] The retrieved HipInteropDeviceMem. + * @return RocJpegStatus Returns ROCJPEG_STATUS_SUCCESS if the HipInteropDeviceMem is successfully retrieved, + * ROCJPEG_STATUS_INVALID_PARAMETER if the requested surface_id is not found in the memory pool. + */ RocJpegStatus RocJpegVappiMemoryPool::GetHipInteropMem(VASurfaceID surface_id, HipInteropDeviceMem& hip_interop) { for (auto& pair : mem_pool_) { auto& entries = pair.second; @@ -194,6 +261,13 @@ RocJpegStatus RocJpegVappiMemoryPool::GetHipInteropMem(VASurfaceID surface_id, H ERR("the surface_id: " + TOSTR(surface_id) + " was not found in the memory pool!"); return ROCJPEG_STATUS_INVALID_PARAMETER; } +/** + * @brief Constructs a RocJpegVappiDecoder object. + * + * This constructor initializes a RocJpegVappiDecoder object with the specified device ID and default values for other member variables. + * + * @param device_id The ID of the device to be used for decoding. + */ RocJpegVappiDecoder::RocJpegVappiDecoder(int device_id) : device_id_{device_id}, drm_fd_{-1}, min_picture_width_{64}, min_picture_height_{64}, max_picture_width_{4096}, max_picture_height_{4096}, va_display_{0}, va_config_attrib_{{}}, va_config_id_{0}, va_profile_{VAProfileJPEGBaseline}, vaapi_mem_pool_(std::make_unique()), current_vcn_jpeg_spec_{0}, va_picture_parameter_buf_id_{0}, va_quantization_matrix_buf_id_{0}, va_huffmantable_buf_id_{0}, @@ -209,8 +283,17 @@ RocJpegVappiDecoder::RocJpegVappiDecoder(int device_id) : device_id_{device_id}, {"gfx1100", {2, false, false}}, {"gfx1101", {1, false, false}}, {"gfx1102", {2, false, false}}}; - }; +}; +/** + * @brief Destructor for the RocJpegVappiDecoder class. + * + * This destructor is responsible for cleaning up the resources used by the RocJpegVappiDecoder object. + * It closes the DRM file descriptor, releases the VAAPI memory pool resources, destroys the VAAPI data buffers, + * destroys the VAAPI configuration, and terminates the VAAPI display. + * + * @note If any of the cleanup operations fail, an error message will be printed. + */ RocJpegVappiDecoder::~RocJpegVappiDecoder() { if (drm_fd_ != -1) { close(drm_fd_); @@ -236,6 +319,17 @@ RocJpegVappiDecoder::~RocJpegVappiDecoder() { } } +/** + * @brief Initializes the VAAPI decoder for RocJpeg. + * + * This function initializes the VAAPI decoder for RocJpeg by setting the device ID, GCN architecture name, + * and other necessary parameters. It also sets up the VAAPI display and creates the decoder configuration. + * + * @param device_name The name of the device. + * @param gcn_arch_name The name of the GCN architecture. + * @param device_id The ID of the device. + * @return The status of the initialization process. + */ RocJpegStatus RocJpegVappiDecoder::InitializeDecoder(std::string device_name, std::string gcn_arch_name, int device_id) { device_id_ = device_id; std::size_t pos = gcn_arch_name.find_first_of(":"); @@ -281,6 +375,17 @@ RocJpegStatus RocJpegVappiDecoder::InitializeDecoder(std::string device_name, st return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Initializes the VAAPI decoder. + * + * This function initializes the VAAPI decoder by opening the DRM node, creating the va_display, + * setting the info callback, and initializing the va_display. + * + * @param drm_node The path to the DRM node. + * @return The status of the initialization process. + * - ROCJPEG_STATUS_SUCCESS if the initialization is successful. + * - ROCJPEG_STATUS_NOT_INITIALIZED if the initialization fails. + */ RocJpegStatus RocJpegVappiDecoder::InitVAAPI(std::string drm_node) { drm_fd_ = open(drm_node.c_str(), O_RDWR); if (drm_fd_ < 0) { @@ -298,6 +403,17 @@ RocJpegStatus RocJpegVappiDecoder::InitVAAPI(std::string drm_node) { return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Creates the decoder configuration for the RocJpegVappiDecoder. + * + * This function creates the decoder configuration by querying the VA API for supported entrypoints + * and checking if the hardware JPEG decoder is supported. If the hardware JPEG decoder is supported, + * it retrieves the maximum picture width and height attributes from the VA API and creates the configuration. + * + * @return The status of the decoder configuration creation. + * - ROCJPEG_STATUS_SUCCESS if the configuration is created successfully. + * - ROCJPEG_STATUS_HW_JPEG_DECODER_NOT_SUPPORTED if the hardware JPEG decoder is not supported. + */ RocJpegStatus RocJpegVappiDecoder::CreateDecoderConfig() { int max_num_entrypoints = vaMaxNumEntrypoints(va_display_); std::vector jpeg_entrypoint_list; @@ -335,6 +451,14 @@ RocJpegStatus RocJpegVappiDecoder::CreateDecoderConfig() { } } +/** + * @brief Destroys the data buffers used by the RocJpegVappiDecoder. + * + * This function destroys the data buffers used by the RocJpegVappiDecoder, including the picture parameter buffer, + * quantization matrix buffer, Huffman table buffer, slice parameter buffer, and slice data buffer. + * + * @return The status of the operation. Returns ROCJPEG_STATUS_SUCCESS if the data buffers were successfully destroyed. + */ RocJpegStatus RocJpegVappiDecoder::DestroyDataBuffers() { if (va_picture_parameter_buf_id_) { CHECK_VAAPI(vaDestroyBuffer(va_display_, va_picture_parameter_buf_id_)); @@ -359,6 +483,21 @@ RocJpegStatus RocJpegVappiDecoder::DestroyDataBuffers() { return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Submits a JPEG decode operation to the VAAPI decoder. + * + * This function submits a JPEG decode operation to the VAAPI decoder using the provided JPEG stream parameters. + * It checks for invalid parameters and unsupported image resolutions before proceeding with the decode operation. + * The output format is determined based on the requested format and the capabilities of the hardware decoder. + * + * @param jpeg_stream_params The JPEG stream parameters for the decode operation. + * @param surface_id [out] The ID of the output surface where the decoded image will be stored. + * @param output_format The desired output format for the decoded image. + * @return The status of the decode operation. + * - ROCJPEG_STATUS_SUCCESS if the decode operation was successful. + * - ROCJPEG_STATUS_INVALID_PARAMETER if the provided parameters are invalid. + * - ROCJPEG_STATUS_JPEG_NOT_SUPPORTED if the JPEG image resolution or chroma subsampling is not supported. + */ RocJpegStatus RocJpegVappiDecoder::SubmitDecode(const JpegStreamParameters *jpeg_stream_params, uint32_t &surface_id, RocJpegOutputFormat output_format) { if (jpeg_stream_params == nullptr) { return ROCJPEG_STATUS_INVALID_PARAMETER; @@ -456,6 +595,16 @@ RocJpegStatus RocJpegVappiDecoder::SubmitDecode(const JpegStreamParameters *jpeg return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Synchronizes the specified VASurfaceID. + * + * This function synchronizes the specified VASurfaceID by querying its status and waiting until it becomes ready. + * If the surface ID is not found in the VAAPI memory pool, it returns ROCJPEG_STATUS_INVALID_PARAMETER. + * If any error occurs during synchronization, it returns ROCJPEG_STATUS_RUNTIME_ERROR. + * + * @param surface_id The VASurfaceID to synchronize. + * @return The status of the synchronization operation. + */ RocJpegStatus RocJpegVappiDecoder::SyncSurface(VASurfaceID surface_id) { VASurfaceStatus surface_status; if (!vaapi_mem_pool_->FindSurfaceId(surface_id)) { @@ -480,10 +629,28 @@ RocJpegStatus RocJpegVappiDecoder::SyncSurface(VASurfaceID surface_id) { return ROCJPEG_STATUS_SUCCESS; } +/** + * @brief Retrieves the HipInteropDeviceMem associated with the specified VASurfaceID. + * + * This function retrieves the HipInteropDeviceMem associated with the specified VASurfaceID + * from the vaapi_mem_pool_ and stores it in the provided `hip_interop` parameter. + * + * @param surface_id The VASurfaceID of the surface to retrieve the HipInteropDeviceMem for. + * @param hip_interop The reference to a HipInteropDeviceMem object where the retrieved memory will be stored. + * @return The RocJpegStatus indicating the success or failure of the operation. + */ RocJpegStatus RocJpegVappiDecoder::GetHipInteropMem(VASurfaceID surface_id, HipInteropDeviceMem& hip_interop) { return vaapi_mem_pool_->GetHipInteropMem(surface_id, hip_interop); } +/** + * @brief Retrieves the visible devices for the RocJpegVappiDecoder. + * + * This function retrieves the visible devices for the RocJpegVappiDecoder by reading the value of the environment variable "HIP_VISIBLE_DEVICES". + * The visible devices are stored in the provided vector `visible_devices_vector`. + * + * @param visible_devices_vector The vector to store the visible devices. + */ void RocJpegVappiDecoder::GetVisibleDevices(std::vector& visible_devices_vetor) { char *visible_devices = std::getenv("HIP_VISIBLE_DEVICES"); if (visible_devices != nullptr) { @@ -496,6 +663,15 @@ void RocJpegVappiDecoder::GetVisibleDevices(std::vector& visible_devices_ve } } +/** + * Retrieves the current compute partitions from the system. + * + * This function searches for the "current_compute_partition" file in the "/sys/devices/" directory + * and reads the partition value from each file found. The partition value is then compared to known + * partition names and the corresponding ComputePartition enum value is added to the provided vector. + * + * @param current_compute_partitions A vector to store the current compute partitions. + */ void RocJpegVappiDecoder::GetCurrentComputePartition(std::vector ¤t_compute_partitions) { std::string search_path = "/sys/devices/"; std::string partition_file = "current_compute_partition"; @@ -526,6 +702,16 @@ void RocJpegVappiDecoder::GetCurrentComputePartition(std::vector& visible_devices, std::vector ¤t_compute_partitions, int &offset) { diff --git a/src/rocjpeg_vaapi_decoder.h b/src/rocjpeg_vaapi_decoder.h index 4d6d94cd89..1dd3cf7bbd 100644 --- a/src/rocjpeg_vaapi_decoder.h +++ b/src/rocjpeg_vaapi_decoder.h @@ -48,31 +48,62 @@ THE SOFTWARE. /*Note: va.h doesn't have VA_FOURCC_YUYV defined but vaExportSurfaceHandle returns 0x56595559 for packed YUYV for YUV 4:2:2*/ #define ROCJPEG_FOURCC_YUYV 0x56595559 +/** + * @brief Enumeration representing the compute partition for the MI300+ family of GPUs. + */ typedef enum { - kSpx = 0, // Single Partition Accelerator - kDpx = 1, // Dual Partition Accelerator - kTpx = 2, // Triple Partition Accelerator - kQpx = 3, // Quad Partition Accelerator - kCpx = 4, // Core Partition Accelerator + kSpx = 0, /**< Single Partition Accelerator */ + kDpx = 1, /**< Dual Partition Accelerator */ + kTpx = 2, /**< Triple Partition Accelerator */ + kQpx = 3, /**< Quad Partition Accelerator */ + kCpx = 4, /**< Core Partition Accelerator */ } ComputePartition; +/** + * @brief Structure representing the specifications of a VCN JPEG decoder. + * + * This structure contains information about the VCN JPEG decoder, including the number of JPEG cores, + * whether it can convert to RGB, and whether it supports ROI (Region of Interest) decoding. + */ typedef struct { - uint32_t num_jpeg_cores; - bool can_convert_to_rgb; - bool can_roi_decode; + uint32_t num_jpeg_cores; /**< Number of JPEG cores in the VCN JPEG decoder. */ + bool can_convert_to_rgb; /**< Flag indicating whether the VCN JPEG decoder can convert to RGB. */ + bool can_roi_decode; /**< Flag indicating whether the VCN JPEG decoder supports ROI decoding. */ } VcnJpegSpec; +/** + * @brief Structure representing the HIP interop device memory. + * + * This structure holds information related to the HIP-VAAPI interop device memory. + * It includes the HIP external memory interface, mapped device memory for the YUV plane, + * pixel format fourcc of the whole surface, width and height of the surface in pixels, + * offset and pitch of each plane, and the number of layers making up the surface. + */ struct HipInteropDeviceMem { - hipExternalMemory_t hip_ext_mem; // Interface to the vaapi-hip interop - uint8_t* hip_mapped_device_mem; // Mapped device memory for the YUV plane - uint32_t surface_format; // Pixel format fourcc of the whole surface - uint32_t width; // Width of the surface in pixels. - uint32_t height; // Height of the surface in pixels. - uint32_t offset[3]; // Offset of each plane - uint32_t pitch[3]; // Pitch of each plane - uint32_t num_layers; // Number of layers making up the surface + hipExternalMemory_t hip_ext_mem; /**< Interface to the vaapi-hip interop */ + uint8_t* hip_mapped_device_mem; /**< Mapped device memory for the YUV plane */ + uint32_t surface_format; /**< Pixel format fourcc of the whole surface */ + uint32_t width; /**< Width of the surface in pixels. */ + uint32_t height; /**< Height of the surface in pixels. */ + uint32_t offset[3]; /**< Offset of each plane */ + uint32_t pitch[3]; /**< Pitch of each plane */ + uint32_t num_layers; /**< Number of layers making up the surface */ }; +/** + * @brief Structure representing an entry in the RocJpegVappiMemPool. + * + * This structure holds information about an image in the memory pool used by the RocJpegVappiDecoder. + * It includes the image width and height, the VASurfaceID and VAContextID associated with the image, + * and the HipInteropDeviceMem for interoperation with HIP. + */ +/** + * @brief Structure representing an entry in the RocJpegVappiMemPool. + * + * This structure holds information about an image in the memory pool used by the RocJpegVappiDecoder. + * It includes the image width and height, the VASurfaceID and VAContextID associated with the image, + * and the HipInteropDeviceMem for interoperation with HIP. + */ struct RocJpegVappiMemPoolEntry { uint32_t image_width; uint32_t image_height; @@ -81,54 +112,190 @@ struct RocJpegVappiMemPoolEntry { HipInteropDeviceMem hip_interop; }; +/** + * @class RocJpegVappiMemoryPool + * @brief A class that represents a memory pool for VAAPI surfaces used by the RocJpegVappiDecoder. + * + * The RocJpegVappiMemoryPool class provides methods to manage and allocate memory resources for VAAPI surfaces. + * It allows setting the pool size, associating a VADisplay, finding surface IDs, getting pool entries, adding pool entries, + * deleting surface IDs, and retrieving HipInterop memory for a specific surface ID. + */ class RocJpegVappiMemoryPool { public: + /** + * @brief Default constructor for RocJpegVappiMemoryPool. + */ RocJpegVappiMemoryPool(); + + /** + * @brief Releases all the resources associated with the memory pool. + */ void ReleaseResources(); + + /** + * @brief Sets the maximum size of the memory pool. + * @param max_pool_size The maximum size of the memory pool. + */ void SetPoolSize(int32_t max_pool_size); + + /** + * @brief Sets the VADisplay for the memory pool. + * @param va_display The VADisplay to be set. + */ void SetVaapiDisplay(const VADisplay& va_display); + + /** + * @brief Finds a surface ID in the memory pool. + * @param surface_id The surface ID to find. + * @return True if the surface ID is found, false otherwise. + */ bool FindSurfaceId(VASurfaceID surface_id); + + /** + * @brief Gets a pool entry based on the surface format, image width, and image height. + * @param surface_format The surface format of the pool entry. + * @param image_width The image width of the pool entry. + * @param image_height The image height of the pool entry. + * @return The RocJpegVappiMemPoolEntry object if found, otherwise a default-constructed object. + */ RocJpegVappiMemPoolEntry GetEntry(uint32_t surface_format, uint32_t image_width, uint32_t image_height); + + /** + * @brief Adds a pool entry to the memory pool. + * @param surface_format The surface format of the pool entry. + * @param pool_entry The RocJpegVappiMemPoolEntry to be added. + * @return The status of the operation. + */ RocJpegStatus AddPoolEntry(uint32_t surface_format, const RocJpegVappiMemPoolEntry& pool_entry); + + /** + * @brief Deletes a surface ID from the memory pool. + * @param surface_id The surface ID to be deleted. + * @return The status of the operation. + */ RocJpegStatus DeleteSurfaceId(VASurfaceID surface_id); + + /** + * @brief Retrieves HipInterop memory for a specific surface ID. + * @param surface_id The surface ID to retrieve HipInterop memory for. + * @param hip_interop The HipInteropDeviceMem object to store the retrieved memory. + * @return The status of the operation. + */ RocJpegStatus GetHipInteropMem(VASurfaceID surface_id, HipInteropDeviceMem& hip_interop); + private: - VADisplay va_display_; - std::unordered_map> mem_pool_; + VADisplay va_display_; // The VADisplay associated with the memory pool. + std::unordered_map> mem_pool_; // The memory pool. }; +/** + * @brief The RocJpegVappiDecoder class represents a VAAPI-based JPEG decoder. + */ class RocJpegVappiDecoder { public: + /** + * @brief Constructs a RocJpegVappiDecoder object. + * @param device_id The ID of the device to use for decoding (default is 0). + */ RocJpegVappiDecoder(int device_id = 0); + + /** + * @brief Destroys the RocJpegVappiDecoder object. + */ ~RocJpegVappiDecoder(); + + /** + * @brief Initializes the decoder with the specified device, GCN architecture, and device ID. + * @param device_name The name of the device. + * @param gcn_arch_name The name of the GCN architecture. + * @param device_id The ID of the device. + * @return The status of the initialization. + */ RocJpegStatus InitializeDecoder(std::string device_name, std::string gcn_arch_name, int device_id); + + /** + * @brief Submits a JPEG stream for decoding. + * @param jpeg_stream_params The parameters of the JPEG stream. + * @param surface_id The ID of the output surface. + * @param output_format The output format of the decoded image. + * @return The status of the decoding operation. + */ RocJpegStatus SubmitDecode(const JpegStreamParameters *jpeg_stream_params, uint32_t &surface_id, RocJpegOutputFormat output_format); + + /** + * @brief Waits for the decoding operation to complete. + * @param surface_id The ID of the output surface. + * @return The status of the synchronization operation. + */ RocJpegStatus SyncSurface(VASurfaceID surface_id); + + /** + * @brief Retrieves the HIP interop memory associated with the specified surface. + * @param surface_id The ID of the surface. + * @param hip_interop The HIP interop memory object to be filled. + * @return The status of the retrieval operation. + */ RocJpegStatus GetHipInteropMem(VASurfaceID surface_id, HipInteropDeviceMem& hip_interop); + private: - int device_id_; - int drm_fd_; - uint32_t min_picture_width_; - uint32_t min_picture_height_; - uint32_t max_picture_width_; - uint32_t max_picture_height_; - VADisplay va_display_; - std::vector va_config_attrib_; - VAConfigID va_config_id_; - VAProfile va_profile_; - std::unordered_map vcn_jpeg_spec_; - std::unique_ptr vaapi_mem_pool_; - VcnJpegSpec current_vcn_jpeg_spec_; - VABufferID va_picture_parameter_buf_id_; - VABufferID va_quantization_matrix_buf_id_; - VABufferID va_huffmantable_buf_id_; - VABufferID va_slice_param_buf_id_; - VABufferID va_slice_data_buf_id_; + int device_id_; // The ID of the device + int drm_fd_; // The file descriptor for the DRM device + uint32_t min_picture_width_; // The minimum width of the picture + uint32_t min_picture_height_; // The minimum height of the picture + uint32_t max_picture_width_; // The maximum width of the picture + uint32_t max_picture_height_; // The maximum height of the picture + VADisplay va_display_; // The VAAPI display + std::vector va_config_attrib_; // The VAAPI configuration attributes + VAConfigID va_config_id_; // The VAAPI configuration ID + VAProfile va_profile_; // The VAAPI profile + std::unordered_map vcn_jpeg_spec_; // The map of VCN JPEG specifications + std::unique_ptr vaapi_mem_pool_; // The VAAPI memory pool + VcnJpegSpec current_vcn_jpeg_spec_; // The current VCN JPEG specification + VABufferID va_picture_parameter_buf_id_; // The VAAPI picture parameter buffer ID + VABufferID va_quantization_matrix_buf_id_; // The VAAPI quantization matrix buffer ID + VABufferID va_huffmantable_buf_id_; // The VAAPI Huffman table buffer ID + VABufferID va_slice_param_buf_id_; // The VAAPI slice parameter buffer ID + VABufferID va_slice_data_buf_id_; // The VAAPI slice data buffer ID + + /** + * @brief Initializes the VAAPI with the specified DRM node. + * @param drm_node The DRM node to use for VAAPI initialization. + * @return The status of the VAAPI initialization. + */ RocJpegStatus InitVAAPI(std::string drm_node); + + /** + * @brief Creates the decoder configuration. + * @return The status of the configuration creation. + */ RocJpegStatus CreateDecoderConfig(); + + /** + * @brief Destroys the data buffers. + * @return The status of the buffer destruction. + */ RocJpegStatus DestroyDataBuffers(); + + /** + * @brief Retrieves the visible devices. + * @param visible_devices The vector to store the visible devices. + */ void GetVisibleDevices(std::vector& visible_devices); + + /** + * @brief Retrieves the current compute partitions. + * @param current_compute_partitions The vector to store the current compute partitions. + */ void GetCurrentComputePartition(std::vector &currnet_compute_partitions); + + /** + * @brief Retrieves the DRM node offset. + * @param device_name The name of the device. + * @param device_id The ID of the device. + * @param visible_devices The vector of visible devices. + * @param current_compute_partitions The vector of current compute partitions. + * @param offset The offset of the DRM node. + */ void GetDrmNodeOffset(std::string device_name, uint8_t device_id, std::vector& visible_devices, std::vector ¤t_compute_partitions, int &offset);