Buffer Management by the Camera Driver (Windows Embedded CE 6.0)
1/6/2010
Buffers can be allocated either by camera driver or by the client. The client decides the whether it or the driver is responsible for allocating the buffer. The total number of buffers available to the client is limited either by the capabilities of the hardware, or by the number of DMA channels the client can allow for the driver to access system memory.
Allocation and Initialization
The number of buffers present in the driver at a given time is fixed. The client determines the capabilities of the hardware with respect to buffer allocation by querying for the CSPROPERTY_CONNECTION_ALLOCATORFRAMING property (see CSPROPERTY_CONNECTION) of the CSPROPSETID_Connection property set (see IOCTL_CS_PROPERTY).”
This will return the number of buffer that can be allocated and indicate the type of allocation; software or hardware. The client and driver negotiate the list of buffers as a part of the driver initialization process.
The buffers are passed between the client and the driver with the buffer header structure CSSTREAM_HEADER. The header may be followed by an optional CS_FRAME_INFO structure and additional information specific to the type of data in the data packet make up the header.
The minimum number of buffers for video capture streams cannot be guaranteed. The architecture is designed such that if there is a need for more than one buffer in the driver for performance reasons, then it is up to the driver developer to provide such support.
For the YUV 422 format, where there are 3 buffers, all buffers are treated as a single image and use up one buffer allocated by the driver.
Buffers allocated by the driver
In the case where the buffers are allocated in hardware memory, the driver must have its own memory allocator and the client must retrieve the list of allocated buffers from the driver.
A driver indicates its support for this buffer allocation model through the CSPROPERTY_BUFFER_DRIVER property (see CSPROPERTY_BUFFER_MODE).
The client determines which framing model the driver supports by querying for the CSPROPERTY_CONNECTION_ALLOCATORFRAMING property (see CSPROPERTY_CONNECTION) of the CSPROPSETID_Connection property set (see IOCTL_CS_PROPERTY).
The client retrieves the list of buffers by calling DeviceIoControl with IOCTL_CS_BUFFERS and specifying CS_ALLOCATE (see BUFFER_COMMANDS).
Buffers allocated by the client
In the case where the buffers are allocated in system memory, the client passes the list of buffers to the driver while the pin is in stop mode. Placing the pin in stop mode allows the driver to prepare for the direct memory access (DMA) operation to transfer the buffer. The client must initialize the buffers before it gives them to the driver. Once the client is done with the buffer, it must free the memory for the buffer. A client can take one of two different approaches for allocating buffers, depending on the direct memory access (DMA) capabilities of the client.
If the driver's DMA preparation time is slow then the driver needs to know in advance about all of the buffers that it will receive from the client. A driver indicates its support for this buffer allocation model through the CSPROPERTY_BUFFER_CLIENT_LIMITED property.
If the driver's DMA preparation time is fast then the client can allocate, initialize, and release buffers as they are needed. A driver indicates its support for this buffer allocation model through the CSPROPERTY_BUFFER_CLIENT_UNLIMITED property.
The client determines which framing model the driver supports by querying for the CSPROPERTY_CONNECTION_ALLOCATORFRAMING property.
The client negotiates the number of buffers through by calling DeviceIoControl with IOCTL_CS_PROPERTY and specifying the property CSPROPERTY_BUFFER_COUNT.
The client sends the buffers to the driver by using IOCTL_CS_BUFFERS and specifying CS_ENQUEUE. The client releases the processed buffers by using IOCTL_CS_BUFFERS and specifying CS_DEALLOCATE.
Buffer rotation
There are two buffer queues, one for idle buffers and the other for ready buffers. The client manages the queue of idle buffers and the driver manages the queue of ready buffers.
After the driver is initialized, all of the capture buffers are loaded in the client's idle queue. At this point, the driver aware of the buffers, but it has no control over them. To allow the driver to control a buffer, the client has to transfer that buffer from the idle queue to the ready queue. The client calls IOCTL_CS_PROPERTY with a SET operation on the CS_ENQUEUE property (see BUFFER_COMMANDS).
This IOCTL call takes a pointer to a CS_STREAM_DESCRIPTOR structure and returns a status. Both members of the CS_STREAM_DESCRIPTOR structure must be populated. The CS_STREAM_DESCRIPTOR structure is allocated by the application and must remain valid until the driver returns the buffer to the application.
When the driver receives the IOCTL call, it uses the handle to validate the pointer and then retrieves the shadow copy of the descriptor. It then associates the shadow copy to the descriptor and adds the buffer to the ready queue.
Once the hardware has filled the buffer, the driver returns the buffer to the application using the message queue. To do so, it sends back the pointer to the stream descriptor passed in through the Read function using the message queue.