framework2

Форк
0
860 строк · 31.6 Кб
1
/*
2
 * ofGstVideoGrabber.cpp
3
 *
4
 *  Created on: 17/01/2011
5
 *      Author: arturo
6
 */
7

8
#include "ofGstVideoGrabber.h"
9
#include "ofPixels.h"
10

11
#include <gst/video/video.h>
12

13
#ifdef TARGET_LINUX
14
#include <sys/utsname.h>
15
#endif
16

17
//-------------------------------------------------
18
//----------------------------------------- grabber
19
//-------------------------------------------------
20

21
#ifdef TARGET_LINUX
22

23
#define PREFER_RGB_OVER_YUV
24
#define PREFER_NON_COMPRESSED
25

26
extern "C" {
27
	#include <libudev.h>
28
}
29

30
#include <gst/gst.h>
31

32
/* for ioctl query */
33
#include <fcntl.h>
34
#include <unistd.h>
35
#include <sys/ioctl.h>
36

37
#include <linux/version.h>
38

39
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
40
	#include <linux/videodev2.h>
41
	#define VIDIOCGCAP              _IOR('v',1,struct video_capability)     /* Get capabilities */
42

43
	struct video_capability
44
	{
45
			 char name[32];
46
			 int type;
47
			 int channels;   /* Num channels */
48
			 int audios;     /* Num audio devices */
49
			 int maxwidth;   /* Supported width */
50
			 int maxheight;  /* And height */
51
			 int minwidth;   /* Supported width */
52
			 int minheight;  /* And height */
53
	};
54
#else
55
	#include <linux/videodev.h>
56
#endif
57

58

59
#endif
60

61
using std::string;
62
using std::vector;
63

64
static void get_video_devices (ofGstCamData & cam_data)
65
{
66
#ifdef TARGET_LINUX
67
	int fd, ok;
68

69
	struct udev * my_udev;
70
	struct udev_enumerate * enumerate;
71
	struct udev_list_entry * list;
72
	struct udev_list_entry * entry;
73

74
	my_udev = udev_new();
75
	enumerate = udev_enumerate_new(my_udev);
76
	udev_enumerate_scan_devices(enumerate);
77
	list = udev_enumerate_get_list_entry(enumerate);
78

79
	/*udev_list_entry_foreach(entry,list){
80
		const char * name = udev_list_entry_get_name(entry);
81
		struct udev_device * device = udev_device_new_from_syspath(my_udev, name);
82
		const char * subsystem = udev_device_get_subsystem(device);
83
		if(strcmp(subsystem,"video4linux")==0){
84
			num_devices++;
85
		}
86
	}*/
87

88
	ofLogNotice("ofGstVideoGrabber") << "Probing devices with udev...";
89

90
	/* Initialize webcam structures */
91
	udev_list_entry_foreach(entry,list){
92
		const char * name = udev_list_entry_get_name(entry);
93
		struct udev_device * device = udev_device_new_from_syspath(my_udev, name);
94
		string subsystem = udev_device_get_subsystem(device);
95

96
		if(subsystem != "video4linux") continue;
97
		const char  *gstreamer_src, *product_name;
98
		struct v4l2_capability  v2cap;
99
		struct video_capability v1cap;
100
		string vendor_id;
101
		string product_id;
102
		string serial_id;
103

104
		const char * dev_node = udev_device_get_devnode(device);
105
		struct udev_list_entry * properties = udev_device_get_properties_list_entry(device);
106
		struct udev_list_entry * property;
107
		udev_list_entry_foreach(property,properties){
108
			const char * name = udev_list_entry_get_name(property);
109

110
			if(strcmp(name,"ID_VENDOR_ID")==0){
111
				vendor_id = udev_list_entry_get_value(property);
112
			}
113

114
			if(strcmp(name,"ID_MODEL_ID")==0){
115
				product_id = udev_list_entry_get_value(property);
116
			}
117

118
			if(strcmp(name,"ID_SERIAL")==0){
119
				serial_id = udev_list_entry_get_value(property);;
120
			}
121

122
		}
123

124

125
		ofLogNotice("ofGstVideoGrabber") << "Found device " << vendor_id << ":" << product_id << ", getting capabilities...";
126

127
		/* vbi devices support capture capability too, but cannot be used,
128
		 * so detect them by device name */
129
		if (strstr (dev_node, "vbi"))
130
		{
131
			ofLogWarning("ofGstVideoGrabber") <<  "Skipping vbi device: " << dev_node;
132
			continue;
133
		}
134

135

136
		if ((fd = open (dev_node, O_RDONLY | O_NONBLOCK)) < 0)
137
		{
138
			ofLogWarning("ofGstVideoGrabber") << "Failed to open " << dev_node << " " << strerror (errno);
139
			continue;
140
		}
141

142
		ok = ioctl (fd, VIDIOC_QUERYCAP, &v2cap);
143
		if (ok < 0)
144
		{
145
			ok = ioctl (fd, VIDIOCGCAP, &v1cap);
146
			if (ok < 0)
147
			{
148
				ofLogWarning("ofGstVideoGrabber") << "Error while probing v4l capabilities for "
149
						<< dev_node << " " << strerror (errno);
150
				close (fd);
151
				continue;
152
			}
153
			ofLogNotice("ofGstVideoGrabber") << "Detected v4l device: " << v1cap.name;
154
			ofLogNotice("ofGstVideoGrabber") << "device type: " << v1cap.type;
155
			gstreamer_src = "v4lsrc";
156
			product_name  = v1cap.name;
157
		}
158
		else
159
		{
160
			guint cap = v2cap.capabilities;
161
			ofLogNotice("ofGstVideoGrabber") << "detected v4l2 device: " << v2cap.card;
162
			ofLogNotice("ofGstVideoGrabber") << "driver: " << v2cap.driver << ", version: " << v2cap.version;
163
			/* g_print ("Bus info: %s\n", v2cap.bus_info); */ /* Doesn't seem anything useful */
164
			ofLogNotice("ofGstVideoGrabber","Capabilities: 0x%08X", v2cap.capabilities);
165
			/* Only consider this device, if
166
			 * 1. it has 'Video Capture' capability and
167
			 * 2. if it also has the 'Device Capabilities' then the actual device has
168
			 *    the 'Video Capture' capability too */
169
			if (!(cap & V4L2_CAP_VIDEO_CAPTURE)
170
			    || (cap & V4L2_CAP_DEVICE_CAPS && !(v2cap.device_caps & V4L2_CAP_VIDEO_CAPTURE))){
171
				ofLogNotice() << "device " << dev_node
172
				    << " seems to not have the capture capability, (radio tuner/metadata device?)";
173
				ofLogNotice() << "removing it from device list";
174
				close (fd);
175
				continue;
176
			}
177
			gstreamer_src = "v4l2src";
178
			product_name  = (char *) v2cap.card;
179
		}
180

181

182
		ofGstDevice gst_device;
183
		gst_device.video_device = dev_node;
184
		gst_device.gstreamer_src = gstreamer_src;
185
		gst_device.product_name = product_name;
186
		gst_device.serial_id = serial_id;
187
		cam_data.webcam_devices.push_back(gst_device);
188
		/*cam_data.webcam_devices[cam_data.num_webcam_devices].video_device      = dev_node;
189
		cam_data.webcam_devices[cam_data.num_webcam_devices].gstreamer_src     = gstreamer_src;
190
		cam_data.webcam_devices[cam_data.num_webcam_devices].product_name      = product_name;
191
		cam_data.webcam_devices[cam_data.num_webcam_devices].num_video_formats = 0;
192
		cam_data.webcam_devices[cam_data.num_webcam_devices].supported_resolutions =
193
		  g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
194
		cam_data.num_webcam_devices++;*/
195

196
		close (fd);
197
	}
198

199
	cam_data.bInited=true;
200
#endif
201
}
202

