diff --git a/projects/rocdecode/samples/common.h b/projects/rocdecode/samples/common.h index 225fcc215d..da22badfb1 100644 --- a/projects/rocdecode/samples/common.h +++ b/projects/rocdecode/samples/common.h @@ -25,8 +25,9 @@ THE SOFTWARE. #include "roc_video_dec.h" typedef enum ReconfigFlushMode_enum { - RECONFIG_FLUSH_MODE_DUMP_TO_FILE = 0, /**< The remaining frames will be dumped to file in this mode */ - //TODO;; Add new flush modes here : defined by the application + RECONFIG_FLUSH_MODE_NONE = 0, /**< Just flush to get the frame count */ + RECONFIG_FLUSH_MODE_DUMP_TO_FILE = 1, /**< The remaining frames will be dumped to file in this mode */ + RECONFIG_FLUSH_MODE_CALCULATE_MD5 = 2, /**< Calculate the MD5 of the flushed frames */ } ReconfigFlushMode; // this struct is used by videodecode and videodecodeMultiFiles to dump last frames to file @@ -47,20 +48,24 @@ int ReconfigureFlushCallback(void *p_viddec_obj, uint32_t flush_mode, void *p_us std::cerr << "Error: Failed to get Output Surface Info!" << std::endl; return n_frames_flushed; } - if (flush_mode == ReconfigFlushMode::RECONFIG_FLUSH_MODE_DUMP_TO_FILE) { - ReconfigDumpFileStruct *p_dump_file_struct = static_cast(p_user_struct); - uint8_t *pframe = nullptr; - int64_t pts; - while ((pframe = viddec->GetFrame(&pts))) { - if (p_dump_file_struct->b_dump_frames_to_file) { - viddec->SaveFrameToFile(p_dump_file_struct->output_file_name, pframe, surf_info); + + uint8_t *pframe = nullptr; + int64_t pts; + while ((pframe = viddec->GetFrame(&pts))) { + if (flush_mode != RECONFIG_FLUSH_MODE_NONE) { + if (flush_mode == ReconfigFlushMode::RECONFIG_FLUSH_MODE_DUMP_TO_FILE) { + ReconfigDumpFileStruct *p_dump_file_struct = static_cast(p_user_struct); + if (p_dump_file_struct->b_dump_frames_to_file) { + viddec->SaveFrameToFile(p_dump_file_struct->output_file_name, pframe, surf_info); + } + } else if (flush_mode == ReconfigFlushMode::RECONFIG_FLUSH_MODE_CALCULATE_MD5) { + viddec->UpdateMd5ForFrame(pframe, surf_info); } - // release and flush frame - viddec->ReleaseFrame(pts, true); - n_frames_flushed ++; } - } else { - //todo:: handle other cases + // release and flush frame + viddec->ReleaseFrame(pts, true); + n_frames_flushed ++; } + return n_frames_flushed; } diff --git a/projects/rocdecode/samples/videoDecode/videodecode.cpp b/projects/rocdecode/samples/videoDecode/videodecode.cpp index 12664f1e33..e5fe2d0f44 100644 --- a/projects/rocdecode/samples/videoDecode/videodecode.cpp +++ b/projects/rocdecode/samples/videoDecode/videodecode.cpp @@ -186,7 +186,13 @@ int main(int argc, char **argv) { reconfig_params.p_fn_reconfigure_flush = ReconfigureFlushCallback; reconfig_user_struct.b_dump_frames_to_file = dump_output_frames; reconfig_user_struct.output_file_name = output_file_path; - reconfig_params.reconfig_flush_mode = RECONFIG_FLUSH_MODE_DUMP_TO_FILE; + if (dump_output_frames) { + reconfig_params.reconfig_flush_mode = RECONFIG_FLUSH_MODE_DUMP_TO_FILE; + } else if (b_generate_md5) { + reconfig_params.reconfig_flush_mode = RECONFIG_FLUSH_MODE_CALCULATE_MD5; + } else { + reconfig_params.reconfig_flush_mode = RECONFIG_FLUSH_MODE_NONE; + } reconfig_params.p_reconfig_user_struct = &reconfig_user_struct; if (b_generate_md5) { @@ -195,7 +201,7 @@ int main(int argc, char **argv) { if (b_md5_check) { ref_md5_file.open(md5_file_path.c_str(), std::ios::in); } - if (dump_output_frames) viddec.SetReconfigParams(&reconfig_params); + viddec.SetReconfigParams(&reconfig_params); do { auto start_time = std::chrono::high_resolution_clock::now(); diff --git a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp index ba450730bc..9b52fba661 100644 --- a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp +++ b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.cpp @@ -293,7 +293,7 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { return 0; } - if (width_ && height_ && chroma_height_) { + if (coded_width_ && coded_height_) { // rocdecCreateDecoder() has been called before, and now there's possible config change return ReconfigureDecoder(p_video_format); } @@ -354,23 +354,25 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { videoDecodeCreateInfo.ulMaxWidth = max_width_; videoDecodeCreateInfo.ulMaxHeight = max_height_; + coded_width_ = p_video_format->coded_width; + coded_height_ = p_video_format->coded_height; if (!(crop_rect_.r && crop_rect_.b)) { - width_ = p_video_format->display_area.right - p_video_format->display_area.left; - height_ = p_video_format->display_area.bottom - p_video_format->display_area.top; - videoDecodeCreateInfo.ulTargetWidth = width_; - videoDecodeCreateInfo.ulTargetHeight = height_; + disp_width_ = p_video_format->display_area.right - p_video_format->display_area.left; + disp_height_ = p_video_format->display_area.bottom - p_video_format->display_area.top; + videoDecodeCreateInfo.ulTargetWidth = disp_width_; + videoDecodeCreateInfo.ulTargetHeight = disp_height_; } else { videoDecodeCreateInfo.display_area.left = crop_rect_.l; videoDecodeCreateInfo.display_area.top = crop_rect_.t; videoDecodeCreateInfo.display_area.right = crop_rect_.r; videoDecodeCreateInfo.display_area.bottom = crop_rect_.b; - width_ = crop_rect_.r - crop_rect_.l; - height_ = crop_rect_.b - crop_rect_.t; - videoDecodeCreateInfo.ulTargetWidth = (width_ + 1) & ~1; - videoDecodeCreateInfo.ulTargetHeight = (height_ + 1) & ~1; + disp_width_ = crop_rect_.r - crop_rect_.l; + disp_height_ = crop_rect_.b - crop_rect_.t; + videoDecodeCreateInfo.ulTargetWidth = (disp_width_ + 1) & ~1; + videoDecodeCreateInfo.ulTargetHeight = (disp_height_ + 1) & ~1; } - chroma_height_ = (int)(ceil(height_ * GetChromaHeightFactor(video_surface_format_))); + chroma_height_ = (int)(ceil(disp_height_ * GetChromaHeightFactor(video_surface_format_))); num_chroma_planes_ = GetChromaPlaneCount(video_surface_format_); if (p_video_format->chroma_format == rocDecVideoChromaFormat_Monochrome) num_chroma_planes_ = 0; if (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL) @@ -380,8 +382,8 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) { } chroma_vstride_ = (int)(ceil(surface_vstride_ * GetChromaHeightFactor(video_surface_format_))); // fill output_surface_info_ - output_surface_info_.output_width = width_; - output_surface_info_.output_height = height_; + output_surface_info_.output_width = disp_width_; + output_surface_info_.output_height = disp_height_; output_surface_info_.output_pitch = surface_stride_; output_surface_info_.output_vstride = (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL) ? surface_vstride_ : videoDecodeCreateInfo.ulTargetHeight; output_surface_info_.bit_depth = bitdepth_minus_8_ + 8; @@ -455,26 +457,18 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { return 0; } - bool is_decode_res_changed = !(p_video_format->coded_width == width_ && p_video_format->coded_height == height_); + bool is_decode_res_changed = !(p_video_format->coded_width == coded_width_ && p_video_format->coded_height == coded_height_); bool is_display_rect_changed = !(p_video_format->display_area.bottom == disp_rect_.b && p_video_format->display_area.top == disp_rect_.t && p_video_format->display_area.left == disp_rect_.l && p_video_format->display_area.right == disp_rect_.r); - if (!is_decode_res_changed) { - // if the coded_width and coded_height hasn't changed but display resolution has changed, then need to update width and height for - // correct output without cropping. There is no need to reconfigure the decoder. - if (is_display_rect_changed) { - width_ = p_video_format->display_area.right - p_video_format->display_area.left; - height_ = p_video_format->display_area.bottom - p_video_format->display_area.top; - chroma_height_ = static_cast(std::ceil(height_ * GetChromaHeightFactor(video_surface_format_))); - num_chroma_planes_ = GetChromaPlaneCount(video_surface_format_); - } + if (!is_decode_res_changed && !is_display_rect_changed) { return 1; } - // flush and clear internal frame store to reconfigure + + // Flush and clear internal frame store to reconfigure when either coded size or display size has changed. if (p_reconfig_params_ && p_reconfig_params_->p_fn_reconfigure_flush) - num_frames_flushed_during_reconfig_ = p_reconfig_params_->p_fn_reconfigure_flush(this, p_reconfig_params_->reconfig_flush_mode, - static_cast(p_reconfig_params_->p_reconfig_user_struct)); + num_frames_flushed_during_reconfig_ += p_reconfig_params_->p_fn_reconfigure_flush(this, p_reconfig_params_->reconfig_flush_mode, static_cast(p_reconfig_params_->p_reconfig_user_struct)); // clear the existing output buffers of different size // note that app lose the remaining frames in the vp_frames/vp_frames_q in case application didn't set p_fn_reconfigure_flush_ callback if (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL) { @@ -497,14 +491,26 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { } decoded_frame_cnt_ = 0; //reset frame_count - width_ = p_video_format->coded_width; - height_ = p_video_format->coded_height; + // If the coded_width or coded_height hasn't changed but display resolution has changed, then need to update width and height for + // correct output with cropping. There is no need to reconfigure the decoder. + if (!is_decode_res_changed && is_display_rect_changed) { + disp_width_ = p_video_format->display_area.right - p_video_format->display_area.left; + disp_height_ = p_video_format->display_area.bottom - p_video_format->display_area.top; + chroma_height_ = static_cast(std::ceil(disp_height_ * GetChromaHeightFactor(video_surface_format_))); + num_chroma_planes_ = GetChromaPlaneCount(video_surface_format_); + return 1; + } + + coded_width_ = p_video_format->coded_width; + coded_height_ = p_video_format->coded_height; + disp_width_ = p_video_format->display_area.right - p_video_format->display_area.left; + disp_height_ = p_video_format->display_area.bottom - p_video_format->display_area.top; RocdecReconfigureDecoderInfo reconfig_params = {0}; - reconfig_params.ulWidth = width_; - reconfig_params.ulHeight = height_; - reconfig_params.ulTargetWidth = (width_ + 1) & ~1; - reconfig_params.ulTargetHeight = (height_ + 1) & ~1; + reconfig_params.ulWidth = coded_width_; + reconfig_params.ulHeight = coded_height_; + reconfig_params.ulTargetWidth = (disp_width_ + 1) & ~1; + reconfig_params.ulTargetHeight = (disp_height_ + 1) & ~1; reconfig_params.ulNumDecodeSurfaces = p_video_format->min_num_decode_surfaces; reconfig_params.roi_area.left = crop_rect_.l; reconfig_params.roi_area.top = crop_rect_.t; @@ -520,13 +526,13 @@ int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) { } else { surface_stride_ = reconfig_params.ulTargetWidth * byte_per_pixel_; } - chroma_height_ = static_cast(ceil(height_ * GetChromaHeightFactor(video_surface_format_))); + chroma_height_ = static_cast(ceil(disp_height_ * GetChromaHeightFactor(video_surface_format_))); num_chroma_planes_ = GetChromaPlaneCount(video_surface_format_); if (p_video_format->chroma_format == rocDecVideoChromaFormat_Monochrome) num_chroma_planes_ = 0; chroma_vstride_ = static_cast(std::ceil(surface_vstride_ * GetChromaHeightFactor(video_surface_format_))); // fill output_surface_info_ - output_surface_info_.output_width = width_; - output_surface_info_.output_height = height_; + output_surface_info_.output_width = disp_width_; + output_surface_info_.output_height = disp_height_; output_surface_info_.output_pitch = surface_stride_; output_surface_info_.output_vstride = (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL) ? surface_vstride_ : reconfig_params.ulTargetHeight; output_surface_info_.bit_depth = bitdepth_minus_8_ + 8; @@ -680,41 +686,41 @@ int RocVideoDecoder::HandlePictureDisplay(RocdecParserDispInfo *pDispInfo) { int dst_pitch = surface_stride_; if (out_mem_type_ == OUT_SURFACE_MEM_DEV_COPIED) { if (src_pitch[0] == dst_pitch) { - int luma_size = src_pitch[0] * height_; + int luma_size = src_pitch[0] * coded_height_; HIP_API_CALL(hipMemcpyDtoDAsync(p_dec_frame, src_dev_ptr[0], luma_size, hip_stream_)); } else { // use 2d copy to copy an ROI - HIP_API_CALL(hipMemcpy2DAsync(p_dec_frame, dst_pitch, src_dev_ptr[0], src_pitch[0], width_ * byte_per_pixel_, height_, hipMemcpyDeviceToDevice, hip_stream_)); + HIP_API_CALL(hipMemcpy2DAsync(p_dec_frame, dst_pitch, src_dev_ptr[0], src_pitch[0], coded_width_ * byte_per_pixel_, coded_height_, hipMemcpyDeviceToDevice, hip_stream_)); } } else - HIP_API_CALL(hipMemcpy2DAsync(p_dec_frame, width_ * byte_per_pixel_, src_dev_ptr[0], src_pitch[0], width_ * byte_per_pixel_, height_, hipMemcpyDeviceToHost, hip_stream_)); + HIP_API_CALL(hipMemcpy2DAsync(p_dec_frame, coded_width_ * byte_per_pixel_, src_dev_ptr[0], src_pitch[0], coded_width_ * byte_per_pixel_, coded_height_, hipMemcpyDeviceToHost, hip_stream_)); // Copy chroma plane ( ) // rocDec output gives pointer to luma and chroma pointers seperated for the decoded frame - uint8_t *p_frame_uv = p_dec_frame + dst_pitch * height_; + uint8_t *p_frame_uv = p_dec_frame + dst_pitch * coded_height_; if (out_mem_type_ == OUT_SURFACE_MEM_DEV_COPIED) { if (src_pitch[1] == dst_pitch) { int chroma_size = chroma_height_ * dst_pitch; HIP_API_CALL(hipMemcpyDtoDAsync(p_frame_uv, src_dev_ptr[1], chroma_size, hip_stream_)); } else { // use 2d copy to copy an ROI - HIP_API_CALL(hipMemcpy2DAsync(p_frame_uv, dst_pitch, src_dev_ptr[1], src_pitch[1], width_ * byte_per_pixel_, chroma_height_, hipMemcpyDeviceToDevice, hip_stream_)); + HIP_API_CALL(hipMemcpy2DAsync(p_frame_uv, dst_pitch, src_dev_ptr[1], src_pitch[1], coded_width_ * byte_per_pixel_, chroma_height_, hipMemcpyDeviceToDevice, hip_stream_)); } } else - HIP_API_CALL(hipMemcpy2DAsync(p_frame_uv, dst_pitch, src_dev_ptr[1], src_pitch[1], width_ * byte_per_pixel_, chroma_height_, hipMemcpyDeviceToHost, hip_stream_)); + HIP_API_CALL(hipMemcpy2DAsync(p_frame_uv, dst_pitch, src_dev_ptr[1], src_pitch[1], coded_width_ * byte_per_pixel_, chroma_height_, hipMemcpyDeviceToHost, hip_stream_)); if (num_chroma_planes_ == 2) { - uint8_t *p_frame_uv = p_dec_frame + dst_pitch * (height_ + chroma_height_); + uint8_t *p_frame_uv = p_dec_frame + dst_pitch * (coded_height_ + chroma_height_); if (out_mem_type_ == OUT_SURFACE_MEM_DEV_COPIED) { if (src_pitch[2] == dst_pitch) { int chroma_size = chroma_height_ * dst_pitch; HIP_API_CALL(hipMemcpyDtoDAsync(p_frame_uv, src_dev_ptr[2], chroma_size, hip_stream_)); } else { // use 2d copy to copy an ROI - HIP_API_CALL(hipMemcpy2DAsync(p_frame_uv, dst_pitch, src_dev_ptr[2], src_pitch[2], width_*byte_per_pixel_, chroma_height_, hipMemcpyDeviceToDevice, hip_stream_)); + HIP_API_CALL(hipMemcpy2DAsync(p_frame_uv, dst_pitch, src_dev_ptr[2], src_pitch[2], coded_width_ * byte_per_pixel_, chroma_height_, hipMemcpyDeviceToDevice, hip_stream_)); } } else - HIP_API_CALL(hipMemcpy2DAsync(p_frame_uv, dst_pitch, src_dev_ptr[2], src_pitch[2], width_*byte_per_pixel_, chroma_height_, hipMemcpyDeviceToHost, hip_stream_)); + HIP_API_CALL(hipMemcpy2DAsync(p_frame_uv, dst_pitch, src_dev_ptr[2], src_pitch[2], coded_width_ * byte_per_pixel_, chroma_height_, hipMemcpyDeviceToHost, hip_stream_)); } HIP_API_CALL(hipStreamSynchronize(hip_stream_)); @@ -888,7 +894,8 @@ void RocVideoDecoder::SaveFrameToFile(std::string output_file_name, void *surf_m // don't append to the output_file_name if multiple output file name is provided (e.g., decoding multi-files using the videDecodeMultiFiles) if (!current_output_filename.compare(output_file_name)) { std::string::size_type const pos(output_file_name.find_last_of('.')); - std::string to_append = "_" + std::to_string(surf_info->output_width) + "_" + std::to_string(surf_info->output_height); + extra_output_file_count_++; + std::string to_append = "_" + std::to_string(surf_info->output_width) + "_" + std::to_string(surf_info->output_height) + "_" + std::to_string(extra_output_file_count_); if (pos != std::string::npos) { output_file_name.insert(pos, to_append); } else { @@ -1052,7 +1059,7 @@ void RocVideoDecoder::GetDeviceinfo(std::string &device_name, std::string &gcn_a bool RocVideoDecoder::GetOutputSurfaceInfo(OutputSurfaceInfo **surface_info) { - if (!width_ || !height_) { + if (!disp_width_ || !disp_height_) { std::cerr << "ERROR: RocVideoDecoderr is not intialized" << std::endl; return false; } diff --git a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h index 5ec0b726ad..17b434107c 100644 --- a/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h +++ b/projects/rocdecode/utils/rocvideodecode/roc_video_dec.h @@ -171,17 +171,17 @@ class RocVideoDecoder { /** * @brief Get the output frame width */ - uint32_t GetWidth() { assert(width_); return width_;} + uint32_t GetWidth() { assert(disp_width_); return disp_width_;} /** * @brief This function is used to get the actual decode width */ - int GetDecodeWidth() { assert(width_); return width_; } + int GetDecodeWidth() { assert(coded_width_); return coded_width_; } /** * @brief Get the output frame height */ - uint32_t GetHeight() { assert(height_); return height_; } + uint32_t GetHeight() { assert(disp_height_); return disp_height_; } /** * @brief This function is used to get the current chroma height. @@ -196,12 +196,12 @@ class RocVideoDecoder { /** * @brief This function is used to get the current frame size based on pixel format. */ - int GetFrameSize() { assert(width_); return width_ * (height_ + (chroma_height_ * num_chroma_planes_)) * byte_per_pixel_; } + int GetFrameSize() { assert(disp_width_); return disp_width_ * (disp_height_ + (chroma_height_ * num_chroma_planes_)) * byte_per_pixel_; } /** * @brief This function is used to get the current frame size based on pitch */ - int GetFrameSizePitched() { assert(surface_stride_); return surface_stride_ * (height_ + (chroma_height_ * num_chroma_planes_)); } + int GetFrameSizePitched() { assert(surface_stride_); return surface_stride_ * (disp_height_ + (chroma_height_ * num_chroma_planes_)); } /** * @brief Get the Bit Depth and BytesPerPixel associated with the pixel format @@ -417,8 +417,10 @@ class RocVideoDecoder { std::ostringstream input_video_info_str_; int bitdepth_minus_8_ = 0; uint32_t byte_per_pixel_ = 1; - uint32_t width_ = 0; - uint32_t height_ = 0; + uint32_t coded_width_ = 0; + uint32_t disp_width_ = 0; + uint32_t coded_height_ = 0; + uint32_t disp_height_ = 0; int max_width_ = 0, max_height_ = 0; uint32_t chroma_height_ = 0; uint32_t num_chroma_planes_ = 0; @@ -438,4 +440,5 @@ class RocVideoDecoder { uint8_t md5_digest_[16]; bool is_decoder_reconfigured_ = false; std::string current_output_filename = ""; + uint32_t extra_output_file_count_ = 0; }; \ No newline at end of file