aboutsummaryrefslogtreecommitdiffstats
path: root/libavdevice
diff options
context:
space:
mode:
authorRamiro Polla <ramiro.polla@gmail.com>2012-08-25 05:09:37 -0300
committerMichael Niedermayer <michaelni@gmx.at>2012-08-29 18:58:20 +0200
commitad7fae4ee1f9c1c080bb4c8760ac503a11420bba (patch)
treec43ee28b5939814502e88831950030c98dc1b8cf /libavdevice
parenta5704659e3e41b7698812b89f67d9a7467a74d20 (diff)
downloadffmpeg-ad7fae4ee1f9c1c080bb4c8760ac503a11420bba.tar.gz
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>
Diffstat (limited to 'libavdevice')
-rw-r--r--libavdevice/dshow.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c
index ea6c21cc6a..18adf8f0fb 100644
--- a/libavdevice/dshow.c
+++ b/libavdevice/dshow.c
@@ -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];
@@ -447,6 +448,51 @@ end:
}
/**
+ * 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
* object found in *ppin.
@@ -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 },
};