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