354 lines
6.0 KiB
C++
354 lines
6.0 KiB
C++
/*
|
|
* Copyright 2014-2016, Dario Casalinuovo
|
|
* Copyright 1999, Be Incorporated
|
|
* All Rights Reserved.
|
|
* This file may be used under the terms of the Be Sample Code License.
|
|
*/
|
|
|
|
|
|
#include "MediaRecorderNode.h"
|
|
|
|
#include <Buffer.h>
|
|
#include <scheduler.h>
|
|
#include <MediaRoster.h>
|
|
#include <MediaRosterEx.h>
|
|
#include <TimedEventQueue.h>
|
|
#include <TimeSource.h>
|
|
|
|
#include "MediaDebug.h"
|
|
|
|
|
|
BMediaRecorderNode::BMediaRecorderNode(const char* name,
|
|
BMediaRecorder* recorder, media_type type)
|
|
:
|
|
BMediaNode(name),
|
|
BMediaEventLooper(),
|
|
BBufferConsumer(type),
|
|
fRecorder(recorder),
|
|
fConnectMode(true)
|
|
{
|
|
CALLED();
|
|
|
|
fInput.node = Node();
|
|
fInput.destination.id = 1;
|
|
fInput.destination.port = ControlPort();
|
|
|
|
fName.SetTo(name);
|
|
|
|
BString str(name);
|
|
str << " Input";
|
|
strcpy(fInput.name, str.String());
|
|
}
|
|
|
|
|
|
BMediaRecorderNode::~BMediaRecorderNode()
|
|
{
|
|
CALLED();
|
|
}
|
|
|
|
|
|
BMediaAddOn*
|
|
BMediaRecorderNode::AddOn(int32* id) const
|
|
{
|
|
CALLED();
|
|
|
|
if (id)
|
|
*id = -1;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::NodeRegistered()
|
|
{
|
|
CALLED();
|
|
Run();
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::SetRunMode(run_mode mode)
|
|
{
|
|
CALLED();
|
|
|
|
int32 priority;
|
|
|
|
if (mode == BMediaNode::B_OFFLINE)
|
|
priority = B_OFFLINE_PROCESSING;
|
|
else {
|
|
switch(ConsumerType()) {
|
|
case B_MEDIA_RAW_AUDIO:
|
|
case B_MEDIA_ENCODED_AUDIO:
|
|
priority = B_AUDIO_RECORDING;
|
|
break;
|
|
|
|
case B_MEDIA_RAW_VIDEO:
|
|
case B_MEDIA_ENCODED_VIDEO:
|
|
priority = B_VIDEO_RECORDING;
|
|
break;
|
|
|
|
default:
|
|
priority = B_DEFAULT_MEDIA_PRIORITY;
|
|
}
|
|
}
|
|
|
|
SetPriority(suggest_thread_priority(priority));
|
|
|
|
BMediaNode::SetRunMode(mode);
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::SetAcceptedFormat(const media_format& format)
|
|
{
|
|
CALLED();
|
|
|
|
fInput.format = format;
|
|
fOKFormat = format;
|
|
}
|
|
|
|
|
|
const media_format&
|
|
BMediaRecorderNode::AcceptedFormat() const
|
|
{
|
|
CALLED();
|
|
|
|
return fInput.format;
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::GetInput(media_input* outInput)
|
|
{
|
|
CALLED();
|
|
|
|
fInput.node = Node();
|
|
*outInput = fInput;
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::SetDataEnabled(bool enabled)
|
|
{
|
|
CALLED();
|
|
|
|
int32 tag;
|
|
|
|
SetOutputEnabled(fInput.source,
|
|
fInput.destination, enabled, NULL, &tag);
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::ActivateInternalConnect(bool connectMode)
|
|
{
|
|
fConnectMode = connectMode;
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::HandleEvent(const media_timed_event* event,
|
|
bigtime_t lateness, bool realTimeEvent)
|
|
{
|
|
CALLED();
|
|
|
|
// we ignore them all!
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::Start(bigtime_t performanceTime)
|
|
{
|
|
CALLED();
|
|
|
|
if (fRecorder->fNotifyHook)
|
|
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
|
BMediaRecorder::B_WILL_START, performanceTime);
|
|
|
|
fRecorder->fRunning = true;
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::Stop(bigtime_t performanceTime, bool immediate)
|
|
{
|
|
CALLED();
|
|
|
|
if (fRecorder->fNotifyHook)
|
|
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
|
BMediaRecorder::B_WILL_STOP, performanceTime, immediate);
|
|
|
|
fRecorder->fRunning = false;
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::Seek(bigtime_t mediaTime, bigtime_t performanceTime)
|
|
{
|
|
CALLED();
|
|
|
|
if (fRecorder->fNotifyHook)
|
|
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
|
BMediaRecorder::B_WILL_SEEK, performanceTime, mediaTime);
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::TimeWarp(bigtime_t realTime, bigtime_t performanceTime)
|
|
{
|
|
CALLED();
|
|
|
|
// Since buffers will come pre-time-stamped, we only need to look
|
|
// at them, so we can ignore the time warp as a consumer.
|
|
if (fRecorder->fNotifyHook)
|
|
(*fRecorder->fNotifyHook)(fRecorder->fBufferCookie,
|
|
BMediaRecorder::B_WILL_TIMEWARP, realTime, performanceTime);
|
|
}
|
|
|
|
|
|
status_t
|
|
BMediaRecorderNode::HandleMessage(int32 message,
|
|
const void* data, size_t size)
|
|
{
|
|
CALLED();
|
|
|
|
if (BBufferConsumer::HandleMessage(message, data, size) < 0
|
|
&& BMediaEventLooper::HandleMessage(message, data, size) < 0
|
|
&& BMediaNode::HandleMessage(message, data, size) < 0) {
|
|
HandleBadMessage(message, data, size);
|
|
return B_ERROR;
|
|
}
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BMediaRecorderNode::AcceptFormat(const media_destination& dest,
|
|
media_format* format)
|
|
{
|
|
CALLED();
|
|
|
|
if (format_is_compatible(*format, fOKFormat))
|
|
return B_OK;
|
|
|
|
*format = fOKFormat;
|
|
|
|
return B_MEDIA_BAD_FORMAT;
|
|
}
|
|
|
|
|
|
status_t
|
|
BMediaRecorderNode::GetNextInput(int32* cookie, media_input* outInput)
|
|
{
|
|
CALLED();
|
|
|
|
if (*cookie == 0) {
|
|
*cookie = -1;
|
|
*outInput = fInput;
|
|
return B_OK;
|
|
}
|
|
|
|
return B_BAD_INDEX;
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::DisposeInputCookie(int32 cookie)
|
|
{
|
|
CALLED();
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::BufferReceived(BBuffer* buffer)
|
|
{
|
|
CALLED();
|
|
|
|
fRecorder->BufferReceived(buffer->Data(), buffer->SizeUsed(),
|
|
*buffer->Header());
|
|
|
|
buffer->Recycle();
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::ProducerDataStatus(
|
|
const media_destination& forWhom, int32 status,
|
|
bigtime_t performanceTime)
|
|
{
|
|
CALLED();
|
|
}
|
|
|
|
|
|
status_t
|
|
BMediaRecorderNode::GetLatencyFor(const media_destination& forWhom,
|
|
bigtime_t* outLatency, media_node_id* outTimesource)
|
|
{
|
|
CALLED();
|
|
|
|
*outLatency = 0;
|
|
*outTimesource = TimeSource()->ID();
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
status_t
|
|
BMediaRecorderNode::Connected(const media_source &producer,
|
|
const media_destination &where, const media_format &withFormat,
|
|
media_input* outInput)
|
|
{
|
|
CALLED();
|
|
|
|
fInput.source = producer;
|
|
fInput.format = withFormat;
|
|
*outInput = fInput;
|
|
|
|
if (fConnectMode == true) {
|
|
// This is a workaround needed for us to get the node
|
|
// so that our owner class can do it's operations.
|
|
media_node node;
|
|
BMediaRosterEx* roster = MediaRosterEx(BMediaRoster::CurrentRoster());
|
|
if (roster->GetNodeFor(roster->NodeIDFor(producer.port), &node) != B_OK)
|
|
return B_MEDIA_BAD_NODE;
|
|
|
|
fRecorder->fOutputNode = node;
|
|
fRecorder->fReleaseOutputNode = true;
|
|
}
|
|
fRecorder->SetUpConnection(producer);
|
|
fRecorder->fConnected = true;
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
void
|
|
BMediaRecorderNode::Disconnected(const media_source& producer,
|
|
const media_destination& where)
|
|
{
|
|
CALLED();
|
|
|
|
fInput.source = media_source::null;
|
|
// Reset the connection mode
|
|
fConnectMode = true;
|
|
fRecorder->fConnected = false;
|
|
fInput.format = fOKFormat;
|
|
}
|
|
|
|
|
|
status_t
|
|
BMediaRecorderNode::FormatChanged(const media_source& producer,
|
|
const media_destination& consumer, int32 tag,
|
|
const media_format& format)
|
|
{
|
|
CALLED();
|
|
|
|
if (!format_is_compatible(format, fOKFormat))
|
|
return B_MEDIA_BAD_FORMAT;
|
|
|
|
fInput.format = format;
|
|
|
|
return B_OK;
|
|
}
|