2 * FreeRDP: A Remote Desktop Protocol client.
3 * Video Redirection Virtual Channel - Codec
5 * Copyright 2010-2011 Vic Lee
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
23 #include <freerdp/utils/stream.h>
24 #include <freerdp/utils/hexdump.h>
26 #include "drdynvc_types.h"
27 #include "tsmf_constants.h"
28 #include "tsmf_types.h"
30 #include "tsmf_codec.h"
32 typedef struct _TSMFMediaTypeMap
39 static const TSMFMediaTypeMap tsmf_major_type_map[] =
41 /* 73646976-0000-0010-8000-00AA00389B71 */
43 { 0x76, 0x69, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
48 /* 73647561-0000-0010-8000-00AA00389B71 */
50 { 0x61, 0x75, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
58 TSMF_MAJOR_TYPE_UNKNOWN
62 static const TSMFMediaTypeMap tsmf_sub_type_map[] =
64 /* 31435657-0000-0010-8000-00AA00389B71 */
66 { 0x57, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
71 /* 00000161-0000-0010-8000-00AA00389B71 */
73 { 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
74 "MEDIASUBTYPE_WMAudioV2", /* V7, V8 has the same GUID */
78 /* 00000162-0000-0010-8000-00AA00389B71 */
80 { 0x62, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
81 "MEDIASUBTYPE_WMAudioV9",
85 /* 00000055-0000-0010-8000-00AA00389B71 */
87 { 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
92 /* E06D802B-DB46-11CF-B4D1-00805F6CBBEA */
94 { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
95 "MEDIASUBTYPE_MPEG2_AUDIO",
99 /* E06D8026-DB46-11CF-B4D1-00805F6CBBEA */
101 { 0x26, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
102 "MEDIASUBTYPE_MPEG2_VIDEO",
106 /* 33564D57-0000-0010-8000-00AA00389B71 */
108 { 0x57, 0x4D, 0x56, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
113 /* 00001610-0000-0010-8000-00AA00389B71 */
115 { 0x10, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
116 "MEDIASUBTYPE_MPEG_HEAAC",
120 /* 34363248-0000-0010-8000-00AA00389B71 */
122 { 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
127 /* 31435641-0000-0010-8000-00AA00389B71 */
129 { 0x41, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
134 /* E06D802C-DB46-11CF-B4D1-00805F6CBBEA */
136 { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
137 "MEDIASUBTYPE_DOLBY_AC3",
144 TSMF_SUB_TYPE_UNKNOWN
149 static const TSMFMediaTypeMap tsmf_format_type_map[] =
151 /* AED4AB2D-7326-43CB-9464-C879CAB9C43D */
153 { 0x2D, 0xAB, 0xD4, 0xAE, 0x26, 0x73, 0xCB, 0x43, 0x94, 0x64, 0xC8, 0x79, 0xCA, 0xB9, 0xC4, 0x3D },
154 "FORMAT_MFVideoFormat",
155 TSMF_FORMAT_TYPE_MFVIDEOFORMAT
158 /* 05589F81-C356-11CE-BF01-00AA0055595A */
160 { 0x81, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59, 0x5A },
161 "FORMAT_WaveFormatEx",
162 TSMF_FORMAT_TYPE_WAVEFORMATEX
165 /* E06D80E3-DB46-11CF-B4D1-00805F6CBBEA */
167 { 0xE3, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
168 "FORMAT_MPEG2_VIDEO",
169 TSMF_FORMAT_TYPE_MPEG2VIDEOINFO
172 /* F72A76A0-EB0A-11D0-ACE4-0000C0CC16BA */
174 { 0xA0, 0x76, 0x2A, 0xF7, 0x0A, 0xEB, 0xD0, 0x11, 0xAC, 0xE4, 0x00, 0x00, 0xC0, 0xCC, 0x16, 0xBA },
176 TSMF_FORMAT_TYPE_VIDEOINFO2
182 TSMF_FORMAT_TYPE_UNKNOWN
186 static void tsmf_print_guid(const uint8* guid)
188 #ifdef WITH_DEBUG_DVC
191 for (i = 3; i >= 0; i--)
192 printf("%02X", guid[i]);
194 for (i = 5; i >= 4; i--)
195 printf("%02X", guid[i]);
197 for (i = 7; i >= 6; i--)
198 printf("%02X", guid[i]);
200 for (i = 8; i < 16; i++)
202 printf("%02X", guid[i]);
210 /* http://msdn.microsoft.com/en-us/library/dd318229.aspx */
211 static uint32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, STREAM* s, boolean bypass)
217 stream_read_uint32(s, biSize);
218 stream_read_uint32(s, biWidth);
219 stream_read_uint32(s, biHeight);
222 if (mediatype->Width == 0)
223 mediatype->Width = biWidth;
224 if (mediatype->Height == 0)
225 mediatype->Height = biHeight;
226 /* Assume there will be no color table for video? */
228 if (bypass && biSize > 40)
229 stream_seek(s, biSize - 40);
231 return (bypass ? biSize : 40);
234 /* http://msdn.microsoft.com/en-us/library/dd407326.aspx */
235 static uint32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, STREAM* s)
237 uint64 AvgTimePerFrame;
239 /* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
240 stream_seek_uint32(s);
241 stream_seek_uint32(s);
242 stream_read_uint32(s, mediatype->Width);
243 stream_read_uint32(s, mediatype->Height);
244 /* VIDEOINFOHEADER2.rcTarget */
246 /* VIDEOINFOHEADER2.dwBitRate */
247 stream_read_uint32(s, mediatype->BitRate);
248 /* VIDEOINFOHEADER2.dwBitErrorRate */
249 stream_seek_uint32(s);
250 /* VIDEOINFOHEADER2.AvgTimePerFrame */
251 stream_read_uint64(s, AvgTimePerFrame);
252 mediatype->SamplesPerSecond.Numerator = 1000000;
253 mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
254 /* Remaining fields before bmiHeader */
260 boolean tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, STREAM* s)
266 memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE));
269 DEBUG_DVC("MajorType:");
270 tsmf_print_guid(stream_get_tail(s));
271 for (i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++)
273 if (memcmp(tsmf_major_type_map[i].guid, stream_get_tail(s), 16) == 0)
276 mediatype->MajorType = tsmf_major_type_map[i].type;
277 if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
279 DEBUG_DVC("MajorType %s", tsmf_major_type_map[i].name);
283 DEBUG_DVC("SubType:");
284 tsmf_print_guid(stream_get_tail(s));
285 for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++)
287 if (memcmp(tsmf_sub_type_map[i].guid, stream_get_tail(s), 16) == 0)
290 mediatype->SubType = tsmf_sub_type_map[i].type;
291 if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
293 DEBUG_DVC("SubType %s", tsmf_sub_type_map[i].name);
296 /* bFixedSizeSamples, bTemporalCompression, SampleSize */
300 DEBUG_DVC("FormatType:");
301 tsmf_print_guid(stream_get_tail(s));
302 for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++)
304 if (memcmp(tsmf_format_type_map[i].guid, stream_get_tail(s), 16) == 0)
307 mediatype->FormatType = tsmf_format_type_map[i].type;
308 if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
310 DEBUG_DVC("FormatType %s", tsmf_format_type_map[i].name);
314 stream_read_uint32(s, cbFormat);
315 DEBUG_DVC("cbFormat %d", cbFormat);
317 #ifdef WITH_DEBUG_DVC
318 freerdp_hexdump(stream_get_tail(s), cbFormat);
321 switch (mediatype->FormatType)
323 case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
324 /* http://msdn.microsoft.com/en-us/library/aa473808.aspx */
326 stream_seek(s, 8); /* dwSize and ? */
327 stream_read_uint32(s, mediatype->Width); /* videoInfo.dwWidth */
328 stream_read_uint32(s, mediatype->Height); /* videoInfo.dwHeight */
330 /* videoInfo.FramesPerSecond */
331 stream_read_uint32(s, mediatype->SamplesPerSecond.Numerator);
332 stream_read_uint32(s, mediatype->SamplesPerSecond.Denominator);
334 stream_read_uint32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */
339 mediatype->ExtraDataSize = cbFormat - 176;
340 mediatype->ExtraData = stream_get_tail(s);
344 case TSMF_FORMAT_TYPE_WAVEFORMATEX:
345 /* http://msdn.microsoft.com/en-us/library/dd757720.aspx */
347 stream_seek_uint16(s);
348 stream_read_uint16(s, mediatype->Channels);
349 stream_read_uint32(s, mediatype->SamplesPerSecond.Numerator);
350 mediatype->SamplesPerSecond.Denominator = 1;
351 stream_read_uint32(s, mediatype->BitRate);
352 mediatype->BitRate *= 8;
353 stream_read_uint16(s, mediatype->BlockAlign);
354 stream_read_uint16(s, mediatype->BitsPerSample);
355 stream_read_uint16(s, mediatype->ExtraDataSize);
356 if (mediatype->ExtraDataSize > 0)
357 mediatype->ExtraData = stream_get_tail(s);
361 case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
362 /* http://msdn.microsoft.com/en-us/library/dd390707.aspx */
364 i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
365 i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, true);
368 mediatype->ExtraDataSize = cbFormat - i;
369 mediatype->ExtraData = stream_get_tail(s);
373 case TSMF_FORMAT_TYPE_VIDEOINFO2:
374 i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
375 i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, false);
378 mediatype->ExtraDataSize = cbFormat - i;
379 mediatype->ExtraData = stream_get_tail(s);
387 if (mediatype->SamplesPerSecond.Numerator == 0)
388 mediatype->SamplesPerSecond.Numerator = 1;
389 if (mediatype->SamplesPerSecond.Denominator == 0)
390 mediatype->SamplesPerSecond.Denominator = 1;
395 boolean tsmf_codec_check_media_type(STREAM* s)
399 TS_AM_MEDIA_TYPE mediatype;
401 stream_get_mark(s, m);
402 ret = tsmf_codec_parse_media_type(&mediatype, s);
403 stream_set_mark(s, m);