FreeRDP
Loading...
Searching...
No Matches
tsmf_codec.c
1
21#include <freerdp/config.h>
22
23#include <winpr/crt.h>
24#include <winpr/stream.h>
25#include <winpr/print.h>
26
27#include "tsmf_decoder.h"
28#include "tsmf_constants.h"
29#include "tsmf_types.h"
30
31#include "tsmf_codec.h"
32
33#include <freerdp/log.h>
34
35#define TAG CHANNELS_TAG("tsmf.client")
36
37typedef struct
38{
39 BYTE guid[16];
40 const char* name;
41 int type;
42} TSMFMediaTypeMap;
43
44static const TSMFMediaTypeMap tsmf_major_type_map[] = {
45 /* 73646976-0000-0010-8000-00AA00389B71 */
46 { { 0x76, 0x69, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
47 0x71 },
48 "MEDIATYPE_Video",
49 TSMF_MAJOR_TYPE_VIDEO },
50
51 /* 73647561-0000-0010-8000-00AA00389B71 */
52 { { 0x61, 0x75, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
53 0x71 },
54 "MEDIATYPE_Audio",
55 TSMF_MAJOR_TYPE_AUDIO },
56
57 { { 0 }, "Unknown", TSMF_MAJOR_TYPE_UNKNOWN }
58};
59
60static const TSMFMediaTypeMap tsmf_sub_type_map[] = {
61 /* 31435657-0000-0010-8000-00AA00389B71 */
62 { { 0x57, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
63 0x71 },
64 "MEDIASUBTYPE_WVC1",
65 TSMF_SUB_TYPE_WVC1 },
66
67 /* 00000160-0000-0010-8000-00AA00389B71 */
68 { { 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
69 0x71 },
70 "MEDIASUBTYPE_WMAudioV1", /* V7, V8 has the same GUID */
71 TSMF_SUB_TYPE_WMA1 },
72
73 /* 00000161-0000-0010-8000-00AA00389B71 */
74 { { 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
75 0x71 },
76 "MEDIASUBTYPE_WMAudioV2", /* V7, V8 has the same GUID */
77 TSMF_SUB_TYPE_WMA2 },
78
79 /* 00000162-0000-0010-8000-00AA00389B71 */
80 { { 0x62, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
81 0x71 },
82 "MEDIASUBTYPE_WMAudioV9",
83 TSMF_SUB_TYPE_WMA9 },
84
85 /* 00000055-0000-0010-8000-00AA00389B71 */
86 { { 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
87 0x71 },
88 "MEDIASUBTYPE_MP3",
89 TSMF_SUB_TYPE_MP3 },
90
91 /* E06D802B-DB46-11CF-B4D1-00805F6CBBEA */
92 { { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
93 0xEA },
94 "MEDIASUBTYPE_MPEG2_AUDIO",
95 TSMF_SUB_TYPE_MP2A },
96
97 /* E06D8026-DB46-11CF-B4D1-00805F6CBBEA */
98 { { 0x26, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
99 0xEA },
100 "MEDIASUBTYPE_MPEG2_VIDEO",
101 TSMF_SUB_TYPE_MP2V },
102
103 /* 31564D57-0000-0010-8000-00AA00389B71 */
104 { { 0x57, 0x4D, 0x56, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
105 0x71 },
106 "MEDIASUBTYPE_WMV1",
107 TSMF_SUB_TYPE_WMV1 },
108
109 /* 32564D57-0000-0010-8000-00AA00389B71 */
110 { { 0x57, 0x4D, 0x56, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
111 0x71 },
112 "MEDIASUBTYPE_WMV2",
113 TSMF_SUB_TYPE_WMV2 },
114
115 /* 33564D57-0000-0010-8000-00AA00389B71 */
116 { { 0x57, 0x4D, 0x56, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
117 0x71 },
118 "MEDIASUBTYPE_WMV3",
119 TSMF_SUB_TYPE_WMV3 },
120
121 /* 00001610-0000-0010-8000-00AA00389B71 */
122 { { 0x10, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
123 0x71 },
124 "MEDIASUBTYPE_MPEG_HEAAC",
125 TSMF_SUB_TYPE_AAC },
126
127 /* 34363248-0000-0010-8000-00AA00389B71 */
128 { { 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
129 0x71 },
130 "MEDIASUBTYPE_H264",
131 TSMF_SUB_TYPE_H264 },
132
133 /* 31435641-0000-0010-8000-00AA00389B71 */
134 { { 0x41, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
135 0x71 },
136 "MEDIASUBTYPE_AVC1",
137 TSMF_SUB_TYPE_AVC1 },
138
139 /* 3334504D-0000-0010-8000-00AA00389B71 */
140 { { 0x4D, 0x50, 0x34, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
141 0x71 },
142 "MEDIASUBTYPE_MP43",
143 TSMF_SUB_TYPE_MP43 },
144
145 /* 5634504D-0000-0010-8000-00AA00389B71 */
146 { { 0x4D, 0x50, 0x34, 0x56, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
147 0x71 },
148 "MEDIASUBTYPE_MP4S",
149 TSMF_SUB_TYPE_MP4S },
150
151 /* 3234504D-0000-0010-8000-00AA00389B71 */
152 { { 0x4D, 0x50, 0x34, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
153 0x71 },
154 "MEDIASUBTYPE_MP42",
155 TSMF_SUB_TYPE_MP42 },
156
157 /* 3253344D-0000-0010-8000-00AA00389B71 */
158 { { 0x4D, 0x34, 0x53, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
159 0x71 },
160 "MEDIASUBTYPE_MP42",
161 TSMF_SUB_TYPE_M4S2 },
162
163 /* E436EB81-524F-11CE-9F53-0020AF0BA770 */
164 { { 0x81, 0xEB, 0x36, 0xE4, 0x4F, 0x52, 0xCE, 0x11, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7,
165 0x70 },
166 "MEDIASUBTYPE_MP1V",
167 TSMF_SUB_TYPE_MP1V },
168
169 /* 00000050-0000-0010-8000-00AA00389B71 */
170 { { 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
171 0x71 },
172 "MEDIASUBTYPE_MP1A",
173 TSMF_SUB_TYPE_MP1A },
174
175 /* E06D802C-DB46-11CF-B4D1-00805F6CBBEA */
176 { { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
177 0xEA },
178 "MEDIASUBTYPE_DOLBY_AC3",
179 TSMF_SUB_TYPE_AC3 },
180
181 /* 32595559-0000-0010-8000-00AA00389B71 */
182 { { 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
183 0x71 },
184 "MEDIASUBTYPE_YUY2",
185 TSMF_SUB_TYPE_YUY2 },
186
187 /* Opencodec IDS */
188 { { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
189 0x71 },
190 "MEDIASUBTYPE_FLAC",
191 TSMF_SUB_TYPE_FLAC },
192
193 { { 0x61, 0x34, 0x70, 0x6D, 0x7A, 0x76, 0x4D, 0x49, 0xB4, 0x78, 0xF2, 0x9D, 0x25, 0xDC, 0x90,
194 0x37 },
195 "MEDIASUBTYPE_OGG",
196 TSMF_SUB_TYPE_OGG },
197
198 { { 0x4D, 0x34, 0x53, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
199 0x71 },
200 "MEDIASUBTYPE_H263",
201 TSMF_SUB_TYPE_H263 },
202
203 /* WebMMF codec IDS */
204 { { 0x56, 0x50, 0x38, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
205 0x71 },
206 "MEDIASUBTYPE_VP8",
207 TSMF_SUB_TYPE_VP8 },
208
209 { { 0x0B, 0xD1, 0x2F, 0x8D, 0x41, 0x58, 0x6B, 0x4A, 0x89, 0x05, 0x58, 0x8F, 0xEC, 0x1A, 0xDE,
210 0xD9 },
211 "MEDIASUBTYPE_OGG",
212 TSMF_SUB_TYPE_OGG },
213
214 { { 0 }, "Unknown", TSMF_SUB_TYPE_UNKNOWN }
215
216};
217
218static const TSMFMediaTypeMap tsmf_format_type_map[] = {
219 /* AED4AB2D-7326-43CB-9464-C879CAB9C43D */
220 { { 0x2D, 0xAB, 0xD4, 0xAE, 0x26, 0x73, 0xCB, 0x43, 0x94, 0x64, 0xC8, 0x79, 0xCA, 0xB9, 0xC4,
221 0x3D },
222 "FORMAT_MFVideoFormat",
223 TSMF_FORMAT_TYPE_MFVIDEOFORMAT },
224
225 /* 05589F81-C356-11CE-BF01-00AA0055595A */
226 { { 0x81, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59,
227 0x5A },
228 "FORMAT_WaveFormatEx",
229 TSMF_FORMAT_TYPE_WAVEFORMATEX },
230
231 /* E06D80E3-DB46-11CF-B4D1-00805F6CBBEA */
232 { { 0xE3, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
233 0xEA },
234 "FORMAT_MPEG2_VIDEO",
235 TSMF_FORMAT_TYPE_MPEG2VIDEOINFO },
236
237 /* F72A76A0-EB0A-11D0-ACE4-0000C0CC16BA */
238 { { 0xA0, 0x76, 0x2A, 0xF7, 0x0A, 0xEB, 0xD0, 0x11, 0xAC, 0xE4, 0x00, 0x00, 0xC0, 0xCC, 0x16,
239 0xBA },
240 "FORMAT_VideoInfo2",
241 TSMF_FORMAT_TYPE_VIDEOINFO2 },
242
243 /* 05589F82-C356-11CE-BF01-00AA0055595A */
244 { { 0x82, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59,
245 0x5A },
246 "FORMAT_MPEG1_VIDEO",
247 TSMF_FORMAT_TYPE_MPEG1VIDEOINFO },
248
249 { { 0 }, "Unknown", TSMF_FORMAT_TYPE_UNKNOWN }
250};
251
252static void tsmf_print_guid(const BYTE* guid)
253{
254 WINPR_UNUSED(guid);
255
256#ifdef WITH_DEBUG_TSMF
257 char guidString[37];
258
259 (void)snprintf(guidString, sizeof(guidString),
260 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8
261 "-%02" PRIX8 "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8
262 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "",
263 guid[3], guid[2], guid[1], guid[0], guid[5], guid[4], guid[7], guid[6], guid[8],
264 guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
265
266 WLog_INFO(TAG, "%s", guidString);
267#endif
268}
269
270/* http://msdn.microsoft.com/en-us/library/dd318229.aspx */
271static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s,
272 BOOL bypass)
273{
274 UINT32 biSize = 0;
275 UINT32 biWidth = 0;
276 UINT32 biHeight = 0;
277
278 if (!Stream_CheckAndLogRequiredLength(TAG, s, 40))
279 return 0;
280 Stream_Read_UINT32(s, biSize);
281 Stream_Read_UINT32(s, biWidth);
282 Stream_Read_UINT32(s, biHeight);
283 Stream_Seek(s, 28);
284
285 if (mediatype->Width == 0)
286 mediatype->Width = biWidth;
287
288 if (mediatype->Height == 0)
289 mediatype->Height = biHeight;
290
291 /* Assume there will be no color table for video? */
292 if (biSize < 40)
293 return 0;
294
295 if (!Stream_CheckAndLogRequiredLength(TAG, s, (biSize - 40)))
296 return 0;
297
298 if (bypass && biSize > 40)
299 Stream_Seek(s, biSize - 40);
300
301 return (bypass ? biSize : 40);
302}
303
304/* http://msdn.microsoft.com/en-us/library/dd407326.aspx */
305static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
306{
307 UINT64 AvgTimePerFrame = 0;
308
309 /* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
310 if (!Stream_CheckAndLogRequiredLength(TAG, s, 72))
311 return 0;
312
313 Stream_Seek_UINT32(s);
314 Stream_Seek_UINT32(s);
315 Stream_Read_UINT32(s, mediatype->Width);
316 Stream_Read_UINT32(s, mediatype->Height);
317 /* VIDEOINFOHEADER2.rcTarget */
318 Stream_Seek(s, 16);
319 /* VIDEOINFOHEADER2.dwBitRate */
320 Stream_Read_UINT32(s, mediatype->BitRate);
321 /* VIDEOINFOHEADER2.dwBitErrorRate */
322 Stream_Seek_UINT32(s);
323 /* VIDEOINFOHEADER2.AvgTimePerFrame */
324 Stream_Read_UINT64(s, AvgTimePerFrame);
325 mediatype->SamplesPerSecond.Numerator = 1000000;
326 mediatype->SamplesPerSecond.Denominator = (UINT32)(AvgTimePerFrame / 10ULL);
327 /* Remaining fields before bmiHeader */
328 Stream_Seek(s, 24);
329 return 72;
330}
331
332/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
333static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
334{
335 /*
336 typedef struct {
337 RECT rcSource; //16
338 RECT rcTarget; //16 32
339 DWORD dwBitRate; //4 36
340 DWORD dwBitErrorRate; //4 40
341 REFERENCE_TIME AvgTimePerFrame; //8 48
342 BITMAPINFOHEADER bmiHeader;
343 } VIDEOINFOHEADER;
344 */
345 UINT64 AvgTimePerFrame = 0;
346
347 if (!Stream_CheckAndLogRequiredLength(TAG, s, 48))
348 return 0;
349
350 /* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
351 Stream_Seek_UINT32(s);
352 Stream_Seek_UINT32(s);
353 Stream_Read_UINT32(s, mediatype->Width);
354 Stream_Read_UINT32(s, mediatype->Height);
355 /* VIDEOINFOHEADER.rcTarget */
356 Stream_Seek(s, 16);
357 /* VIDEOINFOHEADER.dwBitRate */
358 Stream_Read_UINT32(s, mediatype->BitRate);
359 /* VIDEOINFOHEADER.dwBitErrorRate */
360 Stream_Seek_UINT32(s);
361 /* VIDEOINFOHEADER.AvgTimePerFrame */
362 Stream_Read_UINT64(s, AvgTimePerFrame);
363 mediatype->SamplesPerSecond.Numerator = 1000000;
364 mediatype->SamplesPerSecond.Denominator = (UINT32)(AvgTimePerFrame / 10ULL);
365 return 48;
366}
367
368static BOOL tsmf_read_format_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s, UINT32 cbFormat)
369{
370 UINT32 i = 0;
371 UINT32 j = 0;
372
373 switch (mediatype->FormatType)
374 {
375 case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
376 /* http://msdn.microsoft.com/en-us/library/aa473808.aspx */
377 if (!Stream_CheckAndLogRequiredLength(TAG, s, 176))
378 return FALSE;
379
380 Stream_Seek(s, 8); /* dwSize and ? */
381 Stream_Read_UINT32(s, mediatype->Width); /* videoInfo.dwWidth */
382 Stream_Read_UINT32(s, mediatype->Height); /* videoInfo.dwHeight */
383 Stream_Seek(s, 32);
384 /* videoInfo.FramesPerSecond */
385 Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
386 Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Denominator);
387 Stream_Seek(s, 80);
388 Stream_Read_UINT32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */
389 Stream_Seek(s, 36);
390
391 if (cbFormat > 176)
392 {
393 const size_t nsize = cbFormat - 176;
394 if (mediatype->ExtraDataSize < nsize)
395 return FALSE;
396 if (!Stream_CheckAndLogRequiredLength(TAG, s, nsize))
397 return FALSE;
398 mediatype->ExtraDataSize = (UINT32)nsize;
399 mediatype->ExtraData = Stream_Pointer(s);
400 }
401 break;
402
403 case TSMF_FORMAT_TYPE_WAVEFORMATEX:
404 /* http://msdn.microsoft.com/en-us/library/dd757720.aspx */
405 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
406 return FALSE;
407
408 Stream_Seek_UINT16(s);
409 Stream_Read_UINT16(s, mediatype->Channels);
410 Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
411 mediatype->SamplesPerSecond.Denominator = 1;
412 Stream_Read_UINT32(s, mediatype->BitRate);
413 mediatype->BitRate *= 8;
414 Stream_Read_UINT16(s, mediatype->BlockAlign);
415 Stream_Read_UINT16(s, mediatype->BitsPerSample);
416 Stream_Read_UINT16(s, mediatype->ExtraDataSize);
417
418 if (mediatype->ExtraDataSize > 0)
419 {
420 if (!Stream_CheckAndLogRequiredLength(TAG, s, mediatype->ExtraDataSize))
421 return FALSE;
422 mediatype->ExtraData = Stream_Pointer(s);
423 }
424 break;
425
426 case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO:
427 /* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
428 i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s);
429 if (!i)
430 return FALSE;
431 j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
432 if (!j)
433 return FALSE;
434 i += j;
435
436 if (cbFormat > i)
437 {
438 mediatype->ExtraDataSize = cbFormat - i;
439 if (!Stream_CheckAndLogRequiredLength(TAG, s, mediatype->ExtraDataSize))
440 return FALSE;
441 mediatype->ExtraData = Stream_Pointer(s);
442 }
443 break;
444
445 case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
446 /* http://msdn.microsoft.com/en-us/library/dd390707.aspx */
447 i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
448 if (!i)
449 return FALSE;
450 j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
451 if (!j)
452 return FALSE;
453 i += j;
454
455 if (cbFormat > i)
456 {
457 mediatype->ExtraDataSize = cbFormat - i;
458 if (!Stream_CheckAndLogRequiredLength(TAG, s, mediatype->ExtraDataSize))
459 return FALSE;
460 mediatype->ExtraData = Stream_Pointer(s);
461 }
462 break;
463
464 case TSMF_FORMAT_TYPE_VIDEOINFO2:
465 i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
466 if (!i)
467 return FALSE;
468 j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE);
469 if (!j)
470 return FALSE;
471 i += j;
472
473 if (cbFormat > i)
474 {
475 mediatype->ExtraDataSize = cbFormat - i;
476 if (!Stream_CheckAndLogRequiredLength(TAG, s, mediatype->ExtraDataSize))
477 return FALSE;
478 mediatype->ExtraData = Stream_Pointer(s);
479 }
480 break;
481
482 default:
483 WLog_INFO(TAG, "unhandled format type 0x%x", mediatype->FormatType);
484 break;
485 }
486 return TRUE;
487}
488
489BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
490{
491 UINT32 cbFormat = 0;
492 BOOL ret = TRUE;
493
494 ZeroMemory(mediatype, sizeof(TS_AM_MEDIA_TYPE));
495
496 /* MajorType */
497 DEBUG_TSMF("MediaMajorType:");
498 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
499 return FALSE;
500 tsmf_print_guid(Stream_Pointer(s));
501
502 size_t i = 0;
503 for (; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++)
504 {
505 if (memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0)
506 break;
507 }
508
509 mediatype->MajorType = tsmf_major_type_map[i].type;
510 if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
511 ret = FALSE;
512
513 DEBUG_TSMF("MediaMajorType %s", tsmf_major_type_map[i].name);
514 Stream_Seek(s, 16);
515
516 /* SubType */
517 DEBUG_TSMF("MediaSubType:");
518 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
519 return FALSE;
520 tsmf_print_guid(Stream_Pointer(s));
521
522 for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++)
523 {
524 if (memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0)
525 break;
526 }
527
528 mediatype->SubType = tsmf_sub_type_map[i].type;
529 if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
530 ret = FALSE;
531
532 DEBUG_TSMF("MediaSubType %s", tsmf_sub_type_map[i].name);
533 Stream_Seek(s, 16);
534
535 /* bFixedSizeSamples, bTemporalCompression, SampleSize */
536 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
537 return FALSE;
538 Stream_Seek(s, 12);
539
540 /* FormatType */
541 DEBUG_TSMF("FormatType:");
542 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
543 return FALSE;
544 tsmf_print_guid(Stream_Pointer(s));
545
546 for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++)
547 {
548 if (memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0)
549 break;
550 }
551
552 mediatype->FormatType = tsmf_format_type_map[i].type;
553 if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
554 ret = FALSE;
555
556 DEBUG_TSMF("FormatType %s", tsmf_format_type_map[i].name);
557 Stream_Seek(s, 16);
558
559 /* cbFormat */
560 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
561 return FALSE;
562 Stream_Read_UINT32(s, cbFormat);
563 DEBUG_TSMF("cbFormat %" PRIu32 "", cbFormat);
564#ifdef WITH_DEBUG_TSMF
565 winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(s), cbFormat);
566#endif
567
568 ret = tsmf_read_format_type(mediatype, s, cbFormat);
569
570 if (mediatype->SamplesPerSecond.Numerator == 0)
571 mediatype->SamplesPerSecond.Numerator = 1;
572
573 if (mediatype->SamplesPerSecond.Denominator == 0)
574 mediatype->SamplesPerSecond.Denominator = 1;
575
576 return ret;
577}
578
579BOOL tsmf_codec_check_media_type(const char* decoder_name, wStream* s)
580{
581 size_t pos = 0;
582 BOOL ret = FALSE;
583 TS_AM_MEDIA_TYPE mediatype;
584
585 static BOOL decoderAvailable = FALSE;
586 static BOOL firstRun = TRUE;
587
588 if (firstRun)
589 {
590 firstRun = FALSE;
591 if (tsmf_check_decoder_available(decoder_name))
592 decoderAvailable = TRUE;
593 }
594
595 pos = Stream_GetPosition(s);
596 if (decoderAvailable)
597 ret = tsmf_codec_parse_media_type(&mediatype, s);
598 Stream_SetPosition(s, pos);
599
600 if (ret)
601 {
602 ITSMFDecoder* decoder = tsmf_load_decoder(decoder_name, &mediatype);
603
604 if (!decoder)
605 {
606 WLog_WARN(TAG, "Format not supported by decoder %s", decoder_name);
607 ret = FALSE;
608 }
609 else
610 {
611 decoder->Free(decoder);
612 }
613 }
614
615 return ret;
616}