2 * Copyright 2015, Hamish Morrison <hamishm53@gmail.com>
3 * Copyright 2014, 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::SetHooks(ProcessFunc recordFunc
, NotifyFunc notifyFunc
,
81 fRecordHook
= recordFunc
;
82 fNotifyHook
= notifyFunc
;
83 fBufferCookie
= cookie
;
90 BMediaRecorder::BufferReceived(void* buffer
, size_t size
,
91 const media_header
& header
)
96 (*fRecordHook
)(fBufferCookie
, header
.start_time
,
97 buffer
, size
, Format());
103 BMediaRecorder::Connect(const media_format
& format
)
107 if (fInitErr
!= B_OK
)
111 return B_MEDIA_ALREADY_CONNECTED
;
116 switch (format
.type
) {
117 // switch on format for default
118 case B_MEDIA_RAW_AUDIO
:
119 err
= BMediaRoster::Roster()->GetAudioMixer(&node
);
121 case B_MEDIA_RAW_VIDEO
:
122 case B_MEDIA_ENCODED_VIDEO
:
123 err
= BMediaRoster::Roster()->GetVideoInput(&node
);
127 return B_MEDIA_BAD_FORMAT
;
133 fReleaseOutputNode
= true;
135 err
= _Connect(node
, NULL
, format
);
138 BMediaRoster::Roster()->ReleaseNode(node
);
139 fReleaseOutputNode
= false;
147 BMediaRecorder::Connect(const dormant_node_info
& dormantNode
,
148 const media_format
& format
)
152 if (fInitErr
!= B_OK
)
156 return B_MEDIA_ALREADY_CONNECTED
;
159 status_t err
= BMediaRoster::Roster()->InstantiateDormantNode(dormantNode
,
160 &node
, B_FLAVOR_IS_GLOBAL
);
165 fReleaseOutputNode
= true;
167 err
= _Connect(node
, NULL
, format
);
170 BMediaRoster::Roster()->ReleaseNode(node
);
171 fReleaseOutputNode
= false;
179 BMediaRecorder::Connect(const media_node
& node
,
180 const media_output
* output
, const media_format
* format
)
184 if (fInitErr
!= B_OK
)
188 return B_MEDIA_ALREADY_CONNECTED
;
190 if (format
== NULL
&& output
!= NULL
)
191 format
= &output
->format
;
193 return _Connect(node
, output
, *format
);
198 BMediaRecorder::Disconnect()
204 if (fInitErr
!= B_OK
)
208 return B_MEDIA_NOT_CONNECTED
;
220 err
= BMediaRoster::CurrentRoster()->Disconnect(
221 fOutputNode
.node
, fOutput
.source
,
222 fNode
->Node().node
, fInput
.destination
);
224 if (fReleaseOutputNode
) {
225 BMediaRoster::Roster()->ReleaseNode(fOutputNode
);
226 fReleaseOutputNode
= false;
237 BMediaRecorder::Start(bool force
)
241 if (fInitErr
!= B_OK
)
245 return B_MEDIA_NOT_CONNECTED
;
247 if (fRunning
&& !force
)
256 if ((fOutputNode
.kind
& B_TIME_SOURCE
) != 0)
257 err
= BMediaRoster::CurrentRoster()->StartTimeSource(
258 fOutputNode
, BTimeSource::RealTime());
260 err
= BMediaRoster::CurrentRoster()->StartNode(
261 fOutputNode
, fNode
->TimeSource()->Now());
265 fNode
->SetDataEnabled(true);
275 BMediaRecorder::Stop(bool force
)
279 if (fInitErr
!= B_OK
)
282 if (!fRunning
&& !force
)
288 // should have the Node mute the output here
289 fNode
->SetDataEnabled(false);
293 return BMediaRoster::CurrentRoster()->StopNode(fNode
->Node(), 0);
298 BMediaRecorder::IsRunning() const
307 BMediaRecorder::IsConnected() const
316 BMediaRecorder::MediaOutput() const
325 BMediaRecorder::MediaInput() const
334 BMediaRecorder::Format() const
338 return fOutput
.format
;
343 BMediaRecorder::_Connect(const media_node
& node
,
344 const media_output
* output
, const media_format
& format
)
349 media_format ourFormat
= format
;
350 media_output ourOutput
;
355 fNode
->SetAcceptedFormat(ourFormat
);
359 // figure out the output provided
360 if (output
!= NULL
) {
362 } else if (err
== B_OK
) {
363 media_output outputs
[10];
366 err
= BMediaRoster::Roster()->GetFreeOutputsFor(fOutputNode
,
367 outputs
, count
, &count
, ourFormat
.type
);
372 for (int i
= 0; i
< count
; i
++) {
373 if (format_is_compatible(outputs
[i
].format
, ourFormat
)) {
374 ourOutput
= outputs
[i
];
375 ourFormat
= outputs
[i
].format
;
381 if (ourOutput
.source
== media_source::null
)
382 return B_MEDIA_BAD_SOURCE
;
384 // find our Node's free input
385 media_input ourInput
;
386 err
= fNode
->GetInput(&ourInput
);
390 media_node timeSource
;
391 if ((node
.kind
& B_TIME_SOURCE
) != 0)
394 BMediaRoster::Roster()->GetTimeSource(&timeSource
);
397 err
= BMediaRoster::Roster()->SetTimeSourceFor(fNode
->Node().node
,
403 // start the recorder node (it's always running)
404 err
= BMediaRoster::CurrentRoster()->StartNode(fOutputNode
,
405 fNode
->TimeSource()->Now());
410 // perform the connection
414 err
= BMediaRoster::CurrentRoster()->Connect(fOutput
.source
,
415 fInput
.destination
, &ourFormat
, &fOutput
, &fInput
,
416 BMediaRoster::B_CONNECT_MUTED
);
426 void BMediaRecorder::_ReservedMediaRecorder0() { }
427 void BMediaRecorder::_ReservedMediaRecorder1() { }
428 void BMediaRecorder::_ReservedMediaRecorder2() { }
429 void BMediaRecorder::_ReservedMediaRecorder3() { }
430 void BMediaRecorder::_ReservedMediaRecorder4() { }
431 void BMediaRecorder::_ReservedMediaRecorder5() { }
432 void BMediaRecorder::_ReservedMediaRecorder6() { }
433 void BMediaRecorder::_ReservedMediaRecorder7() { }