[PATCH 1/4] winegstreamer: Implement IWMReaderAdvanced::GetMaxStreamSampleSize().
Zebediah Figura
zfigura at codeweavers.com
Thu Nov 11 23:43:21 CST 2021
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
dlls/winegstreamer/gst_private.h | 3 +
dlls/winegstreamer/quartz_parser.c | 113 ++++++++++++++++++++--------
dlls/winegstreamer/wm_asyncreader.c | 11 ++-
dlls/winegstreamer/wm_reader.c | 18 +++++
dlls/wmvcore/tests/wmvcore.c | 18 ++++-
5 files changed, 127 insertions(+), 36 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index e0f8bdae4a6..9e1d67417d4 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -96,6 +96,8 @@ uint64_t wg_parser_stream_get_duration(struct wg_parser_stream *stream) DECLSPEC
void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
uint64_t start_pos, uint64_t stop_pos, DWORD start_flags, DWORD stop_flags) DECLSPEC_HIDDEN;
+unsigned int wg_format_get_max_size(const struct wg_format *format);
+
HRESULT avi_splitter_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
HRESULT decodebin_parser_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
HRESULT mpeg_splitter_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
@@ -168,6 +170,7 @@ struct wm_reader_ops
void wm_reader_cleanup(struct wm_reader *reader);
HRESULT wm_reader_close(struct wm_reader *reader);
+HRESULT wm_reader_get_max_stream_size(struct wm_reader *reader, WORD stream_number, DWORD *size);
HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output,
DWORD index, IWMOutputMediaProps **props);
HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output, DWORD *count);
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c
index 89df41feb66..d91a93532c4 100644
--- a/dlls/winegstreamer/quartz_parser.c
+++ b/dlls/winegstreamer/quartz_parser.c
@@ -231,44 +231,97 @@ static bool amt_from_wg_format_audio(AM_MEDIA_TYPE *mt, const struct wg_format *
#define ALIGN(n, alignment) (((n) + (alignment) - 1) & ~((alignment) - 1))
-static unsigned int get_image_size(const struct wg_format *format)
+unsigned int wg_format_get_max_size(const struct wg_format *format)
{
- unsigned int width = format->u.video.width, height = format->u.video.height;
-
- switch (format->u.video.format)
+ switch (format->major_type)
{
- case WG_VIDEO_FORMAT_BGRA:
- case WG_VIDEO_FORMAT_BGRx:
- case WG_VIDEO_FORMAT_AYUV:
- return width * height * 4;
+ case WG_MAJOR_TYPE_VIDEO:
+ {
+ unsigned int width = format->u.video.width, height = format->u.video.height;
- case WG_VIDEO_FORMAT_BGR:
- return ALIGN(width * 3, 4) * height;
+ switch (format->u.video.format)
+ {
+ case WG_VIDEO_FORMAT_BGRA:
+ case WG_VIDEO_FORMAT_BGRx:
+ case WG_VIDEO_FORMAT_AYUV:
+ return width * height * 4;
- case WG_VIDEO_FORMAT_RGB15:
- case WG_VIDEO_FORMAT_RGB16:
- case WG_VIDEO_FORMAT_UYVY:
- case WG_VIDEO_FORMAT_YUY2:
- case WG_VIDEO_FORMAT_YVYU:
- return ALIGN(width * 2, 4) * height;
+ case WG_VIDEO_FORMAT_BGR:
+ return ALIGN(width * 3, 4) * height;
- case WG_VIDEO_FORMAT_I420:
- case WG_VIDEO_FORMAT_YV12:
- return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
- + 2 * ALIGN((width + 1) / 2, 4) * ((height + 1) / 2); /* U and V planes */
+ case WG_VIDEO_FORMAT_RGB15:
+ case WG_VIDEO_FORMAT_RGB16:
+ case WG_VIDEO_FORMAT_UYVY:
+ case WG_VIDEO_FORMAT_YUY2:
+ case WG_VIDEO_FORMAT_YVYU:
+ return ALIGN(width * 2, 4) * height;
- case WG_VIDEO_FORMAT_NV12:
- return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
- + ALIGN(width, 4) * ((height + 1) / 2); /* U/V plane */
+ case WG_VIDEO_FORMAT_I420:
+ case WG_VIDEO_FORMAT_YV12:
+ return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
+ + 2 * ALIGN((width + 1) / 2, 4) * ((height + 1) / 2); /* U and V planes */
- case WG_VIDEO_FORMAT_CINEPAK:
- /* 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 width * height * 3;
+ case WG_VIDEO_FORMAT_NV12:
+ return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
+ + ALIGN(width, 4) * ((height + 1) / 2); /* U/V plane */
- case WG_VIDEO_FORMAT_UNKNOWN:
+ case WG_VIDEO_FORMAT_CINEPAK:
+ /* 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 width * height * 3;
+
+ case WG_VIDEO_FORMAT_UNKNOWN:
+ FIXME("Cannot guess maximum sample size for unknown video format.\n");
+ return 0;
+ }
break;
+ }
+
+ case WG_MAJOR_TYPE_AUDIO:
+ {
+ unsigned int rate = format->u.audio.rate, channels = format->u.audio.channels;
+
+ /* Actually we don't know how large of a sample GStreamer will give
+ * us. Hopefully 1 second is enough... */
+
+ switch (format->u.audio.format)
+ {
+ case WG_AUDIO_FORMAT_U8:
+ return rate * channels;
+
+ case WG_AUDIO_FORMAT_S16LE:
+ return rate * channels * 2;
+
+ case WG_AUDIO_FORMAT_S24LE:
+ return rate * channels * 3;
+
+ case WG_AUDIO_FORMAT_S32LE:
+ case WG_AUDIO_FORMAT_F32LE:
+ return rate * channels * 4;
+
+ case WG_AUDIO_FORMAT_F64LE:
+ return rate * channels * 8;
+
+ case WG_AUDIO_FORMAT_MPEG1_LAYER1:
+ return 56000;
+
+ case WG_AUDIO_FORMAT_MPEG1_LAYER2:
+ return 48000;
+
+ case WG_AUDIO_FORMAT_MPEG1_LAYER3:
+ return 40000;
+
+ case WG_AUDIO_FORMAT_UNKNOWN:
+ FIXME("Cannot guess maximum sample size for unknown audio format.\n");
+ return 0;
+ }
+ break;
+ }
+
+ case WG_MAJOR_TYPE_UNKNOWN:
+ FIXME("Cannot guess maximum sample size for unknown format.\n");
+ return 0;
}
assert(0);
@@ -338,7 +391,7 @@ static bool amt_from_wg_format_video(AM_MEDIA_TYPE *mt, const struct wg_format *
video_format->bmiHeader.biPlanes = 1;
video_format->bmiHeader.biBitCount = format_table[format->u.video.format].depth;
video_format->bmiHeader.biCompression = format_table[format->u.video.format].compression;
- video_format->bmiHeader.biSizeImage = get_image_size(format);
+ video_format->bmiHeader.biSizeImage = wg_format_get_max_size(format);
if (format->u.video.format == WG_VIDEO_FORMAT_RGB16)
{
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c
index b3dd7d41873..6549c9052e1 100644
--- a/dlls/winegstreamer/wm_asyncreader.c
+++ b/dlls/winegstreamer/wm_asyncreader.c
@@ -566,11 +566,14 @@ static HRESULT WINAPI WMReaderAdvanced_GetMaxOutputSampleSize(IWMReaderAdvanced6
return E_NOTIMPL;
}
-static HRESULT WINAPI WMReaderAdvanced_GetMaxStreamSampleSize(IWMReaderAdvanced6 *iface, WORD stream, DWORD *max)
+static HRESULT WINAPI WMReaderAdvanced_GetMaxStreamSampleSize(IWMReaderAdvanced6 *iface,
+ WORD stream_number, DWORD *size)
{
- struct async_reader *This = impl_from_IWMReaderAdvanced6(iface);
- FIXME("(%p)->(%d %p)\n", This, stream, max);
- return E_NOTIMPL;
+ struct async_reader *reader = impl_from_IWMReaderAdvanced6(iface);
+
+ TRACE("reader %p, stream_number %u, size %p.\n", reader, stream_number, size);
+
+ return wm_reader_get_max_stream_size(&reader->reader, stream_number, size);
}
static HRESULT WINAPI WMReaderAdvanced_NotifyLateDelivery(IWMReaderAdvanced6 *iface, QWORD lateness)
diff --git a/dlls/winegstreamer/wm_reader.c b/dlls/winegstreamer/wm_reader.c
index a6e73c2857e..deef2031c96 100644
--- a/dlls/winegstreamer/wm_reader.c
+++ b/dlls/winegstreamer/wm_reader.c
@@ -2016,6 +2016,24 @@ HRESULT wm_reader_set_read_compressed(struct wm_reader *reader, WORD stream_numb
return S_OK;
}
+HRESULT wm_reader_get_max_stream_size(struct wm_reader *reader, WORD stream_number, DWORD *size)
+{
+ struct wm_stream *stream;
+
+ EnterCriticalSection(&reader->cs);
+
+ if (!(stream = wm_reader_get_stream_by_stream_number(reader, stream_number)))
+ {
+ LeaveCriticalSection(&reader->cs);
+ return E_INVALIDARG;
+ }
+
+ *size = wg_format_get_max_size(&stream->format);
+
+ LeaveCriticalSection(&reader->cs);
+ return S_OK;
+}
+
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops)
{
reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl;
diff --git a/dlls/wmvcore/tests/wmvcore.c b/dlls/wmvcore/tests/wmvcore.c
index 9ddd53ab9e7..c979a06fdb0 100644
--- a/dlls/wmvcore/tests/wmvcore.c
+++ b/dlls/wmvcore/tests/wmvcore.c
@@ -1390,7 +1390,9 @@ struct callback
unsigned int got_closed, got_started, got_sample, got_end_of_streaming, got_eof;
bool all_streams_off;
bool allocated_samples;
+
bool read_compressed;
+ DWORD max_stream_sample_size[2];
};
static struct callback *impl_from_IWMReaderCallback(IWMReaderCallback *iface)
@@ -1661,6 +1663,7 @@ static HRESULT WINAPI callback_advanced_AllocateForStream(IWMReaderCallbackAdvan
WORD stream_number, DWORD size, INSSBuffer **sample, void *context)
{
struct callback *callback = impl_from_IWMReaderCallbackAdvanced(iface);
+ DWORD max_size = callback->max_stream_sample_size[stream_number - 1];
struct buffer *object;
if (winetest_debug > 1)
@@ -1670,6 +1673,8 @@ static HRESULT WINAPI callback_advanced_AllocateForStream(IWMReaderCallbackAdvan
ok(callback->read_compressed, "AllocateForStream() should only be called when reading compressed samples.\n");
ok(callback->allocated_samples, "AllocateForStream() should only be called when using a custom allocator.\n");
+ ok(size <= max_size, "Got size %u, max stream sample size %u.\n", size, max_size);
+
if (!(object = malloc(offsetof(struct buffer, data[size]))))
return E_OUTOFMEMORY;
@@ -2016,12 +2021,21 @@ static void test_async_reader_compressed(IWMReader *reader,
{
HRESULT hr;
+ hr = IWMReaderAdvanced2_GetMaxStreamSampleSize(advanced, 0, &callback->max_stream_sample_size[0]);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_GetMaxStreamSampleSize(advanced, 3, &callback->max_stream_sample_size[0]);
+ ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
+ hr = IWMReaderAdvanced2_GetMaxStreamSampleSize(advanced, 1, &callback->max_stream_sample_size[0]);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(callback->max_stream_sample_size[0] > 0, "Expected nonzero size.\n");
+ hr = IWMReaderAdvanced2_GetMaxStreamSampleSize(advanced, 2, &callback->max_stream_sample_size[1]);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(callback->max_stream_sample_size[1] > 0, "Expected nonzero size.\n");
+
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 0, TRUE);
ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
-
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 3, TRUE);
ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
-
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 1, TRUE);
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 2, TRUE);
--
2.33.0
More information about the wine-devel
mailing list