xref: /haiku/src/kits/media/Buffer.cpp (revision 85892ec52f476b254d75e2bb2e6560e72faa567c)
1 /*
2  * Copyright 2009, Axel Dörfler, axeld@pinc-software.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 /*
7  * Copyright (c) 2002, 2003 Marcus Overhagen <Marcus@Overhagen.de>
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining
10  * a copy of this software and associated documentation files or portions
11  * thereof (the "Software"), to deal in the Software without restriction,
12  * including without limitation the rights to use, copy, modify, merge,
13  * publish, distribute, sublicense, and/or sell copies of the Software,
14  * and to permit persons to whom the Software is furnished to do so, subject
15  * to the following conditions:
16  *
17  *  * Redistributions of source code must retain the above copyright notice,
18  *    this list of conditions and the following disclaimer.
19  *
20  *  * Redistributions in binary form must reproduce the above copyright notice
21  *    in the  binary, as well as this list of conditions and the following
22  *    disclaimer in the documentation and/or other materials provided with
23  *    the distribution.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31  * THE SOFTWARE.
32  */
33 
34 
35 #include <Buffer.h>
36 
37 #include <AppMisc.h>
38 #include <MediaDefs.h>
39 
40 #include "debug.h"
41 #include "DataExchange.h"
42 #include "SharedBufferList.h"
43 
44 
45 using namespace BPrivate::media;
46 
47 
48 //	#pragma mark - buffer_clone_info
49 
50 
51 buffer_clone_info::buffer_clone_info()
52 {
53 	CALLED();
54 	buffer = 0;
55 	area = 0;
56 	offset = 0;
57 	size = 0;
58 	flags = 0;
59 }
60 
61 
62 buffer_clone_info::~buffer_clone_info()
63 {
64 	CALLED();
65 }
66 
67 
68 //	#pragma mark - public BBuffer
69 
70 
71 void*
72 BBuffer::Data()
73 {
74 	CALLED();
75 	return fData;
76 }
77 
78 
79 size_t
80 BBuffer::SizeAvailable()
81 {
82 	CALLED();
83 	return fSize;
84 }
85 
86 
87 size_t
88 BBuffer::SizeUsed()
89 {
90 	CALLED();
91 	return fMediaHeader.size_used;
92 }
93 
94 
95 void
96 BBuffer::SetSizeUsed(size_t size_used)
97 {
98 	CALLED();
99 	fMediaHeader.size_used = min_c(size_used, fSize);
100 }
101 
102 
103 uint32
104 BBuffer::Flags()
105 {
106 	CALLED();
107 	return fFlags;
108 }
109 
110 
111 void
112 BBuffer::Recycle()
113 {
114 	CALLED();
115 	if (fBufferList == NULL)
116 		return;
117 	fBufferList->RecycleBuffer(this);
118 }
119 
120 
121 buffer_clone_info
122 BBuffer::CloneInfo() const
123 {
124 	CALLED();
125 	buffer_clone_info info;
126 
127 	info.buffer = fMediaHeader.buffer;
128 	info.area = fArea;
129 	info.offset = fOffset;
130 	info.size = fSize;
131 	info.flags = fFlags;
132 
133 	return info;
134 }
135 
136 
137 media_buffer_id
138 BBuffer::ID()
139 {
140 	CALLED();
141 	return fMediaHeader.buffer;
142 }
143 
144 
145 media_type
146 BBuffer::Type()
147 {
148 	CALLED();
149 	return fMediaHeader.type;
150 }
151 
152 
153 media_header*
154 BBuffer::Header()
155 {
156 	CALLED();
157 	return &fMediaHeader;
158 }
159 
160 
161 media_audio_header*
162 BBuffer::AudioHeader()
163 {
164 	CALLED();
165 	return &fMediaHeader.u.raw_audio;
166 }
167 
168 
169 media_video_header*
170 BBuffer::VideoHeader()
171 {
172 	CALLED();
173 	return &fMediaHeader.u.raw_video;
174 }
175 
176 
177 size_t
178 BBuffer::Size()
179 {
180 	CALLED();
181 	return SizeAvailable();
182 }
183 
184 
185 // #pragma mark - private BBuffer
186 
187 
188 BBuffer::BBuffer(const buffer_clone_info& info)
189 	:
190 	fBufferList(NULL),
191 	fArea(-1),
192 	fData(NULL),
193 	fSize(0)
194 {
195 	CALLED();
196 
197 	// Must be -1 if not registered
198 	fMediaHeader.buffer = -1;
199 
200 	// special case for BSmallBuffer
201 	if (info.area == 0 && info.buffer == 0)
202 		return;
203 
204 	fBufferList = BPrivate::SharedBufferList::Get();
205 	if (fBufferList == NULL) {
206 		ERROR("BBuffer::BBuffer: BPrivate::SharedBufferList::Get() failed\n");
207 		return;
208 	}
209 
210 	server_register_buffer_request request;
211 	server_register_buffer_reply reply;
212 
213 	request.team = BPrivate::current_team();
214 	request.info = info;
215 
216 	// ask media_server to register this buffer,
217 	// either identified by "buffer" or by area information.
218 	// media_server either has a copy of the area identified
219 	// by "buffer", or creates a new area.
220 	// the information and the area is cached by the media_server
221 	// until the last buffer has been unregistered
222 	// the area_id of the cached area is passed back to us, and we clone it.
223 
224 	if (QueryServer(SERVER_REGISTER_BUFFER, &request, sizeof(request), &reply,
225 			sizeof(reply)) != B_OK) {
226 		ERROR("BBuffer::BBuffer: failed to register buffer with "
227 			"media_server\n");
228 		return;
229 	}
230 
231 	ASSERT(reply.info.buffer > 0);
232 	ASSERT(reply.info.area > 0);
233 	ASSERT(reply.info.size > 0);
234 
235 	fArea = clone_area("a cloned BBuffer", &fData, B_ANY_ADDRESS,
236 		B_READ_AREA | B_WRITE_AREA, reply.info.area);
237 	if (fArea < 0) {
238 		ERROR("BBuffer::BBuffer: buffer cloning failed"
239 			", unregistering buffer\n");
240 		server_unregister_buffer_command cmd;
241 		cmd.team = BPrivate::current_team();
242 		cmd.buffer_id = reply.info.buffer;
243 		SendToServer(SERVER_UNREGISTER_BUFFER, &cmd, sizeof(cmd));
244 		return;
245 	}
246 
247 	// the response from media server contains enough information
248 	// to clone the memory for this buffer
249 	fSize = reply.info.size;
250 	fFlags = reply.info.flags;
251 	fOffset = reply.info.offset;
252 	fMediaHeader.size_used = 0;
253 	fMediaHeader.buffer = reply.info.buffer;
254 	fData = (char*)fData + fOffset;
255 }
256 
257 
258 BBuffer::~BBuffer()
259 {
260 	CALLED();
261 
262 	// unmap the BufferList
263 	if (fBufferList != NULL)
264 		fBufferList->Put();
265 
266 	// unmap the Data
267 	if (fData != NULL) {
268 		delete_area(fArea);
269 
270 		// Ask media_server to unregister the buffer when the last clone of
271 		// this buffer is gone, media_server will also remove its cached area.
272 		server_unregister_buffer_command cmd;
273 		cmd.team = BPrivate::current_team();
274 		cmd.buffer_id = fMediaHeader.buffer;
275 		SendToServer(SERVER_UNREGISTER_BUFFER, &cmd, sizeof(cmd));
276 	}
277 }
278 
279 
280 void
281 BBuffer::SetHeader(const media_header* header)
282 {
283 	CALLED();
284 	ASSERT(header->buffer == fMediaHeader.buffer);
285 	if (header->buffer != fMediaHeader.buffer)
286 		debugger("oops");
287 	fMediaHeader = *header;
288 }
289 
290 
291 // #pragma mark - public BSmallBuffer
292 
293 
294 static const buffer_clone_info sSmallBufferInfo;
295 
296 
297 BSmallBuffer::BSmallBuffer()
298 	:
299 	BBuffer(sSmallBufferInfo)
300 {
301 	UNIMPLEMENTED();
302 	debugger("BSmallBuffer::BSmallBuffer called\n");
303 }
304 
305 
306 size_t
307 BSmallBuffer::SmallBufferSizeLimit()
308 {
309 	CALLED();
310 	return 64;
311 }
312 
313 
314