MediaCapture: Don't repeat frame rate calculations

This commit is contained in:
Stenzek 2025-06-29 16:25:11 +10:00
parent ebf5c9d0c1
commit a59b6357b3
No known key found for this signature in database

View File

@ -631,7 +631,6 @@ class MediaCaptureMF final : public MediaCaptureBase
template<class T> template<class T>
using ComPtr = Microsoft::WRL::ComPtr<T>; using ComPtr = Microsoft::WRL::ComPtr<T>;
static constexpr u32 FRAME_RATE_NUMERATOR = 10 * 1000 * 1000;
static constexpr DWORD INVALID_STREAM_INDEX = std::numeric_limits<DWORD>::max(); static constexpr DWORD INVALID_STREAM_INDEX = std::numeric_limits<DWORD>::max();
static constexpr u32 AUDIO_BITS_PER_SAMPLE = sizeof(s16) * 8; static constexpr u32 AUDIO_BITS_PER_SAMPLE = sizeof(s16) * 8;
@ -678,10 +677,12 @@ private:
return static_cast<time_t>((static_cast<double>(pts) * duration) / 1e+7); return static_cast<time_t>((static_cast<double>(pts) * duration) / 1e+7);
} }
ComPtr<IMFTransform> CreateVideoYUVTransform(ComPtr<IMFMediaType>* output_type, float fps, Error* error); ComPtr<IMFTransform> CreateVideoYUVTransform(ComPtr<IMFMediaType>* output_type, u32 frame_rate_numerator,
ComPtr<IMFTransform> CreateVideoEncodeTransform(std::string_view codec, float fps, u32 bitrate, u32 frame_rate_denominator, Error* error);
IMFMediaType* input_type, ComPtr<IMFMediaType>* output_type, ComPtr<IMFTransform> CreateVideoEncodeTransform(std::string_view codec, u32 frame_rate_numerator,
bool* use_async_transform, Error* error); u32 frame_rate_denominator, u32 bitrate, IMFMediaType* input_type,
ComPtr<IMFMediaType>* output_type, bool* use_async_transform,
Error* error);
bool GetAudioTypes(std::string_view codec, ComPtr<IMFMediaType>* input_type, ComPtr<IMFMediaType>* output_type, bool GetAudioTypes(std::string_view codec, ComPtr<IMFMediaType>* input_type, ComPtr<IMFMediaType>* output_type,
u32 sample_rate, u32 bitrate, Error* error); 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; 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) if (capture_video)
{ {
static constexpr u32 FRAME_RATE_DENOMERATOR = 10 * 1000 * 1000;
const u32 frame_rate_numerator = static_cast<double>(fps) * static_cast<double>(FRAME_RATE_DENOMERATOR);
m_video_sample_duration = ConvertFrequencyToMFDurationUnits(fps); m_video_sample_duration = ConvertFrequencyToMFDurationUnits(fps);
ComPtr<IMFMediaType> yuv_media_type; ComPtr<IMFMediaType> yuv_media_type;
if (!(m_video_yuv_transform = CreateVideoYUVTransform(&yuv_media_type, fps, error)) || if (!(m_video_yuv_transform =
!(m_video_encode_transform = CreateVideoEncodeTransform(video_codec, fps, video_bitrate, yuv_media_type.Get(), CreateVideoYUVTransform(&yuv_media_type, frame_rate_numerator, FRAME_RATE_DENOMERATOR, error)) ||
&video_media_type, &use_async_video_transform, 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; return false;
} }
@ -993,7 +999,8 @@ bool MediaCaptureMF::InternalEndCapture(std::unique_lock<std::mutex>& lock, Erro
} }
MediaCaptureMF::ComPtr<IMFTransform> MediaCaptureMF::CreateVideoYUVTransform(ComPtr<IMFMediaType>* output_type, MediaCaptureMF::ComPtr<IMFTransform> MediaCaptureMF::CreateVideoYUVTransform(ComPtr<IMFMediaType>* 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, const MFT_REGISTER_TYPE_INFO input_type_info = {.guidMajorType = MFMediaType_Video,
.guidSubtype = VIDEO_RGB_MEDIA_FORMAT}; .guidSubtype = VIDEO_RGB_MEDIA_FORMAT};
@ -1037,14 +1044,14 @@ MediaCaptureMF::ComPtr<IMFTransform> MediaCaptureMF::CreateVideoYUVTransform(Com
FAILED(hr = input_type->SetGUID(MF_MT_SUBTYPE, VIDEO_RGB_MEDIA_FORMAT)) || 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 = 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 = 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_MAJOR_TYPE, MFMediaType_Video)) ||
FAILED(hr = (*output_type)->SetGUID(MF_MT_SUBTYPE, VIDEO_YUV_MEDIA_FORMAT)) || 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 = (*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 = MFSetAttributeSize(output_type->Get(), MF_MT_FRAME_SIZE, m_video_width, m_video_height)) ||
FAILED(hr = MFSetAttributeRatio( FAILED(hr = MFSetAttributeRatio(output_type->Get(), MF_MT_FRAME_RATE, frame_rate_numerator,
output_type->Get(), MF_MT_FRAME_RATE, frame_rate_denominator))) [[unlikely]]
static_cast<UINT32>(static_cast<double>(fps) * static_cast<double>(FRAME_RATE_NUMERATOR)),
FRAME_RATE_NUMERATOR))) [[unlikely]]
{ {
Error::SetHResult(error, "YUV setting attributes failed: ", hr); Error::SetHResult(error, "YUV setting attributes failed: ", hr);
return nullptr; return nullptr;
@ -1065,10 +1072,10 @@ MediaCaptureMF::ComPtr<IMFTransform> MediaCaptureMF::CreateVideoYUVTransform(Com
return transform; return transform;
} }
MediaCaptureMF::ComPtr<IMFTransform> MediaCaptureMF::CreateVideoEncodeTransform(std::string_view codec, float fps, MediaCaptureMF::ComPtr<IMFTransform>
u32 bitrate, IMFMediaType* input_type, MediaCaptureMF::CreateVideoEncodeTransform(std::string_view codec, u32 frame_rate_numerator, u32 frame_rate_denominator,
ComPtr<IMFMediaType>* output_type, u32 bitrate, IMFMediaType* input_type, ComPtr<IMFMediaType>* output_type,
bool* use_async_transform, Error* error) bool* use_async_transform, Error* error)
{ {
const MFT_REGISTER_TYPE_INFO input_type_info = {.guidMajorType = MFMediaType_Video, const MFT_REGISTER_TYPE_INFO input_type_info = {.guidMajorType = MFMediaType_Video,
.guidSubtype = VIDEO_YUV_MEDIA_FORMAT}; .guidSubtype = VIDEO_YUV_MEDIA_FORMAT};
@ -1172,10 +1179,8 @@ MediaCaptureMF::ComPtr<IMFTransform> MediaCaptureMF::CreateVideoEncodeTransform(
FAILED(hr = (*output_type)->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) || FAILED(hr = (*output_type)->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)) ||
FAILED(hr = (*output_type)->SetUINT32(MF_MT_MPEG2_PROFILE, profile)) || 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 = MFSetAttributeSize(output_type->Get(), MF_MT_FRAME_SIZE, m_video_width, m_video_height)) ||
FAILED(hr = MFSetAttributeRatio( FAILED(
output_type->Get(), MF_MT_FRAME_RATE, hr = MFSetAttributeRatio(output_type->Get(), MF_MT_FRAME_RATE, frame_rate_numerator, frame_rate_denominator)) ||
static_cast<UINT32>(static_cast<double>(fps) * static_cast<double>(FRAME_RATE_NUMERATOR)),
FRAME_RATE_NUMERATOR)) ||
FAILED(hr = MFSetAttributeRatio(output_type->Get(), MF_MT_PIXEL_ASPECT_RATIO, par_numerator, par_denominator))) FAILED(hr = MFSetAttributeRatio(output_type->Get(), MF_MT_PIXEL_ASPECT_RATIO, par_numerator, par_denominator)))
[[unlikely]] [[unlikely]]
{ {