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