MediaClient: Add remaining wiring for input/output functionality
* BufferReceived is renamed HandleBuffer. * Update doc. * Implement buffer production private methods.
This commit is contained in:
parent
58be34781b
commit
5854fc4a7a
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,7 @@ BSimpleMediaInput::Disconnected()
|
|||
|
||||
|
||||
void
|
||||
BSimpleMediaInput::BufferReceived(BBuffer* buffer)
|
||||
BSimpleMediaInput::HandleBuffer(BBuffer* buffer)
|
||||
{
|
||||
CALLED();
|
||||
|
||||
|
|
Loading…
Reference in New Issue