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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
media / base / win / mf_helpers.h [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_WIN_MF_HELPERS_H_
#define MEDIA_BASE_WIN_MF_HELPERS_H_
#include <mfapi.h>
#include <mfidl.h>
#include <stdint.h>
#include <wrl/client.h>
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "media/base/audio_decoder_config.h"
#include "media/base/channel_layout.h"
#include "media/base/decoder_buffer.h"
#include "media/base/media_export.h"
#include "media/base/subsample_entry.h"
#include "media/base/video_codecs.h"
#include "media/base/video_color_space.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "media/base/win/dxgi_device_manager.h"
#include "media/media_buildflags.h"
struct ID3D11DeviceChild;
struct ID3D11Device;
class IMFMediaType;
namespace media {
// Helper function to print HRESULT to std::string.
const auto PrintHr = logging::SystemErrorCodeToString;
// Helper macro for DVLOG with function name and this pointer.
#define DVLOG_FUNC(level) DVLOG(level) << __func__ << ": (" << this << ") "
// Macros that contain return statements can make code harder to read. Only use
// these when necessary, e.g. in places where we deal with a lot of Windows API
// calls, for each of which we have to check the returned HRESULT.
// See discussion thread at:
// https://groups.google.com/a/chromium.org/d/msg/cxx/zw5Xmcs--S4/r7Fwb-TsCAAJ
#define RETURN_IF_FAILED(expr) \
do { \
HRESULT hresult = (expr); \
if (FAILED(hresult)) { \
LOG(ERROR) << __func__ << ": failed with \"" << PrintHr(hresult) \
<< "\""; \
return hresult; \
} \
} while (0)
#define RETURN_ON_FAILURE(success, log, ret) \
do { \
if (!(success)) { \
LOG(ERROR) << log; \
return ret; \
} \
} while (0)
#define RETURN_ON_HR_FAILURE(hresult, log, ret) \
RETURN_ON_FAILURE(SUCCEEDED(hresult), log << ", " << PrintHr(hresult), ret);
// Creates a Media Foundation sample with one buffer of length |buffer_length|
// on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0.
MEDIA_EXPORT Microsoft::WRL::ComPtr<IMFSample> CreateEmptySampleWithBuffer(
uint32_t buffer_length,
int align);
// Provides scoped access to the underlying buffer in an IMFMediaBuffer
// instance.
class MEDIA_EXPORT MediaBufferScopedPointer {
public:
explicit MediaBufferScopedPointer(IMFMediaBuffer* media_buffer);
MediaBufferScopedPointer(const MediaBufferScopedPointer&) = delete;
MediaBufferScopedPointer& operator=(const MediaBufferScopedPointer&) = delete;
~MediaBufferScopedPointer();
raw_ptr<uint8_t, AllowPtrArithmetic> get() { return buffer_; }
DWORD current_length() const { return current_length_; }
DWORD max_length() const { return max_length_; }
private:
Microsoft::WRL::ComPtr<IMFMediaBuffer> media_buffer_;
raw_ptr<uint8_t, AllowPtrArithmetic> buffer_;
DWORD max_length_;
DWORD current_length_;
};
// Copies |in_string| to |out_string| that is allocated with CoTaskMemAlloc().
MEDIA_EXPORT HRESULT CopyCoTaskMemWideString(LPCWSTR in_string,
LPWSTR* out_string);
// Set the debug name of a D3D11 resource for use with ETW debugging tools.
// D3D11 retains the string passed to this function.
MEDIA_EXPORT HRESULT SetDebugName(ID3D11DeviceChild* d3d11_device_child,
const char* debug_string);
MEDIA_EXPORT HRESULT SetDebugName(ID3D11Device* d3d11_device,
const char* debug_string);
// Represents audio channel configuration constants as understood by Windows.
// E.g. KSAUDIO_SPEAKER_MONO. For a list of possible values see:
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff537083(v=vs.85).aspx
using ChannelConfig = uint32_t;
// Converts Microsoft's channel configuration to ChannelLayout.
// This mapping is not perfect but the best we can do given the current
// ChannelLayout enumerator and the Windows-specific speaker configurations
// defined in ksmedia.h.
MEDIA_EXPORT ChannelLayout ChannelConfigToChannelLayout(ChannelConfig config);
// Converts a GUID (little endian) to a bytes array (big endian).
MEDIA_EXPORT std::vector<uint8_t> ByteArrayFromGUID(REFGUID guid);
// Returns a GUID from a binary serialization of a GUID string in network byte
// order format.
MEDIA_EXPORT GUID GetGUIDFromString(const std::string& guid_string);
// Returns a binary serialization of a GUID string in network byte order format.
MEDIA_EXPORT std::string GetStringFromGUID(REFGUID guid);
// Given an AudioDecoderConfig, get its corresponding IMFMediaType format.
// Note:
// IMFMediaType is derived from IMFAttributes and hence all the of information
// in a media type is store as attributes.
// https://docs.microsoft.com/en-us/windows/win32/medfound/media-type-attributes
// has a list of media type attributes.
MEDIA_EXPORT HRESULT
GetDefaultAudioType(const AudioDecoderConfig decoder_config,
IMFMediaType** media_type_out);
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
// Given an AudioDecoderConfig which represents AAC audio, get its
// corresponding IMFMediaType format (by calling GetDefaultAudioType)
// and populate the aac_extra_data in the decoder_config into the
// returned IMFMediaType.
MEDIA_EXPORT HRESULT GetAacAudioType(const AudioDecoderConfig& decoder_config,
IMFMediaType** media_type_out);
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
#if BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
// Given an AudioDecoderConfig which represents AC4 audio, get its
// corresponding IMFMediaType format (by calling GetDefaultAudioType)
// and populate the AC4 extra_data in the decoder_config into the
// returned IMFMediaType.
MEDIA_EXPORT HRESULT GetAC4AudioType(const AudioDecoderConfig& decoder_config,
IMFMediaType** media_type_out);
#endif // BUILDFLAG(ENABLE_PLATFORM_AC4_AUDIO)
// A wrapper of SubsampleEntry for MediaFoundation. The data blob associated
// with MFSampleExtension_Encryption_SubSample_Mapping attribute should contain
// an array of byte ranges as DWORDs where every two DWORDs make a set.
// SubsampleEntry has a set of uint32_t that needs to be converted to DWORDs.
struct MediaFoundationSubsampleEntry {
explicit MediaFoundationSubsampleEntry(SubsampleEntry entry)
: clear_bytes(entry.clear_bytes), cipher_bytes(entry.cypher_bytes) {}
MediaFoundationSubsampleEntry() = default;
DWORD clear_bytes = 0;
DWORD cipher_bytes = 0;
};
// Converts between MFTIME and TimeDelta. MFTIME defines units of 100
// nanoseconds. See
// https://learn.microsoft.com/en-us/windows/win32/medfound/mftime
MEDIA_EXPORT MFTIME TimeDeltaToMfTime(base::TimeDelta time);
MEDIA_EXPORT base::TimeDelta MfTimeToTimeDelta(MFTIME mf_time);
// Converts `codec` into a MediaFoundation subtype. `profile` must be provided
// when converting VideoCodec::kDolbyVision.
MEDIA_EXPORT GUID
VideoCodecToMFSubtype(VideoCodec codec,
VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN);
// Converts `video_pixel_format` into a MediaFoundation subtype.
MEDIA_EXPORT GUID
VideoPixelFormatToMFSubtype(VideoPixelFormat video_pixel_format);
// Converts `primaries` into an MFVideoPrimaries value
MEDIA_EXPORT MFVideoPrimaries
VideoPrimariesToMFVideoPrimaries(gfx::ColorSpace::PrimaryID primaries);
// Callback to transform a Media Foundation sample when converting from the
// DecoderBuffer if needed.
using TransformSampleCB =
base::OnceCallback<HRESULT(Microsoft::WRL::ComPtr<IMFSample>& sample)>;
// Converts the DecoderBuffer back to a Media Foundation sample.
// `TransformSampleCB` is to allow derived classes to transform the Media
// Foundation sample if needed.
MEDIA_EXPORT HRESULT
GenerateSampleFromDecoderBuffer(const scoped_refptr<DecoderBuffer>& buffer,
IMFSample** sample_out,
GUID* last_key_id,
TransformSampleCB transform_sample_cb);
// Creates a DecryptConfig from a Media Foundation sample.
MEDIA_EXPORT HRESULT
CreateDecryptConfigFromSample(IMFSample* mf_sample,
const GUID& key_id,
std::unique_ptr<DecryptConfig>* decrypt_config);
// Converts `frame` into an IMFSample, using an underlying D3D texture,
// reading back from the GPU, or copying the frame contents as necessary.
MEDIA_EXPORT HRESULT GenerateSampleFromVideoFrame(
const media::VideoFrame* frame,
DXGIDeviceManager* dxgi_device_manager,
bool use_dxgi_buffer,
Microsoft::WRL::ComPtr<ID3D11Texture2D>* staging_texture,
DWORD buffer_alignment,
IMFSample** sample_out);
class CommandBufferHelper;
typedef base::OnceCallback<void(scoped_refptr<VideoFrame> frame,
Microsoft::WRL::ComPtr<IMFSample>,
HRESULT)>
SampleAvailableCB;
MEDIA_EXPORT void GenerateSampleFromSharedImageVideoFrame(
scoped_refptr<VideoFrame> frame,
Microsoft::WRL::ComPtr<ID3D11Device> d3d_device,
scoped_refptr<CommandBufferHelper> command_buffer_helper,
SampleAvailableCB sample_available_cb);
} // namespace media
#endif // MEDIA_BASE_WIN_MF_HELPERS_H_