1739fd34cSBarrett/*
2c1ad6121SDario Casalinuovo * Copyright 2014-2016, Dario Casalinuovo
3683cf2ffSHamish Morrison * Copyright 1999, Be Incorporated
4739fd34cSBarrett * All Rights Reserved.
5739fd34cSBarrett * This file may be used under the terms of the Be Sample Code License.
6739fd34cSBarrett */
7739fd34cSBarrett
8739fd34cSBarrett
9739fd34cSBarrett#include "MediaRecorderNode.h"
10739fd34cSBarrett
11739fd34cSBarrett#include <Buffer.h>
12739fd34cSBarrett#include <scheduler.h>
132a2e352aSDario Casalinuovo#include <MediaRoster.h>
142a2e352aSDario Casalinuovo#include <MediaRosterEx.h>
15739fd34cSBarrett#include <TimedEventQueue.h>
16739fd34cSBarrett#include <TimeSource.h>
17739fd34cSBarrett
183ef4b200SDario Casalinuovo#include "MediaDebug.h"
19739fd34cSBarrett
20739fd34cSBarrett
21739fd34cSBarrettBMediaRecorderNode::BMediaRecorderNode(const char* name,
22739fd34cSBarrett	BMediaRecorder* recorder, media_type type)
23739fd34cSBarrett	:
24739fd34cSBarrett	BMediaNode(name),
25739fd34cSBarrett	BMediaEventLooper(),
26739fd34cSBarrett	BBufferConsumer(type),
27c1ad6121SDario Casalinuovo	fRecorder(recorder),
28c1ad6121SDario Casalinuovo	fConnectMode(true)
29739fd34cSBarrett{
30739fd34cSBarrett	CALLED();
31739fd34cSBarrett
322a2e352aSDario Casalinuovo	fInput.node = Node();
33739fd34cSBarrett	fInput.destination.id = 1;
34739fd34cSBarrett	fInput.destination.port = ControlPort();
35739fd34cSBarrett
36739fd34cSBarrett	fName.SetTo(name);
37739fd34cSBarrett
38739fd34cSBarrett	BString str(name);
39739fd34cSBarrett	str << " Input";
40739fd34cSBarrett	strcpy(fInput.name, str.String());
41739fd34cSBarrett}
42739fd34cSBarrett
43739fd34cSBarrett
44739fd34cSBarrettBMediaRecorderNode::~BMediaRecorderNode()
45739fd34cSBarrett{
46739fd34cSBarrett	CALLED();
47739fd34cSBarrett}
48739fd34cSBarrett
49739fd34cSBarrett
50739fd34cSBarrettBMediaAddOn*
51739fd34cSBarrettBMediaRecorderNode::AddOn(int32* id) const
52739fd34cSBarrett{
53739fd34cSBarrett	CALLED();
54739fd34cSBarrett
55739fd34cSBarrett	if (id)
56739fd34cSBarrett		*id = -1;
57739fd34cSBarrett
58739fd34cSBarrett	return NULL;
59739fd34cSBarrett}
60739fd34cSBarrett
61739fd34cSBarrett
62739fd34cSBarrettvoid
63739fd34cSBarrettBMediaRecorderNode::NodeRegistered()
64739fd34cSBarrett{
65739fd34cSBarrett	CALLED();
66739fd34cSBarrett	Run();
67739fd34cSBarrett}
68739fd34cSBarrett
69739fd34cSBarrett
70739fd34cSBarrettvoid
71739fd34cSBarrettBMediaRecorderNode::SetRunMode(run_mode mode)
72739fd34cSBarrett{
73739fd34cSBarrett	CALLED();
74739fd34cSBarrett
75739fd34cSBarrett	int32 priority;
76739fd34cSBarrett
77739fd34cSBarrett	if (mode == BMediaNode::B_OFFLINE)
78739fd34cSBarrett		priority = B_OFFLINE_PROCESSING;
79739fd34cSBarrett	else {
80739fd34cSBarrett		switch(ConsumerType()) {
81739fd34cSBarrett			case B_MEDIA_RAW_AUDIO:
82739fd34cSBarrett			case B_MEDIA_ENCODED_AUDIO:
83739fd34cSBarrett				priority = B_AUDIO_RECORDING;
84739fd34cSBarrett				break;
85739fd34cSBarrett
86739fd34cSBarrett			case B_MEDIA_RAW_VIDEO:
87739fd34cSBarrett			case B_MEDIA_ENCODED_VIDEO:
88739fd34cSBarrett				priority = B_VIDEO_RECORDING;
89739fd34cSBarrett				break;
90739fd34cSBarrett
91739fd34cSBarrett			default:
92739fd34cSBarrett				priority = B_DEFAULT_MEDIA_PRIORITY;
93739fd34cSBarrett		}
94739fd34cSBarrett	}
95739fd34cSBarrett
96739fd34cSBarrett	SetPriority(suggest_thread_priority(priority));
97739fd34cSBarrett
98739fd34cSBarrett	BMediaNode::SetRunMode(mode);
99739fd34cSBarrett}
100739fd34cSBarrett
101739fd34cSBarrett
102739fd34cSBarrettvoid
103739fd34cSBarrettBMediaRecorderNode::SetAcceptedFormat(const media_format& format)
104739fd34cSBarrett{
105739fd34cSBarrett	CALLED();
106739fd34cSBarrett
107d23913f2SDario Casalinuovo	fInput.format = format;
108739fd34cSBarrett	fOKFormat = format;
109739fd34cSBarrett}
110739fd34cSBarrett
111739fd34cSBarrett
1122a2e352aSDario Casalinuovoconst media_format&
1132a2e352aSDario CasalinuovoBMediaRecorderNode::AcceptedFormat() const
1142a2e352aSDario Casalinuovo{
1152a2e352aSDario Casalinuovo	CALLED();
1162a2e352aSDario Casalinuovo
117d23913f2SDario Casalinuovo	return fInput.format;
1182a2e352aSDario Casalinuovo}
1192a2e352aSDario Casalinuovo
1202a2e352aSDario Casalinuovo
1212a2e352aSDario Casalinuovovoid
122739fd34cSBarrettBMediaRecorderNode::GetInput(media_input* outInput)
123739fd34cSBarrett{
124739fd34cSBarrett	CALLED();
125739fd34cSBarrett
126739fd34cSBarrett	fInput.node = Node();
127739fd34cSBarrett	*outInput = fInput;
128739fd34cSBarrett}
129739fd34cSBarrett
130739fd34cSBarrett
131739fd34cSBarrettvoid
132739fd34cSBarrettBMediaRecorderNode::SetDataEnabled(bool enabled)
133739fd34cSBarrett{
134739fd34cSBarrett	CALLED();
135739fd34cSBarrett
136739fd34cSBarrett	int32 tag;
137739fd34cSBarrett
138739fd34cSBarrett	SetOutputEnabled(fInput.source,
139739fd34cSBarrett		fInput.destination, enabled, NULL, &tag);
140739fd34cSBarrett}
141739fd34cSBarrett
142739fd34cSBarrett
143c1ad6121SDario Casalinuovovoid
144c1ad6121SDario CasalinuovoBMediaRecorderNode::ActivateInternalConnect(bool connectMode)
145c1ad6121SDario Casalinuovo{
146c1ad6121SDario Casalinuovo	fConnectMode = connectMode;
147c1ad6121SDario Casalinuovo}
148c1ad6121SDario Casalinuovo
149c1ad6121SDario Casalinuovo
150739fd34cSBarrettvoid
151739fd34cSBarrettBMediaRecorderNode::HandleEvent(const media_timed_event* event,
152739fd34cSBarrett	bigtime_t lateness, bool realTimeEvent)
153739fd34cSBarrett{
154739fd34cSBarrett	CALLED();
155739fd34cSBarrett
156739fd34cSBarrett	// we ignore them all!
157739fd34cSBarrett}
158739fd34cSBarrett
159739fd34cSBarrett
160739fd34cSBarrettvoid
161739fd34cSBarrettBMediaRecorderNode::Start(bigtime_t performanceTime)
162739fd34cSBarrett{
163739fd34cSBarrett	CALLED();
164739fd34cSBarrett
165739fd34cSBarrett	if (fRecorder->fNotifyHook)
166739fd34cSBarrett		(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
167683cf2ffSHamish Morrison			BMediaRecorder::B_WILL_START, performanceTime);
168739fd34cSBarrett
169739fd34cSBarrett	fRecorder->fRunning = true;
170739fd34cSBarrett}
171739fd34cSBarrett
172739fd34cSBarrett
173739fd34cSBarrettvoid
174739fd34cSBarrettBMediaRecorderNode::Stop(bigtime_t performanceTime, bool immediate)
175739fd34cSBarrett{
176739fd34cSBarrett	CALLED();
177739fd34cSBarrett
178739fd34cSBarrett	if (fRecorder->fNotifyHook)
179739fd34cSBarrett		(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
180683cf2ffSHamish Morrison			BMediaRecorder::B_WILL_STOP, performanceTime, immediate);
181739fd34cSBarrett
182739fd34cSBarrett	fRecorder->fRunning = false;
183739fd34cSBarrett}
184739fd34cSBarrett
185739fd34cSBarrett
186739fd34cSBarrettvoid
187739fd34cSBarrettBMediaRecorderNode::Seek(bigtime_t mediaTime, bigtime_t performanceTime)
188739fd34cSBarrett{
189739fd34cSBarrett	CALLED();
190739fd34cSBarrett
191739fd34cSBarrett	if (fRecorder->fNotifyHook)
192739fd34cSBarrett		(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
193683cf2ffSHamish Morrison			BMediaRecorder::B_WILL_SEEK, performanceTime, mediaTime);
194739fd34cSBarrett}
195739fd34cSBarrett
196739fd34cSBarrett
197739fd34cSBarrettvoid
198739fd34cSBarrettBMediaRecorderNode::TimeWarp(bigtime_t realTime, bigtime_t performanceTime)
199739fd34cSBarrett{
200739fd34cSBarrett	CALLED();
201739fd34cSBarrett
202739fd34cSBarrett	// Since buffers will come pre-time-stamped, we only need to look
203739fd34cSBarrett	// at them, so we can ignore the time warp as a consumer.
204739fd34cSBarrett	if (fRecorder->fNotifyHook)
205739fd34cSBarrett		(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
206683cf2ffSHamish Morrison			BMediaRecorder::B_WILL_TIMEWARP, realTime, performanceTime);
207739fd34cSBarrett}
208739fd34cSBarrett
209739fd34cSBarrett
210739fd34cSBarrettstatus_t
211739fd34cSBarrettBMediaRecorderNode::HandleMessage(int32 message,
212739fd34cSBarrett	const void* data, size_t size)
213739fd34cSBarrett{
214739fd34cSBarrett	CALLED();
215739fd34cSBarrett
216739fd34cSBarrett	if (BBufferConsumer::HandleMessage(message, data, size) < 0
217739fd34cSBarrett		&& BMediaEventLooper::HandleMessage(message, data, size) < 0
218739fd34cSBarrett		&& BMediaNode::HandleMessage(message, data, size) < 0) {
219739fd34cSBarrett		HandleBadMessage(message, data, size);
220739fd34cSBarrett		return B_ERROR;
221739fd34cSBarrett	}
222739fd34cSBarrett	return B_OK;
223739fd34cSBarrett}
224739fd34cSBarrett
225739fd34cSBarrett
226739fd34cSBarrettstatus_t
227739fd34cSBarrettBMediaRecorderNode::AcceptFormat(const media_destination& dest,
228739fd34cSBarrett	media_format* format)
229739fd34cSBarrett{
230739fd34cSBarrett	CALLED();
231739fd34cSBarrett
232739fd34cSBarrett	if (format_is_compatible(*format, fOKFormat))
233739fd34cSBarrett		return B_OK;
234739fd34cSBarrett
235739fd34cSBarrett	*format = fOKFormat;
236739fd34cSBarrett
237739fd34cSBarrett	return B_MEDIA_BAD_FORMAT;
238739fd34cSBarrett}
239739fd34cSBarrett
240739fd34cSBarrett
241739fd34cSBarrettstatus_t
242739fd34cSBarrettBMediaRecorderNode::GetNextInput(int32* cookie, media_input* outInput)
243739fd34cSBarrett{
244739fd34cSBarrett	CALLED();
245739fd34cSBarrett
246739fd34cSBarrett	if (*cookie == 0) {
247739fd34cSBarrett		*cookie = -1;
248739fd34cSBarrett		*outInput = fInput;
249739fd34cSBarrett		return B_OK;
250739fd34cSBarrett	}
251739fd34cSBarrett
252739fd34cSBarrett	return B_BAD_INDEX;
253739fd34cSBarrett}
254739fd34cSBarrett
255739fd34cSBarrett
256739fd34cSBarrettvoid
257739fd34cSBarrettBMediaRecorderNode::DisposeInputCookie(int32 cookie)
258739fd34cSBarrett{
259739fd34cSBarrett	CALLED();
260739fd34cSBarrett}
261739fd34cSBarrett
262739fd34cSBarrett
263739fd34cSBarrettvoid
264739fd34cSBarrettBMediaRecorderNode::BufferReceived(BBuffer* buffer)
265739fd34cSBarrett{
266739fd34cSBarrett	CALLED();
267739fd34cSBarrett
268739fd34cSBarrett	fRecorder->BufferReceived(buffer->Data(), buffer->SizeUsed(),
269739fd34cSBarrett		*buffer->Header());
270739fd34cSBarrett
271739fd34cSBarrett	buffer->Recycle();
272739fd34cSBarrett}
273739fd34cSBarrett
274739fd34cSBarrett
275739fd34cSBarrettvoid
276739fd34cSBarrettBMediaRecorderNode::ProducerDataStatus(
277739fd34cSBarrett	const media_destination& forWhom, int32 status,
278739fd34cSBarrett	bigtime_t performanceTime)
279739fd34cSBarrett{
280739fd34cSBarrett	CALLED();
281739fd34cSBarrett}
282739fd34cSBarrett
283739fd34cSBarrett
284739fd34cSBarrettstatus_t
285739fd34cSBarrettBMediaRecorderNode::GetLatencyFor(const media_destination& forWhom,
286739fd34cSBarrett	bigtime_t* outLatency, media_node_id* outTimesource)
287739fd34cSBarrett{
288739fd34cSBarrett	CALLED();
289739fd34cSBarrett
290739fd34cSBarrett	*outLatency = 0;
291739fd34cSBarrett	*outTimesource = TimeSource()->ID();
292739fd34cSBarrett
293739fd34cSBarrett	return B_OK;
294739fd34cSBarrett}
295739fd34cSBarrett
296739fd34cSBarrett
297739fd34cSBarrettstatus_t
298739fd34cSBarrettBMediaRecorderNode::Connected(const media_source &producer,
299739fd34cSBarrett	const media_destination &where, const media_format &withFormat,
300739fd34cSBarrett	media_input* outInput)
301739fd34cSBarrett{
302739fd34cSBarrett	CALLED();
303739fd34cSBarrett
304739fd34cSBarrett	fInput.source = producer;
305739fd34cSBarrett	fInput.format = withFormat;
306739fd34cSBarrett	*outInput = fInput;
307739fd34cSBarrett
308c1ad6121SDario Casalinuovo	if (fConnectMode == true) {
309c1ad6121SDario Casalinuovo		// This is a workaround needed for us to get the node
310c1ad6121SDario Casalinuovo		// so that our owner class can do it's operations.
311c1ad6121SDario Casalinuovo		media_node node;
312c1ad6121SDario Casalinuovo		BMediaRosterEx* roster = MediaRosterEx(BMediaRoster::CurrentRoster());
313c1ad6121SDario Casalinuovo		if (roster->GetNodeFor(roster->NodeIDFor(producer.port), &node) != B_OK)
314c1ad6121SDario Casalinuovo			return B_MEDIA_BAD_NODE;
3152a2e352aSDario Casalinuovo
316c1ad6121SDario Casalinuovo		fRecorder->fOutputNode = node;
317c1ad6121SDario Casalinuovo		fRecorder->fReleaseOutputNode = true;
318c1ad6121SDario Casalinuovo	}
319cc0d365eSDario Casalinuovo	fRecorder->SetUpConnection(producer);
320739fd34cSBarrett	fRecorder->fConnected = true;
321739fd34cSBarrett
322739fd34cSBarrett	return B_OK;
323739fd34cSBarrett}
324739fd34cSBarrett
325739fd34cSBarrett
326739fd34cSBarrettvoid
327739fd34cSBarrettBMediaRecorderNode::Disconnected(const media_source& producer,
328739fd34cSBarrett	const media_destination& where)
329739fd34cSBarrett{
330739fd34cSBarrett	CALLED();
331739fd34cSBarrett
332739fd34cSBarrett	fInput.source = media_source::null;
333c1ad6121SDario Casalinuovo	// Reset the connection mode
334c1ad6121SDario Casalinuovo	fConnectMode = true;
335739fd34cSBarrett	fRecorder->fConnected = false;
3362a2e352aSDario Casalinuovo	fInput.format = fOKFormat;
337739fd34cSBarrett}
338739fd34cSBarrett
339739fd34cSBarrett
340739fd34cSBarrettstatus_t
341739fd34cSBarrettBMediaRecorderNode::FormatChanged(const media_source& producer,
342739fd34cSBarrett	const media_destination& consumer, int32 tag,
343739fd34cSBarrett	const media_format& format)
344739fd34cSBarrett{
345739fd34cSBarrett	CALLED();
346739fd34cSBarrett
347739fd34cSBarrett	if (!format_is_compatible(format, fOKFormat))
348739fd34cSBarrett		return B_MEDIA_BAD_FORMAT;
349739fd34cSBarrett
350739fd34cSBarrett	fInput.format = format;
351739fd34cSBarrett
352739fd34cSBarrett	return B_OK;
353739fd34cSBarrett}
354