Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion projects/rocdecode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

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

## (Unreleased) rocDecode 1.7.1
## (Unreleased) rocDecode 1.8.0

### Added

* Logging improvement: Added function entry and exit logs (at Info log level).
* Feature: support for user set output surface format.

## rocDecode 1.7.0 for ROCm 7.2.1

Expand Down
2 changes: 1 addition & 1 deletion projects/rocdecode/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ if (NOT DEFINED CMAKE_CXX_COMPILER)
endif()

# rocdecode Version
set(VERSION "1.7.1")
set(VERSION "1.8.0")

# Set Project Version and Language
project(rocdecode VERSION ${VERSION} LANGUAGES CXX)
Expand Down
5 changes: 5 additions & 0 deletions projects/rocdecode/api/rocdecode/rocdecode.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ typedef enum rocDecVideoSurfaceFormat_enum {
rocDecVideoSurfaceFormat_YUV422 = 6, /**< Planar YUV [Y plane followed by U and V planes in 4:2:2 format] */
rocDecVideoSurfaceFormat_YUV422_16Bit = 7, /**< 16 bit Planar YUV [Y plane followed by U and V planes in 4:2:2 format].
Can be used for 10 bit(LSB), 12 bit (LSB) */
rocDecVideoSurfaceFormat_Native = 8 /**< Sentinel value: output format is determined by the coded stream parameters
(chroma format and bit depth), and the decoder selects the appropriate surface
format automatically. This value will not appear in any output_format_mask (or
similar bitmask fields) and MUST NOT be used as a bit position when constructing
or interpreting format bitmasks. */
} rocDecVideoSurfaceFormat;

/**************************************************************************************************************/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The sample decodes raw elementary video frame files as input and produces indivi
``rocdecdecode.cpp`` takes the following arguments:

.. list-table::
:widths: 10 60 30
:widths: 20 60 30
:header-rows: 1

* - Argument
Expand Down Expand Up @@ -54,7 +54,15 @@ The sample decodes raw elementary video frame files as input and produces indivi

* - ``-m``
- The output surface memory type. The memory type where the surface data, such as the decoded frames, resides. Set this to 0 for intermediate GPU memory, to 1 for GPU memory, and to 2 for CPU memory. See :doc:`Surface data memory locations <../conceptual/rocDecode-memory-types>` for more information.
- Optional. Set to 0 by default.
- Optional. Set to 0 by default.

* - ``-f``
- Number of decoded frames to be decoded.
- Optional.

* - ``-o_format``
- Output surface format; [NV12, P016].
- Optional. If not set: auto-detected from stream.

The ``DecoderInfo`` struct defined in the sample is used to store user-supplied parameters as well as the decoder and parser handles.

Expand Down
153 changes: 126 additions & 27 deletions projects/rocdecode/samples/rocdecDecode/rocdecdecode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ static inline float GetChromaHeightFactor(rocDecVideoSurfaceFormat surface_forma
case rocDecVideoSurfaceFormat_YUV444_16Bit:
factor = 1.0;
break;
default:
break;
}

return factor;
Expand Down Expand Up @@ -120,6 +122,8 @@ static inline float GetChromaWidthFactor(rocDecVideoSurfaceFormat surface_format
case rocDecVideoSurfaceFormat_YUV422_16Bit:
factor = 0.5;
break;
default:
break;
}
return factor;
};
Expand Down Expand Up @@ -147,6 +151,7 @@ typedef enum DecoderBackend_enum {
} \
} while (false)


