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