Blame channels/tsmf/client/tsmf_codec.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 * Video Redirection Virtual Channel - Codec
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2010-2011 Vic Lee
Packit 1fb8d4
 * Copyright 2012 Hewlett-Packard Development Company, L.P.
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/stream.h>
Packit 1fb8d4
#include <winpr/print.h>
Packit 1fb8d4
Packit 1fb8d4
#include "tsmf_decoder.h"
Packit 1fb8d4
#include "tsmf_constants.h"
Packit 1fb8d4
#include "tsmf_types.h"
Packit 1fb8d4
Packit 1fb8d4
#include "tsmf_codec.h"
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
Packit 1fb8d4
#define TAG CHANNELS_TAG("tsmf.client")
Packit 1fb8d4
Packit 1fb8d4
typedef struct _TSMFMediaTypeMap
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE guid[16];
Packit 1fb8d4
	const char* name;
Packit 1fb8d4
	int type;
Packit 1fb8d4
} TSMFMediaTypeMap;
Packit 1fb8d4
Packit Service 5a9772
static const TSMFMediaTypeMap tsmf_major_type_map[] = {
Packit 1fb8d4
	/* 73646976-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x76, 0x69, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIATYPE_Video",
Packit Service 5a9772
	  TSMF_MAJOR_TYPE_VIDEO },
Packit 1fb8d4
Packit 1fb8d4
	/* 73647561-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x61, 0x75, 0x64, 0x73, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIATYPE_Audio",
Packit Service 5a9772
	  TSMF_MAJOR_TYPE_AUDIO },
Packit 1fb8d4
Packit Service 5a9772
	{ { 0 }, "Unknown", TSMF_MAJOR_TYPE_UNKNOWN }
Packit 1fb8d4
};
Packit 1fb8d4
Packit Service 5a9772
static const TSMFMediaTypeMap tsmf_sub_type_map[] = {
Packit 1fb8d4
	/* 31435657-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x57, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_WVC1",
Packit Service 5a9772
	  TSMF_SUB_TYPE_WVC1 },
Packit 1fb8d4
Packit Service 5a9772
	/* 00000160-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_WMAudioV1", /* V7, V8 has the same GUID */
Packit Service 5a9772
	  TSMF_SUB_TYPE_WMA1 },
Packit 1fb8d4
Packit 1fb8d4
	/* 00000161-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x61, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_WMAudioV2", /* V7, V8 has the same GUID */
Packit Service 5a9772
	  TSMF_SUB_TYPE_WMA2 },
Packit 1fb8d4
Packit 1fb8d4
	/* 00000162-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x62, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_WMAudioV9",
Packit Service 5a9772
	  TSMF_SUB_TYPE_WMA9 },
Packit 1fb8d4
Packit 1fb8d4
	/* 00000055-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_MP3",
Packit Service 5a9772
	  TSMF_SUB_TYPE_MP3 },
Packit 1fb8d4
Packit 1fb8d4
	/* E06D802B-DB46-11CF-B4D1-00805F6CBBEA */
Packit Service 5a9772
	{ { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
Packit Service 5a9772
	    0xEA },
Packit Service 5a9772
	  "MEDIASUBTYPE_MPEG2_AUDIO",
Packit Service 5a9772
	  TSMF_SUB_TYPE_MP2A },
Packit 1fb8d4
Packit 1fb8d4
	/* E06D8026-DB46-11CF-B4D1-00805F6CBBEA */
Packit Service 5a9772
	{ { 0x26, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
Packit Service 5a9772
	    0xEA },
Packit Service 5a9772
	  "MEDIASUBTYPE_MPEG2_VIDEO",
Packit Service 5a9772
	  TSMF_SUB_TYPE_MP2V },