/**
* @brief Struct containing all the information for decoding and displaying output
*
Expand All @@ -162,14 +167,16 @@ struct DecoderInfo {
std::string output_file_path;
OutputSurfaceMemoryType mem_type;
rocDecVideoSurfaceFormat surf_format;
rocDecVideoSurfaceFormat video_chroma_format;
bool output_format_override; // true: user set output surface format; false: output surface format is determined by the coded stream
rocDecVideoChromaFormat video_chroma_format;
uint32_t coded_width, coded_height;
uint32_t bytes_per_pixel;
bool is_decoder_reconfigured;
Rect disp_rect;
FILE *fp_out;
DecoderInfo() : dec_device_id(0), backend(DECODER_BACKEND_DEVICE), decoder(nullptr), bit_depth(8), dump_decoded_frames(0), mem_type{OUT_SURFACE_MEM_DEV_INTERNAL},
surf_format{rocDecVideoSurfaceFormat_NV12}, video_chroma_format{rocDecVideoSurfaceFormat_NV12},
surf_format{rocDecVideoSurfaceFormat_NV12}, output_format_override{false},
video_chroma_format{rocDecVideoChromaFormat_420},
is_decoder_reconfigured{false}, fp_out{nullptr} {}
};

Expand All @@ -181,7 +188,6 @@ struct DecoderInfo {
* @param pitch stride in bytes of luma and chroma planes
*/
void save_frame_to_file(DecoderInfo *p_dec_info, void *surf_mem[], uint32_t *pitch) {

uint8_t *hst_ptr = nullptr;
uint64_t output_image_size_luma = pitch[0] * p_dec_info->coded_height;
uint64_t output_image_size_chroma = pitch[1] * ((p_dec_info->coded_height * GetChromaHeightFactor(p_dec_info->surf_format)));
Expand Down Expand Up @@ -321,7 +327,7 @@ std::vector<std::vector<uint8_t>> read_frames(std::vector<std::string>& names) {
std::cerr << "Error opening " << name << " for reading." << std::endl;
std::abort();
}
std::cout << "Reading " << name << " for reading." << std::endl;
//std::cout << "Reading " << name << " for reading." << std::endl;
// Determine the file size
inputFile.seekg(0, std::ios::end);
std::streamsize fileSize = inputFile.tellg();
Expand Down Expand Up @@ -357,12 +363,25 @@ void create_decoder(DecoderInfo& dec_info) {
create_info.display_rect.right = static_cast<short>(DEFAULT_WIDTH);
create_info.display_rect.top = 0;
create_info.display_rect.bottom = static_cast<short>(DEFAULT_HEIGHT);
// for decode creation: assuming chroma_format is 4:2:0 and output_format is NV12.
// for decode creation: assuming chroma_format is 4:2:0 and output_format is NV12 unless overridden by user.
// video dimensions ( width, height, max_width, max_height), num_decode_surfaces, and bit_depth_minus_8 are hardcoded here
// this will get changed in reconfigure when the sequence header is parsed from the stream to detect the actual video parameters
create_info.chroma_format = rocDecVideoChromaFormat_420;
create_info.output_format = rocDecVideoSurfaceFormat_NV12;
create_info.bit_depth_minus_8 = 0;
if (dec_info.output_format_override) {
create_info.output_format = dec_info.surf_format;
if (create_info.output_format == rocDecVideoSurfaceFormat_P016) {
create_info.bit_depth_minus_8 = 2;
} else {
create_info.bit_depth_minus_8 = 0;
}
} else {
// Default setting
create_info.output_format = rocDecVideoSurfaceFormat_Native;
create_info.bit_depth_minus_8 = 0;
dec_info.surf_format = create_info.output_format;
dec_info.bit_depth = create_info.bit_depth_minus_8 + 8;
dec_info.bytes_per_pixel = (dec_info.bit_depth + 7) / 8;
}
create_info.num_output_surfaces = 1;
CHECK(rocDecCreateDecoder(&dec_info.decoder, &create_info));
}
Expand Down Expand Up @@ -463,6 +482,63 @@ int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format)
int bitdepth_minus_8 = format->bit_depth_luma_minus8;
uint32_t target_width = (format->display_area.right - format->display_area.left + 1) & ~1;
uint32_t target_height = (format->display_area.bottom - format->display_area.top + 1) & ~1;

