Skip to content

Commit

Permalink
MediaClient: Add remaining wiring for input/output functionality
Browse files Browse the repository at this point in the history
* BufferReceived is renamed HandleBuffer.
* Update doc.
* Implement buffer production private methods.
  • Loading branch information
Numerio committed Mar 10, 2017
1 parent 58be347 commit 5854fc4
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 46 deletions.
4 changes: 2 additions & 2 deletions headers/private/media/experimental/MediaClient.h
Expand Up @@ -61,7 +61,7 @@ class BMediaClient {

// 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);

Expand All @@ -81,7 +81,7 @@ class BMediaClient {
// 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);

Expand Down
12 changes: 3 additions & 9 deletions headers/private/media/experimental/MediaConnection.h
Expand Up @@ -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;
Expand All @@ -39,7 +40,7 @@ class BMediaConnection {
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;
Expand All @@ -48,10 +49,6 @@ class BMediaConnection {
// 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();
Expand Down Expand Up @@ -99,9 +96,6 @@ class BMediaConnection {
// see BMediaClient::Bind.
BMediaConnection* fBind;

size_t fBufferSize;
bigtime_t fBufferDuration;

BBufferGroup* fBufferGroup;

bool fConnected;
Expand Down Expand Up @@ -140,7 +134,7 @@ class BMediaInput : public virtual BMediaConnection {
// Callbacks
virtual status_t FormatChanged(const media_format& format);

virtual void BufferReceived(BBuffer* buffer);
virtual void HandleBuffer(BBuffer* buffer);

private:
media_input _MediaInput() const;
Expand Down
2 changes: 1 addition & 1 deletion headers/private/media/experimental/SimpleMediaClient.h
Expand Up @@ -135,7 +135,7 @@ class BSimpleMediaInput : public BSimpleMediaConnection, public BMediaInput {
virtual void Connected(const media_format& format);
virtual void Disconnected();

virtual void BufferReceived(BBuffer* buffer);
virtual void HandleBuffer(BBuffer* buffer);
};


Expand Down
9 changes: 2 additions & 7 deletions src/kits/media/experimental/MediaClient.cpp
Expand Up @@ -224,9 +224,7 @@ status_t
BMediaClient::Connect(BMediaConnection* connection,
const media_client& client)
{
CALLED();

// TODO: implement this
UNIMPLEMENTED();

return B_ERROR;
}
Expand Down Expand Up @@ -467,7 +465,7 @@ BMediaClient::_Deinit()
{
CALLED();

if (fRunning)
if (IsRunning())
Stop();

Disconnect();
Expand Down Expand Up @@ -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);
Expand Down
77 changes: 62 additions & 15 deletions src/kits/media/experimental/MediaClientNode.cpp
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -492,7 +489,7 @@ BMediaClientNode::GetLatency(bigtime_t* outLatency)
CALLED();

// TODO: finish latency handling
*outLatency = 0;
*outLatency = 1000;
return B_OK;
}

Expand Down Expand Up @@ -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

Expand All @@ -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;

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;

// event.pointer == connection
return buffer;
}
4 changes: 4 additions & 0 deletions src/kits/media/experimental/MediaClientNode.h
Expand Up @@ -16,8 +16,10 @@

namespace BPrivate { namespace media {


class BMediaClient;
class BMediaConnection;
class BMediaOutput;

class BMediaClientNode : public BBufferConsumer, public BBufferProducer,
public BMediaEventLooper {
Expand Down Expand Up @@ -132,6 +134,8 @@ class BMediaClientNode : public BBufferConsumer, public BBufferProducer,
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;
Expand Down
27 changes: 16 additions & 11 deletions src/kits/media/experimental/MediaConnection.cpp
Expand Up @@ -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;

bigtime_t
BMediaConnection::BufferDuration() const
{
CALLED();
case B_MEDIA_RAW_VIDEO:
return fConnection.format.u.raw_video.display.bytes_per_row *
fConnection.format.u.raw_video.display.line_count;

return fBufferDuration;
default:
return 0;
}
}


Expand Down Expand Up @@ -251,7 +250,7 @@ BMediaInput::FormatChanged(const media_format& format)


void
BMediaInput::BufferReceived(BBuffer* buffer)
BMediaInput::HandleBuffer(BBuffer* buffer)
{
CALLED();

Expand Down Expand Up @@ -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;
Expand All @@ -336,6 +338,9 @@ BMediaOutput::SendBuffer(BBuffer* buffer)
{
CALLED();

if (!IsConnected())
return B_ERROR;

return fOwner->fNode->SendBuffer(buffer, this);
}

Expand Down
2 changes: 1 addition & 1 deletion src/kits/media/experimental/SimpleMediaClient.cpp
Expand Up @@ -186,7 +186,7 @@ BSimpleMediaInput::Disconnected()


void
BSimpleMediaInput::BufferReceived(BBuffer* buffer)
BSimpleMediaInput::HandleBuffer(BBuffer* buffer)
{
CALLED();

Expand Down

0 comments on commit 5854fc4

Please sign in to comment.