Packit 1fb8d4
Packit 1fb8d4
	/* 31564D57-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x57, 0x4D, 0x56, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_WMV1",
Packit Service 5a9772
	  TSMF_SUB_TYPE_WMV1 },
Packit 1fb8d4
Packit 1fb8d4
	/* 32564D57-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x57, 0x4D, 0x56, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_WMV2",
Packit Service 5a9772
	  TSMF_SUB_TYPE_WMV2 },
Packit 1fb8d4
Packit 1fb8d4
	/* 33564D57-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x57, 0x4D, 0x56, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_WMV3",
Packit Service 5a9772
	  TSMF_SUB_TYPE_WMV3 },
Packit 1fb8d4
Packit 1fb8d4
	/* 00001610-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x10, 0x16, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_MPEG_HEAAC",
Packit Service 5a9772
	  TSMF_SUB_TYPE_AAC },
Packit 1fb8d4
Packit 1fb8d4
	/* 34363248-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x48, 0x32, 0x36, 0x34, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_H264",
Packit Service 5a9772
	  TSMF_SUB_TYPE_H264 },
Packit 1fb8d4
Packit 1fb8d4
	/* 31435641-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x41, 0x56, 0x43, 0x31, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_AVC1",
Packit Service 5a9772
	  TSMF_SUB_TYPE_AVC1 },
Packit 1fb8d4
Packit 1fb8d4
	/* 3334504D-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x4D, 0x50, 0x34, 0x33, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_MP43",
Packit Service 5a9772
	  TSMF_SUB_TYPE_MP43 },
Packit 1fb8d4
Packit 1fb8d4
	/* 5634504D-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x4D, 0x50, 0x34, 0x56, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_MP4S",
Packit Service 5a9772
	  TSMF_SUB_TYPE_MP4S },
Packit 1fb8d4
Packit 1fb8d4
	/* 3234504D-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x4D, 0x50, 0x34, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_MP42",
Packit Service 5a9772
	  TSMF_SUB_TYPE_MP42 },
Packit 1fb8d4
Packit 1fb8d4
	/* 3253344D-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x4D, 0x34, 0x53, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_MP42",
Packit Service 5a9772
	  TSMF_SUB_TYPE_M4S2 },
Packit 1fb8d4
Packit 1fb8d4
	/* E436EB81-524F-11CE-9F53-0020AF0BA770 */
Packit Service 5a9772
	{ { 0x81, 0xEB, 0x36, 0xE4, 0x4F, 0x52, 0xCE, 0x11, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7,
Packit Service 5a9772
	    0x70 },
Packit Service 5a9772
	  "MEDIASUBTYPE_MP1V",
Packit Service 5a9772
	  TSMF_SUB_TYPE_MP1V },
Packit 1fb8d4
Packit 1fb8d4
	/* 00000050-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_MP1A",
Packit Service 5a9772
	  TSMF_SUB_TYPE_MP1A },
Packit 1fb8d4
Packit 1fb8d4
	/* E06D802C-DB46-11CF-B4D1-00805F6CBBEA */
Packit Service 5a9772
	{ { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
Packit Service 5a9772
	    0xEA },
Packit Service 5a9772
	  "MEDIASUBTYPE_DOLBY_AC3",
Packit Service 5a9772
	  TSMF_SUB_TYPE_AC3 },
Packit 1fb8d4
Packit 1fb8d4
	/* 32595559-0000-0010-8000-00AA00389B71 */
