MD5 digest generation support (#109)
* * rocDecode/HEVC: Added support for MD5 message digest generation. - Command option "-md5" triggers MD5 calculation and output. * * rocDecode/HEVC: Changed C type casting to C++ type casting.
This commit is contained in:
committed by
GitHub
orang tua
86a0b295a5
melakukan
ad20961c4a
@@ -43,6 +43,7 @@ void ShowHelpAndExit(const char *option = NULL) {
|
||||
<< "-d GPU device ID (0 for the first device, 1 for the second, etc.); optional; default: 0" << std::endl
|
||||
<< "-z force_zero_latency (force_zero_latency, Decoded frames will be flushed out for display immediately); optional;" << std::endl
|
||||
<< "-sei extract SEI messages; optional;" << std::endl
|
||||
<< "-md5 generate MD5 message digest on the decoded YUV image sequence; optional;" << std::endl
|
||||
<< "-crop crop rectangle for output (not used when using interopped decoded frame); optional; default: 0" << 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]" << std::endl;
|
||||
@@ -56,6 +57,7 @@ int main(int argc, char **argv) {
|
||||
int device_id = 0;
|
||||
bool b_force_zero_latency = false; // false by default: enabling this option might affect decoding performance
|
||||
bool b_extract_sei_messages = false;
|
||||
bool b_generate_md5 = false;
|
||||
Rect crop_rect = {};
|
||||
Rect *p_crop_rect = nullptr;
|
||||
OutputSurfaceMemoryType mem_type = OUT_SURFACE_MEM_DEV_INTERNAL; // set to internal
|
||||
@@ -103,6 +105,13 @@ int main(int argc, char **argv) {
|
||||
b_extract_sei_messages = true;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-md5")) {
|
||||
if (i == argc) {
|
||||
ShowHelpAndExit("-md5");
|
||||
}
|
||||
b_generate_md5 = true;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(argv[i], "-crop")) {
|
||||
if (++i == argc || 4 != sscanf(argv[i], "%d,%d,%d,%d", &crop_rect.l, &crop_rect.t, &crop_rect.r, &crop_rect.b)) {
|
||||
ShowHelpAndExit("-crop");
|
||||
@@ -146,6 +155,10 @@ int main(int argc, char **argv) {
|
||||
uint32_t width, height;
|
||||
double total_dec_time = 0;
|
||||
|
||||
if (b_generate_md5) {
|
||||
viddec.InitMd5();
|
||||
}
|
||||
|
||||
do {
|
||||
auto start_time = std::chrono::high_resolution_clock::now();
|
||||
demuxer.Demux(&pvideo, &n_video_bytes, &pts);
|
||||
@@ -163,6 +176,9 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
for (int i = 0; i < n_frame_returned; i++) {
|
||||
pframe = viddec.GetFrame(&pts);
|
||||
if (b_generate_md5) {
|
||||
viddec.UpdateMd5ForFrame(pframe, surf_info);
|
||||
}
|
||||
if (dump_output_frames) {
|
||||
viddec.SaveFrameToFile(output_file_path, pframe, surf_info);
|
||||
}
|
||||
@@ -177,6 +193,15 @@ int main(int argc, char **argv) {
|
||||
std::cout << "info: avg decoding time per frame (ms): " << total_dec_time / n_frame << std::endl;
|
||||
std::cout << "info: avg FPS: " << (n_frame / total_dec_time) * 1000 << std::endl;
|
||||
}
|
||||
if (b_generate_md5) {
|
||||
uint8_t *digest;
|
||||
viddec.FinalizeMd5(&digest);
|
||||
std::cout << "MD5 message digest: ";
|
||||
for (int i = 0; i < 16; i++) {
|
||||
std::cout << std::hex << static_cast<int>(digest[i]);
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
} catch (const std::exception &ex) {
|
||||
std::cout << ex.what() << std::endl;
|
||||
exit(1);
|
||||
|
||||
@@ -669,7 +669,7 @@ void RocVideoDecoder::SaveFrameToFile(std::string output_file_name, void *surf_m
|
||||
return;
|
||||
}
|
||||
} else
|
||||
hst_ptr = (uint8_t *)surf_mem;
|
||||
hst_ptr = static_cast<uint8_t *> (surf_mem);
|
||||
|
||||
|
||||
uint8_t *tmp_hst_ptr = hst_ptr;
|
||||
@@ -730,6 +730,84 @@ void RocVideoDecoder::SaveFrameToFile(std::string output_file_name, void *surf_m
|
||||
}
|
||||
}
|
||||
|
||||
void RocVideoDecoder::InitMd5() {
|
||||
md5_ctx_ = av_md5_alloc();
|
||||
av_md5_init(md5_ctx_);
|
||||
}
|
||||
|
||||
void RocVideoDecoder::UpdateMd5ForFrame(void *surf_mem, OutputSurfaceInfo *surf_info) {
|
||||
int i;
|
||||
uint8_t *hst_ptr = nullptr;
|
||||
uint64_t output_image_size = surf_info->output_surface_size_in_bytes;
|
||||
if (surf_info->mem_type == OUT_SURFACE_MEM_DEV_INTERNAL || surf_info->mem_type == OUT_SURFACE_MEM_DEV_COPIED) {
|
||||
if (hst_ptr == nullptr) {
|
||||
hst_ptr = new uint8_t [output_image_size];
|
||||
}
|
||||
hipError_t hip_status = hipSuccess;
|
||||
hip_status = hipMemcpyDtoH((void *)hst_ptr, surf_mem, output_image_size);
|
||||
if (hip_status != hipSuccess) {
|
||||
std::cout << "ERROR: hipMemcpyDtoH failed! (" << hip_status << ")" << std::endl;
|
||||
delete [] hst_ptr;
|
||||
return;
|
||||
}
|
||||
} else
|
||||
hst_ptr = static_cast<uint8_t *> (surf_mem);
|
||||
|
||||
// Need to covert interleaved planar to stacked planar, assuming 4:2:0 chroma sampling.
|
||||
uint8_t *stacked_ptr = new uint8_t [output_image_size];
|
||||
|
||||
uint8_t *tmp_hst_ptr = hst_ptr;
|
||||
uint8_t *tmp_stacked_ptr = stacked_ptr;
|
||||
int img_width = surf_info->output_width;
|
||||
int img_height = surf_info->output_height;
|
||||
int output_stride = surf_info->output_pitch;
|
||||
// Luma
|
||||
if (img_width * surf_info->bytes_per_pixel == output_stride && img_height == surf_info->output_vstride) {
|
||||
memcpy(stacked_ptr, hst_ptr, img_width * surf_info->bytes_per_pixel * img_height);
|
||||
} else {
|
||||
for (i = 0; i < img_height; i++) {
|
||||
memcpy(tmp_stacked_ptr, tmp_hst_ptr, img_width * surf_info->bytes_per_pixel);
|
||||
tmp_hst_ptr += output_stride;
|
||||
tmp_stacked_ptr += img_width * surf_info->bytes_per_pixel;
|
||||
}
|
||||
}
|
||||
// Chroma
|
||||
int img_width_chroma = img_width >> 1;
|
||||
tmp_hst_ptr = hst_ptr + output_stride * surf_info->output_vstride;
|
||||
tmp_stacked_ptr = stacked_ptr + img_width * surf_info->bytes_per_pixel * img_height; // Cb
|
||||
uint8_t *tmp_stacked_ptr_v = tmp_stacked_ptr + img_width_chroma * surf_info->bytes_per_pixel * chroma_height_; // Cr
|
||||
for (i = 0; i < chroma_height_; i++) {
|
||||
for ( int j = 0; j < img_width_chroma; j++) {
|
||||
uint8_t *src_ptr, *dst_ptr;
|
||||
// Cb
|
||||
src_ptr = &tmp_hst_ptr[j * surf_info->bytes_per_pixel * 2];
|
||||
dst_ptr = &tmp_stacked_ptr[j * surf_info->bytes_per_pixel];
|
||||
memcpy(dst_ptr, src_ptr, surf_info->bytes_per_pixel);
|
||||
// Cr
|
||||
src_ptr += surf_info->bytes_per_pixel;
|
||||
dst_ptr = &tmp_stacked_ptr_v[j * surf_info->bytes_per_pixel];
|
||||
memcpy(dst_ptr, src_ptr, surf_info->bytes_per_pixel);
|
||||
}
|
||||
tmp_hst_ptr += output_stride;
|
||||
tmp_stacked_ptr += img_width_chroma * surf_info->bytes_per_pixel;
|
||||
tmp_stacked_ptr_v += img_width_chroma * surf_info->bytes_per_pixel;
|
||||
}
|
||||
|
||||
int img_size = img_width * surf_info->bytes_per_pixel * (img_height + chroma_height_);
|
||||
av_md5_update(md5_ctx_, stacked_ptr, img_size);
|
||||
|
||||
if (hst_ptr && (surf_info->mem_type != OUT_SURFACE_MEM_HOST_COPIED)) {
|
||||
delete [] hst_ptr;
|
||||
}
|
||||
delete [] stacked_ptr;
|
||||
}
|
||||
|
||||
void RocVideoDecoder::FinalizeMd5(uint8_t **digest) {
|
||||
av_md5_final(md5_ctx_, md5_digest_);
|
||||
av_freep(&md5_ctx_);
|
||||
*digest = md5_digest_;
|
||||
}
|
||||
|
||||
void RocVideoDecoder::GetDeviceinfo(std::string &device_name, std::string &gcn_arch_name, int &pci_bus_id, int &pci_domain_id, int &pci_device_id) {
|
||||
device_name = hip_dev_prop_.name;
|
||||
gcn_arch_name = hip_dev_prop_.gcnArchName;
|
||||
|
||||
@@ -34,6 +34,10 @@ THE SOFTWARE.
|
||||
#include <stdexcept>
|
||||
#include <exception>
|
||||
#include <hip/hip_runtime.h>
|
||||
extern "C" {
|
||||
#include "libavutil/md5.h"
|
||||
#include "libavutil/mem.h"
|
||||
}
|
||||
#include "rocdecode.h"
|
||||
#include "rocparser.h"
|
||||
|
||||
@@ -281,6 +285,26 @@ class RocVideoDecoder {
|
||||
*/
|
||||
void SaveFrameToFile(std::string output_file_name, void *surf_mem, OutputSurfaceInfo *surf_info);
|
||||
|
||||
/**
|
||||
* @brief Helper function to start MD5 calculation
|
||||
*/
|
||||
void InitMd5();
|
||||
|
||||
/**
|
||||
* @brief Helper function to dump decoded output surface to file
|
||||
*
|
||||
* @param dev_mem - pointer to surface memory
|
||||
* @param surf_info - surface info
|
||||
*/
|
||||
void UpdateMd5ForFrame(void *surf_mem, OutputSurfaceInfo *surf_info);
|
||||
|
||||
/**
|
||||
* @brief Helper function to complete MD5 calculation
|
||||
*
|
||||
* @param [out] digest Pointer to the 16 byte message digest
|
||||
*/
|
||||
void FinalizeMd5(uint8_t **digest);
|
||||
|
||||
private:
|
||||
int decoder_session_id_; // Decoder session identifier. Used to gather session level stats.
|
||||
/**
|
||||
@@ -375,4 +399,6 @@ class RocVideoDecoder {
|
||||
Rect crop_rect_ = {};
|
||||
FILE *fp_sei_ = NULL;
|
||||
FILE *fp_out_ = NULL;
|
||||
struct AVMD5 *md5_ctx_;
|
||||
uint8_t md5_digest_[16];
|
||||
};
|
||||
Reference in New Issue
Block a user