winegstreamer: Implement CLSID_CMpegVideoCodec.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=9127
This commit is contained in:
parent
e8e5e8b5c9
commit
481fd0ec3b
6 changed files with 195 additions and 1 deletions
|
@ -114,11 +114,13 @@ HRESULT wg_muxer_create(const char *format, wg_muxer_t *muxer);
|
|||
void wg_muxer_destroy(wg_muxer_t muxer);
|
||||
HRESULT wg_muxer_add_stream(wg_muxer_t muxer, UINT32 stream_id, const struct wg_format *format);
|
||||
|
||||
unsigned int wg_format_get_bytes_for_uncompressed(wg_video_format format, unsigned int width, unsigned int height);
|
||||
unsigned int wg_format_get_max_size(const struct wg_format *format);
|
||||
|
||||
HRESULT avi_splitter_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT decodebin_parser_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT mpeg_audio_codec_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT mpeg_video_codec_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT mpeg_layer3_decoder_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT mpeg_splitter_create(IUnknown *outer, IUnknown **out);
|
||||
HRESULT wave_parser_create(IUnknown *outer, IUnknown **out);
|
||||
|
|
|
@ -657,6 +657,7 @@ static const IClassFactoryVtbl class_factory_vtbl =
|
|||
static struct class_factory avi_splitter_cf = {{&class_factory_vtbl}, avi_splitter_create};
|
||||
static struct class_factory decodebin_parser_cf = {{&class_factory_vtbl}, decodebin_parser_create};
|
||||
static struct class_factory mpeg_audio_codec_cf = {{&class_factory_vtbl}, mpeg_audio_codec_create};
|
||||
static struct class_factory mpeg_video_codec_cf = {{&class_factory_vtbl}, mpeg_video_codec_create};
|
||||
static struct class_factory mpeg_layer3_decoder_cf = {{&class_factory_vtbl}, mpeg_layer3_decoder_create};
|
||||
static struct class_factory mpeg_splitter_cf = {{&class_factory_vtbl}, mpeg_splitter_create};
|
||||
static struct class_factory wave_parser_cf = {{&class_factory_vtbl}, wave_parser_create};
|
||||
|
@ -686,6 +687,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out)
|
|||
factory = &decodebin_parser_cf;
|
||||
else if (IsEqualGUID(clsid, &CLSID_CMpegAudioCodec))
|
||||
factory = &mpeg_audio_codec_cf;
|
||||
else if (IsEqualGUID(clsid, &CLSID_CMpegVideoCodec))
|
||||
factory = &mpeg_video_codec_cf;
|
||||
else if (IsEqualGUID(clsid, &CLSID_mpeg_layer3_decoder))
|
||||
factory = &mpeg_layer3_decoder_cf;
|
||||
else if (IsEqualGUID(clsid, &CLSID_MPEG1Splitter))
|
||||
|
@ -799,6 +802,38 @@ static const REGFILTER2 reg_mpeg_audio_codec =
|
|||
.u.s2.rgPins2 = reg_mpeg_audio_codec_pins,
|
||||
};
|
||||
|
||||
static const REGPINTYPES reg_mpeg_video_codec_sink_mts[2] =
|
||||
{
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Packet},
|
||||
{&MEDIATYPE_Video, &MEDIASUBTYPE_MPEG1Payload},
|
||||
};
|
||||
|
||||
static const REGPINTYPES reg_mpeg_video_codec_source_mts[1] =
|
||||
{
|
||||
{&MEDIATYPE_Video, &GUID_NULL},
|
||||
};
|
||||
|
||||
static const REGFILTERPINS2 reg_mpeg_video_codec_pins[2] =
|
||||
{
|
||||
{
|
||||
.nMediaTypes = 2,
|
||||
.lpMediaType = reg_mpeg_video_codec_sink_mts,
|
||||
},
|
||||
{
|
||||
.dwFlags = REG_PINFLAG_B_OUTPUT,
|
||||
.nMediaTypes = 1,
|
||||
.lpMediaType = reg_mpeg_video_codec_source_mts,
|
||||
},
|
||||
};
|
||||
|
||||
static const REGFILTER2 reg_mpeg_video_codec =
|
||||
{
|
||||
.dwVersion = 2,
|
||||
.dwMerit = 0x40000001,
|
||||
.u.s2.cPins2 = 2,
|
||||
.u.s2.rgPins2 = reg_mpeg_video_codec_pins,
|
||||
};
|
||||
|
||||
static const REGPINTYPES reg_mpeg_layer3_decoder_sink_mts[1] =
|
||||
{
|
||||
{&MEDIATYPE_Audio, &MEDIASUBTYPE_MP3},
|
||||
|
@ -1034,6 +1069,8 @@ HRESULT WINAPI DllRegisterServer(void)
|
|||
L"GStreamer splitter filter", NULL, NULL, NULL, ®_decodebin_parser);
|
||||
IFilterMapper2_RegisterFilter(mapper, &CLSID_CMpegAudioCodec,
|
||||
L"MPEG Audio Decoder", NULL, NULL, NULL, ®_mpeg_audio_codec);
|
||||
IFilterMapper2_RegisterFilter(mapper, &CLSID_CMpegVideoCodec,
|
||||
L"MPEG Video Decoder", NULL, NULL, NULL, ®_mpeg_video_codec);
|
||||
IFilterMapper2_RegisterFilter(mapper, &CLSID_mpeg_layer3_decoder,
|
||||
L"MPEG Layer-3 Decoder", NULL, NULL, NULL, ®_mpeg_layer3_decoder);
|
||||
IFilterMapper2_RegisterFilter(mapper, &CLSID_MPEG1Splitter,
|
||||
|
@ -1075,6 +1112,7 @@ HRESULT WINAPI DllUnregisterServer(void)
|
|||
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_AviSplitter);
|
||||
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_decodebin_parser);
|
||||
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_CMpegAudioCodec);
|
||||
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_CMpegVideoCodec);
|
||||
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_mpeg_layer3_decoder);
|
||||
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_MPEG1Splitter);
|
||||
IFilterMapper2_UnregisterFilter(mapper, NULL, NULL, &CLSID_WAVEParser);
|
||||
|
|
|
@ -1933,6 +1933,12 @@ static HRESULT WINAPI GSTOutPin_DecideBufferSize(struct strmbase_source *iface,
|
|||
VIDEOINFOHEADER *format = (VIDEOINFOHEADER *)pin->pin.pin.mt.pbFormat;
|
||||
buffer_size = format->bmiHeader.biSizeImage;
|
||||
}
|
||||
else if (IsEqualGUID(&pin->pin.pin.mt.formattype, &FORMAT_MPEGVideo))
|
||||
{
|
||||
MPEG1VIDEOINFO *format = (MPEG1VIDEOINFO *)pin->pin.pin.mt.pbFormat;
|
||||
buffer_size = format->hdr.bmiHeader.biSizeImage;
|
||||
buffer_count = 8;
|
||||
}
|
||||
else if (IsEqualGUID(&pin->pin.pin.mt.formattype, &FORMAT_WaveFormatEx)
|
||||
&& (IsEqualGUID(&pin->pin.pin.mt.subtype, &MEDIASUBTYPE_PCM)
|
||||
|| IsEqualGUID(&pin->pin.pin.mt.subtype, &MEDIASUBTYPE_IEEE_FLOAT)))
|
||||
|
|
|
@ -738,6 +738,147 @@ HRESULT mpeg_audio_codec_create(IUnknown *outer, IUnknown **out)
|
|||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT mpeg_video_codec_sink_query_accept(struct transform *filter, const AM_MEDIA_TYPE *mt)
|
||||
{
|
||||
if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Video)
|
||||
|| !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_MPEG1Payload)
|
||||
|| !IsEqualGUID(&mt->formattype, &FORMAT_MPEGVideo)
|
||||
|| mt->cbFormat < sizeof(MPEG1VIDEOINFO))
|
||||
return S_FALSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT mpeg_video_codec_source_query_accept(struct transform *filter, const AM_MEDIA_TYPE *mt)
|
||||
{
|
||||
if (!filter->sink.pin.peer)
|
||||
return S_FALSE;
|
||||
|
||||
if (!IsEqualGUID(&mt->majortype, &MEDIATYPE_Video)
|
||||
|| !IsEqualGUID(&mt->formattype, &FORMAT_VideoInfo)
|
||||
|| mt->cbFormat < sizeof(VIDEOINFOHEADER))
|
||||
return S_FALSE;
|
||||
|
||||
if (!IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_YV12)
|
||||
/* missing: MEDIASUBTYPE_Y41P, not supported by GStreamer */
|
||||
&& !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_YUY2)
|
||||
&& !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_UYVY)
|
||||
&& !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB24)
|
||||
&& !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB32)
|
||||
&& !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB565)
|
||||
&& !IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_RGB555)
|
||||
/* missing: MEDIASUBTYPE_RGB8, not supported by GStreamer */)
|
||||
return S_FALSE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT mpeg_video_codec_source_get_media_type(struct transform *filter, unsigned int index, AM_MEDIA_TYPE *mt)
|
||||
{
|
||||
static const enum wg_video_format formats[] = {
|
||||
WG_VIDEO_FORMAT_YV12,
|
||||
WG_VIDEO_FORMAT_YUY2,
|
||||
WG_VIDEO_FORMAT_UYVY,
|
||||
WG_VIDEO_FORMAT_BGR,
|
||||
WG_VIDEO_FORMAT_BGRx,
|
||||
WG_VIDEO_FORMAT_RGB16,
|
||||
WG_VIDEO_FORMAT_RGB15,
|
||||
};
|
||||
|
||||
const MPEG1VIDEOINFO *input_format = (MPEG1VIDEOINFO*)filter->sink.pin.mt.pbFormat;
|
||||
struct wg_format wg_format = {};
|
||||
VIDEOINFO *video_format;
|
||||
|
||||
if (!filter->sink.pin.peer)
|
||||
return VFW_S_NO_MORE_ITEMS;
|
||||
|
||||
if (index >= ARRAY_SIZE(formats))
|
||||
return VFW_S_NO_MORE_ITEMS;
|
||||
|
||||
input_format = (MPEG1VIDEOINFO*)filter->sink.pin.mt.pbFormat;
|
||||
wg_format.major_type = WG_MAJOR_TYPE_VIDEO;
|
||||
wg_format.u.video.format = formats[index];
|
||||
wg_format.u.video.width = input_format->hdr.bmiHeader.biWidth;
|
||||
wg_format.u.video.height = input_format->hdr.bmiHeader.biHeight;
|
||||
wg_format.u.video.fps_n = 10000000;
|
||||
wg_format.u.video.fps_d = input_format->hdr.AvgTimePerFrame;
|
||||
if (!amt_from_wg_format(mt, &wg_format, false))
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
video_format = (VIDEOINFO*)mt->pbFormat;
|
||||
video_format->bmiHeader.biHeight = abs(video_format->bmiHeader.biHeight);
|
||||
SetRect(&video_format->rcSource, 0, 0, video_format->bmiHeader.biWidth, video_format->bmiHeader.biHeight);
|
||||
|
||||
video_format->bmiHeader.biXPelsPerMeter = 2000;
|
||||
video_format->bmiHeader.biYPelsPerMeter = 2000;
|
||||
video_format->dwBitRate = MulDiv(video_format->bmiHeader.biSizeImage * 8, 10000000, video_format->AvgTimePerFrame);
|
||||
mt->lSampleSize = video_format->bmiHeader.biSizeImage;
|
||||
mt->bTemporalCompression = FALSE;
|
||||
mt->bFixedSizeSamples = TRUE;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT mpeg_video_codec_source_decide_buffer_size(struct transform *filter, IMemAllocator *allocator, ALLOCATOR_PROPERTIES *props)
|
||||
{
|
||||
VIDEOINFOHEADER *output_format = (VIDEOINFOHEADER *)filter->source.pin.mt.pbFormat;
|
||||
ALLOCATOR_PROPERTIES ret_props;
|
||||
|
||||
props->cBuffers = max(props->cBuffers, 1);
|
||||
props->cbBuffer = max(props->cbBuffer, output_format->bmiHeader.biSizeImage);
|
||||
props->cbAlign = max(props->cbAlign, 1);
|
||||
|
||||
return IMemAllocator_SetProperties(allocator, props, &ret_props);
|
||||
}
|
||||
|
||||
static const struct transform_ops mpeg_video_codec_transform_ops =
|
||||
{
|
||||
mpeg_video_codec_sink_query_accept,
|
||||
mpeg_video_codec_source_query_accept,
|
||||
mpeg_video_codec_source_get_media_type,
|
||||
mpeg_video_codec_source_decide_buffer_size,
|
||||
};
|
||||
|
||||
HRESULT mpeg_video_codec_create(IUnknown *outer, IUnknown **out)
|
||||
{
|
||||
static const struct wg_format output_format =
|
||||
{
|
||||
.major_type = WG_MAJOR_TYPE_VIDEO,
|
||||
.u.video = {
|
||||
.format = WG_VIDEO_FORMAT_I420,
|
||||
/* size doesn't matter, this one is only used to check if the GStreamer plugin exists */
|
||||
},
|
||||
};
|
||||
static const struct wg_format input_format =
|
||||
{
|
||||
.major_type = WG_MAJOR_TYPE_VIDEO_MPEG1,
|
||||
.u.video_mpeg1 = {},
|
||||
};
|
||||
struct wg_transform_attrs attrs = {0};
|
||||
wg_transform_t transform;
|
||||
struct transform *object;
|
||||
HRESULT hr;
|
||||
|
||||
transform = wg_transform_create(&input_format, &output_format, &attrs);
|
||||
if (!transform)
|
||||
{
|
||||
ERR_(winediag)("GStreamer doesn't support MPEG-1 video decoding, please install appropriate plugins.\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
wg_transform_destroy(transform);
|
||||
|
||||
hr = transform_create(outer, &CLSID_CMpegVideoCodec, &mpeg_video_codec_transform_ops, &object);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
wcscpy(object->sink.pin.name, L"Input");
|
||||
wcscpy(object->source.pin.name, L"Output");
|
||||
|
||||
TRACE("Created MPEG video decoder %p.\n", object);
|
||||
*out = &object->filter.IUnknown_inner;
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT mpeg_layer3_decoder_sink_query_accept(struct transform *filter, const AM_MEDIA_TYPE *mt)
|
||||
{
|
||||
const MPEGLAYER3WAVEFORMAT *format;
|
||||
|
|
|
@ -358,6 +358,7 @@ NTSTATUS wg_transform_create(void *args)
|
|||
case WG_MAJOR_TYPE_VIDEO_CINEPAK:
|
||||
case WG_MAJOR_TYPE_VIDEO_INDEO:
|
||||
case WG_MAJOR_TYPE_VIDEO_WMV:
|
||||
case WG_MAJOR_TYPE_VIDEO_MPEG1:
|
||||
if (!(element = find_element(GST_ELEMENT_FACTORY_TYPE_DECODER, src_caps, raw_caps))
|
||||
|| !append_element(transform->container, element, &first, &last))
|
||||
{
|
||||
|
@ -369,7 +370,6 @@ NTSTATUS wg_transform_create(void *args)
|
|||
case WG_MAJOR_TYPE_AUDIO:
|
||||
case WG_MAJOR_TYPE_VIDEO:
|
||||
break;
|
||||
case WG_MAJOR_TYPE_VIDEO_MPEG1:
|
||||
case WG_MAJOR_TYPE_UNKNOWN:
|
||||
GST_FIXME("Format %u not implemented!", input_format.major_type);
|
||||
gst_caps_unref(raw_caps);
|
||||
|
|
|
@ -35,6 +35,13 @@ coclass AviSplitter {}
|
|||
]
|
||||
coclass CMpegAudioCodec {}
|
||||
|
||||
[
|
||||
helpstring("MPEG Video Decoder"),
|
||||
threading(both),
|
||||
uuid(feb50740-7bef-11ce-9bd9-0000e202599c)
|
||||
]
|
||||
coclass CMpegVideoCodec {}
|
||||
|
||||
[
|
||||
helpstring("MPEG Layer-3 Decoder"),
|
||||
threading(both),
|
||||
|
|
Loading…
Add table
Reference in a new issue