Example #1
0
//--------------------------------------------------------------------
// 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" );
	   }
	}
}
Example #2
0
//--------------------------------------------------------------------
// 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");
		}
	}
}