//-------------------------------------------------------------------- // If a 24 bit video format is founded this is the preferred one, if not, the first // returned by unicap is selected. // // Then it tries to set the desired width and height, if these fails, tries find the // nearest size or to set the default width and height. // // On V4L devices 24 bit format is always BGR, so it needs conversion. // On some V4L devices using non-default width/heigth it reports BGR but returns RGB. // ffmpeg color conversion void ofUCUtils::set_format(int w, int h) { if(!deviceReady) return; d_width=w; d_height=h; unicap_format_t formats[MAX_FORMATS]; int format_count; unicap_status_t status = STATUS_SUCCESS; int rgb24 = -1; ofLog(OF_NOTICE,"ofUCUtils : Available formats for this device:"); for (format_count = 0; SUCCESS (status) && (format_count < MAX_FORMATS); format_count++) { status = unicap_enumerate_formats (handle, NULL, &formats[format_count], format_count); if (SUCCESS (status)) { if (formats[format_count].bpp == 24) { rgb24 = format_count; } ofLog(OF_NOTICE, "ofUCUtils : %d: %s, min size: %dx%d, max size:%dx%d, default size: %dx%d", format_count, formats[format_count].identifier, formats[format_count].min_size.width, formats[format_count].min_size.height, formats[format_count].max_size.width, formats[format_count].max_size.height, formats[format_count].size.width, formats[format_count].size.height); ofLog(OF_VERBOSE,"ofUCUtils: available sizes for this format:"); for(int i=0; i<formats[format_count].size_count;i++){ ofLog(OF_VERBOSE," %dx%d",formats[format_count].sizes[i].width,formats[format_count].sizes[i].height); } } } if (format_count > 0) { int selected_format = 0; if (rgb24 != -1) selected_format = rgb24; else{ for(selected_format=0;selected_format<format_count;selected_format++){ format = formats[selected_format]; if(fourcc_to_pix_fmt(format.fourcc)!=-1) break; } } format = formats[selected_format]; bool exactMatch = false; int sizeDiff = 99999999; int mostAproxSize = -1; for(int i=0; i<format.size_count;i++){ if(format.sizes[i].width == w && format.sizes[i].height==h){ exactMatch=true; format.size.width = format.sizes[i].width; format.size.height = format.sizes[i].height; break; }else{ if(abs(format.sizes[i].width-w)+abs(format.sizes[i].height-h)<sizeDiff){ sizeDiff=abs(format.sizes[i].width-w)+abs(format.sizes[i].height-h); mostAproxSize=i; } } } if(!exactMatch && mostAproxSize!=-1){ format.size.width = format.sizes[mostAproxSize].width; format.size.height = format.sizes[mostAproxSize].height; ofLog(OF_WARNING, "ofUCUtils : Can't set video format %s, with size %dx%d, will use %dx%d", format.identifier, w, h, format.size.width, format.size.height); }else if(format.size_count==0){ int defaultFormatWidth = format.size.width; int defaultFormatHeight = format.size.height; format.size.width = w; format.size.height = h; ofLog(OF_WARNING, "ofUCUtils : Can't recognize supported video sizes for %s, trying with requested size: %i,%i", format.identifier, format.size.width, format.size.height); if ( !SUCCESS ( unicap_set_format (handle, &format) ) ) { format.size.width = defaultFormatWidth; format.size.height = defaultFormatHeight; ofLog(OF_WARNING, "ofUCUtils : Can't set requested size, trying with format defaults: %i,%i", defaultFormatWidth, defaultFormatHeight); } ofLog(OF_WARNING, "ofUCUtils : If this doesn't work try using the reported default size in initGrabber:", defaultFormatWidth, defaultFormatHeight); } if ( !SUCCESS ( unicap_set_format (handle, &format) ) ) { ofLog(OF_ERROR, "ofUCUtils : Failed to set alternative video format!"); return; } ofLog(OF_NOTICE,"ofUCUtils : Selected format: %s, with size %dx%d\n", format.identifier, format.size.width, format.size.height); src_pix_fmt=fourcc_to_pix_fmt(format.fourcc); if( src_pix_fmt==-1){ ofLog(OF_ERROR,"ofUCUtils : Format not suported\n"); return; } if(src_pix_fmt!=PIX_FMT_RGB24 || !exactMatch){ src=new AVPicture; avpicture_alloc(src,src_pix_fmt,format.size.width,format.size.height); dst=new AVPicture; avpicture_alloc(dst,PIX_FMT_RGB24,d_width,d_height); toRGB_convert_ctx = sws_getContext( format.size.width, format.size.height, src_pix_fmt, d_width, d_height, PIX_FMT_RGB24, VIDEOGRABBER_RESIZE_FLAGS, NULL, NULL, NULL); ofLog(OF_NOTICE,"ofUCUtils: Converting to RGB24 (%i,%i)\n",w,h); pixels=new unsigned char[d_width*d_height*3]; } if( !SUCCESS( unicap_get_format( handle, &format ) ) ) { ofLog(OF_ERROR, "can't get format" ); return; } format.buffer_type = UNICAP_BUFFER_TYPE_SYSTEM; if( !SUCCESS( unicap_set_format( handle, &format ) ) ) { ofLog(OF_WARNING, "ofUCUtils: Failed to activate SYSTEM_BUFFERS" ); } } }
//-------------------------------------------------------------------- // If a 24 bit video format is founded this is the preferred one, if not, the first // returned by unicap is selected. // // Then it tries to set the desired width and height, if these fails, tries find the // nearest size or to set the default width and height. // // On V4L devices 24 bit format is always BGR, so it needs conversion. // On some V4L devices using non-default width/heigth it reports BGR but returns RGB. // ffmpeg color conversion void ofUCUtils::set_format(int w, int h) { unicap_format_t formats[MAX_FORMATS]; int format_count; unicap_status_t status = STATUS_SUCCESS; int rgb24 = -1; if(verbose) printf("Unicap : Available formats for this device:\n"); for (format_count = 0; SUCCESS (status) && (format_count < MAX_FORMATS); format_count++) { status = unicap_enumerate_formats (handle, NULL, &formats[format_count], format_count); if (SUCCESS (status)) { if (formats[format_count].bpp == 8) { rgb24 = format_count; } if(verbose) printf ( "Unicap : %d: %s, min size: %dx%d, max size:%dx%d, default size: %dx%d\n", format_count, formats[format_count].identifier, formats[format_count].min_size.width, formats[format_count].min_size.height, formats[format_count].max_size.width, formats[format_count].max_size.height, formats[format_count].size.width, formats[format_count].size.height); } } if (format_count > 0) { int selected_format = 0; if (rgb24 != -1) selected_format = rgb24; format = formats[selected_format]; bool sizeFounded = true; bool exactMatch = false; if(w == format.size.width && h == format.size.height){ exactMatch = true; }else if(w <= format.min_size.width && h <= format.min_size.height){ format.size.width = format.min_size.width; format.size.height = format.min_size.height; }else if(w >= format.max_size.width && h >= format.max_size.height){ format.size.width = format.max_size.width; format.size.height = format.max_size.height; }else{ sizeFounded=false; } if(sizeFounded){ if(verbose && !exactMatch) printf ("Unicap : Can't set video format %s, with size %dx%d\n", format.identifier, w, h); if ( !SUCCESS ( unicap_set_format (handle, &format) ) ) { printf ("Unicap : Failed to set alternative video format!\n"); return; } }else{ format.size.width = w; format.size.height = h; //Try selected size if (!SUCCESS (unicap_set_format (handle, &format))) { printf ("Unicap : Can't set video format %s, with size %dx%d\n", format.identifier, w, h); // If selected size doesn't work try to find a supported one unicap_format_t format_spec; unicap_void_format(&format_spec); int nearW = 9999999; int nearH = 9999999; //Try with unicap reported sizes if(format.size_count > 0){ if(verbose)printf ("Unicap : Available sizes: %d\n",format.size_count); for(int i = 0; i < format.size_count; i++){ if(verbose) printf ("%d,%d\n",format.sizes[i].width,format.sizes[i].height); if(abs(w-format.sizes[i].width)<abs(w-nearW)){ nearW = format.sizes[i].width; nearH = format.sizes[i].height; } } format.size.width = nearW; format.size.height = nearH; //Try with stepping }else if(format.h_stepping > 1 || format.v_stepping > 1){ //This is how many diff sizes are available for the format int stepX = format.h_stepping; int stepY = format.v_stepping; for(int x = format.min_size.x; x <= format.max_size.x; x+= stepX) { if( abs(w-x) < abs(w-nearW) ){ nearW = x; } } for(int y = format.min_size.y; y <= format.max_size.y; y+= stepY) { if( abs(h-y) < abs(h-nearH) ){ nearH = y; } } format.size.width = nearW; format.size.height = nearH; } //Try to set founded size sizeFounded = SUCCESS ( unicap_set_format (handle, &format) ); //If none of the above work, try default size if(!sizeFounded){ if ( !SUCCESS( unicap_enumerate_formats( handle, &format_spec, &format, selected_format ) ) ) { printf("Unicap : Failed to get alternative video format\n"); return; } if ( !SUCCESS ( unicap_set_format (handle, &format) ) ) { printf ("Unicap : Failed to set alternative video format!\n"); return; } } } } if(verbose) printf("Unicap : Selected format: %s, with size %dx%d\n", format.identifier, format.size.width, format.size.height); src_pix_fmt=fourcc_to_pix_fmt(format.fourcc); if( src_pix_fmt==-1){ printf("Unicap : Format not suported\n"); return; } if(src_pix_fmt!=PIX_FMT_RGB24){ src=new AVPicture; avpicture_alloc(src,src_pix_fmt,format.size.width,format.size.height); dst=new AVPicture; avpicture_alloc(dst,PIX_FMT_RGB24,format.size.width,format.size.height); printf("Converting to RGB24"); } } }