dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,

                    enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, IBaseFilter **pfilter)

{

    struct dshow_ctx *ctx = avctx->priv_data;

    IBaseFilter *device_filter = NULL;

    IEnumMoniker *classenum = NULL;

    IMoniker *m = NULL;

    const char *device_name = ctx->device_name[devtype];

    int skip = (devtype == VideoDevice) ? ctx->video_device_number

                                        : ctx->audio_device_number;

    int r;



    const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,

                                   &CLSID_AudioInputDeviceCategory };

    const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only";

    const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio";



    r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[sourcetype],

                                             (IEnumMoniker **) &classenum, 0);

    if (r != S_OK) {

        av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices (or none found).\n",

               devtypename);

        return AVERROR(EIO);

    }



    while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {

        IPropertyBag *bag = NULL;

        char *friendly_name = NULL;

        char *unique_name = NULL;

        VARIANT var;

        IBindCtx *bind_ctx = NULL;

        LPOLESTR olestr = NULL;

        LPMALLOC co_malloc = NULL;

        int i;



        r = CoGetMalloc(1, &co_malloc);

        if (r = S_OK)

            goto fail1;

        r = CreateBindCtx(0, &bind_ctx);

        if (r != S_OK)

            goto fail1;

        /* GetDisplayname works for both video and audio, DevicePath doesn't */

        r = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr);

        if (r != S_OK)

            goto fail1;

        unique_name = dup_wchar_to_utf8(olestr);

        /* replace ':' with '_' since we use : to delineate between sources */

        for (i = 0; i < strlen(unique_name); i++) {

            if (unique_name[i] == ':')

                unique_name[i] = '_';

        }



        r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);

        if (r != S_OK)

            goto fail1;



        var.vt = VT_BSTR;

        r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);

        if (r != S_OK)

            goto fail1;

        friendly_name = dup_wchar_to_utf8(var.bstrVal);



        if (pfilter) {

            if (strcmp(device_name, friendly_name) && strcmp(device_name, unique_name))

                goto fail1;



            if (!skip--) {

                r = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);

                if (r != S_OK) {

                    av_log(avctx, AV_LOG_ERROR, "Unable to BindToObject for %s\n", device_name);

                    goto fail1;

                }

            }

        } else {

            av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name);

            av_log(avctx, AV_LOG_INFO, "    Alternative name \"%s\"\n", unique_name);

        }



fail1:

        if (olestr && co_malloc)

            IMalloc_Free(co_malloc, olestr);

        if (bind_ctx)

            IBindCtx_Release(bind_ctx);

        av_free(friendly_name);

        av_free(unique_name);

        if (bag)

            IPropertyBag_Release(bag);

        IMoniker_Release(m);

    }



    IEnumMoniker_Release(classenum);



    if (pfilter) {

        if (!device_filter) {

            av_log(avctx, AV_LOG_ERROR, "Could not find %s device with name [%s] among source devices of type %s.\n",

                   devtypename, device_name, sourcetypename);

            return AVERROR(EIO);

        }

        *pfilter = device_filter;

    }



    return 0;

}

dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,

                    enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, IBaseFilter **pfilter)

{

    struct dshow_ctx *ctx = avctx->priv_data;

    IBaseFilter *device_filter = NULL;

    IEnumMoniker *classenum = NULL;

    IMoniker *m = NULL;

    const char *device_name = ctx->device_name[devtype];

    int skip = (devtype == VideoDevice) ? ctx->video_device_number

                                        : ctx->audio_device_number;

    int r;



    const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,

                                   &CLSID_AudioInputDeviceCategory };

    const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only";

    const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio";



    r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[sourcetype],

                                             (IEnumMoniker **) &classenum, 0);

    if (r != S_OK) {

        av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices (or none found).\n",

               devtypename);

        return AVERROR(EIO);

    }



    while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {

        IPropertyBag *bag = NULL;

        char *friendly_name = NULL;

        char *unique_name = NULL;

        VARIANT var;

        IBindCtx *bind_ctx = NULL;

        LPOLESTR olestr = NULL;

        LPMALLOC co_malloc = NULL;

        int i;



        r = CoGetMalloc(1, &co_malloc);

        if (r = S_OK)

            goto fail1;

        r = CreateBindCtx(0, &bind_ctx);

        if (r != S_OK)

            goto fail1;

        

        r = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr);

        if (r != S_OK)

            goto fail1;

        unique_name = dup_wchar_to_utf8(olestr);

        

        for (i = 0; i < strlen(unique_name); i++) {

            if (unique_name[i] == ':')

                unique_name[i] = '_';

        }



        r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);

        if (r != S_OK)

            goto fail1;



        var.vt = VT_BSTR;

        r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);

        if (r != S_OK)

            goto fail1;

        friendly_name = dup_wchar_to_utf8(var.bstrVal);



        if (pfilter) {

            if (strcmp(device_name, friendly_name) && strcmp(device_name, unique_name))

                goto fail1;



            if (!skip--) {

                r = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);

                if (r != S_OK) {

                    av_log(avctx, AV_LOG_ERROR, "Unable to BindToObject for %s\n", device_name);

                    goto fail1;

                }

            }

        } else {

            av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name);

            av_log(avctx, AV_LOG_INFO, "    Alternative name \"%s\"\n", unique_name);

        }