203

204
static void get_supported_framerates (ofGstVideoFormat &video_format, GstStructure &structure)
205
{
206
	const GValue *framerates;
207
	ofGstFramerate framerate;
208
	framerates = gst_structure_get_value (&structure, "framerate");
209
	if (GST_VALUE_HOLDS_FRACTION (framerates)){
210
		framerate.numerator   = gst_value_get_fraction_numerator (framerates);
211
		framerate.denominator = gst_value_get_fraction_denominator (framerates);
212
		video_format.framerates.push_back(framerate);
213
		ofLog(OF_LOG_VERBOSE,"%d/%d ", framerate.numerator,
214
						framerate.denominator);
215
	}else if (GST_VALUE_HOLDS_LIST (framerates)){
216
		int num_framerates = gst_value_list_get_size (framerates);
217
		for (int i = 0; i < num_framerates; i++){
218
			const GValue *value = gst_value_list_get_value (framerates, i);
219
			framerate.numerator   = gst_value_get_fraction_numerator (value);
220
			framerate.denominator = gst_value_get_fraction_denominator (value);
221
			video_format.framerates.push_back(framerate);
222
			ofLog(OF_LOG_VERBOSE,"%d/%d ", framerate.numerator,
223
							framerate.denominator);
224
		}
225
	}else if (GST_VALUE_HOLDS_FRACTION_RANGE (framerates)){
226
		int           numerator_min, denominator_min, numerator_max, denominator_max;
227
		const GValue *fraction_range_min;
228
		const GValue *fraction_range_max;
229

230
		fraction_range_min = gst_value_get_fraction_range_min (framerates);
231
		numerator_min      = gst_value_get_fraction_numerator (fraction_range_min);
232
		denominator_min    = gst_value_get_fraction_denominator (fraction_range_min);
233

234
		fraction_range_max = gst_value_get_fraction_range_max (framerates);
235
		numerator_max      = gst_value_get_fraction_numerator (fraction_range_max);
236
		denominator_max    = gst_value_get_fraction_denominator (fraction_range_max);
237

238
		ofLogVerbose("ofGstVideoGrabber") << "get_supported_framerates(): from "
239
				<< numerator_min << "/" << denominator_max
240
				<< " to " << numerator_max << "/" << denominator_min;
241
        if(denominator_max==1 && numerator_max>1000000){
242
            // workaround for #4647 where some camera seems to
243
            // return a really high value for num_max crashing the app
244
            numerator_max = 1000;
245
        }
246
        for (int i = numerator_min; i <= numerator_max; i++){
247
            for (int j = denominator_min; j <= denominator_max; j++){
248
				framerate.numerator = i;
249
				framerate.denominator = j;
250
				video_format.framerates.push_back(framerate);
251
			}
252
		}
253
	}else{
254
		ofLogVerbose("ofGstVideoGrabber") << "get_supported_framerates(): unknown GValue type "
255
				<< G_VALUE_TYPE_NAME (framerates) << " for framerates";
256
	}
257
}
258

