00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavformat/timefilter.h"
00023
00024 #include "avdevice.h"
00025 #include "dshow.h"
00026
00027 struct dshow_ctx {
00028 IGraphBuilder *graph;
00029
00030 char *device_name[2];
00031
00032 IBaseFilter *device_filter[2];
00033 IPin *device_pin[2];
00034 libAVFilter *capture_filter[2];
00035 libAVPin *capture_pin[2];
00036
00037 HANDLE mutex;
00038 HANDLE event;
00039 AVPacketList *pktl;
00040
00041 unsigned int curbufsize;
00042 unsigned int video_frame_num;
00043
00044 IMediaControl *control;
00045
00046 TimeFilter *timefilter;
00047 };
00048
00049 static enum PixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
00050 {
00051 switch(biCompression) {
00052 case MKTAG('U', 'Y', 'V', 'Y'):
00053 return PIX_FMT_UYVY422;
00054 case MKTAG('Y', 'U', 'Y', '2'):
00055 return PIX_FMT_YUYV422;
00056 case MKTAG('I', '4', '2', '0'):
00057 return PIX_FMT_YUV420P;
00058 case BI_RGB:
00059 switch(biBitCount) {
00060 case 1:
00061 return PIX_FMT_MONOWHITE;
00062 case 4:
00063 return PIX_FMT_RGB4;
00064 case 8:
00065 return PIX_FMT_RGB8;
00066 case 16:
00067 return PIX_FMT_RGB555;
00068 case 24:
00069 return PIX_FMT_BGR24;
00070 case 32:
00071 return PIX_FMT_RGB32;
00072 }
00073 }
00074 return PIX_FMT_NONE;
00075 }
00076
00077 static enum CodecID dshow_codecid(DWORD biCompression)
00078 {
00079 switch(biCompression) {
00080 case MKTAG('d', 'v', 's', 'd'):
00081 return CODEC_ID_DVVIDEO;
00082 case MKTAG('M', 'J', 'P', 'G'):
00083 case MKTAG('m', 'j', 'p', 'g'):
00084 return CODEC_ID_MJPEG;
00085 }
00086 return CODEC_ID_NONE;
00087 }
00088
00089 static int
00090 dshow_read_close(AVFormatContext *s)
00091 {
00092 struct dshow_ctx *ctx = s->priv_data;
00093 AVPacketList *pktl;
00094
00095 if (ctx->control) {
00096 IMediaControl_Stop(ctx->control);
00097 IMediaControl_Release(ctx->control);
00098 }
00099 if (ctx->graph)
00100 IGraphBuilder_Release(ctx->graph);
00101
00102
00103
00104 if (ctx->capture_pin[VideoDevice])
00105 libAVPin_Release(ctx->capture_pin[VideoDevice]);
00106 if (ctx->capture_pin[AudioDevice])
00107 libAVPin_Release(ctx->capture_pin[AudioDevice]);
00108 if (ctx->capture_filter[VideoDevice])
00109 libAVFilter_Release(ctx->capture_filter[VideoDevice]);
00110 if (ctx->capture_filter[AudioDevice])
00111 libAVFilter_Release(ctx->capture_filter[AudioDevice]);
00112
00113 if (ctx->device_pin[VideoDevice])
00114 IPin_Release(ctx->device_pin[VideoDevice]);
00115 if (ctx->device_pin[AudioDevice])
00116 IPin_Release(ctx->device_pin[AudioDevice]);
00117 if (ctx->device_filter[VideoDevice])
00118 IBaseFilter_Release(ctx->device_filter[VideoDevice]);
00119 if (ctx->device_filter[AudioDevice])
00120 IBaseFilter_Release(ctx->device_filter[AudioDevice]);
00121
00122 if (ctx->device_name[0])
00123 av_free(ctx->device_name[0]);
00124 if (ctx->device_name[1])
00125 av_free(ctx->device_name[1]);
00126
00127 if(ctx->mutex)
00128 CloseHandle(ctx->mutex);
00129 if(ctx->event)
00130 CloseHandle(ctx->event);
00131
00132 pktl = ctx->pktl;
00133 while (pktl) {
00134 AVPacketList *next = pktl->next;
00135 av_destruct_packet(&pktl->pkt);
00136 av_free(pktl);
00137 pktl = next;
00138 }
00139
00140 return 0;
00141 }
00142
00143 static char *dup_wchar_to_utf8(wchar_t *w)
00144 {
00145 char *s = NULL;
00146 int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
00147 s = av_malloc(l);
00148 if (s)
00149 WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
00150 return s;
00151 }
00152
00153 static int shall_we_drop(AVFormatContext *s)
00154 {
00155 struct dshow_ctx *ctx = s->priv_data;
00156 const uint8_t dropscore[] = {62, 75, 87, 100};
00157 const int ndropscores = FF_ARRAY_ELEMS(dropscore);
00158 unsigned int buffer_fullness = (ctx->curbufsize*100)/s->max_picture_buffer;
00159
00160 if(dropscore[++ctx->video_frame_num%ndropscores] <= buffer_fullness) {
00161 av_log(s, AV_LOG_ERROR,
00162 "real-time buffer %d%% full! frame dropped!\n", buffer_fullness);
00163 return 1;
00164 }
00165
00166 return 0;
00167 }
00168
00169 static void
00170 callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time)
00171 {
00172 AVFormatContext *s = priv_data;
00173 struct dshow_ctx *ctx = s->priv_data;
00174 AVPacketList **ppktl, *pktl_next;
00175
00176
00177
00178 if(shall_we_drop(s))
00179 return;
00180
00181 WaitForSingleObject(ctx->mutex, INFINITE);
00182
00183 pktl_next = av_mallocz(sizeof(AVPacketList));
00184 if(!pktl_next)
00185 goto fail;
00186
00187 if(av_new_packet(&pktl_next->pkt, buf_size) < 0) {
00188 av_free(pktl_next);
00189 goto fail;
00190 }
00191
00192 pktl_next->pkt.stream_index = index;
00193 pktl_next->pkt.pts = time;
00194 memcpy(pktl_next->pkt.data, buf, buf_size);
00195
00196 for(ppktl = &ctx->pktl ; *ppktl ; ppktl = &(*ppktl)->next);
00197 *ppktl = pktl_next;
00198
00199 ctx->curbufsize += buf_size;
00200
00201 SetEvent(ctx->event);
00202 ReleaseMutex(ctx->mutex);
00203
00204 return;
00205 fail:
00206 ReleaseMutex(ctx->mutex);
00207 return;
00208 }
00209
00210 static int
00211 dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
00212 enum dshowDeviceType devtype)
00213 {
00214 struct dshow_ctx *ctx = avctx->priv_data;
00215 IBaseFilter *device_filter = NULL;
00216 IEnumMoniker *classenum = NULL;
00217 IGraphBuilder *graph = ctx->graph;
00218 IEnumPins *pins = 0;
00219 IMoniker *m = NULL;
00220 IPin *device_pin = NULL;
00221 libAVPin *capture_pin = NULL;
00222 libAVFilter *capture_filter = NULL;
00223 const char *device_name = ctx->device_name[devtype];
00224 int ret = AVERROR(EIO);
00225 IPin *pin;
00226 int r, i;
00227
00228 const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
00229 &CLSID_AudioInputDeviceCategory };
00230 const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
00231 const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
00232 const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
00233
00234 r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[devtype],
00235 (IEnumMoniker **) &classenum, 0);
00236 if (r != S_OK) {
00237 av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices.\n",
00238 devtypename);
00239 goto error;
00240 }
00241
00242 while (IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK && !device_filter) {
00243 IPropertyBag *bag = NULL;
00244 char *buf = NULL;
00245 VARIANT var;
00246
00247 r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);
00248 if (r != S_OK)
00249 goto fail1;
00250
00251 var.vt = VT_BSTR;
00252 r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);
00253 if (r != S_OK)
00254 goto fail1;
00255
00256 buf = dup_wchar_to_utf8(var.bstrVal);
00257
00258 if (strcmp(device_name, buf))
00259 goto fail1;
00260
00261 IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);
00262
00263 fail1:
00264 if (buf)
00265 av_free(buf);
00266 if (bag)
00267 IPropertyBag_Release(bag);
00268 IMoniker_Release(m);
00269 }
00270
00271 if (!device_filter) {
00272 av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n",
00273 devtypename);
00274 goto error;
00275 }
00276 ctx->device_filter [devtype] = device_filter;
00277
00278 r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
00279 if (r != S_OK) {
00280 av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
00281 goto error;
00282 }
00283
00284 r = IBaseFilter_EnumPins(device_filter, &pins);
00285 if (r != S_OK) {
00286 av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
00287 goto error;
00288 }
00289
00290 i = 0;
00291 while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK && !device_pin) {
00292 IKsPropertySet *p = NULL;
00293 IEnumMediaTypes *types;
00294 PIN_INFO info = {0};
00295 AM_MEDIA_TYPE *type;
00296 GUID category;
00297 DWORD r2;
00298
00299 IPin_QueryPinInfo(pin, &info);
00300 IBaseFilter_Release(info.pFilter);
00301
00302 if (info.dir != PINDIR_OUTPUT)
00303 goto next;
00304 if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK)
00305 goto next;
00306 if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
00307 NULL, 0, &category, sizeof(GUID), &r2) != S_OK)
00308 goto next;
00309 if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
00310 goto next;
00311
00312 if (IPin_EnumMediaTypes(pin, &types) != S_OK)
00313 goto next;
00314
00315 IEnumMediaTypes_Reset(types);
00316 while (IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK && !device_pin) {
00317 if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
00318 device_pin = pin;
00319 goto next;
00320 }
00321 CoTaskMemFree(type);
00322 }
00323
00324 next:
00325 if (types)
00326 IEnumMediaTypes_Release(types);
00327 if (p)
00328 IKsPropertySet_Release(p);
00329 if (device_pin != pin)
00330 IPin_Release(pin);
00331 }
00332
00333 if (!device_pin) {
00334 av_log(avctx, AV_LOG_ERROR,
00335 "Could not find output pin from %s capture device.\n", devtypename);
00336 goto error;
00337 }
00338 ctx->device_pin[devtype] = device_pin;
00339
00340 capture_filter = libAVFilter_Create(avctx, callback, devtype);
00341 if (!capture_filter) {
00342 av_log(avctx, AV_LOG_ERROR, "Could not create grabber filter.\n");
00343 goto error;
00344 }
00345 ctx->capture_filter[devtype] = capture_filter;
00346
00347 r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter,
00348 filter_name[devtype]);
00349 if (r != S_OK) {
00350 av_log(avctx, AV_LOG_ERROR, "Could not add capture filter to graph\n");
00351 goto error;
00352 }
00353
00354 libAVPin_AddRef(capture_filter->pin);
00355 capture_pin = capture_filter->pin;
00356 ctx->capture_pin[devtype] = capture_pin;
00357
00358 r = IGraphBuilder_ConnectDirect(graph, device_pin, (IPin *) capture_pin, NULL);
00359 if (r != S_OK) {
00360 av_log(avctx, AV_LOG_ERROR, "Could not connect pins\n");
00361 goto error;
00362 }
00363
00364 ret = 0;
00365
00366 error:
00367 if (pins)
00368 IEnumPins_Release(pins);
00369 if (classenum)
00370 IEnumMoniker_Release(classenum);
00371
00372 return ret;
00373 }
00374
00375 static enum CodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
00376 {
00377 switch (sample_fmt) {
00378 case AV_SAMPLE_FMT_U8: return CODEC_ID_PCM_U8;
00379 case AV_SAMPLE_FMT_S16: return CODEC_ID_PCM_S16LE;
00380 case AV_SAMPLE_FMT_S32: return CODEC_ID_PCM_S32LE;
00381 default: return CODEC_ID_NONE;
00382 }
00383 }
00384
00385 static enum SampleFormat sample_fmt_bits_per_sample(int bits)
00386 {
00387 switch (bits) {
00388 case 8: return AV_SAMPLE_FMT_U8;
00389 case 16: return AV_SAMPLE_FMT_S16;
00390 case 32: return AV_SAMPLE_FMT_S32;
00391 default: return AV_SAMPLE_FMT_NONE;
00392 }
00393 }
00394
00395 static int
00396 dshow_add_device(AVFormatContext *avctx, AVFormatParameters *ap,
00397 enum dshowDeviceType devtype)
00398 {
00399 struct dshow_ctx *ctx = avctx->priv_data;
00400 AM_MEDIA_TYPE type;
00401 AVCodecContext *codec;
00402 AVStream *st;
00403 int ret = AVERROR(EIO);
00404
00405 st = av_new_stream(avctx, devtype);
00406 if (!st) {
00407 ret = AVERROR(ENOMEM);
00408 goto error;
00409 }
00410
00411 ctx->capture_filter[devtype]->stream_index = st->index;
00412
00413 libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type);
00414
00415 codec = st->codec;
00416 if (devtype == VideoDevice) {
00417 BITMAPINFOHEADER *bih = NULL;
00418
00419 if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
00420 VIDEOINFOHEADER *v = (void *) type.pbFormat;
00421 bih = &v->bmiHeader;
00422 } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) {
00423 VIDEOINFOHEADER2 *v = (void *) type.pbFormat;
00424 bih = &v->bmiHeader;
00425 }
00426 if (!bih) {
00427 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
00428 goto error;
00429 }
00430
00431 codec->time_base = ap->time_base;
00432 codec->codec_type = AVMEDIA_TYPE_VIDEO;
00433 codec->width = bih->biWidth;
00434 codec->height = bih->biHeight;
00435 codec->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount);
00436 if (codec->pix_fmt == PIX_FMT_NONE) {
00437 codec->codec_id = dshow_codecid(bih->biCompression);
00438 if (codec->codec_id == CODEC_ID_NONE) {
00439 av_log(avctx, AV_LOG_ERROR, "Unknown compression type. "
00440 "Please report verbose (-v 9) debug information.\n");
00441 dshow_read_close(avctx);
00442 return AVERROR_PATCHWELCOME;
00443 }
00444 codec->bits_per_coded_sample = bih->biBitCount;
00445 } else {
00446 codec->codec_id = CODEC_ID_RAWVIDEO;
00447 if (bih->biCompression == BI_RGB) {
00448 codec->bits_per_coded_sample = bih->biBitCount;
00449 codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE);
00450 if (codec->extradata) {
00451 codec->extradata_size = 9;
00452 memcpy(codec->extradata, "BottomUp", 9);
00453 }
00454 }
00455 }
00456 } else {
00457 WAVEFORMATEX *fx = NULL;
00458
00459 if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) {
00460 fx = (void *) type.pbFormat;
00461 }
00462 if (!fx) {
00463 av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
00464 goto error;
00465 }
00466
00467 codec->codec_type = AVMEDIA_TYPE_AUDIO;
00468 codec->sample_fmt = sample_fmt_bits_per_sample(fx->wBitsPerSample);
00469 codec->codec_id = waveform_codec_id(codec->sample_fmt);
00470 codec->sample_rate = fx->nSamplesPerSec;
00471 codec->channels = fx->nChannels;
00472 }
00473
00474 av_set_pts_info(st, 64, 1, 10000000);
00475
00476 ret = 0;
00477
00478 error:
00479 return ret;
00480 }
00481
00482 static int parse_device_name(AVFormatContext *avctx)
00483 {
00484 struct dshow_ctx *ctx = avctx->priv_data;
00485 char **device_name = ctx->device_name;
00486 char *name = av_strdup(avctx->filename);
00487 char *tmp = name;
00488 int ret = 1;
00489 char *type;
00490
00491 while ((type = strtok(tmp, "="))) {
00492 char *token = strtok(NULL, ":");
00493 tmp = NULL;
00494
00495 if (!strcmp(type, "video")) {
00496 device_name[0] = token;
00497 } else if (!strcmp(type, "audio")) {
00498 device_name[1] = token;
00499 } else {
00500 device_name[0] = NULL;
00501 device_name[1] = NULL;
00502 break;
00503 }
00504 }
00505
00506 if (!device_name[0] && !device_name[1]) {
00507 ret = 0;
00508 } else {
00509 if (device_name[0])
00510 device_name[0] = av_strdup(device_name[0]);
00511 if (device_name[1])
00512 device_name[1] = av_strdup(device_name[1]);
00513 }
00514
00515 av_free(name);
00516 return ret;
00517 }
00518
00519 static int dshow_read_header(AVFormatContext *avctx, AVFormatParameters *ap)
00520 {
00521 struct dshow_ctx *ctx = avctx->priv_data;
00522 IGraphBuilder *graph = NULL;
00523 ICreateDevEnum *devenum = NULL;
00524 IMediaControl *control = NULL;
00525 int ret = AVERROR(EIO);
00526 int r;
00527
00528 if (!parse_device_name(avctx)) {
00529 av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n");
00530 goto error;
00531 }
00532
00533 CoInitialize(0);
00534
00535 r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
00536 &IID_IGraphBuilder, (void **) &graph);
00537 if (r != S_OK) {
00538 av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n");
00539 goto error;
00540 }
00541 ctx->graph = graph;
00542
00543 r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
00544 &IID_ICreateDevEnum, (void **) &devenum);
00545 if (r != S_OK) {
00546 av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
00547 goto error;
00548 }
00549
00550 if (ctx->device_name[VideoDevice]) {
00551 ret = dshow_open_device(avctx, devenum, VideoDevice);
00552 if (ret < 0)
00553 goto error;
00554 ret = dshow_add_device(avctx, ap, VideoDevice);
00555 if (ret < 0)
00556 goto error;
00557 }
00558 if (ctx->device_name[AudioDevice]) {
00559 ret = dshow_open_device(avctx, devenum, AudioDevice);
00560 if (ret < 0)
00561 goto error;
00562 ret = dshow_add_device(avctx, ap, AudioDevice);
00563 if (ret < 0)
00564 goto error;
00565 }
00566
00567 ctx->mutex = CreateMutex(NULL, 0, NULL);
00568 if (!ctx->mutex) {
00569 av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n");
00570 goto error;
00571 }
00572 ctx->event = CreateEvent(NULL, 1, 0, NULL);
00573 if (!ctx->event) {
00574 av_log(avctx, AV_LOG_ERROR, "Could not create Event\n");
00575 goto error;
00576 }
00577
00578 r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control);
00579 if (r != S_OK) {
00580 av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n");
00581 goto error;
00582 }
00583 ctx->control = control;
00584
00585 r = IMediaControl_Run(control);
00586 if (r == S_FALSE) {
00587 OAFilterState pfs;
00588 r = IMediaControl_GetState(control, 0, &pfs);
00589 }
00590 if (r != S_OK) {
00591 av_log(avctx, AV_LOG_ERROR, "Could not run filter\n");
00592 goto error;
00593 }
00594
00595 ret = 0;
00596
00597 error:
00598
00599 if (ret < 0)
00600 dshow_read_close(avctx);
00601
00602 if (devenum)
00603 ICreateDevEnum_Release(devenum);
00604
00605 return ret;
00606 }
00607
00608 static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
00609 {
00610 struct dshow_ctx *ctx = s->priv_data;
00611 AVPacketList *pktl = NULL;
00612
00613 while (!pktl) {
00614 WaitForSingleObject(ctx->mutex, INFINITE);
00615 pktl = ctx->pktl;
00616 if (ctx->pktl) {
00617 *pkt = ctx->pktl->pkt;
00618 ctx->pktl = ctx->pktl->next;
00619 av_free(pktl);
00620 }
00621 ResetEvent(ctx->event);
00622 ReleaseMutex(ctx->mutex);
00623 if (!pktl) {
00624 if (s->flags & AVFMT_FLAG_NONBLOCK) {
00625 return AVERROR(EAGAIN);
00626 } else {
00627 WaitForSingleObject(ctx->event, INFINITE);
00628 }
00629 }
00630 }
00631
00632 ctx->curbufsize -= pkt->size;
00633
00634 return pkt->size;
00635 }
00636
00637 AVInputFormat ff_dshow_demuxer = {
00638 "dshow",
00639 NULL_IF_CONFIG_SMALL("DirectShow capture"),
00640 sizeof(struct dshow_ctx),
00641 NULL,
00642 dshow_read_header,
00643 dshow_read_packet,
00644 dshow_read_close,
00645 .flags = AVFMT_NOFILE,
00646 };