BBufferConsumer¶
Constructor and Destructor¶
BBufferConsumer()
BBufferConsumer::BBufferConsumer(media_type consumerType)
The BBufferConsumer constructor. Specify as consumerType the type of data the BBufferConsumer accepts.
Note
In BeOS Release 4.5.2 and earlier consumerType has a default value. It no longer does. You’ll have to actually specify the media type from now on.
~BBufferConsumer()
BBufferConsumer::~BBufferConsumer()
The BBufferConsumer destructor. You can augment this to handle whatever closing-out your consumer node requires.
If your node has created and set BBufferGroup
s for any
producers, you should delete them in the destructor.
Hook Functions¶
AcceptFormat()
virtual status_t BBufferConsumer::AcceptFormat(const media_destination &destination, media_format *format) = 0
Implement this hook function to check that the specified format is reasonable for the specified destination, and to fill in any wildcard fields for which your BBufferConsumer has specific requirements.
If the format isn’t reasonable (or is of a class that’s unsuitable for
destination), return B_MEDIA_BAD_FORMAT
.
When AcceptFormat() returns B_OK
, the Media
Kit will expect a connection request on destination with the
specified format not to fail due to a format incompatibility.
Warning
Don’t try to ask the upstream producer about the format; it’s waiting synchronously for your response, and doing so will cause deadlock.
BufferReceived()
virtual void BBufferConsumer::BufferReceived(BBuffer *buffer) = 0
When a BBufferProducer
sends buffers to one of your
BBufferConsumer’s inputs, it will eventually arrive here, at the
BufferReceived() function (usually after first being dispatched
by HandleMessage()
).
Override this hook function to add the buffer to your internal
playback queue, or to do whatever your node needs to do with buffers you
consume. If you implement both BBufferProducer
and
BBufferConsumer, it’s possible you might examine or alter the
data in the buffer and then call
BBufferProducer::SendBuffer()
to send it along to someone else.
If your processing of the buffer is long enough to cause the buffer to
become late, you should still process it as usual, but you should also call
NotifyLateProducer()
to let the producer know
things are starting to lag.
Information about the contents and timing requirements of the buffer can be
obtained by calling BBuffer::Header()
on it.
Warning
If you’re writing a node, and receive a buffer with the
B_SMALL_BUFFER
flag set, you must recycle the buffer
before returning.
Connected()
virtual status_t BBufferConsumer::Connected(const media_source &destination, const media_format *format, media_input *outInput) = 0
This hook function is called when a connection is being established to your
input destination from the specified source producer. The connection will
be composed of media data with the specified format (which you’ve
previously accepted via AcceptFormat()
).
Your implementation of Connected() should do whatever preparation you need to do to handle data input on the connection, and fill out the outInput buffer with information about the connection from your node’s point-of-view. You can set outInput’s destination field different from destination if destination is a global connection-establishing input that’s used to negotiate a connection, then create a new input to actually handle the data stream.
Note
Since your BBufferConsumer has already had the opportunity to reject the specified format, it’s poor form to return an error from this function. You should only return an error if the resources needed to establish the connection have become unavailable prior to the time Connected() was called.
On entry, outInput’s name field contains the name given the connection by the producer (this may be an empty string if the producer didn’t assign a name). Your consumer should always make sure there’s a valid name here, because it’s a bad thing to have unnamed connections, and there’s no guarantee that the producer will fill this in. If you don’t have a good, descriptive name for a connection, the name should minimally contain the name of the node and a number that makes the connection’s name unique (such as “MyNode Input 1” or “MyNode Output 3”).
If you want the producer to use a specific BBufferGroup
(for
example, if you want a video producer to fill BDirectWindow
buffers), you should create the BBufferGroup
here, then call
BBufferProducer::SetBufferGroup()
to set the producer’s buffer
group:
BBufferGroup *buffers = new BBufferGroup;
BMediaRoster::Roster()->SetOutputBuffersFor(producer, buffers);
Return B_OK
if the connection is started safely,
otherwise, return an appropriate error code.
Disconnected()
virtual void BBufferConsumer::Disconnected(const media_source &producer, const media_destination &whichInput) = 0
This hook function is called when a connection is being terminated. You
should do whatever needs to be done in order to ensure that future
inquiries about the media_source
connected to
the media_input
indicated by
whichInput reference media_source::null (or, if
another connection is later established on the input, that producer).
If your consumer node has created and set a BBufferGroup
for
the producer, you shouldn’t delete or reclaim it here, because the producer
has a clone of the BBufferGroup
that references the same
buffers; deleting the BBufferGroup
would free those buffers,
leaving the producer in deadlock. Instead, delete (or reclaim) the when
Connected()
is called again, and be sure to
delete any remaining BBufferGroup
s in your destructor.
DisposeInputCookie()
virtual void BBufferConsumer::DisposeInputCookie(int32 cookie) = 0
If the cookie value you return in
GetNextInput()
is a pointer to an object that
needs to be deleted when the iteration process is completed, be sure to
implement DisposeInputCookie() to do so.
GetLatencyFor()
virtual status_t BBufferConsumer::GetLatencyFor(const media_destination &forWhom, bigtime_t *outLatency, media_node_id *outTimeSource) = 0
Implement this hook function to calculate the total latency for the
media_destination
specified by
forWhom and store the resulting value in outLatency.
Also, return the time source your node is slaved to in
outTimeSource.
If your node is a BBufferProducer
Return B_OK
if you successfully compute the latency;
otherwise, return an appropriate error.
GetNextInput()
virtual status_t BBufferConsumer::GetNextInput(int32 *cookie, media_input *outInput) = 0
The first time a client calls this function, the value pointed to by cookie will be 0. You should fill the buffer pointed to by outInput with information about your first input, and set the value at cookie to something (other than zero) that will let you keep track of what to return the next time GetNextInput() is called.
Each successive call to GetNextInput() will pass back, in cookie, the value you returned in cookie the last time the function was called by that client, and you should fill outInput with information about the next input, and store a new value in cookie to continue to track your progress through the inputs.
Note
Whenever this function is called with a value of zero in cookie, you must start over with the first input.
When you reach the last input, return B_BAD_INDEX
to
indicate that there aren’t any more inputs.
HandleMessage()
virtual status_t BBufferConsumer::HandleMessage(int32 message, const void *data, size_t size)
When your node derived from BBufferConsumer receives a message on
its control port, you should try dispatching it by calling
HandleMessage(). If BBufferConsumer doesn’t understand
the message, it’ll return B_ERROR
and you can try
dispatching it to another class from which your node is derived, or handle
it yourself.
If this function returns B_OK
, the message has been
handled.
See also: BMediaNode::HandleMessage()
, “About Multiple Virtual Inheritance
”
ProducerDataStatus()
virtual void BBufferConsumer::ProducerDataStatus(const media_destination &destination, int32 status, bigtime_t atPerformanceTime) = 0
This hook function is called to inform your consumer about changes in the availability of buffers from the producer that’s connected to the input destination. The status argument specifies what change has occurred, and atPerformanceTime indicates when the change happened (or when it will happen).
This lets you keep track of which inputs you should await data from; for example, if your consumer is processing data arriving from four producers, and one of them stops sending buffers to the consumer, the producer that’s stopping will cause a call to ProducerDataStatus() to let you know not to await buffers anymore. This way, you know that when buffers have arrived from the other three inputs, it’s okay to begin processing the buffers.
Constant |
Description |
---|---|
|
The producer doesn’t have any data available. |
|
The producer has data available. |
|
The producer has been stopped. |
SeekTagRequested()
virtual status_t BBufferConsumer::SeekTagRequested(const media_destination &destination, bigtime_t inTargetTime, uint32 inFlags, media_seek_tag *outSeekTag, bigtime_t *outTaggedTime, uint32 *outFlags)
This function is provided to aid in supporting media formats in which the outer encapsulation layer doesn’t supply timing information. Producers will tag the buffers they generate with seek tags; these tags can be used to locate key frames in the media data.
It’s the consumer’s job to match up seek tags with performance times. As the consumer processes each incoming buffer, it should cache the seek tag and the performance time at which it occurs (if there’s a tag on the buffer). When the producer needs to know the seek tag and corresponding time that’s closest to a given performance time, this function is resonsible for returning that information.
Return Code |
Description |
---|---|
|
No error. |
Other errors. |
Depend on the node’s implementation. |
See also: “Seek Tags”
Member Functions¶
ConsumerType()
media_type BBufferConsumer::ConsumerType()
Returns the type of media the BBufferConsumer consumes.
NotifyLateProducer()
void BBufferConsumer::NotifyLateProducer(const media_source &source, bigtime_t howLate, bigtime_t performanceTime)
Notifies the BBufferProducer
specified by source that it’s
running late by howLate microseconds; the notification conditions
as of the specified performanceTime. Call this function when you
detect that data is arriving too late and the run mode is
B_DECREASE_PRECISION
,
B_INCREASE_LATENCY
, or B_DROP_DATA
(any
of which permits adjustment of the media playback to maintain timeliness).
The producer should process this notification immediately and take the appropriate action.
RegionToClipData()
static status_t BBufferConsumer::RegionToClipData(const BRegion *region, int32 *format, int32 *ioSize, void *data)
Converts a BRegion
into the clipping format used internally by
the Media Kit. Prior to calling RegionToClipData(),
ioSize is set to the size of the buffer pointed to by
data. On return, format is the format of the clipping
data, ioSize is changed to the actual number of bytes of data
returned, and data contains the actual clipping data.
The clip data format is described in the section “Video Clipping”.
Return Code |
Description |
---|---|
|
Clip data returned without errors. |
|
The data buffer isn’t big enough. |
RequestAdditionalBuffer()
status_t BBufferConsumer::RequestAdditionalBuffer(const media_source &source, BBuffer *previousBuffer, void *_reserved_ = NULL)
status_t BBufferConsumer::RequestAdditionalBuffer(const media_source &source, bigtime_t startTime, void *_reserved_ = NULL)
Asks the upstream producer specified by source to immediately send the next buffer, instead of waiting until the appropriate time. The most obvious use for this function is in cases where a codec requires multiple buffers in order to decode a frame of output (MPEG is a good example).
The requested buffer can be identified either by a startTime parameter, which indicates the time for which a buffer is requested, or by a previousBuffer, which specifies the buffer prior to the one being requested.
This function will cause the producer’s
AdditionalBufferRequested()
function to be
called.
Return Code |
Description |
---|---|
|
The change was requested successfully. |
|
The source isn’t valid. |
|
The previousBuffer pointer is NULL. |
|
The request to the Media Server timed out. |
|
An error occurred communicating with the Media Server. |
RequestFormatChange(), FormatChanged()
status_t BBufferConsumer::RequestFormatChange(const media_source &source, const media_destination &destination, media_format &toFormat, void *userData, const media_destination &changeTag, void *_reserved_ = NULL)
virtual status_t BBufferConsumer::FormatChanged(const media_source &source, const media_destination &destination, media_format &newFormat) = 0
RequestFormatChange() requests that the producer
source connected to the consumer destination change the
format it produces to the format specified by toFormat. The Media
Kit returns in changeTag the tag value that will be received by
your RequestCompleted()
function once the change
takes effect; the change tag lets you match up the call to
RequestCompleted()
with this request. This
function will receive a media_request_info
structure with the
indicated userData and changeTag.
FormatChanged() is called by the upstream producer when the
media format your node will be receiving changes, and indicates the new
format in newFormat and the change tag value at which the new
format will take effect in changeTag. You should implement this
function so your node will know that the data format is going to change.
Note that this may be called in response to your
AcceptFormat()
call, if your
AcceptFormat()
call alters any wildcard
fields in the specified format.
Note
Because FormatChanged() is called by the producer, you don’t need to (and shouldn’t) ask it if the new format is acceptable.
If the format change isn’t possible, return an appropriate error from FormatChanged(); this error will be passed back to the producer that initiated the new format negotiation in the first place.
Return Code |
Description |
---|---|
|
No error. |
|
The specified source isn’t valid. |
|
The specified destination is invalid. |
Port errors. |
See Ports. |
SendLatencyChange()
status_t BBufferConsumer::SendLatencyChange(const media_source &source, const media_destination &destination, bigtime_t newLatency, uint32 flags = 0)
Lets the upstream producer know that the consumer node’s latency has changed. newLatency indicates your new latency, in microseconds. The flags are currently unused and should always be 0.
You should call this whenever something happens to cause a change in your latency.
Return Code |
Description |
---|---|
|
No error. |
|
The source is invalid. |
|
The destination is invalid. |
|
The attempt to communicate with the Media Server timed out. |
Port errors. |
An error occurred communicating with the Media Server. |
SetOutputBuffersFor()
status_t BBufferConsumer::SetOutputBuffersFor(const media_source &source, const media_destination &destination, BBufferGroup *group, void *userData, int32 *changeTag, bool willReclaim = false, void *_reserved_ = NULL)
Specifies that the BBufferGroup
group will provide the buffers
for the connection between source and destination. If willReclaim
is false, the Media Kit will dispose of the group for you; you
can forget about it once this call returns. Otherwise, you’re informing the
Media Server that you want the group back, and that you’ll delete it when
you’re done with it.
The Media Kit returns in changeTag the tag value that will be
received by your RequestCompleted()
function once
the change takes effect; the change tag lets you match up the call to
RequestCompleted()
with this request. This
function will receive a media_request_info
structure with the
indicated userData and changeTag.
The ability to request that certain buffers be used by a particular output
can save you from having to perform unnecessary copies; you might be able
to use BBuffer
s that represent a graphics card frame buffer,
for example, so that a video producer’s output goes directly to video
memory.
Note
Before reclaiming your buffers, be sure to call
SetOutputBuffersFor(output, NULL)
to let the Media Kit know your producer
no longer has permission to use them. If you forget this step, the producer
will hang onto the buffers until it’s deleted, and your
BBufferGroup::ReclaimAllBuffers()
call will hang, possibly
forever.
Return Code |
Description |
---|---|
|
The change was requested successfully. |
Other errors. |
The change could not be made. |
SetOutputEnabled()
static status_t BBufferConsumer::SetOutputEnabled(const media_source &source, const media_destination &destination, bool enabled, void *userData, int32 *changeTag, void *_reserved_ = NULL)
Specifies whether or not the specified output should be transmitting buffers to the destination. If enabled is true, the producer should transmit buffers; otherwise it should not.
The Media Kit returns in changeTag the tag value that will be
received by your RequestCompleted()
function once
the change takes effect; the change tag lets you match up the call to
RequestCompleted()
with this request. This
function will receive a media_request_info structure with the
indicated userData and changeTag.
Return Code |
Description |
---|---|
|
The change was requested successfully. |
|
The source is invalid. |
SetVideoClippingFor()
status_t BBufferConsumer::SetVideoClippingFor(const media_source &output, const media_destination &destination, const int16 *shortsList, int32 shortCount, const media_video_display_info &display, void *userData, int32 *changeTag, void *_reserved_ = NULL)
This function requests that video buffers sent by the specified output to the specified destination clip all its writing in buffers it sends to the BBufferConsumer to the clipping region described by shortsList and shortCount. The clip data format is described in the section “Video Clipping”.
The Media Kit returns in changeTag the tag value that will be received by
your RequestCompleted()
function once the change
takes effect; the change tag lets you match up the call to
RequestCompleted()
with this request. This
function will receive a media_request_info
structure with the
indicated userData and changeTag.
The media_video_display_info
structure referenced by display
describes the current configuration of the video in terms of color space,
resolution, and so forth.
Return Code |
Description |
---|---|
|
The clipping request has been sent without errors. |
|
The clipping data isn’t formatted correctly. |
Port errors |
See Ports. |