259
static void find_framerate (ofGstVideoFormat &format, int desired_framerate = -1)
260
{
261
	int framerate_numerator   = 1;
262
	int framerate_denominator = 1;
263
	float framerate = -1;
264
	float prevFramerate = -1;
265
	// find nearest to desired framerate
266
	if(desired_framerate!=-1){
267
		float diff = 9999;
268
		for(unsigned i=0; i<format.framerates.size(); i++){
269
			framerate = (float)format.framerates[i].numerator / (float)format.framerates[i].denominator;
270
			if( fabs((float)desired_framerate - framerate) < diff){
271
				diff = fabs((float)desired_framerate - framerate );
272
				framerate_numerator   = format.framerates[i].numerator;
273
				framerate_denominator = format.framerates[i].denominator;
274
			}
275
		}
276
	// find fastest
277
	}else{
278
		for (unsigned i = 0; i < format.framerates.size(); i++){
279
			prevFramerate = framerate;
280
			framerate = (float)format.framerates[i].numerator / (float)format.framerates[i].denominator;
281
			if (framerate > prevFramerate ){
282
				framerate_numerator   = format.framerates[i].numerator;
283
				framerate_denominator = format.framerates[i].denominator;
284
			}
285
		}
286
	}
287

288
	format.choosen_framerate.numerator = framerate_numerator;
289
	format.choosen_framerate.denominator = framerate_denominator;
290
}
291

292
static int find_resolution(ofGstDevice &webcam_device, int width, int height){
293
	for(unsigned i=0; i<webcam_device.video_formats.size(); i++){
294
		if(webcam_device.video_formats[i].width == width && webcam_device.video_formats[i].height== height)
295
			return i;
296
	}
297
	return -1;
298
}
299

300

301
#if GST_VERSION_MAJOR==0
302
static void add_video_format (ofGstDevice &webcam_device,
303
  ofGstVideoFormat &video_format, GstStructure &format_structure, int desired_framerate, ofPixelFormat desiredPixelFormat)
304
{
305

306
	ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): " << video_format.mimetype.c_str()
307
			<< " " << video_format.width << "x" << video_format.height << " framerates:";
308
	get_supported_framerates (video_format, format_structure);
309
	find_framerate (video_format, desired_framerate);
310

311
	int i = find_resolution(webcam_device,video_format.width, video_format.height);
312

313
	if (i!=-1) { // Resolution already added ?
314
		float new_framerate = (float)video_format.choosen_framerate.numerator /
315
								 video_format.choosen_framerate.denominator;
316
		float curr_framerate = (float)webcam_device.video_formats[i].choosen_framerate.numerator /
317
								webcam_device.video_formats[i].choosen_framerate.denominator;
318
		if (desired_framerate == -1){
319
			if(new_framerate > curr_framerate) {
320
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): higher framerate replacing existing format";
321
				webcam_device.video_formats[i] = video_format;
322
#ifdef PREFER_NON_COMPRESSED
323
			}else if(webcam_device.video_formats[i].mimetype != "video/x-raw-yuv"
324
					&& webcam_device.video_formats[i].mimetype != "video/x-raw-rgb"
325
					&& ( video_format.mimetype == "video/x-raw-yuv" || video_format.mimetype == "video/x-raw-rgb" )
326
					&& new_framerate == curr_framerate){
327
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): non compressed format with same framerate, replacing existing format";
328
				webcam_device.video_formats[i] = video_format;
329
#else
330
			}else if((webcam_device.video_formats[i].mimetype == "video/x-raw-yuv"
331
					|| webcam_device.video_formats[i].mimetype == "video/x-raw-rgb")
332
					&& ( video_format.mimetype != "video/x-raw-yuv" && video_format.mimetype != "video/x-raw-rgb" )
333
					&& new_framerate == curr_framerate){
334
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): non compressed format with same framerate, replacing existing format";
335
				webcam_device.video_formats[i] = video_format;
336
#endif
337

