winegstreamer: Implement IWMReaderAdvanced::GetMaxStreamSampleSize().
Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3dbce69fd4
commit
639c04a5b4
|
@ -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,
|
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;
|
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 avi_splitter_create(IUnknown *outer, IUnknown **out) DECLSPEC_HIDDEN;
|
||||||
HRESULT decodebin_parser_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;
|
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);
|
void wm_reader_cleanup(struct wm_reader *reader);
|
||||||
HRESULT wm_reader_close(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,
|
HRESULT wm_reader_get_output_format(struct wm_reader *reader, DWORD output,
|
||||||
DWORD index, IWMOutputMediaProps **props);
|
DWORD index, IWMOutputMediaProps **props);
|
||||||
HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output, DWORD *count);
|
HRESULT wm_reader_get_output_format_count(struct wm_reader *reader, DWORD output, DWORD *count);
|
||||||
|
|
|
@ -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))
|
#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->major_type)
|
||||||
|
|
||||||
switch (format->u.video.format)
|
|
||||||
{
|
{
|
||||||
case WG_VIDEO_FORMAT_BGRA:
|
case WG_MAJOR_TYPE_VIDEO:
|
||||||
case WG_VIDEO_FORMAT_BGRx:
|
{
|
||||||
case WG_VIDEO_FORMAT_AYUV:
|
unsigned int width = format->u.video.width, height = format->u.video.height;
|
||||||
return width * height * 4;
|
|
||||||
|
|
||||||
case WG_VIDEO_FORMAT_BGR:
|
switch (format->u.video.format)
|
||||||
return ALIGN(width * 3, 4) * height;
|
{
|
||||||
|
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_BGR:
|
||||||
case WG_VIDEO_FORMAT_RGB16:
|
return ALIGN(width * 3, 4) * height;
|
||||||
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_I420:
|
case WG_VIDEO_FORMAT_RGB15:
|
||||||
case WG_VIDEO_FORMAT_YV12:
|
case WG_VIDEO_FORMAT_RGB16:
|
||||||
return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
|
case WG_VIDEO_FORMAT_UYVY:
|
||||||
+ 2 * ALIGN((width + 1) / 2, 4) * ((height + 1) / 2); /* U and V planes */
|
case WG_VIDEO_FORMAT_YUY2:
|
||||||
|
case WG_VIDEO_FORMAT_YVYU:
|
||||||
|
return ALIGN(width * 2, 4) * height;
|
||||||
|
|
||||||
case WG_VIDEO_FORMAT_NV12:
|
case WG_VIDEO_FORMAT_I420:
|
||||||
return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
|
case WG_VIDEO_FORMAT_YV12:
|
||||||
+ ALIGN(width, 4) * ((height + 1) / 2); /* U/V plane */
|
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:
|
case WG_VIDEO_FORMAT_NV12:
|
||||||
/* Both ffmpeg's encoder and a Cinepak file seen in the wild report
|
return ALIGN(width, 4) * ALIGN(height, 2) /* Y plane */
|
||||||
* 24 bpp. ffmpeg sets biSizeImage as below; others may be smaller,
|
+ ALIGN(width, 4) * ((height + 1) / 2); /* U/V plane */
|
||||||
* but as long as every sample fits into our allocator, we're fine. */
|
|
||||||
return width * height * 3;
|
|
||||||
|
|
||||||
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;
|
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);
|
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.biPlanes = 1;
|
||||||
video_format->bmiHeader.biBitCount = format_table[format->u.video.format].depth;
|
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.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)
|
if (format->u.video.format == WG_VIDEO_FORMAT_RGB16)
|
||||||
{
|
{
|
||||||
|
|
|
@ -566,11 +566,14 @@ static HRESULT WINAPI WMReaderAdvanced_GetMaxOutputSampleSize(IWMReaderAdvanced6
|
||||||
return E_NOTIMPL;
|
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);
|
struct async_reader *reader = impl_from_IWMReaderAdvanced6(iface);
|
||||||
FIXME("(%p)->(%d %p)\n", This, stream, max);
|
|
||||||
return E_NOTIMPL;
|
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)
|
static HRESULT WINAPI WMReaderAdvanced_NotifyLateDelivery(IWMReaderAdvanced6 *iface, QWORD lateness)
|
||||||
|
|
|
@ -1994,6 +1994,24 @@ HRESULT wm_reader_set_read_compressed(struct wm_reader *reader, WORD stream_numb
|
||||||
return S_OK;
|
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)
|
void wm_reader_init(struct wm_reader *reader, const struct wm_reader_ops *ops)
|
||||||
{
|
{
|
||||||
reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl;
|
reader->IWMHeaderInfo3_iface.lpVtbl = &header_info_vtbl;
|
||||||
|
|
|
@ -1390,7 +1390,9 @@ struct callback
|
||||||
unsigned int got_closed, got_started, got_sample, got_end_of_streaming, got_eof;
|
unsigned int got_closed, got_started, got_sample, got_end_of_streaming, got_eof;
|
||||||
bool all_streams_off;
|
bool all_streams_off;
|
||||||
bool allocated_samples;
|
bool allocated_samples;
|
||||||
|
|
||||||
bool read_compressed;
|
bool read_compressed;
|
||||||
|
DWORD max_stream_sample_size[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct callback *impl_from_IWMReaderCallback(IWMReaderCallback *iface)
|
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)
|
WORD stream_number, DWORD size, INSSBuffer **sample, void *context)
|
||||||
{
|
{
|
||||||
struct callback *callback = impl_from_IWMReaderCallbackAdvanced(iface);
|
struct callback *callback = impl_from_IWMReaderCallbackAdvanced(iface);
|
||||||
|
DWORD max_size = callback->max_stream_sample_size[stream_number - 1];
|
||||||
struct buffer *object;
|
struct buffer *object;
|
||||||
|
|
||||||
if (winetest_debug > 1)
|
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->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(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]))))
|
if (!(object = malloc(offsetof(struct buffer, data[size]))))
|
||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
@ -2016,12 +2021,21 @@ static void test_async_reader_compressed(IWMReader *reader,
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
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);
|
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 0, TRUE);
|
||||||
ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
|
ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
|
||||||
|
|
||||||
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 3, TRUE);
|
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 3, TRUE);
|
||||||
ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
|
ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
|
||||||
|
|
||||||
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 1, TRUE);
|
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 1, TRUE);
|
||||||
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
ok(hr == S_OK, "Got hr %#x.\n", hr);
|
||||||
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 2, TRUE);
|
hr = IWMReaderAdvanced2_SetReceiveStreamSamples(advanced, 2, TRUE);
|
||||||
|
|
Loading…
Reference in New Issue