static int dshow_read_header(AVFormatContext *avctx) { struct dshow_ctx *ctx = avctx->priv_data; IGraphBuilder *graph = NULL; ICreateDevEnum *devenum = NULL; IMediaControl *control = NULL; int ret = AVERROR(EIO); int r; if (!ctx->list_devices && !parse_device_name(avctx)) { av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n"); goto error; } ctx->video_codec_id = avctx->video_codec_id ? avctx->video_codec_id : AV_CODEC_ID_RAWVIDEO; if (ctx->pixel_format != AV_PIX_FMT_NONE) { if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) { av_log(avctx, AV_LOG_ERROR, "Pixel format may only be set when " "video codec is not set or set to rawvideo\n"); ret = AVERROR(EINVAL); goto error; } } if (ctx->framerate) { r = av_parse_video_rate(&ctx->requested_framerate, ctx->framerate); if (r < 0) { av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate); goto error; } } CoInitialize(0); r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (void **) &graph); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n"); goto error; } ctx->graph = graph; r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum, (void **) &devenum); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n"); goto error; } if (ctx->list_devices) { av_log(avctx, AV_LOG_INFO, "DirectShow video devices\n"); dshow_cycle_devices(avctx, devenum, VideoDevice, NULL); av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n"); dshow_cycle_devices(avctx, devenum, AudioDevice, NULL); ret = AVERROR_EXIT; goto error; } if (ctx->list_options) { if (ctx->device_name[VideoDevice]) dshow_list_device_options(avctx, devenum, VideoDevice); if (ctx->device_name[AudioDevice]) dshow_list_device_options(avctx, devenum, AudioDevice); ret = AVERROR_EXIT; goto error; } if (ctx->device_name[VideoDevice]) { if ((r = dshow_open_device(avctx, devenum, VideoDevice)) < 0 || (r = dshow_add_device(avctx, VideoDevice)) < 0) { ret = r; goto error; } } if (ctx->device_name[AudioDevice]) { if ((r = dshow_open_device(avctx, devenum, AudioDevice)) < 0 || (r = dshow_add_device(avctx, AudioDevice)) < 0) { ret = r; goto error; } } ctx->mutex = CreateMutex(NULL, 0, NULL); if (!ctx->mutex) { av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n"); goto error; } ctx->event = CreateEvent(NULL, 1, 0, NULL); if (!ctx->event) { av_log(avctx, AV_LOG_ERROR, "Could not create Event\n"); goto error; } r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n"); goto error; } ctx->control = control; r = IMediaControl_Run(control); if (r == S_FALSE) { OAFilterState pfs; r = IMediaControl_GetState(control, 0, &pfs); } if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not run filter\n"); goto error; } ret = 0; error: if (ret < 0) dshow_read_close(avctx); if (devenum) ICreateDevEnum_Release(devenum); return ret; }
static int dshow_read_header(AVFormatContext *avctx) { struct dshow_ctx *ctx = avctx->priv_data; IGraphBuilder *graph = NULL; ICreateDevEnum *devenum = NULL; IMediaControl *control = NULL; IMediaEvent *media_event = NULL; HANDLE media_event_handle; HANDLE proc; int ret = AVERROR(EIO); int r; CoInitialize(0); if (!ctx->list_devices && !parse_device_name(avctx)) { av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n"); goto error; } ctx->video_codec_id = avctx->video_codec_id ? avctx->video_codec_id : AV_CODEC_ID_RAWVIDEO; if (ctx->pixel_format != AV_PIX_FMT_NONE) { if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) { av_log(avctx, AV_LOG_ERROR, "Pixel format may only be set when " "video codec is not set or set to rawvideo\n"); ret = AVERROR(EINVAL); goto error; } } if (ctx->framerate) { r = av_parse_video_rate(&ctx->requested_framerate, ctx->framerate); if (r < 0) { av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate); goto error; } } r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IGraphBuilder, (void **) &graph); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n"); goto error; } ctx->graph = graph; r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, &IID_ICreateDevEnum, (void **) &devenum); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n"); goto error; } if (ctx->list_devices) { av_log(avctx, AV_LOG_INFO, "DirectShow video devices (some may be both video and audio devices)\n"); dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL); av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n"); dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL); ret = AVERROR_EXIT; goto error; } if (ctx->list_options) { if (ctx->device_name[VideoDevice]) if ((r = dshow_list_device_options(avctx, devenum, VideoDevice, VideoSourceDevice))) { ret = r; goto error; } if (ctx->device_name[AudioDevice]) { if (dshow_list_device_options(avctx, devenum, AudioDevice, AudioSourceDevice)) { /* show audio options from combined video+audio sources as fallback */ if ((r = dshow_list_device_options(avctx, devenum, AudioDevice, VideoSourceDevice))) { ret = r; goto error; } } } } if (ctx->device_name[VideoDevice]) { if ((r = dshow_open_device(avctx, devenum, VideoDevice, VideoSourceDevice)) < 0 || (r = dshow_add_device(avctx, VideoDevice)) < 0) { ret = r; goto error; } } if (ctx->device_name[AudioDevice]) { if ((r = dshow_open_device(avctx, devenum, AudioDevice, AudioSourceDevice)) < 0 || (r = dshow_add_device(avctx, AudioDevice)) < 0) { av_log(avctx, AV_LOG_INFO, "Searching for audio device within video devices for %s\n", ctx->device_name[AudioDevice]); /* see if there's a video source with an audio pin with the given audio name */ if ((r = dshow_open_device(avctx, devenum, AudioDevice, VideoSourceDevice)) < 0 || (r = dshow_add_device(avctx, AudioDevice)) < 0) { ret = r; goto error; } } } if (ctx->list_options) { /* allow it to list crossbar options in dshow_open_device */ ret = AVERROR_EXIT; goto error; } ctx->curbufsize[0] = 0; ctx->curbufsize[1] = 0; ctx->mutex = CreateMutex(NULL, 0, NULL); if (!ctx->mutex) { av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n"); goto error; } ctx->event[1] = CreateEvent(NULL, 1, 0, NULL); if (!ctx->event[1]) { av_log(avctx, AV_LOG_ERROR, "Could not create Event\n"); goto error; } r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n"); goto error; } ctx->control = control; r = IGraphBuilder_QueryInterface(graph, &IID_IMediaEvent, (void **) &media_event); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not get media event.\n"); goto error; } ctx->media_event = media_event; r = IMediaEvent_GetEventHandle(media_event, (void *) &media_event_handle); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not get media event handle.\n"); goto error; } proc = GetCurrentProcess(); r = DuplicateHandle(proc, media_event_handle, proc, &ctx->event[0], 0, 0, DUPLICATE_SAME_ACCESS); if (!r) { av_log(avctx, AV_LOG_ERROR, "Could not duplicate media event handle.\n"); goto error; } r = IMediaControl_Run(control); if (r == S_FALSE) { OAFilterState pfs; r = IMediaControl_GetState(control, 0, &pfs); } if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Could not run graph (sometimes caused by a device already in use by other application)\n"); goto error; } ret = 0; error: if (devenum) ICreateDevEnum_Release(devenum); if (ret < 0) dshow_read_close(avctx); return ret; }
static int dshow_add_device(AVFormatContext *avctx, enum dshowDeviceType devtype) { struct dshow_ctx *ctx = avctx->priv_data; AM_MEDIA_TYPE type; AVCodecContext *codec; AVStream *st; int ret = AVERROR(EIO); st = avformat_new_stream(avctx, NULL); if (!st) { ret = AVERROR(ENOMEM); goto error; } st->id = devtype; ctx->capture_filter[devtype]->stream_index = st->index; libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type); codec = st->codec; if (devtype == VideoDevice) { BITMAPINFOHEADER *bih = NULL; AVRational time_base; if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) { VIDEOINFOHEADER *v = (void *) type.pbFormat; time_base = (AVRational) { v->AvgTimePerFrame, 10000000 }; bih = &v->bmiHeader; } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) { VIDEOINFOHEADER2 *v = (void *) type.pbFormat; time_base = (AVRational) { v->AvgTimePerFrame, 10000000 }; bih = &v->bmiHeader; } if (!bih) { av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n"); goto error; } codec->time_base = time_base; codec->codec_type = AVMEDIA_TYPE_VIDEO; codec->width = bih->biWidth; codec->height = bih->biHeight; codec->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); if (codec->pix_fmt == AV_PIX_FMT_NONE) { codec->codec_id = dshow_codecid(bih->biCompression); if (codec->codec_id == AV_CODEC_ID_NONE) { av_log(avctx, AV_LOG_ERROR, "Unknown compression type. " "Please report verbose (-v 9) debug information.\n"); dshow_read_close(avctx); return AVERROR_PATCHWELCOME; } codec->bits_per_coded_sample = bih->biBitCount; } else { codec->codec_id = AV_CODEC_ID_RAWVIDEO; if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) { codec->bits_per_coded_sample = bih->biBitCount; codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE); if (codec->extradata) { codec->extradata_size = 9; memcpy(codec->extradata, "BottomUp", 9); } } } } else { WAVEFORMATEX *fx = NULL; if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) { fx = (void *) type.pbFormat; } if (!fx) { av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n"); goto error; } codec->codec_type = AVMEDIA_TYPE_AUDIO; codec->sample_fmt = sample_fmt_bits_per_sample(fx->wBitsPerSample); codec->codec_id = waveform_codec_id(codec->sample_fmt); codec->sample_rate = fx->nSamplesPerSec; codec->channels = fx->nChannels; } avpriv_set_pts_info(st, 64, 1, 10000000); ret = 0; error: return ret; }