338
#ifdef PREFER_RGB_OVER_YUV
339
			}else if(webcam_device.video_formats[i].mimetype == "video/x-raw-yuv"
340
					&& video_format.mimetype == "video/x-raw-rgb"
341
					&& new_framerate == curr_framerate){
342
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): rgb format with same framerate as yuv, replacing existing format";
343
				webcam_device.video_formats[i] = video_format;
344
#else
345
			}else if(webcam_device.video_formats[i].mimetype == "video/x-raw-rgb"
346
					&& video_format.mimetype == "video/x-raw-yuv"
347
					&& new_framerate == curr_framerate){
348
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): rgb format with same framerate as yuv, replacing existing format";
349
				webcam_device.video_formats[i] = video_format;
350
#endif
351
			}else{
352
				ofLog(OF_LOG_VERBOSE,"already added, skipping\n");
353
			}
354
		}else{
355
			if(fabs(new_framerate - desired_framerate) < fabs(curr_framerate - desired_framerate) ){
356
				ofLog(OF_LOG_VERBOSE,"more similar framerate replacing existing format\n");
357
				webcam_device.video_formats[i] = video_format;
358
#ifdef PREFER_NON_COMPRESSED
359
			}else if(webcam_device.video_formats[i].mimetype != "video/x-raw-yuv"
360
					&& webcam_device.video_formats[i].mimetype != "video/x-raw-rgb"
361
					&& ( video_format.mimetype == "video/x-raw-yuv" || video_format.mimetype == "video/x-raw-rgb" )
362
					&& new_framerate == curr_framerate){
363
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): non compressed format with same framerate, replacing existing format";
364
				webcam_device.video_formats[i] = video_format;
365
#else
366
			}else if((webcam_device.video_formats[i].mimetype == "video/x-raw-yuv"
367
					|| webcam_device.video_formats[i].mimetype == "video/x-raw-rgb")
368
					&& ( video_format.mimetype != "video/x-raw-yuv" && video_format.mimetype != "video/x-raw-rgb" )
369
					&& new_framerate == curr_framerate){
370
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): non compressed format with same framerate, replacing existing format";
371
				webcam_device.video_formats[i] = video_format;
372
#endif
373
#ifdef PREFER_RGB_OVER_YUV
374
			}else if(webcam_device.video_formats[i].mimetype == "video/x-raw-yuv"
375
					&& video_format.mimetype == "video/x-raw-rgb"
376
					&& new_framerate == curr_framerate){
377
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): rgb format with same framerate as yuv, replacing existing format";
378
				webcam_device.video_formats[i] = video_format;
379
#else
380
			}else if(webcam_device.video_formats[i].mimetype == "video/x-raw-rgb"
381
					&& video_format.mimetype == "video/x-raw-yuv"
382
					&& new_framerate == curr_framerate){
383
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): rgb format with same framerate as yuv, replacing existing format";
384
				webcam_device.video_formats[i] = video_format;
385
#endif
386
			}else{
387
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): already added, skipping";
388
			}
389
		}
390

391
		return;
392
	}
393

394
	webcam_device.video_formats.push_back(video_format);
395
}
396
#else
397
static void add_video_format (ofGstDevice &webcam_device,
398
  ofGstVideoFormat &video_format, GstStructure &format_structure, int desired_framerate, ofPixelFormat desiredPixelFormat)
399
{
400

401
	ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): "
402
							<< video_format.mimetype << " " << video_format.format_name
403
							<< video_format.width << "x" << video_format.height << " "
404
							<< "videoformat: " << gst_video_format_from_string(video_format.format_name.c_str())
405
							<< " framerates: ";
406
	get_supported_framerates (video_format, format_structure);
407
	find_framerate (video_format, desired_framerate);
408

409
	int i = find_resolution(webcam_device,video_format.width, video_format.height);
410

411
	if (i!=-1) { // Resolution already added ?
412
		float new_framerate = (float)video_format.choosen_framerate.numerator /
413
								 video_format.choosen_framerate.denominator;
414
		float curr_framerate = (float)webcam_device.video_formats[i].choosen_framerate.numerator /
415
								webcam_device.video_formats[i].choosen_framerate.denominator;
416
		if (desired_framerate == -1){
417
			// choose faster
418
			if(new_framerate > curr_framerate) {
419
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): higher framerate replacing existing format";
420
				webcam_device.video_formats[i] = video_format;
421

422
			}
423
		}else{
424
			if(fabs(new_framerate - desired_framerate) < fabs(curr_framerate - desired_framerate) ){
425
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): more similar framerate replacing existing format";
426
				webcam_device.video_formats[i] = video_format;
427
			}else{
428
				ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): already added, skipping";
429
			}
430
		}
431

432
		// with same fps choose non_compressed over compressed
433
		if((gst_video_format_from_string(webcam_device.video_formats[i].format_name.c_str()) == GST_VIDEO_FORMAT_ENCODED
434
				|| gst_video_format_from_string(webcam_device.video_formats[i].format_name.c_str()) == GST_VIDEO_FORMAT_UNKNOWN)
435
				&& ( gst_video_format_from_string(video_format.format_name.c_str()) != GST_VIDEO_FORMAT_ENCODED )
436
				&& ( gst_video_format_from_string(video_format.format_name.c_str()) != GST_VIDEO_FORMAT_UNKNOWN )
437
				&& new_framerate == curr_framerate){
438
			ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): non compressed format with same framerate, replacing existing format";
