annotate ffmpeg/libavdevice/dshow.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Directshow capture interface
yading@10 3 * Copyright (c) 2010 Ramiro Polla
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 #include "libavutil/parseutils.h"
yading@10 23 #include "libavutil/pixdesc.h"
yading@10 24 #include "libavutil/opt.h"
yading@10 25 #include "libavformat/internal.h"
yading@10 26 #include "libavformat/riff.h"
yading@10 27 #include "avdevice.h"
yading@10 28 #include "dshow_capture.h"
yading@10 29 #include "libavcodec/raw.h"
yading@10 30
yading@10 31 struct dshow_ctx {
yading@10 32 const AVClass *class;
yading@10 33
yading@10 34 IGraphBuilder *graph;
yading@10 35
yading@10 36 char *device_name[2];
yading@10 37 int video_device_number;
yading@10 38 int audio_device_number;
yading@10 39
yading@10 40 int list_options;
yading@10 41 int list_devices;
yading@10 42 int audio_buffer_size;
yading@10 43
yading@10 44 IBaseFilter *device_filter[2];
yading@10 45 IPin *device_pin[2];
yading@10 46 libAVFilter *capture_filter[2];
yading@10 47 libAVPin *capture_pin[2];
yading@10 48
yading@10 49 HANDLE mutex;
yading@10 50 HANDLE event[2]; /* event[0] is set by DirectShow
yading@10 51 * event[1] is set by callback() */
yading@10 52 AVPacketList *pktl;
yading@10 53
yading@10 54 int eof;
yading@10 55
yading@10 56 int64_t curbufsize;
yading@10 57 unsigned int video_frame_num;
yading@10 58
yading@10 59 IMediaControl *control;
yading@10 60 IMediaEvent *media_event;
yading@10 61
yading@10 62 enum AVPixelFormat pixel_format;
yading@10 63 enum AVCodecID video_codec_id;
yading@10 64 char *framerate;
yading@10 65
yading@10 66 int requested_width;
yading@10 67 int requested_height;
yading@10 68 AVRational requested_framerate;
yading@10 69
yading@10 70 int sample_rate;
yading@10 71 int sample_size;
yading@10 72 int channels;
yading@10 73 };
yading@10 74
yading@10 75 static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
yading@10 76 {
yading@10 77 switch(biCompression) {
yading@10 78 case BI_BITFIELDS:
yading@10 79 case BI_RGB:
yading@10 80 switch(biBitCount) { /* 1-8 are untested */
yading@10 81 case 1:
yading@10 82 return AV_PIX_FMT_MONOWHITE;
yading@10 83 case 4:
yading@10 84 return AV_PIX_FMT_RGB4;
yading@10 85 case 8:
yading@10 86 return AV_PIX_FMT_RGB8;
yading@10 87 case 16:
yading@10 88 return AV_PIX_FMT_RGB555;
yading@10 89 case 24:
yading@10 90 return AV_PIX_FMT_BGR24;
yading@10 91 case 32:
yading@10 92 return AV_PIX_FMT_RGB32;
yading@10 93 }
yading@10 94 }
yading@10 95 return avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, biCompression); // all others
yading@10 96 }
yading@10 97
yading@10 98 static int
yading@10 99 dshow_read_close(AVFormatContext *s)
yading@10 100 {
yading@10 101 struct dshow_ctx *ctx = s->priv_data;
yading@10 102 AVPacketList *pktl;
yading@10 103
yading@10 104 if (ctx->control) {
yading@10 105 IMediaControl_Stop(ctx->control);
yading@10 106 IMediaControl_Release(ctx->control);
yading@10 107 }
yading@10 108
yading@10 109 if (ctx->media_event)
yading@10 110 IMediaEvent_Release(ctx->media_event);
yading@10 111
yading@10 112 if (ctx->graph) {
yading@10 113 IEnumFilters *fenum;
yading@10 114 int r;
yading@10 115 r = IGraphBuilder_EnumFilters(ctx->graph, &fenum);
yading@10 116 if (r == S_OK) {
yading@10 117 IBaseFilter *f;
yading@10 118 IEnumFilters_Reset(fenum);
yading@10 119 while (IEnumFilters_Next(fenum, 1, &f, NULL) == S_OK) {
yading@10 120 if (IGraphBuilder_RemoveFilter(ctx->graph, f) == S_OK)
yading@10 121 IEnumFilters_Reset(fenum); /* When a filter is removed,
yading@10 122 * the list must be reset. */
yading@10 123 IBaseFilter_Release(f);
yading@10 124 }
yading@10 125 IEnumFilters_Release(fenum);
yading@10 126 }
yading@10 127 IGraphBuilder_Release(ctx->graph);
yading@10 128 }
yading@10 129
yading@10 130 if (ctx->capture_pin[VideoDevice])
yading@10 131 libAVPin_Release(ctx->capture_pin[VideoDevice]);
yading@10 132 if (ctx->capture_pin[AudioDevice])
yading@10 133 libAVPin_Release(ctx->capture_pin[AudioDevice]);
yading@10 134 if (ctx->capture_filter[VideoDevice])
yading@10 135 libAVFilter_Release(ctx->capture_filter[VideoDevice]);
yading@10 136 if (ctx->capture_filter[AudioDevice])
yading@10 137 libAVFilter_Release(ctx->capture_filter[AudioDevice]);
yading@10 138
yading@10 139 if (ctx->device_pin[VideoDevice])
yading@10 140 IPin_Release(ctx->device_pin[VideoDevice]);
yading@10 141 if (ctx->device_pin[AudioDevice])
yading@10 142 IPin_Release(ctx->device_pin[AudioDevice]);
yading@10 143 if (ctx->device_filter[VideoDevice])
yading@10 144 IBaseFilter_Release(ctx->device_filter[VideoDevice]);
yading@10 145 if (ctx->device_filter[AudioDevice])
yading@10 146 IBaseFilter_Release(ctx->device_filter[AudioDevice]);
yading@10 147
yading@10 148 if (ctx->device_name[0])
yading@10 149 av_free(ctx->device_name[0]);
yading@10 150 if (ctx->device_name[1])
yading@10 151 av_free(ctx->device_name[1]);
yading@10 152
yading@10 153 if(ctx->mutex)
yading@10 154 CloseHandle(ctx->mutex);
yading@10 155 if(ctx->event[0])
yading@10 156 CloseHandle(ctx->event[0]);
yading@10 157 if(ctx->event[1])
yading@10 158 CloseHandle(ctx->event[1]);
yading@10 159
yading@10 160 pktl = ctx->pktl;
yading@10 161 while (pktl) {
yading@10 162 AVPacketList *next = pktl->next;
yading@10 163 av_destruct_packet(&pktl->pkt);
yading@10 164 av_free(pktl);
yading@10 165 pktl = next;
yading@10 166 }
yading@10 167
yading@10 168 CoUninitialize();
yading@10 169
yading@10 170 return 0;
yading@10 171 }
yading@10 172
yading@10 173 static char *dup_wchar_to_utf8(wchar_t *w)
yading@10 174 {
yading@10 175 char *s = NULL;
yading@10 176 int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
yading@10 177 s = av_malloc(l);
yading@10 178 if (s)
yading@10 179 WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
yading@10 180 return s;
yading@10 181 }
yading@10 182
yading@10 183 static int shall_we_drop(AVFormatContext *s)
yading@10 184 {
yading@10 185 struct dshow_ctx *ctx = s->priv_data;
yading@10 186 const uint8_t dropscore[] = {62, 75, 87, 100};
yading@10 187 const int ndropscores = FF_ARRAY_ELEMS(dropscore);
yading@10 188 unsigned int buffer_fullness = (ctx->curbufsize*100)/s->max_picture_buffer;
yading@10 189
yading@10 190 if(dropscore[++ctx->video_frame_num%ndropscores] <= buffer_fullness) {
yading@10 191 av_log(s, AV_LOG_ERROR,
yading@10 192 "real-time buffer %d%% full! frame dropped!\n", buffer_fullness);
yading@10 193 return 1;
yading@10 194 }
yading@10 195
yading@10 196 return 0;
yading@10 197 }
yading@10 198
yading@10 199 static void
yading@10 200 callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time)
yading@10 201 {
yading@10 202 AVFormatContext *s = priv_data;
yading@10 203 struct dshow_ctx *ctx = s->priv_data;
yading@10 204 AVPacketList **ppktl, *pktl_next;
yading@10 205
yading@10 206 // dump_videohdr(s, vdhdr);
yading@10 207
yading@10 208 WaitForSingleObject(ctx->mutex, INFINITE);
yading@10 209
yading@10 210 if(shall_we_drop(s))
yading@10 211 goto fail;
yading@10 212
yading@10 213 pktl_next = av_mallocz(sizeof(AVPacketList));
yading@10 214 if(!pktl_next)
yading@10 215 goto fail;
yading@10 216
yading@10 217 if(av_new_packet(&pktl_next->pkt, buf_size) < 0) {
yading@10 218 av_free(pktl_next);
yading@10 219 goto fail;
yading@10 220 }
yading@10 221
yading@10 222 pktl_next->pkt.stream_index = index;
yading@10 223 pktl_next->pkt.pts = time;
yading@10 224 memcpy(pktl_next->pkt.data, buf, buf_size);
yading@10 225
yading@10 226 for(ppktl = &ctx->pktl ; *ppktl ; ppktl = &(*ppktl)->next);
yading@10 227 *ppktl = pktl_next;
yading@10 228
yading@10 229 ctx->curbufsize += buf_size;
yading@10 230
yading@10 231 SetEvent(ctx->event[1]);
yading@10 232 ReleaseMutex(ctx->mutex);
yading@10 233
yading@10 234 return;
yading@10 235 fail:
yading@10 236 ReleaseMutex(ctx->mutex);
yading@10 237 return;
yading@10 238 }
yading@10 239
yading@10 240 /**
yading@10 241 * Cycle through available devices using the device enumerator devenum,
yading@10 242 * retrieve the device with type specified by devtype and return the
yading@10 243 * pointer to the object found in *pfilter.
yading@10 244 * If pfilter is NULL, list all device names.
yading@10 245 */
yading@10 246 static int
yading@10 247 dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
yading@10 248 enum dshowDeviceType devtype, IBaseFilter **pfilter)
yading@10 249 {
yading@10 250 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 251 IBaseFilter *device_filter = NULL;
yading@10 252 IEnumMoniker *classenum = NULL;
yading@10 253 IMoniker *m = NULL;
yading@10 254 const char *device_name = ctx->device_name[devtype];
yading@10 255 int skip = (devtype == VideoDevice) ? ctx->video_device_number
yading@10 256 : ctx->audio_device_number;
yading@10 257 int r;
yading@10 258
yading@10 259 const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
yading@10 260 &CLSID_AudioInputDeviceCategory };
yading@10 261 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
yading@10 262
yading@10 263 r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[devtype],
yading@10 264 (IEnumMoniker **) &classenum, 0);
yading@10 265 if (r != S_OK) {
yading@10 266 av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices.\n",
yading@10 267 devtypename);
yading@10 268 return AVERROR(EIO);
yading@10 269 }
yading@10 270
yading@10 271 while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {
yading@10 272 IPropertyBag *bag = NULL;
yading@10 273 char *buf = NULL;
yading@10 274 VARIANT var;
yading@10 275
yading@10 276 r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);
yading@10 277 if (r != S_OK)
yading@10 278 goto fail1;
yading@10 279
yading@10 280 var.vt = VT_BSTR;
yading@10 281 r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);
yading@10 282 if (r != S_OK)
yading@10 283 goto fail1;
yading@10 284
yading@10 285 buf = dup_wchar_to_utf8(var.bstrVal);
yading@10 286
yading@10 287 if (pfilter) {
yading@10 288 if (strcmp(device_name, buf))
yading@10 289 goto fail1;
yading@10 290
yading@10 291 if (!skip--)
yading@10 292 IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);
yading@10 293 } else {
yading@10 294 av_log(avctx, AV_LOG_INFO, " \"%s\"\n", buf);
yading@10 295 }
yading@10 296
yading@10 297 fail1:
yading@10 298 if (buf)
yading@10 299 av_free(buf);
yading@10 300 if (bag)
yading@10 301 IPropertyBag_Release(bag);
yading@10 302 IMoniker_Release(m);
yading@10 303 }
yading@10 304
yading@10 305 IEnumMoniker_Release(classenum);
yading@10 306
yading@10 307 if (pfilter) {
yading@10 308 if (!device_filter) {
yading@10 309 av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n",
yading@10 310 devtypename);
yading@10 311 return AVERROR(EIO);
yading@10 312 }
yading@10 313 *pfilter = device_filter;
yading@10 314 }
yading@10 315
yading@10 316 return 0;
yading@10 317 }
yading@10 318
yading@10 319 /**
yading@10 320 * Cycle through available formats using the specified pin,
yading@10 321 * try to set parameters specified through AVOptions and if successful
yading@10 322 * return 1 in *pformat_set.
yading@10 323 * If pformat_set is NULL, list all pin capabilities.
yading@10 324 */
yading@10 325 static void
yading@10 326 dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
yading@10 327 IPin *pin, int *pformat_set)
yading@10 328 {
yading@10 329 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 330 IAMStreamConfig *config = NULL;
yading@10 331 AM_MEDIA_TYPE *type = NULL;
yading@10 332 int format_set = 0;
yading@10 333 void *caps = NULL;
yading@10 334 int i, n, size;
yading@10 335
yading@10 336 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
yading@10 337 return;
yading@10 338 if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK)
yading@10 339 goto end;
yading@10 340
yading@10 341 caps = av_malloc(size);
yading@10 342 if (!caps)
yading@10 343 goto end;
yading@10 344
yading@10 345 for (i = 0; i < n && !format_set; i++) {
yading@10 346 IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
yading@10 347
yading@10 348 #if DSHOWDEBUG
yading@10 349 ff_print_AM_MEDIA_TYPE(type);
yading@10 350 #endif
yading@10 351
yading@10 352 if (devtype == VideoDevice) {
yading@10 353 VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
yading@10 354 BITMAPINFOHEADER *bih;
yading@10 355 int64_t *fr;
yading@10 356 #if DSHOWDEBUG
yading@10 357 ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps);
yading@10 358 #endif
yading@10 359 if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {
yading@10 360 VIDEOINFOHEADER *v = (void *) type->pbFormat;
yading@10 361 fr = &v->AvgTimePerFrame;
yading@10 362 bih = &v->bmiHeader;
yading@10 363 } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {
yading@10 364 VIDEOINFOHEADER2 *v = (void *) type->pbFormat;
yading@10 365 fr = &v->AvgTimePerFrame;
yading@10 366 bih = &v->bmiHeader;
yading@10 367 } else {
yading@10 368 goto next;
yading@10 369 }
yading@10 370 if (!pformat_set) {
yading@10 371 enum AVPixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
yading@10 372 if (pix_fmt == AV_PIX_FMT_NONE) {
yading@10 373 enum AVCodecID codec_id = ff_codec_get_id(avformat_get_riff_video_tags(), bih->biCompression);
yading@10 374 AVCodec *codec = avcodec_find_decoder(codec_id);
yading@10 375 if (codec_id == AV_CODEC_ID_NONE || !codec) {
yading@10 376 av_log(avctx, AV_LOG_INFO, " unknown compression type 0x%X", (int) bih->biCompression);
yading@10 377 } else {
yading@10 378 av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name);
yading@10 379 }
yading@10 380 } else {
yading@10 381 av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt));
yading@10 382 }
yading@10 383 av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
yading@10 384 vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
yading@10 385 1e7 / vcaps->MaxFrameInterval,
yading@10 386 vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
yading@10 387 1e7 / vcaps->MinFrameInterval);
yading@10 388 continue;
yading@10 389 }
yading@10 390 if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
yading@10 391 if (ctx->video_codec_id != ff_codec_get_id(avformat_get_riff_video_tags(), bih->biCompression))
yading@10 392 goto next;
yading@10 393 }
yading@10 394 if (ctx->pixel_format != AV_PIX_FMT_NONE &&
yading@10 395 ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) {
yading@10 396 goto next;
yading@10 397 }
yading@10 398 if (ctx->framerate) {
yading@10 399 int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
yading@10 400 / ctx->requested_framerate.num;
yading@10 401 if (framerate > vcaps->MaxFrameInterval ||
yading@10 402 framerate < vcaps->MinFrameInterval)
yading@10 403 goto next;
yading@10 404 *fr = framerate;
yading@10 405 }
yading@10 406 if (ctx->requested_width && ctx->requested_height) {
yading@10 407 if (ctx->requested_width > vcaps->MaxOutputSize.cx ||
yading@10 408 ctx->requested_width < vcaps->MinOutputSize.cx ||
yading@10 409 ctx->requested_height > vcaps->MaxOutputSize.cy ||
yading@10 410 ctx->requested_height < vcaps->MinOutputSize.cy)
yading@10 411 goto next;
yading@10 412 bih->biWidth = ctx->requested_width;
yading@10 413 bih->biHeight = ctx->requested_height;
yading@10 414 }
yading@10 415 } else {
yading@10 416 AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
yading@10 417 WAVEFORMATEX *fx;
yading@10 418 #if DSHOWDEBUG
yading@10 419 ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps);
yading@10 420 #endif
yading@10 421 if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {
yading@10 422 fx = (void *) type->pbFormat;
yading@10 423 } else {
yading@10 424 goto next;
yading@10 425 }
yading@10 426 if (!pformat_set) {
yading@10 427 av_log(avctx, AV_LOG_INFO, " min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
yading@10 428 acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
yading@10 429 acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
yading@10 430 continue;
yading@10 431 }
yading@10 432 if (ctx->sample_rate) {
yading@10 433 if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
yading@10 434 ctx->sample_rate < acaps->MinimumSampleFrequency)
yading@10 435 goto next;
yading@10 436 fx->nSamplesPerSec = ctx->sample_rate;
yading@10 437 }
yading@10 438 if (ctx->sample_size) {
yading@10 439 if (ctx->sample_size > acaps->MaximumBitsPerSample ||
yading@10 440 ctx->sample_size < acaps->MinimumBitsPerSample)
yading@10 441 goto next;
yading@10 442 fx->wBitsPerSample = ctx->sample_size;
yading@10 443 }
yading@10 444 if (ctx->channels) {
yading@10 445 if (ctx->channels > acaps->MaximumChannels ||
yading@10 446 ctx->channels < acaps->MinimumChannels)
yading@10 447 goto next;
yading@10 448 fx->nChannels = ctx->channels;
yading@10 449 }
yading@10 450 }
yading@10 451 if (IAMStreamConfig_SetFormat(config, type) != S_OK)
yading@10 452 goto next;
yading@10 453 format_set = 1;
yading@10 454 next:
yading@10 455 if (type->pbFormat)
yading@10 456 CoTaskMemFree(type->pbFormat);
yading@10 457 CoTaskMemFree(type);
yading@10 458 }
yading@10 459 end:
yading@10 460 IAMStreamConfig_Release(config);
yading@10 461 if (caps)
yading@10 462 av_free(caps);
yading@10 463 if (pformat_set)
yading@10 464 *pformat_set = format_set;
yading@10 465 }
yading@10 466
yading@10 467 /**
yading@10 468 * Set audio device buffer size in milliseconds (which can directly impact
yading@10 469 * latency, depending on the device).
yading@10 470 */
yading@10 471 static int
yading@10 472 dshow_set_audio_buffer_size(AVFormatContext *avctx, IPin *pin)
yading@10 473 {
yading@10 474 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 475 IAMBufferNegotiation *buffer_negotiation = NULL;
yading@10 476 ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
yading@10 477 IAMStreamConfig *config = NULL;
yading@10 478 AM_MEDIA_TYPE *type = NULL;
yading@10 479 int ret = AVERROR(EIO);
yading@10 480
yading@10 481 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
yading@10 482 goto end;
yading@10 483 if (IAMStreamConfig_GetFormat(config, &type) != S_OK)
yading@10 484 goto end;
yading@10 485 if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
yading@10 486 goto end;
yading@10 487
yading@10 488 props.cbBuffer = (((WAVEFORMATEX *) type->pbFormat)->nAvgBytesPerSec)
yading@10 489 * ctx->audio_buffer_size / 1000;
yading@10 490
yading@10 491 if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (void **) &buffer_negotiation) != S_OK)
yading@10 492 goto end;
yading@10 493 if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) != S_OK)
yading@10 494 goto end;
yading@10 495
yading@10 496 ret = 0;
yading@10 497
yading@10 498 end:
yading@10 499 if (buffer_negotiation)
yading@10 500 IAMBufferNegotiation_Release(buffer_negotiation);
yading@10 501 if (type) {
yading@10 502 if (type->pbFormat)
yading@10 503 CoTaskMemFree(type->pbFormat);
yading@10 504 CoTaskMemFree(type);
yading@10 505 }
yading@10 506 if (config)
yading@10 507 IAMStreamConfig_Release(config);
yading@10 508
yading@10 509 return ret;
yading@10 510 }
yading@10 511
yading@10 512 /**
yading@10 513 * Cycle through available pins using the device_filter device, of type
yading@10 514 * devtype, retrieve the first output pin and return the pointer to the
yading@10 515 * object found in *ppin.
yading@10 516 * If ppin is NULL, cycle through all pins listing audio/video capabilities.
yading@10 517 */
yading@10 518 static int
yading@10 519 dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
yading@10 520 IBaseFilter *device_filter, IPin **ppin)
yading@10 521 {
yading@10 522 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 523 IEnumPins *pins = 0;
yading@10 524 IPin *device_pin = NULL;
yading@10 525 IPin *pin;
yading@10 526 int r;
yading@10 527
yading@10 528 const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
yading@10 529 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
yading@10 530
yading@10 531 int set_format = (devtype == VideoDevice && (ctx->framerate ||
yading@10 532 (ctx->requested_width && ctx->requested_height) ||
yading@10 533 ctx->pixel_format != AV_PIX_FMT_NONE ||
yading@10 534 ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO))
yading@10 535 || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
yading@10 536 int format_set = 0;
yading@10 537
yading@10 538 r = IBaseFilter_EnumPins(device_filter, &pins);
yading@10 539 if (r != S_OK) {
yading@10 540 av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
yading@10 541 return AVERROR(EIO);
yading@10 542 }
yading@10 543
yading@10 544 if (!ppin) {
yading@10 545 av_log(avctx, AV_LOG_INFO, "DirectShow %s device options\n",
yading@10 546 devtypename);
yading@10 547 }
yading@10 548 while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) {
yading@10 549 IKsPropertySet *p = NULL;
yading@10 550 IEnumMediaTypes *types = NULL;
yading@10 551 PIN_INFO info = {0};
yading@10 552 AM_MEDIA_TYPE *type;
yading@10 553 GUID category;
yading@10 554 DWORD r2;
yading@10 555
yading@10 556 IPin_QueryPinInfo(pin, &info);
yading@10 557 IBaseFilter_Release(info.pFilter);
yading@10 558
yading@10 559 if (info.dir != PINDIR_OUTPUT)
yading@10 560 goto next;
yading@10 561 if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK)
yading@10 562 goto next;
yading@10 563 if (IKsPropertySet_Get(p, &AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
yading@10 564 NULL, 0, &category, sizeof(GUID), &r2) != S_OK)
yading@10 565 goto next;
yading@10 566 if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
yading@10 567 goto next;
yading@10 568
yading@10 569 if (!ppin) {
yading@10 570 char *buf = dup_wchar_to_utf8(info.achName);
yading@10 571 av_log(avctx, AV_LOG_INFO, " Pin \"%s\"\n", buf);
yading@10 572 av_free(buf);
yading@10 573 dshow_cycle_formats(avctx, devtype, pin, NULL);
yading@10 574 goto next;
yading@10 575 }
yading@10 576 if (set_format) {
yading@10 577 dshow_cycle_formats(avctx, devtype, pin, &format_set);
yading@10 578 if (!format_set) {
yading@10 579 goto next;
yading@10 580 }
yading@10 581 }
yading@10 582 if (devtype == AudioDevice && ctx->audio_buffer_size) {
yading@10 583 if (dshow_set_audio_buffer_size(avctx, pin) < 0)
yading@10 584 goto next;
yading@10 585 }
yading@10 586
yading@10 587 if (IPin_EnumMediaTypes(pin, &types) != S_OK)
yading@10 588 goto next;
yading@10 589
yading@10 590 IEnumMediaTypes_Reset(types);
yading@10 591 while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) {
yading@10 592 if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
yading@10 593 device_pin = pin;
yading@10 594 goto next;
yading@10 595 }
yading@10 596 CoTaskMemFree(type);
yading@10 597 }
yading@10 598
yading@10 599 next:
yading@10 600 if (types)
yading@10 601 IEnumMediaTypes_Release(types);
yading@10 602 if (p)
yading@10 603 IKsPropertySet_Release(p);
yading@10 604 if (device_pin != pin)
yading@10 605 IPin_Release(pin);
yading@10 606 }
yading@10 607
yading@10 608 IEnumPins_Release(pins);
yading@10 609
yading@10 610 if (ppin) {
yading@10 611 if (set_format && !format_set) {
yading@10 612 av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
yading@10 613 return AVERROR(EIO);
yading@10 614 }
yading@10 615 if (!device_pin) {
yading@10 616 av_log(avctx, AV_LOG_ERROR,
yading@10 617 "Could not find output pin from %s capture device.\n", devtypename);
yading@10 618 return AVERROR(EIO);
yading@10 619 }
yading@10 620 *ppin = device_pin;
yading@10 621 }
yading@10 622
yading@10 623 return 0;
yading@10 624 }
yading@10 625
yading@10 626 /**
yading@10 627 * List options for device with type devtype.
yading@10 628 *
yading@10 629 * @param devenum device enumerator used for accessing the device
yading@10 630 */
yading@10 631 static int
yading@10 632 dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
yading@10 633 enum dshowDeviceType devtype)
yading@10 634 {
yading@10 635 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 636 IBaseFilter *device_filter = NULL;
yading@10 637 int r;
yading@10 638
yading@10 639 if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0)
yading@10 640 return r;
yading@10 641 ctx->device_filter[devtype] = device_filter;
yading@10 642 if ((r = dshow_cycle_pins(avctx, devtype, device_filter, NULL)) < 0)
yading@10 643 return r;
yading@10 644
yading@10 645 return 0;
yading@10 646 }
yading@10 647
yading@10 648 static int
yading@10 649 dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
yading@10 650 enum dshowDeviceType devtype)
yading@10 651 {
yading@10 652 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 653 IBaseFilter *device_filter = NULL;
yading@10 654 IGraphBuilder *graph = ctx->graph;
yading@10 655 IPin *device_pin = NULL;
yading@10 656 libAVPin *capture_pin = NULL;
yading@10 657 libAVFilter *capture_filter = NULL;
yading@10 658 int ret = AVERROR(EIO);
yading@10 659 int r;
yading@10 660
yading@10 661 const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
yading@10 662
yading@10 663 if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0) {
yading@10 664 ret = r;
yading@10 665 goto error;
yading@10 666 }
yading@10 667
yading@10 668 ctx->device_filter [devtype] = device_filter;
yading@10 669
yading@10 670 r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
yading@10 671 if (r != S_OK) {
yading@10 672 av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
yading@10 673 goto error;
yading@10 674 }
yading@10 675
yading@10 676 if ((r = dshow_cycle_pins(avctx, devtype, device_filter, &device_pin)) < 0) {
yading@10 677 ret = r;
yading@10 678 goto error;
yading@10 679 }
yading@10 680 ctx->device_pin[devtype] = device_pin;
yading@10 681
yading@10 682 capture_filter = libAVFilter_Create(avctx, callback, devtype);
yading@10 683 if (!capture_filter) {
yading@10 684 av_log(avctx, AV_LOG_ERROR, "Could not create grabber filter.\n");
yading@10 685 goto error;
yading@10 686 }
yading@10 687 ctx->capture_filter[devtype] = capture_filter;
yading@10 688
yading@10 689 r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter,
yading@10 690 filter_name[devtype]);
yading@10 691 if (r != S_OK) {
yading@10 692 av_log(avctx, AV_LOG_ERROR, "Could not add capture filter to graph\n");
yading@10 693 goto error;
yading@10 694 }
yading@10 695
yading@10 696 libAVPin_AddRef(capture_filter->pin);
yading@10 697 capture_pin = capture_filter->pin;
yading@10 698 ctx->capture_pin[devtype] = capture_pin;
yading@10 699
yading@10 700 r = IGraphBuilder_ConnectDirect(graph, device_pin, (IPin *) capture_pin, NULL);
yading@10 701 if (r != S_OK) {
yading@10 702 av_log(avctx, AV_LOG_ERROR, "Could not connect pins\n");
yading@10 703 goto error;
yading@10 704 }
yading@10 705
yading@10 706 ret = 0;
yading@10 707
yading@10 708 error:
yading@10 709 return ret;
yading@10 710 }
yading@10 711
yading@10 712 static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
yading@10 713 {
yading@10 714 switch (sample_fmt) {
yading@10 715 case AV_SAMPLE_FMT_U8: return AV_CODEC_ID_PCM_U8;
yading@10 716 case AV_SAMPLE_FMT_S16: return AV_CODEC_ID_PCM_S16LE;
yading@10 717 case AV_SAMPLE_FMT_S32: return AV_CODEC_ID_PCM_S32LE;
yading@10 718 default: return AV_CODEC_ID_NONE; /* Should never happen. */
yading@10 719 }
yading@10 720 }
yading@10 721
yading@10 722 static enum AVSampleFormat sample_fmt_bits_per_sample(int bits)
yading@10 723 {
yading@10 724 switch (bits) {
yading@10 725 case 8: return AV_SAMPLE_FMT_U8;
yading@10 726 case 16: return AV_SAMPLE_FMT_S16;
yading@10 727 case 32: return AV_SAMPLE_FMT_S32;
yading@10 728 default: return AV_SAMPLE_FMT_NONE; /* Should never happen. */
yading@10 729 }
yading@10 730 }
yading@10 731
yading@10 732 static int
yading@10 733 dshow_add_device(AVFormatContext *avctx,
yading@10 734 enum dshowDeviceType devtype)
yading@10 735 {
yading@10 736 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 737 AM_MEDIA_TYPE type;
yading@10 738 AVCodecContext *codec;
yading@10 739 AVStream *st;
yading@10 740 int ret = AVERROR(EIO);
yading@10 741
yading@10 742 st = avformat_new_stream(avctx, NULL);
yading@10 743 if (!st) {
yading@10 744 ret = AVERROR(ENOMEM);
yading@10 745 goto error;
yading@10 746 }
yading@10 747 st->id = devtype;
yading@10 748
yading@10 749 ctx->capture_filter[devtype]->stream_index = st->index;
yading@10 750
yading@10 751 libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type);
yading@10 752
yading@10 753 codec = st->codec;
yading@10 754 if (devtype == VideoDevice) {
yading@10 755 BITMAPINFOHEADER *bih = NULL;
yading@10 756 AVRational time_base;
yading@10 757
yading@10 758 if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
yading@10 759 VIDEOINFOHEADER *v = (void *) type.pbFormat;
yading@10 760 time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
yading@10 761 bih = &v->bmiHeader;
yading@10 762 } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) {
yading@10 763 VIDEOINFOHEADER2 *v = (void *) type.pbFormat;
yading@10 764 time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
yading@10 765 bih = &v->bmiHeader;
yading@10 766 }
yading@10 767 if (!bih) {
yading@10 768 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
yading@10 769 goto error;
yading@10 770 }
yading@10 771
yading@10 772 codec->time_base = time_base;
yading@10 773 codec->codec_type = AVMEDIA_TYPE_VIDEO;
yading@10 774 codec->width = bih->biWidth;
yading@10 775 codec->height = bih->biHeight;
yading@10 776 codec->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
yading@10 777 if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) {
yading@10 778 av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n");
yading@10 779 codec->color_range = AVCOL_RANGE_MPEG; // just in case it needs this...
yading@10 780 }
yading@10 781 if (codec->pix_fmt == AV_PIX_FMT_NONE) {
yading@10 782 codec->codec_id = ff_codec_get_id(avformat_get_riff_video_tags(), bih->biCompression);
yading@10 783 if (codec->codec_id == AV_CODEC_ID_NONE) {
yading@10 784 av_log(avctx, AV_LOG_ERROR, "Unknown compression type. "
yading@10 785 "Please report type 0x%X.\n", (int) bih->biCompression);
yading@10 786 return AVERROR_PATCHWELCOME;
yading@10 787 }
yading@10 788 codec->bits_per_coded_sample = bih->biBitCount;
yading@10 789 } else {
yading@10 790 codec->codec_id = AV_CODEC_ID_RAWVIDEO;
yading@10 791 if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
yading@10 792 codec->bits_per_coded_sample = bih->biBitCount;
yading@10 793 codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE);
yading@10 794 if (codec->extradata) {
yading@10 795 codec->extradata_size = 9;
yading@10 796 memcpy(codec->extradata, "BottomUp", 9);
yading@10 797 }
yading@10 798 }
yading@10 799 }
yading@10 800 } else {
yading@10 801 WAVEFORMATEX *fx = NULL;
yading@10 802
yading@10 803 if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) {
yading@10 804 fx = (void *) type.pbFormat;
yading@10 805 }
yading@10 806 if (!fx) {
yading@10 807 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
yading@10 808 goto error;
yading@10 809 }
yading@10 810
yading@10 811 codec->codec_type = AVMEDIA_TYPE_AUDIO;
yading@10 812 codec->sample_fmt = sample_fmt_bits_per_sample(fx->wBitsPerSample);
yading@10 813 codec->codec_id = waveform_codec_id(codec->sample_fmt);
yading@10 814 codec->sample_rate = fx->nSamplesPerSec;
yading@10 815 codec->channels = fx->nChannels;
yading@10 816 }
yading@10 817
yading@10 818 avpriv_set_pts_info(st, 64, 1, 10000000);
yading@10 819
yading@10 820 ret = 0;
yading@10 821
yading@10 822 error:
yading@10 823 return ret;
yading@10 824 }
yading@10 825
yading@10 826 static int parse_device_name(AVFormatContext *avctx)
yading@10 827 {
yading@10 828 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 829 char **device_name = ctx->device_name;
yading@10 830 char *name = av_strdup(avctx->filename);
yading@10 831 char *tmp = name;
yading@10 832 int ret = 1;
yading@10 833 char *type;
yading@10 834
yading@10 835 while ((type = strtok(tmp, "="))) {
yading@10 836 char *token = strtok(NULL, ":");
yading@10 837 tmp = NULL;
yading@10 838
yading@10 839 if (!strcmp(type, "video")) {
yading@10 840 device_name[0] = token;
yading@10 841 } else if (!strcmp(type, "audio")) {
yading@10 842 device_name[1] = token;
yading@10 843 } else {
yading@10 844 device_name[0] = NULL;
yading@10 845 device_name[1] = NULL;
yading@10 846 break;
yading@10 847 }
yading@10 848 }
yading@10 849
yading@10 850 if (!device_name[0] && !device_name[1]) {
yading@10 851 ret = 0;
yading@10 852 } else {
yading@10 853 if (device_name[0])
yading@10 854 device_name[0] = av_strdup(device_name[0]);
yading@10 855 if (device_name[1])
yading@10 856 device_name[1] = av_strdup(device_name[1]);
yading@10 857 }
yading@10 858
yading@10 859 av_free(name);
yading@10 860 return ret;
yading@10 861 }
yading@10 862
yading@10 863 static int dshow_read_header(AVFormatContext *avctx)
yading@10 864 {
yading@10 865 struct dshow_ctx *ctx = avctx->priv_data;
yading@10 866 IGraphBuilder *graph = NULL;
yading@10 867 ICreateDevEnum *devenum = NULL;
yading@10 868 IMediaControl *control = NULL;
yading@10 869 IMediaEvent *media_event = NULL;
yading@10 870 HANDLE media_event_handle;
yading@10 871 HANDLE proc;
yading@10 872 int ret = AVERROR(EIO);
yading@10 873 int r;
yading@10 874
yading@10 875 CoInitialize(0);
yading@10 876
yading@10 877 if (!ctx->list_devices && !parse_device_name(avctx)) {
yading@10 878 av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n");
yading@10 879 goto error;
yading@10 880 }
yading@10 881
yading@10 882 ctx->video_codec_id = avctx->video_codec_id ? avctx->video_codec_id
yading@10 883 : AV_CODEC_ID_RAWVIDEO;
yading@10 884 if (ctx->pixel_format != AV_PIX_FMT_NONE) {
yading@10 885 if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
yading@10 886 av_log(avctx, AV_LOG_ERROR, "Pixel format may only be set when "
yading@10 887 "video codec is not set or set to rawvideo\n");
yading@10 888 ret = AVERROR(EINVAL);
yading@10 889 goto error;
yading@10 890 }
yading@10 891 }
yading@10 892 if (ctx->framerate) {
yading@10 893 r = av_parse_video_rate(&ctx->requested_framerate, ctx->framerate);
yading@10 894 if (r < 0) {
yading@10 895 av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate);
yading@10 896 goto error;
yading@10 897 }
yading@10 898 }
yading@10 899
yading@10 900 r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
yading@10 901 &IID_IGraphBuilder, (void **) &graph);
yading@10 902 if (r != S_OK) {
yading@10 903 av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n");
yading@10 904 goto error;
yading@10 905 }
yading@10 906 ctx->graph = graph;
yading@10 907
yading@10 908 r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
yading@10 909 &IID_ICreateDevEnum, (void **) &devenum);
yading@10 910 if (r != S_OK) {
yading@10 911 av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
yading@10 912 goto error;
yading@10 913 }
yading@10 914
yading@10 915 if (ctx->list_devices) {
yading@10 916 av_log(avctx, AV_LOG_INFO, "DirectShow video devices\n");
yading@10 917 dshow_cycle_devices(avctx, devenum, VideoDevice, NULL);
yading@10 918 av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n");
yading@10 919 dshow_cycle_devices(avctx, devenum, AudioDevice, NULL);
yading@10 920 ret = AVERROR_EXIT;
yading@10 921 goto error;
yading@10 922 }
yading@10 923 if (ctx->list_options) {
yading@10 924 if (ctx->device_name[VideoDevice])
yading@10 925 dshow_list_device_options(avctx, devenum, VideoDevice);
yading@10 926 if (ctx->device_name[AudioDevice])
yading@10 927 dshow_list_device_options(avctx, devenum, AudioDevice);
yading@10 928 ret = AVERROR_EXIT;
yading@10 929 goto error;
yading@10 930 }
yading@10 931
yading@10 932 if (ctx->device_name[VideoDevice]) {
yading@10 933 if ((r = dshow_open_device(avctx, devenum, VideoDevice)) < 0 ||
yading@10 934 (r = dshow_add_device(avctx, VideoDevice)) < 0) {
yading@10 935 ret = r;
yading@10 936 goto error;
yading@10 937 }
yading@10 938 }
yading@10 939 if (ctx->device_name[AudioDevice]) {
yading@10 940 if ((r = dshow_open_device(avctx, devenum, AudioDevice)) < 0 ||
yading@10 941 (r = dshow_add_device(avctx, AudioDevice)) < 0) {
yading@10 942 ret = r;
yading@10 943 goto error;
yading@10 944 }
yading@10 945 }
yading@10 946
yading@10 947 ctx->mutex = CreateMutex(NULL, 0, NULL);
yading@10 948 if (!ctx->mutex) {
yading@10 949 av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n");
yading@10 950 goto error;
yading@10 951 }
yading@10 952 ctx->event[1] = CreateEvent(NULL, 1, 0, NULL);
yading@10 953 if (!ctx->event[1]) {
yading@10 954 av_log(avctx, AV_LOG_ERROR, "Could not create Event\n");
yading@10 955 goto error;
yading@10 956 }
yading@10 957
yading@10 958 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control);
yading@10 959 if (r != S_OK) {
yading@10 960 av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n");
yading@10 961 goto error;
yading@10 962 }
yading@10 963 ctx->control = control;
yading@10 964
yading@10 965 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaEvent, (void **) &media_event);
yading@10 966 if (r != S_OK) {
yading@10 967 av_log(avctx, AV_LOG_ERROR, "Could not get media event.\n");
yading@10 968 goto error;
yading@10 969 }
yading@10 970 ctx->media_event = media_event;
yading@10 971
yading@10 972 r = IMediaEvent_GetEventHandle(media_event, (void *) &media_event_handle);
yading@10 973 if (r != S_OK) {
yading@10 974 av_log(avctx, AV_LOG_ERROR, "Could not get media event handle.\n");
yading@10 975 goto error;
yading@10 976 }
yading@10 977 proc = GetCurrentProcess();
yading@10 978 r = DuplicateHandle(proc, media_event_handle, proc, &ctx->event[0],
yading@10 979 0, 0, DUPLICATE_SAME_ACCESS);
yading@10 980 if (!r) {
yading@10 981 av_log(avctx, AV_LOG_ERROR, "Could not duplicate media event handle.\n");
yading@10 982 goto error;
yading@10 983 }
yading@10 984
yading@10 985 r = IMediaControl_Run(control);
yading@10 986 if (r == S_FALSE) {
yading@10 987 OAFilterState pfs;
yading@10 988 r = IMediaControl_GetState(control, 0, &pfs);
yading@10 989 }
yading@10 990 if (r != S_OK) {
yading@10 991 av_log(avctx, AV_LOG_ERROR, "Could not run filter\n");
yading@10 992 goto error;
yading@10 993 }
yading@10 994
yading@10 995 ret = 0;
yading@10 996
yading@10 997 error:
yading@10 998
yading@10 999 if (devenum)
yading@10 1000 ICreateDevEnum_Release(devenum);
yading@10 1001
yading@10 1002 if (ret < 0)
yading@10 1003 dshow_read_close(avctx);
yading@10 1004
yading@10 1005 return ret;
yading@10 1006 }
yading@10 1007
yading@10 1008 /**
yading@10 1009 * Checks media events from DirectShow and returns -1 on error or EOF. Also
yading@10 1010 * purges all events that might be in the event queue to stop the trigger
yading@10 1011 * of event notification.
yading@10 1012 */
yading@10 1013 static int dshow_check_event_queue(IMediaEvent *media_event)
yading@10 1014 {
yading@10 1015 LONG_PTR p1, p2;
yading@10 1016 long code;
yading@10 1017 int ret = 0;
yading@10 1018
yading@10 1019 while (IMediaEvent_GetEvent(media_event, &code, &p1, &p2, 0) != E_ABORT) {
yading@10 1020 if (code == EC_COMPLETE || code == EC_DEVICE_LOST || code == EC_ERRORABORT)
yading@10 1021 ret = -1;
yading@10 1022 IMediaEvent_FreeEventParams(media_event, code, p1, p2);
yading@10 1023 }
yading@10 1024
yading@10 1025 return ret;
yading@10 1026 }
yading@10 1027
yading@10 1028 static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
yading@10 1029 {
yading@10 1030 struct dshow_ctx *ctx = s->priv_data;
yading@10 1031 AVPacketList *pktl = NULL;
yading@10 1032
yading@10 1033 while (!ctx->eof && !pktl) {
yading@10 1034 WaitForSingleObject(ctx->mutex, INFINITE);
yading@10 1035 pktl = ctx->pktl;
yading@10 1036 if (pktl) {
yading@10 1037 *pkt = pktl->pkt;
yading@10 1038 ctx->pktl = ctx->pktl->next;
yading@10 1039 av_free(pktl);
yading@10 1040 ctx->curbufsize -= pkt->size;
yading@10 1041 }
yading@10 1042 ResetEvent(ctx->event[1]);
yading@10 1043 ReleaseMutex(ctx->mutex);
yading@10 1044 if (!pktl) {
yading@10 1045 if (dshow_check_event_queue(ctx->media_event) < 0) {
yading@10 1046 ctx->eof = 1;
yading@10 1047 } else if (s->flags & AVFMT_FLAG_NONBLOCK) {
yading@10 1048 return AVERROR(EAGAIN);
yading@10 1049 } else {
yading@10 1050 WaitForMultipleObjects(2, ctx->event, 0, INFINITE);
yading@10 1051 }
yading@10 1052 }
yading@10 1053 }
yading@10 1054
yading@10 1055 return ctx->eof ? AVERROR(EIO) : pkt->size;
yading@10 1056 }
yading@10 1057
yading@10 1058 #define OFFSET(x) offsetof(struct dshow_ctx, x)
yading@10 1059 #define DEC AV_OPT_FLAG_DECODING_PARAM
yading@10 1060 static const AVOption options[] = {
yading@10 1061 { "video_size", "set video size given a string such as 640x480 or hd720.", OFFSET(requested_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC },
yading@10 1062 { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.i64 = AV_PIX_FMT_NONE}, -1, AV_PIX_FMT_NB-1, DEC },
yading@10 1063 { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
yading@10 1064 { "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
yading@10 1065 { "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 16, DEC },
yading@10 1066 { "channels", "set number of audio channels, such as 1 or 2", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
yading@10 1067 { "list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, DEC, "list_devices" },
yading@10 1068 { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "list_devices" },
yading@10 1069 { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "list_devices" },
yading@10 1070 { "list_options", "list available options for specified device", OFFSET(list_options), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, DEC, "list_options" },
yading@10 1071 { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "list_options" },
yading@10 1072 { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "list_options" },
yading@10 1073 { "video_device_number", "set video device number for devices with same name (starts at 0)", OFFSET(video_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
yading@10 1074 { "audio_device_number", "set audio device number for devices with same name (starts at 0)", OFFSET(audio_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
yading@10 1075 { "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, {.i64 = 0}, 0, INT_MAX, DEC },
yading@10 1076 { NULL },
yading@10 1077 };
yading@10 1078
yading@10 1079 static const AVClass dshow_class = {
yading@10 1080 .class_name = "dshow indev",
yading@10 1081 .item_name = av_default_item_name,
yading@10 1082 .option = options,
yading@10 1083 .version = LIBAVUTIL_VERSION_INT,
yading@10 1084 };
yading@10 1085
yading@10 1086 AVInputFormat ff_dshow_demuxer = {
yading@10 1087 .name = "dshow",
yading@10 1088 .long_name = NULL_IF_CONFIG_SMALL("DirectShow capture"),
yading@10 1089 .priv_data_size = sizeof(struct dshow_ctx),
yading@10 1090 .read_header = dshow_read_header,
yading@10 1091 .read_packet = dshow_read_packet,
yading@10 1092 .read_close = dshow_read_close,
yading@10 1093 .flags = AVFMT_NOFILE,
yading@10 1094 .priv_class = &dshow_class,
yading@10 1095 };