based on !5504
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/quartz_parser.c | 8 ++++---- dlls/winegstreamer/unixlib.h | 12 +++++------- dlls/winegstreamer/wg_format.c | 26 +++++++++++++------------- 3 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 9b17b0afddd..b78a37c25f6 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -391,7 +391,7 @@ unsigned int wg_format_get_max_size(const struct wg_format *format) /* Both ffmpeg's encoder and a Cinepak file seen in the wild report * 24 bpp. ffmpeg sets biSizeImage as below; others may be smaller, * but as long as every sample fits into our allocator, we're fine. */ - return format->u.video_cinepak.width * format->u.video_cinepak.height * 3; + return format->u.video.width * format->u.video.height * 3;
case WG_MAJOR_TYPE_VIDEO_MPEG1: /* Estimated max size of a compressed video frame. @@ -609,11 +609,11 @@ static bool amt_from_wg_format_video_cinepak(AM_MEDIA_TYPE *mt, const struct wg_ mt->pbFormat = (BYTE *)video_format;
memset(video_format, 0, sizeof(*video_format)); - if ((frame_time = MulDiv(10000000, format->u.video_cinepak.fps_d, format->u.video_cinepak.fps_n)) != -1) + if ((frame_time = MulDiv(10000000, format->u.video.fps_d, format->u.video.fps_n)) != -1) video_format->AvgTimePerFrame = frame_time; video_format->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - video_format->bmiHeader.biWidth = format->u.video_cinepak.width; - video_format->bmiHeader.biHeight = format->u.video_cinepak.height; + video_format->bmiHeader.biWidth = format->u.video.width; + video_format->bmiHeader.biHeight = format->u.video.height; video_format->bmiHeader.biPlanes = 1; video_format->bmiHeader.biBitCount = 24; video_format->bmiHeader.biCompression = mt->subtype.Data1; diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index d77a0346d46..7270c54bb54 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -119,9 +119,14 @@ struct wg_format unsigned char codec_data[64]; } audio;
+ /* Valid members for different video formats: + * + * Uncompressed(RGB and YUV): width, height, fps_n, fps_d, padding. + * CINEPAK: width, height, fps_n, fps_d. */ struct { wg_video_format format; + /* Positive height indicates top-down video; negative height * indicates bottom-up video. */ int32_t width, height; @@ -129,13 +134,6 @@ struct wg_format RECT padding; } video; struct - { - uint32_t width; - uint32_t height; - uint32_t fps_n; - uint32_t fps_d; - } video_cinepak; - struct { int32_t width, height; uint32_t fps_n, fps_d; diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 6d10952f16d..50f8f53891b 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -287,10 +287,10 @@ static void wg_format_from_caps_video_cinepak(struct wg_format *format, const Gs }
format->major_type = WG_MAJOR_TYPE_VIDEO_CINEPAK; - format->u.video_cinepak.width = width; - format->u.video_cinepak.height = height; - format->u.video_cinepak.fps_n = fps_n; - format->u.video_cinepak.fps_d = fps_d; + format->u.video.width = width; + format->u.video.height = height; + format->u.video.fps_n = fps_n; + format->u.video.fps_d = fps_d; }
static void wg_format_from_caps_video_wmv(struct wg_format *format, const GstCaps *caps) @@ -622,12 +622,12 @@ static GstCaps *wg_format_to_caps_video_cinepak(const struct wg_format *format) if (!(caps = gst_caps_new_empty_simple("video/x-cinepak"))) return NULL;
- if (format->u.video_cinepak.width) - gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_cinepak.width, NULL); - if (format->u.video_cinepak.height) - gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_cinepak.height, NULL); - if (format->u.video_cinepak.fps_d || format->u.video_cinepak.fps_n) - gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_cinepak.fps_n, format->u.video_cinepak.fps_d, NULL); + if (format->u.video.width) + gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video.width, NULL); + if (format->u.video.height) + gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video.height, NULL); + if (format->u.video.fps_d || format->u.video.fps_n) + gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video.fps_n, format->u.video.fps_d, NULL);
return caps; } @@ -848,7 +848,7 @@ static GstCaps *wg_format_to_caps_video_mpeg1(const struct wg_format *format) gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_mpeg1.width, NULL); if (format->u.video_mpeg1.height) gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_mpeg1.height, NULL); - if (format->u.video_mpeg1.fps_d || format->u.video_cinepak.fps_n) + if (format->u.video_mpeg1.fps_d || format->u.video.fps_n) gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_mpeg1.fps_n, format->u.video_mpeg1.fps_d, NULL); return caps; } @@ -916,8 +916,8 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
case WG_MAJOR_TYPE_VIDEO_CINEPAK: /* Do not compare FPS. */ - return a->u.video_cinepak.width == b->u.video_cinepak.width - && a->u.video_cinepak.height == b->u.video_cinepak.height; + return a->u.video.width == b->u.video.width + && a->u.video.height == b->u.video.height;
case WG_MAJOR_TYPE_VIDEO_WMV: /* Do not compare FPS. */
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/mfplat.c | 22 +++++++++++----------- dlls/winegstreamer/unixlib.h | 10 +++------- dlls/winegstreamer/wg_format.c | 26 +++++++++++++------------- 3 files changed, 27 insertions(+), 31 deletions(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index f8d94f86677..e6ccda58482 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -800,33 +800,33 @@ static void mf_media_type_to_wg_format_video_h264(IMFMediaType *type, struct wg_
if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) { - format->u.video_h264.width = frame_size >> 32; - format->u.video_h264.height = (UINT32)frame_size; + format->u.video.width = frame_size >> 32; + format->u.video.height = (UINT32)frame_size; }
if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate) { - format->u.video_h264.fps_n = frame_rate >> 32; - format->u.video_h264.fps_d = (UINT32)frame_rate; + format->u.video.fps_n = frame_rate >> 32; + format->u.video.fps_d = (UINT32)frame_rate; } else { - format->u.video_h264.fps_n = 1; - format->u.video_h264.fps_d = 1; + format->u.video.fps_n = 1; + format->u.video.fps_d = 1; }
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_PROFILE, &profile))) - format->u.video_h264.profile = profile; + format->u.video.profile = profile;
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level))) - format->u.video_h264.level = level; + format->u.video.level = level;
if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_MPEG_SEQUENCE_HEADER, &codec_data, &codec_data_len))) { - if (codec_data_len <= sizeof(format->u.video_h264.codec_data)) + if (codec_data_len <= sizeof(format->u.video.codec_data)) { - format->u.video_h264.codec_data_len = codec_data_len; - memcpy(format->u.video_h264.codec_data, codec_data, codec_data_len); + format->u.video.codec_data_len = codec_data_len; + memcpy(format->u.video.codec_data, codec_data, codec_data_len); } else { diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 7270c54bb54..d07f788b1bb 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -122,7 +122,8 @@ struct wg_format /* Valid members for different video formats: * * Uncompressed(RGB and YUV): width, height, fps_n, fps_d, padding. - * CINEPAK: width, height, fps_n, fps_d. */ + * CINEPAK: width, height, fps_n, fps_d. + * H264: width, height, fps_n, fps_d, profile, level, codec_data_len, codec_data. */ struct { wg_video_format format; @@ -132,16 +133,11 @@ struct wg_format int32_t width, height; uint32_t fps_n, fps_d; RECT padding; - } video; - struct - { - int32_t width, height; - uint32_t fps_n, fps_d; uint32_t profile; uint32_t level; uint32_t codec_data_len; unsigned char codec_data[64]; - } video_h264; + } video; struct { wg_wmv_video_format format; diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 50f8f53891b..848443e3e00 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -680,20 +680,20 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) gst_caps_set_simple(caps, "stream-format", G_TYPE_STRING, "byte-stream", NULL); gst_caps_set_simple(caps, "alignment", G_TYPE_STRING, "au", NULL);
- if (format->u.video_h264.width) - gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_h264.width, NULL); - if (format->u.video_h264.height) - gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_h264.height, NULL); - if (format->u.video_h264.fps_n || format->u.video_h264.fps_d) - gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_h264.fps_n, format->u.video_h264.fps_d, NULL); + if (format->u.video.width) + gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video.width, NULL); + if (format->u.video.height) + gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video.height, NULL); + if (format->u.video.fps_n || format->u.video.fps_d) + gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video.fps_n, format->u.video.fps_d, NULL);
- switch (format->u.video_h264.profile) + switch (format->u.video.profile) { case eAVEncH264VProfile_Main: profile = "main"; break; case eAVEncH264VProfile_High: profile = "high"; break; case eAVEncH264VProfile_444: profile = "high-4:4:4"; break; default: - GST_FIXME("H264 profile attribute %u not implemented.", format->u.video_h264.profile); + GST_FIXME("H264 profile attribute %u not implemented.", format->u.video.profile); /* fallthrough */ case eAVEncH264VProfile_unknown: profile = "baseline"; @@ -701,7 +701,7 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) } gst_caps_set_simple(caps, "profile", G_TYPE_STRING, profile, NULL);
- switch (format->u.video_h264.level) + switch (format->u.video.level) { case eAVEncH264VLevel1: level = "1"; break; case eAVEncH264VLevel1_1: level = "1.1"; break; @@ -720,7 +720,7 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) case eAVEncH264VLevel5_1: level = "5.1"; break; case eAVEncH264VLevel5_2: level = "5.2"; break; default: - GST_FIXME("H264 level attribute %u not implemented.", format->u.video_h264.level); + GST_FIXME("H264 level attribute %u not implemented.", format->u.video.level); /* fallthrough */ case 0: level = NULL; @@ -729,9 +729,9 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) if (level) gst_caps_set_simple(caps, "level", G_TYPE_STRING, level, NULL);
- if (format->u.video_h264.codec_data_len) + if (format->u.video.codec_data_len) { - if (!(buffer = gst_buffer_new_and_alloc(format->u.video_h264.codec_data_len))) + if (!(buffer = gst_buffer_new_and_alloc(format->u.video.codec_data_len))) { gst_caps_unref(caps); return NULL; @@ -739,7 +739,7 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format)
GST_BUFFER_PTS(buffer) = 0; GST_BUFFER_DTS(buffer) = 0; - gst_buffer_fill(buffer, 0, format->u.video_h264.codec_data, format->u.video_h264.codec_data_len); + gst_buffer_fill(buffer, 0, format->u.video.codec_data, format->u.video.codec_data_len); gst_caps_set_simple(caps, "streamheader", GST_TYPE_BUFFER, buffer, NULL); gst_buffer_unref(buffer); }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/main.c | 9 +--- dlls/winegstreamer/quartz_parser.c | 83 ++++++++++++++++-------------- dlls/winegstreamer/unixlib.h | 26 +++------- dlls/winegstreamer/wg_format.c | 70 ++++++++++++------------- dlls/winegstreamer/wg_transform.c | 14 ++--- dlls/winegstreamer/wmv_decoder.c | 10 ++-- 6 files changed, 99 insertions(+), 113 deletions(-)
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 671d011424e..cabcae3946d 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -651,14 +651,7 @@ bool wg_video_format_is_rgb(enum wg_video_format format) case WG_VIDEO_FORMAT_RGB16: return true;
- case WG_VIDEO_FORMAT_AYUV: - case WG_VIDEO_FORMAT_I420: - case WG_VIDEO_FORMAT_NV12: - case WG_VIDEO_FORMAT_UYVY: - case WG_VIDEO_FORMAT_YUY2: - case WG_VIDEO_FORMAT_YV12: - case WG_VIDEO_FORMAT_YVYU: - case WG_VIDEO_FORMAT_UNKNOWN: + default: break; }
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index b78a37c25f6..87a5c033516 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -370,8 +370,8 @@ static unsigned int wg_format_get_max_size_video_raw(enum wg_video_format format return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */ + ALIGN(width, 4) * ((height + 1) / 2); /* U/V plane */
- case WG_VIDEO_FORMAT_UNKNOWN: - FIXME("Cannot guess maximum sample size for unknown video format.\n"); + default: + FIXME("Cannot guess maximum sample size for video format %d.\n", format); return 0; }
@@ -402,7 +402,7 @@ unsigned int wg_format_get_max_size(const struct wg_format *format)
case WG_MAJOR_TYPE_VIDEO_WMV: return wg_format_get_max_size_video_raw(WG_VIDEO_FORMAT_YV12, - format->u.video_wmv.width, format->u.video_wmv.height); + format->u.video.width, format->u.video.height);
case WG_MAJOR_TYPE_AUDIO: { @@ -488,6 +488,11 @@ static const GUID *wg_video_format_get_mediasubtype(enum wg_video_format format) case WG_VIDEO_FORMAT_YUY2: return &MEDIASUBTYPE_YUY2; case WG_VIDEO_FORMAT_YV12: return &MEDIASUBTYPE_YV12; case WG_VIDEO_FORMAT_YVYU: return &MEDIASUBTYPE_YVYU; + case WG_VIDEO_FORMAT_WMV1: return &MEDIASUBTYPE_WMV1; + case WG_VIDEO_FORMAT_WMV2: return &MEDIASUBTYPE_WMV2; + case WG_VIDEO_FORMAT_WMV3: return &MEDIASUBTYPE_WMV3; + case WG_VIDEO_FORMAT_WMVA: return &MEDIASUBTYPE_WMVA; + case WG_VIDEO_FORMAT_WVC1: return &MEDIASUBTYPE_WVC1; }
assert(0); @@ -511,10 +516,10 @@ static DWORD wg_video_format_get_compression(enum wg_video_format format) case WG_VIDEO_FORMAT_YUY2: return mmioFOURCC('Y','U','Y','2'); case WG_VIDEO_FORMAT_YV12: return mmioFOURCC('Y','V','1','2'); case WG_VIDEO_FORMAT_YVYU: return mmioFOURCC('Y','V','Y','U'); + default: + ERR("Cannot get compression for video format %d.", format); + return 0; } - - assert(0); - return 0; }
static WORD wg_video_format_get_depth(enum wg_video_format format) @@ -534,10 +539,10 @@ static WORD wg_video_format_get_depth(enum wg_video_format format) case WG_VIDEO_FORMAT_YUY2: return 16; case WG_VIDEO_FORMAT_YV12: return 12; case WG_VIDEO_FORMAT_YVYU: return 16; + default: + ERR("Cannot get depth for video format %d.", format); + return 0; } - - assert(0); - return 0; }
static bool amt_from_wg_format_video(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm) @@ -628,29 +633,29 @@ static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_form uint32_t frame_time; const GUID *subtype;
- switch (format->u.video_wmv.format) + switch (format->u.video.format) { - case WG_WMV_VIDEO_FORMAT_WMV1: + case WG_VIDEO_FORMAT_WMV1: subtype = &MEDIASUBTYPE_WMV1; break; - case WG_WMV_VIDEO_FORMAT_WMV2: + case WG_VIDEO_FORMAT_WMV2: subtype = &MEDIASUBTYPE_WMV2; break; - case WG_WMV_VIDEO_FORMAT_WMV3: + case WG_VIDEO_FORMAT_WMV3: subtype = &MEDIASUBTYPE_WMV3; break; - case WG_WMV_VIDEO_FORMAT_WMVA: + case WG_VIDEO_FORMAT_WMVA: subtype = &MEDIASUBTYPE_WMVA; break; - case WG_WMV_VIDEO_FORMAT_WVC1: + case WG_VIDEO_FORMAT_WVC1: subtype = &MEDIASUBTYPE_WVC1; break; default: - WARN("Invalid WMV format %u.\n", format->u.video_wmv.format); + WARN("Invalid WMV format %u.\n", format->u.video.format); return false; }
- if (!(video_format = CoTaskMemAlloc(sizeof(*video_format) + format->u.video_wmv.codec_data_len))) + if (!(video_format = CoTaskMemAlloc(sizeof(*video_format) + format->u.video.codec_data_len))) return false;
mt->majortype = MEDIATYPE_Video; @@ -659,22 +664,22 @@ static bool amt_from_wg_format_video_wmv(AM_MEDIA_TYPE *mt, const struct wg_form mt->bTemporalCompression = TRUE; mt->lSampleSize = 0; mt->formattype = FORMAT_VideoInfo; - mt->cbFormat = sizeof(*video_format) + format->u.video_wmv.codec_data_len; + mt->cbFormat = sizeof(*video_format) + format->u.video.codec_data_len; mt->pbFormat = (BYTE *)video_format;
memset(video_format, 0, sizeof(*video_format)); - SetRect(&video_format->rcSource, 0, 0, format->u.video_wmv.width, format->u.video_wmv.height); + SetRect(&video_format->rcSource, 0, 0, format->u.video.width, format->u.video.height); video_format->rcTarget = video_format->rcSource; - if ((frame_time = MulDiv(10000000, format->u.video_wmv.fps_d, format->u.video_wmv.fps_n)) != -1) + if ((frame_time = MulDiv(10000000, format->u.video.fps_d, format->u.video.fps_n)) != -1) video_format->AvgTimePerFrame = frame_time; - video_format->bmiHeader.biSize = sizeof(BITMAPINFOHEADER) + format->u.video_wmv.codec_data_len; - video_format->bmiHeader.biWidth = format->u.video_wmv.width; - video_format->bmiHeader.biHeight = format->u.video_wmv.height; + video_format->bmiHeader.biSize = sizeof(BITMAPINFOHEADER) + format->u.video.codec_data_len; + video_format->bmiHeader.biWidth = format->u.video.width; + video_format->bmiHeader.biHeight = format->u.video.height; video_format->bmiHeader.biPlanes = 1; video_format->bmiHeader.biCompression = mt->subtype.Data1; video_format->bmiHeader.biBitCount = 24; video_format->dwBitRate = 0; - memcpy(video_format+1, format->u.video_wmv.codec_data, format->u.video_wmv.codec_data_len); + memcpy(video_format+1, format->u.video.codec_data, format->u.video.codec_data_len);
return true; } @@ -985,31 +990,31 @@ static bool amt_to_wg_format_video_wmv(const AM_MEDIA_TYPE *mt, struct wg_format }
format->major_type = WG_MAJOR_TYPE_VIDEO_WMV; - format->u.video_wmv.width = video_format->bmiHeader.biWidth; - format->u.video_wmv.height = video_format->bmiHeader.biHeight; - format->u.video_wmv.fps_n = 10000000; - format->u.video_wmv.fps_d = video_format->AvgTimePerFrame; + format->u.video.width = video_format->bmiHeader.biWidth; + format->u.video.height = video_format->bmiHeader.biHeight; + format->u.video.fps_n = 10000000; + format->u.video.fps_d = video_format->AvgTimePerFrame;
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV1)) - format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMV1; + format->u.video.format = WG_VIDEO_FORMAT_WMV1; else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV2)) - format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMV2; + format->u.video.format = WG_VIDEO_FORMAT_WMV2; else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV3)) - format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMV3; + format->u.video.format = WG_VIDEO_FORMAT_WMV3; else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMVA)) - format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMVA; + format->u.video.format = WG_VIDEO_FORMAT_WMVA; else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WVC1)) - format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WVC1; + format->u.video.format = WG_VIDEO_FORMAT_WVC1; else - format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_UNKNOWN; + format->u.video.format = WG_VIDEO_FORMAT_UNKNOWN;
- format->u.video_wmv.codec_data_len = mt->cbFormat - sizeof(VIDEOINFOHEADER); - if (format->u.video_wmv.codec_data_len > sizeof(format->u.video_wmv.codec_data)) + format->u.video.codec_data_len = mt->cbFormat - sizeof(VIDEOINFOHEADER); + if (format->u.video.codec_data_len > sizeof(format->u.video.codec_data)) { - ERR("Too big codec_data value (%u).\n", format->u.video_wmv.codec_data_len); - format->u.video_wmv.codec_data_len = 0; + ERR("Too big codec_data value (%u).\n", format->u.video.codec_data_len); + format->u.video.codec_data_len = 0; } - memcpy(format->u.video_wmv.codec_data, video_format+1, format->u.video_wmv.codec_data_len); + memcpy(format->u.video.codec_data, video_format+1, format->u.video.codec_data_len); return true; }
diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index d07f788b1bb..75fb6610a3b 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -76,17 +76,12 @@ enum wg_video_format WG_VIDEO_FORMAT_YUY2, WG_VIDEO_FORMAT_YV12, WG_VIDEO_FORMAT_YVYU, -};
-typedef UINT32 wg_wmv_video_format; -enum wg_wmv_video_format -{ - WG_WMV_VIDEO_FORMAT_UNKNOWN, - WG_WMV_VIDEO_FORMAT_WMV1, - WG_WMV_VIDEO_FORMAT_WMV2, - WG_WMV_VIDEO_FORMAT_WMV3, - WG_WMV_VIDEO_FORMAT_WMVA, - WG_WMV_VIDEO_FORMAT_WVC1, + WG_VIDEO_FORMAT_WMV1, + WG_VIDEO_FORMAT_WMV2, + WG_VIDEO_FORMAT_WMV3, + WG_VIDEO_FORMAT_WMVA, + WG_VIDEO_FORMAT_WVC1, };
struct wg_format @@ -123,7 +118,8 @@ struct wg_format * * Uncompressed(RGB and YUV): width, height, fps_n, fps_d, padding. * CINEPAK: width, height, fps_n, fps_d. - * H264: width, height, fps_n, fps_d, profile, level, codec_data_len, codec_data. */ + * H264: width, height, fps_n, fps_d, profile, level, codec_data_len, codec_data. + * WMV: width, height, fps_n, fps_d, codec_data_len, codec_data. */ struct { wg_video_format format; @@ -139,14 +135,6 @@ struct wg_format unsigned char codec_data[64]; } video; struct - { - wg_wmv_video_format format; - int32_t width, height; - uint32_t fps_n, fps_d; - uint32_t codec_data_len; - unsigned char codec_data[64]; - } video_wmv; - struct { int32_t width, height; uint32_t fps_n, fps_d; diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 848443e3e00..da618313597 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -298,8 +298,8 @@ static void wg_format_from_caps_video_wmv(struct wg_format *format, const GstCap const GstStructure *structure = gst_caps_get_structure(caps, 0); gint width, height, fps_n, fps_d, wmv_version = 0; gchar format_buffer[5] = {'W','M','V','0',0}; - enum wg_wmv_video_format wmv_format; const gchar *wmv_format_str = NULL; + enum wg_video_format video_format; const GValue *codec_data_value; GstBuffer *codec_data; GstMapInfo map; @@ -323,17 +323,17 @@ static void wg_format_from_caps_video_wmv(struct wg_format *format, const GstCap wmv_format_str = format_buffer; } if (!strcmp(wmv_format_str, "WMV1")) - wmv_format = WG_WMV_VIDEO_FORMAT_WMV1; + video_format = WG_VIDEO_FORMAT_WMV1; else if (!strcmp(wmv_format_str, "WMV2")) - wmv_format = WG_WMV_VIDEO_FORMAT_WMV2; + video_format = WG_VIDEO_FORMAT_WMV2; else if (!strcmp(wmv_format_str, "WMV3")) - wmv_format = WG_WMV_VIDEO_FORMAT_WMV3; + video_format = WG_VIDEO_FORMAT_WMV3; else if (!strcmp(wmv_format_str, "WMVA")) - wmv_format = WG_WMV_VIDEO_FORMAT_WMVA; + video_format = WG_VIDEO_FORMAT_WMVA; else if (!strcmp(wmv_format_str, "WVC1")) - wmv_format = WG_WMV_VIDEO_FORMAT_WVC1; + video_format = WG_VIDEO_FORMAT_WVC1; else - wmv_format = WG_WMV_VIDEO_FORMAT_UNKNOWN; + video_format = WG_VIDEO_FORMAT_UNKNOWN;
if (!gst_structure_get_fraction(structure, "framerate", &fps_n, &fps_d)) { @@ -342,19 +342,19 @@ static void wg_format_from_caps_video_wmv(struct wg_format *format, const GstCap }
format->major_type = WG_MAJOR_TYPE_VIDEO_WMV; - format->u.video_wmv.width = width; - format->u.video_wmv.height = height; - format->u.video_wmv.format = wmv_format; - format->u.video_wmv.fps_n = fps_n; - format->u.video_wmv.fps_d = fps_d; + format->u.video.width = width; + format->u.video.height = height; + format->u.video.format = video_format; + format->u.video.fps_n = fps_n; + format->u.video.fps_d = fps_d;
if ((codec_data_value = gst_structure_get_value(structure, "codec_data")) && (codec_data = gst_value_get_buffer(codec_data_value))) { gst_buffer_map(codec_data, &map, GST_MAP_READ); - if (map.size <= sizeof(format->u.video_wmv.codec_data)) + if (map.size <= sizeof(format->u.video.codec_data)) { - format->u.video_wmv.codec_data_len = map.size; - memcpy(format->u.video_wmv.codec_data, map.data, map.size); + format->u.video.codec_data_len = map.size; + memcpy(format->u.video.codec_data, map.data, map.size); } else GST_WARNING("Too big codec_data value (%u) in %" GST_PTR_FORMAT ".", (UINT)map.size, caps); @@ -757,32 +757,32 @@ static GstCaps *wg_format_to_caps_video_wmv(const struct wg_format *format) if (!(caps = gst_caps_new_empty_simple("video/x-wmv"))) return NULL;
- switch (format->u.video_wmv.format) + switch (format->u.video.format) { - case WG_WMV_VIDEO_FORMAT_WMV1: + case WG_VIDEO_FORMAT_WMV1: wmv_format = "WMV1"; wmv_version = 1; break; - case WG_WMV_VIDEO_FORMAT_WMV2: + case WG_VIDEO_FORMAT_WMV2: wmv_format = "WMV2"; wmv_version = 2; break; - case WG_WMV_VIDEO_FORMAT_WMV3: + case WG_VIDEO_FORMAT_WMV3: wmv_format = "WMV3"; wmv_version = 3; break; - case WG_WMV_VIDEO_FORMAT_WMVA: + case WG_VIDEO_FORMAT_WMVA: wmv_format = "WMVA"; wmv_version = 3; break; - case WG_WMV_VIDEO_FORMAT_WVC1: + case WG_VIDEO_FORMAT_WVC1: wmv_format = "WVC1"; wmv_version = 3; break; default: - GST_WARNING("Unknown WMV format %u.", format->u.video_wmv.format); + GST_WARNING("Unknown WMV format %u.", format->u.video.format); /* fallthrough */ - case WG_WMV_VIDEO_FORMAT_UNKNOWN: + case WG_VIDEO_FORMAT_UNKNOWN: wmv_format = NULL; wmv_version = 0; break; @@ -792,22 +792,22 @@ static GstCaps *wg_format_to_caps_video_wmv(const struct wg_format *format) gst_caps_set_simple(caps, "format", G_TYPE_STRING, wmv_format, NULL); if (wmv_version) gst_caps_set_simple(caps, "wmvversion", G_TYPE_INT, wmv_version, NULL); - if (format->u.video_wmv.width) - gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_wmv.width, NULL); - if (format->u.video_wmv.height) - gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_wmv.height, NULL); - if (format->u.video_wmv.fps_d || format->u.video_wmv.fps_n) - gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_wmv.fps_n, format->u.video_wmv.fps_d, NULL); + if (format->u.video.width) + gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video.width, NULL); + if (format->u.video.height) + gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video.height, NULL); + if (format->u.video.fps_d || format->u.video.fps_n) + gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video.fps_n, format->u.video.fps_d, NULL);
- if (format->u.video_wmv.codec_data_len) + if (format->u.video.codec_data_len) { - if (!(buffer = gst_buffer_new_and_alloc(format->u.video_wmv.codec_data_len))) + if (!(buffer = gst_buffer_new_and_alloc(format->u.video.codec_data_len))) { gst_caps_unref(caps); return NULL; }
- gst_buffer_fill(buffer, 0, format->u.video_wmv.codec_data, format->u.video_wmv.codec_data_len); + gst_buffer_fill(buffer, 0, format->u.video.codec_data, format->u.video.codec_data_len); gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL); gst_buffer_unref(buffer); } @@ -921,9 +921,9 @@ bool wg_format_compare(const struct wg_format *a, const struct wg_format *b)
case WG_MAJOR_TYPE_VIDEO_WMV: /* Do not compare FPS. */ - return a->u.video_wmv.format == b->u.video_wmv.format - && a->u.video_wmv.width == b->u.video_wmv.width - && a->u.video_wmv.height == b->u.video_wmv.height; + return a->u.video.format == b->u.video.format + && a->u.video.width == b->u.video.width + && a->u.video.height == b->u.video.height; }
assert(0); diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 52c32123b4a..d85da3d7633 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -358,21 +358,21 @@ static GstCaps *transform_get_parsed_caps(struct wg_format *format, const char * gst_caps_set_simple(parsed_caps, "parsed", G_TYPE_BOOLEAN, true, "mpegversion", G_TYPE_INT, 1, NULL); break; case WG_MAJOR_TYPE_VIDEO_WMV: - switch (format->u.video_wmv.format) + switch (format->u.video.format) { - case WG_WMV_VIDEO_FORMAT_WMV1: + case WG_VIDEO_FORMAT_WMV1: gst_caps_set_simple(parsed_caps, "wmvversion", G_TYPE_INT, 1, NULL); break; - case WG_WMV_VIDEO_FORMAT_WMV2: + case WG_VIDEO_FORMAT_WMV2: gst_caps_set_simple(parsed_caps, "wmvversion", G_TYPE_INT, 2, NULL); break; - case WG_WMV_VIDEO_FORMAT_WMV3: - case WG_WMV_VIDEO_FORMAT_WMVA: - case WG_WMV_VIDEO_FORMAT_WVC1: + case WG_VIDEO_FORMAT_WMV3: + case WG_VIDEO_FORMAT_WMVA: + case WG_VIDEO_FORMAT_WVC1: gst_caps_set_simple(parsed_caps, "wmvversion", G_TYPE_INT, 3, NULL); break; default: - GST_WARNING("Unknown WMV format %u.", format->u.video_wmv.format); + GST_WARNING("Unknown WMV format %u.", format->u.video.format); break; } break; diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c index ee77309aae4..ea8b4b19eb6 100644 --- a/dlls/winegstreamer/wmv_decoder.c +++ b/dlls/winegstreamer/wmv_decoder.c @@ -445,8 +445,8 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde if (!wg_format_is_set(&decoder->input_format)) return DMO_E_TYPE_NOT_SET;
- width = decoder->input_format.u.video_wmv.width; - height = abs(decoder->input_format.u.video_wmv.height); + width = decoder->input_format.u.video.width; + height = abs(decoder->input_format.u.video.height); subtype = wmv_decoder_output_types[type_index].subtype; if (FAILED(hr = MFCalculateImageSize(subtype, width, height, &image_size))) { @@ -470,8 +470,8 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde info->rcSource.bottom = height; info->rcTarget.right = width; info->rcTarget.bottom = height; - info->AvgTimePerFrame = MulDiv(10000000, decoder->input_format.u.video_wmv.fps_d, - decoder->input_format.u.video_wmv.fps_n); + info->AvgTimePerFrame = MulDiv(10000000, decoder->input_format.u.video.fps_d, + decoder->input_format.u.video.fps_n); info->bmiHeader.biSize = sizeof(info->bmiHeader); info->bmiHeader.biWidth = width; info->bmiHeader.biHeight = height; @@ -881,7 +881,7 @@ HRESULT wmv_decoder_create(IUnknown *outer, IUnknown **out) static const struct wg_format input_format = { .major_type = WG_MAJOR_TYPE_VIDEO_WMV, - .u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMV3, + .u.video.format = WG_VIDEO_FORMAT_WMV3, }; static const struct wg_format output_format = {
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/mfplat.c | 14 +++++++------- dlls/winegstreamer/unixlib.h | 10 +++------- dlls/winegstreamer/wg_format.c | 16 ++++++++-------- 3 files changed, 18 insertions(+), 22 deletions(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index e6ccda58482..2344e22b12b 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -845,22 +845,22 @@ static void mf_media_type_to_wg_format_video_indeo(IMFMediaType *type, uint32_t
if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) { - format->u.video_indeo.width = frame_size >> 32; - format->u.video_indeo.height = (UINT32)frame_size; + format->u.video.width = frame_size >> 32; + format->u.video.height = (UINT32)frame_size; }
if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate) { - format->u.video_indeo.fps_n = frame_rate >> 32; - format->u.video_indeo.fps_d = (UINT32)frame_rate; + format->u.video.fps_n = frame_rate >> 32; + format->u.video.fps_d = (UINT32)frame_rate; } else { - format->u.video_indeo.fps_n = 1; - format->u.video_indeo.fps_d = 1; + format->u.video.fps_n = 1; + format->u.video.fps_d = 1; }
- format->u.video_indeo.version = version; + format->u.video.version = version; }
void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 75fb6610a3b..ee5b5a0c757 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -119,7 +119,8 @@ struct wg_format * Uncompressed(RGB and YUV): width, height, fps_n, fps_d, padding. * CINEPAK: width, height, fps_n, fps_d. * H264: width, height, fps_n, fps_d, profile, level, codec_data_len, codec_data. - * WMV: width, height, fps_n, fps_d, codec_data_len, codec_data. */ + * WMV: width, height, fps_n, fps_d, codec_data_len, codec_data. + * INDEO: width, height, fps_n, fps_d, version. */ struct { wg_video_format format; @@ -131,16 +132,11 @@ struct wg_format RECT padding; uint32_t profile; uint32_t level; + uint32_t version; uint32_t codec_data_len; unsigned char codec_data[64]; } video; struct - { - int32_t width, height; - uint32_t fps_n, fps_d; - uint32_t version; - } video_indeo; - struct { int32_t width, height; uint32_t fps_n, fps_d; diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index da618313597..460e3d8cae5 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -822,14 +822,14 @@ static GstCaps *wg_format_to_caps_video_indeo(const struct wg_format *format) if (!(caps = gst_caps_new_empty_simple("video/x-indeo"))) return NULL;
- if (format->u.video_indeo.width) - gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_indeo.width, NULL); - if (format->u.video_indeo.height) - gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_indeo.height, NULL); - if (format->u.video_indeo.fps_d || format->u.video_indeo.fps_n) - gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_indeo.fps_n, format->u.video_indeo.fps_d, NULL); - if (format->u.video_indeo.version) - gst_caps_set_simple(caps, "indeoversion", G_TYPE_INT, format->u.video_indeo.version, NULL); + if (format->u.video.width) + gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video.width, NULL); + if (format->u.video.height) + gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video.height, NULL); + if (format->u.video.fps_d || format->u.video.fps_n) + gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video.fps_n, format->u.video.fps_d, NULL); + if (format->u.video.version) + gst_caps_set_simple(caps, "indeoversion", G_TYPE_INT, format->u.video.version, NULL);
return caps; }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/quartz_parser.c | 19 ++++++++----------- dlls/winegstreamer/quartz_transform.c | 2 +- dlls/winegstreamer/unixlib.h | 8 ++------ dlls/winegstreamer/wg_format.c | 20 ++++++++++---------- 4 files changed, 21 insertions(+), 28 deletions(-)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 87a5c033516..8bbfee17df0 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -394,13 +394,10 @@ unsigned int wg_format_get_max_size(const struct wg_format *format) return format->u.video.width * format->u.video.height * 3;
case WG_MAJOR_TYPE_VIDEO_MPEG1: + case WG_MAJOR_TYPE_VIDEO_WMV: /* Estimated max size of a compressed video frame. * There's no way to no way to know the real upper bound, * so let's just use the decompressed size and hope it works. */ - return wg_format_get_max_size_video_raw(WG_VIDEO_FORMAT_YV12, - format->u.video_mpeg1.width, format->u.video_mpeg1.height); - - case WG_MAJOR_TYPE_VIDEO_WMV: return wg_format_get_max_size_video_raw(WG_VIDEO_FORMAT_YV12, format->u.video.width, format->u.video.height);
@@ -701,11 +698,11 @@ static bool amt_from_wg_format_video_mpeg1(AM_MEDIA_TYPE *mt, const struct wg_fo mt->pbFormat = (BYTE *)video_format;
memset(video_format, 0, sizeof(*video_format)); - if ((frame_time = MulDiv(10000000, format->u.video_mpeg1.fps_d, format->u.video_mpeg1.fps_n)) != -1) + if ((frame_time = MulDiv(10000000, format->u.video.fps_d, format->u.video.fps_n)) != -1) video_format->hdr.AvgTimePerFrame = frame_time; video_format->hdr.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - video_format->hdr.bmiHeader.biWidth = format->u.video_mpeg1.width; - video_format->hdr.bmiHeader.biHeight = format->u.video_mpeg1.height; + video_format->hdr.bmiHeader.biWidth = format->u.video.width; + video_format->hdr.bmiHeader.biHeight = format->u.video.height; video_format->hdr.bmiHeader.biPlanes = 1; video_format->hdr.bmiHeader.biBitCount = 12; video_format->hdr.bmiHeader.biCompression = mt->subtype.Data1; @@ -1034,10 +1031,10 @@ static bool amt_to_wg_format_video_mpeg1(const AM_MEDIA_TYPE *mt, struct wg_form }
format->major_type = WG_MAJOR_TYPE_VIDEO_MPEG1; - format->u.video_mpeg1.width = video_format->hdr.bmiHeader.biWidth; - format->u.video_mpeg1.height = video_format->hdr.bmiHeader.biHeight; - format->u.video_mpeg1.fps_n = 10000000; - format->u.video_mpeg1.fps_d = video_format->hdr.AvgTimePerFrame; + format->u.video.width = video_format->hdr.bmiHeader.biWidth; + format->u.video.height = video_format->hdr.bmiHeader.biHeight; + format->u.video.fps_n = 10000000; + format->u.video.fps_d = video_format->hdr.AvgTimePerFrame;
return true; } diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c index 784bf6f9411..ad0c3077733 100644 --- a/dlls/winegstreamer/quartz_transform.c +++ b/dlls/winegstreamer/quartz_transform.c @@ -907,7 +907,7 @@ HRESULT mpeg_video_codec_create(IUnknown *outer, IUnknown **out) static const struct wg_format input_format = { .major_type = WG_MAJOR_TYPE_VIDEO_MPEG1, - .u.video_mpeg1 = {}, + .u.video = {}, }; struct wg_transform_attrs attrs = {0}; wg_transform_t transform; diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index ee5b5a0c757..2b3365834f5 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -120,7 +120,8 @@ struct wg_format * CINEPAK: width, height, fps_n, fps_d. * H264: width, height, fps_n, fps_d, profile, level, codec_data_len, codec_data. * WMV: width, height, fps_n, fps_d, codec_data_len, codec_data. - * INDEO: width, height, fps_n, fps_d, version. */ + * INDEO: width, height, fps_n, fps_d, version. + * MPEG1: width, height, fps_n, fps_d. */ struct { wg_video_format format; @@ -136,11 +137,6 @@ struct wg_format uint32_t codec_data_len; unsigned char codec_data[64]; } video; - struct - { - int32_t width, height; - uint32_t fps_n, fps_d; - } video_mpeg1; } u; };
diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 460e3d8cae5..b28dc3f22ec 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -384,10 +384,10 @@ static void wg_format_from_caps_video_mpeg1(struct wg_format *format, const GstC }
format->major_type = WG_MAJOR_TYPE_VIDEO_MPEG1; - format->u.video_mpeg1.width = width; - format->u.video_mpeg1.height = height; - format->u.video_mpeg1.fps_n = fps_n; - format->u.video_mpeg1.fps_d = fps_d; + format->u.video.width = width; + format->u.video.height = height; + format->u.video.fps_n = fps_n; + format->u.video.fps_d = fps_d; }
void wg_format_from_caps(struct wg_format *format, const GstCaps *caps) @@ -844,12 +844,12 @@ static GstCaps *wg_format_to_caps_video_mpeg1(const struct wg_format *format) gst_caps_set_simple(caps, "mpegversion", G_TYPE_INT, 1, NULL); gst_caps_set_simple(caps, "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); gst_caps_set_simple(caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - if (format->u.video_mpeg1.width) - gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_mpeg1.width, NULL); - if (format->u.video_mpeg1.height) - gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_mpeg1.height, NULL); - if (format->u.video_mpeg1.fps_d || format->u.video.fps_n) - gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_mpeg1.fps_n, format->u.video_mpeg1.fps_d, NULL); + if (format->u.video.width) + gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video.width, NULL); + if (format->u.video.height) + gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video.height, NULL); + if (format->u.video.fps_d || format->u.video.fps_n) + gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video.fps_n, format->u.video.fps_d, NULL); return caps; }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_decoder.c | 31 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 8cdab7cdb8b..e931880659e 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -821,24 +821,10 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U decoder->output_type_count = output_type_count; decoder->output_types = output_types;
- decoder->input_info.dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER - | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE; - decoder->input_info.cbSize = 0x1000; - decoder->output_info.dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER - | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; - decoder->output_info.cbSize = 1920 * 1088 * 2; - if (FAILED(hr = MFCreateMediaType(&decoder->stream_type))) goto failed; if (FAILED(hr = MFCreateAttributes(&decoder->attributes, 16))) goto failed; - if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_LOW_LATENCY, 0))) - goto failed; - if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D11_AWARE, TRUE))) - goto failed; - if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &AVDecVideoAcceleration_H264, TRUE))) - goto failed; - if (FAILED(hr = MFCreateAttributes(&decoder->output_attributes, 0))) goto failed; if (FAILED(hr = wg_sample_queue_create(&decoder->wg_sample_queue))) @@ -887,6 +873,7 @@ HRESULT h264_decoder_create(REFIID riid, void **out) }; static const struct wg_format input_format = {.major_type = WG_MAJOR_TYPE_VIDEO_H264}; struct wg_transform_attrs attrs = {0}; + struct video_decoder *decoder; wg_transform_t transform; IMFTransform *iface; HRESULT hr; @@ -903,6 +890,22 @@ HRESULT h264_decoder_create(REFIID riid, void **out) if (FAILED(hr = video_decoder_create_with_types(h264_decoder_input_types, ARRAY_SIZE(h264_decoder_input_types), video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), &iface))) return hr; + decoder = impl_from_IMFTransform(iface); + + decoder->input_info.dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER + | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE; + decoder->input_info.cbSize = 0x1000; + decoder->output_info.dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER + | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; + decoder->output_info.cbSize = 1920 * 1088 * 2; + + if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_LOW_LATENCY, 0)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D11_AWARE, TRUE)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &AVDecVideoAcceleration_H264, TRUE))) + { + IMFTransform_Release(iface); + return hr; + }
hr = IMFTransform_QueryInterface(iface, riid, out); IMFTransform_Release(iface);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 2 + dlls/winegstreamer/main.c | 15 +++ dlls/winegstreamer/quartz_parser.c | 5 - dlls/winegstreamer/quartz_transform.c | 13 +-- dlls/winegstreamer/wma_decoder.c | 151 ++++++++++++-------------- dlls/winegstreamer/wmv_decoder.c | 82 ++++++++------ 6 files changed, 140 insertions(+), 128 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index e03c779f750..a616939b524 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -83,6 +83,8 @@ void wg_parser_stream_seek(wg_parser_stream_t stream, double rate,
wg_transform_t wg_transform_create(const struct wg_format *input_format, const struct wg_format *output_format, const struct wg_transform_attrs *attrs); +HRESULT wg_transform_create_quartz(const AM_MEDIA_TYPE *input_format, const AM_MEDIA_TYPE *output_format, + const struct wg_transform_attrs *attrs, wg_transform_t *transform); void wg_transform_destroy(wg_transform_t transform); bool wg_transform_set_output_format(wg_transform_t transform, struct wg_format *format); bool wg_transform_get_status(wg_transform_t transform, bool *accepts_input); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index cabcae3946d..559e882fcc5 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -356,6 +356,21 @@ wg_transform_t wg_transform_create(const struct wg_format *input_format, return params.transform; }
+HRESULT wg_transform_create_quartz(const AM_MEDIA_TYPE *input_type, const AM_MEDIA_TYPE *output_type, + const struct wg_transform_attrs *attrs, wg_transform_t *transform) +{ + struct wg_format input_format, output_format; + + TRACE("input_type %p, output_type %p.\n", input_type, output_type); + + amt_to_wg_format(input_type, &input_format); + amt_to_wg_format(output_type, &output_format); + if (!(*transform = wg_transform_create(&input_format, &output_format, attrs))) + return E_FAIL; + + return S_OK; +} + void wg_transform_destroy(wg_transform_t transform) { TRACE("transform %#I64x.\n", transform); diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 8bbfee17df0..7d2178e1b19 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -873,11 +873,6 @@ static bool amt_to_wg_format_audio_wma(const AM_MEDIA_TYPE *mt, struct wg_format 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.version = 1; diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c index ad0c3077733..b85b24f4278 100644 --- a/dlls/winegstreamer/quartz_transform.c +++ b/dlls/winegstreamer/quartz_transform.c @@ -98,26 +98,19 @@ static HRESULT transform_query_interface(struct strmbase_filter *iface, REFIID i static HRESULT transform_init_stream(struct strmbase_filter *iface) { struct transform *filter = impl_from_strmbase_filter(iface); - struct wg_format input_format, output_format; struct wg_transform_attrs attrs = {0}; HRESULT hr;
if (filter->source.pin.peer) { - if (!amt_to_wg_format(&filter->sink.pin.mt, &input_format)) - return E_FAIL; - - if (!amt_to_wg_format(&filter->source.pin.mt, &output_format)) - return E_FAIL; - if (FAILED(hr = wg_sample_queue_create(&filter->sample_queue))) return hr;
- filter->transform = wg_transform_create(&input_format, &output_format, &attrs); - if (!filter->transform) + if (FAILED(hr = wg_transform_create_quartz(&filter->sink.pin.mt, &filter->source.pin.mt, + &attrs, &filter->transform))) { wg_sample_queue_destroy(filter->sample_queue); - return E_FAIL; + return hr; }
hr = IMemAllocator_Commit(filter->source.pAllocator); diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index ee128dd7905..e08aff5923d 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -53,8 +53,8 @@ struct wma_decoder IUnknown *outer; LONG refcount;
- struct wg_format input_format; - struct wg_format output_format; + DMO_MEDIA_TYPE input_type; + DMO_MEDIA_TYPE output_type;
DWORD input_buf_size; DWORD output_buf_size; @@ -73,19 +73,13 @@ static HRESULT try_create_wg_transform(struct wma_decoder *decoder) struct wg_transform_attrs attrs = {0};
if (decoder->wg_transform) + { wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - - if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) - return MF_E_INVALIDMEDIATYPE; - - if (decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) - return MF_E_INVALIDMEDIATYPE; - - if (!(decoder->wg_transform = wg_transform_create(&decoder->input_format, &decoder->output_format, &attrs))) - return E_FAIL; + decoder->wg_transform = 0; + }
- return S_OK; + return wg_transform_create_quartz(&decoder->input_type, &decoder->output_type, + &attrs, &decoder->wg_transform); }
static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) @@ -202,8 +196,8 @@ static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id
TRACE("iface %p, id %lu, info %p.\n", iface, id, info);
- if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN - || decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL) + || IsEqualGUID(&decoder->output_type.majortype, &GUID_NULL)) { memset(info, 0, sizeof(*info)); return MF_E_TRANSFORM_TYPE_NOT_SET; @@ -223,8 +217,8 @@ static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD i
TRACE("iface %p, id %lu, info %p.\n", iface, id, info);
- if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN - || decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL) + || IsEqualGUID(&decoder->output_type.majortype, &GUID_NULL)) { memset(info, 0, sizeof(*info)); return MF_E_TRANSFORM_TYPE_NOT_SET; @@ -280,11 +274,12 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR struct wma_decoder *decoder = impl_from_IMFTransform(iface); IMFMediaType *media_type; const GUID *output_type; + WAVEFORMATEX *wfx; HRESULT hr;
TRACE("iface %p, id %lu, index %lu, type %p.\n", iface, id, index, type);
- if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) return MF_E_TRANSFORM_TYPE_NOT_SET;
*type = NULL; @@ -316,20 +311,16 @@ static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWOR sample_size))) goto done;
- if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, - decoder->input_format.u.audio.channels))) + wfx = (WAVEFORMATEX *)decoder->input_type.pbFormat; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_NUM_CHANNELS, wfx->nChannels))) goto done; - - if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, - decoder->input_format.u.audio.rate))) + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, wfx->nSamplesPerSec))) goto done;
- block_alignment = sample_size * decoder->input_format.u.audio.channels / 8; - if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, - block_alignment))) + block_alignment = sample_size * wfx->nChannels / 8; + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, block_alignment))) goto done; - if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, - decoder->input_format.u.audio.rate * block_alignment))) + if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, wfx->nSamplesPerSec * block_alignment))) goto done;
if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, 1))) @@ -385,9 +376,13 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM if (flags & MFT_SET_TYPE_TEST_ONLY) return S_OK;
- mf_media_type_to_wg_format(type, &decoder->input_format); - decoder->input_buf_size = block_alignment; - decoder->output_format.major_type = WG_MAJOR_TYPE_UNKNOWN; + FreeMediaType(&decoder->output_type); + memset(&decoder->output_type, 0, sizeof(decoder->output_type)); + FreeMediaType(&decoder->input_type); + memset(&decoder->input_type, 0, sizeof(decoder->input_type)); + + if (SUCCEEDED(hr = MFInitAMMediaTypeFromMFMediaType(type, GUID_NULL, &decoder->input_type))) + decoder->input_buf_size = block_alignment;
return hr; } @@ -403,7 +398,7 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
TRACE("iface %p, id %lu, type %p, flags %#lx.\n", iface, id, type, flags);
- if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) return MF_E_TRANSFORM_TYPE_NOT_SET;
if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) || @@ -446,10 +441,15 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF if (flags & MFT_SET_TYPE_TEST_ONLY) return S_OK;
- decoder->input_format.u.audio.depth = sample_size; + FreeMediaType(&decoder->output_type); + memset(&decoder->output_type, 0, sizeof(decoder->output_type));
- mf_media_type_to_wg_format(type, &decoder->output_format); - decoder->output_buf_size = 1024 * block_alignment * channel_count; + if (SUCCEEDED(hr = MFInitAMMediaTypeFromMFMediaType(type, GUID_NULL, &decoder->output_type))) + { + WAVEFORMATEX *wfx = (WAVEFORMATEX *)decoder->input_type.pbFormat; + wfx->wBitsPerSample = sample_size; + decoder->output_buf_size = 1024 * block_alignment * channel_count; + }
if (FAILED(hr = try_create_wg_transform(decoder))) goto failed; @@ -457,7 +457,8 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF return S_OK;
failed: - decoder->output_format.major_type = WG_MAJOR_TYPE_UNKNOWN; + FreeMediaType(&decoder->output_type); + memset(&decoder->output_type, 0, sizeof(decoder->output_type)); return hr; }
@@ -656,7 +657,9 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde DMO_MEDIA_TYPE *type) { struct wma_decoder *decoder = impl_from_IMediaObject(iface); - WAVEFORMATEX *wfx; + IMFMediaType *media_type; + UINT32 depth; + HRESULT hr;
TRACE("iface %p, index %lu, type_index %lu, type %p\n", iface, index, type_index, type);
@@ -664,42 +667,34 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde return DMO_E_INVALIDSTREAMINDEX; if (type_index >= 1) return DMO_E_NO_MORE_ITEMS; - if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET; if (!type) return S_OK;
- memset(type, 0, sizeof(*type)); - type->majortype = MFMediaType_Audio; - type->subtype = MEDIASUBTYPE_PCM; - type->formattype = FORMAT_WaveFormatEx; - type->bFixedSizeSamples = FALSE; - type->bTemporalCompression = TRUE; - type->lSampleSize = 0; - - type->cbFormat = sizeof(WAVEFORMATEX); - type->pbFormat = CoTaskMemAlloc(type->cbFormat); - memset(type->pbFormat, 0, type->cbFormat); + if (FAILED(hr = MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + &decoder->input_type, &media_type))) + return hr;
- wfx = (WAVEFORMATEX *)type->pbFormat; - if (decoder->input_format.u.audio.depth == 32) - wfx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + if (SUCCEEDED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, &depth)) + && depth == 32) + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_Float); else - wfx->wFormatTag = WAVE_FORMAT_PCM; - wfx->nChannels = decoder->input_format.u.audio.channels; - wfx->nSamplesPerSec = decoder->input_format.u.audio.rate; - wfx->wBitsPerSample = decoder->input_format.u.audio.depth; - wfx->nAvgBytesPerSec = wfx->nChannels * wfx->nSamplesPerSec * wfx->wBitsPerSample / 8; - wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8; + hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
- return S_OK; + if (SUCCEEDED(hr)) + hr = IMFMediaType_DeleteItem(media_type, &MF_MT_USER_DATA); + if (SUCCEEDED(hr)) + hr = MFInitAMMediaTypeFromMFMediaType(media_type, GUID_NULL, type); + + IMFMediaType_Release(media_type); + return hr; }
static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags) { struct wma_decoder *decoder = impl_from_IMediaObject(iface); - struct wg_format wg_format; unsigned int i;
TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); @@ -711,7 +706,8 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index { if (flags != DMO_SET_TYPEF_CLEAR) return E_INVALIDARG; - memset(&decoder->input_format, 0, sizeof(decoder->input_format)); + FreeMediaType(&decoder->input_type); + memset(&decoder->input_type, 0, sizeof(decoder->input_type)); if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -733,14 +729,13 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index if (i == ARRAY_SIZE(wma_decoder_input_types)) return DMO_E_TYPE_NOT_ACCEPTED;
- if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) - return DMO_E_TYPE_NOT_ACCEPTED; - assert(wg_format.major_type == WG_MAJOR_TYPE_AUDIO_WMA); - if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK;
- decoder->input_format = wg_format; + FreeMediaType(&decoder->input_type); + memset(&decoder->input_type, 0, sizeof(decoder->input_type)); + CopyMediaType(&decoder->input_type, type); + if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -755,8 +750,8 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde { struct wma_decoder *decoder = impl_from_IMediaObject(iface); struct wg_transform_attrs attrs = {0}; - struct wg_format wg_format; unsigned int i; + HRESULT hr;
TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags);
@@ -767,7 +762,8 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde { if (flags != DMO_SET_TYPEF_CLEAR) return E_INVALIDARG; - memset(&decoder->output_format, 0, sizeof(decoder->output_format)); + FreeMediaType(&decoder->output_type); + memset(&decoder->output_type, 0, sizeof(decoder->output_type)); if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -789,18 +785,14 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde if (i == ARRAY_SIZE(wma_decoder_output_types)) return DMO_E_TYPE_NOT_ACCEPTED;
- - if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) - return DMO_E_TYPE_NOT_ACCEPTED; - assert(wg_format.major_type == WG_MAJOR_TYPE_AUDIO); - - if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET; - if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK;
- decoder->output_format = wg_format; + FreeMediaType(&decoder->output_type); + memset(&decoder->output_type, 0, sizeof(decoder->output_type)); + CopyMediaType(&decoder->output_type, type);
/* Set up wg_transform. */ if (decoder->wg_transform) @@ -808,8 +800,9 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde wg_transform_destroy(decoder->wg_transform); decoder->wg_transform = 0; } - if (!(decoder->wg_transform = wg_transform_create(&decoder->input_format, &decoder->output_format, &attrs))) - return E_FAIL; + if (FAILED(hr = wg_transform_create_quartz(&decoder->input_type, &decoder->output_type, + &attrs, &decoder->wg_transform))) + return hr;
return S_OK; } @@ -844,7 +837,7 @@ static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD return E_POINTER; if (index > 0) return DMO_E_INVALIDSTREAMINDEX; - if (decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + if (IsEqualGUID(&decoder->output_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET;
*size = 8192; diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c index ea8b4b19eb6..e63448427b8 100644 --- a/dlls/winegstreamer/wmv_decoder.c +++ b/dlls/winegstreamer/wmv_decoder.c @@ -81,19 +81,13 @@ struct wmv_decoder IUnknown *outer; LONG refcount;
- struct wg_format input_format; - struct wg_format output_format; - GUID output_subtype; + DMO_MEDIA_TYPE input_type; + DMO_MEDIA_TYPE output_type;
wg_transform_t wg_transform; struct wg_sample_queue *wg_sample_queue; };
-static bool wg_format_is_set(struct wg_format *format) -{ - return format->major_type != WG_MAJOR_TYPE_UNKNOWN; -} - static inline struct wmv_decoder *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, struct wmv_decoder, IUnknown_inner); @@ -428,6 +422,8 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde DMO_MEDIA_TYPE *type) { struct wmv_decoder *decoder = impl_from_IMediaObject(iface); + UINT64 frame_size, frame_rate; + IMFMediaType *media_type; VIDEOINFOHEADER *info; const GUID *subtype; LONG width, height; @@ -442,15 +438,25 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde return DMO_E_NO_MORE_ITEMS; if (!type) return S_OK; - if (!wg_format_is_set(&decoder->input_format)) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET;
- width = decoder->input_format.u.video.width; - height = abs(decoder->input_format.u.video.height); + if (FAILED(hr = MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + &decoder->input_type, &media_type))) + return hr; + + if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size))) + frame_size = 0; + if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_RATE, &frame_rate))) + frame_rate = 0; + + width = frame_size >> 32; + height = (UINT32)frame_size; subtype = wmv_decoder_output_types[type_index].subtype; if (FAILED(hr = MFCalculateImageSize(subtype, width, height, &image_size))) { FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(subtype)); + IMFMediaType_Release(media_type); return hr; }
@@ -470,8 +476,8 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde info->rcSource.bottom = height; info->rcTarget.right = width; info->rcTarget.bottom = height; - info->AvgTimePerFrame = MulDiv(10000000, decoder->input_format.u.video.fps_d, - decoder->input_format.u.video.fps_n); + if (frame_rate) + MFFrameRateToAverageTimePerFrame(frame_rate >> 32, frame_rate, (UINT64 *)&info->AvgTimePerFrame); info->bmiHeader.biSize = sizeof(info->bmiHeader); info->bmiHeader.biWidth = width; info->bmiHeader.biHeight = height; @@ -480,6 +486,7 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde info->bmiHeader.biCompression = wmv_decoder_output_types[type_index].compression; info->bmiHeader.biSizeImage = image_size;
+ IMFMediaType_Release(media_type); return S_OK; }
@@ -487,7 +494,7 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index const DMO_MEDIA_TYPE *type, DWORD flags) { struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - struct wg_format wg_format; + IMFMediaType *media_type; unsigned int i;
TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); @@ -499,7 +506,8 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index { if (flags & DMO_SET_TYPEF_CLEAR) { - memset(&decoder->input_format, 0, sizeof(decoder->input_format)); + FreeMediaType(&decoder->input_type); + memset(&decoder->input_type, 0, sizeof(decoder->input_type)); if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -519,14 +527,16 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index if (i == ARRAY_SIZE(wmv_decoder_input_types)) return DMO_E_TYPE_NOT_ACCEPTED;
- if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) + if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + (void *)type, &media_type))) return DMO_E_TYPE_NOT_ACCEPTED; - assert(wg_format.major_type == WG_MAJOR_TYPE_VIDEO_WMV); + IMFMediaType_Release(media_type);
if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK;
- decoder->input_format = wg_format; + FreeMediaType(&decoder->input_type); + CopyMediaType(&decoder->input_type, type); if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -541,8 +551,9 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde { struct wmv_decoder *decoder = impl_from_IMediaObject(iface); struct wg_transform_attrs attrs = {0}; - struct wg_format wg_format; + IMFMediaType *media_type; unsigned int i; + HRESULT hr;
TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags);
@@ -553,7 +564,8 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde { if (flags & DMO_SET_TYPEF_CLEAR) { - memset(&decoder->output_format, 0, sizeof(decoder->output_format)); + FreeMediaType(&decoder->output_type); + memset(&decoder->output_type, 0, sizeof(decoder->output_type)); if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -564,7 +576,7 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde return E_POINTER; }
- if (!wg_format_is_set(&decoder->input_format)) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET;
if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) @@ -576,15 +588,16 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde if (i == ARRAY_SIZE(wmv_decoder_output_types)) return DMO_E_TYPE_NOT_ACCEPTED;
- if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) + if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + (void *)type, &media_type))) return DMO_E_TYPE_NOT_ACCEPTED; - assert(wg_format.major_type == WG_MAJOR_TYPE_VIDEO); + IMFMediaType_Release(media_type);
if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK;
- decoder->output_subtype = type->subtype; - decoder->output_format = wg_format; + FreeMediaType(&decoder->output_type); + CopyMediaType(&decoder->output_type, type);
/* Set up wg_transform. */ if (decoder->wg_transform) @@ -592,8 +605,9 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde wg_transform_destroy(decoder->wg_transform); decoder->wg_transform = 0; } - if (!(decoder->wg_transform = wg_transform_create(&decoder->input_format, &decoder->output_format, &attrs))) - return E_FAIL; + if (FAILED(hr = wg_transform_create_quartz(&decoder->input_type, type, + &attrs, &decoder->wg_transform))) + return hr;
return S_OK; } @@ -621,22 +635,22 @@ static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD i static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) { struct wmv_decoder *decoder = impl_from_IMediaObject(iface); + IMFMediaType *media_type; HRESULT hr;
TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface, index, size, alignment);
if (index > 0) return DMO_E_INVALIDSTREAMINDEX; - if (!wg_format_is_set(&decoder->output_format)) + if (IsEqualGUID(&decoder->output_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET;
- if (FAILED(hr = MFCalculateImageSize(&decoder->output_subtype, - decoder->output_format.u.video.width, abs(decoder->output_format.u.video.height), (UINT32 *)size))) - { - FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(&decoder->output_subtype)); + if (FAILED(hr = MFCreateMediaType(&media_type))) return hr; - } - *alignment = 1; + if (SUCCEEDED(hr = MFInitMediaTypeFromAMMediaType(media_type, &decoder->output_type)) + && SUCCEEDED(hr = IMFMediaType_GetUINT32(media_type, &MF_MT_SAMPLE_SIZE, (UINT32 *)size))) + *alignment = 1; + IMFMediaType_Release(media_type);
return S_OK; }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_decoder.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index e931880659e..d286b00e2b5 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -64,6 +64,7 @@ struct video_decoder IMFMediaType *stream_type;
wg_transform_t wg_transform; + struct wg_transform_attrs wg_transform_attrs; struct wg_sample_queue *wg_sample_queue;
IMFVideoSampleAllocatorEx *allocator; @@ -84,12 +85,6 @@ static HRESULT try_create_wg_transform(struct video_decoder *decoder) * transform to be able to queue its input buffers. We need to use a buffer list * to match its expectations. */ - struct wg_transform_attrs attrs = - { - .output_plane_align = 15, - .input_queue_length = 15, - .allow_size_change = TRUE, - }; struct wg_format input_format; struct wg_format output_format; UINT32 low_latency; @@ -107,9 +102,9 @@ static HRESULT try_create_wg_transform(struct video_decoder *decoder) return MF_E_INVALIDMEDIATYPE;
if (SUCCEEDED(IMFAttributes_GetUINT32(decoder->attributes, &MF_LOW_LATENCY, &low_latency))) - attrs.low_latency = !!low_latency; + decoder->wg_transform_attrs.low_latency = !!low_latency;
- if (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format, &attrs))) + if (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format, &decoder->wg_transform_attrs))) { ERR("Failed to create transform with input major_type %u.\n", input_format.major_type); return E_FAIL; @@ -907,6 +902,10 @@ HRESULT h264_decoder_create(REFIID riid, void **out) return hr; }
+ decoder->wg_transform_attrs.output_plane_align = 15; + decoder->wg_transform_attrs.input_queue_length = 15; + decoder->wg_transform_attrs.allow_size_change = TRUE; + hr = IMFTransform_QueryInterface(iface, riid, out); IMFTransform_Release(iface); return hr;
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/Makefile.in | 3 +- dlls/winegstreamer/video_decoder.c | 752 ++++++++++++++++++++++- dlls/winegstreamer/wmv_decoder.c | 943 ----------------------------- 3 files changed, 738 insertions(+), 960 deletions(-) delete mode 100644 dlls/winegstreamer/wmv_decoder.c
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 410bbd1dc03..abf3d82d6a8 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -28,5 +28,4 @@ SOURCES = \ wg_transform.c \ winegstreamer_classes.idl \ wm_reader.c \ - wma_decoder.c \ - wmv_decoder.c + wma_decoder.c diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 5b16e36de34..f9467b22ed1 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -24,6 +24,8 @@ #include "mferror.h" #include "mfobjects.h" #include "mftransform.h" +#include "mediaerr.h" +#include "wmcodecdsp.h"
#include "wine/debug.h"
@@ -34,6 +36,35 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DECLARE_DEBUG_CHANNEL(winediag);
+struct subtype_info +{ + const GUID *subtype; + WORD bpp; + DWORD compression; +}; + +static const struct subtype_info subtype_info_list[] = +{ + { &MFVideoFormat_NV12, 12, MAKEFOURCC('N', 'V', '1', '2') }, + { &MFVideoFormat_YV12, 12, MAKEFOURCC('Y', 'V', '1', '2') }, + { &MFVideoFormat_IYUV, 12, MAKEFOURCC('I', 'Y', 'U', 'V') }, + { &MFVideoFormat_I420, 12, MAKEFOURCC('I', '4', '2', '0') }, + { &MFVideoFormat_YUY2, 16, MAKEFOURCC('Y', 'U', 'Y', '2') }, + { &MFVideoFormat_UYVY, 16, MAKEFOURCC('U', 'Y', 'V', 'Y') }, + { &MFVideoFormat_YVYU, 16, MAKEFOURCC('Y', 'V', 'Y', 'U') }, + { &MFVideoFormat_NV11, 12, MAKEFOURCC('N', 'V', '1', '1') }, + { &MFVideoFormat_RGB8, 8, BI_RGB }, + { &MFVideoFormat_RGB555, 16, BI_RGB }, + { &MFVideoFormat_RGB565, 16, BI_BITFIELDS }, + { &MFVideoFormat_RGB24, 24, BI_RGB }, + { &MFVideoFormat_RGB32, 32, BI_RGB }, + { &MEDIASUBTYPE_RGB8, 8, BI_RGB }, + { &MEDIASUBTYPE_RGB555, 16, BI_RGB }, + { &MEDIASUBTYPE_RGB565, 16, BI_BITFIELDS }, + { &MEDIASUBTYPE_RGB24, 24, BI_RGB }, + { &MEDIASUBTYPE_RGB32, 32, BI_RGB }, +}; + static const GUID *const video_decoder_output_types[] = { &MFVideoFormat_NV12, @@ -47,6 +78,9 @@ struct video_decoder { IUnknown IUnknown_inner; IMFTransform IMFTransform_iface; + IMediaObject IMediaObject_iface; + IPropertyBag IPropertyBag_iface; + IPropertyStore IPropertyStore_iface; IUnknown *outer; LONG refcount;
@@ -73,6 +107,9 @@ struct video_decoder BOOL allocator_initialized; IMFTransform *copier; IMFMediaBuffer *temp_buffer; + + DMO_MEDIA_TYPE dmo_input_type; + DMO_MEDIA_TYPE dmo_output_type; };
static inline struct video_decoder *impl_from_IUnknown(IUnknown *iface) @@ -88,8 +125,14 @@ static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void *
if (IsEqualGUID(iid, &IID_IUnknown)) *out = &decoder->IUnknown_inner; - else if (IsEqualGUID(iid, &IID_IMFTransform)) + else if (IsEqualGUID(iid, &IID_IMFTransform) && decoder->IMFTransform_iface.lpVtbl) *out = &decoder->IMFTransform_iface; + else if (IsEqualGUID(iid, &IID_IMediaObject) && decoder->IMediaObject_iface.lpVtbl) + *out = &decoder->IMediaObject_iface; + else if (IsEqualGUID(iid, &IID_IPropertyBag) && decoder->IPropertyBag_iface.lpVtbl) + *out = &decoder->IPropertyBag_iface; + else if (IsEqualGUID(iid, &IID_IPropertyStore) && decoder->IPropertyStore_iface.lpVtbl) + *out = &decoder->IPropertyStore_iface; else { *out = NULL; @@ -148,6 +191,48 @@ static const IUnknownVtbl unknown_vtbl = unknown_Release, };
+static WORD get_subtype_bpp(const GUID *subtype) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(subtype_info_list); ++i) + { + if (IsEqualGUID(subtype, subtype_info_list[i].subtype)) + return subtype_info_list[i].bpp; + } + + return 0; +} + +static DWORD get_subtype_compression(const GUID *subtype) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(subtype_info_list); ++i) + { + if (IsEqualGUID(subtype, subtype_info_list[i].subtype)) + return subtype_info_list[i].compression; + } + + return 0; +} + +static const GUID *get_dmo_subtype(const GUID *subtype) +{ + if (IsEqualGUID(subtype, &MFVideoFormat_RGB8)) + return &MEDIASUBTYPE_RGB8; + else if (IsEqualGUID(subtype, &MFVideoFormat_RGB555)) + return &MEDIASUBTYPE_RGB555; + else if (IsEqualGUID(subtype, &MFVideoFormat_RGB565)) + return &MEDIASUBTYPE_RGB565; + else if (IsEqualGUID(subtype, &MFVideoFormat_RGB24)) + return &MEDIASUBTYPE_RGB24; + else if (IsEqualGUID(subtype, &MFVideoFormat_RGB32)) + return &MEDIASUBTYPE_RGB32; + else + return subtype; +} + static struct video_decoder *impl_from_IMFTransform(IMFTransform *iface) { return CONTAINING_RECORD(iface, struct video_decoder, IMFTransform_iface); @@ -829,8 +914,547 @@ static const IMFTransformVtbl transform_vtbl = transform_ProcessOutput, };
+static inline struct video_decoder *impl_from_IMediaObject(IMediaObject *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IMediaObject_iface); +} + +static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj) +{ + return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj); +} + +static ULONG WINAPI media_object_AddRef(IMediaObject *iface) +{ + return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer); +} + +static ULONG WINAPI media_object_Release(IMediaObject *iface) +{ + return IUnknown_Release(impl_from_IMediaObject(iface)->outer); +} + +static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output) +{ + TRACE("iface %p, input %p, output %p.\n", iface, input, output); + + if (!input || !output) + return E_POINTER; + + *input = *output = 1; + + return S_OK; +} + +static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, + DMO_MEDIA_TYPE *type) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + + TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= decoder->input_type_count) + return DMO_E_NO_MORE_ITEMS; + if (!type) + return S_OK; + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Video; + type->subtype = *get_dmo_subtype(decoder->input_types[type_index]); + type->bFixedSizeSamples = FALSE; + type->bTemporalCompression = TRUE; + type->lSampleSize = 0; + + return S_OK; +} + +static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, + DMO_MEDIA_TYPE *type) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + UINT64 frame_size, frame_rate; + IMFMediaType *media_type; + VIDEOINFOHEADER *info; + const GUID *subtype; + LONG width, height; + UINT32 image_size; + HRESULT hr; + + TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= decoder->output_type_count) + return DMO_E_NO_MORE_ITEMS; + if (!type) + return S_OK; + if (IsEqualGUID(&decoder->dmo_input_type.majortype, &GUID_NULL)) + return DMO_E_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + &decoder->dmo_input_type, &media_type))) + return hr; + + if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size))) + frame_size = 0; + if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_RATE, &frame_rate))) + frame_rate = 0; + + width = frame_size >> 32; + height = (UINT32)frame_size; + subtype = get_dmo_subtype(decoder->output_types[type_index]); + if (FAILED(hr = MFCalculateImageSize(subtype, width, height, &image_size))) + { + FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(subtype)); + IMFMediaType_Release(media_type); + return hr; + } + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Video; + type->subtype = *subtype; + type->bFixedSizeSamples = TRUE; + type->bTemporalCompression = FALSE; + type->lSampleSize = image_size; + type->formattype = FORMAT_VideoInfo; + type->cbFormat = sizeof(VIDEOINFOHEADER); + type->pbFormat = CoTaskMemAlloc(type->cbFormat); + memset(type->pbFormat, 0, type->cbFormat); + + info = (VIDEOINFOHEADER *)type->pbFormat; + info->rcSource.right = width; + info->rcSource.bottom = height; + info->rcTarget.right = width; + info->rcTarget.bottom = height; + if (frame_rate) + MFFrameRateToAverageTimePerFrame(frame_rate >> 32, frame_rate, (UINT64 *)&info->AvgTimePerFrame); + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = height; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = get_subtype_bpp(subtype); + info->bmiHeader.biCompression = get_subtype_compression(subtype); + info->bmiHeader.biSizeImage = image_size; + + IMFMediaType_Release(media_type); + return S_OK; +} + +static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, + const DMO_MEDIA_TYPE *type, DWORD flags) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + IMFMediaType *media_type; + unsigned int i; + + TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + if (!type) + { + if (flags & DMO_SET_TYPEF_CLEAR) + { + FreeMediaType(&decoder->dmo_input_type); + memset(&decoder->dmo_input_type, 0, sizeof(decoder->dmo_input_type)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + return S_OK; + } + return DMO_E_TYPE_NOT_ACCEPTED; + } + + if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) + return DMO_E_TYPE_NOT_ACCEPTED; + + for (i = 0; i < decoder->input_type_count; ++i) + if (IsEqualGUID(&type->subtype, get_dmo_subtype(decoder->input_types[i]))) + break; + if (i == decoder->input_type_count) + return DMO_E_TYPE_NOT_ACCEPTED; + + if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + (void *)type, &media_type))) + return DMO_E_TYPE_NOT_ACCEPTED; + IMFMediaType_Release(media_type); + + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + FreeMediaType(&decoder->dmo_input_type); + CopyMediaType(&decoder->dmo_input_type, type); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + + return S_OK; +} + +static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index, + const DMO_MEDIA_TYPE *type, DWORD flags) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + IMFMediaType *media_type; + unsigned int i; + HRESULT hr; + + TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + if (!type) + { + if (flags & DMO_SET_TYPEF_CLEAR) + { + FreeMediaType(&decoder->dmo_output_type); + memset(&decoder->dmo_output_type, 0, sizeof(decoder->dmo_output_type)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + return S_OK; + } + return E_POINTER; + } + + if (IsEqualGUID(&decoder->dmo_input_type.majortype, &GUID_NULL)) + return DMO_E_TYPE_NOT_SET; + + if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) + return DMO_E_TYPE_NOT_ACCEPTED; + + for (i = 0; i < decoder->output_type_count; ++i) + if (IsEqualGUID(&type->subtype, get_dmo_subtype(decoder->output_types[i]))) + break; + if (i == decoder->output_type_count) + return DMO_E_TYPE_NOT_ACCEPTED; + + if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + (void *)type, &media_type))) + return DMO_E_TYPE_NOT_ACCEPTED; + IMFMediaType_Release(media_type); + + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + FreeMediaType(&decoder->dmo_output_type); + CopyMediaType(&decoder->dmo_output_type, type); + + /* Set up wg_transform. */ + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + if (FAILED(hr = wg_transform_create_quartz(&decoder->dmo_input_type, type, + &decoder->wg_transform_attrs, &decoder->wg_transform))) + return hr; + + return S_OK; +} + +static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, + DWORD *lookahead, DWORD *alignment) +{ + FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size, + lookahead, alignment); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + IMFMediaType *media_type; + HRESULT hr; + + TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface, index, size, alignment); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (IsEqualGUID(&decoder->dmo_output_type.majortype, &GUID_NULL)) + return DMO_E_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaType(&media_type))) + return hr; + if (SUCCEEDED(hr = MFInitMediaTypeFromAMMediaType(media_type, &decoder->dmo_output_type)) + && SUCCEEDED(hr = IMFMediaType_GetUINT32(media_type, &MF_MT_SAMPLE_SIZE, (UINT32 *)size))) + *alignment = 1; + IMFMediaType_Release(media_type); + + return S_OK; +} + +static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency) +{ + FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency) +{ + FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency)); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_Flush(IMediaObject *iface) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + if (FAILED(hr = wg_transform_flush(decoder->wg_transform))) + return hr; + + wg_sample_queue_flush(decoder->wg_sample_queue, TRUE); + + return S_OK; +} + +static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index) +{ + TRACE("iface %p, index %lu.\n", iface, index); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + return S_OK; +} + +static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags) +{ + TRACE("iface %p, index %lu, flags %p.\n", iface, index, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (!flags) + return E_POINTER; + + *flags = DMO_INPUT_STATUSF_ACCEPT_DATA; + + return S_OK; +} + +static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index, + IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + + TRACE("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s.\n", iface, + index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); + + if (!decoder->wg_transform) + return DMO_E_TYPE_NOT_SET; + + return wg_transform_push_dmo(decoder->wg_transform, buffer, flags, timestamp, timelength, decoder->wg_sample_queue); +} + +static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, + DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + HRESULT hr; + + TRACE("iface %p, flags %#lx, count %lu, buffers %p, status %p.\n", iface, flags, count, buffers, status); + + if (!decoder->wg_transform) + return DMO_E_TYPE_NOT_SET; + + if ((hr = wg_transform_read_dmo(decoder->wg_transform, buffers)) == MF_E_TRANSFORM_STREAM_CHANGE) + hr = wg_transform_read_dmo(decoder->wg_transform, buffers); + + if (SUCCEEDED(hr)) + wg_sample_queue_flush(decoder->wg_sample_queue, false); + + return hr; +} + +static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock) +{ + FIXME("iface %p, lock %ld stub!\n", iface, lock); + return E_NOTIMPL; +} + +static const IMediaObjectVtbl media_object_vtbl = +{ + media_object_QueryInterface, + media_object_AddRef, + media_object_Release, + media_object_GetStreamCount, + media_object_GetInputStreamInfo, + media_object_GetOutputStreamInfo, + media_object_GetInputType, + media_object_GetOutputType, + media_object_SetInputType, + media_object_SetOutputType, + media_object_GetInputCurrentType, + media_object_GetOutputCurrentType, + media_object_GetInputSizeInfo, + media_object_GetOutputSizeInfo, + media_object_GetInputMaxLatency, + media_object_SetInputMaxLatency, + media_object_Flush, + media_object_Discontinuity, + media_object_AllocateStreamingResources, + media_object_FreeStreamingResources, + media_object_GetInputStatus, + media_object_ProcessInput, + media_object_ProcessOutput, + media_object_Lock, +}; + +static inline struct video_decoder *impl_from_IPropertyBag(IPropertyBag *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IPropertyBag_iface); +} + +static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out); +} + +static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface) +{ + return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer); +} + +static ULONG WINAPI property_bag_Release(IPropertyBag *iface) +{ + return IUnknown_Release(impl_from_IPropertyBag(iface)->outer); +} + +static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value, + IErrorLog *error_log) +{ + FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value) +{ + FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value); + return S_OK; +} + +static const IPropertyBagVtbl property_bag_vtbl = +{ + property_bag_QueryInterface, + property_bag_AddRef, + property_bag_Release, + property_bag_Read, + property_bag_Write, +}; + +static inline struct video_decoder *impl_from_IPropertyStore(IPropertyStore *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IPropertyStore_iface); +} + +static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out); +} + +static ULONG WINAPI property_store_AddRef(IPropertyStore *iface) +{ + return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer); +} + +static ULONG WINAPI property_store_Release(IPropertyStore *iface) +{ + return IUnknown_Release(impl_from_IPropertyStore(iface)->outer); +} + +static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count) +{ + FIXME("iface %p, count %p stub!\n", iface, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key) +{ + FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value) +{ + FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value) +{ + FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_Commit(IPropertyStore *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static const IPropertyStoreVtbl property_store_vtbl = +{ + property_store_QueryInterface, + property_store_AddRef, + property_store_Release, + property_store_GetCount, + property_store_GetAt, + property_store_GetValue, + property_store_SetValue, + property_store_Commit, +}; + static HRESULT video_decoder_create_with_types(const GUID *const *input_types, UINT input_type_count, - const GUID *const *output_types, UINT output_type_count, IUnknown *outer, IMFTransform **ret) + const GUID *const *output_types, UINT output_type_count, IUnknown *outer, struct video_decoder **out) { struct video_decoder *decoder; HRESULT hr; @@ -839,7 +1463,6 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U return E_OUTOFMEMORY;
decoder->IUnknown_inner.lpVtbl = &unknown_vtbl; - decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; decoder->refcount = 1; decoder->outer = outer ? outer : &decoder->IUnknown_inner;
@@ -861,8 +1484,8 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U if (FAILED(hr = MFCreateSampleCopierMFT(&decoder->copier))) goto failed;
- *ret = &decoder->IMFTransform_iface; - TRACE("Created decoder %p\n", *ret); + *out = decoder; + TRACE("Created decoder %p\n", decoder); return S_OK;
failed: @@ -902,7 +1525,6 @@ HRESULT h264_decoder_create(REFIID riid, void **out) struct wg_transform_attrs attrs = {0}; struct video_decoder *decoder; wg_transform_t transform; - IMFTransform *iface; HRESULT hr;
TRACE("riid %s, out %p.\n", debugstr_guid(riid), out); @@ -915,9 +1537,10 @@ HRESULT h264_decoder_create(REFIID riid, void **out) wg_transform_destroy(transform);
if (FAILED(hr = video_decoder_create_with_types(h264_decoder_input_types, ARRAY_SIZE(h264_decoder_input_types), - video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), NULL, &iface))) + video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), NULL, &decoder))) return hr; - decoder = impl_from_IMFTransform(iface); + + decoder->IMFTransform_iface.lpVtbl = &transform_vtbl;
decoder->input_info.dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE; @@ -927,10 +1550,10 @@ HRESULT h264_decoder_create(REFIID riid, void **out) decoder->output_info.cbSize = 1920 * 1088 * 2;
if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_LOW_LATENCY, 0)) - || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D11_AWARE, TRUE)) - || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &AVDecVideoAcceleration_H264, TRUE))) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D11_AWARE, TRUE)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &AVDecVideoAcceleration_H264, TRUE))) { - IMFTransform_Release(iface); + IMFTransform_Release(&decoder->IMFTransform_iface); return hr; }
@@ -938,8 +1561,10 @@ HRESULT h264_decoder_create(REFIID riid, void **out) decoder->wg_transform_attrs.input_queue_length = 15; decoder->wg_transform_attrs.allow_size_change = TRUE;
- hr = IMFTransform_QueryInterface(iface, riid, out); - IMFTransform_Release(iface); + TRACE("Created h264 transform %p.\n", &decoder->IMFTransform_iface); + + hr = IMFTransform_QueryInterface(&decoder->IMFTransform_iface, riid, out); + IMFTransform_Release(&decoder->IMFTransform_iface); return hr; }
@@ -963,11 +1588,108 @@ static const GUID *const iv50_decoder_output_types[] =
HRESULT WINAPI winegstreamer_create_video_decoder(IMFTransform **out) { + struct video_decoder *decoder; + HRESULT hr; + TRACE("out %p.\n", out);
if (!init_gstreamer()) return E_FAIL;
- return video_decoder_create_with_types(iv50_decoder_input_types, ARRAY_SIZE(iv50_decoder_input_types), - iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), NULL, out); + if (FAILED(hr = video_decoder_create_with_types(iv50_decoder_input_types, ARRAY_SIZE(iv50_decoder_input_types), + iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), NULL, &decoder))) + return hr; + + decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; + + TRACE("Created iv50 transform %p.\n", &decoder->IMFTransform_iface); + + *out = &decoder->IMFTransform_iface; + return S_OK; +} + +extern const GUID MEDIASUBTYPE_VC1S; +DEFINE_GUID(MEDIASUBTYPE_WMV_Unknown, 0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b); +static const GUID *const wmv_decoder_input_types[] = +{ + &MEDIASUBTYPE_WMV1, + &MEDIASUBTYPE_WMV2, + &MEDIASUBTYPE_WMVA, + &MEDIASUBTYPE_WMVP, + &MEDIASUBTYPE_WVP2, + &MEDIASUBTYPE_WMV_Unknown, + &MEDIASUBTYPE_WVC1, + &MEDIASUBTYPE_WMV3, + &MEDIASUBTYPE_VC1S, +}; +static const GUID *const wmv_decoder_output_types[] = +{ + &MFVideoFormat_NV12, + &MFVideoFormat_YV12, + &MFVideoFormat_IYUV, + &MFVideoFormat_I420, + &MFVideoFormat_YUY2, + &MFVideoFormat_UYVY, + &MFVideoFormat_YVYU, + &MFVideoFormat_NV11, + &MFVideoFormat_RGB32, + &MFVideoFormat_RGB24, + &MFVideoFormat_RGB565, + &MFVideoFormat_RGB555, + &MFVideoFormat_RGB8, +}; + +HRESULT wmv_decoder_create(IUnknown *outer, IUnknown **out) +{ + static const struct wg_format input_format = + { + .major_type = WG_MAJOR_TYPE_VIDEO_WMV, + .u.video.format = WG_VIDEO_FORMAT_WMV3, + }; + static const struct wg_format output_format = + { + .major_type = WG_MAJOR_TYPE_VIDEO, + .u.video = + { + .format = WG_VIDEO_FORMAT_NV12, + .width = 1920, + .height = 1080, + }, + }; + struct wg_transform_attrs attrs = {0}; + struct video_decoder *decoder; + wg_transform_t transform; + HRESULT hr; + + TRACE("outer %p, out %p.\n", outer, out); + + if (!(transform = wg_transform_create(&input_format, &output_format, &attrs))) + { + ERR_(winediag)("GStreamer doesn't support WMV decoding, please install appropriate plugins.\n"); + return E_FAIL; + } + wg_transform_destroy(transform); + + if (FAILED(hr = video_decoder_create_with_types(wmv_decoder_input_types, ARRAY_SIZE(wmv_decoder_input_types), + wmv_decoder_output_types, ARRAY_SIZE(wmv_decoder_output_types), outer, &decoder))) + return hr; + + decoder->IMediaObject_iface.lpVtbl = &media_object_vtbl; + decoder->IPropertyBag_iface.lpVtbl = &property_bag_vtbl; + decoder->IPropertyStore_iface.lpVtbl = &property_store_vtbl; + + if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_LOW_LATENCY, 0)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D11_AWARE, TRUE)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D_AWARE, TRUE)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, + &MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, FALSE))) + { + IMFTransform_Release(&decoder->IMFTransform_iface); + return hr; + } + + TRACE("Created wmv media object %p.\n", &decoder->IMediaObject_iface); + + *out = &decoder->IUnknown_inner; + return S_OK; } diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c deleted file mode 100644 index e63448427b8..00000000000 --- a/dlls/winegstreamer/wmv_decoder.c +++ /dev/null @@ -1,943 +0,0 @@ -/* Copyright 2022 Rémi Bernon for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "gst_private.h" - -#include "mfapi.h" -#include "mferror.h" -#include "mediaerr.h" -#include "mfobjects.h" -#include "mftransform.h" -#include "wmcodecdsp.h" -#include "initguid.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(mfplat); -WINE_DECLARE_DEBUG_CHANNEL(winediag); - -extern const GUID MEDIASUBTYPE_VC1S; - -DEFINE_GUID(MEDIASUBTYPE_WMV_Unknown, 0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b); - -struct decoder_type -{ - const GUID *subtype; - WORD bpp; - DWORD compression; -}; - -static const GUID *const wmv_decoder_input_types[] = -{ - &MEDIASUBTYPE_WMV1, - &MEDIASUBTYPE_WMV2, - &MEDIASUBTYPE_WMVA, - &MEDIASUBTYPE_WMVP, - &MEDIASUBTYPE_WVP2, - &MEDIASUBTYPE_WMV_Unknown, - &MEDIASUBTYPE_WVC1, - &MEDIASUBTYPE_WMV3, - &MEDIASUBTYPE_VC1S, -}; - -static const struct decoder_type wmv_decoder_output_types[] = -{ - { &MEDIASUBTYPE_NV12, 12, MAKEFOURCC('N', 'V', '1', '2') }, - { &MEDIASUBTYPE_YV12, 12, MAKEFOURCC('Y', 'V', '1', '2') }, - { &MEDIASUBTYPE_IYUV, 12, MAKEFOURCC('I', 'Y', 'U', 'V') }, - { &MEDIASUBTYPE_I420, 12, MAKEFOURCC('I', '4', '2', '0') }, - { &MEDIASUBTYPE_YUY2, 16, MAKEFOURCC('Y', 'U', 'Y', '2') }, - { &MEDIASUBTYPE_UYVY, 16, MAKEFOURCC('U', 'Y', 'V', 'Y') }, - { &MEDIASUBTYPE_YVYU, 16, MAKEFOURCC('Y', 'V', 'Y', 'U') }, - { &MEDIASUBTYPE_NV11, 12, MAKEFOURCC('N', 'V', '1', '1') }, - { &MEDIASUBTYPE_RGB32, 32, BI_RGB }, - { &MEDIASUBTYPE_RGB24, 24, BI_RGB }, - { &MEDIASUBTYPE_RGB565, 16, BI_BITFIELDS }, - { &MEDIASUBTYPE_RGB555, 16, BI_RGB }, - { &MEDIASUBTYPE_RGB8, 8, BI_RGB }, -}; - -struct wmv_decoder -{ - IUnknown IUnknown_inner; - IMFTransform IMFTransform_iface; - IMediaObject IMediaObject_iface; - IPropertyBag IPropertyBag_iface; - IPropertyStore IPropertyStore_iface; - IUnknown *outer; - LONG refcount; - - DMO_MEDIA_TYPE input_type; - DMO_MEDIA_TYPE output_type; - - wg_transform_t wg_transform; - struct wg_sample_queue *wg_sample_queue; -}; - -static inline struct wmv_decoder *impl_from_IUnknown(IUnknown *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IUnknown_inner); -} - -static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) -{ - struct wmv_decoder *impl = impl_from_IUnknown(iface); - - TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); - - if (IsEqualGUID(iid, &IID_IUnknown)) - *out = &impl->IUnknown_inner; - else if (IsEqualGUID(iid, &IID_IMFTransform)) - *out = &impl->IMFTransform_iface; - else if (IsEqualGUID(iid, &IID_IMediaObject)) - *out = &impl->IMediaObject_iface; - else if (IsEqualIID(iid, &IID_IPropertyBag)) - *out = &impl->IPropertyBag_iface; - else if (IsEqualIID(iid, &IID_IPropertyStore)) - *out = &impl->IPropertyStore_iface; - else - { - *out = NULL; - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)*out); - return S_OK; -} - -static ULONG WINAPI unknown_AddRef(IUnknown *iface) -{ - struct wmv_decoder *impl = impl_from_IUnknown(iface); - ULONG refcount = InterlockedIncrement(&impl->refcount); - - TRACE("iface %p increasing refcount to %lu.\n", iface, refcount); - - return refcount; -} - -static ULONG WINAPI unknown_Release(IUnknown *iface) -{ - struct wmv_decoder *impl = impl_from_IUnknown(iface); - ULONG refcount = InterlockedDecrement(&impl->refcount); - - TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount); - - if (!refcount) - { - if (impl->wg_transform) - wg_transform_destroy(impl->wg_transform); - wg_sample_queue_destroy(impl->wg_sample_queue); - free(impl); - } - - return refcount; -} - -static const IUnknownVtbl unknown_vtbl = -{ - unknown_QueryInterface, - unknown_AddRef, - unknown_Release, -}; - -static struct wmv_decoder *impl_from_IMFTransform(IMFTransform *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IMFTransform_iface); -} - -static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) -{ - return IUnknown_QueryInterface(impl_from_IMFTransform(iface)->outer, iid, out); -} - -static ULONG WINAPI transform_AddRef(IMFTransform *iface) -{ - return IUnknown_AddRef(impl_from_IMFTransform(iface)->outer); -} - -static ULONG WINAPI transform_Release(IMFTransform *iface) -{ - return IUnknown_Release(impl_from_IMFTransform(iface)->outer); -} - -static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, - DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) -{ - TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n", - iface, input_minimum, input_maximum, output_minimum, output_maximum); - *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; - return S_OK; -} - -static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) -{ - TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs); - *inputs = *outputs = 1; - return S_OK; -} - -static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, - DWORD output_size, DWORD *outputs) -{ - TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface, - input_size, inputs, output_size, outputs); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) -{ - FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) -{ - FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) -{ - FIXME("iface %p, attributes %p stub!\n", iface, attributes); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) -{ - TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) -{ - FIXME("iface %p, id %#lx, attributes %p stub!\n", iface, id, attributes); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id) -{ - TRACE("iface %p, id %#lx.\n", iface, id); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) -{ - TRACE("iface %p, streams %lu, ids %p.\n", iface, streams, ids); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, - IMFMediaType **type) -{ - FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface, id, index, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, - IMFMediaType **type) -{ - FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface, id, index, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) -{ - FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) -{ - FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) -{ - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) -{ - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) -{ - FIXME("iface %p, id %#lx, flags %p stub!\n", iface, id, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags) -{ - FIXME("iface %p, flags %p stub!\n", iface, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) -{ - TRACE("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) -{ - FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) -{ - FIXME("iface %p, message %#x, param %#Ix stub!\n", iface, message, param); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) -{ - FIXME("iface %p, id %#lx, sample %p, flags %#lx stub!\n", iface, id, sample, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, - MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) -{ - FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status); - return E_NOTIMPL; -} - -static const IMFTransformVtbl transform_vtbl = -{ - transform_QueryInterface, - transform_AddRef, - transform_Release, - transform_GetStreamLimits, - transform_GetStreamCount, - transform_GetStreamIDs, - transform_GetInputStreamInfo, - transform_GetOutputStreamInfo, - transform_GetAttributes, - transform_GetInputStreamAttributes, - transform_GetOutputStreamAttributes, - transform_DeleteInputStream, - transform_AddInputStreams, - transform_GetInputAvailableType, - transform_GetOutputAvailableType, - transform_SetInputType, - transform_SetOutputType, - transform_GetInputCurrentType, - transform_GetOutputCurrentType, - transform_GetInputStatus, - transform_GetOutputStatus, - transform_SetOutputBounds, - transform_ProcessEvent, - transform_ProcessMessage, - transform_ProcessInput, - transform_ProcessOutput, -}; - -static inline struct wmv_decoder *impl_from_IMediaObject(IMediaObject *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IMediaObject_iface); -} - -static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj) -{ - return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj); -} - -static ULONG WINAPI media_object_AddRef(IMediaObject *iface) -{ - return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer); -} - -static ULONG WINAPI media_object_Release(IMediaObject *iface) -{ - return IUnknown_Release(impl_from_IMediaObject(iface)->outer); -} - -static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output) -{ - TRACE("iface %p, input %p, output %p.\n", iface, input, output); - - if (!input || !output) - return E_POINTER; - - *input = *output = 1; - - return S_OK; -} - -static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) -{ - FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) -{ - FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, - DMO_MEDIA_TYPE *type) -{ - TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - if (type_index >= ARRAY_SIZE(wmv_decoder_input_types)) - return DMO_E_NO_MORE_ITEMS; - if (!type) - return S_OK; - - memset(type, 0, sizeof(*type)); - type->majortype = MFMediaType_Video; - type->subtype = *wmv_decoder_input_types[type_index]; - type->bFixedSizeSamples = FALSE; - type->bTemporalCompression = TRUE; - type->lSampleSize = 0; - - return S_OK; -} - -static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, - DMO_MEDIA_TYPE *type) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - UINT64 frame_size, frame_rate; - IMFMediaType *media_type; - VIDEOINFOHEADER *info; - const GUID *subtype; - LONG width, height; - UINT32 image_size; - HRESULT hr; - - TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - if (type_index >= ARRAY_SIZE(wmv_decoder_output_types)) - return DMO_E_NO_MORE_ITEMS; - if (!type) - return S_OK; - if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) - return DMO_E_TYPE_NOT_SET; - - if (FAILED(hr = MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, - &decoder->input_type, &media_type))) - return hr; - - if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size))) - frame_size = 0; - if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_RATE, &frame_rate))) - frame_rate = 0; - - width = frame_size >> 32; - height = (UINT32)frame_size; - subtype = wmv_decoder_output_types[type_index].subtype; - if (FAILED(hr = MFCalculateImageSize(subtype, width, height, &image_size))) - { - FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(subtype)); - IMFMediaType_Release(media_type); - return hr; - } - - memset(type, 0, sizeof(*type)); - type->majortype = MFMediaType_Video; - type->subtype = *subtype; - type->bFixedSizeSamples = TRUE; - type->bTemporalCompression = FALSE; - type->lSampleSize = image_size; - type->formattype = FORMAT_VideoInfo; - type->cbFormat = sizeof(VIDEOINFOHEADER); - type->pbFormat = CoTaskMemAlloc(type->cbFormat); - memset(type->pbFormat, 0, type->cbFormat); - - info = (VIDEOINFOHEADER *)type->pbFormat; - info->rcSource.right = width; - info->rcSource.bottom = height; - info->rcTarget.right = width; - info->rcTarget.bottom = height; - if (frame_rate) - MFFrameRateToAverageTimePerFrame(frame_rate >> 32, frame_rate, (UINT64 *)&info->AvgTimePerFrame); - info->bmiHeader.biSize = sizeof(info->bmiHeader); - info->bmiHeader.biWidth = width; - info->bmiHeader.biHeight = height; - info->bmiHeader.biPlanes = 1; - info->bmiHeader.biBitCount = wmv_decoder_output_types[type_index].bpp; - info->bmiHeader.biCompression = wmv_decoder_output_types[type_index].compression; - info->bmiHeader.biSizeImage = image_size; - - IMFMediaType_Release(media_type); - return S_OK; -} - -static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, - const DMO_MEDIA_TYPE *type, DWORD flags) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - IMFMediaType *media_type; - unsigned int i; - - TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - - if (!type) - { - if (flags & DMO_SET_TYPEF_CLEAR) - { - FreeMediaType(&decoder->input_type); - memset(&decoder->input_type, 0, sizeof(decoder->input_type)); - if (decoder->wg_transform) - { - wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - } - return S_OK; - } - return DMO_E_TYPE_NOT_ACCEPTED; - } - - if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) - return DMO_E_TYPE_NOT_ACCEPTED; - - for (i = 0; i < ARRAY_SIZE(wmv_decoder_input_types); ++i) - if (IsEqualGUID(&type->subtype, wmv_decoder_input_types[i])) - break; - if (i == ARRAY_SIZE(wmv_decoder_input_types)) - return DMO_E_TYPE_NOT_ACCEPTED; - - if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, - (void *)type, &media_type))) - return DMO_E_TYPE_NOT_ACCEPTED; - IMFMediaType_Release(media_type); - - if (flags & DMO_SET_TYPEF_TEST_ONLY) - return S_OK; - - FreeMediaType(&decoder->input_type); - CopyMediaType(&decoder->input_type, type); - if (decoder->wg_transform) - { - wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - } - - return S_OK; -} - -static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index, - const DMO_MEDIA_TYPE *type, DWORD flags) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - struct wg_transform_attrs attrs = {0}; - IMFMediaType *media_type; - unsigned int i; - HRESULT hr; - - TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - - if (!type) - { - if (flags & DMO_SET_TYPEF_CLEAR) - { - FreeMediaType(&decoder->output_type); - memset(&decoder->output_type, 0, sizeof(decoder->output_type)); - if (decoder->wg_transform) - { - wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - } - return S_OK; - } - return E_POINTER; - } - - if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) - return DMO_E_TYPE_NOT_SET; - - if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) - return DMO_E_TYPE_NOT_ACCEPTED; - - for (i = 0; i < ARRAY_SIZE(wmv_decoder_output_types); ++i) - if (IsEqualGUID(&type->subtype, wmv_decoder_output_types[i].subtype)) - break; - if (i == ARRAY_SIZE(wmv_decoder_output_types)) - return DMO_E_TYPE_NOT_ACCEPTED; - - if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, - (void *)type, &media_type))) - return DMO_E_TYPE_NOT_ACCEPTED; - IMFMediaType_Release(media_type); - - if (flags & DMO_SET_TYPEF_TEST_ONLY) - return S_OK; - - FreeMediaType(&decoder->output_type); - CopyMediaType(&decoder->output_type, type); - - /* Set up wg_transform. */ - if (decoder->wg_transform) - { - wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - } - if (FAILED(hr = wg_transform_create_quartz(&decoder->input_type, type, - &attrs, &decoder->wg_transform))) - return hr; - - return S_OK; -} - -static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) -{ - FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) -{ - FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, - DWORD *lookahead, DWORD *alignment) -{ - FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size, - lookahead, alignment); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - IMFMediaType *media_type; - HRESULT hr; - - TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface, index, size, alignment); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - if (IsEqualGUID(&decoder->output_type.majortype, &GUID_NULL)) - return DMO_E_TYPE_NOT_SET; - - if (FAILED(hr = MFCreateMediaType(&media_type))) - return hr; - if (SUCCEEDED(hr = MFInitMediaTypeFromAMMediaType(media_type, &decoder->output_type)) - && SUCCEEDED(hr = IMFMediaType_GetUINT32(media_type, &MF_MT_SAMPLE_SIZE, (UINT32 *)size))) - *alignment = 1; - IMFMediaType_Release(media_type); - - return S_OK; -} - -static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency) -{ - FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency) -{ - FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency)); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_Flush(IMediaObject *iface) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - HRESULT hr; - - TRACE("iface %p.\n", iface); - - if (FAILED(hr = wg_transform_flush(decoder->wg_transform))) - return hr; - - wg_sample_queue_flush(decoder->wg_sample_queue, TRUE); - - return S_OK; -} - -static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index) -{ - TRACE("iface %p, index %lu.\n", iface, index); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - - return S_OK; -} - -static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface) -{ - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface) -{ - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags) -{ - TRACE("iface %p, index %lu, flags %p.\n", iface, index, flags); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - if (!flags) - return E_POINTER; - - *flags = DMO_INPUT_STATUSF_ACCEPT_DATA; - - return S_OK; -} - -static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index, - IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - - TRACE("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s.\n", iface, - index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); - - if (!decoder->wg_transform) - return DMO_E_TYPE_NOT_SET; - - return wg_transform_push_dmo(decoder->wg_transform, buffer, flags, timestamp, timelength, decoder->wg_sample_queue); -} - -static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, - DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - HRESULT hr; - - TRACE("iface %p, flags %#lx, count %lu, buffers %p, status %p.\n", iface, flags, count, buffers, status); - - if (!decoder->wg_transform) - return DMO_E_TYPE_NOT_SET; - - if ((hr = wg_transform_read_dmo(decoder->wg_transform, buffers)) == MF_E_TRANSFORM_STREAM_CHANGE) - hr = wg_transform_read_dmo(decoder->wg_transform, buffers); - - if (SUCCEEDED(hr)) - wg_sample_queue_flush(decoder->wg_sample_queue, false); - - return hr; -} - -static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock) -{ - FIXME("iface %p, lock %ld stub!\n", iface, lock); - return E_NOTIMPL; -} - -static const IMediaObjectVtbl media_object_vtbl = -{ - media_object_QueryInterface, - media_object_AddRef, - media_object_Release, - media_object_GetStreamCount, - media_object_GetInputStreamInfo, - media_object_GetOutputStreamInfo, - media_object_GetInputType, - media_object_GetOutputType, - media_object_SetInputType, - media_object_SetOutputType, - media_object_GetInputCurrentType, - media_object_GetOutputCurrentType, - media_object_GetInputSizeInfo, - media_object_GetOutputSizeInfo, - media_object_GetInputMaxLatency, - media_object_SetInputMaxLatency, - media_object_Flush, - media_object_Discontinuity, - media_object_AllocateStreamingResources, - media_object_FreeStreamingResources, - media_object_GetInputStatus, - media_object_ProcessInput, - media_object_ProcessOutput, - media_object_Lock, -}; - -static inline struct wmv_decoder *impl_from_IPropertyBag(IPropertyBag *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IPropertyBag_iface); -} - -static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out) -{ - return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out); -} - -static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface) -{ - return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer); -} - -static ULONG WINAPI property_bag_Release(IPropertyBag *iface) -{ - return IUnknown_Release(impl_from_IPropertyBag(iface)->outer); -} - -static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value, - IErrorLog *error_log) -{ - FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value) -{ - FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value); - return S_OK; -} - -static const IPropertyBagVtbl property_bag_vtbl = -{ - property_bag_QueryInterface, - property_bag_AddRef, - property_bag_Release, - property_bag_Read, - property_bag_Write, -}; - -static inline struct wmv_decoder *impl_from_IPropertyStore(IPropertyStore *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IPropertyStore_iface); -} - -static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out) -{ - return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out); -} - -static ULONG WINAPI property_store_AddRef(IPropertyStore *iface) -{ - return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer); -} - -static ULONG WINAPI property_store_Release(IPropertyStore *iface) -{ - return IUnknown_Release(impl_from_IPropertyStore(iface)->outer); -} - -static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count) -{ - FIXME("iface %p, count %p stub!\n", iface, count); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key) -{ - FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value) -{ - FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value) -{ - FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_store_Commit(IPropertyStore *iface) -{ - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; -} - -static const IPropertyStoreVtbl property_store_vtbl = -{ - property_store_QueryInterface, - property_store_AddRef, - property_store_Release, - property_store_GetCount, - property_store_GetAt, - property_store_GetValue, - property_store_SetValue, - property_store_Commit, -}; - -HRESULT wmv_decoder_create(IUnknown *outer, IUnknown **out) -{ - static const struct wg_format input_format = - { - .major_type = WG_MAJOR_TYPE_VIDEO_WMV, - .u.video.format = WG_VIDEO_FORMAT_WMV3, - }; - static const struct wg_format output_format = - { - .major_type = WG_MAJOR_TYPE_VIDEO, - .u.video = - { - .format = WG_VIDEO_FORMAT_NV12, - .width = 1920, - .height = 1080, - }, - }; - struct wg_transform_attrs attrs = {0}; - wg_transform_t transform; - struct wmv_decoder *decoder; - HRESULT hr; - - TRACE("outer %p, out %p.\n", outer, out); - - if (!(transform = wg_transform_create(&input_format, &output_format, &attrs))) - { - ERR_(winediag)("GStreamer doesn't support WMV decoding, please install appropriate plugins.\n"); - return E_FAIL; - } - wg_transform_destroy(transform); - - if (!(decoder = calloc(1, sizeof(*decoder)))) - return E_OUTOFMEMORY; - if (FAILED(hr = wg_sample_queue_create(&decoder->wg_sample_queue))) - { - free(decoder); - return hr; - } - - decoder->IUnknown_inner.lpVtbl = &unknown_vtbl; - decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; - decoder->IMediaObject_iface.lpVtbl = &media_object_vtbl; - decoder->IPropertyBag_iface.lpVtbl = &property_bag_vtbl; - decoder->IPropertyStore_iface.lpVtbl = &property_store_vtbl; - decoder->refcount = 1; - decoder->outer = outer ? outer : &decoder->IUnknown_inner; - - *out = &decoder->IUnknown_inner; - TRACE("Created %p\n", *out); - return S_OK; -}
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_decoder.c | 134 ++++++++++++++++++----------- 1 file changed, 83 insertions(+), 51 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index d286b00e2b5..5b16e36de34 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -45,7 +45,9 @@ static const GUID *const video_decoder_output_types[] =
struct video_decoder { + IUnknown IUnknown_inner; IMFTransform IMFTransform_iface; + IUnknown *outer; LONG refcount;
IMFAttributes *attributes; @@ -73,6 +75,79 @@ struct video_decoder IMFMediaBuffer *temp_buffer; };
+static inline struct video_decoder *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IUnknown_inner); +} + +static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown)) + *out = &decoder->IUnknown_inner; + else if (IsEqualGUID(iid, &IID_IMFTransform)) + *out = &decoder->IMFTransform_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI unknown_AddRef(IUnknown *iface) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&decoder->refcount); + + TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); + + return refcount; +} + +static ULONG WINAPI unknown_Release(IUnknown *iface) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&decoder->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); + + if (!refcount) + { + IMFTransform_Release(decoder->copier); + IMFVideoSampleAllocatorEx_Release(decoder->allocator); + if (decoder->temp_buffer) + IMFMediaBuffer_Release(decoder->temp_buffer); + if (decoder->wg_transform) + wg_transform_destroy(decoder->wg_transform); + if (decoder->input_type) + IMFMediaType_Release(decoder->input_type); + if (decoder->output_type) + IMFMediaType_Release(decoder->output_type); + if (decoder->output_attributes) + IMFAttributes_Release(decoder->output_attributes); + if (decoder->attributes) + IMFAttributes_Release(decoder->attributes); + wg_sample_queue_destroy(decoder->wg_sample_queue); + free(decoder); + } + + return refcount; +} + +static const IUnknownVtbl unknown_vtbl = +{ + unknown_QueryInterface, + unknown_AddRef, + unknown_Release, +}; + static struct video_decoder *impl_from_IMFTransform(IMFTransform *iface) { return CONTAINING_RECORD(iface, struct video_decoder, IMFTransform_iface); @@ -220,62 +295,17 @@ static void uninit_allocator(struct video_decoder *decoder)
static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - - TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); - - if (IsEqualGUID(iid, &IID_IUnknown) || - IsEqualGUID(iid, &IID_IMFTransform)) - *out = &decoder->IMFTransform_iface; - else - { - *out = NULL; - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)*out); - return S_OK; + return IUnknown_QueryInterface(impl_from_IMFTransform(iface)->outer, iid, out); }
static ULONG WINAPI transform_AddRef(IMFTransform *iface) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - ULONG refcount = InterlockedIncrement(&decoder->refcount); - - TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); - - return refcount; + return IUnknown_AddRef(impl_from_IMFTransform(iface)->outer); }
static ULONG WINAPI transform_Release(IMFTransform *iface) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - ULONG refcount = InterlockedDecrement(&decoder->refcount); - - TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); - - if (!refcount) - { - IMFTransform_Release(decoder->copier); - IMFVideoSampleAllocatorEx_Release(decoder->allocator); - if (decoder->temp_buffer) - IMFMediaBuffer_Release(decoder->temp_buffer); - if (decoder->wg_transform) - wg_transform_destroy(decoder->wg_transform); - if (decoder->input_type) - IMFMediaType_Release(decoder->input_type); - if (decoder->output_type) - IMFMediaType_Release(decoder->output_type); - if (decoder->output_attributes) - IMFAttributes_Release(decoder->output_attributes); - if (decoder->attributes) - IMFAttributes_Release(decoder->attributes); - wg_sample_queue_destroy(decoder->wg_sample_queue); - free(decoder); - } - - return refcount; + return IUnknown_Release(impl_from_IMFTransform(iface)->outer); }
static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, @@ -800,7 +830,7 @@ static const IMFTransformVtbl transform_vtbl = };
static HRESULT video_decoder_create_with_types(const GUID *const *input_types, UINT input_type_count, - const GUID *const *output_types, UINT output_type_count, IMFTransform **ret) + const GUID *const *output_types, UINT output_type_count, IUnknown *outer, IMFTransform **ret) { struct video_decoder *decoder; HRESULT hr; @@ -808,8 +838,10 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U if (!(decoder = calloc(1, sizeof(*decoder)))) return E_OUTOFMEMORY;
+ decoder->IUnknown_inner.lpVtbl = &unknown_vtbl; decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; decoder->refcount = 1; + decoder->outer = outer ? outer : &decoder->IUnknown_inner;
decoder->input_type_count = input_type_count; decoder->input_types = input_types; @@ -883,7 +915,7 @@ HRESULT h264_decoder_create(REFIID riid, void **out) wg_transform_destroy(transform);
if (FAILED(hr = video_decoder_create_with_types(h264_decoder_input_types, ARRAY_SIZE(h264_decoder_input_types), - video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), &iface))) + video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), NULL, &iface))) return hr; decoder = impl_from_IMFTransform(iface);
@@ -937,5 +969,5 @@ HRESULT WINAPI winegstreamer_create_video_decoder(IMFTransform **out) return E_FAIL;
return video_decoder_create_with_types(iv50_decoder_input_types, ARRAY_SIZE(iv50_decoder_input_types), - iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), out); + iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), NULL, out); }
The WMV decoder also exposes `MF_LOW_LATENCY` and `MF_SA_D3D11_AWARE`, and I think we could also make the H264 decoder expose `MF_SA_D3D_AWARE` as well.
Moving only codec-specific attributes out: `AVDecVideoAcceleration_H264` here, and later keeping `MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER` wmv specific, would be better IMO.
Making the transform interface optional defeats the purpose of merging the two files, this should implement the IMFTransform interface for the WMV decoder as well.
The WMV decoder MF transform also aligns buffers the same way as the H264 decoder, so the output plane alignment could be kept. The input queue length attribute also could probably be kept.
I'm not sure if it supports frame size changes, that would require some tests with concatenated streams like we have for H264, although I think it's probably safe to keep it as default.