Packit Service 5a9772
	{ { 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_YUY2",
Packit Service 5a9772
	  TSMF_SUB_TYPE_YUY2 },
Packit 1fb8d4
Packit 1fb8d4
	/* Opencodec IDS */
Packit Service 5a9772
	{ { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_FLAC",
Packit Service 5a9772
	  TSMF_SUB_TYPE_FLAC },
Packit 1fb8d4
Packit Service 5a9772
	{ { 0x61, 0x34, 0x70, 0x6D, 0x7A, 0x76, 0x4D, 0x49, 0xB4, 0x78, 0xF2, 0x9D, 0x25, 0xDC, 0x90,
Packit Service 5a9772
	    0x37 },
Packit Service 5a9772
	  "MEDIASUBTYPE_OGG",
Packit Service 5a9772
	  TSMF_SUB_TYPE_OGG },
Packit 1fb8d4
Packit Service 5a9772
	{ { 0x4D, 0x34, 0x53, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_H263",
Packit Service 5a9772
	  TSMF_SUB_TYPE_H263 },
Packit 1fb8d4
Packit 1fb8d4
	/* WebMMF codec IDS */
Packit Service 5a9772
	{ { 0x56, 0x50, 0x38, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B,
Packit Service 5a9772
	    0x71 },
Packit Service 5a9772
	  "MEDIASUBTYPE_VP8",
Packit Service 5a9772
	  TSMF_SUB_TYPE_VP8 },
Packit 1fb8d4
Packit Service 5a9772
	{ { 0x0B, 0xD1, 0x2F, 0x8D, 0x41, 0x58, 0x6B, 0x4A, 0x89, 0x05, 0x58, 0x8F, 0xEC, 0x1A, 0xDE,
Packit Service 5a9772
	    0xD9 },
Packit Service 5a9772
	  "MEDIASUBTYPE_OGG",
Packit Service 5a9772
	  TSMF_SUB_TYPE_OGG },
Packit 1fb8d4
Packit Service 5a9772
	{ { 0 }, "Unknown", TSMF_SUB_TYPE_UNKNOWN }
Packit 1fb8d4
Packit 1fb8d4
};
Packit 1fb8d4
Packit Service 5a9772
static const TSMFMediaTypeMap tsmf_format_type_map[] = {
Packit 1fb8d4
	/* AED4AB2D-7326-43CB-9464-C879CAB9C43D */
Packit Service 5a9772
	{ { 0x2D, 0xAB, 0xD4, 0xAE, 0x26, 0x73, 0xCB, 0x43, 0x94, 0x64, 0xC8, 0x79, 0xCA, 0xB9, 0xC4,
Packit Service 5a9772
	    0x3D },
Packit Service 5a9772
	  "FORMAT_MFVideoFormat",
Packit Service 5a9772
	  TSMF_FORMAT_TYPE_MFVIDEOFORMAT },
Packit 1fb8d4
Packit 1fb8d4
	/* 05589F81-C356-11CE-BF01-00AA0055595A */
Packit Service 5a9772
	{ { 0x81, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59,
Packit Service 5a9772
	    0x5A },
Packit Service 5a9772
	  "FORMAT_WaveFormatEx",
Packit Service 5a9772
	  TSMF_FORMAT_TYPE_WAVEFORMATEX },
Packit 1fb8d4
Packit 1fb8d4
	/* E06D80E3-DB46-11CF-B4D1-00805F6CBBEA */
Packit Service 5a9772
	{ { 0xE3, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB,
Packit Service 5a9772
	    0xEA },
Packit Service 5a9772
	  "FORMAT_MPEG2_VIDEO",
Packit Service 5a9772
	  TSMF_FORMAT_TYPE_MPEG2VIDEOINFO },
Packit 1fb8d4
Packit 1fb8d4
	/* F72A76A0-EB0A-11D0-ACE4-0000C0CC16BA */
Packit Service 5a9772
	{ { 0xA0, 0x76, 0x2A, 0xF7, 0x0A, 0xEB, 0xD0, 0x11, 0xAC, 0xE4, 0x00, 0x00, 0xC0, 0xCC, 0x16,
Packit Service 5a9772
	    0xBA },
Packit Service 5a9772
	  "FORMAT_VideoInfo2",
Packit Service 5a9772
	  TSMF_FORMAT_TYPE_VIDEOINFO2 },
Packit 1fb8d4
Packit 1fb8d4
	/* 05589F82-C356-11CE-BF01-00AA0055595A */
Packit Service 5a9772
	{ { 0x82, 0x9F, 0x58, 0x05, 0x56, 0xC3, 0xCE, 0x11, 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59,
Packit Service 5a9772
	    0x5A },
Packit Service 5a9772
	  "FORMAT_MPEG1_VIDEO",
Packit Service 5a9772
	  TSMF_FORMAT_TYPE_MPEG1VIDEOINFO },
Packit 1fb8d4
Packit Service 5a9772
	{ { 0 }, "Unknown", TSMF_FORMAT_TYPE_UNKNOWN }
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static void tsmf_print_guid(const BYTE* guid)
Packit 1fb8d4
{
Packit 1fb8d4
#ifdef WITH_DEBUG_TSMF
Packit 1fb8d4
	char guidString[37];
Packit 1fb8d4
Packit Service 5a9772
	snprintf(guidString, sizeof(guidString),
Packit Service 5a9772
	         "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8 "-%02" PRIX8
Packit Service 5a9772
	         "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8 "-%02" PRIX8 "%02" PRIX8 "%02" PRIX8 "%02" PRIX8
Packit Service 5a9772
	         "%02" PRIX8 "%02" PRIX8 "",
Packit Service 5a9772
	         guid[3], guid[2], guid[1], guid[0], guid[5], guid[4], guid[7], guid[6], guid[8],
Packit Service 5a9772
	         guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]);
Packit 1fb8d4
Packit 1fb8d4
	WLog_INFO(TAG, "%s", guidString);
Packit 1fb8d4
#endif
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* http://msdn.microsoft.com/en-us/library/dd318229.aspx */
Packit Service 5a9772
static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s,
Packit Service 5a9772
                                                BOOL bypass)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 biSize;
Packit 1fb8d4
	UINT32 biWidth;
Packit 1fb8d4
	UINT32 biHeight;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 40)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
	Stream_Read_UINT32(s, biSize);
Packit 1fb8d4
	Stream_Read_UINT32(s, biWidth);
Packit 1fb8d4
	Stream_Read_UINT32(s, biHeight);
Packit 1fb8d4
	Stream_Seek(s, 28);
Packit 1fb8d4
Packit 1fb8d4
	if (mediatype->Width == 0)
Packit 1fb8d4
		mediatype->Width = biWidth;
Packit 1fb8d4
Packit 1fb8d4
	if (mediatype->Height == 0)
Packit 1fb8d4
		mediatype->Height = biHeight;
Packit 1fb8d4
Packit 1fb8d4
	/* Assume there will be no color table for video? */
Packit Service 5a9772
	if ((biSize < 40) || (Stream_GetRemainingLength(s) < (biSize - 40)))
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	if (bypass && biSize > 40)
Packit 1fb8d4
		Stream_Seek(s, biSize - 40);
Packit 1fb8d4
Packit 1fb8d4
	return (bypass ? biSize : 40);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* http://msdn.microsoft.com/en-us/library/dd407326.aspx */
Packit 1fb8d4
static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT64 AvgTimePerFrame;
Packit 1fb8d4
Packit 1fb8d4
	/* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 72)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	Stream_Seek_UINT32(s);
Packit 1fb8d4
	Stream_Seek_UINT32(s);
Packit 1fb8d4
	Stream_Read_UINT32(s, mediatype->Width);
Packit 1fb8d4
	Stream_Read_UINT32(s, mediatype->Height);
Packit 1fb8d4
	/* VIDEOINFOHEADER2.rcTarget */
Packit 1fb8d4
	Stream_Seek(s, 16);
Packit 1fb8d4
	/* VIDEOINFOHEADER2.dwBitRate */
Packit 1fb8d4
	Stream_Read_UINT32(s, mediatype->BitRate);
Packit 1fb8d4
	/* VIDEOINFOHEADER2.dwBitErrorRate */
Packit 1fb8d4
	Stream_Seek_UINT32(s);
Packit 1fb8d4
	/* VIDEOINFOHEADER2.AvgTimePerFrame */
Packit 1fb8d4
	Stream_Read_UINT64(s, AvgTimePerFrame);
Packit 1fb8d4
	mediatype->SamplesPerSecond.Numerator = 1000000;
Packit 1fb8d4
	mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
Packit 1fb8d4
	/* Remaining fields before bmiHeader */
Packit 1fb8d4
	Stream_Seek(s, 24);
Packit 1fb8d4
	return 72;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
Packit 1fb8d4
static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
Packit 1fb8d4
{
Packit 1fb8d4
	/*
Packit 1fb8d4
	typedef struct tagVIDEOINFOHEADER {
Packit 1fb8d4
	  RECT             rcSource;			//16
Packit 1fb8d4
	  RECT             rcTarget;			//16	32
Packit 1fb8d4
	  DWORD            dwBitRate;			//4	36
Packit 1fb8d4
	  DWORD            dwBitErrorRate;		//4	40
Packit 1fb8d4
	  REFERENCE_TIME   AvgTimePerFrame;		//8	48
Packit 1fb8d4
	  BITMAPINFOHEADER bmiHeader;
Packit 1fb8d4
	} VIDEOINFOHEADER;
Packit 1fb8d4
	*/
Packit 1fb8d4
	UINT64 AvgTimePerFrame;
Packit 1fb8d4
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 48)
Packit 1fb8d4
		return 0;
Packit 1fb8d4
Packit 1fb8d4
	/* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */
Packit 1fb8d4
	Stream_Seek_UINT32(s);
Packit 1fb8d4
	Stream_Seek_UINT32(s);
Packit 1fb8d4
	Stream_Read_UINT32(s, mediatype->Width);
Packit 1fb8d4
	Stream_Read_UINT32(s, mediatype->Height);
Packit 1fb8d4
	/* VIDEOINFOHEADER.rcTarget */
Packit 1fb8d4
	Stream_Seek(s, 16);
Packit 1fb8d4
	/* VIDEOINFOHEADER.dwBitRate */
Packit 1fb8d4
	Stream_Read_UINT32(s, mediatype->BitRate);
Packit 1fb8d4
	/* VIDEOINFOHEADER.dwBitErrorRate */
Packit 1fb8d4
	Stream_Seek_UINT32(s);
Packit 1fb8d4
	/* VIDEOINFOHEADER.AvgTimePerFrame */
Packit 1fb8d4
	Stream_Read_UINT64(s, AvgTimePerFrame);
Packit 1fb8d4
	mediatype->SamplesPerSecond.Numerator = 1000000;
Packit 1fb8d4
	mediatype->SamplesPerSecond.Denominator = (int)(AvgTimePerFrame / 10LL);
Packit 1fb8d4
	return 48;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL tsmf_read_format_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s, UINT32 cbFormat)
