obs-qsv11: Fix timestamp for fractional frame rate
This commit rounds the timestamp to the integer multiple of fps_den. Prior to this change, since the timestamp in MFX is defined in units of 90 kHz, timestamps for 60000/1001 fps is not accurately expressed. Also the encoder sometimes returns the decode time stamp slightly off. Hence, the timestamp in OBS becomes not a multiple of fps_den after converting back from the timestamp in MFX.
This commit is contained in:
parent
b65411c343
commit
56c502b254
@ -826,8 +826,23 @@ static void obs_qsv_video_info(void *data, struct video_scale_info *info)
|
||||
cap_resolution(obsqsv->encoder, info);
|
||||
}
|
||||
|
||||
static mfxU64 ts_obs_to_mfx(int64_t ts, const struct video_output_info *voi)
|
||||
{
|
||||
return ts * 90000 / voi->fps_num;
|
||||
}
|
||||
|
||||
static int64_t ts_mfx_to_obs(mfxI64 ts, const struct video_output_info *voi)
|
||||
{
|
||||
int64_t div = 90000 * (int64_t)voi->fps_den;
|
||||
/* Round to the nearest integer multiple of `voi->fps_den`. */
|
||||
if (ts < 0)
|
||||
return (ts * voi->fps_num - div / 2) / div * voi->fps_den;
|
||||
else
|
||||
return (ts * voi->fps_num + div / 2) / div * voi->fps_den;
|
||||
}
|
||||
|
||||
static void parse_packet(struct obs_qsv *obsqsv, struct encoder_packet *packet,
|
||||
mfxBitstream *pBS, uint32_t fps_num,
|
||||
mfxBitstream *pBS, const struct video_output_info *voi,
|
||||
bool *received_packet)
|
||||
{
|
||||
uint8_t *start, *end;
|
||||
@ -845,7 +860,7 @@ static void parse_packet(struct obs_qsv *obsqsv, struct encoder_packet *packet,
|
||||
packet->data = obsqsv->packet_data.array;
|
||||
packet->size = obsqsv->packet_data.num;
|
||||
packet->type = OBS_ENCODER_VIDEO;
|
||||
packet->pts = pBS->TimeStamp * fps_num / 90000;
|
||||
packet->pts = ts_mfx_to_obs((mfxI64)pBS->TimeStamp, voi);
|
||||
packet->keyframe = (pBS->FrameType & MFX_FRAMETYPE_IDR);
|
||||
|
||||
uint16_t frameType = pBS->FrameType;
|
||||
@ -906,7 +921,7 @@ static void parse_packet(struct obs_qsv *obsqsv, struct encoder_packet *packet,
|
||||
g_prevDts = packet->dts;
|
||||
}
|
||||
} else {
|
||||
packet->dts = pBS->DecodeTimeStamp * fps_num / 90000;
|
||||
packet->dts = ts_mfx_to_obs(pBS->DecodeTimeStamp, voi);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -940,7 +955,7 @@ static bool obs_qsv_encode(void *data, struct encoder_frame *frame,
|
||||
|
||||
int ret;
|
||||
|
||||
mfxU64 qsvPTS = frame->pts * 90000 / voi->fps_num;
|
||||
mfxU64 qsvPTS = ts_obs_to_mfx(frame->pts, voi);
|
||||
|
||||
// FIXME: remove null check from the top of this function
|
||||
// if we actually do expect null frames to complete output.
|
||||
@ -959,7 +974,7 @@ static bool obs_qsv_encode(void *data, struct encoder_frame *frame,
|
||||
return false;
|
||||
}
|
||||
|
||||
parse_packet(obsqsv, packet, pBS, voi->fps_num, received_packet);
|
||||
parse_packet(obsqsv, packet, pBS, voi, received_packet);
|
||||
|
||||
LeaveCriticalSection(&g_QsvCs);
|
||||
|
||||
@ -991,7 +1006,7 @@ static bool obs_qsv_encode_tex(void *data, uint32_t handle, int64_t pts,
|
||||
|
||||
int ret;
|
||||
|
||||
mfxU64 qsvPTS = pts * 90000 / voi->fps_num;
|
||||
mfxU64 qsvPTS = ts_obs_to_mfx(pts, voi);
|
||||
|
||||
ret = qsv_encoder_encode_tex(obsqsv->context, qsvPTS, handle, lock_key,
|
||||
next_key, &pBS);
|
||||
@ -1002,7 +1017,7 @@ static bool obs_qsv_encode_tex(void *data, uint32_t handle, int64_t pts,
|
||||
return false;
|
||||
}
|
||||
|
||||
parse_packet(obsqsv, packet, pBS, voi->fps_num, received_packet);
|
||||
parse_packet(obsqsv, packet, pBS, voi, received_packet);
|
||||
|
||||
LeaveCriticalSection(&g_QsvCs);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user