fail1:

        if (olestr && co_malloc)

            IMalloc_Free(co_malloc, olestr);

        if (bind_ctx)

            IBindCtx_Release(bind_ctx);

        av_free(friendly_name);

        av_free(unique_name);

        if (bag)

            IPropertyBag_Release(bag);

        IMoniker_Release(m);

    }



    IEnumMoniker_Release(classenum);



    if (pfilter) {

        if (!device_filter) {

            av_log(avctx, AV_LOG_ERROR, "Could not find %s device with name [%s] among source devices of type %s.\n",

                   devtypename, device_name, sourcetypename);

            return AVERROR(EIO);

        }

        *pfilter = device_filter;

    }



    return 0;

}

FUNC_0(AVFormatContext *VAR_0, ICreateDevEnum *VAR_1,

                    enum dshowDeviceType VAR_2, enum dshowSourceFilterType VAR_3, IBaseFilter **VAR_4)

{

    struct dshow_ctx *VAR_5 = VAR_0->priv_data;

    IBaseFilter *device_filter = NULL;

    IEnumMoniker *classenum = NULL;

    IMoniker *m = NULL;

    const char *VAR_6 = VAR_5->VAR_6[VAR_2];

    int VAR_7 = (VAR_2 == VideoDevice) ? VAR_5->video_device_number

                                        : VAR_5->audio_device_number;

    int VAR_8;



    const GUID *VAR_9[2] = { &CLSID_VideoInputDeviceCategory,

                                   &CLSID_AudioInputDeviceCategory };

    const char *VAR_10 = (VAR_2 == VideoDevice) ? "video" : "audio only";

    const char *VAR_11 = (VAR_3 == VideoSourceDevice) ? "video" : "audio";



    VAR_8 = ICreateDevEnum_CreateClassEnumerator(VAR_1, VAR_9[VAR_3],

                                             (IEnumMoniker **) &classenum, 0);

    if (VAR_8 != S_OK) {

        av_log(VAR_0, AV_LOG_ERROR, "Could not enumerate %s devices (or none found).\n",

               VAR_10);

        return AVERROR(EIO);

    }



    while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {

        IPropertyBag *bag = NULL;

        char *VAR_12 = NULL;

        char *VAR_13 = NULL;

        VARIANT var;

        IBindCtx *bind_ctx = NULL;

        LPOLESTR olestr = NULL;

        LPMALLOC co_malloc = NULL;

        int VAR_14;



        VAR_8 = CoGetMalloc(1, &co_malloc);

        if (VAR_8 = S_OK)

            goto fail1;

        VAR_8 = CreateBindCtx(0, &bind_ctx);

        if (VAR_8 != S_OK)

            goto fail1;

        

        VAR_8 = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr);

        if (VAR_8 != S_OK)

            goto fail1;

        VAR_13 = dup_wchar_to_utf8(olestr);

        

        for (VAR_14 = 0; VAR_14 < strlen(VAR_13); VAR_14++) {

            if (VAR_13[VAR_14] == ':')

                VAR_13[VAR_14] = '_';

        }



        VAR_8 = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);

        if (VAR_8 != S_OK)

            goto fail1;



        var.vt = VT_BSTR;

        VAR_8 = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);

        if (VAR_8 != S_OK)

            goto fail1;

        VAR_12 = dup_wchar_to_utf8(var.bstrVal);



        if (VAR_4) {

            if (strcmp(VAR_6, VAR_12) && strcmp(VAR_6, VAR_13))

                goto fail1;



            if (!VAR_7--) {

                VAR_8 = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);

                if (VAR_8 != S_OK) {

                    av_log(VAR_0, AV_LOG_ERROR, "Unable to BindToObject for %s\n", VAR_6);

                    goto fail1;

                }

            }

        } else {

            av_log(VAR_0, AV_LOG_INFO, " \"%s\"\n", VAR_12);

            av_log(VAR_0, AV_LOG_INFO, "    Alternative name \"%s\"\n", VAR_13);

        }



