예제 #1
0
static fb_mode_t *find_best_mode(int xres, int yres, range_t *hfreq,
		range_t *vfreq, range_t *dotclock)
{
	int i;
	fb_mode_t *best = fb_modes;
	fb_mode_t *curr;

	mp_msg(MSGT_VO, MSGL_DBG2, "Searching for first working mode\n");

	for (i = 0; i < nr_modes; i++, best++)
		if (mode_works(best, hfreq, vfreq, dotclock))
			break;

	if (i == nr_modes)
		return NULL;
	if (i == nr_modes - 1)
		return best;

	mp_msg(MSGT_VO, MSGL_DBG2, "First working mode: %dx%d\n", best->xres, best->yres);
	mp_msg(MSGT_VO, MSGL_DBG2, "Searching for better modes\n");

	for (curr = best + 1; i < nr_modes - 1; i++, curr++) {
		if (!mode_works(curr, hfreq, vfreq, dotclock))
			continue;

		if (best->xres < xres || best->yres < yres) {
			if (curr->xres > best->xres || curr->yres > best->yres) {
				mp_msg(MSGT_VO, MSGL_DBG2, "better than %dx%d, which is too small.\n",
							best->xres, best->yres);
				best = curr;
			} else
				mp_msg(MSGT_VO, MSGL_DBG2, "too small.\n");
		} else if (curr->xres == best->xres && curr->yres == best->yres &&
				vsf(curr) > vsf(best)) {
			mp_msg(MSGT_VO, MSGL_DBG2, "faster screen refresh.\n");
			best = curr;
		} else if ((curr->xres <= best->xres && curr->yres <= best->yres) &&
				(curr->xres >= xres && curr->yres >= yres)) {
			mp_msg(MSGT_VO, MSGL_DBG2, "better than %dx%d, which is too large.\n",
						best->xres, best->yres);
			best = curr;
		} else {
			if (curr->xres < xres || curr->yres < yres)
				mp_msg(MSGT_VO, MSGL_DBG2, "too small.\n");
			else if (curr->xres > best->xres || curr->yres > best->yres)
				mp_msg(MSGT_VO, MSGL_DBG2, "too large.\n");
			else mp_msg(MSGT_VO, MSGL_DBG2, "it's worse, don't know why.\n");
		}
	}

	return best;
}
예제 #2
0
파일: vo_fbdev.c 프로젝트: HermiG/mplayer2
static int mode_works(fb_mode_t *m, range_t *hfreq, range_t *vfreq,
                      range_t *dotclock)
{
    float h = hsf(m);
    float v = vsf(m);
    float d = dcf(m);
    int ret = 1;

    mp_msg(MSGT_VO, MSGL_DBG2, "mode %dx%d:", m->xres, m->yres);
    if (!in_range(hfreq, h)) {
        ret = 0;
        mp_msg(MSGT_VO, MSGL_DBG2, " hsync out of range.");
    }
    if (!in_range(vfreq, v)) {
        ret = 0;
        mp_msg(MSGT_VO, MSGL_DBG2, " vsync out of range.");
    }
    if (!in_range(dotclock, d)) {
        ret = 0;
        mp_msg(MSGT_VO, MSGL_DBG2, " dotclock out of range.");
    }
    if (ret)
        mp_msg(MSGT_VO, MSGL_DBG2, " hsync, vsync, dotclock ok.\n");
    else
        mp_msg(MSGT_VO, MSGL_DBG2, "\n");

    return ret;
}
예제 #3
0
int main(int argc, char *argv[])
{
    timeSelector::addOptions();

#   include "addRegionOption.H"
#   include "setRootCase.H"
#   include "createTime.H"

    instantList timeDirs = timeSelector::select0(runTime, args);

#   include "createNamedMesh.H"

    forAll(timeDirs, timeI)
    {
        runTime.setTime(timeDirs[timeI], timeI);

        Info<< "Time = " << runTime.timeName() << nl << endl;

        const IOobjectList fieldObjs(mesh, runTime.timeName());
        const wordList objNames = fieldObjs.names();

        PtrList<volScalarField> vsf(objNames.size());
        PtrList<volVectorField> vvf(objNames.size());
        PtrList<volSphericalTensorField> vsptf(objNames.size());
        PtrList<volSymmTensorField> vsytf(objNames.size());
        PtrList<volTensorField> vtf(objNames.size());

        Info<< "Valid fields:" << endl;

        forAll(objNames, objI)
        {
            IOobject obj
            (
                objNames[objI],
                runTime.timeName(),
                mesh,
                IOobject::MUST_READ
            );

            if (obj.headerOk())
            {
                addToFieldList<scalar>(vsf, obj, objI, mesh);
                addToFieldList<vector>(vvf, obj, objI, mesh);
                addToFieldList<sphericalTensor>(vsptf, obj, objI, mesh);
                addToFieldList<symmTensor>(vsytf, obj, objI, mesh);
                addToFieldList<tensor>(vtf, obj, objI, mesh);
            }
        }
예제 #4
0
파일: vo_fbdev.c 프로젝트: HermiG/mplayer2
static int config(uint32_t width, uint32_t height, uint32_t d_width,
                  uint32_t d_height, uint32_t flags, char *title,
                  uint32_t format)
{
    struct fb_cmap *cmap;
    int vm   = flags & VOFLAG_MODESWITCHING;

    fs = flags & VOFLAG_FULLSCREEN;

    if (pre_init_err == -2) {
        mp_msg(MSGT_VO, MSGL_ERR, "Internal fatal error: config() was called before preinit()\n");
        return -1;
    }

    if (pre_init_err)
        return 1;

    if (fb_mode_name && !vm) {
        mp_msg(MSGT_VO, MSGL_ERR, "-fbmode can only be used with -vm\n");
        return 1;
    }
    if (vm && parse_fbmode_cfg(fb_mode_cfgfile) < 0)
        return 1;
    if (d_width && (fs || vm)) {
        out_width  = d_width;
        out_height = d_height;
    } else {
        out_width  = width;
        out_height = height;
    }
    in_width     = width;
    in_height    = height;
    pixel_format = format;

    if (fb_mode_name) {
        if (!(fb_mode = find_mode_by_name(fb_mode_name))) {
            mp_msg(MSGT_VO, MSGL_ERR, "can't find requested video mode\n");
            return 1;
        }
        fb_mode2fb_vinfo(fb_mode, &fb_vinfo, fb_rgb);
    } else if (vm) {
        monitor_hfreq = str2range(monitor_hfreq_str);
        monitor_vfreq = str2range(monitor_vfreq_str);
        monitor_dotclock = str2range(monitor_dotclock_str);
        if (!monitor_hfreq || !monitor_vfreq || !monitor_dotclock) {
            mp_msg(MSGT_VO, MSGL_ERR, "you have to specify the capabilities of"
                   " the monitor.\n");
            return 1;
        }
        if (!(fb_mode = find_best_mode(out_width, out_height, monitor_hfreq,
                                       monitor_vfreq, monitor_dotclock))) {
            mp_msg(MSGT_VO, MSGL_ERR, "can't find best video mode\n");
            return 1;
        }
        mp_msg(MSGT_VO, MSGL_V, "using mode %dx%d @ %.1fHz\n", fb_mode->xres,
               fb_mode->yres, vsf(fb_mode));
        fb_mode2fb_vinfo(fb_mode, &fb_vinfo, fb_rgb);
    }
    fb_bpp_we_want = fb_bpp;
    set_bpp(&fb_vinfo, fb_bpp, fb_rgb);
    fb_vinfo.xres_virtual = fb_vinfo.xres;
    fb_vinfo.yres_virtual = fb_vinfo.yres;
    fb_page = 0;
    if (vo_doublebuffering) {
        fb_vinfo.yres_virtual <<= 1;
        fb_vinfo.yoffset = 0;
        fb_page = 1; // start writing into the page we don't display
    }

    if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_GRAPHICS) < 0) {
        mp_msg(MSGT_VO, MSGL_V, "Can't set graphics mode: %s\n", strerror(errno));
        close(fb_tty_fd);
        fb_tty_fd = -1;
    }

    if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo))
        // Intel drivers fail if we request a transparency channel
        fb_vinfo.transp.length = fb_vinfo.transp.offset = 0;
    if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) {
        mp_msg(MSGT_VO, MSGL_ERR, "Can't put VSCREENINFO: %s\n", strerror(errno));
        if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_TEXT) < 0) {
            mp_msg(MSGT_VO, MSGL_ERR, "Can't restore text mode: %s\n", strerror(errno));
        }
        return 1;
    }

    fb_pixel_size = fb_vinfo.bits_per_pixel / 8;
    fb_bpp = fb_vinfo.bits_per_pixel;
    if (fb_bpp == 16)
        fb_bpp = fb_vinfo.red.length  + fb_vinfo.green.length + fb_vinfo.blue.length;
    if (fb_bpp_we_want != fb_bpp)
        mp_msg(MSGT_VO, MSGL_WARN, "requested %d bpp, got %d bpp!!!\n",
               fb_bpp_we_want, fb_bpp);

    switch (fb_bpp) {
    case 32:
        draw_alpha_p = vo_draw_alpha_rgb32;
        break;
    case 24:
        draw_alpha_p = vo_draw_alpha_rgb24;
        break;
    case 16:
        draw_alpha_p = vo_draw_alpha_rgb16;
        break;
    case 15:
        draw_alpha_p = vo_draw_alpha_rgb15;
        break;
    case 12:
        draw_alpha_p = vo_draw_alpha_rgb12;
        break;
    default:
        return 1;
    }

    fb_xres = fb_vinfo.xres;
    fb_yres = fb_vinfo.yres;

    if (vm || fs) {
        out_width  = fb_xres;
        out_height = fb_yres;
    }
    if (out_width < in_width || out_height < in_height) {
        mp_msg(MSGT_VO, MSGL_ERR, "screensize is smaller than video size\n");
        return 1;
    }

    first_row = (out_height - in_height) / 2;
    last_row  = (out_height + in_height) / 2;

    if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) {
        mp_msg(MSGT_VO, MSGL_ERR, "Can't get FSCREENINFO: %s\n", strerror(errno));
        return 1;
    }

    if (fb_finfo.type != FB_TYPE_PACKED_PIXELS) {
        mp_msg(MSGT_VO, MSGL_ERR, "type %d not supported\n", fb_finfo.type);
        return 1;
    }

    switch (fb_finfo.visual) {
    case FB_VISUAL_TRUECOLOR:
        break;
    case FB_VISUAL_DIRECTCOLOR:
        mp_msg(MSGT_VO, MSGL_V, "creating cmap for directcolor\n");
        if (ioctl(fb_dev_fd, FBIOGETCMAP, &fb_oldcmap)) {
            mp_msg(MSGT_VO, MSGL_ERR, "can't get cmap: %s\n",
                    strerror(errno));
            return 1;
        }
        if (!(cmap = make_directcolor_cmap(&fb_vinfo)))
            return 1;
        if (ioctl(fb_dev_fd, FBIOPUTCMAP, cmap)) {
            mp_msg(MSGT_VO, MSGL_ERR, "can't put cmap: %s\n",
                   strerror(errno));
            return 1;
        }
        fb_cmap_changed = 1;
        free(cmap->red);
        free(cmap->green);
        free(cmap->blue);
        free(cmap);
        break;
    default:
        mp_msg(MSGT_VO, MSGL_ERR, "visual: %d not yet supported\n",
               fb_finfo.visual);
        return 1;
    }

    fb_line_len = fb_finfo.line_length;
    fb_size     = fb_finfo.smem_len;
    if (vo_doublebuffering && fb_size < 2 * fb_yres * fb_line_len)
    {
        mp_msg(MSGT_VO, MSGL_WARN, "framebuffer too small for double-buffering, disabling\n");
        vo_doublebuffering = 0;
        fb_page = 0;
    }

    {
        int x_offset = 0, y_offset = 0;
        geometry(&x_offset, &y_offset, &out_width, &out_height, fb_xres, fb_yres);

        frame_buffer = mmap(0, fb_size, PROT_READ | PROT_WRITE,
                            MAP_SHARED, fb_dev_fd, 0);
        if (frame_buffer == (uint8_t *) -1) {
            mp_msg(MSGT_VO, MSGL_ERR, "Can't mmap %s: %s\n", fb_dev_name, strerror(errno));
            return 1;
        }

        center = frame_buffer +
                 ( (out_width  - in_width)  / 2 ) * fb_pixel_size +
                 ( (out_height - in_height) / 2 ) * fb_line_len +
                 x_offset * fb_pixel_size + y_offset * fb_line_len +
                 fb_page * fb_yres * fb_line_len;

        mp_msg(MSGT_VO, MSGL_DBG2, "frame_buffer @ %p\n", frame_buffer);
        mp_msg(MSGT_VO, MSGL_DBG2, "center @ %p\n", center);
        mp_msg(MSGT_VO, MSGL_V, "pixel per line: %d\n", fb_line_len / fb_pixel_size);

        if (fs || vm) {
            int clear_size = fb_line_len * fb_yres;
            if (vo_doublebuffering)
                clear_size <<= 1;
            memset(frame_buffer, 0, clear_size);
        }
    }

    vt_set_textarea(last_row, fb_yres);

    return 0;
}
예제 #5
0
static int config(uint32_t width, uint32_t height, uint32_t d_width,
		uint32_t d_height, uint32_t flags, char *title,
		uint32_t format)
{
	struct fb_cmap *cmap;
	int vm = flags & VOFLAG_MODESWITCHING;
	int zoom = flags & VOFLAG_SWSCALE;
	int vt_fd;

	fs = flags & VOFLAG_FULLSCREEN;

	if(pre_init_err == -2)
	{
	    mp_msg(MSGT_VO, MSGL_ERR, "Internal fatal error: config() was called before preinit()\n");
	    return -1;
	}

	if (pre_init_err) return 1;

	if (fb_mode_name && !vm) {
		mp_msg(MSGT_VO, MSGL_ERR, "-fbmode can only be used with -vm\n");
		return 1;
	}
	if (vm && (parse_fbmode_cfg(fb_mode_cfgfile) < 0))
			return 1;
	if (d_width && (fs || vm)) {
		out_width = d_width;
		out_height = d_height;
	} else {
		out_width = width;
		out_height = height;
	}
	in_width = width;
	in_height = height;
	pixel_format = format;

	if (fb_mode_name) {
		if (!(fb_mode = find_mode_by_name(fb_mode_name))) {
			mp_msg(MSGT_VO, MSGL_ERR, "can't find requested video mode\n");
			return 1;
		}
		fb_mode2fb_vinfo(fb_mode, &fb_vinfo);
	} else if (vm) {
		monitor_hfreq = str2range(monitor_hfreq_str);
		monitor_vfreq = str2range(monitor_vfreq_str);
		monitor_dotclock = str2range(monitor_dotclock_str);
		if (!monitor_hfreq || !monitor_vfreq || !monitor_dotclock) {
			mp_msg(MSGT_VO, MSGL_ERR, "you have to specify the capabilities of"
					" the monitor.\n");
			return 1;
		}
		if (!(fb_mode = find_best_mode(out_width, out_height,
					monitor_hfreq, monitor_vfreq,
					monitor_dotclock))) {
			mp_msg(MSGT_VO, MSGL_ERR, "can't find best video mode\n");
			return 1;
		}
		mp_msg(MSGT_VO, MSGL_V, "using mode %dx%d @ %.1fHz\n", fb_mode->xres,
				fb_mode->yres, vsf(fb_mode));
		fb_mode2fb_vinfo(fb_mode, &fb_vinfo);
	}
	fb_bpp_we_want = fb_bpp;
	set_bpp(&fb_vinfo, fb_bpp);
	fb_vinfo.xres_virtual = fb_vinfo.xres;
	fb_vinfo.yres_virtual = fb_vinfo.yres;

        if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_GRAPHICS) < 0) {
                mp_msg(MSGT_VO, MSGL_V, "Can't set graphics mode: %s\n", strerror(errno));
                close(fb_tty_fd);
                fb_tty_fd = -1;
        }

	if (ioctl(fb_dev_fd, FBIOPUT_VSCREENINFO, &fb_vinfo)) {
		mp_msg(MSGT_VO, MSGL_ERR, "Can't put VSCREENINFO: %s\n", strerror(errno));
                if (fb_tty_fd >= 0 && ioctl(fb_tty_fd, KDSETMODE, KD_TEXT) < 0) {
                        mp_msg(MSGT_VO, MSGL_ERR, "Can't restore text mode: %s\n", strerror(errno));
                }
		return 1;
	}

	fb_pixel_size = fb_vinfo.bits_per_pixel / 8;
	fb_bpp = fb_vinfo.red.length + fb_vinfo.green.length +
		fb_vinfo.blue.length + fb_vinfo.transp.length;
	if (fb_bpp_we_want != fb_bpp)
		mp_msg(MSGT_VO, MSGL_WARN, "requested %d bpp, got %d bpp!!!\n",
				fb_bpp_we_want, fb_bpp);

	switch (fb_bpp) {
		case 32: draw_alpha_p = vo_draw_alpha_rgb32; break;
		case 24: draw_alpha_p = vo_draw_alpha_rgb24; break;
		case 16: draw_alpha_p = vo_draw_alpha_rgb16; break;
		case 15: draw_alpha_p = vo_draw_alpha_rgb15; break;
		default: return 1;
	}

	fb_xres = fb_vinfo.xres;
	fb_yres = fb_vinfo.yres;

	if (vm || fs) {
		out_width = fb_xres;
		out_height = fb_yres;
	}
	if (out_width < in_width || out_height < in_height) {
		mp_msg(MSGT_VO, MSGL_ERR, "screensize is smaller than video size\n");
		return 1;
	}

	first_row = (out_height - in_height) / 2;
	last_row = (out_height + in_height) / 2;

	if (ioctl(fb_dev_fd, FBIOGET_FSCREENINFO, &fb_finfo)) {
		mp_msg(MSGT_VO, MSGL_ERR, "Can't get FSCREENINFO: %s\n", strerror(errno));
		return 1;
	}

	lots_of_printf();

	if (fb_finfo.type != FB_TYPE_PACKED_PIXELS) {
		mp_msg(MSGT_VO, MSGL_ERR, "type %d not supported\n", fb_finfo.type);
		return 1;
	}

	switch (fb_finfo.visual) {
		case FB_VISUAL_TRUECOLOR:
			break;
		case FB_VISUAL_DIRECTCOLOR:
			mp_msg(MSGT_VO, MSGL_V, "creating cmap for directcolor\n");
			if (ioctl(fb_dev_fd, FBIOGETCMAP, &fb_oldcmap)) {
				mp_msg(MSGT_VO, MSGL_ERR, "can't get cmap: %s\n",
						strerror(errno));
				return 1;
			}
			if (!(cmap = make_directcolor_cmap(&fb_vinfo)))
				return 1;
			if (ioctl(fb_dev_fd, FBIOPUTCMAP, cmap)) {
				mp_msg(MSGT_VO, MSGL_ERR, "can't put cmap: %s\n",
						strerror(errno));
				return 1;
			}
			fb_cmap_changed = 1;
			free(cmap->red);
			free(cmap->green);
			free(cmap->blue);
			free(cmap);
			break;
		default:
			mp_msg(MSGT_VO, MSGL_ERR, "visual: %d not yet supported\n",
					fb_finfo.visual);
			return 1;
	}

	fb_line_len = fb_finfo.line_length;
	fb_size = fb_finfo.smem_len;
	frame_buffer = NULL;
