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