2 * Copyright 2015, Hamish Morrison <hamishm53@gmail.com>
3 * Copyright 2014-2016, Dario Casalinuovo
4 * Copyright 1999, Be Incorporated
6 * This file may be used under the terms of the Be Sample Code License.
10 #include <MediaRecorder.h>
12 #include <MediaAddOn.h>
13 #include <MediaRoster.h>
14 #include <TimeSource.h>
16 #include "MediaDebug.h"
17 #include "MediaRecorderNode.h"
20 BMediaRecorder::BMediaRecorder(const char* name
, media_type type
)
25 fReleaseOutputNode(false),
33 BMediaRoster::Roster(&fInitErr
);
35 if (fInitErr
== B_OK
) {
36 fNode
= new(std::nothrow
) BMediaRecorderNode(name
, this, type
);
38 fInitErr
= B_NO_MEMORY
;
40 fInitErr
= BMediaRoster::CurrentRoster()->RegisterNode(fNode
);
45 BMediaRecorder::~BMediaRecorder()
58 BMediaRecorder::InitCheck() const
67 BMediaRecorder::SetAcceptedFormat(const media_format
& format
)
71 fNode
->SetAcceptedFormat(format
);
76 BMediaRecorder::AcceptedFormat() const
80 return fNode
->AcceptedFormat();
85 BMediaRecorder::SetHooks(ProcessFunc recordFunc
, NotifyFunc notifyFunc
,
90 fRecordHook
= recordFunc
;
91 fNotifyHook
= notifyFunc
;
92 fBufferCookie
= cookie
;
99 BMediaRecorder::BufferReceived(void* buffer
, size_t size
,
100 const media_header
& header
)
105 (*fRecordHook
)(fBufferCookie
, header
.start_time
,
106 buffer
, size
, Format());
112 BMediaRecorder::Connect(const media_format
& format
)
116 if (fInitErr
!= B_OK
)
120 return B_MEDIA_ALREADY_CONNECTED
;
125 switch (format
.type
) {
126 // switch on format for default
127 case B_MEDIA_RAW_AUDIO
:
128 err
= BMediaRoster::Roster()->GetAudioMixer(&node
);
130 case B_MEDIA_RAW_VIDEO
:
131 case B_MEDIA_ENCODED_VIDEO
:
132 err
= BMediaRoster::Roster()->GetVideoInput(&node
);
136 return B_MEDIA_BAD_FORMAT
;
142 fReleaseOutputNode
= true;
144 err
= _Connect(node
, NULL
, format
);
147 BMediaRoster::Roster()->ReleaseNode(node
);
148 fReleaseOutputNode
= false;
156 BMediaRecorder::Connect(const dormant_node_info
& dormantNode
,
157 const media_format
& format
)
161 if (fInitErr
!= B_OK
)
165 return B_MEDIA_ALREADY_CONNECTED
;
168 status_t err
= BMediaRoster::Roster()->InstantiateDormantNode(dormantNode
,
169 &node
, B_FLAVOR_IS_GLOBAL
);
174 fReleaseOutputNode
= true;
176 err
= _Connect(node
, NULL
, format
);
179 BMediaRoster::Roster()->ReleaseNode(node
);
180 fReleaseOutputNode
= false;
188 BMediaRecorder::Connect(const media_node
& node
,
189 const media_output
* output
, const media_format
* format
)
193 if (fInitErr
!= B_OK
)
197 return B_MEDIA_ALREADY_CONNECTED
;
199 if (format
== NULL
&& output
!= NULL
)
200 format
= &output
->format
;
202 return _Connect(node
, output
, *format
);
207 BMediaRecorder::Disconnect()
213 if (fInitErr
!= B_OK
)
217 return B_MEDIA_NOT_CONNECTED
;
228 media_input ourInput
;
229 fNode
->GetInput(&ourInput
);
232 err
= BMediaRoster::CurrentRoster()->Disconnect(
233 fOutputNode
.node
, fOutputSource
,
234 fNode
->Node().node
, ourInput
.destination
);
236 if (fReleaseOutputNode
) {
237 BMediaRoster::Roster()->ReleaseNode(fOutputNode
);
238 fReleaseOutputNode
= false;
249 BMediaRecorder::Start(bool force
)
253 if (fInitErr
!= B_OK
)
257 return B_MEDIA_NOT_CONNECTED
;
259 if (fRunning
&& !force
)
268 if ((fOutputNode
.kind
& B_TIME_SOURCE
) != 0)
269 err
= BMediaRoster::CurrentRoster()->StartTimeSource(
270 fOutputNode
, BTimeSource::RealTime());
272 err
= BMediaRoster::CurrentRoster()->StartNode(
273 fOutputNode
, fNode
->TimeSource()->Now());
277 fNode
->SetDataEnabled(true);
287 BMediaRecorder::Stop(bool force
)
291 if (fInitErr
!= B_OK
)
294 if (!fRunning
&& !force
)
300 // should have the Node mute the output here
301 fNode
->SetDataEnabled(false);
305 return BMediaRoster::CurrentRoster()->StopNode(fNode
->Node(), 0);
310 BMediaRecorder::IsRunning() const
319 BMediaRecorder::IsConnected() const
328 BMediaRecorder::MediaSource() const
332 return fOutputSource
;
337 BMediaRecorder::MediaInput() const
341 media_input
* input
= NULL
;
342 fNode
->GetInput(input
);
348 BMediaRecorder::Format() const
352 return fNode
->AcceptedFormat();
357 BMediaRecorder::SetUpConnection(media_source outputSource
)
359 fOutputSource
= outputSource
;
361 // Perform the connection
362 media_node timeSource
;
363 if ((fOutputNode
.kind
& B_TIME_SOURCE
) != 0)
364 timeSource
= fOutputNode
;
366 BMediaRoster::Roster()->GetTimeSource(&timeSource
);
369 return BMediaRoster::Roster()->SetTimeSourceFor(fNode
->Node().node
,
375 BMediaRecorder::_Connect(const media_node
& node
,
376 const media_output
* output
, const media_format
& format
)
381 media_format ourFormat
= format
;
382 media_output ourOutput
;
387 fNode
->SetAcceptedFormat(ourFormat
);
391 // Figure out the output provided
392 if (output
!= NULL
) {
394 } else if (err
== B_OK
) {
395 media_output outputs
[10];
398 err
= BMediaRoster::Roster()->GetFreeOutputsFor(fOutputNode
,
399 outputs
, count
, &count
, ourFormat
.type
);
404 for (int i
= 0; i
< count
; i
++) {
405 if (format_is_compatible(outputs
[i
].format
, ourFormat
)) {
406 ourOutput
= outputs
[i
];
407 ourFormat
= outputs
[i
].format
;
413 if (ourOutput
.source
== media_source::null
)
414 return B_MEDIA_BAD_SOURCE
;
416 // Find our Node's free input
417 media_input ourInput
;
418 fNode
->GetInput(&ourInput
);
420 // Acknowledge the node that we already know
421 // who is our producer node.
422 fNode
->ActivateInternalConnect(false);
424 return BMediaRoster::CurrentRoster()->Connect(ourOutput
.source
,
425 ourInput
.destination
, &ourFormat
, &ourOutput
, &ourInput
,
426 BMediaRoster::B_CONNECT_MUTED
);
430 void BMediaRecorder::_ReservedMediaRecorder0() { }
431 void BMediaRecorder::_ReservedMediaRecorder1() { }
432 void BMediaRecorder::_ReservedMediaRecorder2() { }
433 void BMediaRecorder::_ReservedMediaRecorder3() { }
434 void BMediaRecorder::_ReservedMediaRecorder4() { }
435 void BMediaRecorder::_ReservedMediaRecorder5() { }
436 void BMediaRecorder::_ReservedMediaRecorder6() { }
437 void BMediaRecorder::_ReservedMediaRecorder7() { }