1 /* 2 * Copyright 2019, Ryan Leavengood. 3 * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. 4 * Copyright 2002, Marcus Overhagen. All Rights Reserved. 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 //! A cache for BBuffers to be received by BBufferConsumer::BufferReceived(). 10 11 12 #include "BufferCache.h" 13 14 #include <Buffer.h> 15 16 #include "MediaDebug.h" 17 #include "MediaMisc.h" 18 #include "SharedBufferList.h" 19 20 21 namespace BPrivate { 22 23 24 BufferCache::BufferCache() 25 { 26 } 27 28 29 BufferCache::~BufferCache() 30 { 31 BufferMap::Iterator iterator = fMap.GetIterator(); 32 while (iterator.HasNext()) { 33 BufferMap::Entry entry = iterator.Next(); 34 delete entry.value.buffer; 35 } 36 } 37 38 39 BBuffer* 40 BufferCache::GetBuffer(media_buffer_id id, port_id port) 41 { 42 if (id <= 0) 43 return NULL; 44 45 buffer_cache_entry* existing; 46 if (fMap.Get(id, existing)) { 47 existing->buffer->fFlags |= BUFFER_TO_RECLAIM; 48 return existing->buffer; 49 } 50 51 buffer_clone_info info; 52 info.buffer = id; 53 BBuffer* buffer = new(std::nothrow) BBuffer(info); 54 if (buffer == NULL || buffer->ID() <= 0 55 || buffer->Data() == NULL) { 56 delete buffer; 57 return NULL; 58 } 59 60 if (buffer->ID() != id) 61 debugger("BufferCache::GetBuffer: IDs mismatch"); 62 63 buffer_cache_entry entry; 64 entry.buffer = buffer; 65 entry.port = port; 66 status_t error = fMap.Put(id, entry); 67 if (error != B_OK) { 68 delete buffer; 69 return NULL; 70 } 71 72 buffer->fFlags |= BUFFER_TO_RECLAIM; 73 return buffer; 74 } 75 76 77 void 78 BufferCache::FlushCacheForPort(port_id port) 79 { 80 BufferMap::Iterator iterator = fMap.GetIterator(); 81 while (iterator.HasNext()) { 82 BufferMap::Entry entry = iterator.Next(); 83 if (entry.value.port == port) { 84 BBuffer* buffer = entry.value.buffer; 85 bool isReclaimed = (buffer->fFlags & BUFFER_TO_RECLAIM) == 0; 86 if (isReclaimed && buffer->fBufferList != NULL) 87 isReclaimed = buffer->fBufferList->RemoveBuffer(buffer) == B_OK; 88 89 if (isReclaimed) 90 delete buffer; 91 else { 92 // mark the buffer for deletion 93 buffer->fFlags |= BUFFER_MARKED_FOR_DELETION; 94 } 95 // Then remove it from the map 96 fMap.Remove(iterator); 97 } 98 } 99 } 100 101 102 } // namespace BPrivate 103