21 #include <freerdp/config.h>
23 #include <winpr/crt.h>
24 #include <winpr/stream.h>
25 #include <winpr/print.h>
27 #include "tsmf_decoder.h"
28 #include "tsmf_constants.h"
29 #include "tsmf_types.h"
31 #include "tsmf_codec.h"
33 #include <freerdp/log.h>
35 #define TAG CHANNELS_TAG("tsmf.client")
44 static const TSMFMediaTypeMap tsmf_major_type_map[] = {
46 { { 0x76, 0x69, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
49 TSMF_MAJOR_TYPE_VIDEO },
52 { { 0x61, 0x75, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
55 TSMF_MAJOR_TYPE_AUDIO },
57 { { 0 },
"Unknown", TSMF_MAJOR_TYPE_UNKNOWN }
60 static const TSMFMediaTypeMap tsmf_sub_type_map[] = {
62 { { 0x57, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
68 { { 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
70 "MEDIASUBTYPE_WMAudioV1",
74 { { 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
76 "MEDIASUBTYPE_WMAudioV2",
80 { { 0x62, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
82 "MEDIASUBTYPE_WMAudioV9",
86 { { 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
92 { { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
94 "MEDIASUBTYPE_MPEG2_AUDIO",
98 { { 0x26, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
100 "MEDIASUBTYPE_MPEG2_VIDEO",
101 TSMF_SUB_TYPE_MP2V },
104 { { 0x57, 0x4D, 0x56, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
107 TSMF_SUB_TYPE_WMV1 },
110 { { 0x57, 0x4D, 0x56, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
113 TSMF_SUB_TYPE_WMV2 },
116 { { 0x57, 0x4D, 0x56, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
119 TSMF_SUB_TYPE_WMV3 },
122 { { 0x10, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
124 "MEDIASUBTYPE_MPEG_HEAAC",
128 { { 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
131 TSMF_SUB_TYPE_H264 },
134 { { 0x41, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
137 TSMF_SUB_TYPE_AVC1 },
140 { { 0x4D, 0x50, 0x34, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
143 TSMF_SUB_TYPE_MP43 },
146 { { 0x4D, 0x50, 0x34, 0x56, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
149 TSMF_SUB_TYPE_MP4S },
152 { { 0x4D, 0x50, 0x34, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
155 TSMF_SUB_TYPE_MP42 },
158 { { 0x4D, 0x34, 0x53, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
161 TSMF_SUB_TYPE_M4S2 },
164 { { 0x81, 0xEB, 0x36, 0xE4, 0x4F, 0x52, 0xCE, 0x11, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7,
167 TSMF_SUB_TYPE_MP1V },
170 { { 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
173 TSMF_SUB_TYPE_MP1A },
176 { { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
178 "MEDIASUBTYPE_DOLBY_AC3",
182 { { 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
185 TSMF_SUB_TYPE_YUY2 },
188 { { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
191 TSMF_SUB_TYPE_FLAC },
193 { { 0x61, 0x34, 0x70, 0x6D, 0x7A, 0x76, 0x4D, 0x49, 0xB4, 0x78, 0xF2, 0x9D, 0x25, 0xDC, 0x90,
198 { { 0x4D, 0x34, 0x53, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
201 TSMF_SUB_TYPE_H263 },
204 { { 0x56, 0x50, 0x38, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
209 { { 0x0B, 0xD1, 0x2F, 0x8D, 0x41, 0x58, 0x6B, 0x4A, 0x89, 0x05, 0x58, 0x8F, 0xEC, 0x1A, 0xDE,
214 { { 0 },
"Unknown", TSMF_SUB_TYPE_UNKNOWN }
218 static const TSMFMediaTypeMap tsmf_format_type_map[] = {
220 { { 0x2D, 0xAB, 0xD4, 0xAE, 0x26, 0x73, 0xCB, 0x43, 0x94, 0x64, 0xC8, 0x79, 0xCA, 0xB9, 0xC4,
222 "FORMAT_MFVideoFormat",
223 TSMF_FORMAT_TYPE_MFVIDEOFORMAT },
226 { { 0x81, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59,
228 "FORMAT_WaveFormatEx",
229 TSMF_FORMAT_TYPE_WAVEFORMATEX },
232 { { 0xE3, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
234 "FORMAT_MPEG2_VIDEO",
235 TSMF_FORMAT_TYPE_MPEG2VIDEOINFO },
238 { { 0xA0, 0x76, 0x2A, 0xF7, 0x0A, 0xEB, 0xD0, 0x11, 0xAC, 0xE4, 0x00, 0x00, 0xC0, 0xCC, 0x16,
241 TSMF_FORMAT_TYPE_VIDEOINFO2 },
244 { { 0x82, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59,
246 "FORMAT_MPEG1_VIDEO",
247 TSMF_FORMAT_TYPE_MPEG1VIDEOINFO },
249 { { 0 },
"Unknown", TSMF_FORMAT_TYPE_UNKNOWN }
252 static void tsmf_print_guid(
const BYTE* guid)
256 #ifdef WITH_DEBUG_TSMF
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]);
266 WLog_INFO(TAG,
"%s", guidString);
278 if (!Stream_CheckAndLogRequiredLength(TAG, s, 40))
280 Stream_Read_UINT32(s, biSize);
281 Stream_Read_UINT32(s, biWidth);
282 Stream_Read_UINT32(s, biHeight);
285 if (mediatype->Width == 0)
286 mediatype->Width = biWidth;
288 if (mediatype->Height == 0)
289 mediatype->Height = biHeight;
295 if (!Stream_CheckAndLogRequiredLength(TAG, s, (biSize - 40)))
298 if (bypass && biSize > 40)
299 Stream_Seek(s, biSize - 40);
301 return (bypass ? biSize : 40);
307 UINT64 AvgTimePerFrame = 0;
310 if (!Stream_CheckAndLogRequiredLength(TAG, s, 72))
313 Stream_Seek_UINT32(s);
314 Stream_Seek_UINT32(s);
315 Stream_Read_UINT32(s, mediatype->Width);
316 Stream_Read_UINT32(s, mediatype->Height);
320 Stream_Read_UINT32(s, mediatype->BitRate);
322 Stream_Seek_UINT32(s);
324 Stream_Read_UINT64(s, AvgTimePerFrame);
325 mediatype->SamplesPerSecond.Numerator = 1000000;
326 mediatype->SamplesPerSecond.Denominator = (UINT32)(AvgTimePerFrame / 10ULL);
345 UINT64 AvgTimePerFrame = 0;
347 if (!Stream_CheckAndLogRequiredLength(TAG, s, 48))
351 Stream_Seek_UINT32(s);
352 Stream_Seek_UINT32(s);
353 Stream_Read_UINT32(s, mediatype->Width);
354 Stream_Read_UINT32(s, mediatype->Height);
358 Stream_Read_UINT32(s, mediatype->BitRate);
360 Stream_Seek_UINT32(s);
362 Stream_Read_UINT64(s, AvgTimePerFrame);
363 mediatype->SamplesPerSecond.Numerator = 1000000;
364 mediatype->SamplesPerSecond.Denominator = (UINT32)(AvgTimePerFrame / 10ULL);
373 switch (mediatype->FormatType)
375 case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
377 if (!Stream_CheckAndLogRequiredLength(TAG, s, 176))
381 Stream_Read_UINT32(s, mediatype->Width);
382 Stream_Read_UINT32(s, mediatype->Height);
385 Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
386 Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Denominator);
388 Stream_Read_UINT32(s, mediatype->BitRate);
393 const size_t nsize = cbFormat - 176;
394 if (mediatype->ExtraDataSize < nsize)
396 if (!Stream_CheckAndLogRequiredLength(TAG, s, nsize))
398 mediatype->ExtraDataSize = (UINT32)nsize;
399 mediatype->ExtraData = Stream_Pointer(s);
403 case TSMF_FORMAT_TYPE_WAVEFORMATEX:
405 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
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);
418 if (mediatype->ExtraDataSize > 0)
420 if (!Stream_CheckAndLogRequiredLength(TAG, s, mediatype->ExtraDataSize))
422 mediatype->ExtraData = Stream_Pointer(s);
426 case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO:
428 i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s);
431 j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
438 mediatype->ExtraDataSize = cbFormat - i;
439 if (!Stream_CheckAndLogRequiredLength(TAG, s, mediatype->ExtraDataSize))
441 mediatype->ExtraData = Stream_Pointer(s);
445 case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
447 i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
450 j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
457 mediatype->ExtraDataSize = cbFormat - i;
458 if (!Stream_CheckAndLogRequiredLength(TAG, s, mediatype->ExtraDataSize))
460 mediatype->ExtraData = Stream_Pointer(s);
464 case TSMF_FORMAT_TYPE_VIDEOINFO2:
465 i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
468 j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE);
475 mediatype->ExtraDataSize = cbFormat - i;
476 if (!Stream_CheckAndLogRequiredLength(TAG, s, mediatype->ExtraDataSize))
478 mediatype->ExtraData = Stream_Pointer(s);
483 WLog_INFO(TAG,
"unhandled format type 0x%x", mediatype->FormatType);
497 DEBUG_TSMF(
"MediaMajorType:");
498 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
500 tsmf_print_guid(Stream_Pointer(s));
503 for (; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++)
505 if (memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0)
509 mediatype->MajorType = tsmf_major_type_map[i].type;
510 if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
513 DEBUG_TSMF(
"MediaMajorType %s", tsmf_major_type_map[i].name);
517 DEBUG_TSMF(
"MediaSubType:");
518 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
520 tsmf_print_guid(Stream_Pointer(s));
522 for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++)
524 if (memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0)
528 mediatype->SubType = tsmf_sub_type_map[i].type;
529 if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
532 DEBUG_TSMF(
"MediaSubType %s", tsmf_sub_type_map[i].name);
536 if (!Stream_CheckAndLogRequiredLength(TAG, s, 12))
541 DEBUG_TSMF(
"FormatType:");
542 if (!Stream_CheckAndLogRequiredLength(TAG, s, 16))
544 tsmf_print_guid(Stream_Pointer(s));
546 for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++)
548 if (memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0)
552 mediatype->FormatType = tsmf_format_type_map[i].type;
553 if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
556 DEBUG_TSMF(
"FormatType %s", tsmf_format_type_map[i].name);
560 if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
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);
568 ret = tsmf_read_format_type(mediatype, s, cbFormat);
570 if (mediatype->SamplesPerSecond.Numerator == 0)
571 mediatype->SamplesPerSecond.Numerator = 1;
573 if (mediatype->SamplesPerSecond.Denominator == 0)
574 mediatype->SamplesPerSecond.Denominator = 1;
579 BOOL tsmf_codec_check_media_type(
const char* decoder_name,
wStream* s)
585 static BOOL decoderAvailable = FALSE;
586 static BOOL firstRun = TRUE;
591 if (tsmf_check_decoder_available(decoder_name))
592 decoderAvailable = TRUE;
595 pos = Stream_GetPosition(s);
596 if (decoderAvailable)
597 ret = tsmf_codec_parse_media_type(&mediatype, s);
598 Stream_SetPosition(s, pos);
602 ITSMFDecoder* decoder = tsmf_load_decoder(decoder_name, &mediatype);
606 WLog_WARN(TAG,
"Format not supported by decoder %s", decoder_name);
611 decoder->Free(decoder);