439
			webcam_device.video_formats[i] = video_format;
440
		}
441

442
		// with same fps choose desiredPixelFormat over other formats to avoid colorspace compression
443
		else if(gst_video_format_from_string(webcam_device.video_formats[i].format_name.c_str()) != ofGstVideoUtils::getGstFormat(desiredPixelFormat)
444
				&& gst_video_format_from_string(video_format.format_name.c_str()) == ofGstVideoUtils::getGstFormat(desiredPixelFormat)
445
				&& new_framerate == curr_framerate){
446
			ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): " << webcam_device.video_formats[i].format_name << " format with same framerate as other format, replacing existing format";
447
			webcam_device.video_formats[i] = video_format;
448

449
		}
450

451
		else{
452
			ofLogVerbose("ofGstVideoGrabber") << "add_video_format(): already added, skipping";
453
		}
454

455
		return;
456
	}
457

458
	webcam_device.video_formats.push_back(video_format);
459
}
460
#endif
461

462
// TODO: gets formats for cameras, when a format returns a range it gets
463
// in steps /2 and *2 from min to max and max to min, for format7 it should be free to get any size
464
static void get_supported_video_formats (ofGstDevice &webcam_device, GstCaps &caps, int desired_framerate, ofPixelFormat desiredPixelFormat)
465
{
466

467
	int num_structures;
468

469
	num_structures = gst_caps_get_size (&caps);
470
	for (int i = 0; i < num_structures; i++){
471
		GstStructure *structure;
472
		const GValue *width, *height;
473
		structure = gst_caps_get_structure (&caps, i);
474

475
		width  = gst_structure_get_value (structure, "width");
476
		height = gst_structure_get_value (structure, "height");
477

478
		if (G_VALUE_HOLDS_INT (width)){
479
			ofGstVideoFormat video_format;
480

481
			video_format.mimetype = gst_structure_get_name (structure);
482
			gst_structure_get_int (structure, "width", &(video_format.width));
483
			gst_structure_get_int (structure, "height", &(video_format.height));
484
			#if GST_VERSION_MAJOR==1
485
			if(gst_structure_get_string(structure,"format"))
486
				video_format.format_name = gst_structure_get_string(structure,"format");
487
			#endif
488
			//cout << gst_structure_to_string(structure) << endl;;
489
			add_video_format(webcam_device, video_format, *structure, desired_framerate, desiredPixelFormat);
490
		}else if (GST_VALUE_HOLDS_INT_RANGE (width)){
491
			int min_width, max_width, min_height, max_height;
492
			int cur_width, cur_height;
493

494
			min_width  = gst_value_get_int_range_min (width);
495
			max_width  = gst_value_get_int_range_max (width);
496
			min_height = gst_value_get_int_range_min (height);
497
			max_height = gst_value_get_int_range_max (height);
498

499
			cur_width  = min_width;
500
			cur_height = min_height;
501
			while (cur_width <= max_width && cur_height <= max_height){
502
				ofGstVideoFormat video_format;
503

504
				video_format.mimetype = gst_structure_get_name (structure);
505
				video_format.width    = cur_width;
506
				video_format.height   = cur_height;
507
				#if GST_VERSION_MAJOR==1
508
				if(gst_structure_get_string(structure,"format"))
509
					video_format.format_name = gst_structure_get_string(structure,"format");
510
				#endif
511
				add_video_format(webcam_device, video_format, *structure, desired_framerate, desiredPixelFormat);
512
				cur_width  *= 2;
513
				cur_height *= 2;
514
			}
515

516
			cur_width  = max_width;
517
			cur_height = max_height;
518
			while (cur_width > min_width && cur_height > min_height){
519
				ofGstVideoFormat video_format;
520

521
				video_format.mimetype = gst_structure_get_name (structure);
522
				video_format.width    = cur_width;
523
				video_format.height   = cur_height;
524
				#if GST_VERSION_MAJOR==1
525
				if(gst_structure_get_string(structure,"format"))
526
					video_format.format_name = gst_structure_get_string(structure,"format");
527
				#endif
528
				add_video_format(webcam_device, video_format, *structure, desired_framerate, desiredPixelFormat);
529
				cur_width  /= 2;
530
				cur_height /= 2;
531
			}
532
		}else{
533
			ofLog(OF_LOG_ERROR, "unknown GValue type %s, for resolution width", G_VALUE_TYPE_NAME (width));
534
		}
535
	}
536
}
537

