Commit d91ca8e8 authored by David Reid's avatar David Reid

Resource Manager: Cleanup from some previous refactoring.

parent 0cbd8c2c
......@@ -2052,7 +2052,7 @@ static ma_data_source* ma_resource_manager_data_buffer_get_connector(ma_resource
}
}
static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 hashedName32, ma_uint32 flags, ma_resource_manager_memory_buffer* pExistingData, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer)
static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 hashedName32, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer)
{
ma_result result;
ma_resource_manager_data_buffer_node* pInsertPoint;
......@@ -2123,198 +2123,180 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
}
/*
The new data buffer has been inserted into the BST. If the data for the item is owned by the application we don't need to do anything except
set the necessary data pointers. Otherwise we need to load the data. If we are loading synchronously we need to load everything from the
calling thread because we may be in a situation where there are no job threads running and therefore the data will never get loaded. If we
are loading asynchronously, we can assume at least one job thread exists and we can do everything from there.
The new data buffer has been inserted into the BST. We now need to load the data. If we are loading synchronously we need to load
everything from the calling thread because we may be in a situation where there are no job threads running and therefore the data
will never get loaded. If we are loading asynchronously, we can assume at least one job thread exists and we can do everything
from there.
*/
if (pExistingData != NULL) {
/* We don't need to do anything if the data is owned by the application except set the necessary data pointers. */
MA_ASSERT(dataBufferType == pExistingData->type);
pDataBuffer->pNode->isDataOwnedByResourceManager = MA_TRUE;
pDataBuffer->pNode->result = MA_BUSY;
pDataBuffer->pNode->isDataOwnedByResourceManager = MA_FALSE;
pDataBuffer->pNode->data = *pExistingData;
pDataBuffer->pNode->result = MA_SUCCESS;
if (async) {
/* Asynchronous. Post to the job thread. */
ma_job job;
/* Fire the event if we have one. */
if (pNotification != NULL) {
ma_async_notification_signal(pNotification);
/* We need a copy of the file path. We should probably make this more efficient, but for now we'll do a transient memory allocation. */
pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
if (pFilePathCopy == NULL) {
if (pNotification != NULL) {
ma_async_notification_signal(pNotification);
}
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
ma__free_from_callbacks(pDataBuffer->pNode, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/);
return MA_OUT_OF_MEMORY;
}
} else {
/*
The data needs to be loaded. If we're loading synchronously we need to do everything here on the calling thread. Otherwise we post
a job and get one of the job threads to do it for us.
*/
pDataBuffer->pNode->isDataOwnedByResourceManager = MA_TRUE;
pDataBuffer->pNode->result = MA_BUSY;
if (async) {
/* Asynchronous. Post to the job thread. */
ma_job job;
/* We need a copy of the file path. We should probably make this more efficient, but for now we'll do a transient memory allocation. */
pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
if (pFilePathCopy == NULL) {
if (pNotification != NULL) {
ma_async_notification_signal(pNotification);
}
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
ma__free_from_callbacks(pDataBuffer->pNode, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/);
return MA_OUT_OF_MEMORY;
/* We now have everything we need to post the job to the job thread. */
job = ma_job_init(MA_JOB_LOAD_DATA_BUFFER);
job.order = ma_resource_manager_data_buffer_next_execution_order(pDataBuffer);
job.loadDataBuffer.pDataBuffer = pDataBuffer;
job.loadDataBuffer.pFilePath = pFilePathCopy;
job.loadDataBuffer.pNotification = pNotification;
result = ma_resource_manager_post_job(pResourceManager, &job);
if (result != MA_SUCCESS) {
/* Failed to post the job to the queue. Probably ran out of space. */
if (pNotification != NULL) {
ma_async_notification_signal(pNotification);
}
/* We now have everything we need to post the job to the job thread. */
job = ma_job_init(MA_JOB_LOAD_DATA_BUFFER);
job.order = ma_resource_manager_data_buffer_next_execution_order(pDataBuffer);
job.loadDataBuffer.pDataBuffer = pDataBuffer;
job.loadDataBuffer.pFilePath = pFilePathCopy;
job.loadDataBuffer.pNotification = pNotification;
result = ma_resource_manager_post_job(pResourceManager, &job);
if (result != MA_SUCCESS) {
/* Failed to post the job to the queue. Probably ran out of space. */
if (pNotification != NULL) {
ma_async_notification_signal(pNotification);
}
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
ma__free_from_callbacks(pDataBuffer->pNode, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/);
ma__free_from_callbacks(pFilePathCopy, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
return result;
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
ma__free_from_callbacks(pDataBuffer->pNode, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/);
ma__free_from_callbacks(pFilePathCopy, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
return result;
}
} else {
/* Synchronous. Do everything here. */
if (pDataBuffer->pNode->data.type == ma_resource_manager_data_buffer_encoding_encoded) {
/* No decoding. Just store the file contents in memory. */
void* pData;
size_t sizeInBytes;
result = ma_vfs_open_and_read_file_ex(pResourceManager->config.pVFS, pFilePath, &pData, &sizeInBytes, &pResourceManager->config.allocationCallbacks, MA_ALLOCATION_TYPE_ENCODED_BUFFER);
if (result == MA_SUCCESS) {
pDataBuffer->pNode->data.encoded.pData = pData;
pDataBuffer->pNode->data.encoded.sizeInBytes = sizeInBytes;
}
} else {
/* Synchronous. Do everything here. */
if (pDataBuffer->pNode->data.type == ma_resource_manager_data_buffer_encoding_encoded) {
/* No decoding. Just store the file contents in memory. */
void* pData;
size_t sizeInBytes;
result = ma_vfs_open_and_read_file_ex(pResourceManager->config.pVFS, pFilePath, &pData, &sizeInBytes, &pResourceManager->config.allocationCallbacks, MA_ALLOCATION_TYPE_ENCODED_BUFFER);
if (result == MA_SUCCESS) {
pDataBuffer->pNode->data.encoded.pData = pData;
pDataBuffer->pNode->data.encoded.sizeInBytes = sizeInBytes;
}
} else {
/* Decoding. */
ma_decoder decoder;
} else {
/* Decoding. */
ma_decoder decoder;
result = ma_resource_manager__init_decoder(pResourceManager, pFilePath, &decoder);
if (result == MA_SUCCESS) {
ma_uint64 totalFrameCount;
ma_uint64 dataSizeInBytes;
void* pData = NULL;
pDataBuffer->pNode->data.decoded.format = decoder.outputFormat;
pDataBuffer->pNode->data.decoded.channels = decoder.outputChannels;
pDataBuffer->pNode->data.decoded.sampleRate = decoder.outputSampleRate;
totalFrameCount = ma_decoder_get_length_in_pcm_frames(&decoder);
if (totalFrameCount > 0) {
/* It's a known length. We can use an optimized allocation strategy in this case. */
dataSizeInBytes = totalFrameCount * ma_get_bytes_per_frame(decoder.outputFormat, decoder.outputChannels);
if (dataSizeInBytes <= MA_SIZE_MAX) {
pData = ma__malloc_from_callbacks((size_t)dataSizeInBytes, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
if (pData != NULL) {
totalFrameCount = ma_decoder_read_pcm_frames(&decoder, pData, totalFrameCount);
} else {
result = MA_OUT_OF_MEMORY;
}
result = ma_resource_manager__init_decoder(pResourceManager, pFilePath, &decoder);
if (result == MA_SUCCESS) {
ma_uint64 totalFrameCount;
ma_uint64 dataSizeInBytes;
void* pData = NULL;
pDataBuffer->pNode->data.decoded.format = decoder.outputFormat;
pDataBuffer->pNode->data.decoded.channels = decoder.outputChannels;
pDataBuffer->pNode->data.decoded.sampleRate = decoder.outputSampleRate;
totalFrameCount = ma_decoder_get_length_in_pcm_frames(&decoder);
if (totalFrameCount > 0) {
/* It's a known length. We can use an optimized allocation strategy in this case. */
dataSizeInBytes = totalFrameCount * ma_get_bytes_per_frame(decoder.outputFormat, decoder.outputChannels);
if (dataSizeInBytes <= MA_SIZE_MAX) {
pData = ma__malloc_from_callbacks((size_t)dataSizeInBytes, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
if (pData != NULL) {
totalFrameCount = ma_decoder_read_pcm_frames(&decoder, pData, totalFrameCount);
} else {
result = MA_TOO_BIG;
result = MA_OUT_OF_MEMORY;
}
} else {
/* It's an unknown length. We need to dynamically expand the buffer as we decode. To start with we allocate space for one page. We'll then double it as we need more space. */
ma_uint64 bytesPerFrame;
ma_uint64 pageSizeInFrames;
ma_uint64 dataSizeInFrames;
result = MA_TOO_BIG;
}
} else {
/* It's an unknown length. We need to dynamically expand the buffer as we decode. To start with we allocate space for one page. We'll then double it as we need more space. */
ma_uint64 bytesPerFrame;
ma_uint64 pageSizeInFrames;
ma_uint64 dataSizeInFrames;
bytesPerFrame = ma_get_bytes_per_frame(decoder.outputFormat, decoder.outputChannels);
pageSizeInFrames = MA_RESOURCE_MANAGER_PAGE_SIZE_IN_MILLISECONDS * (decoder.outputSampleRate/1000);
dataSizeInFrames = 0;
/* Keep loading, page-by-page. */
for (;;) {
ma_uint64 framesRead;
/* Expand the buffer if need be. */
if (totalFrameCount + pageSizeInFrames > dataSizeInFrames) {
ma_uint64 oldDataSizeInFrames;
ma_uint64 oldDataSizeInBytes;
ma_uint64 newDataSizeInFrames;
ma_uint64 newDataSizeInBytes;
void* pNewData;
oldDataSizeInFrames = (dataSizeInFrames);
newDataSizeInFrames = (dataSizeInFrames == 0) ? pageSizeInFrames : dataSizeInFrames * 2;
oldDataSizeInBytes = bytesPerFrame * oldDataSizeInFrames;
newDataSizeInBytes = bytesPerFrame * newDataSizeInFrames;
if (newDataSizeInBytes > MA_SIZE_MAX) {
result = MA_TOO_BIG;
break;
}
pNewData = ma__realloc_from_callbacks(pData, (size_t)newDataSizeInBytes, (size_t)oldDataSizeInBytes, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
if (pNewData == NULL) {
ma__free_from_callbacks(pData, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
result = MA_OUT_OF_MEMORY;
break;
}
pData = pNewData;
dataSizeInFrames = newDataSizeInFrames;
bytesPerFrame = ma_get_bytes_per_frame(decoder.outputFormat, decoder.outputChannels);
pageSizeInFrames = MA_RESOURCE_MANAGER_PAGE_SIZE_IN_MILLISECONDS * (decoder.outputSampleRate/1000);
dataSizeInFrames = 0;
/* Keep loading, page-by-page. */
for (;;) {
ma_uint64 framesRead;
/* Expand the buffer if need be. */
if (totalFrameCount + pageSizeInFrames > dataSizeInFrames) {
ma_uint64 oldDataSizeInFrames;
ma_uint64 oldDataSizeInBytes;
ma_uint64 newDataSizeInFrames;
ma_uint64 newDataSizeInBytes;
void* pNewData;
oldDataSizeInFrames = (dataSizeInFrames);
newDataSizeInFrames = (dataSizeInFrames == 0) ? pageSizeInFrames : dataSizeInFrames * 2;
oldDataSizeInBytes = bytesPerFrame * oldDataSizeInFrames;
newDataSizeInBytes = bytesPerFrame * newDataSizeInFrames;
if (newDataSizeInBytes > MA_SIZE_MAX) {
result = MA_TOO_BIG;
break;
}
framesRead = ma_decoder_read_pcm_frames(&decoder, ma_offset_ptr(pData, bytesPerFrame * totalFrameCount), pageSizeInFrames);
totalFrameCount += framesRead;
if (framesRead < pageSizeInFrames) {
/* We've reached the end. As we were loading we were doubling the size of the buffer each time we needed more memory. Let's try reducing this by doing a final realloc(). */
size_t newDataSizeInBytes = (size_t)(totalFrameCount * bytesPerFrame);
size_t oldDataSizeInBytes = (size_t)(dataSizeInFrames * bytesPerFrame);
void* pNewData = ma__realloc_from_callbacks(pData, newDataSizeInBytes, oldDataSizeInBytes, &pResourceManager->config.allocationCallbacks);
if (pNewData != NULL) {
pData = pNewData;
}
/* We're done, so get out of the loop. */
pNewData = ma__realloc_from_callbacks(pData, (size_t)newDataSizeInBytes, (size_t)oldDataSizeInBytes, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
if (pNewData == NULL) {
ma__free_from_callbacks(pData, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_DECODED_BUFFER*/);
result = MA_OUT_OF_MEMORY;
break;
}
pData = pNewData;
dataSizeInFrames = newDataSizeInFrames;
}
}
if (result == MA_SUCCESS) {
pDataBuffer->pNode->data.decoded.pData = pData;
pDataBuffer->pNode->data.decoded.frameCount = totalFrameCount;
pDataBuffer->pNode->data.decoded.decodedFrameCount = totalFrameCount; /* We've decoded everything. */
} else {
pDataBuffer->pNode->data.decoded.pData = NULL;
pDataBuffer->pNode->data.decoded.frameCount = 0;
pDataBuffer->pNode->data.decoded.decodedFrameCount = 0;
framesRead = ma_decoder_read_pcm_frames(&decoder, ma_offset_ptr(pData, bytesPerFrame * totalFrameCount), pageSizeInFrames);
totalFrameCount += framesRead;
if (framesRead < pageSizeInFrames) {
/* We've reached the end. As we were loading we were doubling the size of the buffer each time we needed more memory. Let's try reducing this by doing a final realloc(). */
size_t newDataSizeInBytes = (size_t)(totalFrameCount * bytesPerFrame);
size_t oldDataSizeInBytes = (size_t)(dataSizeInFrames * bytesPerFrame);
void* pNewData = ma__realloc_from_callbacks(pData, newDataSizeInBytes, oldDataSizeInBytes, &pResourceManager->config.allocationCallbacks);
if (pNewData != NULL) {
pData = pNewData;
}
/* We're done, so get out of the loop. */
break;
}
}
}
ma_decoder_uninit(&decoder);
if (result == MA_SUCCESS) {
pDataBuffer->pNode->data.decoded.pData = pData;
pDataBuffer->pNode->data.decoded.frameCount = totalFrameCount;
pDataBuffer->pNode->data.decoded.decodedFrameCount = totalFrameCount; /* We've decoded everything. */
} else {
pDataBuffer->pNode->data.decoded.pData = NULL;
pDataBuffer->pNode->data.decoded.frameCount = 0;
pDataBuffer->pNode->data.decoded.decodedFrameCount = 0;
}
}
/* When loading synchronously we need to initialize the connector straight away. */
if (result == MA_SUCCESS) {
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
ma_decoder_uninit(&decoder);
}
}
pDataBuffer->pNode->result = result;
/* When loading synchronously we need to initialize the connector straight away. */
if (result == MA_SUCCESS) {
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer);
}
/* If we failed to initialize make sure we fire the event and free memory. */
if (result != MA_SUCCESS) {
if (pNotification != NULL) {
ma_async_notification_signal(pNotification);
}
pDataBuffer->pNode->result = result;
}
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
ma__free_from_callbacks(pDataBuffer->pNode, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/);
return result;
/* If we failed to initialize make sure we fire the event and free memory. */
if (result != MA_SUCCESS) {
if (pNotification != NULL) {
ma_async_notification_signal(pNotification);
}
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
ma__free_from_callbacks(pDataBuffer->pNode, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/);
return result;
}
/* It's not really necessary, but for completeness we'll want to fire the event if we have one in synchronous mode. */
......@@ -2347,7 +2329,7 @@ MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pReso
/* At this point we can now enter the critical section. */
ma_mutex_lock(&pResourceManager->dataBufferLock);
{
result = ma_resource_manager_data_buffer_init_nolock(pResourceManager, pFilePath, hashedName32, flags, NULL, pNotification, pDataBuffer);
result = ma_resource_manager_data_buffer_init_nolock(pResourceManager, pFilePath, hashedName32, flags, pNotification, pDataBuffer);
}
ma_mutex_unlock(&pResourceManager->dataBufferLock);
......
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