summaryrefslogtreecommitdiffstats
path: root/Whisper/MF/mfUtils.cpp
blob: e7390799681b1e62dc6e406259ce9eb908ae7438 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "stdafx.h"
#include "mfUtils.h"
#include <mfapi.h>

HRESULT Whisper::createMediaType( bool stereo, IMFMediaType** pp )
{
	if( nullptr == pp )
		return E_POINTER;

	CComPtr<IMFMediaType> mt;
	CHECK( MFCreateMediaType( &mt ) );
	CHECK( mt->SetGUID( MF_MT_MAJOR_TYPE, MFMediaType_Audio ) );
	CHECK( mt->SetGUID( MF_MT_SUBTYPE, MFAudioFormat_Float ) );
	CHECK( mt->SetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, SAMPLE_RATE ) );

	const uint32_t channels = stereo ? 2 : 1;
	CHECK( mt->SetUINT32( MF_MT_AUDIO_NUM_CHANNELS, channels ) );
	CHECK( mt->SetUINT32( MF_MT_AUDIO_BLOCK_ALIGNMENT, channels * 4 ) );
	CHECK( mt->SetUINT32( MF_MT_AUDIO_AVG_BYTES_PER_SECOND, channels * 4 * SAMPLE_RATE ) );
	CHECK( mt->SetUINT32( MF_MT_AUDIO_BITS_PER_SAMPLE, 32 ) );
	CHECK( mt->SetUINT32( MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE ) );

	*pp = mt.Detach();

	return S_OK;
}

HRESULT Whisper::getStreamDuration( IMFSourceReader* reader, int64_t& duration )
{
	PROPVARIANT var;
	PropVariantInit( &var );
	CHECK( reader->GetPresentationAttribute( MF_SOURCE_READER_MEDIASOURCE, MF_PD_DURATION, &var ) );

	if( var.vt == VT_UI8 )
	{
		// The documentation says the type of that attribute is UINT64
		// https://learn.microsoft.com/en-us/windows/win32/medfound/mf-pd-duration-attribute
		duration = var.uhVal.QuadPart;
		return S_OK;
	}
	logError( u8"Unexpected type of MF_PD_DURATION attribute" );
	return E_INVALIDARG;
}

HRESULT Whisper::validateCurrentMediaType( IMFSourceReader* reader, uint32_t expectedChannels )
{
	CComPtr<IMFMediaType> mt;
	CHECK( reader->GetCurrentMediaType( MF_SOURCE_READER_FIRST_AUDIO_STREAM, &mt ) );

	GUID guid;
	CHECK( mt->GetGUID( MF_MT_MAJOR_TYPE, &guid ) );
	if( guid != MFMediaType_Audio )
		return E_FAIL;

	CHECK( mt->GetGUID( MF_MT_SUBTYPE, &guid ) );
	if( guid != MFAudioFormat_Float )
		return E_FAIL;

	UINT32 u32;
	CHECK( mt->GetUINT32( MF_MT_AUDIO_SAMPLES_PER_SECOND, &u32 ) );
	if( u32 != SAMPLE_RATE )
		return E_FAIL;

	CHECK( mt->GetUINT32( MF_MT_AUDIO_NUM_CHANNELS, &u32 ) );
	if( u32 != expectedChannels )
		return E_FAIL;

	return S_OK;
}