Add support for rocDecReconfigureDecoder API (#116)

* Add support for rocDecReconfigureDecoder API

* adrress reviewer's comemnts

* Add doxygen comment for ReconfigureDecoder function

[ROCm/rocdecode commit: 875994bb4f]
This commit is contained in:
Aryan Salmanpour
2023-12-05 11:16:32 -05:00
committed by GitHub
parent 62fb6aa511
commit 70a18314d5
6 changed files with 166 additions and 23 deletions
@@ -77,11 +77,15 @@ rocDecStatus RocDecoder::GetDecodeStatus(int pic_idx, RocdecDecodeStatus* decode
}
rocDecStatus RocDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconfig_params) {
// todo:: return appropriate decStatus
// this will be called when the current configuration is changed during decoding
// release the current va-api decoder instance and create a new one with the new parameters (or reinit if available)
// return status
return ROCDEC_NOT_IMPLEMENTED;
if (reconfig_params == nullptr) {
return ROCDEC_INVALID_PARAMETER;
}
rocDecStatus rocdec_status = va_video_decoder_.ReconfigureDecoder(reconfig_params);
if (rocdec_status != ROCDEC_SUCCESS) {
ERR("ERROR: Reconfiguration of the decoder failed with rocDecStatus# " + TOSTR(rocdec_status));
return rocdec_status;
}
return rocdec_status;
}
rocDecStatus RocDecoder::MapVideoFrame(int pic_idx, void *dev_mem_ptr[3], uint32_t horizontal_pitch[3], RocdecProcParams *vid_postproc_params) {
@@ -143,6 +143,9 @@ rocDecGetDecodeStatus(rocDecDecoderHandle decoder_handle, int pic_idx, RocdecDec
/*********************************************************************************************************/
rocDecStatus ROCDECAPI
rocDecReconfigureDecoder(rocDecDecoderHandle decoder_handle, RocdecReconfigureDecoderInfo *reconfig_params) {
if (decoder_handle == nullptr || reconfig_params == nullptr) {
return ROCDEC_INVALID_PARAMETER;
}
auto handle = static_cast<DecHandle *> (decoder_handle);
rocDecStatus ret;
try {
@@ -323,3 +323,44 @@ rocDecStatus VaapiVideoDecoder::ExportSurface(int pic_idx, VADRMPRIMESurfaceDesc
return ROCDEC_SUCCESS;
}
rocDecStatus VaapiVideoDecoder::ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconfig_params) {
if (reconfig_params == nullptr) {
return ROCDEC_INVALID_PARAMETER;
}
if (va_display_ == 0) {
ERR("ERROR: VAAPI decoder has not been initialized but reconfiguration of the decoder has been requested!");
return ROCDEC_NOT_SUPPORTED;
}
rocDecStatus rocdec_status = DestroyDataBuffers();
if (rocdec_status != ROCDEC_SUCCESS) {
ERR("ERROR: Failed to destroy VAAPI buffers during the reconfiguration, with rocDecStatus# " + TOSTR(rocdec_status));
return rocdec_status;
}
CHECK_VAAPI(vaDestroySurfaces(va_display_, va_surface_ids_.data(), va_surface_ids_.size()));
CHECK_VAAPI(vaDestroyContext(va_display_, va_context_id_));
va_surface_ids_.clear();
decoder_create_info_.ulWidth = reconfig_params->ulWidth;
decoder_create_info_.ulHeight = reconfig_params->ulHeight;
decoder_create_info_.ulNumDecodeSurfaces = reconfig_params->ulNumDecodeSurfaces;
decoder_create_info_.ulTargetHeight = reconfig_params->ulTargetHeight;
decoder_create_info_.ulTargetWidth = reconfig_params->ulTargetWidth;
rocdec_status = CreateSurfaces();
if (rocdec_status != ROCDEC_SUCCESS) {
ERR("ERROR: Failed to create VAAPI surfaces during the decoder reconfiguration " + TOSTR(rocdec_status));
return rocdec_status;
}
rocdec_status = CreateContext();
if (rocdec_status != ROCDEC_SUCCESS) {
ERR("ERROR: Failed to create a VAAPI context during the decoder reconfiguration " + TOSTR(rocdec_status));
return rocdec_status;
}
rocdec_status = CreateDataBuffers();
if (rocdec_status != ROCDEC_SUCCESS) {
ERR("ERROR: Failed to create VAAPI buffers during the decoder reconfiguration " + TOSTR(rocdec_status));
return rocdec_status;
}
return rocdec_status;
}
@@ -52,7 +52,7 @@ public:
rocDecStatus SubmitDecode(RocdecPicParams *pPicParams);
rocDecStatus GetDecodeStatus(int pic_idx, RocdecDecodeStatus* decode_status);
rocDecStatus ExportSurface(int pic_idx, VADRMPRIMESurfaceDescriptor &va_drm_prime_surface_desc);
rocDecStatus ReconfigureDecoder(RocdecReconfigureDecoderInfo *reconfig_params);
private:
RocDecoderCreateInfo decoder_create_info_;
int drm_fd_;
@@ -270,10 +270,8 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) {
}
if (width_ && height_ && chroma_height_) {
// rocdecCreateDecoder() has been called before, and now there's possible config change
// todo:: support reconfigure
//return ReconfigureDecoder(p_video_format);
return ReconfigureDecoder(p_video_format);
}
// e_codec has been set in the constructor (for parser). Here it's set again for potential correction
@@ -395,10 +393,108 @@ int RocVideoDecoder::HandleVideoSequence(RocdecVideoFormat *p_video_format) {
return nDecodeSurface;
}
/**
* @brief function to reconfigure decoder if there is a change in sequence params.
*
* @param p_video_format
* @return int 1: success 0: fail
*/
int RocVideoDecoder::ReconfigureDecoder(RocdecVideoFormat *p_video_format) {
ROCDEC_THROW("ReconfigureDecoder is not supported in this version: ", ROCDEC_NOT_SUPPORTED);
return ROCDEC_NOT_SUPPORTED;
if (p_video_format->codec != codec_id_) {
ROCDEC_THROW("Reconfigure Not supported for codec change", ROCDEC_NOT_SUPPORTED);
return 0;
}
if (p_video_format->chroma_format != video_chroma_format_) {
ROCDEC_THROW("Reconfigure Not supported for chroma format change", ROCDEC_NOT_SUPPORTED);
return 0;
}
if (p_video_format->bit_depth_luma_minus8 != bitdepth_minus_8_){
ROCDEC_THROW("Reconfigure Not supported for bit depth change", ROCDEC_NOT_SUPPORTED);
return 0;
}
bool is_decode_res_changed = !(p_video_format->coded_width == width_ && p_video_format->coded_height == 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<int>(std::ceil(height_ * GetChromaHeightFactor(video_surface_format_)));
num_chroma_planes_ = GetChromaPlaneCount(video_surface_format_);
}
return 1;
}
width_ = p_video_format->coded_width;
height_ = p_video_format->coded_height;
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.ulNumDecodeSurfaces = p_video_format->min_num_decode_surfaces;
reconfig_params.roi_area.left = crop_rect_.l;
reconfig_params.roi_area.top = crop_rect_.t;
reconfig_params.roi_area.right = crop_rect_.r;
reconfig_params.roi_area.bottom = crop_rect_.b;
reconfig_params.target_rect.left = p_video_format->display_area.left;
reconfig_params.target_rect.top = p_video_format->display_area.top;
reconfig_params.target_rect.right = p_video_format->display_area.right;
reconfig_params.target_rect.bottom = p_video_format->display_area.bottom;
if (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL) {
GetSurfaceStrideInternal(video_surface_format_, p_video_format->coded_width, p_video_format->coded_height, &surface_stride_, &surface_vstride_);
} else {
surface_stride_ = reconfig_params.ulTargetWidth * byte_per_pixel_;
}
chroma_vstride_ = static_cast<int>(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_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;
output_surface_info_.bytes_per_pixel = byte_per_pixel_;
output_surface_info_.surface_format = video_surface_format_;
output_surface_info_.num_chroma_planes = num_chroma_planes_;
if (out_mem_type_ == OUT_SURFACE_MEM_DEV_INTERNAL) {
output_surface_info_.output_surface_size_in_bytes = surface_stride_ * (surface_vstride_ + (chroma_vstride_ * num_chroma_planes_));
output_surface_info_.mem_type = OUT_SURFACE_MEM_DEV_INTERNAL;
} else if (out_mem_type_ == OUT_SURFACE_MEM_DEV_COPIED) {
output_surface_info_.output_surface_size_in_bytes = GetFrameSizePitched();
output_surface_info_.mem_type = OUT_SURFACE_MEM_DEV_COPIED;
} else {
output_surface_info_.output_surface_size_in_bytes = GetFrameSize();
output_surface_info_.mem_type = OUT_SURFACE_MEM_HOST_COPIED;
}
if (roc_decoder_ == nullptr) {
ROCDEC_THROW("Reconfigurition of the decoder detected but the decoder was not initialized previoulsy!", ROCDEC_NOT_SUPPORTED);
return 0;
}
ROCDEC_API_CALL(rocDecReconfigureDecoder(roc_decoder_, &reconfig_params));
input_video_info_str_.str("");
input_video_info_str_.clear();
input_video_info_str_ << "Input Video Resolution Changed:" << std::endl
<< "\tCoded size : [" << p_video_format->coded_width << ", " << p_video_format->coded_height << "]" << std::endl
<< "\tDisplay area : [" << p_video_format->display_area.left << ", " << p_video_format->display_area.top << ", "
<< p_video_format->display_area.right << ", " << p_video_format->display_area.bottom << "]" << std::endl;
input_video_info_str_ << std::endl;
input_video_info_str_ << "Video Decoding Params:" << std::endl
<< "\tNum Surfaces : " << reconfig_params.ulNumDecodeSurfaces << std::endl
<< "\tResize : " << reconfig_params.ulTargetWidth << "x" << reconfig_params.ulTargetHeight << std::endl
;
input_video_info_str_ << std::endl;
std::cout << input_video_info_str_.str();
return 1;
}
/**
@@ -650,7 +746,6 @@ bool RocVideoDecoder::ReleaseFrame(int64_t pTimestamp) {
return true;
}
void RocVideoDecoder::SaveFrameToFile(std::string output_file_name, void *surf_mem, OutputSurfaceInfo *surf_info) {
uint8_t *hst_ptr = nullptr;
uint64_t output_image_size = surf_info->output_surface_size_in_bytes;
@@ -384,16 +384,16 @@ class RocVideoDecoder {
std::ostringstream input_video_info_str_;
int bitdepth_minus_8_ = 0;
uint32_t byte_per_pixel_ = 1;
uint32_t width_;
uint32_t height_;
int max_width_, max_height_;
uint32_t chroma_height_;
uint32_t num_chroma_planes_;
uint32_t num_components_;
uint32_t surface_stride_;
uint32_t surface_vstride_, chroma_vstride_; // vertical stride between planes: used when using internal dev memory
size_t surface_size_;
OutputSurfaceInfo output_surface_info_;
uint32_t width_ = 0;
uint32_t height_ = 0;
int max_width_ = 0, max_height_ = 0;
uint32_t chroma_height_ = 0;
uint32_t num_chroma_planes_ = 0;
uint32_t num_components_ = 0;
uint32_t surface_stride_ = 0;
uint32_t surface_vstride_ = 0, chroma_vstride_ = 0; // vertical stride between planes: used when using internal dev memory
size_t surface_size_ = 0;
OutputSurfaceInfo output_surface_info_ = {};
std::mutex mtx_vp_frame_;
std::vector<DecFrameBuffer> vp_frames_; // vector of decoded frames
std::queue<DecFrameBuffer> vp_frames_q_;