diff --git a/src/util/media_capture.cpp b/src/util/media_capture.cpp index cc83cb164..9e6c9fc34 100644 --- a/src/util/media_capture.cpp +++ b/src/util/media_capture.cpp @@ -631,7 +631,6 @@ class MediaCaptureMF final : public MediaCaptureBase template using ComPtr = Microsoft::WRL::ComPtr; - static constexpr u32 FRAME_RATE_NUMERATOR = 10 * 1000 * 1000; static constexpr DWORD INVALID_STREAM_INDEX = std::numeric_limits::max(); static constexpr u32 AUDIO_BITS_PER_SAMPLE = sizeof(s16) * 8; @@ -678,10 +677,12 @@ private: return static_cast((static_cast(pts) * duration) / 1e+7); } - ComPtr CreateVideoYUVTransform(ComPtr* output_type, float fps, Error* error); - ComPtr CreateVideoEncodeTransform(std::string_view codec, float fps, u32 bitrate, - IMFMediaType* input_type, ComPtr* output_type, - bool* use_async_transform, Error* error); + ComPtr CreateVideoYUVTransform(ComPtr* output_type, u32 frame_rate_numerator, + u32 frame_rate_denominator, Error* error); + ComPtr CreateVideoEncodeTransform(std::string_view codec, u32 frame_rate_numerator, + u32 frame_rate_denominator, u32 bitrate, IMFMediaType* input_type, + ComPtr* output_type, bool* use_async_transform, + Error* error); bool GetAudioTypes(std::string_view codec, ComPtr* input_type, ComPtr* output_type, u32 sample_rate, u32 bitrate, Error* error); void ConvertVideoFrame(u8* dst, size_t dst_stride, const u8* src, size_t src_stride, u32 width, u32 height) const; @@ -881,12 +882,17 @@ bool MediaCaptureMF::InternalBeginCapture(float fps, float aspect, u32 sample_ra if (capture_video) { + static constexpr u32 FRAME_RATE_DENOMERATOR = 10 * 1000 * 1000; + const u32 frame_rate_numerator = static_cast(fps) * static_cast(FRAME_RATE_DENOMERATOR); + m_video_sample_duration = ConvertFrequencyToMFDurationUnits(fps); ComPtr yuv_media_type; - if (!(m_video_yuv_transform = CreateVideoYUVTransform(&yuv_media_type, fps, error)) || - !(m_video_encode_transform = CreateVideoEncodeTransform(video_codec, fps, video_bitrate, yuv_media_type.Get(), - &video_media_type, &use_async_video_transform, error))) + if (!(m_video_yuv_transform = + CreateVideoYUVTransform(&yuv_media_type, frame_rate_numerator, FRAME_RATE_DENOMERATOR, error)) || + !(m_video_encode_transform = + CreateVideoEncodeTransform(video_codec, frame_rate_numerator, FRAME_RATE_DENOMERATOR, video_bitrate, + yuv_media_type.Get(), &video_media_type, &use_async_video_transform, error))) { return false; } @@ -993,7 +999,8 @@ bool MediaCaptureMF::InternalEndCapture(std::unique_lock& lock, Erro } MediaCaptureMF::ComPtr MediaCaptureMF::CreateVideoYUVTransform(ComPtr* output_type, - float fps, Error* error) + u32 frame_rate_numerator, + u32 frame_rate_denominator, Error* error) { const MFT_REGISTER_TYPE_INFO input_type_info = {.guidMajorType = MFMediaType_Video, .guidSubtype = VIDEO_RGB_MEDIA_FORMAT}; @@ -1037,14 +1044,14 @@ MediaCaptureMF::ComPtr MediaCaptureMF::CreateVideoYUVTransform(Com FAILED(hr = input_type->SetGUID(MF_MT_SUBTYPE, VIDEO_RGB_MEDIA_FORMAT)) || FAILED(hr = input_type->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) || FAILED(hr = MFSetAttributeSize(input_type.Get(), MF_MT_FRAME_SIZE, m_video_width, m_video_height)) || + FAILED(hr = + MFSetAttributeRatio(input_type.Get(), MF_MT_FRAME_RATE, frame_rate_numerator, frame_rate_denominator)) || FAILED(hr = (*output_type)->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)) || FAILED(hr = (*output_type)->SetGUID(MF_MT_SUBTYPE, VIDEO_YUV_MEDIA_FORMAT)) || FAILED(hr = (*output_type)->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) || FAILED(hr = MFSetAttributeSize(output_type->Get(), MF_MT_FRAME_SIZE, m_video_width, m_video_height)) || - FAILED(hr = MFSetAttributeRatio( - output_type->Get(), MF_MT_FRAME_RATE, - static_cast(static_cast(fps) * static_cast(FRAME_RATE_NUMERATOR)), - FRAME_RATE_NUMERATOR))) [[unlikely]] + FAILED(hr = MFSetAttributeRatio(output_type->Get(), MF_MT_FRAME_RATE, frame_rate_numerator, + frame_rate_denominator))) [[unlikely]] { Error::SetHResult(error, "YUV setting attributes failed: ", hr); return nullptr; @@ -1065,10 +1072,10 @@ MediaCaptureMF::ComPtr MediaCaptureMF::CreateVideoYUVTransform(Com return transform; } -MediaCaptureMF::ComPtr MediaCaptureMF::CreateVideoEncodeTransform(std::string_view codec, float fps, - u32 bitrate, IMFMediaType* input_type, - ComPtr* output_type, - bool* use_async_transform, Error* error) +MediaCaptureMF::ComPtr +MediaCaptureMF::CreateVideoEncodeTransform(std::string_view codec, u32 frame_rate_numerator, u32 frame_rate_denominator, + u32 bitrate, IMFMediaType* input_type, ComPtr* output_type, + bool* use_async_transform, Error* error) { const MFT_REGISTER_TYPE_INFO input_type_info = {.guidMajorType = MFMediaType_Video, .guidSubtype = VIDEO_YUV_MEDIA_FORMAT}; @@ -1172,10 +1179,8 @@ MediaCaptureMF::ComPtr MediaCaptureMF::CreateVideoEncodeTransform( FAILED(hr = (*output_type)->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) || FAILED(hr = (*output_type)->SetUINT32(MF_MT_MPEG2_PROFILE, profile)) || FAILED(hr = MFSetAttributeSize(output_type->Get(), MF_MT_FRAME_SIZE, m_video_width, m_video_height)) || - FAILED(hr = MFSetAttributeRatio( - output_type->Get(), MF_MT_FRAME_RATE, - static_cast(static_cast(fps) * static_cast(FRAME_RATE_NUMERATOR)), - FRAME_RATE_NUMERATOR)) || + FAILED( + hr = MFSetAttributeRatio(output_type->Get(), MF_MT_FRAME_RATE, frame_rate_numerator, frame_rate_denominator)) || FAILED(hr = MFSetAttributeRatio(output_type->Get(), MF_MT_PIXEL_ASPECT_RATIO, par_numerator, par_denominator))) [[unlikely]] {