538
static void get_device_data (ofGstDevice &webcam_device, int desired_framerate, ofPixelFormat desiredPixelFormat)
539
{
540
	string pipeline_desc = webcam_device.gstreamer_src + " name=source device=" +
541
			webcam_device.video_device + " ! fakesink";
542

543
	GError * err = NULL;
544
	GstElement * pipeline = gst_parse_launch (pipeline_desc.c_str(), &err);
545
	if ((pipeline == NULL) || (err != NULL)){
546
		if (err){
547
			ofLog(OF_LOG_ERROR, "ofGstUtils: error getting device data: %s", err->message);
548
			g_error_free (err);
549
		}else{
550
			ofLog(OF_LOG_ERROR, "ofGstUtils: error getting device data, cannot get pipeline");
551
		}
552
		if(pipeline)
553
			gst_object_unref (pipeline);
554
		return;
555
	}
556

557
	// TODO: try to lower seconds,
558
	// Start the pipeline and wait for max. 10 seconds for it to start up
559
	gst_element_set_state (pipeline, GST_STATE_READY);
560
	GstStateChangeReturn ret = gst_element_get_state (pipeline, NULL, NULL, 10 * GST_SECOND);
561

562
	// Check if any error messages were posted on the bus
563
	GstBus * bus = gst_element_get_bus (pipeline);
564
	GstMessage * msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0);
565
	gst_object_unref (bus);
566

567
	if ((msg == NULL) && (ret == GST_STATE_CHANGE_SUCCESS)){
568

569
		GstElement *src = gst_bin_get_by_name (GST_BIN (pipeline), "source");
570
		char       *name;
571
		g_object_get (G_OBJECT (src), "device-name", &name, (void*)NULL);
572

573
		ofLog(OF_LOG_VERBOSE, "Device: %s (%s)\n", name==NULL?"":name, webcam_device.video_device.c_str());
574
		GstPad     *pad  = gst_element_get_static_pad (src, "src");
575
		GstCaps    *caps = gst_pad_get_allowed_caps (pad);
576
		gst_object_unref (pad);
577

578
		get_supported_video_formats (webcam_device, *caps, desired_framerate, desiredPixelFormat);
579

580
		gst_caps_unref (caps);
581
		gst_object_unref(src);
582
	}else if(msg){
583
		gchar *debug;
584
		gst_message_parse_error(msg, &err, &debug);
585

586
		ofLog(OF_LOG_ERROR, "ofGstUtils: error getting device data; module %s reported: %s",
587
			  gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
588

589
		g_error_free(err);
590
		g_free(debug);
591
	}
592
	gst_element_set_state (pipeline, GST_STATE_NULL);
593
	ret = gst_element_get_state (pipeline, NULL, NULL, 10 * GST_SECOND);
594
	gst_object_unref (pipeline);
595

596
}
597

598
ofGstVideoGrabber::ofGstVideoGrabber(){
599
	bIsCamera			= false;
600
	camData.bInited		= false;
601

602
	deviceID 			= 0;
603
	attemptFramerate	= -1;
604
	internalPixelFormat	= OF_PIXELS_RGB;
605
}
606

607
ofGstVideoGrabber::~ofGstVideoGrabber(){
608
	close();
609
}
610

611
bool ofGstVideoGrabber::setPixelFormat(ofPixelFormat pixelFormat){
612
	internalPixelFormat = pixelFormat;
613
	return true;
614
}
615

616
ofPixelFormat ofGstVideoGrabber::getPixelFormat() const{
617
	if(videoUtils.isInitialized()){
618
		return videoUtils.getPixelFormat();
619
	}else{
620
		return internalPixelFormat;
621
	}
622
}
623

624
void ofGstVideoGrabber::setVerbose(bool bVerbose){
625
	if(bVerbose) ofSetLogLevel("ofGstVideoGrabber", OF_LOG_VERBOSE);
626
	else ofSetLogLevel("ofGstVideoGrabber",OF_LOG_NOTICE);
627
}
628

629
bool ofGstVideoGrabber::isInitialized() const{
630
	return videoUtils.isInitialized();
631
}
632

633
ofPixelFormat ofPixelFormatFromGstFormat(string format){
634
#if GST_VERSION_MAJOR>=1
635
	switch(gst_video_format_from_string(format.c_str())){
636
	case GST_VIDEO_FORMAT_RGB: return OF_PIXELS_RGB;
637
	case GST_VIDEO_FORMAT_RGBA: return OF_PIXELS_RGBA;
638
	case GST_VIDEO_FORMAT_BGRA: return OF_PIXELS_BGRA;
639
	case GST_VIDEO_FORMAT_GRAY8: return OF_PIXELS_MONO;
640
	case GST_VIDEO_FORMAT_RGB16: return OF_PIXELS_RGB565;
641
	default: return OF_PIXELS_UNKNOWN;
642
	}
643
#else
644
	ofLogWarning("ofGstVideoGrabber") << "ofPixelFormatFromGstFormat(): only supported for gstreamer 1.0";
645
	return OF_PIXELS_UNKNOWN;
646
#endif
647
}
648

