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