xref: /haiku/src/kits/media/Buffer.cpp (revision 82a8a20999118b748396cf16a33c47c3b0c0222d)
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 #include <MediaDefs.h>
31 #include <Buffer.h>
32 #include "SharedBufferList.h"
33 #include "debug.h"
34 #include "DataExchange.h"
35 
36 namespace BPrivate { namespace media {
37 	extern team_id team;
38 } } // BPrivate::media
39 using namespace BPrivate::media;
40 
41 /*************************************************************
42  * public struct buffer_clone_info
43  *************************************************************/
44 
45 buffer_clone_info::buffer_clone_info()
46 {
47 	CALLED();
48 	buffer	= 0;
49 	area 	= 0;
50 	offset 	= 0;
51 	size 	= 0;
52 	flags 	= 0;
53 }
54 
55 
56 buffer_clone_info::~buffer_clone_info()
57 {
58 	CALLED();
59 }
60 
61 /*************************************************************
62  * public BBuffer
63  *************************************************************/
64 
65 void *
66 BBuffer::Data()
67 {
68 	CALLED();
69 	return fData;
70 }
71 
72 
73 size_t
74 BBuffer::SizeAvailable()
75 {
76 	CALLED();
77 	return fSize;
78 }
79 
80 
81 size_t
82 BBuffer::SizeUsed()
83 {
84 	CALLED();
85 	return fMediaHeader.size_used;
86 }
87 
88 
89 void
90 BBuffer::SetSizeUsed(size_t size_used)
91 {
92 	CALLED();
93 	fMediaHeader.size_used = min_c(size_used, fSize);
94 }
95 
96 
97 uint32
98 BBuffer::Flags()
99 {
100 	CALLED();
101 	return fFlags;
102 }
103 
104 
105 void
106 BBuffer::Recycle()
107 {
108 	CALLED();
109 	if (fBufferList == NULL)
110 		return;
111 	fBufferList->RecycleBuffer(this);
112 }
113 
114 
115 buffer_clone_info
116 BBuffer::CloneInfo() const
117 {
118 	CALLED();
119 	buffer_clone_info info;
120 
121 	info.buffer	= fBufferID;
122 	info.area	= fArea;
123 	info.offset	= fOffset;
124 	info.size	= fSize;
125 	info.flags	= fFlags;
126 
127 	return info;
128 }
129 
130 
131 media_buffer_id
132 BBuffer::ID()
133 {
134 	CALLED();
135 	return fMediaHeader.buffer;
136 	//return fBufferID;
137 }
138 
139 
140 media_type
141 BBuffer::Type()
142 {
143 	CALLED();
144 	return fMediaHeader.type;
145 }
146 
147 
148 media_header *
149 BBuffer::Header()
150 {
151 	CALLED();
152 	return &fMediaHeader;
153 }
154 
155 
156 media_audio_header *
157 BBuffer::AudioHeader()
158 {
159 	CALLED();
160 	return &fMediaHeader.u.raw_audio;
161 }
162 
163 
164 media_video_header *
165 BBuffer::VideoHeader()
166 {
167 	CALLED();
168 	return &fMediaHeader.u.raw_video;
169 }
170 
171 
172 size_t
173 BBuffer::Size()
174 {
175 	CALLED();
176 	return SizeAvailable();
177 }
178 
179 /*************************************************************
180  * private BBuffer
181  *************************************************************/
182 
183 /* explicit */
184 BBuffer::BBuffer(const buffer_clone_info & info) :
185 	fBufferList(0), // must be 0 if not correct initialized
186 	fData(0), // must be 0 if not correct initialized
187 	fSize(0), // should be 0 if not correct initialized
188 	fBufferID(0) // must be 0 if not registered
189 {
190 	CALLED();
191 
192 	// special case for BSmallBuffer
193 	if (info.area == 0 && info.buffer == 0)
194 		return;
195 
196 	// ask media_server to get the area_id of the shared buffer list
197 	server_get_shared_buffer_area_request area_request;
198 	server_get_shared_buffer_area_reply area_reply;
199 	if (QueryServer(SERVER_GET_SHARED_BUFFER_AREA, &area_request, sizeof(area_request), &area_reply, sizeof(area_reply)) != B_OK) {
200 		ERROR("BBuffer::BBuffer: SERVER_GET_SHARED_BUFFER_AREA failed\n");
201 		return;
202 	}
203 
204 	ASSERT(area_reply.area > 0);
205 
206 	fBufferList = _shared_buffer_list::Clone(area_reply.area);
207 	if (fBufferList == NULL) {
208 		ERROR("BBuffer::BBuffer: _shared_buffer_list::Clone() failed\n");
209 		return;
210 	}
211 
212 	server_register_buffer_request request;
213 	server_register_buffer_reply reply;
214 
215 	request.team = team;
216 	request.info = info;
217 
218 	// ask media_server to register this buffer,
219 	// either identified by "buffer" or by area information.
220 	// media_server either has a copy of the area identified
221 	// by "buffer", or creates a new area.
222 	// the information and the area is cached by the media_server
223 	// until the last buffer has been unregistered
224 	// the area_id of the cached area is passed back to us, and we clone it.
225 
226 	if (QueryServer(SERVER_REGISTER_BUFFER, &request, sizeof(request), &reply, sizeof(reply)) != B_OK) {
227 		ERROR("BBuffer::BBuffer: failed to register buffer with 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 	// the response from media server contains enough information
236 	// to clone the memory for this buffer
237 	fBufferID = reply.info.buffer;
238 	fSize = reply.info.size;
239 	fFlags = reply.info.flags;
240 	fOffset = reply.info.offset;
241 
242 	fArea = clone_area("a cloned BBuffer", &fData, B_ANY_ADDRESS,
243 		B_READ_AREA | B_WRITE_AREA, reply.info.area);
244 	if (fArea <= B_OK) {
245 		// XXX should unregister buffer here
246 		ERROR("BBuffer::BBuffer: buffer cloning failed\n");
247 		fData = 0;
248 		return;
249 	}
250 
251 	fData = (char *)fData + fOffset;
252 	fMediaHeader.size_used = 0;
253 	fMediaHeader.buffer = fBufferID;
254 }
255 
256 
257 BBuffer::~BBuffer()
258 {
259 	CALLED();
260 	// unmap the BufferList
261 	if (fBufferList != NULL) {
262 		fBufferList->Unmap();
263 	}
264 	// unmap the Data
265 	if (fData != NULL) {
266 
267 		delete_area(fArea);
268 
269 		// ask media_server to unregister the buffer
270 		// when the last clone of this buffer is gone,
271 		// media_server will also remove it's cached area
272 		server_unregister_buffer_command cmd;
273 		cmd.team = team;
274 		cmd.bufferid = fBufferID;
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 	fMediaHeader = *header;
285 
286 //  XXX why can't we do this without crash? what's wrong?
287 //	fMediaHeader.buffer = fBufferID;
288 }
289 
290 
291 /*************************************************************
292  * public BSmallBuffer
293  *************************************************************/
294 
295 static const buffer_clone_info info;
296 BSmallBuffer::BSmallBuffer()
297 	: BBuffer(info)
298 {
299 	UNIMPLEMENTED();
300 	debugger("BSmallBuffer::BSmallBuffer called\n");
301 }
302 
303 
304 size_t
305 BSmallBuffer::SmallBufferSizeLimit()
306 {
307 	CALLED();
308 	return 64;
309 }
310 
311 
312