Packit 1fb8d4
{
Packit Service 5a9772
	UINT32 i, j;
Packit 1fb8d4
Packit 1fb8d4
	switch (mediatype->FormatType)
Packit 1fb8d4
	{
Packit 1fb8d4
		case TSMF_FORMAT_TYPE_MFVIDEOFORMAT:
Packit 1fb8d4
			/* http://msdn.microsoft.com/en-us/library/aa473808.aspx */
Packit 1fb8d4
			if (Stream_GetRemainingLength(s) < 176)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
Packit Service 5a9772
			Stream_Seek(s, 8);                        /* dwSize and ? */
Packit Service 5a9772
			Stream_Read_UINT32(s, mediatype->Width);  /* videoInfo.dwWidth */
Packit 1fb8d4
			Stream_Read_UINT32(s, mediatype->Height); /* videoInfo.dwHeight */
Packit 1fb8d4
			Stream_Seek(s, 32);
Packit 1fb8d4
			/* videoInfo.FramesPerSecond */
Packit 1fb8d4
			Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
Packit 1fb8d4
			Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Denominator);
Packit 1fb8d4
			Stream_Seek(s, 80);
Packit 1fb8d4
			Stream_Read_UINT32(s, mediatype->BitRate); /* compressedInfo.AvgBitrate */
Packit 1fb8d4
			Stream_Seek(s, 36);
Packit 1fb8d4
Packit 1fb8d4
			if (cbFormat > 176)
Packit 1fb8d4
			{
Packit 1fb8d4
				mediatype->ExtraDataSize = cbFormat - 176;
Packit 1fb8d4
				mediatype->ExtraData = Stream_Pointer(s);
Packit 1fb8d4
			}
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case TSMF_FORMAT_TYPE_WAVEFORMATEX:
Packit 1fb8d4
			/* http://msdn.microsoft.com/en-us/library/dd757720.aspx */
Packit 1fb8d4
			if (Stream_GetRemainingLength(s) < 18)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
Packit 1fb8d4
			Stream_Seek_UINT16(s);
Packit 1fb8d4
			Stream_Read_UINT16(s, mediatype->Channels);
Packit 1fb8d4
			Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator);
