Transferring Multimedia Data to and from Device Drivers

The primary purpose of a multimedia device driver is to transfer data between an application and the audio or video device. The data-transfer model used depends on the data transferred and the device involved. For example, the model for data transfer is different for waveform devices than it is for MIDI devices because of the nature of the data. Auxiliary audio devices don't require the transfer of audio data, just control information.

Single-Frame Data Capture

Single-frame data capture supports simple video capture. Applications might use this form of data capture to record animated sequences created frame-by-frame or, to capture a single still image, such as a photograph.

This data transfer model typically involves a high data-transfer rate. It is similar to streaming data, except it does not require the continuous transfer of data. The following sequence of operations occurs when a client application requests the transfer of a single video frame:

1 The client allocates the memory for the data buffer.

2 The client sets a pointer to the empty data buffer in a data structure and sends the device driver a pointer to it.

3 When the device driver receives the messages to capture data, it fills the data buffer with information from the frame buffer and updates the data structure.

4 When the device driver has filled a data buffer, it returns control to the client.

5 After the client has finished with the data, it frees the memory used for the data.

Streaming Data Transfer

Waveform and video streams involve the continuous flow of real-time audio and video data. Typically, these streams involve a high data-transfer rate and require significant processor time.

The data-transfer model for streaming audio and video input is similar. If you have worked with waveform or video-capture device drivers, many of the concepts you already understand apply to the other type of driver.

The following sequence of operations occurs when streaming waveform or video data between a device driver and a client application:

1 The client allocates the memory buffers for the audio or video data.

2 If required, the client initializes the data stream.

3 The client requests that the driver prepare the data buffers.

4 The client sends the empty data buffers to the driver.

5 The driver puts the data buffers in its input queue.

6 When the streaming operation begins, the driver fills a data buffer and sets the done bit for the data buffer. The driver then releases the buffer from its queue and proceeds to fill the next buffer.

7 When the client is ready for data, it uses the done bit or a callback to see if the data in the buffer is ready.

8 After the client empties the buffer, it resets the done bit and sends the empty buffer back to the driver for it to add to its queue.

Once the stream starts, the client application and the audio and video device driver do not communicate directly. The device driver fills the data buffers at the data rate specified by the client application. It fills the buffers without waiting for any synchronization signal from the application, as long as buffers are available and it is not paused or stopped by the application. The buffers are filled in the order that the driver receives them from the application. (If the device driver runs out of buffers, it should set an error flag. A client video application can use the DVM_STREAM_GETERROR message to test for this condition.)

The client application expects the buffers back in the order that it sends them to the device driver. When it is ready for more data, it checks the done bit of the next buffer it expects to receive from the device driver. If the done bit is set, the application continues operation with that buffer. If the done bit is not set, the application periodically checks the done bit while it waits for the buffer.

Streaming continues until it is stopped by the application. The following sequence of operations occurs when the application has finished capturing data:

Preparing Data Buffers

Because audio and video data buffers must be accessed at interrupt time, the memory allocated for them is subject to the requirements mentioned in . Rather than have the client application prepare the memory before sending data blocks to the driver, the client requests that the driver make the preparations.

This request involves two messages, in the form of _PREPARE and _UNPREPARE. Most drivers can respond to these messages by returning a MMSYSERR_NOTSUPPORTED error. Then, MMSYSTEM prepares the data block by page-locking it so the driver can access it at interrupt time. For example, most drivers can respond to the DVM_STREAM_PREPAREHEADER and DVM_STREAM_UNPREPAREHEADER messages by returning a DV_ERR_UNSUPPORTED error. When a driver returns the DV_ERR_UNSUPPORTED error, MMSYSTEM prepares the data block by page-locking the header and data sections so the driver can access them at interrupt time.

If a device driver does not need page-locked data (for example, if the application immediately copies the data to an on-card buffer) or if the buffer requires additional preparation, the application can respond to these messages directly instead of letting MMSYSTEM handle them. An application should respond to both messages, or to neither.

The following table identifies the drivers that use these messages, and the name of the prepare and unprepare messages.

Driver type

Prepare/unprepare message

MIDI input

MIDM_PREPARE

MIDM_UNPREPARE

MIDI output

MODM_PREPARE

MODM_UNPREPARE

Waveform audio input

WIDM_PREPARE

WIDM_UNPREPARE

Waveform audio output

WODM_PREPARE

WODM_UNPREPARE

Video capture

DVM_STREAM_PREPAREHEADER

DVM_STREAM_UNPREPAREHEADER

Audio compression and decompression

ACMDM_STREAMPREPARE

ACMDM_STREAMUNPREPARE


Data Transfer Using the Audio Compression Manager

If the Audio Compression Manager (ACM) is involved in the transfer, the data transfer model is as follows:

1 The client allocates the memory for the source and destination buffers. The ACMDM_STREAM_PREPARE message prepares the buffers.

2 The client sends both source and destination data blocks to the driver.

3 The driver processes the data blocks.

4 The driver (codec) returns the data to the client. The ACMDM_STREAM_UNPREPARE message releases the buffers, reversing the preparations made earlier by the ACMDM_STREAM_PREPARE message.

5 The client then frees the memory for both data blocks.

Data Transfer Using Waveform Device Drivers

The following sequence of operations occurs when transferring audio data between a client application and a waveform-output device driver:

1 The client allocates the memory for the data block.

2 The client requests that the driver prepare the data block.

3 The client sends the data block to the driver.

4 The driver puts the data block in its output queue.

5 The client can send additional data blocks, which the driver also puts in its output queue.

6 When the driver has sent a data block from its output queue to its output device, it returns the data block to the client by sending the client a message.

7 The client requests that the driver clean up the preparation previously done on the data block.

8 The client then frees the memory for the data block.

In addition, the driver must transfer the data it receives from the client to the waveform hardware. This transfer takes place in the background, as an interrupt-driven process. The driver can transfer data directly, or it can use the computer's DMA controller to transfer the data. Whether you choose to transfer data directly or use DMA depends on the capabilities of your target hardware.

For input devices, the model is similar, except the client sends the driver an empty buffer. The buffer is directly filled with audio data by the driver or with DMA. The driver notifies the client when the buffer is filled.

Data Transfer Using MIDI Device Drivers

With MIDI system-exclusive events, data transfer between a client application and a MIDI device driver is identical to the sequence described for waveform and video drivers. However, for all other MIDI events, the driver uses a different transfer mechanism. Because all other MIDI events are 3 bytes or fewer in size, they are packed into a DWORD and sent directly to the driver for output. The driver parses the event to determine its size, and sends the individual bytes to the MIDI output hardware. If the driver is for an internal synthesizer, it parses the event and responds accordingly. MIDI-input device drivers wait until receiving a complete MIDI event before packing the event into a DWORD and sending it to the client application through its callback.