Application Session Buffers (Windows CE 5.0)
Buffers are just memory ranges allocated by the application. When an application attaches a buffer to a session, it is given an opaque buffer identifier value to represent the buffer in later calls. This identifier is valid until the buffer is detached. You will need to know the required size of the buffer, as the AVC_STREAM driver will inherently expect a certain minimum size. The developer should utilize IOCTL_STREAM_GET_MEDIA_SIZE to determine the appropriate buffer size, which this IOCTL returns as the frame size. For some media types, you can utilize a different frame size than the default, and can inform AVC_STREAM of this by calling IOCTL_STREAM_SET_MEDIA_SIZE. If you do this, the change is applicable to the next session started against the same CreateFile handle.
Buffer processing involves attaching the buffer, querying whether the buffer has completed or not, and detaching the buffer.
Application Session Buffer Attachment
An application can attach buffers to a session by using the IOCTL_STREAM_ATTACH_BUFFER command. The buffers are attached in order that they are provided in the STREAM_AttachBuffers_Request structure, and are processed by the streaming filter driver in that order. When the IOCTL completes, the STREAM_AttachBuffers_Response structure is filled in with an array of buffer identifier values, one for each buffer provided in the request, and they are one to one associated. This means that the first buffer in the request array will be assigned the first buffer identifier returned. The second buffer in the request array will be assigned the second buffer identifier returned, and so on.
At attachment time, each buffer must be provided to IOCTL_STREAM_ATTACH_BUFFER by both a pointer to the application buffer memory, and by a length value. This length value represents the amount of data to attempt to read in, for receive sessions, and the amount of data to transmit, for transmit sessions.
Application Session Buffer Detachment
Detaching a buffer requires only that the application provide an array of buffer identifiers, the same values that were returned by the attachment procedure, to the IOCTL_STREAM_DETACH_BUFFER command in the STREAM_DetachBuffers_Request structure. For each buffer identifier value included, if the buffer is not found, not attached or an illegal buffer identifier value, it is skipped. If it is attached, it will be immediately detached, whether complete or not.
If buffers are attached to a session when that session is stopped due to an IOCTL_STREAM_STOP_SESSION command, or even due to someone removing the physical device from the IEEE 1394 bus, all attached buffers will be automatically detached*.*
Application Session Buffer State Determination
The application can determine which attached buffers are complete by utilizing the IOCTL_STREAM_QUERY_BUFFER_STATE command. This command refers to a particular session and will return an array of buffer identifier values that represent those buffers that are still attached, but have reached completion state. That is, buffers that should be detached and processed by the application.
The IOCTL_STREAM_QUERY_BUFFER_STATE command will typically return immediately, even if no buffers are completed. To prevent potential polling, the application can optionally set a flag in the command's request, STREAM_QueryBufferState_Flag_Block, that causes the command to not complete until at least a single buffer has reached the completion state.
If the session in question is stopped for any reason and any IOCTL_STREAM_QUERY_BUFFER_STATE commands are still pending, these commands will immediately fail with an error.
Typical Application Session Buffer Processing
Dealing with streaming issues and buffers requires that the application be prepared to manage a collection of data describing which buffers are in which state. It is advantageous for the application to attach many buffers to a session at once, both to spread the overhead of the IOCTL call out over several buffers, and also to double, triple, or further multiply the buffer data.
The following is an example of the general flow for a receive session:
- Application allocates many buffers and places them in a queue of unused buffers.
- Application attaches as many free buffers as it can to the session. The application associates its buffer pointers and lengths to the returned buffer identifiers.
- Application issues a query against the session, requesting to block until at least one buffer completes.
- When the query completes, for each buffer identifier returned, the application detaches the appropriate buffer, and places those buffers on a queue of completed, but unprocessed, buffers.
- The application processes the completed buffers, extracting the received data from each, and adds them to the queue of unused buffers.
- Repeat from step 2.
The flow for a transmit session differs only in where the data processing occurs. The following is an example of the general flow for a transmit session:
- Application allocates many buffers and places them in a queue of unused buffers.
- Application fills as many unused buffers with transmit data as it can, and attaches them to the session. The application associates its buffer pointers and lengths to the returned buffer identifiers.
- Application issues a query against the session, requesting to block until at least one buffer completes.
- When the query completes, for each buffer identifier returned, the application detaches the appropriate buffer, and places those buffers on a queue of completed, but unprocessed, buffers.
- Repeat from step 2.
Both of these lists of actions can easily be expanded to permit for multithreading, which would allow processing of data while other data is being completed.
Send Feedback on this topic to the authors