Packit 1fb8d4
			mediatype->SamplesPerSecond.Denominator = 1;
Packit 1fb8d4
			Stream_Read_UINT32(s, mediatype->BitRate);
Packit 1fb8d4
			mediatype->BitRate *= 8;
Packit 1fb8d4
			Stream_Read_UINT16(s, mediatype->BlockAlign);
Packit 1fb8d4
			Stream_Read_UINT16(s, mediatype->BitsPerSample);
Packit 1fb8d4
			Stream_Read_UINT16(s, mediatype->ExtraDataSize);
Packit 1fb8d4
Packit 1fb8d4
			if (mediatype->ExtraDataSize > 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				if (Stream_GetRemainingLength(s) < mediatype->ExtraDataSize)
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				mediatype->ExtraData = Stream_Pointer(s);
Packit 1fb8d4
			}
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO:
Packit 1fb8d4
			/* http://msdn.microsoft.com/en-us/library/dd390700.aspx */
Packit 1fb8d4
			i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s);
Packit 1fb8d4
			if (!i)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
Packit 1fb8d4
			if (!j)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			i += j;
Packit 1fb8d4
Packit 1fb8d4
			if (cbFormat > i)
Packit 1fb8d4
			{
Packit 1fb8d4
				mediatype->ExtraDataSize = cbFormat - i;
Packit 1fb8d4
				if (Stream_GetRemainingLength(s) < mediatype->ExtraDataSize)
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				mediatype->ExtraData = Stream_Pointer(s);
Packit 1fb8d4
			}
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO:
Packit 1fb8d4
			/* http://msdn.microsoft.com/en-us/library/dd390707.aspx */
