The Media Kit: BBufferGroup

The Media Kit Table of Contents | The Media Kit Index

# BBufferGroup

Derived from: none

Declared in: be/media/BufferGroup.h

Library: libmedia.so

Allocation: Constructor only

###### Summary

A BBufferGroup serves as a repository for BBuffers, and can be used to pass those buffers to another node for its use when sending data. It must also be used by your BBufferProducer to acquire BBuffers to put data that you produce into before you send the buffer on to its destination.

You can create a new BBufferGroup by simply calling:

       new BBufferGroup;

If you pass in some arguments describing what sort of buffers you want, and how many of them, the group will even create the BBuffers for you. This is how you'll usually use BBufferGroup, from within your BBufferProducer subclass' constructor so you'll know there are buffers ready and waiting when it's time to start sending data. A possible exception is if your node is a filter that simply processes buffers it receives and passes them along.

A BBufferGroup instance runs a thread that reclaims BBuffers whose `Recycle()` function has been called. If the group is temporarily out of free buffers, a request for a buffer may block until one is available, or until the request times out, if a timeout is specified when the request is made.

## Using BBitmaps as Buffers

If you're doing video processing, you might want your buffers to be BBitmaps. Here's how you can accomplish this:

       BBufferGroup *my_group = new BBufferGroup;
       BBitmap *my_bitmap = new BBitmap(BRect(0,0,639,479), B_BITMAP_IS_AREA,
                   B_RGB32, 640*4);

       if (!my_bitmap->IsValid()) {
          return B_ERROR;
       }
       area_info bm_info;

       if (get_area_info(my_bitmap->Area(), &bm_info) != B_OK) {
          return B_ERROR;
       }

       buffer_clone_info bc_info;
       bc_info.area = bm_info.area;
       bc_info.offset = ((char *) my_bitmap->Bits())-((char *) bm_info.address);
       bc_info.size = my_bitmap->BitsLength();

       BBuffer *out_buffer = NULL;
       status_t err = my_group->AddBuffer(bc_info, &out_buffer);

       /* out_buffer is now set to use the BBitmap's memory */

This code takes advantage of the `B_BITMAP_IS_AREA` flag when creating the bitmap. This forces the bitmap to be in a memory area of its very own, which you can then use when creating the BBuffer.

If you need to do real-time accesses to the BBuffer, you should lock it down. In addition, if you use DMA, you'll need to specify for the buffer to be contiguous (you can do this using the BBitmap constructor, specifying the contiguous flag).

Before deleting any BBitmaps used in this way, be sure the buffer group has been deleted first and (if `SetOutputBuffersFor()` has been used) all buffers have been reclaimed.

## Constructor and Destructor

### BBufferGroup()

`BBufferGroup(`

size_t size, int32 numBuffers = 3,
uint32 placement = B_ANY_ADDRESS,
uint32 lock = B_FULL_LOCK`)`

`BBufferGroup(`void`)`
`BBufferGroup(`int32 numBuffers, const buffer_id *bufferList`)`

The first form of the constructor creates a BBufferGroup with some number of BBuffers already allocated by the group. These buffers will all live within a single Kernel Kit area, allocated by the group. The group tries to allocate an area with properties specified by the placement and lock arguments, large enough to hold numBuffers buffers of the specified size (there may be some padding added).

The second form of the constructor creates a BBufferGroup but doesn't create any buffers for it. You should add BBuffers to the group before trying to use it.

The third form of the constructor creates a BBufferGroup that contains the specified list of buffers. bufferList points to an array of buffer IDs for the buffers to be controlled by the group, and numBuffers is the number of buffers in the list. This version of the constructor isn't one you'll use very often.

Before using any buffers from a new BBufferGroup, call `InitCheck()` to determine if any errors occurred while creating the group.

### ~BBufferGroup

`~BBufferGroup()`

Releases all memory used by the BBufferGroup, including the BBuffers it controls.

Keep in mind that `AddBuffer()` clones the buffer area. This destructor releases the clones, but it's your application's job to release the original area you added.

Your node needs to delete the buffer group corresponding to any connection that is disconnected or whenever the node is deleted. Until your node does so, the other end of the connection will be blocked waiting for the buffer group to be deleted.

## Member Functions

### AddBuffer()

status_t `AddBuffer(`const buffer_clone_info &info`) `

Given the buffer_clone_info, this function clones the buffer and adds the clone to the BBufferGroup. Normally you'll fill out the buffer_clone_info structure yourself.

Since the buffer is cloned, you'll need to delete the original memory area specified by the buffer_clone_info structure yourself when you're no longer using it; the BBufferGroup won't do it for you.

| You shouldn't pass the result of a `BBuffer::CloneInfo()` call to this function, as doing so would create an "alias" buffer for the same memory area. This is probably not the effect you want.

RETURN CODES

`B_OK`. No error adding the buffer to the group.

- `B_NO_MEMORY`. Couldn't clone the buffer into the BBufferGroup's address space.

### AddBuffersTo()