p_dec_info->is_decoder_reconfigured = true;
p_dec_info->disp_rect.top = format->display_area.top;
p_dec_info->disp_rect.bottom = format->display_area.bottom;
p_dec_info->disp_rect.left = format->display_area.left;
p_dec_info->disp_rect.right = format->display_area.right;
if (p_dec_info->output_format_override) {
switch (p_dec_info->surf_format) {
case rocDecVideoSurfaceFormat_NV12:
case rocDecVideoSurfaceFormat_YUV420:
case rocDecVideoSurfaceFormat_YUV422:
case rocDecVideoSurfaceFormat_YUV444: {
p_dec_info->bytes_per_pixel = 1;
p_dec_info->bit_depth = 8;
}
break;

case rocDecVideoSurfaceFormat_P016:
case rocDecVideoSurfaceFormat_YUV420_16Bit:
case rocDecVideoSurfaceFormat_YUV444_16Bit:
case rocDecVideoSurfaceFormat_YUV422_16Bit: {
if (bitdepth_minus_8) {
p_dec_info->bytes_per_pixel = 2;
p_dec_info->bit_depth = bitdepth_minus_8 + 8;
} else {
p_dec_info->bytes_per_pixel = 1;
p_dec_info->bit_depth = 8;
if (p_dec_info->surf_format == rocDecVideoSurfaceFormat_P016) {
p_dec_info->surf_format = rocDecVideoSurfaceFormat_NV12;
} else if (p_dec_info->surf_format == rocDecVideoSurfaceFormat_YUV420_16Bit) {
p_dec_info->surf_format = rocDecVideoSurfaceFormat_YUV420;
} else if (p_dec_info->surf_format == rocDecVideoSurfaceFormat_YUV422_16Bit) {
p_dec_info->surf_format = rocDecVideoSurfaceFormat_YUV422;
} else if (p_dec_info->surf_format == rocDecVideoSurfaceFormat_YUV444_16Bit) {
p_dec_info->surf_format = rocDecVideoSurfaceFormat_YUV444;
}
}
}
break;
Comment thread
jeffqjiangNew marked this conversation as resolved.
Resolved
default:
break;
}
} else {
rocDecVideoChromaFormat video_chroma_format = format->chroma_format;
if (video_chroma_format == rocDecVideoChromaFormat_420 || video_chroma_format == rocDecVideoChromaFormat_Monochrome)
p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_P016 : rocDecVideoSurfaceFormat_NV12;
else if (video_chroma_format == rocDecVideoChromaFormat_444)
p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV444_16Bit : rocDecVideoSurfaceFormat_YUV444;
else if (video_chroma_format == rocDecVideoChromaFormat_422)
p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV422_16Bit : rocDecVideoSurfaceFormat_YUV422;

p_dec_info->bytes_per_pixel = bitdepth_minus_8 > 0 ? 2 : 1;
p_dec_info->bit_depth = bitdepth_minus_8 + 8;
}
p_dec_info->coded_width = format->coded_width;
p_dec_info->coded_height = format->coded_height;

reconfig_params.width = format->coded_width;
reconfig_params.height = format->coded_height;
reconfig_params.bit_depth_minus_8 = bitdepth_minus_8;
Expand All @@ -474,21 +550,7 @@ int ROCDECAPI handle_video_sequence(void* user_data, RocdecVideoFormat* format)
reconfig_params.display_rect.top = format->display_area.top;
reconfig_params.display_rect.bottom = format->display_area.bottom;
CHECK(rocDecReconfigureDecoder(p_dec_info->decoder, &reconfig_params));
p_dec_info->is_decoder_reconfigured = true;
p_dec_info->disp_rect.top = format->display_area.top;
p_dec_info->disp_rect.bottom = format->display_area.bottom;
p_dec_info->disp_rect.left = format->display_area.left;
p_dec_info->disp_rect.right = format->display_area.right;
rocDecVideoChromaFormat video_chroma_format = format->chroma_format;
if (video_chroma_format == rocDecVideoChromaFormat_420 || rocDecVideoChromaFormat_Monochrome)
p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_P016 : rocDecVideoSurfaceFormat_NV12;
else if (video_chroma_format == rocDecVideoChromaFormat_444)
p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV444_16Bit : rocDecVideoSurfaceFormat_YUV444;
else if (video_chroma_format == rocDecVideoChromaFormat_422)
p_dec_info->surf_format = bitdepth_minus_8 ? rocDecVideoSurfaceFormat_YUV422_16Bit : rocDecVideoSurfaceFormat_YUV422;
p_dec_info->coded_width = format->coded_width;
p_dec_info->coded_height = format->coded_height;
p_dec_info->bytes_per_pixel = bitdepth_minus_8 > 0 ? 2 : 1;

