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