MediaClient: Add remaining wiring for input/output functionality

* BufferReceived is renamed HandleBuffer.
* Update doc.
* Implement buffer production private methods.
This commit is contained in:
Dario Casalinuovo 2017-02-18 20:40:38 +01:00
parent 58be34781b
commit 5854fc4a7a
8 changed files with 91 additions and 46 deletions

View File

@ -61,7 +61,7 @@ public:
// When those functions return, the BMediaConnection is added to the
// list and is visible to other nodes as not connected. Any input/output
// should be registered to a BMediaClient to become something useful.
// should be registered to a BMediaClient to become visible in the system.
virtual status_t RegisterInput(BMediaInput* input);
virtual status_t RegisterOutput(BMediaOutput* output);
@ -81,7 +81,7 @@ public:
// BMediaClient::Format() will be used, in case both aren't specified
// an error is returned. The first parameter should always belong to
// this node, the second will be a connection obtained from another
// BMediaClient.
// BMediaClient. Unregistered connections will be registered automatically.
virtual status_t Connect(BMediaConnection* ourConnection,
BMediaConnection* theirConnection);

View File

@ -25,6 +25,7 @@ class BMediaClientNode;
// the BufferReceived function will be called so that you can process the BBuffer,
// and once the function returns the output will be automatically forwarded
// to the connection B SendBuffer method.
// It's not possible to mix a BMediaInput with a BMediaOutput in the same class.
class BMediaConnection {
public:
const media_connection& Connection() const;
@ -39,7 +40,7 @@ public:
bool IsConnected() const;
// This allow to specify a format that will be used while
// connecting to another node. See BMediaClient::SetFormat.
// connecting to another node.
void SetAcceptedFormat(
const media_format& format);
const media_format& AcceptedFormat() const;
@ -48,10 +49,6 @@ public:
// for this connection.
size_t BufferSize() const;
// Represents the duration of one buffer depends on the format set or
// negotiated for this connection.
bigtime_t BufferDuration() const;
// Disconnect this connection. When a connection is disconnected,
// it can be reused as brand new.
status_t Disconnect();
@ -99,9 +96,6 @@ private:
// see BMediaClient::Bind.
BMediaConnection* fBind;
size_t fBufferSize;
bigtime_t fBufferDuration;
BBufferGroup* fBufferGroup;
bool fConnected;
@ -140,7 +134,7 @@ protected:
// Callbacks
virtual status_t FormatChanged(const media_format& format);
virtual void BufferReceived(BBuffer* buffer);
virtual void HandleBuffer(BBuffer* buffer);
private:
media_input _MediaInput() const;

View File

@ -135,7 +135,7 @@ protected:
virtual void Connected(const media_format& format);
virtual void Disconnected();
virtual void BufferReceived(BBuffer* buffer);
virtual void HandleBuffer(BBuffer* buffer);
};

View File