std::ostringstream input_video_info_str;
input_video_info_str.str("");
input_video_info_str.clear();
Expand Down Expand Up @@ -601,8 +663,10 @@ void ShowHelpAndExit(const char *option = NULL) {
#else
<< "-b backend (0 for GPU); optional; default: 0" << std::endl
#endif
<< "-c codec (0 : HEVC, 1 : H264, 2: AV1, 4: VP9, 5: VP8 ); optional; default: 0" << std::endl
<< "-c codec (0 : HEVC, 1 : H264, 2: AV1, 3: VP9, 4: VP8 ); optional; default: 0" << std::endl
<< "-n Number of iteration - specify the number of iterations for performance evaluation; optional; default: 1" << std::endl
<< "-f Number of decoded frames - specify the number of pictures to be decoded; optional" << std::endl
<< "-o_format Output surface format; optional; [NV12, P016]; if not set: auto-detected from stream" << std::endl
<< "-m output_surface_memory_type - decoded surface memory; optional; default - 0"
<< " [0 : OUT_SURFACE_MEM_DEV_INTERNAL/ 1 : OUT_SURFACE_MEM_DEV_COPIED/ 2 : OUT_SURFACE_MEM_HOST_COPIED/ 3 : OUT_SURFACE_MEM_NOT_MAPPED]" << std::endl;
exit(0);
Expand Down Expand Up @@ -641,13 +705,27 @@ bool compareFilenames(const std::string& a, const std::string& b) {
return a < b; // Fallback to lexicographical comparison
};

int main(int argc, char** argv) {
static inline bool ParseOutputFormat(const char *str, rocDecVideoSurfaceFormat *surface_format) {
if (!strcmp(str, "NV12")) { *surface_format = rocDecVideoSurfaceFormat_NV12; return true; }
if (!strcmp(str, "P016")) { *surface_format = rocDecVideoSurfaceFormat_P016; return true; }
#if 0
if (!strcmp(str, "YUV444")) { *surface_format = rocDecVideoSurfaceFormat_YUV444; return true; }
if (!strcmp(str, "YUV444_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV444_16Bit; return true; }
if (!strcmp(str, "YUV422")) { *surface_format = rocDecVideoSurfaceFormat_YUV422; return true; }
if (!strcmp(str, "YUV422_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV422_16Bit; return true; }
if (!strcmp(str, "YUV420")) { *surface_format = rocDecVideoSurfaceFormat_YUV420; return true; }
if (!strcmp(str, "YUV420_16Bit")) { *surface_format = rocDecVideoSurfaceFormat_YUV420_16Bit; return true; }
#endif
return false; // unrecognised
}

int main(int argc, char** argv) {
std::string input_file_path, output_file_path;
int dump_output_frames = 0;
int device_id = 0;
DecoderBackend backend = DECODER_BACKEND_DEVICE;
int num_iterations = 1;
int num_iterations = 1;
uint32_t num_decoded_frames = 0; // default value is 0, meaning decode all frames
std::vector<std::string> input_file_names;
int codec_type = 0; // default for HEVC
DecoderInfo dec_info;
Expand Down Expand Up @@ -691,8 +769,6 @@ int main(int argc, char** argv) {
} else {
input_file_names.push_back(input_file_path);
}

std::cout << "Read " << input_file_names.size() << " frames from disk." << std::endl;
continue;
}
if (!strcmp(argv[i], "-o")) {
Expand Down Expand Up @@ -734,6 +810,24 @@ int main(int argc, char** argv) {
num_iterations = atoi(argv[i]);
continue;
}
if (!strcmp(argv[i], "-f")) {
if (++i == argc) {
ShowHelpAndExit("-f");
}
num_decoded_frames = std::stoul(argv[i]);
continue;
Comment thread
jeffqjiangNew marked this conversation as resolved.
Resolved
Comment thread
jeffqjiangNew marked this conversation as resolved.
Resolved
}
if (!strcmp(argv[i], "-o_format")) {
if (++i == argc) {
ShowHelpAndExit("-o_format");
}
dec_info.output_format_override = ParseOutputFormat(argv[i], &dec_info.surf_format);
if (!dec_info.output_format_override) {
std::cerr << "Unknown output format: " << argv[i] << std::endl;
ShowHelpAndExit("-o_format");
}
continue;
}
ShowHelpAndExit(argv[i]);
}
dec_info.rocdec_codec_id = CodecTypeToRocDecVideoCodec(codec_type);
Expand All @@ -750,10 +844,15 @@ int main(int argc, char** argv) {
}
#endif
dec_info.dump_decoded_frames = dump_output_frames;
if (num_decoded_frames && num_decoded_frames < input_file_names.size()) {
input_file_names.resize(num_decoded_frames);
}
auto input_frames = read_frames(input_file_names);
std::cout << "Read " << input_file_names.size() << " frames from disk." << std::endl;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < num_iterations; i++) {
decode_frames(dec_info, input_frames);
std::cout << "Total decoded frames in iteration " << i << ": " << input_frames.size() << std::endl;
}
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
Expand Down
Loading
Loading