mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 19:17:17 +00:00
winegstreamer: Implement WMA <-> AMT conversion.
This commit is contained in:
parent
30ab13fa9c
commit
41dfd7d7c1
|
@ -278,6 +278,68 @@ static bool amt_from_wg_format_audio_mpeg1(AM_MEDIA_TYPE *mt, const struct wg_fo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool amt_from_wg_format_audio_wma(AM_MEDIA_TYPE *mt, const struct wg_format *format)
|
||||||
|
{
|
||||||
|
DWORD codec_data_len, size;
|
||||||
|
WAVEFORMATEX *wave_format;
|
||||||
|
const GUID *subtype;
|
||||||
|
WORD fmt_tag;
|
||||||
|
|
||||||
|
mt->majortype = MEDIATYPE_Audio;
|
||||||
|
mt->formattype = FORMAT_WaveFormatEx;
|
||||||
|
|
||||||
|
switch (format->u.audio_wma.version)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
subtype = &MEDIASUBTYPE_MSAUDIO1;
|
||||||
|
codec_data_len = MSAUDIO1_WFX_EXTRA_BYTES;
|
||||||
|
fmt_tag = WAVE_FORMAT_MSAUDIO1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
subtype = &MEDIASUBTYPE_WMAUDIO2;
|
||||||
|
codec_data_len = WMAUDIO2_WFX_EXTRA_BYTES;
|
||||||
|
fmt_tag = WAVE_FORMAT_WMAUDIO2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
subtype = &MEDIASUBTYPE_WMAUDIO3;
|
||||||
|
codec_data_len = WMAUDIO3_WFX_EXTRA_BYTES;
|
||||||
|
fmt_tag = WAVE_FORMAT_WMAUDIO3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS;
|
||||||
|
codec_data_len = 18;
|
||||||
|
fmt_tag = WAVE_FORMAT_WMAUDIO_LOSSLESS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = sizeof(WAVEFORMATEX) + codec_data_len;
|
||||||
|
if (!(wave_format = CoTaskMemAlloc(size)))
|
||||||
|
return false;
|
||||||
|
memset(wave_format, 0, size);
|
||||||
|
|
||||||
|
mt->subtype = *subtype;
|
||||||
|
mt->bFixedSizeSamples = TRUE;
|
||||||
|
mt->lSampleSize = format->u.audio_wma.block_align;
|
||||||
|
mt->cbFormat = size;
|
||||||
|
mt->pbFormat = (BYTE *)wave_format;
|
||||||
|
wave_format->wFormatTag = fmt_tag;
|
||||||
|
wave_format->nChannels = format->u.audio_wma.channels;
|
||||||
|
wave_format->nSamplesPerSec = format->u.audio_wma.rate;
|
||||||
|
wave_format->nAvgBytesPerSec = format->u.audio_wma.bitrate / 8;
|
||||||
|
wave_format->nBlockAlign = format->u.audio_wma.block_align;
|
||||||
|
wave_format->wBitsPerSample = format->u.audio_wma.depth;
|
||||||
|
wave_format->cbSize = codec_data_len;
|
||||||
|
|
||||||
|
if (format->u.audio_wma.codec_data_len == codec_data_len)
|
||||||
|
memcpy(wave_format+1, format->u.audio_wma.codec_data, format->u.audio_wma.codec_data_len);
|
||||||
|
else
|
||||||
|
FIXME("Unexpected codec_data length; got %u, expected %lu\n", format->u.audio_wma.codec_data_len, codec_data_len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#define ALIGN(n, alignment) (((n) + (alignment) - 1) & ~((alignment) - 1))
|
#define ALIGN(n, alignment) (((n) + (alignment) - 1) & ~((alignment) - 1))
|
||||||
|
|
||||||
static unsigned int wg_format_get_max_size_video_raw(enum wg_video_format format, unsigned int width, unsigned int height)
|
static unsigned int wg_format_get_max_size_video_raw(enum wg_video_format format, unsigned int width, unsigned int height)
|
||||||
|
@ -384,8 +446,13 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WG_MAJOR_TYPE_AUDIO_MPEG4:
|
|
||||||
case WG_MAJOR_TYPE_AUDIO_WMA:
|
case WG_MAJOR_TYPE_AUDIO_WMA:
|
||||||
|
/* Estimated max size of a compressed audio frame.
|
||||||
|
* There's no way to no way to know the real upper bound,
|
||||||
|
* so let's just use one second of decompressed size and hope it works. */
|
||||||
|
return format->u.audio_wma.rate * format->u.audio_wma.channels * format->u.audio_wma.depth / 8;
|
||||||
|
|
||||||
|
case WG_MAJOR_TYPE_AUDIO_MPEG4:
|
||||||
case WG_MAJOR_TYPE_VIDEO_H264:
|
case WG_MAJOR_TYPE_VIDEO_H264:
|
||||||
case WG_MAJOR_TYPE_VIDEO_WMV:
|
case WG_MAJOR_TYPE_VIDEO_WMV:
|
||||||
case WG_MAJOR_TYPE_VIDEO_INDEO:
|
case WG_MAJOR_TYPE_VIDEO_INDEO:
|
||||||
|
@ -643,7 +710,6 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
|
||||||
switch (format->major_type)
|
switch (format->major_type)
|
||||||
{
|
{
|
||||||
case WG_MAJOR_TYPE_AUDIO_MPEG4:
|
case WG_MAJOR_TYPE_AUDIO_MPEG4:
|
||||||
case WG_MAJOR_TYPE_AUDIO_WMA:
|
|
||||||
case WG_MAJOR_TYPE_VIDEO_H264:
|
case WG_MAJOR_TYPE_VIDEO_H264:
|
||||||
case WG_MAJOR_TYPE_VIDEO_INDEO:
|
case WG_MAJOR_TYPE_VIDEO_INDEO:
|
||||||
FIXME("Format %u not implemented!\n", format->major_type);
|
FIXME("Format %u not implemented!\n", format->major_type);
|
||||||
|
@ -657,6 +723,9 @@ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool
|
||||||
case WG_MAJOR_TYPE_AUDIO_MPEG1:
|
case WG_MAJOR_TYPE_AUDIO_MPEG1:
|
||||||
return amt_from_wg_format_audio_mpeg1(mt, format);
|
return amt_from_wg_format_audio_mpeg1(mt, format);
|
||||||
|
|
||||||
|
case WG_MAJOR_TYPE_AUDIO_WMA:
|
||||||
|
return amt_from_wg_format_audio_wma(mt, format);
|
||||||
|
|
||||||
case WG_MAJOR_TYPE_VIDEO:
|
case WG_MAJOR_TYPE_VIDEO:
|
||||||
return amt_from_wg_format_video(mt, format, wm);
|
return amt_from_wg_format_video(mt, format, wm);
|
||||||
|
|
||||||
|
@ -787,6 +856,55 @@ static bool amt_to_wg_format_audio_mpeg1_layer3(const AM_MEDIA_TYPE *mt, struct
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool amt_to_wg_format_audio_wma(const AM_MEDIA_TYPE *mt, struct wg_format *format)
|
||||||
|
{
|
||||||
|
const WAVEFORMATEX *audio_format = (const WAVEFORMATEX *)mt->pbFormat;
|
||||||
|
|
||||||
|
if (!IsEqualGUID(&mt->formattype, &FORMAT_WaveFormatEx))
|
||||||
|
{
|
||||||
|
FIXME("Unknown format type %s.\n", debugstr_guid(&mt->formattype));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mt->cbFormat < sizeof(*audio_format) || !mt->pbFormat)
|
||||||
|
{
|
||||||
|
ERR("Unexpected format size %lu.\n", mt->cbFormat);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MSAUDIO1))
|
||||||
|
format->u.audio_wma.version = 1;
|
||||||
|
else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO2))
|
||||||
|
format->u.audio_wma.version = 2;
|
||||||
|
else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO3))
|
||||||
|
format->u.audio_wma.version = 3;
|
||||||
|
else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO_LOSSLESS))
|
||||||
|
format->u.audio_wma.version = 4;
|
||||||
|
else
|
||||||
|
assert(false);
|
||||||
|
format->major_type = WG_MAJOR_TYPE_AUDIO_WMA;
|
||||||
|
format->u.audio_wma.bitrate = audio_format->nAvgBytesPerSec * 8;
|
||||||
|
format->u.audio_wma.rate = audio_format->nSamplesPerSec;
|
||||||
|
format->u.audio_wma.depth = audio_format->wBitsPerSample;
|
||||||
|
format->u.audio_wma.channels = audio_format->nChannels;
|
||||||
|
format->u.audio_wma.block_align = audio_format->nBlockAlign;
|
||||||
|
|
||||||
|
format->u.audio_wma.codec_data_len = 0;
|
||||||
|
if (format->u.audio_wma.version == 1)
|
||||||
|
format->u.audio_wma.codec_data_len = 4;
|
||||||
|
if (format->u.audio_wma.version == 2)
|
||||||
|
format->u.audio_wma.codec_data_len = 10;
|
||||||
|
if (format->u.audio_wma.version == 3)
|
||||||
|
format->u.audio_wma.codec_data_len = 18;
|
||||||
|
if (format->u.audio_wma.version == 4)
|
||||||
|
format->u.audio_wma.codec_data_len = 18;
|
||||||
|
if (mt->cbFormat >= sizeof(WAVEFORMATEX) + format->u.audio_wma.codec_data_len)
|
||||||
|
memcpy(format->u.audio_wma.codec_data, audio_format+1, format->u.audio_wma.codec_data_len);
|
||||||
|
else
|
||||||
|
FIXME("Too small format block, can't copy codec data\n");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool amt_to_wg_format_video(const AM_MEDIA_TYPE *mt, struct wg_format *format)
|
static bool amt_to_wg_format_video(const AM_MEDIA_TYPE *mt, struct wg_format *format)
|
||||||
{
|
{
|
||||||
static const struct
|
static const struct
|
||||||
|
@ -932,6 +1050,11 @@ bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format)
|
||||||
return amt_to_wg_format_audio_mpeg1(mt, format);
|
return amt_to_wg_format_audio_mpeg1(mt, format);
|
||||||
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MP3))
|
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MP3))
|
||||||
return amt_to_wg_format_audio_mpeg1_layer3(mt, format);
|
return amt_to_wg_format_audio_mpeg1_layer3(mt, format);
|
||||||
|
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MSAUDIO1)
|
||||||
|
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO2)
|
||||||
|
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO3)
|
||||||
|
|| IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMAUDIO_LOSSLESS))
|
||||||
|
return amt_to_wg_format_audio_wma(mt, format);
|
||||||
return amt_to_wg_format_audio(mt, format);
|
return amt_to_wg_format_audio(mt, format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1455,7 +1455,7 @@ static void check_audio_type(const WM_MEDIA_TYPE *mt)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_stream_media_props(IWMStreamConfig *config,
|
static void test_stream_media_props(IWMStreamConfig *config,
|
||||||
const GUID *majortype, const GUID *subtype, const GUID *formattype, BOOL todo_subtype)
|
const GUID *majortype, const GUID *subtype, const GUID *formattype)
|
||||||
{
|
{
|
||||||
char mt_buffer[2000];
|
char mt_buffer[2000];
|
||||||
WM_MEDIA_TYPE *mt = (WM_MEDIA_TYPE *)mt_buffer;
|
WM_MEDIA_TYPE *mt = (WM_MEDIA_TYPE *)mt_buffer;
|
||||||
|
@ -1484,7 +1484,6 @@ static void test_stream_media_props(IWMStreamConfig *config,
|
||||||
ok(size == sizeof(WM_MEDIA_TYPE) + mt->cbFormat, "got %lu.\n", size);
|
ok(size == sizeof(WM_MEDIA_TYPE) + mt->cbFormat, "got %lu.\n", size);
|
||||||
ok(IsEqualGUID(&mt->majortype, majortype), "Expected major type %s, got %s.\n",
|
ok(IsEqualGUID(&mt->majortype, majortype), "Expected major type %s, got %s.\n",
|
||||||
debugstr_guid(majortype), debugstr_guid(&mt->majortype));
|
debugstr_guid(majortype), debugstr_guid(&mt->majortype));
|
||||||
todo_wine_if(todo_subtype)
|
|
||||||
ok(IsEqualGUID(&mt->subtype, subtype), "Expected sub type %s, got %s.\n",
|
ok(IsEqualGUID(&mt->subtype, subtype), "Expected sub type %s, got %s.\n",
|
||||||
debugstr_guid(subtype), debugstr_guid(&mt->subtype));
|
debugstr_guid(subtype), debugstr_guid(&mt->subtype));
|
||||||
ok(IsEqualGUID(&mt->formattype, formattype), "Expected format type %s, got %s.\n",
|
ok(IsEqualGUID(&mt->formattype, formattype), "Expected format type %s, got %s.\n",
|
||||||
|
@ -1546,9 +1545,9 @@ static void test_sync_reader_types(void)
|
||||||
ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
|
ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
|
||||||
|
|
||||||
if (IsEqualGUID(&majortype, &MEDIATYPE_Audio))
|
if (IsEqualGUID(&majortype, &MEDIATYPE_Audio))
|
||||||
test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx, TRUE);
|
test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx);
|
||||||
else
|
else
|
||||||
test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, FALSE);
|
test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo);
|
||||||
|
|
||||||
ref = IWMStreamConfig_Release(config);
|
ref = IWMStreamConfig_Release(config);
|
||||||
ok(!ref, "Got outstanding refcount %ld.\n", ref);
|
ok(!ref, "Got outstanding refcount %ld.\n", ref);
|
||||||
|
@ -3425,9 +3424,9 @@ static void test_async_reader_types(void)
|
||||||
ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
|
ok(IsEqualGUID(&majortype, &MEDIATYPE_Audio), "Got major type %s.\n", debugstr_guid(&majortype));
|
||||||
|
|
||||||
if (IsEqualGUID(&majortype, &MEDIATYPE_Audio))
|
if (IsEqualGUID(&majortype, &MEDIATYPE_Audio))
|
||||||
test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx, TRUE);
|
test_stream_media_props(config, &MEDIATYPE_Audio, &MEDIASUBTYPE_MSAUDIO1, &FORMAT_WaveFormatEx);
|
||||||
else
|
else
|
||||||
test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo, FALSE);
|
test_stream_media_props(config, &MEDIATYPE_Video, &MEDIASUBTYPE_WMV1, &FORMAT_VideoInfo);
|
||||||
|
|
||||||
ref = IWMStreamConfig_Release(config);
|
ref = IWMStreamConfig_Release(config);
|
||||||
ok(!ref, "Got outstanding refcount %ld.\n", ref);
|
ok(!ref, "Got outstanding refcount %ld.\n", ref);
|
||||||
|
|
Loading…
Reference in a new issue