#ifdef CONFIG_VIDIX
	if(vidix_name)
	{
	    unsigned image_width,image_height,x_offset,y_offset;
	    if(zoom || fs){
		aspect_save_orig(width,height);
		aspect_save_prescale(d_width,d_height);
		aspect_save_screenres(fb_xres,fb_yres);
		aspect(&image_width,&image_height,fs ? A_ZOOM : A_NOZOOM);
	    } else {
		image_width=width;
		image_height=height;
	    }

		if(fb_xres > image_width)
		    x_offset = (fb_xres - image_width) / 2;
		else x_offset = 0;
		if(fb_yres > image_height)
		    y_offset = (fb_yres - image_height) / 2;
		else y_offset = 0;

		if(vidix_init(width,height,x_offset,y_offset,image_width,
			    image_height,format,fb_bpp,
			    fb_xres,fb_yres) != 0)
		{
		    mp_msg(MSGT_VO, MSGL_ERR, "Can't initialize VIDIX driver\n");
		    vidix_name = NULL;
		    vidix_term();
		    return -1;
		}
		else mp_msg(MSGT_VO, MSGL_V, "Using VIDIX\n");
		vidix_start();
		if (vidix_grkey_support())
		{
		    vidix_grkey_get(&gr_key);
		    gr_key.key_op = KEYS_PUT;
		    if (!(vo_colorkey & 0xff000000))
		    {
			gr_key.ckey.op = CKEY_TRUE;
			gr_key.ckey.red = (vo_colorkey & 0x00ff0000) >> 16;
			gr_key.ckey.green = (vo_colorkey & 0x0000ff00) >> 8;
			gr_key.ckey.blue = vo_colorkey & 0x000000ff;
		    }
		    else
			gr_key.ckey.op = CKEY_FALSE;
		    vidix_grkey_set(&gr_key);
		}
/**
 * \brief Construct a camera from a USB Device
 *
 * The constructor undertakes an extensive analysis of the descriptors
 * to find the video control and video streaming interfaces of the video
 * function of the device. It also makes sure no kernel driver is attached
 * to the device. It does not, however, claim any of the interfaces, this
 * is done when the device is really used.
 * \param _device	an USB device to open as a UVC camera
 * \param force		force opening as camera even if the
 *			interface associaten descriptor does not
 *			declare itself as a video interface association
 *                      descriptor (handles the TIS camera)
 * XXX apparently the force parameter is never used, so the question should be
 *     asked whether we can remove it.
 */
UVCCamera::UVCCamera(Device& _device, bool /* force */) throw(USBError)
	: device(_device) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "create a UVC camera object");

	// make sure the camera is open, this most probably will not have
	// any effect
	device.open();

	// scan the active configuration for one that has an Interface
	// association descriptor
	ConfigurationPtr config = device.activeConfig();
	if (config->extra().size() == 0) {
		debug(LOG_ERR, DEBUG_LOG, 0, "no extra descriptors");
		throw USBError("no InterfaceAssociationDescriptor");
	}

	// get the list of interface association descriptors
	std::list<USBDescriptorPtr>	iadlist
		= device.interfaceAssociationDescriptors(true);
	if (0 == iadlist.size()) {
		throw USBError("no Video Interface Association found");
	}
	iadptr = *iadlist.begin();
	debug(LOG_DEBUG, DEBUG_LOG, 0, "Video Interface Association found");

	// get the control interface, and the list of interface descriptors
	// for the control interface, and claim it
	uint8_t	ci = controlInterfaceNumber();
	videocontrol = (*config)[ci];
	debug(LOG_DEBUG, DEBUG_LOG, 0, "Control interface number: %d", ci);
	videocontrol->detachKernelDriver();

	// we also need to know all the video control descriptors appended
	// to this InterfaceDescriptor. The VideoControlDescriptorFactory
	// does that.
	debug(LOG_DEBUG, DEBUG_LOG, 0, "parse the video control descriptors");
	InterfaceDescriptorPtr	controlinterface = (*videocontrol)[0];
	VideoControlDescriptorFactory	vcdf(device);
	videocontroldescriptors = vcdf.descriptors(controlinterface->extra());
	std::cout << videocontroldescriptors[0];
	
	// now claim get the various interface descriptors, i.e. the
	// alternate settings for an interface
	int	interfacecount = iad().bInterfaceCount();
	debug(LOG_DEBUG, DEBUG_LOG, 0, "interfaces in association: %d",
		interfacecount);

	// now parse the video streaming interfaces
	debug(LOG_DEBUG, DEBUG_LOG, 0, "parse streaming interface descriptors");
	VideoStreamingDescriptorFactory	vsf(device);
	for (int vsif = controlInterfaceNumber() + 1;
		vsif < controlInterfaceNumber() + iad().bInterfaceCount();
		vsif++) {
		debug(LOG_DEBUG, DEBUG_LOG, 0,
			"analyzing video streaming interface %d", vsif);
		InterfacePtr	interface = (*config)[vsif];
		// only alternate setting 0 contains the formats
		InterfaceDescriptorPtr	id = (*interface)[0];
		std::string	extra = id->extra();
		debug(LOG_DEBUG, DEBUG_LOG, 0, "extra descriptors: %d bytes",
			extra.size());
		USBDescriptorPtr	vsd = vsf.descriptor(extra);
		debug(LOG_DEBUG, DEBUG_LOG, 0, "parse complete");
		videostreaming.push_back(vsd);
	}
	debug(LOG_DEBUG, DEBUG_LOG, 0, "UVCCamera constructed");
}