vfs: check userland buffers before reading them.
[haiku.git] / src / kits / media / MediaRecorderNode.cpp
blobec4c58ebf9ec85031e4b69f26661e283cff699de
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 */
9 #include "MediaRecorderNode.h"
11 #include <Buffer.h>
12 #include <scheduler.h>
13 #include <MediaRoster.h>
14 #include <MediaRosterEx.h>
15 #include <TimedEventQueue.h>
16 #include <TimeSource.h>
18 #include "MediaDebug.h"
21 BMediaRecorderNode::BMediaRecorderNode(const char* name,
22 BMediaRecorder* recorder, media_type type)
24 BMediaNode(name),
25 BMediaEventLooper(),
26 BBufferConsumer(type),
27 fRecorder(recorder),
28 fConnectMode(true)
30 CALLED();
32 fInput.node = Node();
33 fInput.destination.id = 1;
34 fInput.destination.port = ControlPort();
36 fName.SetTo(name);
38 BString str(name);
39 str << " Input";
40 strcpy(fInput.name, str.String());
44 BMediaRecorderNode::~BMediaRecorderNode()
46 CALLED();
50 BMediaAddOn*
51 BMediaRecorderNode::AddOn(int32* id) const
53 CALLED();
55 if (id)
56 *id = -1;
58 return NULL;
62 void
63 BMediaRecorderNode::NodeRegistered()
65 CALLED();
66 Run();
70 void
71 BMediaRecorderNode::SetRunMode(run_mode mode)
73 CALLED();
75 int32 priority;
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;
86 case B_MEDIA_RAW_VIDEO:
87 case B_MEDIA_ENCODED_VIDEO:
88 priority = B_VIDEO_RECORDING;
89 break;
91 default:
92 priority = B_DEFAULT_MEDIA_PRIORITY;
96 SetPriority(suggest_thread_priority(priority));
98 BMediaNode::SetRunMode(mode);
102 void
103 BMediaRecorderNode::SetAcceptedFormat(const media_format& format)
105 CALLED();
107 fInput.format = format;
108 fOKFormat = format;
112 const media_format&
113 BMediaRecorderNode::AcceptedFormat() const
115 CALLED();
117 return fInput.format;
121 void
122 BMediaRecorderNode::GetInput(media_input* outInput)
124 CALLED();
126 fInput.node = Node();
127 *outInput = fInput;
131 void
132 BMediaRecorderNode::SetDataEnabled(bool enabled)
134 CALLED();
136 int32 tag;
138 SetOutputEnabled(fInput.source,
139 fInput.destination, enabled, NULL, &tag);
143 void
144 BMediaRecorderNode::ActivateInternalConnect(bool connectMode)
146 fConnectMode = connectMode;
150 void
151 BMediaRecorderNode::HandleEvent(const media_timed_event* event,
152 bigtime_t lateness, bool realTimeEvent)
154 CALLED();
156 // we ignore them all!
160 void
161 BMediaRecorderNode::Start(bigtime_t performanceTime)
163 CALLED();
165 if (fRecorder->fNotifyHook)
166 (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
167 BMediaRecorder::B_WILL_START, performanceTime);
169 fRecorder->fRunning = true;
173 void
174 BMediaRecorderNode::Stop(bigtime_t performanceTime, bool immediate)
176 CALLED();
178 if (fRecorder->fNotifyHook)
179 (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
180 BMediaRecorder::B_WILL_STOP, performanceTime, immediate);
182 fRecorder->fRunning = false;
186 void
187 BMediaRecorderNode::Seek(bigtime_t mediaTime, bigtime_t performanceTime)
189 CALLED();
191 if (fRecorder->fNotifyHook)
192 (*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
193 BMediaRecorder::B_WILL_SEEK, performanceTime, mediaTime);
197 void
198 BMediaRecorderNode::TimeWarp(bigtime_t realTime, bigtime_t performanceTime)
200 CALLED();
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);
210 status_t
211 BMediaRecorderNode::HandleMessage(int32 message,
212 const void* data, size_t size)
214 CALLED();
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;
222 return B_OK;
226 status_t
227 BMediaRecorderNode::AcceptFormat(const media_destination& dest,
228 media_format* format)
230 CALLED();
232 if (format_is_compatible(*format, fOKFormat))
233 return B_OK;
235 *format = fOKFormat;
237 return B_MEDIA_BAD_FORMAT;
241 status_t
242 BMediaRecorderNode::GetNextInput(int32* cookie, media_input* outInput)
244 CALLED();
246 if (*cookie == 0) {
247 *cookie = -1;
248 *outInput = fInput;
249 return B_OK;
252 return B_BAD_INDEX;
256 void
257 BMediaRecorderNode::DisposeInputCookie(int32 cookie)
259 CALLED();
263 void
264 BMediaRecorderNode::BufferReceived(BBuffer* buffer)
266 CALLED();
268 fRecorder->BufferReceived(buffer->Data(), buffer->SizeUsed(),
269 *buffer->Header());
271 buffer->Recycle();
275 void
276 BMediaRecorderNode::ProducerDataStatus(
277 const media_destination& forWhom, int32 status,
278 bigtime_t performanceTime)
280 CALLED();
284 status_t
285 BMediaRecorderNode::GetLatencyFor(const media_destination& forWhom,
286 bigtime_t* outLatency, media_node_id* outTimesource)
288 CALLED();
290 *outLatency = 0;
291 *outTimesource = TimeSource()->ID();
293 return B_OK;
297 status_t
298 BMediaRecorderNode::Connected(const media_source &producer,
299 const media_destination &where, const media_format &withFormat,
300 media_input* outInput)
302 CALLED();
304 fInput.source = producer;
305 fInput.format = withFormat;
306 *outInput = fInput;
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;
316 fRecorder->fOutputNode = node;
317 fRecorder->fReleaseOutputNode = true;
319 fRecorder->SetUpConnection(producer);
320 fRecorder->fConnected = true;
322 return B_OK;
326 void
327 BMediaRecorderNode::Disconnected(const media_source& producer,
328 const media_destination& where)
330 CALLED();
332 fInput.source = media_source::null;
333 // Reset the connection mode
334 fConnectMode = true;
335 fRecorder->fConnected = false;
336 fInput.format = fOKFormat;
340 status_t
341 BMediaRecorderNode::FormatChanged(const media_source& producer,
342 const media_destination& consumer, int32 tag,
343 const media_format& format)
345 CALLED();
347 if (!format_is_compatible(format, fOKFormat))
348 return B_MEDIA_BAD_FORMAT;
350 fInput.format = format;
352 return B_OK;