00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/parseutils.h"
00023 #include "libavutil/pixdesc.h"
00024 #include "libavutil/opt.h"
00025 #include "libavformat/internal.h"
00026 #include "avdevice.h"
00027 #include "dshow_capture.h"
00028
00029 struct dshow_ctx {
00030 const AVClass *class;
00031
00032 IGraphBuilder *graph;
00033
00034 char *device_name[2];
00035 int video_device_number;
00036 int audio_device_number;
00037
00038 int list_options;
00039 int list_devices;
00040 int audio_buffer_size;
00041
00042 IBaseFilter *device_filter[2];
00043 IPin *device_pin[2];
00044 libAVFilter *capture_filter[2];
00045 libAVPin *capture_pin[2];
00046
00047 HANDLE mutex;
00048 HANDLE event;
00049 AVPacketList *pktl;
00050
00051 int64_t curbufsize;
00052 unsigned int video_frame_num;
00053
00054 IMediaControl *control;
00055
00056 enum PixelFormat pixel_format;
00057 enum AVCodecID video_codec_id;
00058 char *framerate;
00059
00060 int requested_width;
00061 int requested_height;
00062 AVRational requested_framerate;
00063
00064 int sample_rate;
00065 int sample_size;
00066 int channels;
00067 };
00068
00069 static enum PixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
00070 {
00071 switch(biCompression) {
00072 case MKTAG('U', 'Y', 'V', 'Y'):
00073 return PIX_FMT_UYVY422;
00074 case MKTAG('Y', 'U', 'Y', '2'):
00075 return PIX_FMT_YUYV422;
00076 case MKTAG('I', '4', '2', '0'):
00077 return PIX_FMT_YUV420P;
00078 case BI_BITFIELDS:
00079 case BI_RGB:
00080 switch(biBitCount) {
00081 case 1:
00082 return PIX_FMT_MONOWHITE;
00083 case 4:
00084 return PIX_FMT_RGB4;
00085 case 8:
00086 return PIX_FMT_RGB8;
00087 case 16:
00088 return PIX_FMT_RGB555;
00089 case 24:
00090 return PIX_FMT_BGR24;
00091 case 32:
00092 return PIX_FMT_RGB32;
00093 }
00094 }
00095 return PIX_FMT_NONE;
00096 }
00097
00098 static enum AVCodecID dshow_codecid(DWORD biCompression)
00099 {
00100 switch(biCompression) {
00101 case MKTAG('d', 'v', 's', 'd'):
00102 return AV_CODEC_ID_DVVIDEO;
00103 case MKTAG('M', 'J', 'P', 'G'):
00104 case MKTAG('m', 'j', 'p', 'g'):
00105 return AV_CODEC_ID_MJPEG;
00106 }
00107 return AV_CODEC_ID_NONE;
00108 }
00109
00110 static int
00111 dshow_read_close(AVFormatContext *s)
00112 {
00113 struct dshow_ctx *ctx = s->priv_data;
00114 AVPacketList *pktl;
00115
00116 if (ctx->control) {
00117 IMediaControl_Stop(ctx->control);
00118 IMediaControl_Release(ctx->control);
00119 }
00120
00121 if (ctx->graph) {
00122 IEnumFilters *fenum;
00123 int r;
00124 r = IGraphBuilder_EnumFilters(ctx->graph, &fenum);
00125 if (r == S_OK) {
00126 IBaseFilter *f;
00127 IEnumFilters_Reset(fenum);
00128 while (IEnumFilters_Next(fenum, 1, &f, NULL) == S_OK) {
00129 if (IGraphBuilder_RemoveFilter(ctx->graph, f) == S_OK)
00130 IEnumFilters_Reset(fenum);
00131
00132 IBaseFilter_Release(f);
00133 }
00134 IEnumFilters_Release(fenum);
00135 }
00136 IGraphBuilder_Release(ctx->graph);
00137 }
00138
00139 if (ctx->capture_pin[VideoDevice])
00140 libAVPin_Release(ctx->capture_pin[VideoDevice]);
00141 if (ctx->capture_pin[AudioDevice])
00142 libAVPin_Release(ctx->capture_pin[AudioDevice]);
00143 if (ctx->capture_filter[VideoDevice])
00144 libAVFilter_Release(ctx->capture_filter[VideoDevice]);
00145 if (ctx->capture_filter[AudioDevice])
00146 libAVFilter_Release(ctx->capture_filter[AudioDevice]);
00147
00148 if (ctx->device_pin[VideoDevice])
00149 IPin_Release(ctx->device_pin[VideoDevice]);
00150 if (ctx->device_pin[AudioDevice])
00151 IPin_Release(ctx->device_pin[AudioDevice]);
00152 if (ctx->device_filter[VideoDevice])
00153 IBaseFilter_Release(ctx->device_filter[VideoDevice]);
00154 if (ctx->device_filter[AudioDevice])
00155 IBaseFilter_Release(ctx->device_filter[AudioDevice]);
00156
00157 if (ctx->device_name[0])
00158 av_free(ctx->device_name[0]);
00159 if (ctx->device_name[1])
00160 av_free(ctx->device_name[1]);
00161
00162 if(ctx->mutex)
00163 CloseHandle(ctx->mutex);
00164 if(ctx->event)
00165 CloseHandle(ctx->event);
00166
00167 pktl = ctx->pktl;
00168 while (pktl) {
00169 AVPacketList *next = pktl->next;
00170 av_destruct_packet(&pktl->pkt);
00171 av_free(pktl);
00172 pktl = next;
00173 }
00174
00175 return 0;
00176 }
00177
00178 static char *dup_wchar_to_utf8(wchar_t *w)
00179 {
00180 char *s = NULL;
00181 int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
00182 s = av_malloc(l);
00183 if (s)
00184 WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
00185 return s;
00186 }
00187
00188 static int shall_we_drop(AVFormatContext *s)
00189 {
00190 struct dshow_ctx *ctx = s->priv_data;
00191 const uint8_t dropscore[] = {62, 75, 87, 100};
00192 const int ndropscores = FF_ARRAY_ELEMS(dropscore);
00193 unsigned int buffer_fullness = (ctx->curbufsize*100)/s->max_picture_buffer;
00194
00195 if(dropscore[++ctx->video_frame_num%ndropscores] <= buffer_fullness) {
00196 av_log(s, AV_LOG_ERROR,
00197 "real-time buffer %d%% full! frame dropped!\n", buffer_fullness);
00198 return 1;
00199 }
00200
00201 return 0;
00202 }
00203
00204 static void
00205 callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time)
00206 {
00207 AVFormatContext *s = priv_data;
00208 struct dshow_ctx *ctx = s->priv_data;
00209 AVPacketList **ppktl, *pktl_next;
00210
00211
00212
00213 WaitForSingleObject(ctx->mutex, INFINITE);
00214
00215 if(shall_we_drop(s))
00216 goto fail;
00217
00218 pktl_next = av_mallocz(sizeof(AVPacketList));
00219 if(!pktl_next)
00220 goto fail;
00221
00222 if(av_new_packet(&pktl_next->pkt, buf_size) < 0) {
00223 av_free(pktl_next);
00224 goto fail;
00225 }
00226
00227 pktl_next->pkt.stream_index = index;
00228 pktl_next->pkt.pts = time;
00229 memcpy(pktl_next->pkt.data, buf, buf_size);
00230
00231 for(ppktl = &ctx->pktl ; *ppktl ; ppktl = &(*ppktl)->next);
00232 *ppktl = pktl_next;
00233
00234 ctx->curbufsize += buf_size;
00235
00236 SetEvent(ctx->event);
00237 ReleaseMutex(ctx->mutex);
00238
00239 return;
00240 fail:
00241 ReleaseMutex(ctx->mutex);
00242 return;
00243 }
00244
00251 static int
00252 dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
00253 enum dshowDeviceType devtype, IBaseFilter **pfilter)
00254 {
00255 struct dshow_ctx *ctx = avctx->priv_data;
00256 IBaseFilter *device_filter = NULL;
00257 IEnumMoniker *classenum = NULL;
00258 IMoniker *m = NULL;
00259 const char *device_name = ctx->device_name[devtype];
00260 int skip = (devtype == VideoDevice) ? ctx->video_device_number
00261 : ctx->audio_device_number;
00262 int r;
00263
00264 const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
00265 &CLSID_AudioInputDeviceCategory };
00266 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
00267
00268 r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[devtype],
00269 (IEnumMoniker **) &classenum, 0);
00270 if (r != S_OK) {
00271 av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices.\n",
00272 devtypename);
00273 return AVERROR(EIO);
00274 }
00275
00276 while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {
00277 IPropertyBag *bag = NULL;
00278 char *buf = NULL;
00279 VARIANT var;
00280
00281 r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);
00282 if (r != S_OK)
00283 goto fail1;
00284
00285 var.vt = VT_BSTR;
00286 r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);
00287 if (r != S_OK)
00288 goto fail1;
00289
00290 buf = dup_wchar_to_utf8(var.bstrVal);
00291
00292 if (pfilter) {
00293 if (strcmp(device_name, buf))
00294 goto fail1;
00295
00296 if (!skip--)
00297 IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);
00298 } else {
00299 av_log(avctx, AV_LOG_INFO, " \"%s\"\n", buf);
00300 }
00301
00302 fail1:
00303 if (buf)
00304 av_free(buf);
00305 if (bag)
00306 IPropertyBag_Release(bag);
00307 IMoniker_Release(m);
00308 }
00309
00310 IEnumMoniker_Release(classenum);
00311
00312 if (pfilter) {
00313 if (!device_filter) {
00314 av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n",
00315 devtypename);
00316 return AVERROR(EIO);
00317 }
00318 *pfilter = device_filter;
00319 }
00320
00321 return 0;
00322 }
00323
00330 static void
00331 dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
00332 IPin *pin, int *pformat_set)
00333 {
00334 struct dshow_ctx *ctx = avctx->priv_data;
00335 IAMStreamConfig *config = NULL;
00336 AM_MEDIA_TYPE *type = NULL;
00337 int format_set = 0;
00338 void *caps = NULL;
00339 int i, n, size;
00340
00341 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
00342 return;
00343 if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK)
00344 goto end;
00345
00346 caps = av_malloc(size);
00347 if (!caps)
00348 goto end;
00349
00350 for (i = 0; i < n && !format_set; i++) {
00351 IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
00352
00353 #if DSHOWDEBUG
00354 ff_print_AM_MEDIA_TYPE(type);
00355 #endif
00356
00357 if (devtype == VideoDevice) {
00358 VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
00359 BITMAPINFOHEADER *bih;
00360 int64_t *fr;
00361 #if DSHOWDEBUG
00362 ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps);
00363 #endif
00364 if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {
00365 VIDEOINFOHEADER *v = (void *) type->pbFormat;
00366 fr = &v->AvgTimePerFrame;
00367 bih = &v->bmiHeader;
00368 } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {
00369 VIDEOINFOHEADER2 *v = (void *) type->pbFormat;
00370 fr = &v->AvgTimePerFrame;
00371 bih = &v->bmiHeader;
00372 } else {
00373 goto next;
00374 }
00375 if (!pformat_set) {
00376 enum PixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
00377 if (pix_fmt == PIX_FMT_NONE) {
00378 enum AVCodecID codec_id = dshow_codecid(bih->biCompression);
00379 AVCodec *codec = avcodec_find_decoder(codec_id);
00380 if (codec_id == AV_CODEC_ID_NONE || !codec) {
00381 av_log(avctx, AV_LOG_INFO, " unknown compression type");
00382 } else {
00383 av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name);
00384 }
00385 } else {
00386 av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt));
00387 }
00388 av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
00389 vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
00390 1e7 / vcaps->MaxFrameInterval,
00391 vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
00392 1e7 / vcaps->MinFrameInterval);
00393 continue;
00394 }
00395 if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
00396 if (ctx->video_codec_id != dshow_codecid(bih->biCompression))
00397 goto next;
00398 }
00399 if (ctx->pixel_format != PIX_FMT_NONE &&
00400 ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) {
00401 goto next;
00402 }
00403 if (ctx->framerate) {
00404 int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
00405 / ctx->requested_framerate.num;
00406 if (framerate > vcaps->MaxFrameInterval ||
00407 framerate < vcaps->MinFrameInterval)
00408 goto next;
00409 *fr = framerate;
00410 }
00411 if (ctx->requested_width && ctx->requested_height) {
00412 if (ctx->requested_width > vcaps->MaxOutputSize.cx ||
00413 ctx->requested_width < vcaps->MinOutputSize.cx ||
00414 ctx->requested_height > vcaps->MaxOutputSize.cy ||
00415 ctx->requested_height < vcaps->MinOutputSize.cy)
00416 goto next;
00417 bih->biWidth = ctx->requested_width;
00418 bih->biHeight = ctx->requested_height;
00419 }
00420 } else {
00421 AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
00422 WAVEFORMATEX *fx;
00423 #if DSHOWDEBUG
00424 ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps);
00425 #endif
00426 if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {
00427 fx = (void *) type->pbFormat;
00428 } else {
00429 goto next;
00430 }
00431 if (!pformat_set) {
00432 av_log(avctx, AV_LOG_INFO, " min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
00433 acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
00434 acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
00435 continue;
00436 }
00437 if (ctx->sample_rate) {
00438 if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
00439 ctx->sample_rate < acaps->MinimumSampleFrequency)
00440 goto next;
00441 fx->nSamplesPerSec = ctx->sample_rate;
00442 }
00443 if (ctx->sample_size) {
00444 if (ctx->sample_size > acaps->MaximumBitsPerSample ||
00445 ctx->sample_size < acaps->MinimumBitsPerSample)
00446 goto next;
00447 fx->wBitsPerSample = ctx->sample_size;
00448 }
00449 if (ctx->channels) {
00450 if (ctx->channels > acaps->MaximumChannels ||
00451 ctx->channels < acaps->MinimumChannels)
00452 goto next;
00453 fx->nChannels = ctx->channels;
00454 }
00455 }
00456 if (IAMStreamConfig_SetFormat(config, type) != S_OK)
00457 goto next;
00458 format_set = 1;
00459 next:
00460 if (type->pbFormat)
00461 CoTaskMemFree(type->pbFormat);
00462 CoTaskMemFree(type);
00463 }
00464 end:
00465 IAMStreamConfig_Release(config);
00466 if (caps)
00467 av_free(caps);
00468 if (pformat_set)
00469 *pformat_set = format_set;
00470 }
00471
00476 static int
00477 dshow_set_audio_buffer_size(AVFormatContext *avctx, IPin *pin)
00478 {
00479 struct dshow_ctx *ctx = avctx->priv_data;
00480 IAMBufferNegotiation *buffer_negotiation = NULL;
00481 ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
00482 IAMStreamConfig *config = NULL;
00483 AM_MEDIA_TYPE *type = NULL;
00484 int ret = AVERROR(EIO);
00485
00486 if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
00487 goto end;
00488 if (IAMStreamConfig_GetFormat(config, &type) != S_OK)
00489 goto end;
00490 if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
00491 goto end;
00492
00493 props.cbBuffer = (((WAVEFORMATEX *) type->pbFormat)->nAvgBytesPerSec)
00494 * ctx->audio_buffer_size / 1000;
00495
00496 if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (void **) &buffer_negotiation) != S_OK)
00497 goto end;
00498 if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) != S_OK)
00499 goto end;
00500
00501 ret = 0;
00502
00503 end:
00504 if (buffer_negotiation)
00505 IAMBufferNegotiation_Release(buffer_negotiation);
00506 if (type) {
00507 if (type->pbFormat)
00508 CoTaskMemFree(type->pbFormat);
00509 CoTaskMemFree(type);
00510 }
00511 if (config)
00512 IAMStreamConfig_Release(config);
00513
00514 return ret;
00515 }
00516
00523 static int
00524 dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
00525 IBaseFilter *device_filter, IPin **ppin)
00526 {
00527 struct dshow_ctx *ctx = avctx->priv_data;
00528 IEnumPins *pins = 0;
00529 IPin *device_pin = NULL;
00530 IPin *pin;
00531 int r;
00532
00533 const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
00534 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
00535
00536 int set_format = (devtype == VideoDevice && (ctx->framerate ||
00537 (ctx->requested_width && ctx->requested_height) ||
00538 ctx->pixel_format != PIX_FMT_NONE ||
00539 ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO))
00540 || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
00541 int format_set = 0;
00542
00543 r = IBaseFilter_EnumPins(device_filter, &pins);
00544 if (r != S_OK) {
00545 av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
00546 return AVERROR(EIO);
00547 }
00548
00549 if (!ppin) {
00550 av_log(avctx, AV_LOG_INFO, "DirectShow %s device options\n",
00551 devtypename);
00552 }
00553 while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) {
00554 IKsPropertySet *p = NULL;
00555 IEnumMediaTypes *types = NULL;
00556 PIN_INFO info = {0};
00557 AM_MEDIA_TYPE *type;
00558 GUID category;
00559 DWORD r2;
00560
00561 IPin_QueryPinInfo(pin, &info);
00562 IBaseFilter_Release(info.pFilter);
00563
00564 if (info.dir != PINDIR_OUTPUT)
00565 goto next;
00566 if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK)
00567 goto next;
00568 if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
00569 NULL, 0, &category, sizeof(GUID), &r2) != S_OK)
00570 goto next;
00571 if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
00572 goto next;
00573
00574 if (!ppin) {
00575 char *buf = dup_wchar_to_utf8(info.achName);
00576 av_log(avctx, AV_LOG_INFO, " Pin \"%s\"\n", buf);
00577 av_free(buf);
00578 dshow_cycle_formats(avctx, devtype, pin, NULL);
00579 goto next;
00580 }
00581 if (set_format) {
00582 dshow_cycle_formats(avctx, devtype, pin, &format_set);
00583 if (!format_set) {
00584 goto next;
00585 }
00586 }
00587 if (devtype == AudioDevice && ctx->audio_buffer_size) {
00588 if (dshow_set_audio_buffer_size(avctx, pin) < 0)
00589 goto next;
00590 }
00591
00592 if (IPin_EnumMediaTypes(pin, &types) != S_OK)
00593 goto next;
00594
00595 IEnumMediaTypes_Reset(types);
00596 while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) {
00597 if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
00598 device_pin = pin;
00599 goto next;
00600 }
00601 CoTaskMemFree(type);
00602 }
00603
00604 next:
00605 if (types)
00606 IEnumMediaTypes_Release(types);
00607 if (p)
00608 IKsPropertySet_Release(p);
00609 if (device_pin != pin)
00610 IPin_Release(pin);
00611 }
00612
00613 IEnumPins_Release(pins);
00614
00615 if (ppin) {
00616 if (set_format && !format_set) {
00617 av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
00618 return AVERROR(EIO);
00619 }
00620 if (!device_pin) {
00621 av_log(avctx, AV_LOG_ERROR,
00622 "Could not find output pin from %s capture device.\n", devtypename);
00623 return AVERROR(EIO);
00624 }
00625 *ppin = device_pin;
00626 }
00627
00628 return 0;
00629 }
00630
00636 static int
00637 dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
00638 enum dshowDeviceType devtype)
00639 {
00640 struct dshow_ctx *ctx = avctx->priv_data;
00641 IBaseFilter *device_filter = NULL;
00642 int r;
00643
00644 if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0)
00645 return r;
00646 ctx->device_filter[devtype] = device_filter;
00647 if ((r = dshow_cycle_pins(avctx, devtype, device_filter, NULL)) < 0)
00648 return r;
00649
00650 return 0;
00651 }
00652
00653 static int
00654 dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
00655 enum dshowDeviceType devtype)
00656 {
00657 struct dshow_ctx *ctx = avctx->priv_data;
00658 IBaseFilter *device_filter = NULL;
00659 IGraphBuilder *graph = ctx->graph;
00660 IPin *device_pin = NULL;
00661 libAVPin *capture_pin = NULL;
00662 libAVFilter *capture_filter = NULL;
00663 int ret = AVERROR(EIO);
00664 int r;
00665
00666 const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
00667
00668 if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0) {
00669 ret = r;
00670 goto error;
00671 }
00672
00673 ctx->device_filter [devtype] = device_filter;
00674
00675 r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
00676 if (r != S_OK) {
00677 av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
00678 goto error;
00679 }
00680
00681 if ((r = dshow_cycle_pins(avctx, devtype, device_filter, &device_pin)) < 0) {
00682 ret = r;
00683 goto error;
00684 }
00685 ctx->device_pin[devtype] = device_pin;
00686
00687 capture_filter = libAVFilter_Create(avctx, callback, devtype);
00688 if (!capture_filter) {
00689 av_log(avctx, AV_LOG_ERROR, "Could not create grabber filter.\n");
00690 goto error;
00691 }
00692 ctx->capture_filter[devtype] = capture_filter;
00693
00694 r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter,
00695 filter_name[devtype]);
00696 if (r != S_OK) {
00697 av_log(avctx, AV_LOG_ERROR, "Could not add capture filter to graph\n");
00698 goto error;
00699 }
00700
00701 libAVPin_AddRef(capture_filter->pin);
00702 capture_pin = capture_filter->pin;
00703 ctx->capture_pin[devtype] = capture_pin;
00704
00705 r = IGraphBuilder_ConnectDirect(graph, device_pin, (IPin *) capture_pin, NULL);
00706 if (r != S_OK) {
00707 av_log(avctx, AV_LOG_ERROR, "Could not connect pins\n");
00708 goto error;
00709 }
00710
00711 ret = 0;
00712
00713 error:
00714 return ret;
00715 }
00716
00717 static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
00718 {
00719 switch (sample_fmt) {
00720 case AV_SAMPLE_FMT_U8: return AV_CODEC_ID_PCM_U8;
00721 case AV_SAMPLE_FMT_S16: return AV_CODEC_ID_PCM_S16LE;
00722 case AV_SAMPLE_FMT_S32: return AV_CODEC_ID_PCM_S32LE;
00723 default: return AV_CODEC_ID_NONE;
00724 }
00725 }
00726
00727 static enum AVSampleFormat sample_fmt_bits_per_sample(int bits)
00728 {
00729 switch (bits) {
00730 case 8: return AV_SAMPLE_FMT_U8;
00731 case 16: return AV_SAMPLE_FMT_S16;
00732 case 32: return AV_SAMPLE_FMT_S32;
00733 default: return AV_SAMPLE_FMT_NONE;
00734 }
00735 }
00736
00737 static int
00738 dshow_add_device(AVFormatContext *avctx,
00739 enum dshowDeviceType devtype)
00740 {
00741 struct dshow_ctx *ctx = avctx->priv_data;
00742 AM_MEDIA_TYPE type;
00743 AVCodecContext *codec;
00744 AVStream *st;
00745 int ret = AVERROR(EIO);
00746
00747 st = avformat_new_stream(avctx, NULL);
00748 if (!st) {
00749 ret = AVERROR(ENOMEM);
00750 goto error;
00751 }
00752 st->id = devtype;
00753
00754 ctx->capture_filter[devtype]->stream_index = st->index;
00755
00756 libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type);
00757
00758 codec = st->codec;
00759 if (devtype == VideoDevice) {
00760 BITMAPINFOHEADER *bih = NULL;
00761 AVRational time_base;
00762
00763 if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
00764 VIDEOINFOHEADER *v = (void *) type.pbFormat;
00765 time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
00766 bih = &v->bmiHeader;
00767 } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) {
00768 VIDEOINFOHEADER2 *v = (void *) type.pbFormat;
00769 time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
00770 bih = &v->bmiHeader;
00771 }
00772 if (!bih) {
00773 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
00774 goto error;
00775 }
00776
00777 codec->time_base = time_base;
00778 codec->codec_type = AVMEDIA_TYPE_VIDEO;
00779 codec->width = bih->biWidth;
00780 codec->height = bih->biHeight;
00781 codec->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
00782 if (codec->pix_fmt == PIX_FMT_NONE) {
00783 codec->codec_id = dshow_codecid(bih->biCompression);
00784 if (codec->codec_id == AV_CODEC_ID_NONE) {
00785 av_log(avctx, AV_LOG_ERROR, "Unknown compression type. "
00786 "Please report verbose (-v 9) debug information.\n");
00787 dshow_read_close(avctx);
00788 return AVERROR_PATCHWELCOME;
00789 }
00790 codec->bits_per_coded_sample = bih->biBitCount;
00791 } else {
00792 codec->codec_id = AV_CODEC_ID_RAWVIDEO;
00793 if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
00794 codec->bits_per_coded_sample = bih->biBitCount;
00795 codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE);
00796 if (codec->extradata) {
00797 codec->extradata_size = 9;
00798 memcpy(codec->extradata, "BottomUp", 9);
00799 }
00800 }
00801 }
00802 } else {
00803 WAVEFORMATEX *fx = NULL;
00804
00805 if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) {
00806 fx = (void *) type.pbFormat;
00807 }
00808 if (!fx) {
00809 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
00810 goto error;
00811 }
00812
00813 codec->codec_type = AVMEDIA_TYPE_AUDIO;
00814 codec->sample_fmt = sample_fmt_bits_per_sample(fx->wBitsPerSample);
00815 codec->codec_id = waveform_codec_id(codec->sample_fmt);
00816 codec->sample_rate = fx->nSamplesPerSec;
00817 codec->channels = fx->nChannels;
00818 }
00819
00820 avpriv_set_pts_info(st, 64, 1, 10000000);
00821
00822 ret = 0;
00823
00824 error:
00825 return ret;
00826 }
00827
00828 static int parse_device_name(AVFormatContext *avctx)
00829 {
00830 struct dshow_ctx *ctx = avctx->priv_data;
00831 char **device_name = ctx->device_name;
00832 char *name = av_strdup(avctx->filename);
00833 char *tmp = name;
00834 int ret = 1;
00835 char *type;
00836
00837 while ((type = strtok(tmp, "="))) {
00838 char *token = strtok(NULL, ":");
00839 tmp = NULL;
00840
00841 if (!strcmp(type, "video")) {
00842 device_name[0] = token;
00843 } else if (!strcmp(type, "audio")) {
00844 device_name[1] = token;
00845 } else {
00846 device_name[0] = NULL;
00847 device_name[1] = NULL;
00848 break;
00849 }
00850 }
00851
00852 if (!device_name[0] && !device_name[1]) {
00853 ret = 0;
00854 } else {
00855 if (device_name[0])
00856 device_name[0] = av_strdup(device_name[0]);
00857 if (device_name[1])
00858 device_name[1] = av_strdup(device_name[1]);
00859 }
00860
00861 av_free(name);
00862 return ret;
00863 }
00864
00865 static int dshow_read_header(AVFormatContext *avctx)
00866 {
00867 struct dshow_ctx *ctx = avctx->priv_data;
00868 IGraphBuilder *graph = NULL;
00869 ICreateDevEnum *devenum = NULL;
00870 IMediaControl *control = NULL;
00871 int ret = AVERROR(EIO);
00872 int r;
00873
00874 if (!ctx->list_devices && !parse_device_name(avctx)) {
00875 av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n");
00876 goto error;
00877 }
00878
00879 ctx->video_codec_id = avctx->video_codec_id ? avctx->video_codec_id
00880 : AV_CODEC_ID_RAWVIDEO;
00881 if (ctx->pixel_format != PIX_FMT_NONE) {
00882 if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) {
00883 av_log(avctx, AV_LOG_ERROR, "Pixel format may only be set when "
00884 "video codec is not set or set to rawvideo\n");
00885 ret = AVERROR(EINVAL);
00886 goto error;
00887 }
00888 }
00889 if (ctx->framerate) {
00890 r = av_parse_video_rate(&ctx->requested_framerate, ctx->framerate);
00891 if (r < 0) {
00892 av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate);
00893 goto error;
00894 }
00895 }
00896
00897 CoInitialize(0);
00898
00899 r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
00900 &IID_IGraphBuilder, (void **) &graph);
00901 if (r != S_OK) {
00902 av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n");
00903 goto error;
00904 }
00905 ctx->graph = graph;
00906
00907 r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
00908 &IID_ICreateDevEnum, (void **) &devenum);
00909 if (r != S_OK) {
00910 av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
00911 goto error;
00912 }
00913
00914 if (ctx->list_devices) {
00915 av_log(avctx, AV_LOG_INFO, "DirectShow video devices\n");
00916 dshow_cycle_devices(avctx, devenum, VideoDevice, NULL);
00917 av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n");
00918 dshow_cycle_devices(avctx, devenum, AudioDevice, NULL);
00919 ret = AVERROR_EXIT;
00920 goto error;
00921 }
00922 if (ctx->list_options) {
00923 if (ctx->device_name[VideoDevice])
00924 dshow_list_device_options(avctx, devenum, VideoDevice);
00925 if (ctx->device_name[AudioDevice])
00926 dshow_list_device_options(avctx, devenum, AudioDevice);
00927 ret = AVERROR_EXIT;
00928 goto error;
00929 }
00930
00931 if (ctx->device_name[VideoDevice]) {
00932 ret = dshow_open_device(avctx, devenum, VideoDevice);
00933 if (ret < 0)
00934 goto error;
00935 ret = dshow_add_device(avctx, VideoDevice);
00936 if (ret < 0)
00937 goto error;
00938 }
00939 if (ctx->device_name[AudioDevice]) {
00940 ret = dshow_open_device(avctx, devenum, AudioDevice);
00941 if (ret < 0)
00942 goto error;
00943 ret = dshow_add_device(avctx, AudioDevice);
00944 if (ret < 0)
00945 goto error;
00946 }
00947
00948 ctx->mutex = CreateMutex(NULL, 0, NULL);
00949 if (!ctx->mutex) {
00950 av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n");
00951 goto error;
00952 }
00953 ctx->event = CreateEvent(NULL, 1, 0, NULL);
00954 if (!ctx->event) {
00955 av_log(avctx, AV_LOG_ERROR, "Could not create Event\n");
00956 goto error;
00957 }
00958
00959 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control);
00960 if (r != S_OK) {
00961 av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n");
00962 goto error;
00963 }
00964 ctx->control = control;
00965
00966 r = IMediaControl_Run(control);
00967 if (r == S_FALSE) {
00968 OAFilterState pfs;
00969 r = IMediaControl_GetState(control, 0, &pfs);
00970 }
00971 if (r != S_OK) {
00972 av_log(avctx, AV_LOG_ERROR, "Could not run filter\n");
00973 goto error;
00974 }
00975
00976 ret = 0;
00977
00978 error:
00979
00980 if (ret < 0)
00981 dshow_read_close(avctx);
00982
00983 if (devenum)
00984 ICreateDevEnum_Release(devenum);
00985
00986 return ret;
00987 }
00988
00989 static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
00990 {
00991 struct dshow_ctx *ctx = s->priv_data;
00992 AVPacketList *pktl = NULL;
00993
00994 while (!pktl) {
00995 WaitForSingleObject(ctx->mutex, INFINITE);
00996 pktl = ctx->pktl;
00997 if (pktl) {
00998 *pkt = pktl->pkt;
00999 ctx->pktl = ctx->pktl->next;
01000 av_free(pktl);
01001 ctx->curbufsize -= pkt->size;
01002 }
01003 ResetEvent(ctx->event);
01004 ReleaseMutex(ctx->mutex);
01005 if (!pktl) {
01006 if (s->flags & AVFMT_FLAG_NONBLOCK) {
01007 return AVERROR(EAGAIN);
01008 } else {
01009 WaitForSingleObject(ctx->event, INFINITE);
01010 }
01011 }
01012 }
01013
01014 return pkt->size;
01015 }
01016
01017 #define OFFSET(x) offsetof(struct dshow_ctx, x)
01018 #define DEC AV_OPT_FLAG_DECODING_PARAM
01019 static const AVOption options[] = {
01020 { "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 },
01021 { "pixel_format", "set video pixel format", OFFSET(pixel_format), AV_OPT_TYPE_PIXEL_FMT, {.str = NULL}, 0, 0, DEC },
01022 { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
01023 { "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
01024 { "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 16, DEC },
01025 { "channels", "set number of audio channels, such as 1 or 2", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
01026 { "list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, DEC, "list_devices" },
01027 { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "list_devices" },
01028 { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "list_devices" },
01029 { "list_options", "list available options for specified device", OFFSET(list_options), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, DEC, "list_options" },
01030 { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "list_options" },
01031 { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "list_options" },
01032 { "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 },
01033 { "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 },
01034 { "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 },
01035 { NULL },
01036 };
01037
01038 static const AVClass dshow_class = {
01039 .class_name = "DirectShow indev",
01040 .item_name = av_default_item_name,
01041 .option = options,
01042 .version = LIBAVUTIL_VERSION_INT,
01043 };
01044
01045 AVInputFormat ff_dshow_demuxer = {
01046 .name = "dshow",
01047 .long_name = NULL_IF_CONFIG_SMALL("DirectShow capture"),
01048 .priv_data_size = sizeof(struct dshow_ctx),
01049 .read_header = dshow_read_header,
01050 .read_packet = dshow_read_packet,
01051 .read_close = dshow_read_close,
01052 .flags = AVFMT_NOFILE,
01053 .priv_class = &dshow_class,
01054 };