xref: /haiku/src/kits/media/BufferCache.cpp (revision 899e0ef82b5624ace2ccfa5f5a58c8ebee54aaef)
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