Fix changelog email address
[freerdp-ubuntu-pcb-backport.git] / channels / drdynvc / tsmf / tsmf_codec.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol client.
3  * Video Redirection Virtual Channel - Codec
4  *
5  * Copyright 2010-2011 Vic Lee
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <freerdp/utils/stream.h>
24 #include <freerdp/utils/hexdump.h>
25
26 #include "drdynvc_types.h"
27 #include "tsmf_constants.h"
28 #include "tsmf_types.h"
29
30 #include "tsmf_codec.h"
31
32 typedef struct _TSMFMediaTypeMap
33 {
34         uint8 guid[16];
35         const char* name;
36         int type;
37 } TSMFMediaTypeMap;
38
39 static const TSMFMediaTypeMap tsmf_major_type_map[] =
40 {
41         /* 73646976-0000-0010-8000-00AA00389B71 */
42         {
43                 { 0x76, 0x69, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
44                 "MEDIATYPE_Video",
45                 TSMF_MAJOR_TYPE_VIDEO
46         },
47
48         /* 73647561-0000-0010-8000-00AA00389B71 */
49         {
50                 { 0x61, 0x75, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
51                 "MEDIATYPE_Audio",
52                 TSMF_MAJOR_TYPE_AUDIO
53         },
54
55         {
56                 { 0 },
57                 "Unknown",
58                 TSMF_MAJOR_TYPE_UNKNOWN
59         }
60 };
61
62 static const TSMFMediaTypeMap tsmf_sub_type_map[] =
63 {
64         /* 31435657-0000-0010-8000-00AA00389B71 */
65         {
66                 { 0x57, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
67                 "MEDIASUBTYPE_WVC1",
68                 TSMF_SUB_TYPE_WVC1
69         },
70
71         /* 00000161-0000-0010-8000-00AA00389B71 */
72         {
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 */
75                 TSMF_SUB_TYPE_WMA2
76         },
77
78         /* 00000162-0000-0010-8000-00AA00389B71 */
79         {
80                 { 0x62, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
81                 "MEDIASUBTYPE_WMAudioV9",
82                 TSMF_SUB_TYPE_WMA9
83         },
84
85         /* 00000055-0000-0010-8000-00AA00389B71 */
86         {
87                 { 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
88                 "MEDIASUBTYPE_MP3",
89                 TSMF_SUB_TYPE_MP3
90         },
91
92         /* E06D802B-DB46-11CF-B4D1-00805F6CBBEA */
93         {
94                 { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
95                 "MEDIASUBTYPE_MPEG2_AUDIO",
96                 TSMF_SUB_TYPE_MP2A
97         },
98
99         /* E06D8026-DB46-11CF-B4D1-00805F6CBBEA */
100         {
101                 { 0x26, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
102                 "MEDIASUBTYPE_MPEG2_VIDEO",
103                 TSMF_SUB_TYPE_MP2V
104         },
105
106         /* 33564D57-0000-0010-8000-00AA00389B71 */
107         {
108                 { 0x57, 0x4D, 0x56, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
109                 "MEDIASUBTYPE_WMV3",
110                 TSMF_SUB_TYPE_WMV3
111         },
112
113         /* 00001610-0000-0010-8000-00AA00389B71 */
114         {
115                 { 0x10, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
116                 "MEDIASUBTYPE_MPEG_HEAAC",
117                 TSMF_SUB_TYPE_AAC
118         },
119
120         /* 34363248-0000-0010-8000-00AA00389B71 */
121         {
122                 { 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
123                 "MEDIASUBTYPE_H264",
124                 TSMF_SUB_TYPE_H264
125         },
126
127         /* 31435641-0000-0010-8000-00AA00389B71 */
128         {
129                 { 0x41, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
130                 "MEDIASUBTYPE_AVC1",
131                 TSMF_SUB_TYPE_AVC1
132         },
133
134         /* E06D802C-DB46-11CF-B4D1-00805F6CBBEA */
135         {
136                 { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
137                 "MEDIASUBTYPE_DOLBY_AC3",
138                 TSMF_SUB_TYPE_AC3
139         },
140
141         {
142                 { 0 },
143                 "Unknown",
144                 TSMF_SUB_TYPE_UNKNOWN
145         }
146
147 };
148
149 static const TSMFMediaTypeMap tsmf_format_type_map[] =
150 {
151         /* AED4AB2D-7326-43CB-9464-C879CAB9C43D */
152         {
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
156         },
157
158         /* 05589F81-C356-11CE-BF01-00AA0055595A */
159         {
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
163         },
164
165         /* E06D80E3-DB46-11CF-B4D1-00805F6CBBEA */
166         {
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
170         },
171
172         /* F72A76A0-EB0A-11D0-ACE4-0000C0CC16BA */
173         {
174                 { 0xA0, 0x76, 0x2A, 0xF7, 0x0A, 0xEB, 0xD0, 0x11, 0xAC, 0xE4, 0x00, 0x00, 0xC0, 0xCC, 0x16, 0xBA },
175                 "FORMAT_VideoInfo2",
176                 TSMF_FORMAT_TYPE_VIDEOINFO2
177         },
178
179         {
180                 { 0 },
181                 "Unknown",
182                 TSMF_FORMAT_TYPE_UNKNOWN
183         }
184 };
185
186 static void tsmf_print_guid(const uint8* guid)
187 {
188 #ifdef WITH_DEBUG_DVC
189         int i;
190
191         for (i = 3; i >= 0; i--)
192                 printf("%02X", guid[i]);
193         printf("-");
194         for (i = 5; i >= 4; i--)
195                 printf("%02X", guid[i]);
196         printf("-");
197         for (i = 7; i >= 6; i--)
198                 printf("%02X", guid[i]);
199         printf("-");
200         for (i = 8; i < 16; i++)
201         {
202                 printf("%02X", guid[i]);
203                 if (i == 9)
204                         printf("-");
205         }
206         printf("\n");
207 #endif
208 }
209
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)
212 {
213         uint32 biSize;
214         uint32 biWidth;
215         uint32 biHeight;
216
217         stream_read_uint32(s, biSize);
218         stream_read_uint32(s, biWidth);
219         stream_read_uint32(s, biHeight);
220         stream_seek(s, 28);
221
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? */
227
228         if (bypass && biSize > 40)
229                 stream_seek(s, biSize - 40);
230
231         return (bypass ? biSize : 40);
232 }
233
234 /* http://msdn.microsoft.com/en-us/library/dd407326.aspx */
235 static uint32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, STREAM* s)
236 {
237         uint64 AvgTimePerFrame;
238
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 */
245         stream_seek(s, 16);
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 */
255         stream_seek(s, 24);
256
257         return 72;
258 }
259
260 boolean tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, STREAM* s)
261 {
262         int i;
263         uint32 cbFormat;
264         boolean ret = true;
265
266         memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE));
267
268         /* MajorType */
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++)
272         {
273                 if (memcmp(tsmf_major_type_map[i].guid, stream_get_tail(s), 16) == 0)
274                         break;
275         }
276         mediatype->MajorType = tsmf_major_type_map[i].type;
277         if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
278                 ret = false;
279         DEBUG_DVC("MajorType %s", tsmf_major_type_map[i].name);
280         stream_seek(s, 16);
281
282         /* SubType */
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++)
286         {
287                 if (memcmp(tsmf_sub_type_map[i].guid, stream_get_tail(s), 16) == 0)
288                         break;
289         }
290         mediatype->SubType = tsmf_sub_type_map[i].type;
291         if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
292                 ret = false;
293         DEBUG_DVC("SubType %s", tsmf_sub_type_map[i].name);
294         stream_seek(s, 16);
295
296         /* bFixedSizeSamples, bTemporalCompression, SampleSize */
297         stream_seek(s, 12);
298
299         /* FormatType */
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++)
303         {
304                 if (memcmp(tsmf_format_type_map[i].guid, stream_get_tail(s), 16) == 0)
305                         break;
306         }
307         mediatype->FormatType = tsmf_format_type_map[i].type;
308         if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
309                 ret = false;
310         DEBUG_DVC("FormatType %s", tsmf_format_type_map[i].name);
311         stream_seek(s, 16);
312
313         /* cbFormat */
314         stream_read_uint32(s, cbFormat);
315         DEBUG_DVC("cbFormat %d", cbFormat);
316
317 #ifdef WITH_DEBUG_DVC
318         freerdp_hexdump(stream_get_tail(s), cbFormat);
319 #endif
320
321         switch (mediatype->FormatType)
322         {
323                 case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
324                         /* http://msdn.microsoft.com/en-us/library/aa473808.aspx */
325
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 */
329                         stream_seek(s, 32);
330                         /* videoInfo.FramesPerSecond */
331                         stream_read_uint32(s, mediatype->SamplesPerSecond.Numerator);
332                         stream_read_uint32(s, mediatype->SamplesPerSecond.Denominator);
333                         stream_seek(s, 80);
334                         stream_read_uint32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */
335                         stream_seek(s, 36);
336
337                         if (cbFormat > 176)
338                         {
339                                 mediatype->ExtraDataSize = cbFormat - 176;
340                                 mediatype->ExtraData = stream_get_tail(s);
341                         }
342                         break;
343
344                 case TSMF_FORMAT_TYPE_WAVEFORMATEX:
345                         /* http://msdn.microsoft.com/en-us/library/dd757720.aspx */
346
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);
358                         
359                         break;
360
361                 case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
362                         /* http://msdn.microsoft.com/en-us/library/dd390707.aspx */
363
364                         i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
365                         i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, true);
366                         if (cbFormat > i)
367                         {
368                                 mediatype->ExtraDataSize = cbFormat - i;
369                                 mediatype->ExtraData = stream_get_tail(s);
370                         }
371                         break;
372
373                 case TSMF_FORMAT_TYPE_VIDEOINFO2:
374                         i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
375                         i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, false);
376                         if (cbFormat > i)
377                         {
378                                 mediatype->ExtraDataSize = cbFormat - i;
379                                 mediatype->ExtraData = stream_get_tail(s);
380                         }
381                         break;
382
383                 default:
384                         break;
385         }
386
387         if (mediatype->SamplesPerSecond.Numerator == 0)
388                 mediatype->SamplesPerSecond.Numerator = 1;
389         if (mediatype->SamplesPerSecond.Denominator == 0)
390                 mediatype->SamplesPerSecond.Denominator = 1;
391
392         return ret;
393 }
394
395 boolean tsmf_codec_check_media_type(STREAM* s)
396 {
397         uint8* m;
398         boolean ret;
399         TS_AM_MEDIA_TYPE mediatype;
400
401         stream_get_mark(s, m);
402         ret = tsmf_codec_parse_media_type(&mediatype, s);
403         stream_set_mark(s, m);
404
405         return ret;
406 }
407