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>
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 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);
}
ComPtr<IMFTransform> CreateVideoYUVTransform(ComPtr<IMFMediaType>* output_type, float fps, Error* error);
ComPtr<IMFTransform> CreateVideoEncodeTransform(std::string_view codec, float fps, u32 bitrate,
IMFMediaType* input_type, ComPtr<IMFMediaType>* output_type,
bool* use_async_transform, Error* error);
ComPtr<IMFTransform> CreateVideoYUVTransform(ComPtr<IMFMediaType>* output_type, u32 frame_rate_numerator,
u32 frame_rate_denominator, Error* error);
ComPtr<IMFTransform> CreateVideoEncodeTransform(std::string_view codec, u32 frame_rate_numerator,
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,
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<double>(fps) * static_cast<double>(FRAME_RATE_DENOMERATOR);
m_video_sample_duration = ConvertFrequencyToMFDurationUnits(fps);
ComPtr<IMFMediaType> 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<std::mutex>& lock, Erro
}
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,
.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->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<UINT32>(static_cast<double>(fps) * static_cast<double>(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<IMFTransform> MediaCaptureMF::CreateVideoYUVTransform(Com
return transform;
}
MediaCaptureMF::ComPtr<IMFTransform> MediaCaptureMF::CreateVideoEncodeTransform(std::string_view codec, float fps,
u32 bitrate, IMFMediaType* input_type,
ComPtr<IMFMediaType>* output_type,
bool* use_async_transform, Error* error)
MediaCaptureMF::ComPtr<IMFTransform>
MediaCaptureMF::CreateVideoEncodeTransform(std::string_view codec, u32 frame_rate_numerator, u32 frame_rate_denominator,
u32 bitrate, IMFMediaType* input_type, ComPtr<IMFMediaType>* 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<IMFTransform> 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<UINT32>(static_cast<double>(fps) * static_cast<double>(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]]
{