commit 1144afd26a8da8c00ab831be1c7f0628ca863586
parent 78c8ffd8542e3f09b6cf37164aa536dd12f6bda9
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date: Thu, 18 May 2023 21:10:15 +0800
audio_windows.c: fixed several memory leaks
A few objects weren't being released correctly. This commits ensures
they are. There appears to be some more leak, but this change drastically
reduces the leak severity.
Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Diffstat:
2 files changed, 67 insertions(+), 23 deletions(-)
diff --git a/audio_windows.c b/audio_windows.c
@@ -51,7 +51,7 @@ NewResult(void* value, Error* err)
return (Result){value, err};
}
-// CharWiden converst a raw C string to a wide string used by Windows.
+// CharWiden converts a raw C string to a wide string used by Windows.
Result
CharWiden(char* str)
{
@@ -70,8 +70,6 @@ CharWiden(char* str)
return NewResult(target, NULL);
}
-#define BUFFER_DEFAULT_SIZE 1024*1024
-
// BufferNew allocates a new buffer ready to use.
Buffer*
BufferNew()
@@ -122,6 +120,9 @@ BufferWrite(Buffer* buffer, int size, BYTE* data)
void
BufferFree(Buffer* buffer)
{
+ if (buffer == NULL) {
+ return;
+ }
free(buffer->Data);
free(buffer);
}
@@ -357,12 +358,11 @@ done:
HRESULT
ConfigureAudioStream(
IMFSourceReader *pReader, // Pointer to the source reader.
+ IMFMediaType **pUncompressedAudioType,
+ IMFMediaType **pPartialType,
IMFMediaType **ppPCMAudio // Receives the audio format.
)
{
- IMFMediaType *pUncompressedAudioType = NULL;
- IMFMediaType *pPartialType = NULL;
-
// Select the first audio stream, and deselect all other streams.
HRESULT hr = pReader->lpVtbl->SetStreamSelection(pReader,
(DWORD)MF_SOURCE_READER_ALL_STREAMS, FALSE);
@@ -374,16 +374,16 @@ ConfigureAudioStream(
}
// Create a partial media type that specifies uncompressed PCM audio.
- hr = MFCreateMediaType(&pPartialType);
+ hr = MFCreateMediaType(pPartialType);
if (SUCCEEDED(hr))
{
- hr = pPartialType->lpVtbl->SetGUID(pPartialType, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
+ hr = (*pPartialType)->lpVtbl->SetGUID((*pPartialType), &MF_MT_MAJOR_TYPE, &MFMediaType_Audio);
}
if (SUCCEEDED(hr))
{
- hr = pPartialType->lpVtbl->SetGUID(pPartialType, &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
+ hr = (*pPartialType)->lpVtbl->SetGUID((*pPartialType), &MF_MT_SUBTYPE, &MFAudioFormat_PCM);
}
// Set this type on the source reader. The source reader will
@@ -392,7 +392,7 @@ ConfigureAudioStream(
{
hr = pReader->lpVtbl->SetCurrentMediaType(pReader,
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
- NULL, pPartialType);
+ NULL, (*pPartialType));
}
// Get the complete uncompressed format.
@@ -400,7 +400,7 @@ ConfigureAudioStream(
{
hr = pReader->lpVtbl->GetCurrentMediaType(pReader,
(DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM,
- &pUncompressedAudioType);
+ pUncompressedAudioType);
}
// Ensure the stream is selected.
@@ -414,7 +414,7 @@ ConfigureAudioStream(
// Return the PCM format to the caller.
if (SUCCEEDED(hr))
{
- *ppPCMAudio = pUncompressedAudioType;
+ *ppPCMAudio = (*pUncompressedAudioType);
(*ppPCMAudio)->lpVtbl->AddRef(*ppPCMAudio);
}
@@ -546,11 +546,12 @@ decode(IMFSourceReader * reader, Buffer ** out)
assert(reader);
IMFMediaBuffer *bufferReader = NULL; // buffer object containing the raw buffer.
- LONGLONG prev_time_stamp = -1;
IMFSample *pSample = NULL; // sample object containing on or more streams.
- LONGLONG time_stamp = 0;
Buffer *buffer = NULL; // Buffer to accumulate decoded PCM and return to Go.
BYTE *chunk = NULL; // pointer to start of chunk.
+
+ LONGLONG prev_time_stamp = -1;
+ LONGLONG time_stamp = 0;
DWORD cbBuffer = 0; // size of chunk.
HRESULT hr = S_OK;
Error *err = NULL;
@@ -567,7 +568,13 @@ decode(IMFSourceReader * reader, Buffer ** out)
// it all back to Go at once.
while (1) {
DWORD dwFlags = 0;
-
+
+ if (pSample != NULL)
+ {
+ pSample->lpVtbl->RemoveAllBuffers(pSample);
+ pSample->lpVtbl->Release(pSample);
+ }
+
// Read the next sample.
hr = reader->lpVtbl->ReadSample(
reader,
@@ -613,6 +620,10 @@ decode(IMFSourceReader * reader, Buffer ** out)
continue;
}
+ if (bufferReader != NULL) {
+ bufferReader->lpVtbl->Release(bufferReader);
+ }
+
// Get a pointer to the buffer object.
hr = pSample->lpVtbl->ConvertToContiguousBuffer(pSample, &bufferReader);
@@ -642,7 +653,7 @@ decode(IMFSourceReader * reader, Buffer ** out)
goto done;
}
- chunk = NULL;
+ chunk = NULL;
}
*out = buffer;
@@ -651,6 +662,7 @@ done:
if (pSample != NULL)
{
+ pSample->lpVtbl->RemoveAllBuffers(pSample);
pSample->lpVtbl->Release(pSample);
}
@@ -708,7 +720,10 @@ Decode(BYTE* compressed, UINT size)
IMFMediaType * m_type = NULL;
- hr = ConfigureAudioStream(reader, &m_type);
+ IMFMediaType * pUncompressedAudioType = NULL;
+ IMFMediaType * pPartialType = NULL;
+
+ hr = ConfigureAudioStream(reader, &pUncompressedAudioType, &pPartialType, &m_type);
if (FAILED(hr))
{
@@ -736,6 +751,13 @@ Decode(BYTE* compressed, UINT size)
assert(buffer);
done:
+ if (pUncompressedAudioType != NULL) {
+ pUncompressedAudioType->lpVtbl->Release(pUncompressedAudioType);
+ }
+
+ if (pPartialType != NULL) {
+ pPartialType->lpVtbl->Release(pPartialType);
+ }
if (m_type != NULL)
{
@@ -747,6 +769,10 @@ done:
stream->lpVtbl->Release(stream);
}
+ if (mem_stream != NULL) {
+ mem_stream->lpVtbl->Release(mem_stream);
+ }
+
if (reader != NULL)
{
reader->lpVtbl->Release(reader);
@@ -801,7 +827,10 @@ Load(char* path)
IMFMediaType * m_type = NULL;
- hr = ConfigureAudioStream(reader, &m_type);
+ IMFMediaType * pUncompressedAudioType = NULL;
+ IMFMediaType * pPartialType = NULL;
+
+ hr = ConfigureAudioStream(reader, &pUncompressedAudioType, &pPartialType, &m_type);
if (FAILED(hr))
{
@@ -837,6 +866,14 @@ Load(char* path)
done:
+ if (pUncompressedAudioType != NULL) {
+ pUncompressedAudioType->lpVtbl->Release(pUncompressedAudioType);
+ }
+
+ if (pPartialType != NULL) {
+ pPartialType->lpVtbl->Release(pPartialType);
+ }
+
if (m_type != NULL)
{
m_type->lpVtbl->Release(m_type);
diff --git a/audio_windows.h b/audio_windows.h
@@ -40,7 +40,6 @@ typedef struct Result
Error* Err;
} Result;
-
// Format describes uncompressed PCM necessary for correct playback.
typedef struct Format
{
@@ -49,7 +48,6 @@ typedef struct Format
uint32_t BitDepth;
} Format;
-
// Buffer describes a dynamic byte buffer with a length, capacity and
// a pointer to the first element.
typedef struct Buffer
@@ -59,8 +57,6 @@ typedef struct Buffer
BYTE* Data; // Data is the pointer to the first byte.
} Buffer;
-
-
// FormatResult captures the result of decoding an audio buffer.
typedef struct FormatResult
{
@@ -77,9 +73,20 @@ typedef struct DecodeResult
Error* Err;
} DecodeResult;
+#define BUFFER_DEFAULT_SIZE 1024*1024
+
+// BufferNew allocates a buffer object that can read and write data.
+Buffer*
+BufferNew();
+
+// BufferWrites the data to the buffer.
+void
+BufferWrite(Buffer* buf, int size, BYTE* data);
+
// BufferFree deallocates the memory for a buffer, including the pointer
// to it and it's pointer to the raw data.
-void BufferFree(Buffer*);
+void
+BufferFree(Buffer*);
// ErrorFree deallocates the memory for an error and all wrapped errors.
void ErrorFree(Error*);