fail1:

        if (olestr && co_malloc)

            IMalloc_Free(co_malloc, olestr);

        if (bind_ctx)

            IBindCtx_Release(bind_ctx);

        av_free(VAR_12);

        av_free(VAR_13);

        if (bag)

            IPropertyBag_Release(bag);

        IMoniker_Release(m);

    }



    IEnumMoniker_Release(classenum);



    if (VAR_4) {

        if (!device_filter) {

            av_log(VAR_0, AV_LOG_ERROR, "Could not find %s device with name [%s] among source devices of type %s.\n",

                   VAR_10, VAR_6, VAR_11);

            return AVERROR(EIO);

        }

        *VAR_4 = device_filter;

    }



    return 0;

}

FUNC_0(AVFormatContext *VAR_0, ICreateDevEnum *VAR_1,
enum dshowDeviceType VAR_2, enum dshowSourceFilterType VAR_3, IBaseFilter **VAR_4)
{ struct dshow_ctx *VAR_5 = VAR_0->priv_data; IBaseFilter *device_filter = NULL; IEnumMoniker *classenum = NULL; IMoniker *m = NULL; const char *VAR_6 = VAR_5->VAR_6[VAR_2]; int VAR_7 = (VAR_2 == VideoDevice) ? VAR_5->video_device_number
: VAR_5->audio_device_number; int VAR_8; const GUID *VAR_9[2] = { &CLSID_VideoInputDeviceCategory, &CLSID_AudioInputDeviceCategory }; const char *VAR_10 = (VAR_2 == VideoDevice) ? "video" : "audio only"; const char *VAR_11 = (VAR_3 == VideoSourceDevice) ? "video" : "audio"; VAR_8 = ICreateDevEnum_CreateClassEnumerator(VAR_1, VAR_9[VAR_3],
(IEnumMoniker **) &classenum, 0); if (VAR_8 != S_OK) { av_log(VAR_0, AV_LOG_ERROR, "Could not enumerate %s devices (or none found).\n",
VAR_10); return AVERROR(EIO); } while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) { IPropertyBag *bag = NULL; char *VAR_12 = NULL; char *VAR_13 = NULL; VARIANT var; IBindCtx *bind_ctx = NULL; LPOLESTR olestr = NULL; LPMALLOC co_malloc = NULL; int VAR_14; VAR_8 = CoGetMalloc(1, &co_malloc); if (VAR_8 = S_OK)
goto fail1; VAR_8 = CreateBindCtx(0, &bind_ctx); if (VAR_8 != S_OK)
goto fail1; VAR_8 = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr); if (VAR_8 != S_OK)
goto fail1; VAR_13 = dup_wchar_to_utf8(olestr); for (VAR_14 = 0; VAR_14 < strlen(VAR_13); VAR_14++) { if (VAR_13[VAR_14] == ':')
VAR_13[VAR_14] = '_'; } VAR_8 = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag); if (VAR_8 != S_OK)
goto fail1; var.vt = VT_BSTR; VAR_8 = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL); if (VAR_8 != S_OK)
goto fail1; VAR_12 = dup_wchar_to_utf8(var.bstrVal); if (VAR_4) { if (strcmp(VAR_6, VAR_12) && strcmp(VAR_6, VAR_13))
goto fail1; if (!VAR_7--) { VAR_8 = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter); if (VAR_8 != S_OK) { av_log(VAR_0, AV_LOG_ERROR, "Unable to BindToObject for %s\n", VAR_6); goto fail1; } } } else { av_log(VAR_0, AV_LOG_INFO, " \"%s\"\n", VAR_12); av_log(VAR_0, AV_LOG_INFO, "    Alternative name \"%s\"\n", VAR_13); } fail1:
if (olestr && co_malloc)
IMalloc_Free(co_malloc, olestr); if (bind_ctx)
IBindCtx_Release(bind_ctx); av_free(VAR_12); av_free(VAR_13); if (bag)
IPropertyBag_Release(bag); IMoniker_Release(m); } IEnumMoniker_Release(classenum); if (VAR_4) { if (!device_filter) { av_log(VAR_0, AV_LOG_ERROR, "Could not find %s device with name [%s] among source devices of type %s.\n",
VAR_10, VAR_6, VAR_11); return AVERROR(EIO); } *VAR_4 = device_filter; } return 0; }