649
vector<ofVideoDevice> ofGstVideoGrabber::listDevices() const {
650
#if GST_VERSION_MAJOR>=1
651
	if(!camData.bInited) get_video_devices(camData);
652
	vector<ofVideoDevice> devices(camData.webcam_devices.size());
653
	for(unsigned i=0; i<camData.webcam_devices.size(); i++){
654
		devices[i].id = i;
655
        devices[i].bAvailable = true; 
656
		devices[i].deviceName = camData.webcam_devices[i].product_name;
657
		devices[i].hardwareName = camData.webcam_devices[i].video_device;
658
		devices[i].serialID = camData.webcam_devices[i].serial_id;
659
		devices[i].formats.resize(camData.webcam_devices[i].video_formats.size());
660
		for(int j=0;j<(int)camData.webcam_devices[i].video_formats.size();j++){
661
			devices[i].formats[j].pixelFormat = ofPixelFormatFromGstFormat(camData.webcam_devices[i].video_formats[j].format_name);
662
			devices[i].formats[j].width = camData.webcam_devices[i].video_formats[j].width;
663
			devices[i].formats[j].height = camData.webcam_devices[i].video_formats[j].height;
664
			devices[i].formats[j].framerates.resize(camData.webcam_devices[i].video_formats[j].framerates.size());
665
			for(int k=0;k<(int)camData.webcam_devices[i].video_formats[j].framerates.size();k++){
666
				devices[i].formats[j].framerates[k] = float(camData.webcam_devices[i].video_formats[j].framerates[k].numerator)/float(camData.webcam_devices[i].video_formats[j].framerates[k].denominator);
667
			}
668
		}
669
		ofLogVerbose("ofGstVideoGrabber") << "listDevices(): device " << i << ": " << camData.webcam_devices[i].video_device << ": " << camData.webcam_devices[i].product_name;
670
	}
671
	return devices;
672
#else
673
	ofLogWarning("ofGstVideoGrabber") << "listDevices(): only supported for gstreamer 1.0";
674
	return vector<ofVideoDevice>();
675
#endif
676
}
677

678
void ofGstVideoGrabber::setDeviceID(int id){
679
	if(!camData.bInited) get_video_devices(camData);
680
	if(int(camData.webcam_devices.size())>id){
681
		deviceID = id;
682
	}else{
683
		ofLogWarning("ofGstVideoGrabber") << "setDeviceID(): selected device doesn't exist, selecting device 0";
684
	}
685
}
686

687
ofGstVideoFormat & ofGstVideoGrabber::selectFormat(int w, int h, int desired_framerate, ofPixelFormat desiredPixelFormat){
688
	int minDiff=999999;
689
	int mostSimilarFormat=0;
690

691
	get_device_data (camData.webcam_devices[deviceID], desired_framerate, desiredPixelFormat);
692

693
	for(unsigned i=0; i<camData.webcam_devices[deviceID].video_formats.size(); i++){
694
		if(camData.webcam_devices[deviceID].video_formats[i].width==w && camData.webcam_devices[deviceID].video_formats[i].height==h){
695
			mostSimilarFormat = i;
696
			break;
697
		}
698
		int diff = abs(camData.webcam_devices[deviceID].video_formats[i].width + camData.webcam_devices[deviceID].video_formats[i].height - w - h);
699
		if(diff<minDiff){
700
			minDiff = diff;
701
			mostSimilarFormat = i;
702
		}
703
	}
704
	camData.webcam_devices[deviceID].current_format = mostSimilarFormat;
705
	return camData.webcam_devices[deviceID].video_formats[mostSimilarFormat];
706
}
707