status_t `AddBuffersTo(` BMessage *message, const char *name, bool needLock = true`) `

Adds the group's buffers to the specified message, storing them in an array with the specified name. If needLock is `true`, the BBufferGroup is locked before performing the operation, then unlocked when finished; otherwise, you guarantee that the buffers won't go anywhere during the `AddBuffersTo()` call.

The buffers are added by ID number, and are therefore in int32 format.

RETURN CODES

`B_OK`. No error adding the buffers to the message.

- Errors from `AddInt32()`.

### CountBuffers()

status_t `CountBuffers(`int32 *outBufferCount`) `

Returns, in outBufferCount, the number of buffers in the group.

RETURN CODES

`B_OK`. The number of buffers was returned successfully.

- `B_BAD_VALUE`. Invalid outBufferCount pointer.

### GetBufferList()

status_t `GetBufferList(`int32 listCount, BBuffer **outBuffers`) `

Returns a list of all the buffers in the group. When calling `GetBufferList()`, pass in outBuffers a pointer to an array of BBuffer pointers that you want to be filled with pointers to the group's buffers, and specify the number of elements in the array in listCount.

RETURN CODES

`B_OK`. No errors.

- `B_BAD_VALUE`. listCount is less than 1, or outBuffers is `NULL

  `

### InitCheck()

status_t `InitCheck(`void`) `

Returns the error code resulting from the construction of the BBufferGroup.

RETURN CODES

`B_OK`. The new group was created successfully.

- `B_ERROR`. Couldn't allocate the buffers for the group.

- Area errors. See

  # Areas

  in

  # The Kernel Kit

  .

### ReclaimAllBuffers()

status_t `ReclaimAllBuffers(`void`) `

If you pass a buffer group to some other BBufferProducer but pass `true` for willReclaim in the `BMediaRoster::SetOutputBuffers()` call, you can later reclaim the buffers into the BBufferGroup by calling `Reclaim()`.

`ReclaimAllBuffers()` will return `B_OK` when all buffers are accounted for, or return an error if buffers can't be reclaimed.

If you have buffers that reference some object that might go away (such as a BBitmap), you should call `ReclaimAllBuffers()` on the group and delete the BBufferGroup before that object goes away.

Before reclaiming your buffers, be sure to call `BMediaRoster::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 `ReclaimAllBuffers()` call will hang, possibly forever.

RETURN CODES

`B_OK`. All buffers reclaimed successfully.

- `B_MEDIA_CANNOT_RECLAIM_BUFFERS`. Some buffers couldn't be reclaimed.

### RequestBuffer()

BBuffer *`Request` `Buffer(`size_t size, bigtime_t timeout = B_INFINITE_TIMEOUT`) `
status_t `RequestBuffer(` BBuffer *outBuffer, bigtime_t timeout = B_INFINITE_TIMEOUT`) `

Returns a pointer to a BBuffer of at least the specified size that your BBufferProducer subclass can put data into, then pass on to a `media_destination`. If there isn't a suitable buffer available, the call will block until either a buffer becomes available (in which case the buffer is returned) or the specified timeout is reached.

If you pass a timeout value that's less than zero, `RequestBuffer()` will return `NULL` immediately if there's no buffer available, otherwise it will return a pointer to a buffer you can use.

| In BeOS Release 4.5, the timeout is ignored (unless you specify a negative value); `B_INFINITE_TIMEOUT` is always used, regardless of the value you specify.

`RequestBuffer()` doesn't use the buffer flags; instead, you can look at the buffers within a BBufferGroup to find a specific buffer to request yourself, based on the value returned by `BBuffer::Flags()` or `BBuffer::Size()`, for example. Use the second form of `RequestBuffer()` to obtain a specific buffer.

The first version of `RequestBuffer()` returns `NULL` if no buffer can be obtained, and sets errno to the appropriate error code. The second version returns an appropriate error code.

Don't call `RequestBuffer()` while an outstanding `ReclaimAllBuffers()` request is pending. To make sure that doesn't happen, a buffer producer should be designed to not know about the old group anymore once `SetBufferGroup()` is called to change its buffer group.

RETURN CODES

`B_OK`. No errors.

- `B_MEDIA_BUFFERS_NOT_RECLAIMED`. Buffers are in the process of being reclaimed.

- `B_ERROR`. A miscellaneous error occurred.

### RequestError()

status_t `RequestError``(`void`) `

Returns the last `RequestBuffer()` error. This is useful if `RequestBuffer()` returns `NULL`.

### WaitForBuffers()

status_t `WaitForBuffers``(`void`) `

Waits until the currently pending buffer reclamation is finished, then returns. If there isn't a buffer reclamation in progress, returns immediately.

RETURN CODES

B_OK. No error.

- Semaphore errors. Unable to acquire the semaphore used to detect that buffer reclamation is done.

The Media Kit Table of Contents | The Media Kit Index

The Be Book,
...in lovely HTML...
for BeOS Release 5.

Copyright © 2000 Be, Inc. All rights reserved..