Commit 56dde41b authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

winegstreamer: Implement IWMSyncReader::Open().

parent c3811e84
...@@ -139,6 +139,7 @@ struct wm_reader ...@@ -139,6 +139,7 @@ struct wm_reader
QWORD start_time; QWORD start_time;
IStream *source_stream; IStream *source_stream;
HANDLE file;
HANDLE read_thread; HANDLE read_thread;
bool read_thread_shutdown; bool read_thread_shutdown;
struct wg_parser *wg_parser; struct wg_parser *wg_parser;
...@@ -167,6 +168,7 @@ struct wm_stream *wm_reader_get_stream_by_stream_number(struct wm_reader *reader ...@@ -167,6 +168,7 @@ struct wm_stream *wm_reader_get_stream_by_stream_number(struct wm_reader *reader
HRESULT wm_reader_get_stream_sample(struct wm_stream *stream, HRESULT wm_reader_get_stream_sample(struct wm_stream *stream,
INSSBuffer **sample, QWORD *pts, QWORD *duration, DWORD *flags); INSSBuffer **sample, QWORD *pts, QWORD *duration, DWORD *flags);
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);
HRESULT wm_reader_open_file(struct wm_reader *reader, const WCHAR *filename);
HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream); HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream);
void wm_reader_seek(struct wm_reader *reader, QWORD start, LONGLONG duration); void wm_reader_seek(struct wm_reader *reader, QWORD start, LONGLONG duration);
HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output, HRESULT wm_reader_set_output_props(struct wm_reader *reader, DWORD output,
......
...@@ -438,22 +438,34 @@ static DWORD CALLBACK read_thread(void *arg) ...@@ -438,22 +438,34 @@ static DWORD CALLBACK read_thread(void *arg)
{ {
struct wm_reader *reader = arg; struct wm_reader *reader = arg;
IStream *stream = reader->source_stream; IStream *stream = reader->source_stream;
HANDLE file = reader->file;
size_t buffer_size = 4096; size_t buffer_size = 4096;
uint64_t file_size; uint64_t file_size;
STATSTG stat;
void *data; void *data;
if (!(data = malloc(buffer_size))) if (!(data = malloc(buffer_size)))
return 0; return 0;
IStream_Stat(stream, &stat, STATFLAG_NONAME); if (file)
file_size = stat.cbSize.QuadPart; {
LARGE_INTEGER size;
GetFileSizeEx(file, &size);
file_size = size.QuadPart;
}
else
{
STATSTG stat;
IStream_Stat(stream, &stat, STATFLAG_NONAME);
file_size = stat.cbSize.QuadPart;
}
TRACE("Starting read thread for reader %p.\n", reader); TRACE("Starting read thread for reader %p.\n", reader);
while (!reader->read_thread_shutdown) while (!reader->read_thread_shutdown)
{ {
LARGE_INTEGER stream_offset; LARGE_INTEGER large_offset;
uint64_t offset; uint64_t offset;
ULONG ret_size; ULONG ret_size;
uint32_t size; uint32_t size;
...@@ -481,14 +493,32 @@ static DWORD CALLBACK read_thread(void *arg) ...@@ -481,14 +493,32 @@ static DWORD CALLBACK read_thread(void *arg)
ret_size = 0; ret_size = 0;
stream_offset.QuadPart = offset; large_offset.QuadPart = offset;
if (SUCCEEDED(hr = IStream_Seek(stream, stream_offset, STREAM_SEEK_SET, NULL))) if (file)
hr = IStream_Read(stream, data, size, &ret_size); {
if (FAILED(hr)) if (!SetFilePointerEx(file, large_offset, NULL, FILE_BEGIN)
ERR("Failed to read %u bytes at offset %I64u, hr %#x.\n", size, offset, hr); || !ReadFile(file, data, size, &ret_size, NULL))
else if (ret_size != size) {
ERR("Failed to read %u bytes at offset %I64u, error %u.\n", size, offset, GetLastError());
wg_parser_push_data(reader->wg_parser, NULL, 0);
continue;
}
}
else
{
if (SUCCEEDED(hr = IStream_Seek(stream, large_offset, STREAM_SEEK_SET, NULL)))
hr = IStream_Read(stream, data, size, &ret_size);
if (FAILED(hr))
{
ERR("Failed to read %u bytes at offset %I64u, hr %#x.\n", size, offset, hr);
wg_parser_push_data(reader->wg_parser, NULL, 0);
continue;
}
}
if (ret_size != size)
ERR("Unexpected short read: requested %u bytes, got %u.\n", size, ret_size); ERR("Unexpected short read: requested %u bytes, got %u.\n", size, ret_size);
wg_parser_push_data(reader->wg_parser, SUCCEEDED(hr) ? data : NULL, ret_size); wg_parser_push_data(reader->wg_parser, data, ret_size);
} }
free(data); free(data);
...@@ -1326,26 +1356,16 @@ static const IWMReaderTimecodeVtbl timecode_vtbl = ...@@ -1326,26 +1356,16 @@ static const IWMReaderTimecodeVtbl timecode_vtbl =
timecode_GetTimecodeRangeBounds, timecode_GetTimecodeRangeBounds,
}; };
HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream) static HRESULT init_stream(struct wm_reader *reader, QWORD file_size)
{ {
struct wg_parser *wg_parser; struct wg_parser *wg_parser;
STATSTG stat;
HRESULT hr; HRESULT hr;
WORD i; WORD i;
if (FAILED(hr = IStream_Stat(stream, &stat, STATFLAG_NONAME)))
{
ERR("Failed to stat stream, hr %#x.\n", hr);
return hr;
}
if (!(wg_parser = wg_parser_create(WG_PARSER_DECODEBIN, false))) if (!(wg_parser = wg_parser_create(WG_PARSER_DECODEBIN, false)))
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
EnterCriticalSection(&reader->cs);
reader->wg_parser = wg_parser; reader->wg_parser = wg_parser;
IStream_AddRef(reader->source_stream = stream);
reader->read_thread_shutdown = false; reader->read_thread_shutdown = false;
if (!(reader->read_thread = CreateThread(NULL, 0, read_thread, reader, 0, NULL))) if (!(reader->read_thread = CreateThread(NULL, 0, read_thread, reader, 0, NULL)))
{ {
...@@ -1353,7 +1373,7 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream) ...@@ -1353,7 +1373,7 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
goto out_destroy_parser; goto out_destroy_parser;
} }
if (FAILED(hr = wg_parser_connect(reader->wg_parser, stat.cbSize.QuadPart))) if (FAILED(hr = wg_parser_connect(reader->wg_parser, file_size)))
{ {
ERR("Failed to connect parser, hr %#x.\n", hr); ERR("Failed to connect parser, hr %#x.\n", hr);
goto out_shutdown_thread; goto out_shutdown_thread;
...@@ -1402,7 +1422,6 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream) ...@@ -1402,7 +1422,6 @@ HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
wg_parser_stream_seek(reader->streams[0].wg_stream, 1.0, 0, 0, wg_parser_stream_seek(reader->streams[0].wg_stream, 1.0, 0, 0,
AM_SEEKING_AbsolutePositioning, AM_SEEKING_NoPositioning); AM_SEEKING_AbsolutePositioning, AM_SEEKING_NoPositioning);
LeaveCriticalSection(&reader->cs);
return S_OK; return S_OK;
out_disconnect_parser: out_disconnect_parser:
...@@ -1417,8 +1436,60 @@ out_shutdown_thread: ...@@ -1417,8 +1436,60 @@ out_shutdown_thread:
out_destroy_parser: out_destroy_parser:
wg_parser_destroy(reader->wg_parser); wg_parser_destroy(reader->wg_parser);
reader->wg_parser = NULL; reader->wg_parser = NULL;
IStream_Release(reader->source_stream);
reader->source_stream = NULL; return hr;
}
HRESULT wm_reader_open_stream(struct wm_reader *reader, IStream *stream)
{
STATSTG stat;
HRESULT hr;
if (FAILED(hr = IStream_Stat(stream, &stat, STATFLAG_NONAME)))
{
ERR("Failed to stat stream, hr %#x.\n", hr);
return hr;
}
EnterCriticalSection(&reader->cs);
IStream_AddRef(reader->source_stream = stream);
if (FAILED(hr = init_stream(reader, stat.cbSize.QuadPart)))
{
IStream_Release(stream);
reader->source_stream = NULL;
}
LeaveCriticalSection(&reader->cs);
return hr;
}
HRESULT wm_reader_open_file(struct wm_reader *reader, const WCHAR *filename)
{
LARGE_INTEGER size;
HANDLE file;
HRESULT hr;
if ((file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
{
ERR("Failed to open %s, error %u.\n", debugstr_w(filename), GetLastError());
return HRESULT_FROM_WIN32(GetLastError());
}
if (!GetFileSizeEx(file, &size))
{
ERR("Failed to get the size of %s, error %u.\n", debugstr_w(filename), GetLastError());
CloseHandle(file);
return HRESULT_FROM_WIN32(GetLastError());
}
EnterCriticalSection(&reader->cs);
reader->file = file;
if (FAILED(hr = init_stream(reader, size.QuadPart)))
reader->file = NULL;
LeaveCriticalSection(&reader->cs); LeaveCriticalSection(&reader->cs);
return hr; return hr;
...@@ -1428,7 +1499,7 @@ HRESULT wm_reader_close(struct wm_reader *reader) ...@@ -1428,7 +1499,7 @@ HRESULT wm_reader_close(struct wm_reader *reader)
{ {
EnterCriticalSection(&reader->cs); EnterCriticalSection(&reader->cs);
if (!reader->source_stream) if (!reader->wg_parser)
{ {
LeaveCriticalSection(&reader->cs); LeaveCriticalSection(&reader->cs);
return NS_E_INVALID_REQUEST; return NS_E_INVALID_REQUEST;
...@@ -1443,8 +1514,13 @@ HRESULT wm_reader_close(struct wm_reader *reader) ...@@ -1443,8 +1514,13 @@ HRESULT wm_reader_close(struct wm_reader *reader)
wg_parser_destroy(reader->wg_parser); wg_parser_destroy(reader->wg_parser);
reader->wg_parser = NULL; reader->wg_parser = NULL;
IStream_Release(reader->source_stream);
if (reader->source_stream)
IStream_Release(reader->source_stream);
reader->source_stream = NULL; reader->source_stream = NULL;
if (reader->file)
CloseHandle(reader->file);
reader->file = NULL;
LeaveCriticalSection(&reader->cs); LeaveCriticalSection(&reader->cs);
return S_OK; return S_OK;
......
...@@ -226,9 +226,11 @@ static HRESULT WINAPI WMSyncReader_GetStreamSelected(IWMSyncReader2 *iface, WORD ...@@ -226,9 +226,11 @@ static HRESULT WINAPI WMSyncReader_GetStreamSelected(IWMSyncReader2 *iface, WORD
static HRESULT WINAPI WMSyncReader_Open(IWMSyncReader2 *iface, const WCHAR *filename) static HRESULT WINAPI WMSyncReader_Open(IWMSyncReader2 *iface, const WCHAR *filename)
{ {
struct sync_reader *This = impl_from_IWMSyncReader2(iface); struct sync_reader *reader = impl_from_IWMSyncReader2(iface);
FIXME("(%p)->(%s): stub!\n", This, debugstr_w(filename));
return E_NOTIMPL; TRACE("reader %p, filename %s.\n", reader, debugstr_w(filename));
return wm_reader_open_file(&reader->reader, filename);
} }
static HRESULT WINAPI WMSyncReader_OpenStream(IWMSyncReader2 *iface, IStream *stream) static HRESULT WINAPI WMSyncReader_OpenStream(IWMSyncReader2 *iface, IStream *stream)
......
...@@ -1012,6 +1012,45 @@ static void test_sync_reader_types(void) ...@@ -1012,6 +1012,45 @@ static void test_sync_reader_types(void)
ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError()); ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
} }
static void test_sync_reader_file(void)
{
const WCHAR *filename = load_resource(L"test.wmv");
IWMSyncReader *reader;
IWMProfile *profile;
DWORD count;
HRESULT hr;
ULONG ref;
BOOL ret;
hr = WMCreateSyncReader(NULL, 0, &reader);
ok(hr == S_OK, "Got hr %#x.\n", hr);
IWMSyncReader_QueryInterface(reader, &IID_IWMProfile, (void **)&profile);
hr = IWMSyncReader_Open(reader, filename);
ok(hr == S_OK, "Got hr %#x.\n", hr);
count = 0xdeadbeef;
hr = IWMSyncReader_GetOutputCount(reader, &count);
ok(hr == S_OK, "Got hr %#x.\n", hr);
ok(count == 2, "Got count %u.\n", count);
hr = IWMSyncReader_Close(reader);
ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = IWMSyncReader_Close(reader);
ok(hr == NS_E_INVALID_REQUEST, "Got hr %#x.\n", hr);
hr = IWMSyncReader_Open(reader, filename);
ok(hr == S_OK, "Got hr %#x.\n", hr);
IWMProfile_Release(profile);
ref = IWMSyncReader_Release(reader);
ok(!ref, "Got outstanding refcount %d.\n", ref);
ret = DeleteFileW(filename);
ok(ret, "Failed to delete %s, error %u.\n", debugstr_w(filename), GetLastError());
}
START_TEST(wmvcore) START_TEST(wmvcore)
{ {
HRESULT hr; HRESULT hr;
...@@ -1030,6 +1069,7 @@ START_TEST(wmvcore) ...@@ -1030,6 +1069,7 @@ START_TEST(wmvcore)
test_iscontentprotected(); test_iscontentprotected();
test_sync_reader_streaming(); test_sync_reader_streaming();
test_sync_reader_types(); test_sync_reader_types();
test_sync_reader_file();
CoUninitialize(); CoUninitialize();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment