FreeRDP
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 
37 typedef struct
38 {
39  BYTE guid[16];
40  const char* name;
41  int type;
42 } TSMFMediaTypeMap;
43 
44 static 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 
60 static 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 
218 static 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 
252 static 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 */
271 static 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 */
305 static 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 */
333 static 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 
368 static 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 
489 BOOL 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 
579 BOOL 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 }