@ -224,9 +224,7 @@ status_t
BMediaClient::Connect(BMediaConnection* connection,
const media_client& client)
{
CALLED();
// TODO: implement this
UNIMPLEMENTED();
return B_ERROR;
}
@ -467,7 +465,7 @@ BMediaClient::_Deinit()
{
CALLED();
if (fRunning)
if (IsRunning())
Stop();
Disconnect();
@ -556,9 +554,6 @@ BMediaClient::_ConnectOutput(BMediaInput* input,
media_output theirOutput = output._MediaOutput();
media_format format = input->AcceptedFormat();
// TODO manage the node problems
//fNode->ActivateInternalConnect(false);
return BMediaRoster::CurrentRoster()->Connect(theirOutput.source,
ourInput.destination, &format, &theirOutput, &ourInput,
BMediaRoster::B_CONNECT_MUTED);

View File

@ -382,14 +382,7 @@ BMediaClientNode::SetBufferGroup(const media_source& source, BBufferGroup* group
return B_OK;
}
bigtime_t latency = 0;
GetLatency(&latency);
int32 count = int32(latency / conn->BufferDuration() + 2);
if (count < 3)
count = 3;
conn->fBufferGroup = new BBufferGroup(conn->BufferSize(), count);
conn->fBufferGroup = new BBufferGroup(conn->BufferSize(), 3);
if (conn->fBufferGroup == NULL)
return B_NO_MEMORY;
@ -450,8 +443,12 @@ BMediaClientNode::Connect(status_t status, const media_source& source,
conn->SetAcceptedFormat(format);
strcpy(name, Name());
// TODO: Allocate buffers, add correct latency estimate
// and buffer duration mode.
// TODO: add correct latency estimate
SetEventLatency(1000);
conn->fBufferGroup = new BBufferGroup(conn->BufferSize(), 3);
if (conn->fBufferGroup == NULL)
TRACE("Can't allocate the buffer group\n");
conn->Connected(format);
}
@ -492,7 +489,7 @@ BMediaClientNode::GetLatency(bigtime_t* outLatency)
CALLED();
// TODO: finish latency handling
*outLatency = 0;
*outLatency = 1000;
return B_OK;
}
@ -600,7 +597,7 @@ BMediaClientNode::_HandleBuffer(BBuffer* buffer)
BMediaInput* conn = fOwner->_FindInput(dest);
if (conn != NULL)
conn->BufferReceived(buffer);
conn->HandleBuffer(buffer);
// TODO: Investigate system level latency logging
@ -620,8 +617,58 @@ BMediaClientNode::_ProduceNewBuffer(const media_timed_event* event,
if (RunState() != BMediaEventLooper::B_STARTED)
return;
// We get the data through the event
// so that we know which connection
// The connection is get through the event
BMediaOutput* output
= dynamic_cast<BMediaOutput*>((BMediaConnection*)event->pointer);
if (output == NULL)
return;
// event.pointer == connection
if (output->IsEnabled()) {
BBuffer* buffer = _GetNextBuffer(output, event->event_time);
if (buffer != NULL) {
if (output->SendBuffer(buffer) != B_OK) {
TRACE("BMediaClientNode: Failed to send buffer\n");
// The output failed, let's recycle the buffer
buffer->Recycle();
}
}
}
bigtime_t time = 0;
media_format format = output->AcceptedFormat();
if (format.IsAudio()) {
size_t nFrames = format.u.raw_audio.buffer_size
/ ((format.u.raw_audio.format
& media_raw_audio_format::B_AUDIO_SIZE_MASK)
* format.u.raw_audio.channel_count);
output->fFramesSent += nFrames;
time = fStartTime + bigtime_t((1000000LL * output->fFramesSent)
/ (int32)format.u.raw_audio.frame_rate);
}
media_timed_event nextEvent(time, B_NEW_BUFFER);
EventQueue()->AddEvent(nextEvent);
}
BBuffer*
BMediaClientNode::_GetNextBuffer(BMediaOutput* output, bigtime_t eventTime)
{
CALLED();
BBuffer* buffer = NULL;
if (output->fBufferGroup->RequestBuffer(buffer, 0) != B_OK) {
TRACE("MediaClientNode:::_GetNextBuffer: Failed to get the buffer\n");
return NULL;
}
media_header* header = buffer->Header();
header->type = output->AcceptedFormat().type;
header->size_used = output->BufferSize();
header->time_source = TimeSource()->ID();
header->start_time = eventTime;
return buffer;
}

View File

@ -16,8 +16,10 @@
namespace BPrivate { namespace media {
class BMediaClient;
class BMediaConnection;
class BMediaOutput;
class BMediaClientNode : public BBufferConsumer, public BBufferProducer,
public BMediaEventLooper {
@ -132,6 +134,8 @@ private:
void _HandleBuffer(BBuffer* buffer);
void _ProduceNewBuffer(const media_timed_event* event,
bigtime_t late);
BBuffer* _GetNextBuffer(BMediaOutput* output,
bigtime_t eventTime);
BMediaClient* fOwner;
bigtime_t fStartTime;

View File

@ -122,23 +122,22 @@ BMediaConnection::Release()
}
// TODO: The data represented by the following two functions should be
// automatically calculated depending on the media_format.
size_t
BMediaConnection::BufferSize() const
{
CALLED();
return fBufferSize;
}
switch (fConnection.format.type) {
case B_MEDIA_RAW_AUDIO:
return fConnection.format.u.raw_audio.buffer_size;
case B_MEDIA_RAW_VIDEO:
return fConnection.format.u.raw_video.display.bytes_per_row *
fConnection.format.u.raw_video.display.line_count;
bigtime_t
BMediaConnection::BufferDuration() const
{
CALLED();
return fBufferDuration;
default:
return 0;
}
}
@ -251,7 +250,7 @@ BMediaInput::FormatChanged(const media_format& format)
void
BMediaInput::BufferReceived(BBuffer* buffer)
BMediaInput::HandleBuffer(BBuffer* buffer)
{
CALLED();
@ -310,6 +309,9 @@ BMediaOutput::SetEnabled(bool enabled)
status_t
BMediaOutput::PrepareToConnect(media_format* format)
{
if (!format_is_compatible(AcceptedFormat(), *format))
return B_ERROR;
SetAcceptedFormat(*format);
return B_OK;
@ -336,6 +338,9 @@ BMediaOutput::SendBuffer(BBuffer* buffer)
{
CALLED();
if (!IsConnected())
return B_ERROR;
return fOwner->fNode->SendBuffer(buffer, this);
}

View File

@ -186,7 +186,7 @@ BSimpleMediaInput::Disconnected()
void
BSimpleMediaInput::BufferReceived(BBuffer* buffer)
BSimpleMediaInput::HandleBuffer(BBuffer* buffer)
{
CALLED();