From 81ee2a9f2a07b6bba2d63579f55062aaeac61c2d Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Mon, 25 Apr 2022 22:59:14 +0900 Subject: [PATCH] qsvencoder: Workaround for invalid DTS with VP9 SDK runtime seems to report zero DTS for all frames in case of VP9 but we don't need to use DTS for the codec. Part-of: --- .../gst-plugins-bad/sys/qsv/gstqsvencoder.cpp | 37 ++++++++++++++++------ 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.cpp b/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.cpp index e16a13a..3b6e747 100644 --- a/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.cpp +++ b/subprojects/gst-plugins-bad/sys/qsv/gstqsvencoder.cpp @@ -704,8 +704,8 @@ gst_qsv_encoder_finish_frame (GstQsvEncoder * self, GstQsvEncoderTask * task, mfxStatus status; mfxBitstream *bs; GstVideoCodecFrame *frame; - GstClockTime pts = GST_CLOCK_TIME_NONE; - GstClockTime dts = GST_CLOCK_TIME_NONE; + GstClockTime qsv_pts = GST_CLOCK_TIME_NONE; + GstClockTime qsv_dts = GST_CLOCK_TIME_NONE; GstBuffer *buffer; gboolean keyframe = FALSE; guint retry_count = 0; @@ -750,8 +750,19 @@ gst_qsv_encoder_finish_frame (GstQsvEncoder * self, GstQsvEncoderTask * task, } bs = &task->bitstream; - pts = gst_qsv_timestamp_to_gst (bs->TimeStamp); - dts = gst_qsv_timestamp_to_gst ((mfxU64) bs->DecodeTimeStamp); + qsv_pts = gst_qsv_timestamp_to_gst (bs->TimeStamp); + + /* SDK runtime seems to report zero DTS for all fraems in case of VP9. + * It sounds SDK bug, but we can workaround it safely because VP9 B-frame is + * not supported in this implementation. + * + * Also we perfer our nanoseconds timestamp instead of QSV's timescale. + * So let' ignore QSV's timescale for non-{h264,h265} cases. + * + * TODO: We may need to use DTS for MPEG2 (not implemented yet) + */ + if (klass->codec_id == MFX_CODEC_AVC || klass->codec_id == MFX_CODEC_HEVC) + qsv_dts = gst_qsv_timestamp_to_gst ((mfxU64) bs->DecodeTimeStamp); if ((bs->FrameType & MFX_FRAMETYPE_IDR) != 0) keyframe = TRUE; @@ -768,10 +779,15 @@ gst_qsv_encoder_finish_frame (GstQsvEncoder * self, GstQsvEncoderTask * task, return GST_FLOW_ERROR; } - frame = gst_qsv_encoder_find_output_frame (self, pts); + frame = gst_qsv_encoder_find_output_frame (self, qsv_pts); if (frame) { - frame->pts = pts; - frame->dts = dts; + if (GST_CLOCK_TIME_IS_VALID (qsv_dts)) { + frame->pts = qsv_pts; + frame->dts = qsv_dts; + } else { + frame->dts = frame->pts; + } + frame->output_buffer = buffer; if (keyframe) @@ -783,8 +799,11 @@ gst_qsv_encoder_finish_frame (GstQsvEncoder * self, GstQsvEncoderTask * task, /* Empty available frame, something went wrong but we can just push this * buffer */ GST_WARNING_OBJECT (self, "Failed to find corresponding frame"); - GST_BUFFER_PTS (buffer) = pts; - GST_BUFFER_DTS (buffer) = dts; + GST_BUFFER_PTS (buffer) = qsv_pts; + if (GST_CLOCK_TIME_IS_VALID (qsv_dts)) + GST_BUFFER_DTS (buffer) = qsv_dts; + else + GST_BUFFER_DTS (buffer) = qsv_pts; if (!keyframe) GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); -- 2.7.4