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