-- v3: avifil32: Fix dwLength counting for fixed size samples. avifil32: Assume OF_WRITE for OF_CREATE in AVIFileOpenW(). avifil32/tests: Test creating AVI file with OF_CREATE but without access mode.
From: Paul Gofman pgofman@codeweavers.com
--- dlls/avifil32/tests/api.c | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/dlls/avifil32/tests/api.c b/dlls/avifil32/tests/api.c index f7571f48b6a..55838c92b1d 100644 --- a/dlls/avifil32/tests/api.c +++ b/dlls/avifil32/tests/api.c @@ -771,10 +771,58 @@ static void test_COM_editstream(void) while (IAVIEditStream_Release(edit)); }
+static void test_avifile_write(void) +{ + WCHAR fn[MAX_PATH]; + IPersistFile *persist; + AVISTREAMINFOW si; + PAVIFILE avifile; + PAVISTREAM stm; + HRESULT hr; + BOOL ret; + + GetTempPathW(MAX_PATH, fn); + wcscat(fn, L"test.avi"); + + hr = CoCreateInstance(&CLSID_AVIFile, NULL, CLSCTX_INPROC, &IID_IAVIFile, (void **)&avifile); + ok(hr == S_OK, "got %#lx.\n", hr); + hr = IAVIFile_QueryInterface(avifile, &IID_IPersistFile, (void **)&persist); + ok(hr == S_OK, "got %#lx.\n", hr); + hr = IPersistFile_Load(persist, fn, STGM_CREATE); + ok(hr == S_OK, "got %#lx.\n", hr); + + memset(&si, 0, sizeof(si)); + si.fccType = streamtypeAUDIO; + si.dwScale = 1; + si.dwRate = 48000; + si.dwLength = 4; + si.dwQuality = ~0u; + si.dwSampleSize = 4; + hr = IAVIFile_CreateStream(avifile, &stm, &si); + ok(hr == AVIERR_READONLY, "got %#lx.\n", hr); + + IPersistFile_Release(persist); + IAVIFile_Release(avifile); + + ret = DeleteFileW(fn); + ok(ret, "got error %lu.\n", GetLastError()); + + hr = AVIFileOpenW(&avifile, fn, OF_CREATE, NULL); + ok(hr == S_OK, "got %#lx.\n", hr); + hr = AVIFileCreateStreamW(avifile, &stm, &si); + todo_wine ok(hr == S_OK, "got %#lx.\n", hr); + if (hr == S_OK) + IAVIStream_Release(stm); + IAVIFile_Release(avifile); + ret = DeleteFileW(fn); + ok(ret, "got error %lu.\n", GetLastError()); +} + START_TEST(api) {
AVIFileInit(); + test_EditStreamSetInfo(); test_AVISaveOptions(); test_default_data(); @@ -784,6 +832,7 @@ START_TEST(api) test_COM(); test_COM_wavfile(); test_COM_editstream(); + test_avifile_write(); AVIFileExit();
}
From: Paul Gofman pgofman@codeweavers.com
--- dlls/avifil32/api.c | 3 +++ dlls/avifil32/tests/api.c | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/dlls/avifil32/api.c b/dlls/avifil32/api.c index fe0c163cf0a..f2ed1736882 100644 --- a/dlls/avifil32/api.c +++ b/dlls/avifil32/api.c @@ -260,6 +260,9 @@ HRESULT WINAPI AVIFileOpenW(PAVIFILE *ppfile, LPCWSTR szFile, UINT uMode, return hr; }
+ if (uMode & OF_CREATE) + uMode |= OF_WRITE; + hr = IPersistFile_Load(ppersist, szFile, uMode); IPersistFile_Release(ppersist); if (FAILED(hr)) { diff --git a/dlls/avifil32/tests/api.c b/dlls/avifil32/tests/api.c index 55838c92b1d..9efba25fd56 100644 --- a/dlls/avifil32/tests/api.c +++ b/dlls/avifil32/tests/api.c @@ -810,9 +810,8 @@ static void test_avifile_write(void) hr = AVIFileOpenW(&avifile, fn, OF_CREATE, NULL); ok(hr == S_OK, "got %#lx.\n", hr); hr = AVIFileCreateStreamW(avifile, &stm, &si); - todo_wine ok(hr == S_OK, "got %#lx.\n", hr); - if (hr == S_OK) - IAVIStream_Release(stm); + ok(hr == S_OK, "got %#lx.\n", hr); + IAVIStream_Release(stm); IAVIFile_Release(avifile); ret = DeleteFileW(fn); ok(ret, "got error %lu.\n", GetLastError());
From: Paul Gofman pgofman@codeweavers.com
--- dlls/avifil32/avifile.c | 17 +++++++++++++--- dlls/avifil32/tests/api.c | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/dlls/avifil32/avifile.c b/dlls/avifil32/avifile.c index 719d96edf86..6aae4736c4d 100644 --- a/dlls/avifil32/avifile.c +++ b/dlls/avifil32/avifile.c @@ -1399,9 +1399,19 @@ static HRESULT AVIFILE_AddFrame(IAVIStreamImpl *This, DWORD ckid, DWORD size, DW This->idxFrames[This->lLastFrame].dwChunkLength = size;
/* update AVISTREAMINFO structure if necessary */ - if (This->sInfo.dwLength <= This->lLastFrame) - This->sInfo.dwLength = This->lLastFrame + 1; + if (This->sInfo.dwSampleSize) + { + unsigned int block;
+ size = 0; + for (block = 0; block <= This->lLastFrame; block++) + size += This->idxFrames[block].dwChunkLength; + This->sInfo.dwLength = max(This->sInfo.dwLength, size / This->sInfo.dwSampleSize); + } + else + { + This->sInfo.dwLength = max(This->sInfo.dwLength, This->lLastFrame + 1); + } return AVIERR_OK; }
@@ -1989,7 +1999,8 @@ static HRESULT AVIFILE_ReadBlock(IAVIStreamImpl *This, DWORD pos, assert(This != NULL); assert(This->paf != NULL); assert(This->paf->hmmio != NULL); - assert(This->sInfo.dwStart <= pos && pos < This->sInfo.dwLength); + if (!This->sInfo.dwSampleSize) + assert(This->sInfo.dwStart <= pos && pos < This->sInfo.dwLength); assert(pos <= This->lLastFrame);
/* should we read as much as block gives us? */ diff --git a/dlls/avifil32/tests/api.c b/dlls/avifil32/tests/api.c index 9efba25fd56..227fd7a286d 100644 --- a/dlls/avifil32/tests/api.c +++ b/dlls/avifil32/tests/api.c @@ -775,7 +775,9 @@ static void test_avifile_write(void) { WCHAR fn[MAX_PATH]; IPersistFile *persist; + PCMWAVEFORMAT afmt; AVISTREAMINFOW si; + USHORT buffer[64]; PAVIFILE avifile; PAVISTREAM stm; HRESULT hr; @@ -811,6 +813,47 @@ static void test_avifile_write(void) ok(hr == S_OK, "got %#lx.\n", hr); hr = AVIFileCreateStreamW(avifile, &stm, &si); ok(hr == S_OK, "got %#lx.\n", hr); + + memset(&afmt, 0, sizeof(afmt)); + afmt.wBitsPerSample = 16; + afmt.wf.wFormatTag = WAVE_FORMAT_PCM; + afmt.wf.nChannels = 2; + afmt.wf.nSamplesPerSec = 44800; + afmt.wf.nAvgBytesPerSec = afmt.wf.nSamplesPerSec * afmt.wf.nChannels; + afmt.wf.nBlockAlign = afmt.wf.nChannels * 2; + hr = AVIStreamSetFormat(stm, 0, &afmt, sizeof(afmt)); + ok(hr == S_OK, "got %#lx.\n", hr); + + memset(buffer, 0xcc, sizeof(buffer)); + + hr = IAVIStream_Info(stm, &si, sizeof(si)); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(!si.dwLength, "got %lu.\n", si.dwLength); + ok(!si.dwStart, "got %lu.\n", si.dwStart); + ok(!si.dwSuggestedBufferSize, "got %lu.\n", si.dwSuggestedBufferSize); + hr = AVIStreamWrite(stm, 0, 2, buffer, si.dwSampleSize * 2, 0, NULL, NULL); + ok(hr == S_OK, "got %#lx.\n", hr); + hr = IAVIStream_Info(stm, &si, sizeof(si)); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(si.dwLength == 2, "got %lu.\n", si.dwLength); + ok(!si.dwStart, "got %lu.\n", si.dwStart); + ok(si.dwSuggestedBufferSize == 8, "got %lu.\n", si.dwSuggestedBufferSize); + hr = AVIStreamWrite(stm, 2, 2, buffer, si.dwSampleSize * 2, 0, NULL, NULL); + ok(hr == S_OK, "got %#lx.\n", hr); + hr = IAVIStream_Info(stm, &si, sizeof(si)); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(si.dwLength == 4, "got %lu.\n", si.dwLength); + ok(!si.dwStart, "got %lu.\n", si.dwStart); + ok(si.dwSuggestedBufferSize == 8, "got %lu.\n", si.dwSuggestedBufferSize); + + hr = AVIStreamWrite(stm, 4, 4, buffer, si.dwSampleSize * 4, 0, NULL, NULL); + ok(hr == S_OK, "got %#lx.\n", hr); + hr = IAVIStream_Info(stm, &si, sizeof(si)); + ok(hr == S_OK, "got %#lx.\n", hr); + ok(si.dwLength == 8, "got %lu.\n", si.dwLength); + ok(!si.dwStart, "got %lu.\n", si.dwStart); + ok(si.dwSuggestedBufferSize == 16, "got %lu.\n", si.dwSuggestedBufferSize); + IAVIStream_Release(stm); IAVIFile_Release(avifile); ret = DeleteFileW(fn);
On Mon Jun 2 19:13:30 2025 +0000, Elizabeth Figura wrote:
I'm not familiar with avifil32, but I don't see any obvious errors here, except:
+ //afmt.wf.wBitsPerSample = afmt.wf.nChannels * 2 * 8;
That line should probably be uncommented or removed. (Also, "bits per sample" usually also means per channel, at least in other APIs?)
Yes, sorry, it is just a leftover, removed that.
v3: - remove leftover commented out line in test.