Packit 1fb8d4
			i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
Packit 1fb8d4
			if (!i)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE);
Packit 1fb8d4
			if (!j)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			i += j;
Packit 1fb8d4
Packit 1fb8d4
			if (cbFormat > i)
Packit 1fb8d4
			{
Packit 1fb8d4
				mediatype->ExtraDataSize = cbFormat - i;
Packit 1fb8d4
				if (Stream_GetRemainingLength(s) < mediatype->ExtraDataSize)
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				mediatype->ExtraData = Stream_Pointer(s);
Packit 1fb8d4
			}
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		case TSMF_FORMAT_TYPE_VIDEOINFO2:
Packit 1fb8d4
			i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s);
Packit 1fb8d4
			if (!i)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE);
Packit 1fb8d4
			if (!j)
Packit 1fb8d4
				return FALSE;
Packit 1fb8d4
			i += j;
Packit 1fb8d4
Packit 1fb8d4
			if (cbFormat > i)
Packit 1fb8d4
			{
Packit 1fb8d4
				mediatype->ExtraDataSize = cbFormat - i;
Packit 1fb8d4
				if (Stream_GetRemainingLength(s) < mediatype->ExtraDataSize)
Packit 1fb8d4
					return FALSE;
Packit 1fb8d4
				mediatype->ExtraData = Stream_Pointer(s);
Packit 1fb8d4
			}
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit 1fb8d4
			WLog_INFO(TAG, "unhandled format type 0x%x", mediatype->FormatType);
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
Packit 1fb8d4
{
Packit 1fb8d4
	UINT32 cbFormat;
Packit 1fb8d4
	BOOL ret = TRUE;
Packit 1fb8d4
	int i;
Packit 1fb8d4
Packit 1fb8d4
	ZeroMemory(mediatype, sizeof(TS_AM_MEDIA_TYPE));
Packit 1fb8d4
Packit 1fb8d4
	/* MajorType */
Packit 1fb8d4
	DEBUG_TSMF("MediaMajorType:");
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 16)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	tsmf_print_guid(Stream_Pointer(s));
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0)
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	mediatype->MajorType = tsmf_major_type_map[i].type;
Packit 1fb8d4
	if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN)
Packit 1fb8d4
		ret = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	DEBUG_TSMF("MediaMajorType %s", tsmf_major_type_map[i].name);
Packit 1fb8d4
	Stream_Seek(s, 16);
Packit 1fb8d4
Packit 1fb8d4
	/* SubType */
Packit 1fb8d4
	DEBUG_TSMF("MediaSubType:");
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 16)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	tsmf_print_guid(Stream_Pointer(s));
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0)
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	mediatype->SubType = tsmf_sub_type_map[i].type;
Packit 1fb8d4
	if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN)
Packit 1fb8d4
		ret = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	DEBUG_TSMF("MediaSubType %s", tsmf_sub_type_map[i].name);
Packit 1fb8d4
	Stream_Seek(s, 16);
Packit 1fb8d4
Packit 1fb8d4
	/* bFixedSizeSamples, bTemporalCompression, SampleSize */
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 12)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	Stream_Seek(s, 12);
Packit 1fb8d4
Packit 1fb8d4
	/* FormatType */
Packit 1fb8d4
	DEBUG_TSMF("FormatType:");
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 16)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	tsmf_print_guid(Stream_Pointer(s));
Packit 1fb8d4
Packit 1fb8d4
	for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0)
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	mediatype->FormatType = tsmf_format_type_map[i].type;
Packit 1fb8d4
	if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN)
Packit 1fb8d4
		ret = FALSE;
Packit 1fb8d4
Packit 1fb8d4
	DEBUG_TSMF("FormatType %s", tsmf_format_type_map[i].name);
Packit 1fb8d4
	Stream_Seek(s, 16);
Packit 1fb8d4
Packit 1fb8d4
	/* cbFormat */
Packit 1fb8d4
	if (Stream_GetRemainingLength(s) < 4)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	Stream_Read_UINT32(s, cbFormat);
Packit Service 5a9772
	DEBUG_TSMF("cbFormat %" PRIu32 "", cbFormat);
Packit 1fb8d4
#ifdef WITH_DEBUG_TSMF
Packit 1fb8d4
	winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(s), cbFormat);
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
	ret = tsmf_read_format_type(mediatype, s, cbFormat);
Packit 1fb8d4
Packit 1fb8d4
	if (mediatype->SamplesPerSecond.Numerator == 0)
Packit 1fb8d4
		mediatype->SamplesPerSecond.Numerator = 1;
Packit 1fb8d4
Packit 1fb8d4
	if (mediatype->SamplesPerSecond.Denominator == 0)
Packit 1fb8d4
		mediatype->SamplesPerSecond.Denominator = 1;
Packit 1fb8d4
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
BOOL tsmf_codec_check_media_type(const char* decoder_name, wStream* s)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* m;
Packit 1fb8d4
	BOOL ret = FALSE;
Packit 1fb8d4
	TS_AM_MEDIA_TYPE mediatype;
Packit 1fb8d4
Packit 1fb8d4
	static BOOL decoderAvailable = FALSE;
Packit 1fb8d4
	static BOOL firstRun = TRUE;
Packit 1fb8d4
Packit 1fb8d4
	if (firstRun)
Packit 1fb8d4
	{
Packit Service 5a9772
		firstRun = FALSE;
Packit 1fb8d4
		if (tsmf_check_decoder_available(decoder_name))
Packit 1fb8d4
			decoderAvailable = TRUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	Stream_GetPointer(s, m);
Packit 1fb8d4
	if (decoderAvailable)
Packit 1fb8d4
		ret = tsmf_codec_parse_media_type(&mediatype, s);
Packit 1fb8d4
	Stream_SetPointer(s, m);
Packit 1fb8d4
Packit 1fb8d4
	if (ret)
Packit 1fb8d4
	{
Packit 1fb8d4
		ITSMFDecoder* decoder = tsmf_load_decoder(decoder_name, &mediatype);
Packit 1fb8d4
Packit 1fb8d4
		if (!decoder)
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_WARN(TAG, "Format not supported by decoder %s", decoder_name);
Packit 1fb8d4
			ret = FALSE;
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			decoder->Free(decoder);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return ret;
Packit 1fb8d4
}