From 201c2842bd4a85d24cd37e4119ba8c3b22b1a1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 6 Aug 2009 10:01:20 +0000 Subject: [PATCH] * The media server now clones each buffer area only once - before, you could only add a very limited amount of buffers part of the frame buffer, for example, as that one is usually a very large area. * This could prevent all sorts of media buffers to be cloned on certain conditions (and could also cause a MediaPlayer fallback to bitmap mode for no apparent reason). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32156 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/media/BufferManager.cpp | 45 +++++++++++++++++++++++++++-- src/servers/media/BufferManager.h | 3 +- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/servers/media/BufferManager.cpp b/src/servers/media/BufferManager.cpp index 89f6c3ad49..6dd3a59619 100644 --- a/src/servers/media/BufferManager.cpp +++ b/src/servers/media/BufferManager.cpp @@ -182,10 +182,32 @@ BufferManager::Dump() area_id BufferManager::_CloneArea(area_id area) { + clone_info* info; + if (fCloneInfoMap.Get(area, info)) { + // we have already cloned this particular area + TRACE("BufferManager::_CloneArea() area %ld has already been cloned " + "(id %ld)\n", area, info->clone); + + info->ref_count++; + return info->clone; + } + void* address; area_id clonedArea = clone_area("media_server cloned buffer", &address, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, area); - + + TRACE("BufferManager::_CloneArea() cloned area %ld, clone id %ld\n", + area, clonedArea); + + if (clonedArea >= 0) { + clone_info info; + info.clone = clonedArea; + info.ref_count = 1; + + fCloneInfoMap.Put(area, info); + fSourceInfoMap.Put(clonedArea, area); + } + return clonedArea; } @@ -193,5 +215,24 @@ BufferManager::_CloneArea(area_id area) void BufferManager::_ReleaseClonedArea(area_id clone) { - delete_area(clone); + area_id source = fSourceInfoMap.Get(clone); + + clone_info* info; + if (!fCloneInfoMap.Get(source, info)) { + ERROR("BufferManager::_ReleaseClonedArea(): could not find clone info " + "for id %ld (clone %ld)\n", source, clone); + return; + } + + if (--info->ref_count == 0) { + TRACE("BufferManager::_ReleaseClonedArea(): delete cloned area %ld " + "(source %ld)\n", clone, source); + + fSourceInfoMap.Remove(clone); + fCloneInfoMap.Remove(source); + delete_area(clone); + } else { + TRACE("BufferManager::_ReleaseClonedArea(): released cloned area %ld " + "(source %ld)\n", clone, source); + } } diff --git a/src/servers/media/BufferManager.h b/src/servers/media/BufferManager.h index 2b3e60950d..41a9ecfa25 100644 --- a/src/servers/media/BufferManager.h +++ b/src/servers/media/BufferManager.h @@ -44,7 +44,6 @@ private: private: struct clone_info { - area_id source; area_id clone; vint32 ref_count; }; @@ -98,6 +97,7 @@ private: typedef HashMap, buffer_info> BufferInfoMap; typedef HashMap, clone_info> CloneInfoMap; + typedef HashMap, area_id> SourceInfoMap; _shared_buffer_list* fSharedBufferList; area_id fSharedBufferListID; @@ -105,5 +105,6 @@ private: BLocker fLocker; BufferInfoMap fBufferInfoMap; CloneInfoMap fCloneInfoMap; + SourceInfoMap fSourceInfoMap; };