1 /* 2 * Copyright 2014-2016, Dario Casalinuovo 3 * Copyright 1999, Be Incorporated 4 * All Rights Reserved. 5 * This file may be used under the terms of the Be Sample Code License. 6 */ 7 8 9 #include "MediaRecorderNode.h" 10 11 #include <Buffer.h> 12 #include <scheduler.h> 13 #include <MediaRoster.h> 14 #include <MediaRosterEx.h> 15 #include <TimedEventQueue.h> 16 #include <TimeSource.h> 17 18 #include "MediaDebug.h" 19 20 21 BMediaRecorderNode::BMediaRecorderNode(const char* name, 22 BMediaRecorder* recorder, media_type type) 23 : 24 BMediaNode(name), 25 BMediaEventLooper(), 26 BBufferConsumer(type), 27 fRecorder(recorder), 28 fConnectMode(true) 29 { 30 CALLED(); 31 32 fInput.node = Node(); 33 fInput.destination.id = 1; 34 fInput.destination.port = ControlPort(); 35 36 fName.SetTo(name); 37 38 BString str(name); 39 str << " Input"; 40 strcpy(fInput.name, str.String()); 41 } 42 43 44 BMediaRecorderNode::~BMediaRecorderNode() 45 { 46 CALLED(); 47 } 48 49 50 BMediaAddOn* 51 BMediaRecorderNode::AddOn(int32* id) const 52 { 53 CALLED(); 54 55 if (id) 56 *id = -1; 57 58 return NULL; 59 } 60 61 62 void 63 BMediaRecorderNode::NodeRegistered() 64 { 65 CALLED(); 66 Run(); 67 } 68 69 70 void 71 BMediaRecorderNode::SetRunMode(run_mode mode) 72 { 73 CALLED(); 74 75 int32 priority; 76 77 if (mode == BMediaNode::B_OFFLINE) 78 priority = B_OFFLINE_PROCESSING; 79 else { 80 switch(ConsumerType()) { 81 case B_MEDIA_RAW_AUDIO: 82 case B_MEDIA_ENCODED_AUDIO: 83 priority = B_AUDIO_RECORDING; 84 break; 85 86 case B_MEDIA_RAW_VIDEO: 87 case B_MEDIA_ENCODED_VIDEO: 88 priority = B_VIDEO_RECORDING; 89 break; 90 91 default: 92 priority = B_DEFAULT_MEDIA_PRIORITY; 93 } 94 } 95 96 SetPriority(suggest_thread_priority(priority)); 97 98 BMediaNode::SetRunMode(mode); 99 } 100 101 102 void 103 BMediaRecorderNode::SetAcceptedFormat(const media_format& format) 104 { 105 CALLED(); 106 107 fInput.format = format; 108 fOKFormat = format; 109 } 110 111 112 const media_format& 113 BMediaRecorderNode::AcceptedFormat() const 114 { 115 CALLED(); 116 117 return fInput.format; 118 } 119 120 121 void 122 BMediaRecorderNode::GetInput(media_input* outInput) 123 { 124 CALLED(); 125 126 fInput.node = Node(); 127 *outInput = fInput; 128 } 129 130 131 void 132 BMediaRecorderNode::SetDataEnabled(bool enabled) 133 { 134 CALLED(); 135 136 int32 tag; 137 138 SetOutputEnabled(fInput.source, 139 fInput.destination, enabled, NULL, &tag); 140 } 141 142 143 void 144 BMediaRecorderNode::ActivateInternalConnect(bool connectMode) 145 { 146 fConnectMode = connectMode; 147 } 148 149 150 void 151 BMediaRecorderNode::HandleEvent(const media_timed_event* event, 152 bigtime_t lateness, bool realTimeEvent) 153 { 154 CALLED(); 155 156 // we ignore them all! 157 } 158 159 160 void 161 BMediaRecorderNode::Start(bigtime_t performanceTime) 162 { 163 CALLED(); 164 165 if (fRecorder->fNotifyHook) 166 (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie, 167 BMediaRecorder::B_WILL_START, performanceTime); 168 169 fRecorder->fRunning = true; 170 } 171 172 173 void 174 BMediaRecorderNode::Stop(bigtime_t performanceTime, bool immediate) 175 { 176 CALLED(); 177 178 if (fRecorder->fNotifyHook) 179 (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie, 180 BMediaRecorder::B_WILL_STOP, performanceTime, immediate); 181 182 fRecorder->fRunning = false; 183 } 184 185 186 void 187 BMediaRecorderNode::Seek(bigtime_t mediaTime, bigtime_t performanceTime) 188 { 189 CALLED(); 190 191 if (fRecorder->fNotifyHook) 192 (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie, 193 BMediaRecorder::B_WILL_SEEK, performanceTime, mediaTime); 194 } 195 196 197 void 198 BMediaRecorderNode::TimeWarp(bigtime_t realTime, bigtime_t performanceTime) 199 { 200 CALLED(); 201 202 // Since buffers will come pre-time-stamped, we only need to look 203 // at them, so we can ignore the time warp as a consumer. 204 if (fRecorder->fNotifyHook) 205 (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie, 206 BMediaRecorder::B_WILL_TIMEWARP, realTime, performanceTime); 207 } 208 209 210 status_t 211 BMediaRecorderNode::HandleMessage(int32 message, 212 const void* data, size_t size) 213 { 214 CALLED(); 215 216 if (BBufferConsumer::HandleMessage(message, data, size) < 0 217 && BMediaEventLooper::HandleMessage(message, data, size) < 0 218 && BMediaNode::HandleMessage(message, data, size) < 0) { 219 HandleBadMessage(message, data, size); 220 return B_ERROR; 221 } 222 return B_OK; 223 } 224 225 226 status_t 227 BMediaRecorderNode::AcceptFormat(const media_destination& dest, 228 media_format* format) 229 { 230 CALLED(); 231 232 if (format_is_compatible(*format, fOKFormat)) 233 return B_OK; 234 235 *format = fOKFormat; 236 237 return B_MEDIA_BAD_FORMAT; 238 } 239 240 241 status_t 242 BMediaRecorderNode::GetNextInput(int32* cookie, media_input* outInput) 243 { 244 CALLED(); 245 246 if (*cookie == 0) { 247 *cookie = -1; 248 *outInput = fInput; 249 return B_OK; 250 } 251 252 return B_BAD_INDEX; 253 } 254 255 256 void 257 BMediaRecorderNode::DisposeInputCookie(int32 cookie) 258 { 259 CALLED(); 260 } 261 262 263 void 264 BMediaRecorderNode::BufferReceived(BBuffer* buffer) 265 { 266 CALLED(); 267 268 fRecorder->BufferReceived(buffer->Data(), buffer->SizeUsed(), 269 *buffer->Header()); 270 271 buffer->Recycle(); 272 } 273 274 275 void 276 BMediaRecorderNode::ProducerDataStatus( 277 const media_destination& forWhom, int32 status, 278 bigtime_t performanceTime) 279 { 280 CALLED(); 281 } 282 283 284 status_t 285 BMediaRecorderNode::GetLatencyFor(const media_destination& forWhom, 286 bigtime_t* outLatency, media_node_id* outTimesource) 287 { 288 CALLED(); 289 290 *outLatency = 0; 291 *outTimesource = TimeSource()->ID(); 292 293 return B_OK; 294 } 295 296 297 status_t 298 BMediaRecorderNode::Connected(const media_source &producer, 299 const media_destination &where, const media_format &withFormat, 300 media_input* outInput) 301 { 302 CALLED(); 303 304 fInput.source = producer; 305 fInput.format = withFormat; 306 *outInput = fInput; 307 308 if (fConnectMode == true) { 309 // This is a workaround needed for us to get the node 310 // so that our owner class can do it's operations. 311 media_node node; 312 BMediaRosterEx* roster = MediaRosterEx(BMediaRoster::CurrentRoster()); 313 if (roster->GetNodeFor(roster->NodeIDFor(producer.port), &node) != B_OK) 314 return B_MEDIA_BAD_NODE; 315 316 fRecorder->fOutputNode = node; 317 fRecorder->fReleaseOutputNode = true; 318 } 319 fRecorder->SetUpConnection(producer); 320 fRecorder->fConnected = true; 321 322 return B_OK; 323 } 324 325 326 void 327 BMediaRecorderNode::Disconnected(const media_source& producer, 328 const media_destination& where) 329 { 330 CALLED(); 331 332 fInput.source = media_source::null; 333 // Reset the connection mode 334 fConnectMode = true; 335 fRecorder->fConnected = false; 336 fInput.format = fOKFormat; 337 } 338 339 340 status_t 341 BMediaRecorderNode::FormatChanged(const media_source& producer, 342 const media_destination& consumer, int32 tag, 343 const media_format& format) 344 { 345 CALLED(); 346 347 if (!format_is_compatible(format, fOKFormat)) 348 return B_MEDIA_BAD_FORMAT; 349 350 fInput.format = format; 351 352 return B_OK; 353 } 354