708
bool ofGstVideoGrabber::setup(int w, int h){
709
	if(!camData.bInited) get_video_devices(camData);
710

711
	if(camData.webcam_devices.size()==0){
712
		ofLogError("ofGstVideoGrabber") << "initGrabber(): no devices found, exiting without initializing";
713
		return false;
714
	}
715

716
	ofGstVideoFormat format;
717
	if(internalPixelFormat!=OF_PIXELS_NATIVE){
718
		format = selectFormat(w, h, attemptFramerate, internalPixelFormat);
719
		ofLogNotice("ofGstVideoGrabber") << "initGrabber(): selected device: " << camData.webcam_devices[deviceID].product_name;
720
		ofLogNotice("ofGstVideoGrabber") << "initGrabber(): selected format: " << format.width << "x" << format.height
721
			<< " " << format.mimetype << " " << format.format_name << " framerate: " << format.choosen_framerate.numerator << "/" << format.choosen_framerate.denominator;
722
	}
723

724
	bIsCamera = true;
725

726

727
#if GST_VERSION_MAJOR==0
728
	const char * decodebin = "";
729
	if(format.mimetype == "video/x-raw-bayer")
730
		decodebin = "! bayer2rgb ";
731
	else if(format.mimetype != "video/x-raw-yuv" && format.mimetype != "video/x-raw-rgb")
732
		decodebin = "! decodebin2 ";
733
	const char * scale = "! ffmpegcolorspace ";
734
	if( w!=format.width || h!=format.height )	scale = "! ffvideoscale method=2 ";
735

736
	string format_str_pipeline = "%s name=video_source device=%s ! "
737
			 "%s,width=%d,height=%d,framerate=%d/%d "
738
			 "%s %s ";
739

740
	gchar* pipeline_string=g_strdup_printf (
741
		      format_str_pipeline.c_str(),
742
		      camData.webcam_devices[deviceID].gstreamer_src.c_str(),
743
		      camData.webcam_devices[deviceID].video_device.c_str(),
744
		      format.mimetype.c_str(),
745
		      format.width,
746
		      format.height,
747
		      format.choosen_framerate.numerator,
748
		      format.choosen_framerate.denominator,
749
		      decodebin, scale);
750
#else
751
	string pipeline_string;
752
	string format_str_pipeline;
753
	string fix_v4l2_316;
754
#if defined(TARGET_LINUX) && !defined(OF_USE_GST_GL) && GST_VERSION_MAJOR>0 && GST_VERSION_MINOR>2 && GST_VERSION_MINOR<5
755
	videoUtils.setCopyPixels(true);
756
#endif
757
	if(internalPixelFormat!=OF_PIXELS_NATIVE){
758
		string decodebin, scale;
759
		if(format.mimetype == "video/x-bayer"){
760
			decodebin = "! bayer2rgb ";
761
		}else if(gst_video_format_from_string(format.format_name.c_str()) == GST_VIDEO_FORMAT_ENCODED || gst_video_format_from_string(format.format_name.c_str()) ==GST_VIDEO_FORMAT_UNKNOWN){
762
			decodebin = "! decodebin ";
763
		}
764

765
		if(format.format_name!=ofGstVideoUtils::getGstFormatName(internalPixelFormat)){
766
			scale = "! videoconvert ";
767
		}
768

769
		if( w!=format.width || h!=format.height ){
770
			scale = "! videoscale method=2 ";
771
		}
772

773
		if(format.format_name==""){
774
			format_str_pipeline = "%s name=video_source device=%s ! "
775
									 "%s,width=%d,height=%d,framerate=%d/%d "
776
									 "%s %s ";
777

778
			pipeline_string=g_strdup_printf (
779
							  format_str_pipeline.c_str(),
780
							  camData.webcam_devices[deviceID].gstreamer_src.c_str(),
781
							  camData.webcam_devices[deviceID].video_device.c_str(),
782
							  format.mimetype.c_str(),
783
							  format.width,
784
							  format.height,
785
							  format.choosen_framerate.numerator,
786
							  format.choosen_framerate.denominator,
787
							  decodebin.c_str(), (scale + fix_v4l2_316).c_str());
788
		}else{
789
			format_str_pipeline = "%s name=video_source device=%s ! "
790
									 "%s,format=%s,width=%d,height=%d,framerate=%d/%d "
791
									 "%s %s ";
792

793
			pipeline_string=g_strdup_printf (
794
							  format_str_pipeline.c_str(),
795
							  camData.webcam_devices[deviceID].gstreamer_src.c_str(),
796
							  camData.webcam_devices[deviceID].video_device.c_str(),
797
							  format.mimetype.c_str(),
798
							  format.format_name.c_str(),
799
							  format.width,
800
							  format.height,
801
							  format.choosen_framerate.numerator,
802
							  format.choosen_framerate.denominator,
803
							  decodebin.c_str(), (scale + fix_v4l2_316).c_str());
804
		}
805
	}else{
806
		format_str_pipeline = "v4l2src name=video_source device=/dev/video%d ! video/x-raw,framerate=%d/1 %s";
807
		pipeline_string=g_strdup_printf (
808
				format_str_pipeline.c_str(),
809
				deviceID,attemptFramerate,fix_v4l2_316.c_str());
810

811

812
	}
813
#endif
814

815

816

817
	return videoUtils.setPipeline(pipeline_string,internalPixelFormat,false,w,h) && videoUtils.startPipeline();
818
}
819

820
void ofGstVideoGrabber::setDesiredFrameRate(int framerate){
821
	attemptFramerate = framerate;
822
}
823

824
ofGstVideoUtils * ofGstVideoGrabber::getGstVideoUtils(){
825
	return &videoUtils;
826
}
827

828

829
void ofGstVideoGrabber::update(){
830
 	videoUtils.update();
831
}
832

833
bool ofGstVideoGrabber::isFrameNew() const {
834
	return videoUtils.isFrameNew();
835
}
836

837

838
ofPixels& ofGstVideoGrabber::getPixels(){
839
	return videoUtils.getPixels();
840
}
841

842
const ofPixels & ofGstVideoGrabber::getPixels() const {
843
	return videoUtils.getPixels();
844
}
845

846
ofTexture * ofGstVideoGrabber::getTexturePtr(){
847
	return videoUtils.getTexture();
848
}
849

850
float ofGstVideoGrabber::getHeight() const {
851
	return videoUtils.getHeight();
852
}
853

854
float ofGstVideoGrabber::getWidth() const {
855
	return videoUtils.getWidth();
856
}
857

858
void ofGstVideoGrabber::close(){
859
	videoUtils.close();
860
}
861

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.