dshow: allow user to specify audio buffer size

Based on patch by rogerdpack <rogerpack2005@gmail.com>

Tested-by: Roger Pack <rogerdpack2@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Ramiro Polla 2012-08-25 05:09:37 -03:00 committed by Michael Niedermayer
parent a5704659e3
commit ad7fae4ee1
2 changed files with 60 additions and 0 deletions

View File

@ -112,6 +112,15 @@ defaults to 0).
Set audio device number for devices with same name (starts at 0,
defaults to 0).
@item audio_buffer_size
Set audio device buffer size in milliseconds (which can directly
impact latency, depending on the device).
Defaults to using the audio device's
default buffer size (typically some multiple of 500ms).
Setting this value too low can degrade performance.
See also
@url{http://msdn.microsoft.com/en-us/library/windows/desktop/dd377582(v=vs.85).aspx}
@end table
@subsection Examples

View File

@ -36,6 +36,7 @@ struct dshow_ctx {
int list_options;
int list_devices;
int audio_buffer_size;
IBaseFilter *device_filter[2];
IPin *device_pin[2];
@ -446,6 +447,51 @@ end:
*pformat_set = format_set;
}
/**
* Set audio device buffer size in milliseconds (which can directly impact
* latency, depending on the device).
*/
static int
dshow_set_audio_buffer_size(AVFormatContext *avctx, IPin *pin)
{
struct dshow_ctx *ctx = avctx->priv_data;
IAMBufferNegotiation *buffer_negotiation = NULL;
ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
IAMStreamConfig *config = NULL;
AM_MEDIA_TYPE *type = NULL;
int ret = AVERROR(EIO);
if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
goto end;
if (IAMStreamConfig_GetFormat(config, &type) != S_OK)
goto end;
if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
goto end;
props.cbBuffer = (((WAVEFORMATEX *) type->pbFormat)->nAvgBytesPerSec)
* ctx->audio_buffer_size / 1000;
if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (void **) &buffer_negotiation) != S_OK)
goto end;
if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) != S_OK)
goto end;
ret = 0;
end:
if (buffer_negotiation)
IAMBufferNegotiation_Release(buffer_negotiation);
if (type) {
if (type->pbFormat)
CoTaskMemFree(type->pbFormat);
CoTaskMemFree(type);
}
if (config)
IAMStreamConfig_Release(config);
return ret;
}
/**
* Cycle through available pins using the device_filter device, of type
* devtype, retrieve the first output pin and return the pointer to the
@ -513,6 +559,10 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
goto next;
}
}
if (devtype == AudioDevice && ctx->audio_buffer_size) {
if (dshow_set_audio_buffer_size(avctx, pin) < 0)
goto next;
}
if (IPin_EnumMediaTypes(pin, &types) != S_OK)
goto next;
@ -952,6 +1002,7 @@ static const AVOption options[] = {
{ "false", "", 0, AV_OPT_TYPE_CONST, {.dbl=0}, 0, 0, DEC, "list_options" },
{ "video_device_number", "set video device number for devices with same name (starts at 0)", OFFSET(video_device_number), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
{ "audio_device_number", "set audio device number for devices with same name (starts at 0)", OFFSET(audio_device_number), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
{ "audio_buffer_size", "set audio device buffer latency size in milliseconds (default is the device's default)", OFFSET(audio_buffer_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
{ NULL },
};