Advertisement
Guest User

Untitled

a guest
Jun 14th, 2011
452
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 80.71 KB | None | 0 0
  1. //
  2. // ZoneMinder Local Camera Class Implementation, $Date$, $Revision$
  3. // Copyright (C) 2001-2008 Philip Coombes
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18. //
  19.  
  20. #include "zm.h"
  21.  
  22. #if ZM_HAS_V4L
  23.  
  24. #include "zm_local_camera.h"
  25.  
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <fcntl.h>
  29. #include <unistd.h>
  30. #include <sys/mman.h>
  31. #include <errno.h>
  32.  
  33. static unsigned int BigEndian;
  34.  
  35. static int vidioctl( int fd, int request, void *arg )
  36. {
  37. int result = -1;
  38. do
  39. {
  40. result = ioctl( fd, request, arg );
  41. } while ( result == -1 && errno == EINTR );
  42. return( result );
  43. }
  44.  
  45. #if HAVE_LIBSWSCALE
  46. static PixelFormat getFfPixFormatFromV4lPalette( int v4l_version, int palette )
  47. {
  48. PixelFormat pixFormat = PIX_FMT_NONE;
  49.  
  50. #if ZM_HAS_V4L2
  51. if ( v4l_version == 2 )
  52. {
  53. switch( palette )
  54. {
  55. #ifdef V4L2_PIX_FMT_RGB444
  56. case V4L2_PIX_FMT_RGB444 :
  57. pixFormat = PIX_FMT_RGB444;
  58. break;
  59. #endif // V4L2_PIX_FMT_RGB444
  60. case V4L2_PIX_FMT_RGB555 :
  61. pixFormat = PIX_FMT_RGB555;
  62. break;
  63. case V4L2_PIX_FMT_RGB565 :
  64. pixFormat = PIX_FMT_RGB565;
  65. break;
  66. case V4L2_PIX_FMT_BGR24 :
  67. pixFormat = PIX_FMT_BGR24;
  68. break;
  69. case V4L2_PIX_FMT_RGB24 :
  70. pixFormat = PIX_FMT_RGB24;
  71. break;
  72. case V4L2_PIX_FMT_BGR32 :
  73. pixFormat = PIX_FMT_BGRA;
  74. break;
  75. case V4L2_PIX_FMT_RGB32 :
  76. pixFormat = PIX_FMT_ARGB;
  77. break;
  78. case V4L2_PIX_FMT_GREY :
  79. pixFormat = PIX_FMT_GRAY8;
  80. break;
  81. case V4L2_PIX_FMT_YUYV :
  82. pixFormat = PIX_FMT_YUYV422;
  83. break;
  84. case V4L2_PIX_FMT_YUV422P :
  85. pixFormat = PIX_FMT_YUV422P;
  86. break;
  87. case V4L2_PIX_FMT_YUV411P :
  88. pixFormat = PIX_FMT_YUV411P;
  89. break;
  90. #ifdef V4L2_PIX_FMT_YUV444
  91. case V4L2_PIX_FMT_YUV444 :
  92. pixFormat = PIX_FMT_YUV444P;
  93. break;
  94. #endif // V4L2_PIX_FMT_YUV444
  95. case V4L2_PIX_FMT_YUV410 :
  96. pixFormat = PIX_FMT_YUV410P;
  97. break;
  98. case V4L2_PIX_FMT_YUV420 :
  99. pixFormat = PIX_FMT_YUV420P;
  100. break;
  101. case V4L2_PIX_FMT_JPEG :
  102. pixFormat = PIX_FMT_YUVJ444P;
  103. break;
  104. // These don't seem to have ffmpeg equivalents
  105. // See if you can match any of the ones in the default clause below!?
  106. case V4L2_PIX_FMT_UYVY :
  107. case V4L2_PIX_FMT_RGB332 :
  108. case V4L2_PIX_FMT_RGB555X :
  109. case V4L2_PIX_FMT_RGB565X :
  110. //case V4L2_PIX_FMT_Y16 :
  111. //case V4L2_PIX_FMT_PAL8 :
  112. case V4L2_PIX_FMT_YVU410 :
  113. case V4L2_PIX_FMT_YVU420 :
  114. case V4L2_PIX_FMT_Y41P :
  115. //case V4L2_PIX_FMT_YUV555 :
  116. //case V4L2_PIX_FMT_YUV565 :
  117. //case V4L2_PIX_FMT_YUV32 :
  118. case V4L2_PIX_FMT_NV12 :
  119. case V4L2_PIX_FMT_NV21 :
  120. case V4L2_PIX_FMT_YYUV :
  121. case V4L2_PIX_FMT_HI240 :
  122. case V4L2_PIX_FMT_HM12 :
  123. //case V4L2_PIX_FMT_SBGGR8 :
  124. //case V4L2_PIX_FMT_SGBRG8 :
  125. //case V4L2_PIX_FMT_SBGGR16 :
  126. case V4L2_PIX_FMT_MJPEG :
  127. case V4L2_PIX_FMT_DV :
  128. case V4L2_PIX_FMT_MPEG :
  129. case V4L2_PIX_FMT_WNVA :
  130. case V4L2_PIX_FMT_SN9C10X :
  131. case V4L2_PIX_FMT_PWC1 :
  132. case V4L2_PIX_FMT_PWC2 :
  133. case V4L2_PIX_FMT_ET61X251 :
  134. //case V4L2_PIX_FMT_SPCA501 :
  135. //case V4L2_PIX_FMT_SPCA505 :
  136. //case V4L2_PIX_FMT_SPCA508 :
  137. //case V4L2_PIX_FMT_SPCA561 :
  138. //case V4L2_PIX_FMT_PAC207 :
  139. //case V4L2_PIX_FMT_PJPG :
  140. //case V4L2_PIX_FMT_YVYU :
  141. default :
  142. {
  143. Fatal( "Can't find swscale format for palette %d", palette );
  144. break;
  145. // These are all spare and may match some of the above
  146. pixFormat = PIX_FMT_YUVJ420P;
  147. pixFormat = PIX_FMT_YUVJ422P;
  148. pixFormat = PIX_FMT_XVMC_MPEG2_MC;
  149. pixFormat = PIX_FMT_XVMC_MPEG2_IDCT;
  150. pixFormat = PIX_FMT_UYVY422;
  151. pixFormat = PIX_FMT_UYYVYY411;
  152. pixFormat = PIX_FMT_BGR565;
  153. pixFormat = PIX_FMT_BGR555;
  154. pixFormat = PIX_FMT_BGR8;
  155. pixFormat = PIX_FMT_BGR4;
  156. pixFormat = PIX_FMT_BGR4_BYTE;
  157. pixFormat = PIX_FMT_RGB8;
  158. pixFormat = PIX_FMT_RGB4;
  159. pixFormat = PIX_FMT_RGB4_BYTE;
  160. pixFormat = PIX_FMT_NV12;
  161. pixFormat = PIX_FMT_NV21;
  162. pixFormat = PIX_FMT_RGB32_1;
  163. pixFormat = PIX_FMT_BGR32_1;
  164. pixFormat = PIX_FMT_GRAY16BE;
  165. pixFormat = PIX_FMT_GRAY16LE;
  166. pixFormat = PIX_FMT_YUV440P;
  167. pixFormat = PIX_FMT_YUVJ440P;
  168. pixFormat = PIX_FMT_YUVA420P;
  169. //pixFormat = PIX_FMT_VDPAU_H264;
  170. //pixFormat = PIX_FMT_VDPAU_MPEG1;
  171. //pixFormat = PIX_FMT_VDPAU_MPEG2;
  172. }
  173. }
  174. }
  175. #endif // ZM_HAS_V4L2
  176. #if ZM_HAS_V4L1
  177. if ( v4l_version == 1 )
  178. {
  179. switch( palette )
  180. {
  181. case VIDEO_PALETTE_RGB32 :
  182. if(BigEndian)
  183. pixFormat = PIX_FMT_ARGB;
  184. else
  185. pixFormat = PIX_FMT_BGRA;
  186. break;
  187. case VIDEO_PALETTE_RGB24 :
  188. if(BigEndian)
  189. pixFormat = PIX_FMT_RGB24;
  190. else
  191. pixFormat = PIX_FMT_BGR24;
  192. break;
  193. case VIDEO_PALETTE_GREY :
  194. pixFormat = PIX_FMT_GRAY8;
  195. break;
  196. case VIDEO_PALETTE_RGB555 :
  197. pixFormat = PIX_FMT_RGB555;
  198. break;
  199. case VIDEO_PALETTE_RGB565 :
  200. pixFormat = PIX_FMT_RGB565;
  201. break;
  202. case VIDEO_PALETTE_YUYV :
  203. case VIDEO_PALETTE_YUV422 :
  204. pixFormat = PIX_FMT_YUYV422;
  205. break;
  206. case VIDEO_PALETTE_YUV422P :
  207. pixFormat = PIX_FMT_YUV422P;
  208. break;
  209. case VIDEO_PALETTE_YUV420P :
  210. pixFormat = PIX_FMT_YUV420P;
  211. break;
  212. default :
  213. {
  214. Fatal( "Can't find swscale format for palette %d", palette );
  215. break;
  216. // These are all spare and may match some of the above
  217. pixFormat = PIX_FMT_YUVJ420P;
  218. pixFormat = PIX_FMT_YUVJ422P;
  219. pixFormat = PIX_FMT_YUVJ444P;
  220. pixFormat = PIX_FMT_XVMC_MPEG2_MC;
  221. pixFormat = PIX_FMT_XVMC_MPEG2_IDCT;
  222. pixFormat = PIX_FMT_UYVY422;
  223. pixFormat = PIX_FMT_UYYVYY411;
  224. pixFormat = PIX_FMT_BGR565;
  225. pixFormat = PIX_FMT_BGR555;
  226. pixFormat = PIX_FMT_BGR8;
  227. pixFormat = PIX_FMT_BGR4;
  228. pixFormat = PIX_FMT_BGR4_BYTE;
  229. pixFormat = PIX_FMT_RGB8;
  230. pixFormat = PIX_FMT_RGB4;
  231. pixFormat = PIX_FMT_RGB4_BYTE;
  232. pixFormat = PIX_FMT_NV12;
  233. pixFormat = PIX_FMT_NV21;
  234. pixFormat = PIX_FMT_RGB32_1;
  235. pixFormat = PIX_FMT_BGR32_1;
  236. pixFormat = PIX_FMT_GRAY16BE;
  237. pixFormat = PIX_FMT_GRAY16LE;
  238. pixFormat = PIX_FMT_YUV440P;
  239. pixFormat = PIX_FMT_YUVJ440P;
  240. pixFormat = PIX_FMT_YUVA420P;
  241. //pixFormat = PIX_FMT_VDPAU_H264;
  242. //pixFormat = PIX_FMT_VDPAU_MPEG1;
  243. //pixFormat = PIX_FMT_VDPAU_MPEG2;
  244. }
  245. }
  246. }
  247. #endif // ZM_HAS_V4L1
  248. return( pixFormat );
  249. }
  250. #endif // HAVE_LIBSWSCALE
  251.  
  252. int LocalCamera::camera_count = 0;
  253. int LocalCamera::channel_count = 0;
  254. int LocalCamera::channels[VIDEO_MAX_FRAME];
  255. int LocalCamera::standards[VIDEO_MAX_FRAME];
  256.  
  257. int LocalCamera::vid_fd = -1;
  258.  
  259. int LocalCamera::v4l_version = 0;
  260. #if ZM_HAS_V4L2
  261. LocalCamera::V4L2Data LocalCamera::v4l2_data;
  262. #endif // ZM_HAS_V4L2
  263. #if ZM_HAS_V4L1
  264. LocalCamera::V4L1Data LocalCamera::v4l1_data;
  265. #endif // ZM_HAS_V4L1
  266.  
  267. #if HAVE_LIBSWSCALE
  268. AVFrame **LocalCamera::capturePictures = 0;
  269. #endif // HAVE_LIBSWSCALE
  270.  
  271. LocalCamera *LocalCamera::last_camera = NULL;
  272.  
  273. LocalCamera::LocalCamera( int p_id, const std::string &p_device, int p_channel, int p_standard, const std::string &p_method, int p_width, int p_height, int p_colours, int p_palette, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture ) :
  274. Camera( p_id, LOCAL_SRC, p_width, p_height, p_colours, ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours), p_brightness, p_contrast, p_hue, p_colour, p_capture ),
  275. device( p_device ),
  276. channel( p_channel ),
  277. standard( p_standard ),
  278. palette( p_palette ),
  279. channel_index( 0 )
  280. {
  281. // If we are the first, or only, input on this device then
  282. // do the initial opening etc
  283. device_prime = (camera_count++ == 0);
  284. v4l_version = (p_method=="v4l2"?2:1);
  285.  
  286. if ( capture )
  287. {
  288. if ( device_prime )
  289. {
  290. Debug( 2, "V4L support enabled, using V4L%d api", v4l_version );
  291. }
  292.  
  293. if ( !last_camera || channel != last_camera->channel )
  294. {
  295. // We are the first, or only, input that uses this channel
  296. channel_prime = true;
  297. channel_index = channel_count++;
  298. channels[channel_index] = channel;
  299. standards[channel_index] = standard;
  300. }
  301. else
  302. {
  303. // We are the second, or subsequent, input using this channel
  304. channel_prime = false;
  305. }
  306.  
  307. if ( last_camera )
  308. {
  309. if ( (p_method == "v4l2" && v4l_version != 2) || (p_method == "v4l1" && v4l_version != 1) )
  310. Fatal( "Different Video For Linux version used for monitors sharing same device" );
  311.  
  312. if ( standard != last_camera->standard )
  313. Warning( "Different video standards defined for monitors sharing same device, results may be unpredictable or completely wrong" );
  314.  
  315. if ( palette != last_camera->palette )
  316. Warning( "Different video palettes defined for monitors sharing same device, results may be unpredictable or completely wrong" );
  317.  
  318. if ( width != last_camera->width || height != last_camera->height )
  319. Warning( "Different capture sizes defined for monitors sharing same device, results may be unpredictable or completely wrong" );
  320. }
  321.  
  322. }
  323.  
  324. /* The V4L1 API doesn't care about endianness, we need to check the endianness of the machine */
  325. uint32_t checkval = 0xAABBCCDD;
  326. if(*(unsigned char*)&checkval == 0xDD) {
  327. BigEndian = 0;
  328. Debug(2,"little-endian processor detected");
  329. } else if(*(unsigned char*)&checkval == 0xAA) {
  330. BigEndian = 1;
  331. Debug(2,"Big-endian processor detected");
  332. } else {
  333. Error("Unable to detect the processor's endianness. Assuming little-endian.");
  334. BigEndian = 0;
  335. }
  336.  
  337.  
  338. #if HAVE_LIBSWSCALE
  339. if( capture ) {
  340. /* Get ffmpeg pixel format based on capture palette and endianness */
  341. capturePixFormat = getFfPixFormatFromV4lPalette( v4l_version, palette );
  342. imagePixFormat = PIX_FMT_NONE;
  343. }
  344. #endif // HAVE_LIBSWSCALE
  345.  
  346.  
  347. /* V4L2 format matching */
  348. #if ZM_HAS_V4L2
  349. if ( v4l_version == 2 ) {
  350. /* Try to find a match for the selected palette and target colourspace */
  351.  
  352. /* RGB32 palette and 32bit target colourspace */
  353. if(palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_RGB32) {
  354. conversion_type = 0;
  355. subpixelorder = ZM_SUBPIX_ORDER_ARGB;
  356.  
  357. /* BGR32 palette and 32bit target colourspace */
  358. } else if(palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_RGB32) {
  359. conversion_type = 0;
  360. subpixelorder = ZM_SUBPIX_ORDER_BGRA;
  361.  
  362. /* RGB24 palette and 24bit target colourspace */
  363. } else if(palette == V4L2_PIX_FMT_RGB24 && colours == ZM_COLOUR_RGB24) {
  364. conversion_type = 0;
  365. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  366.  
  367. /* BGR24 palette and 24bit target colourspace */
  368. } else if(palette == V4L2_PIX_FMT_BGR24 && colours == ZM_COLOUR_RGB24) {
  369. conversion_type = 0;
  370. subpixelorder = ZM_SUBPIX_ORDER_BGR;
  371.  
  372. /* Grayscale palette and grayscale target colourspace */
  373. } else if(palette == V4L2_PIX_FMT_GREY && colours == ZM_COLOUR_GRAY8) {
  374. conversion_type = 0;
  375. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  376. /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */
  377. } else {
  378. if( capture )
  379. Warning("Unable to find a match for the selected palette and target colourspace. Conversion required, performance penalty expected");
  380. #if HAVE_LIBSWSCALE
  381. /* Try using swscale for the conversion */
  382. conversion_type = 1;
  383. Debug(2,"Using swscale for image conversion");
  384. if(colours == ZM_COLOUR_RGB32) {
  385. subpixelorder = ZM_SUBPIX_ORDER_RGBA;
  386. imagePixFormat = PIX_FMT_RGBA;
  387. } else if(colours == ZM_COLOUR_RGB24) {
  388. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  389. imagePixFormat = PIX_FMT_RGB24;
  390. } else if(colours == ZM_COLOUR_GRAY8) {
  391. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  392. imagePixFormat = PIX_FMT_GRAY8;
  393. } else {
  394. Panic("Unexpected colours: %d",colours);
  395. }
  396. if( capture ) {
  397. if(!sws_isSupportedInput(capturePixFormat)) {
  398. Error("swscale does not support the used capture format");
  399. conversion_type = 2; /* Try ZM format conversions */
  400. }
  401. if(!sws_isSupportedOutput(imagePixFormat)) {
  402. Error("swscale does not support the target format");
  403. conversion_type = 2; /* Try ZM format conversions */
  404. }
  405. }
  406. #else
  407. /* Don't have swscale, see what we can do */
  408. conversion_type = 2;
  409. #endif
  410. /* Our YUYV->Grayscale conversion is a lot faster than swscale's */
  411. if(conversion_type == 1 && colours == ZM_COLOUR_GRAY8 && palette == V4L2_PIX_FMT_YUYV) {
  412. conversion_type = 2;
  413. }
  414.  
  415. if(conversion_type == 2) {
  416. Debug(2,"Using ZM for image conversion");
  417. if(palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_GRAY8) {
  418. conversion_fptr = &std_convert_argb_gray8;
  419. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  420. } else if(palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_GRAY8) {
  421. conversion_fptr = &std_convert_bgra_gray8;
  422. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  423. } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8) {
  424. /* Fast YUYV->Grayscale conversion by extracting the Y channel */
  425. if(config.cpu_extensions && sseversion >= 35) {
  426. conversion_fptr = &ssse3_convert_yuyv_gray8;
  427. Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
  428. } else {
  429. conversion_fptr = &std_convert_yuyv_gray8;
  430. Debug(2,"Using standard YUYV->grayscale fast conversion");
  431. }
  432. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  433. } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB24) {
  434. conversion_fptr = &zm_convert_yuyv_rgb;
  435. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  436. } else if(palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB32) {
  437. conversion_fptr = &zm_convert_yuyv_rgba;
  438. subpixelorder = ZM_SUBPIX_ORDER_RGBA;
  439. } else if(palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB24) {
  440. conversion_fptr = &zm_convert_rgb555_rgb;
  441. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  442. } else if(palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB32) {
  443. conversion_fptr = &zm_convert_rgb555_rgba;
  444. subpixelorder = ZM_SUBPIX_ORDER_RGBA;
  445. } else if(palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB24) {
  446. conversion_fptr = &zm_convert_rgb565_rgb;
  447. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  448. } else if(palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB32) {
  449. conversion_fptr = &zm_convert_rgb565_rgba;
  450. subpixelorder = ZM_SUBPIX_ORDER_RGBA;
  451. } else {
  452. Fatal("Unable to find suitable conversion for selected palette and target colourspace.");
  453. }
  454. }
  455. }
  456. }
  457. #endif // ZM_HAS_V4L2
  458.  
  459. /* V4L1 format matching */
  460. #if ZM_HAS_V4L1
  461. if ( v4l_version == 1) {
  462. /* Try to find a match for the selected palette and target colourspace */
  463.  
  464. /* RGB32 palette and 32bit target colourspace */
  465. if(palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_RGB32) {
  466. conversion_type = 0;
  467. if(BigEndian) {
  468. subpixelorder = ZM_SUBPIX_ORDER_ARGB;
  469. } else {
  470. subpixelorder = ZM_SUBPIX_ORDER_BGRA;
  471. }
  472.  
  473. /* RGB24 palette and 24bit target colourspace */
  474. } else if(palette == VIDEO_PALETTE_RGB24 && colours == ZM_COLOUR_RGB24) {
  475. conversion_type = 0;
  476. if(BigEndian) {
  477. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  478. } else {
  479. subpixelorder = ZM_SUBPIX_ORDER_BGR;
  480. }
  481.  
  482. /* Grayscale palette and grayscale target colourspace */
  483. } else if(palette == VIDEO_PALETTE_GREY && colours == ZM_COLOUR_GRAY8) {
  484. conversion_type = 0;
  485. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  486. /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */
  487. } else {
  488. if( capture )
  489. Warning("Unable to find a match for the selected palette and target colourspace. Conversion required, performance penalty expected");
  490. #if HAVE_LIBSWSCALE
  491. /* Try using swscale for the conversion */
  492. conversion_type = 1;
  493. Debug(2,"Using swscale for image conversion");
  494. if(colours == ZM_COLOUR_RGB32) {
  495. subpixelorder = ZM_SUBPIX_ORDER_RGBA;
  496. imagePixFormat = PIX_FMT_RGBA;
  497. } else if(colours == ZM_COLOUR_RGB24) {
  498. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  499. imagePixFormat = PIX_FMT_RGB24;
  500. } else if(colours == ZM_COLOUR_GRAY8) {
  501. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  502. imagePixFormat = PIX_FMT_GRAY8;
  503. } else {
  504. Panic("Unexpected colours: %d",colours);
  505. }
  506. if( capture ) {
  507. if(!sws_isSupportedInput(capturePixFormat)) {
  508. Error("swscale does not support the used capture format");
  509. conversion_type = 2; /* Try ZM format conversions */
  510. }
  511. if(!sws_isSupportedOutput(imagePixFormat)) {
  512. Error("swscale does not support the target format");
  513. conversion_type = 2; /* Try ZM format conversions */
  514. }
  515. }
  516. #else
  517. /* Don't have swscale, see what we can do */
  518. conversion_type = 2;
  519. #endif
  520. /* Our YUYV->Grayscale conversion is a lot faster than swscale's */
  521. if(conversion_type == 1 && colours == ZM_COLOUR_GRAY8 && (palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422)) {
  522. conversion_type = 2;
  523. }
  524.  
  525. if(conversion_type == 2) {
  526. Debug(2,"Using ZM for image conversion");
  527. if(palette == VIDEO_PALETTE_RGB32 && colours == ZM_COLOUR_GRAY8) {
  528. if(BigEndian) {
  529. conversion_fptr = &std_convert_argb_gray8;
  530. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  531. } else {
  532. conversion_fptr = &std_convert_bgra_gray8;
  533. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  534. }
  535. } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_GRAY8) {
  536. /* Fast YUYV->Grayscale conversion by extracting the Y channel */
  537. if(config.cpu_extensions && sseversion >= 35) {
  538. conversion_fptr = &ssse3_convert_yuyv_gray8;
  539. Debug(2,"Using SSSE3 YUYV->grayscale fast conversion");
  540. } else {
  541. conversion_fptr = &std_convert_yuyv_gray8;
  542. Debug(2,"Using standard YUYV->grayscale fast conversion");
  543. }
  544. subpixelorder = ZM_SUBPIX_ORDER_NONE;
  545. } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB24) {
  546. conversion_fptr = &zm_convert_yuyv_rgb;
  547. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  548. } else if((palette == VIDEO_PALETTE_YUYV || palette == VIDEO_PALETTE_YUV422) && colours == ZM_COLOUR_RGB32) {
  549. conversion_fptr = &zm_convert_yuyv_rgba;
  550. subpixelorder = ZM_SUBPIX_ORDER_RGBA;
  551. } else if(palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB24) {
  552. conversion_fptr = &zm_convert_rgb555_rgb;
  553. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  554. } else if(palette == VIDEO_PALETTE_RGB555 && colours == ZM_COLOUR_RGB32) {
  555. conversion_fptr = &zm_convert_rgb555_rgba;
  556. subpixelorder = ZM_SUBPIX_ORDER_RGBA;
  557. } else if(palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB24) {
  558. conversion_fptr = &zm_convert_rgb565_rgb;
  559. subpixelorder = ZM_SUBPIX_ORDER_RGB;
  560. } else if(palette == VIDEO_PALETTE_RGB565 && colours == ZM_COLOUR_RGB32) {
  561. conversion_fptr = &zm_convert_rgb565_rgba;
  562. subpixelorder = ZM_SUBPIX_ORDER_RGBA;
  563. } else {
  564. Panic("Unable to find suitable conversion for selected palette and target colourspace.");
  565. }
  566. }
  567. }
  568. }
  569. #endif // ZM_HAS_V4L1
  570.  
  571. last_camera = this;
  572. Debug(3,"Selected subpixelorder: %d",subpixelorder);
  573.  
  574. #if HAVE_LIBSWSCALE
  575. /* Initialize swscale stuff */
  576. if(capture && conversion_type == 1) {
  577. tmpPicture = avcodec_alloc_frame();
  578. if ( !tmpPicture )
  579. Fatal( "Could not allocate temporary picture" );
  580.  
  581. int pSize = avpicture_get_size( imagePixFormat, width, height );
  582. if( pSize != imagesize) {
  583. Fatal("Image size mismatch. Required: %d Available: %d",pSize,imagesize);
  584. }
  585.  
  586. if(config.cpu_extensions && sseversion >= 20) {
  587. imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC | SWS_CPU_CAPS_SSE2, NULL, NULL, NULL );
  588. } else {
  589. imgConversionContext = sws_getContext(width, height, capturePixFormat, width, height, imagePixFormat, SWS_BICUBIC, NULL, NULL, NULL );
  590. }
  591.  
  592. if ( !imgConversionContext )
  593. Fatal( "Unable to initialise image scaling context" );
  594.  
  595. }
  596. #endif
  597. }
  598.  
  599. LocalCamera::~LocalCamera()
  600. {
  601. if ( device_prime && capture )
  602. Terminate();
  603.  
  604. #if HAVE_LIBSWSCALE
  605. /* Clean up swscale stuff */
  606. if(capture && conversion_type == 1) {
  607. sws_freeContext(imgConversionContext);
  608. imgConversionContext = NULL;
  609.  
  610. av_free(tmpPicture);
  611. tmpPicture = NULL;
  612. }
  613. #endif
  614. }
  615.  
  616. void LocalCamera::Initialise()
  617. {
  618. #if HAVE_LIBSWSCALE
  619. if ( zmDbgLevel > ZM_DBG_INF )
  620. av_log_set_level( AV_LOG_DEBUG );
  621. else
  622. av_log_set_level( AV_LOG_QUIET );
  623. #endif // HAVE_LIBSWSCALE
  624.  
  625. struct stat st;
  626.  
  627. if ( stat( device.c_str(), &st ) < 0 )
  628. Fatal( "Failed to stat video device %s: %s", device.c_str(), strerror(errno) );
  629.  
  630. if ( !S_ISCHR(st.st_mode) )
  631. Fatal( "File %s is not device file: %s", device.c_str(), strerror(errno) );
  632.  
  633. Debug( 3, "Opening video device %s", device.c_str() );
  634. //if ( (vid_fd = open( device.c_str(), O_RDWR|O_NONBLOCK, 0 )) < 0 )
  635. if ( (vid_fd = open( device.c_str(), O_RDWR, 0 )) < 0 )
  636. Fatal( "Failed to open video device %s: %s", device.c_str(), strerror(errno) );
  637.  
  638. #if ZM_HAS_V4L2
  639. Debug( 2, "V4L2 support enabled, using V4L%d api", v4l_version );
  640. if ( v4l_version == 2 )
  641. {
  642. struct v4l2_capability vid_cap;
  643.  
  644. Debug( 3, "Checking video device capabilities" );
  645. if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 )
  646. Fatal( "Failed to query video device: %s", strerror(errno) );
  647.  
  648. if ( !(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) )
  649. Fatal( "Video device is not video capture device" );
  650.  
  651. if ( !(vid_cap.capabilities & V4L2_CAP_STREAMING) )
  652. Fatal( "Video device does not support streaming i/o" );
  653.  
  654. Debug( 3, "Setting up video format" );
  655.  
  656. memset( &v4l2_data.fmt, 0, sizeof(v4l2_data.fmt) );
  657. v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  658.  
  659. if ( vidioctl( vid_fd, VIDIOC_G_FMT, &v4l2_data.fmt ) < 0 )
  660. Fatal( "Failed to get video format: %s", strerror(errno) );
  661.  
  662. Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type );
  663. Debug( 4, " v4l2_data.fmt.fmt.pix.width = %08x", v4l2_data.fmt.fmt.pix.width );
  664. Debug( 4, " v4l2_data.fmt.fmt.pix.height = %08x", v4l2_data.fmt.fmt.pix.height );
  665. Debug( 4, " v4l2_data.fmt.fmt.pix.pixelformat = %08x", v4l2_data.fmt.fmt.pix.pixelformat );
  666. Debug( 4, " v4l2_data.fmt.fmt.pix.field = %08x", v4l2_data.fmt.fmt.pix.field );
  667. Debug( 4, " v4l2_data.fmt.fmt.pix.bytesperline = %08x", v4l2_data.fmt.fmt.pix.bytesperline );
  668. Debug( 4, " v4l2_data.fmt.fmt.pix.sizeimage = %08x", v4l2_data.fmt.fmt.pix.sizeimage );
  669. Debug( 4, " v4l2_data.fmt.fmt.pix.colorspace = %08x", v4l2_data.fmt.fmt.pix.colorspace );
  670. Debug( 4, " v4l2_data.fmt.fmt.pix.priv = %08x", v4l2_data.fmt.fmt.pix.priv );
  671.  
  672. v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  673. v4l2_data.fmt.fmt.pix.width = width;
  674. v4l2_data.fmt.fmt.pix.height = height;
  675. v4l2_data.fmt.fmt.pix.pixelformat = palette;
  676.  
  677. if ( config.v4l2_capture_fields )
  678. {
  679. v4l2_data.fmt.fmt.pix.field = (v4l2_field)config.v4l2_capture_fields;
  680. if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 )
  681. {
  682. Warning( "Failed to set V4L2 field to %d, falling back to auto", config.v4l2_capture_fields );
  683. v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY;
  684. }
  685. }
  686. if ( vidioctl( vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt ) < 0 )
  687. Fatal( "Failed to set video format: %s", strerror(errno) );
  688.  
  689. /* Note VIDIOC_S_FMT may change width and height. */
  690. Debug( 4, " v4l2_data.fmt.type = %08x", v4l2_data.fmt.type );
  691. Debug( 4, " v4l2_data.fmt.fmt.pix.width = %08x", v4l2_data.fmt.fmt.pix.width );
  692. Debug( 4, " v4l2_data.fmt.fmt.pix.height = %08x", v4l2_data.fmt.fmt.pix.height );
  693. Debug( 4, " v4l2_data.fmt.fmt.pix.pixelformat = %08x", v4l2_data.fmt.fmt.pix.pixelformat );
  694. Debug( 4, " v4l2_data.fmt.fmt.pix.field = %08x", v4l2_data.fmt.fmt.pix.field );
  695. Debug( 4, " v4l2_data.fmt.fmt.pix.bytesperline = %08x", v4l2_data.fmt.fmt.pix.bytesperline );
  696. Debug( 4, " v4l2_data.fmt.fmt.pix.sizeimage = %08x", v4l2_data.fmt.fmt.pix.sizeimage );
  697. Debug( 4, " v4l2_data.fmt.fmt.pix.colorspace = %08x", v4l2_data.fmt.fmt.pix.colorspace );
  698. Debug( 4, " v4l2_data.fmt.fmt.pix.priv = %08x", v4l2_data.fmt.fmt.pix.priv );
  699.  
  700. /* Buggy driver paranoia. */
  701. unsigned int min;
  702. min = v4l2_data.fmt.fmt.pix.width * 2;
  703. if (v4l2_data.fmt.fmt.pix.bytesperline < min)
  704. v4l2_data.fmt.fmt.pix.bytesperline = min;
  705. min = v4l2_data.fmt.fmt.pix.bytesperline * v4l2_data.fmt.fmt.pix.height;
  706. if (v4l2_data.fmt.fmt.pix.sizeimage < min)
  707. v4l2_data.fmt.fmt.pix.sizeimage = min;
  708.  
  709. Debug( 3, "Setting up request buffers" );
  710.  
  711. memset( &v4l2_data.reqbufs, 0, sizeof(v4l2_data.reqbufs) );
  712. if ( channel_count > 1 )
  713. if ( config.v4l_multi_buffer )
  714. v4l2_data.reqbufs.count = 2*channel_count;
  715. else
  716. v4l2_data.reqbufs.count = 1;
  717. else
  718. v4l2_data.reqbufs.count = 8;
  719. v4l2_data.reqbufs.type = v4l2_data.fmt.type;
  720. v4l2_data.reqbufs.memory = V4L2_MEMORY_MMAP;
  721.  
  722. if ( vidioctl( vid_fd, VIDIOC_REQBUFS, &v4l2_data.reqbufs ) < 0 )
  723. {
  724. if ( errno == EINVAL )
  725. {
  726. Fatal( "Unable to initialise memory mapping, unsupported in device" );
  727. }
  728. else
  729. {
  730. Fatal( "Unable to initialise memory mapping: %s", strerror(errno) );
  731. }
  732. }
  733.  
  734. if ( v4l2_data.reqbufs.count < (config.v4l_multi_buffer?2:1) )
  735. Fatal( "Insufficient buffer memory %d on video device", v4l2_data.reqbufs.count );
  736.  
  737. Debug( 3, "Setting up %d data buffers", v4l2_data.reqbufs.count );
  738.  
  739. v4l2_data.buffers = new V4L2MappedBuffer[v4l2_data.reqbufs.count];
  740. #if HAVE_LIBSWSCALE
  741. capturePictures = new AVFrame *[v4l2_data.reqbufs.count];
  742. #endif // HAVE_LIBSWSCALE
  743. for ( int i = 0; i < v4l2_data.reqbufs.count; i++ )
  744. {
  745. struct v4l2_buffer vid_buf;
  746.  
  747. memset( &vid_buf, 0, sizeof(vid_buf) );
  748.  
  749. //vid_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  750. vid_buf.type = v4l2_data.fmt.type;
  751. //vid_buf.memory = V4L2_MEMORY_MMAP;
  752. vid_buf.memory = v4l2_data.reqbufs.memory;
  753. vid_buf.index = i;
  754.  
  755. if ( vidioctl( vid_fd, VIDIOC_QUERYBUF, &vid_buf ) < 0 )
  756. Fatal( "Unable to query video buffer: %s", strerror(errno) );
  757.  
  758. v4l2_data.buffers[i].length = vid_buf.length;
  759. v4l2_data.buffers[i].start = mmap( NULL, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset );
  760.  
  761. if ( v4l2_data.buffers[i].start == MAP_FAILED )
  762. Fatal( "Can't map video buffer %d (%d bytes) to memory: %s(%d)", i, vid_buf.length, strerror(errno), errno );
  763.  
  764. #if HAVE_LIBSWSCALE
  765. capturePictures[i] = avcodec_alloc_frame();
  766. if ( !capturePictures[i] )
  767. Fatal( "Could not allocate picture" );
  768. avpicture_fill( (AVPicture *)capturePictures[i], (uint8_t*)v4l2_data.buffers[i].start, capturePixFormat, v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height );
  769. #endif // HAVE_LIBSWSCALE
  770. }
  771.  
  772. Debug( 3, "Configuring video source" );
  773.  
  774. if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channel ) < 0 )
  775. {
  776. Fatal( "Failed to set camera source %d: %s", channel, strerror(errno) );
  777. }
  778.  
  779. struct v4l2_input input;
  780. v4l2_std_id stdId;
  781.  
  782. memset( &input, 0, sizeof(input) );
  783.  
  784. if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 )
  785. {
  786. Fatal( "Failed to enumerate input %d: %s", channel, strerror(errno) );
  787. }
  788.  
  789. if ( (input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN) )
  790. {
  791. Fatal( "Device does not support video standard %d", standard );
  792. }
  793.  
  794. stdId = standard;
  795. if ( (input.std != V4L2_STD_UNKNOWN) && vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 )
  796. {
  797. Fatal( "Failed to set video standard %d: %s", standard, strerror(errno) );
  798. }
  799.  
  800. Contrast(contrast);
  801. Brightness(brightness);
  802. Hue(hue);
  803. Colour(colour);
  804. }
  805. #endif // ZM_HAS_V4L2
  806. #if ZM_HAS_V4L1
  807. if ( v4l_version == 1 )
  808. {
  809. Debug( 3, "Configuring picture attributes" );
  810.  
  811. struct video_picture vid_pic;
  812. memset( &vid_pic, 0, sizeof(vid_pic) );
  813. if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
  814. Fatal( "Failed to get picture attributes: %s", strerror(errno) );
  815.  
  816. Debug( 4, "Old P:%d", vid_pic.palette );
  817. Debug( 4, "Old D:%d", vid_pic.depth );
  818. Debug( 4, "Old B:%d", vid_pic.brightness );
  819. Debug( 4, "Old h:%d", vid_pic.hue );
  820. Debug( 4, "Old Cl:%d", vid_pic.colour );
  821. Debug( 4, "Old Cn:%d", vid_pic.contrast );
  822.  
  823. switch (vid_pic.palette = palette)
  824. {
  825. case VIDEO_PALETTE_RGB32 :
  826. {
  827. vid_pic.depth = 32;
  828. break;
  829. }
  830. case VIDEO_PALETTE_RGB24 :
  831. {
  832. vid_pic.depth = 24;
  833. break;
  834. }
  835. case VIDEO_PALETTE_GREY :
  836. {
  837. vid_pic.depth = 8;
  838. break;
  839. }
  840. case VIDEO_PALETTE_RGB565 :
  841. case VIDEO_PALETTE_YUYV :
  842. case VIDEO_PALETTE_YUV422 :
  843. case VIDEO_PALETTE_YUV420P :
  844. case VIDEO_PALETTE_YUV422P :
  845. default:
  846. {
  847. vid_pic.depth = 16;
  848. break;
  849. }
  850. }
  851.  
  852. if ( brightness >= 0 ) vid_pic.brightness = brightness;
  853. if ( hue >= 0 ) vid_pic.hue = hue;
  854. if ( colour >= 0 ) vid_pic.colour = colour;
  855. if ( contrast >= 0 ) vid_pic.contrast = contrast;
  856.  
  857. if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 )
  858. {
  859. Error( "Failed to set picture attributes: %s", strerror(errno) );
  860. if ( config.strict_video_config )
  861. exit(-1);
  862. }
  863.  
  864. Debug( 3, "Configuring window attributes" );
  865.  
  866. struct video_window vid_win;
  867. memset( &vid_win, 0, sizeof(vid_win) );
  868. if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win) < 0 )
  869. {
  870. Error( "Failed to get window attributes: %s", strerror(errno) );
  871. exit(-1);
  872. }
  873. Debug( 4, "Old X:%d", vid_win.x );
  874. Debug( 4, "Old Y:%d", vid_win.y );
  875. Debug( 4, "Old W:%d", vid_win.width );
  876. Debug( 4, "Old H:%d", vid_win.height );
  877.  
  878. vid_win.x = 0;
  879. vid_win.y = 0;
  880. vid_win.width = width;
  881. vid_win.height = height;
  882. vid_win.flags &= ~VIDEO_WINDOW_INTERLACE;
  883.  
  884. if ( ioctl( vid_fd, VIDIOCSWIN, &vid_win ) < 0 )
  885. {
  886. Error( "Failed to set window attributes: %s", strerror(errno) );
  887. if ( config.strict_video_config )
  888. exit(-1);
  889. }
  890.  
  891. Info( "vid_win.width = %08x", vid_win.width );
  892. Info( "vid_win.height = %08x", vid_win.height );
  893. Info( "vid_win.flags = %08x", vid_win.flags );
  894.  
  895. Debug( 3, "Setting up request buffers" );
  896. if ( ioctl( vid_fd, VIDIOCGMBUF, &v4l1_data.frames ) < 0 )
  897. Fatal( "Failed to setup memory: %s", strerror(errno) );
  898. if ( channel_count > 1 && !config.v4l_multi_buffer )
  899. v4l1_data.frames.frames = 1;
  900. v4l1_data.buffers = new video_mmap[v4l1_data.frames.frames];
  901. Debug( 4, "vmb.frames = %d", v4l1_data.frames.frames );
  902. Debug( 4, "vmb.size = %d", v4l1_data.frames.size );
  903.  
  904. Debug( 3, "Setting up %d frame buffers", v4l1_data.frames.frames );
  905.  
  906. v4l1_data.bufptr = (unsigned char *)mmap( 0, v4l1_data.frames.size, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, 0 );
  907. if ( v4l1_data.bufptr == MAP_FAILED )
  908. Fatal( "Could not mmap video: %s", strerror(errno) );
  909.  
  910. #if HAVE_LIBSWSCALE
  911. capturePictures = new AVFrame *[v4l1_data.frames.frames];
  912. for ( int i = 0; i < v4l1_data.frames.frames; i++ )
  913. {
  914. v4l1_data.buffers[i].frame = i;
  915. v4l1_data.buffers[i].width = width;
  916. v4l1_data.buffers[i].height = height;
  917. v4l1_data.buffers[i].format = palette;
  918.  
  919. capturePictures[i] = avcodec_alloc_frame();
  920. if ( !capturePictures[i] )
  921. Fatal( "Could not allocate picture" );
  922. avpicture_fill( (AVPicture *)capturePictures[i], (unsigned char *)v4l1_data.bufptr+v4l1_data.frames.offsets[i], capturePixFormat, width, height );
  923. }
  924. #endif // HAVE_LIBSWSCALE
  925.  
  926. Debug( 3, "Configuring video source" );
  927.  
  928. struct video_channel vid_src;
  929. memset( &vid_src, 0, sizeof(vid_src) );
  930. vid_src.channel = channel;
  931. if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src) < 0 )
  932. Fatal( "Failed to get camera source: %s", strerror(errno) );
  933.  
  934. Debug( 4, "Old C:%d", vid_src.channel );
  935. Debug( 4, "Old F:%d", vid_src.norm );
  936. Debug( 4, "Old Fl:%x", vid_src.flags );
  937. Debug( 4, "Old T:%d", vid_src.type );
  938.  
  939. vid_src.norm = standard;
  940. vid_src.flags = 0;
  941. vid_src.type = VIDEO_TYPE_CAMERA;
  942. if ( ioctl( vid_fd, VIDIOCSCHAN, &vid_src ) < 0 )
  943. {
  944. Error( "Failed to set camera source %d: %s", channel, strerror(errno) );
  945. if ( config.strict_video_config )
  946. exit(-1);
  947. }
  948.  
  949. if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win) < 0 )
  950. Fatal( "Failed to get window data: %s", strerror(errno) );
  951.  
  952. Info( "vid_win.width = %08x", vid_win.width );
  953. Info( "vid_win.height = %08x", vid_win.height );
  954. Info( "vid_win.flags = %08x", vid_win.flags );
  955.  
  956. Debug( 4, "New X:%d", vid_win.x );
  957. Debug( 4, "New Y:%d", vid_win.y );
  958. Debug( 4, "New W:%d", vid_win.width );
  959. Debug( 4, "New H:%d", vid_win.height );
  960.  
  961. if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
  962. Fatal( "Failed to get window data: %s", strerror(errno) );
  963.  
  964. Debug( 4, "New P:%d", vid_pic.palette );
  965. Debug( 4, "New D:%d", vid_pic.depth );
  966. Debug( 4, "New B:%d", vid_pic.brightness );
  967. Debug( 4, "New h:%d", vid_pic.hue );
  968. Debug( 4, "New Cl:%d", vid_pic.colour );
  969. Debug( 4, "New Cn:%d", vid_pic.contrast );
  970. }
  971. #endif // ZM_HAS_V4L1
  972. }
  973.  
  974. void LocalCamera::Terminate()
  975. {
  976. #if ZM_HAS_V4L2
  977. if ( v4l_version == 2 )
  978. {
  979. Debug( 3, "Terminating video stream" );
  980. //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  981. enum v4l2_buf_type type = v4l2_data.fmt.type;
  982. if ( vidioctl( vid_fd, VIDIOC_STREAMOFF, &type ) < 0 )
  983. Error( "Failed to stop capture stream: %s", strerror(errno) );
  984.  
  985. Debug( 3, "Unmapping video buffers" );
  986. for ( int i = 0; i < v4l2_data.reqbufs.count; i++ ) {
  987. #if HAVE_LIBSWSCALE
  988. /* Free capture pictures */
  989. av_free(capturePictures[i]);
  990. capturePictures[i] = NULL;
  991. #endif
  992. if ( munmap( v4l2_data.buffers[i].start, v4l2_data.buffers[i].length ) < 0 )
  993. Error( "Failed to munmap buffer %d: %s", i, strerror(errno) );
  994. }
  995.  
  996. }
  997. else
  998. #endif // ZM_HAS_V4L2
  999.  
  1000.  
  1001. #if ZM_HAS_V4L1
  1002. if ( v4l_version == 1 )
  1003. {
  1004. #if HAVE_LIBSWSCALE
  1005. for(unsigned int i=0; i < v4l1_data.frames.frames; i++) {
  1006. /* Free capture pictures */
  1007. av_free(capturePictures[i]);
  1008. capturePictures[i] = NULL;
  1009. }
  1010. #endif
  1011.  
  1012. Debug( 3, "Unmapping video buffers" );
  1013. if ( munmap((char*)v4l1_data.bufptr, v4l1_data.frames.size) < 0 )
  1014. Error( "Failed to munmap buffers: %s", strerror(errno) );
  1015.  
  1016. delete[] v4l1_data.buffers;
  1017. }
  1018. #endif // ZM_HAS_V4L1
  1019.  
  1020. close( vid_fd );
  1021.  
  1022. }
  1023.  
  1024. #define capString(test,prefix,yesString,noString,capability) \
  1025. (test) ? (prefix yesString " " capability "\n") : (prefix noString " " capability "\n")
  1026.  
  1027. bool LocalCamera::GetCurrentSettings( const char *device, char *output, int version, bool verbose )
  1028. {
  1029. output[0] = 0;
  1030.  
  1031. char queryDevice[PATH_MAX] = "";
  1032. int devIndex = 0;
  1033. do
  1034. {
  1035. if ( device )
  1036. strcpy( queryDevice, device );
  1037. else
  1038. sprintf( queryDevice, "/dev/video%d", devIndex );
  1039. if ( (vid_fd = open(queryDevice, O_RDWR)) <= 0 )
  1040. {
  1041. if ( device )
  1042. {
  1043. Error( "Failed to open video device %s: %s", queryDevice, strerror(errno) );
  1044. if ( verbose )
  1045. sprintf( output+strlen(output), "Error, failed to open video device %s: %s\n", queryDevice, strerror(errno) );
  1046. else
  1047. sprintf( output+strlen(output), "error%d\n", errno );
  1048. return( false );
  1049. }
  1050. else
  1051. {
  1052. return( true );
  1053. }
  1054. }
  1055. if ( verbose )
  1056. sprintf( output+strlen(output), "Video Device: %s\n", queryDevice );
  1057. else
  1058. sprintf( output+strlen(output), "d:%s|", queryDevice );
  1059.  
  1060. #if ZM_HAS_V4L2
  1061. if ( version == 2 )
  1062. {
  1063. struct v4l2_capability vid_cap;
  1064. if ( vidioctl( vid_fd, VIDIOC_QUERYCAP, &vid_cap ) < 0 )
  1065. {
  1066. Error( "Failed to query video device: %s", strerror(errno) );
  1067. if ( verbose )
  1068. sprintf( output, "Error, failed to query video capabilities %s: %s\n", queryDevice, strerror(errno) );
  1069. else
  1070. sprintf( output, "error%d\n", errno );
  1071. return( false );
  1072. }
  1073.  
  1074. if ( verbose )
  1075. {
  1076. sprintf( output+strlen(output), "General Capabilities\n" );
  1077. sprintf( output+strlen(output), " Driver: %s\n", vid_cap.driver );
  1078. sprintf( output+strlen(output), " Card: %s\n", vid_cap.card );
  1079. sprintf( output+strlen(output), " Bus: %s\n", vid_cap.bus_info );
  1080. sprintf( output+strlen(output), " Version: %u.%u.%u\n", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff );
  1081. sprintf( output+strlen(output), " Type: 0x%x\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.capabilities,
  1082. capString( vid_cap.capabilities&V4L2_CAP_VIDEO_CAPTURE, " ", "Supports", "Does not support", "video capture (X)" ),
  1083. capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT, " ", "Supports", "Does not support", "video output" ),
  1084. capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OVERLAY, " ", "Supports", "Does not support", "frame buffer overlay" ),
  1085. capString( vid_cap.capabilities&V4L2_CAP_VBI_CAPTURE, " ", "Supports", "Does not support", "VBI capture" ),
  1086. capString( vid_cap.capabilities&V4L2_CAP_VBI_OUTPUT, " ", "Supports", "Does not support", "VBI output" ),
  1087. capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_CAPTURE, " ", "Supports", "Does not support", "sliced VBI capture" ),
  1088. capString( vid_cap.capabilities&V4L2_CAP_SLICED_VBI_OUTPUT, " ", "Supports", "Does not support", "sliced VBI output" ),
  1089. #ifdef V4L2_CAP_VIDEO_OUTPUT_OVERLAY
  1090. capString( vid_cap.capabilities&V4L2_CAP_VIDEO_OUTPUT_OVERLAY, " ", "Supports", "Does not support", "video output overlay" ),
  1091. #else // V4L2_CAP_VIDEO_OUTPUT_OVERLAY
  1092. "",
  1093. #endif // V4L2_CAP_VIDEO_OUTPUT_OVERLAY
  1094. capString( vid_cap.capabilities&V4L2_CAP_TUNER, " ", "Has", "Does not have", "tuner" ),
  1095. capString( vid_cap.capabilities&V4L2_CAP_AUDIO, " ", "Has", "Does not have", "audio in and/or out" ),
  1096. capString( vid_cap.capabilities&V4L2_CAP_RADIO, " ", "Has", "Does not have", "radio" ),
  1097. capString( vid_cap.capabilities&V4L2_CAP_READWRITE, " ", "Supports", "Does not support", "read/write i/o (X)" ),
  1098. capString( vid_cap.capabilities&V4L2_CAP_ASYNCIO, " ", "Supports", "Does not support", "async i/o" ),
  1099. capString( vid_cap.capabilities&V4L2_CAP_STREAMING, " ", "Supports", "Does not support", "streaming i/o (X)" )
  1100. );
  1101. }
  1102. else
  1103. {
  1104. sprintf( output+strlen(output), "D:%s|", vid_cap.driver );
  1105. sprintf( output+strlen(output), "C:%s|", vid_cap.card );
  1106. sprintf( output+strlen(output), "B:%s|", vid_cap.bus_info );
  1107. sprintf( output+strlen(output), "V:%u.%u.%u|", (vid_cap.version>>16)&0xff, (vid_cap.version>>8)&0xff, vid_cap.version&0xff );
  1108. sprintf( output+strlen(output), "T:0x%x|", vid_cap.capabilities );
  1109. }
  1110.  
  1111. if ( verbose )
  1112. sprintf( output+strlen(output), " Standards:\n" );
  1113. else
  1114. sprintf( output+strlen(output), "S:" );
  1115. struct v4l2_standard standard;
  1116. int standardIndex = 0;
  1117. do
  1118. {
  1119. memset( &standard, 0, sizeof(standard) );
  1120. standard.index = standardIndex;
  1121.  
  1122. if ( vidioctl( vid_fd, VIDIOC_ENUMSTD, &standard ) < 0 )
  1123. {
  1124. if ( errno == EINVAL )
  1125. {
  1126. standardIndex = -1;
  1127. break;
  1128. }
  1129. else
  1130. {
  1131. Error( "Failed to enumerate standard %d: %s", standard.index, strerror(errno) );
  1132. if ( verbose )
  1133. sprintf( output, "Error, failed to enumerate standard %d: %s\n", standard.index, strerror(errno) );
  1134. else
  1135. sprintf( output, "error%d\n", errno );
  1136. return( false );
  1137. }
  1138. }
  1139. if ( verbose )
  1140. sprintf( output+strlen(output), " %s\n", standard.name );
  1141. else
  1142. sprintf( output+strlen(output), "%s/", standard.name );
  1143. }
  1144. while ( standardIndex++ >= 0 );
  1145. if ( !verbose && output[strlen(output)-1] == '/')
  1146. output[strlen(output)-1] = '|';
  1147.  
  1148. if ( verbose )
  1149. sprintf( output+strlen(output), " Formats:\n" );
  1150. else
  1151. sprintf( output+strlen(output), "F:" );
  1152. struct v4l2_fmtdesc format;
  1153. int formatIndex = 0;
  1154. do
  1155. {
  1156. memset( &format, 0, sizeof(format) );
  1157. format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1158. format.index = formatIndex;
  1159.  
  1160. if ( vidioctl( vid_fd, VIDIOC_ENUM_FMT, &format ) < 0 )
  1161. {
  1162. if ( errno == EINVAL )
  1163. {
  1164. formatIndex = -1;
  1165. break;
  1166. }
  1167. else
  1168. {
  1169. Error( "Failed to enumerate format %d: %s", format.index, strerror(errno) );
  1170. if ( verbose )
  1171. sprintf( output, "Error, failed to enumerate format %d: %s\n", format.index, strerror(errno) );
  1172. else
  1173. sprintf( output, "error%d\n", errno );
  1174. return( false );
  1175. }
  1176. }
  1177. if ( verbose )
  1178. sprintf( output+strlen(output), " %s (%c%c%c%c)\n", format.description, format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff );
  1179. else
  1180. sprintf( output+strlen(output), "%c%c%c%c/", format.pixelformat&0xff, (format.pixelformat>>8)&0xff, (format.pixelformat>>16)&0xff, (format.pixelformat>>24)&0xff );
  1181. }
  1182. while ( formatIndex++ >= 0 );
  1183. if ( !verbose )
  1184. output[strlen(output)-1] = '|';
  1185.  
  1186. struct v4l2_cropcap cropcap;
  1187. memset( &cropcap, 0, sizeof(cropcap) );
  1188. cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1189. if ( vidioctl( vid_fd, VIDIOC_CROPCAP, &cropcap ) < 0 )
  1190. {
  1191. if(errno != EINVAL) {
  1192. /* Failed querying crop capability, write error to the log and continue as if crop is not supported */
  1193. Error( "Failed to query crop capabilities: %s", strerror(errno) );
  1194. }
  1195.  
  1196. if(verbose) {
  1197. sprintf( output+strlen(output), "Cropping is not supported");
  1198. } else {
  1199. /* Send fake crop bounds to not confuse things parsing this, such as monitor probe */
  1200. sprintf( output+strlen(output), "B:%dx%d|",0,0);
  1201. }
  1202. } else {
  1203. struct v4l2_crop crop;
  1204. memset( &crop, 0, sizeof(crop) );
  1205. crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1206.  
  1207. if ( vidioctl( vid_fd, VIDIOC_G_CROP, &crop ) < 0 )
  1208. {
  1209. if ( errno != EINVAL )
  1210. {
  1211. /* Failed querying crop sizes, write error to the log and continue as if crop is not supported */
  1212. Error( "Failed to query crop: %s", strerror(errno) );
  1213. }
  1214.  
  1215. if ( verbose ) {
  1216. sprintf( output+strlen(output), "Cropping is not supported");
  1217. } else {
  1218. /* Send fake crop bounds to not confuse things parsing this, such as monitor probe */
  1219. sprintf( output+strlen(output), "B:%dx%d|",0,0);
  1220. }
  1221. } else {
  1222. /* Cropping supported */
  1223. if ( verbose ) {
  1224. sprintf( output+strlen(output), "Crop Capabilities\n" );
  1225. sprintf( output+strlen(output), " Bounds: %d x %d\n", cropcap.bounds.width, cropcap.bounds.height );
  1226. sprintf( output+strlen(output), " Default: %d x %d\n", cropcap.defrect.width, cropcap.defrect.height );
  1227. sprintf( output+strlen(output), " Current: %d x %d\n", crop.c.width, crop.c.height );
  1228. } else {
  1229. sprintf( output+strlen(output), "B:%dx%d|", cropcap.bounds.width, cropcap.bounds.height );
  1230. }
  1231. }
  1232. } /* Crop code */
  1233.  
  1234. struct v4l2_input input;
  1235. int inputIndex = 0;
  1236. do
  1237. {
  1238. memset( &input, 0, sizeof(input) );
  1239. input.index = inputIndex;
  1240.  
  1241. if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 )
  1242. {
  1243. if ( errno == EINVAL )
  1244. {
  1245. break;
  1246. }
  1247. else
  1248. {
  1249. Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) );
  1250. if ( verbose )
  1251. sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) );
  1252. else
  1253. sprintf( output, "error%d\n", errno );
  1254. return( false );
  1255. }
  1256. }
  1257. }
  1258. while ( inputIndex++ >= 0 );
  1259.  
  1260. if ( verbose )
  1261. sprintf( output+strlen(output), "Inputs: %d\n", inputIndex );
  1262. else
  1263. sprintf( output+strlen(output), "I:%d|", inputIndex );
  1264.  
  1265. inputIndex = 0;
  1266. do
  1267. {
  1268. memset( &input, 0, sizeof(input) );
  1269. input.index = inputIndex;
  1270.  
  1271. if ( vidioctl( vid_fd, VIDIOC_ENUMINPUT, &input ) < 0 )
  1272. {
  1273. if ( errno == EINVAL )
  1274. {
  1275. inputIndex = -1;
  1276. break;
  1277. }
  1278. else
  1279. {
  1280. Error( "Failed to enumerate input %d: %s", input.index, strerror(errno) );
  1281. if ( verbose )
  1282. sprintf( output, "Error, failed to enumerate input %d: %s\n", input.index, strerror(errno) );
  1283. else
  1284. sprintf( output, "error%d\n", errno );
  1285. return( false );
  1286. }
  1287. }
  1288.  
  1289. if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &input.index ) < 0 )
  1290. {
  1291. Error( "Failed to set video input %d: %s", input.index, strerror(errno) );
  1292. if ( verbose )
  1293. sprintf( output, "Error, failed to switch to input %d: %s\n", input.index, strerror(errno) );
  1294. else
  1295. sprintf( output, "error%d\n", errno );
  1296. return( false );
  1297. }
  1298.  
  1299. if ( verbose )
  1300. {
  1301. sprintf( output+strlen(output), " Input %d\n", input.index );
  1302. sprintf( output+strlen(output), " Name: %s\n", input.name );
  1303. sprintf( output+strlen(output), " Type: %s\n", input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
  1304. sprintf( output+strlen(output), " Audioset: %08x\n", input.audioset );
  1305. sprintf( output+strlen(output), " Standards: 0x%llx\n", input.std );
  1306. }
  1307. else
  1308. {
  1309. sprintf( output+strlen(output), "i%d:%s|", input.index, input.name );
  1310. sprintf( output+strlen(output), "i%dT:%s|", input.index, input.type==V4L2_INPUT_TYPE_TUNER?"Tuner":(input.type==V4L2_INPUT_TYPE_CAMERA?"Camera":"Unknown") );
  1311. sprintf( output+strlen(output), "i%dS:%llx|", input.index, input.std );
  1312. }
  1313.  
  1314. if ( verbose )
  1315. {
  1316. sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_POWER, "Power ", "off", "on", " (X)" ) );
  1317. sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_SIGNAL, "Signal ", "not detected", "detected", " (X)" ) );
  1318. sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_COLOR, "Colour Signal ", "not detected", "detected", "" ) );
  1319. sprintf( output+strlen(output), " %s", capString( input.status&V4L2_IN_ST_NO_H_LOCK, "Horizontal Lock ", "not detected", "detected", "" ) );
  1320. }
  1321. else
  1322. {
  1323. sprintf( output+strlen(output), "i%dSP:%d|", input.index, input.status&V4L2_IN_ST_NO_POWER?0:1 );
  1324. sprintf( output+strlen(output), "i%dSS:%d|", input.index, input.status&V4L2_IN_ST_NO_SIGNAL?0:1 );
  1325. sprintf( output+strlen(output), "i%dSC:%d|", input.index, input.status&V4L2_IN_ST_NO_COLOR?0:1 );
  1326. sprintf( output+strlen(output), "i%dHP:%d|", input.index, input.status&V4L2_IN_ST_NO_H_LOCK?0:1 );
  1327. }
  1328. }
  1329. while ( inputIndex++ >= 0 );
  1330. if ( !verbose )
  1331. output[strlen(output)-1] = '\n';
  1332. }
  1333. #endif // ZM_HAS_V4L2
  1334. #if ZM_HAS_V4L1
  1335. if ( version == 1 )
  1336. {
  1337. struct video_capability vid_cap;
  1338. memset( &vid_cap, 0, sizeof(video_capability) );
  1339. if ( ioctl( vid_fd, VIDIOCGCAP, &vid_cap ) < 0 )
  1340. {
  1341. Error( "Failed to get video capabilities: %s", strerror(errno) );
  1342. if ( verbose )
  1343. sprintf( output, "Error, failed to get video capabilities %s: %s\n", queryDevice, strerror(errno) );
  1344. else
  1345. sprintf( output, "error%d\n", errno );
  1346. return( false );
  1347. }
  1348. if ( verbose )
  1349. {
  1350. sprintf( output+strlen(output), "Video Capabilities\n" );
  1351. sprintf( output+strlen(output), " Name: %s\n", vid_cap.name );
  1352. sprintf( output+strlen(output), " Type: %d\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s", vid_cap.type,
  1353. vid_cap.type&VID_TYPE_CAPTURE?" Can capture\n":"",
  1354. vid_cap.type&VID_TYPE_TUNER?" Can tune\n":"",
  1355. vid_cap.type&VID_TYPE_TELETEXT?" Does teletext\n":"",
  1356. vid_cap.type&VID_TYPE_OVERLAY?" Overlay onto frame buffer\n":"",
  1357. vid_cap.type&VID_TYPE_CHROMAKEY?" Overlay by chromakey\n":"",
  1358. vid_cap.type&VID_TYPE_CLIPPING?" Can clip\n":"",
  1359. vid_cap.type&VID_TYPE_FRAMERAM?" Uses the frame buffer memory\n":"",
  1360. vid_cap.type&VID_TYPE_SCALES?" Scalable\n":"",
  1361. vid_cap.type&VID_TYPE_MONOCHROME?" Monochrome only\n":"",
  1362. vid_cap.type&VID_TYPE_SUBCAPTURE?" Can capture subareas of the image\n":"",
  1363. vid_cap.type&VID_TYPE_MPEG_DECODER?" Can decode MPEG streams\n":"",
  1364. vid_cap.type&VID_TYPE_MPEG_ENCODER?" Can encode MPEG streams\n":"",
  1365. vid_cap.type&VID_TYPE_MJPEG_DECODER?" Can decode MJPEG streams\n":"",
  1366. vid_cap.type&VID_TYPE_MJPEG_ENCODER?" Can encode MJPEG streams\n":""
  1367. );
  1368. sprintf( output+strlen(output), " Video Channels: %d\n", vid_cap.channels );
  1369. sprintf( output+strlen(output), " Audio Channels: %d\n", vid_cap.audios );
  1370. sprintf( output+strlen(output), " Maximum Width: %d\n", vid_cap.maxwidth );
  1371. sprintf( output+strlen(output), " Maximum Height: %d\n", vid_cap.maxheight );
  1372. sprintf( output+strlen(output), " Minimum Width: %d\n", vid_cap.minwidth );
  1373. sprintf( output+strlen(output), " Minimum Height: %d\n", vid_cap.minheight );
  1374. }
  1375. else
  1376. {
  1377. sprintf( output+strlen(output), "N:%s|", vid_cap.name );
  1378. sprintf( output+strlen(output), "T:%d|", vid_cap.type );
  1379. sprintf( output+strlen(output), "nC:%d|", vid_cap.channels );
  1380. sprintf( output+strlen(output), "nA:%d|", vid_cap.audios );
  1381. sprintf( output+strlen(output), "mxW:%d|", vid_cap.maxwidth );
  1382. sprintf( output+strlen(output), "mxH:%d|", vid_cap.maxheight );
  1383. sprintf( output+strlen(output), "mnW:%d|", vid_cap.minwidth );
  1384. sprintf( output+strlen(output), "mnH:%d|", vid_cap.minheight );
  1385. }
  1386.  
  1387. struct video_window vid_win;
  1388. memset( &vid_win, 0, sizeof(video_window) );
  1389. if ( ioctl( vid_fd, VIDIOCGWIN, &vid_win ) < 0 )
  1390. {
  1391. Error( "Failed to get window attributes: %s", strerror(errno) );
  1392. if ( verbose )
  1393. sprintf( output, "Error, failed to get window attributes: %s\n", strerror(errno) );
  1394. else
  1395. sprintf( output, "error%d\n", errno );
  1396. return( false );
  1397. }
  1398. if ( verbose )
  1399. {
  1400. sprintf( output+strlen(output), "Window Attributes\n" );
  1401. sprintf( output+strlen(output), " X Offset: %d\n", vid_win.x );
  1402. sprintf( output+strlen(output), " Y Offset: %d\n", vid_win.y );
  1403. sprintf( output+strlen(output), " Width: %d\n", vid_win.width );
  1404. sprintf( output+strlen(output), " Height: %d\n", vid_win.height );
  1405. }
  1406. else
  1407. {
  1408. sprintf( output+strlen(output), "X:%d|", vid_win.x );
  1409. sprintf( output+strlen(output), "Y:%d|", vid_win.y );
  1410. sprintf( output+strlen(output), "W:%d|", vid_win.width );
  1411. sprintf( output+strlen(output), "H:%d|", vid_win.height );
  1412. }
  1413.  
  1414. struct video_picture vid_pic;
  1415. memset( &vid_cap, 0, sizeof(video_picture) );
  1416. if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic ) < 0 )
  1417. {
  1418. Error( "Failed to get picture attributes: %s", strerror(errno) );
  1419. if ( verbose )
  1420. sprintf( output, "Error, failed to get picture attributes: %s\n", strerror(errno) );
  1421. else
  1422. sprintf( output, "error%d\n", errno );
  1423. return( false );
  1424. }
  1425. if ( verbose )
  1426. {
  1427. sprintf( output+strlen(output), "Picture Attributes\n" );
  1428. sprintf( output+strlen(output), " Palette: %d - %s\n", vid_pic.palette,
  1429. vid_pic.palette==VIDEO_PALETTE_GREY?"Linear greyscale":(
  1430. vid_pic.palette==VIDEO_PALETTE_HI240?"High 240 cube (BT848)":(
  1431. vid_pic.palette==VIDEO_PALETTE_RGB565?"565 16 bit RGB":(
  1432. vid_pic.palette==VIDEO_PALETTE_RGB24?"24bit RGB":(
  1433. vid_pic.palette==VIDEO_PALETTE_RGB32?"32bit RGB":(
  1434. vid_pic.palette==VIDEO_PALETTE_RGB555?"555 15bit RGB":(
  1435. vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422 capture":(
  1436. vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":(
  1437. vid_pic.palette==VIDEO_PALETTE_UYVY?"UVYV":(
  1438. vid_pic.palette==VIDEO_PALETTE_YUV420?"YUV420":(
  1439. vid_pic.palette==VIDEO_PALETTE_YUV411?"YUV411 capture":(
  1440. vid_pic.palette==VIDEO_PALETTE_RAW?"RAW capture (BT848)":(
  1441. vid_pic.palette==VIDEO_PALETTE_YUYV?"YUYV":(
  1442. vid_pic.palette==VIDEO_PALETTE_YUV422?"YUV422":(
  1443. vid_pic.palette==VIDEO_PALETTE_YUV422P?"YUV 4:2:2 Planar":(
  1444. vid_pic.palette==VIDEO_PALETTE_YUV411P?"YUV 4:1:1 Planar":(
  1445. vid_pic.palette==VIDEO_PALETTE_YUV420P?"YUV 4:2:0 Planar":(
  1446. vid_pic.palette==VIDEO_PALETTE_YUV410P?"YUV 4:1:0 Planar":"Unknown"
  1447. ))))))))))))))))));
  1448. sprintf( output+strlen(output), " Colour Depth: %d\n", vid_pic.depth );
  1449. sprintf( output+strlen(output), " Brightness: %d\n", vid_pic.brightness );
  1450. sprintf( output+strlen(output), " Hue: %d\n", vid_pic.hue );
  1451. sprintf( output+strlen(output), " Colour :%d\n", vid_pic.colour );
  1452. sprintf( output+strlen(output), " Contrast: %d\n", vid_pic.contrast );
  1453. sprintf( output+strlen(output), " Whiteness: %d\n", vid_pic.whiteness );
  1454. }
  1455. else
  1456. {
  1457. sprintf( output+strlen(output), "P:%d|", vid_pic.palette );
  1458. sprintf( output+strlen(output), "D:%d|", vid_pic.depth );
  1459. sprintf( output+strlen(output), "B:%d|", vid_pic.brightness );
  1460. sprintf( output+strlen(output), "h:%d|", vid_pic.hue );
  1461. sprintf( output+strlen(output), "Cl:%d|", vid_pic.colour );
  1462. sprintf( output+strlen(output), "Cn:%d|", vid_pic.contrast );
  1463. sprintf( output+strlen(output), "w:%d|", vid_pic.whiteness );
  1464. }
  1465.  
  1466. for ( int chan = 0; chan < vid_cap.channels; chan++ )
  1467. {
  1468. struct video_channel vid_src;
  1469. memset( &vid_src, 0, sizeof(video_channel) );
  1470. vid_src.channel = chan;
  1471. if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src ) < 0 )
  1472. {
  1473. Error( "Failed to get channel %d attributes: %s", chan, strerror(errno) );
  1474. if ( verbose )
  1475. sprintf( output, "Error, failed to get channel %d attributes: %s\n", chan, strerror(errno) );
  1476. else
  1477. sprintf( output, "error%d\n", errno );
  1478. return( false );
  1479. }
  1480. if ( verbose )
  1481. {
  1482. sprintf( output+strlen(output), "Channel %d Attributes\n", chan );
  1483. sprintf( output+strlen(output), " Name: %s\n", vid_src.name );
  1484. sprintf( output+strlen(output), " Channel: %d\n", vid_src.channel );
  1485. sprintf( output+strlen(output), " Flags: %d\n%s%s", vid_src.flags,
  1486. vid_src.flags&VIDEO_VC_TUNER?" Channel has a tuner\n":"",
  1487. vid_src.flags&VIDEO_VC_AUDIO?" Channel has audio\n":""
  1488. );
  1489. sprintf( output+strlen(output), " Type: %d - %s\n", vid_src.type,
  1490. vid_src.type==VIDEO_TYPE_TV?"TV":(
  1491. vid_src.type==VIDEO_TYPE_CAMERA?"Camera":"Unknown"
  1492. ));
  1493. sprintf( output+strlen(output), " Format: %d - %s\n", vid_src.norm,
  1494. vid_src.norm==VIDEO_MODE_PAL?"PAL":(
  1495. vid_src.norm==VIDEO_MODE_NTSC?"NTSC":(
  1496. vid_src.norm==VIDEO_MODE_SECAM?"SECAM":(
  1497. vid_src.norm==VIDEO_MODE_AUTO?"AUTO":"Unknown"
  1498. ))));
  1499. }
  1500. else
  1501. {
  1502. sprintf( output+strlen(output), "n%d:%s|", chan, vid_src.name );
  1503. sprintf( output+strlen(output), "C%d:%d|", chan, vid_src.channel );
  1504. sprintf( output+strlen(output), "Fl%d:%x|", chan, vid_src.flags );
  1505. sprintf( output+strlen(output), "T%d:%d|", chan, vid_src.type );
  1506. sprintf( output+strlen(output), "F%d:%d%s|", chan, vid_src.norm, chan==(vid_cap.channels-1)?"":"," );
  1507. }
  1508. }
  1509. if ( !verbose )
  1510. output[strlen(output)-1] = '\n';
  1511. }
  1512. #endif // ZM_HAS_V4L1
  1513. close( vid_fd );
  1514. if ( device )
  1515. break;
  1516. }
  1517. while ( ++devIndex < 32 );
  1518. return( true );
  1519. }
  1520.  
  1521. int LocalCamera::Brightness( int p_brightness )
  1522. {
  1523. #if ZM_HAS_V4L2
  1524. if ( v4l_version == 2 )
  1525. {
  1526. struct v4l2_control vid_control;
  1527.  
  1528. memset( &vid_control, 0, sizeof(vid_control) );
  1529. vid_control.id = V4L2_CID_BRIGHTNESS;
  1530.  
  1531. if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 )
  1532. {
  1533. if ( errno != EINVAL )
  1534. Error( "Unable to query brightness: %s", strerror(errno) )
  1535. else
  1536. Warning( "Brightness control is not suppported" )
  1537. //Info( "Brightness 1 %d", vid_control.value );
  1538. }
  1539. else if ( p_brightness >= 0 )
  1540. {
  1541. vid_control.value = p_brightness;
  1542.  
  1543. //Info( "Brightness 2 %d", vid_control.value );
  1544. /* The driver may clamp the value or return ERANGE, ignored here */
  1545. if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) )
  1546. {
  1547. if ( errno != ERANGE )
  1548. Error( "Unable to set brightness: %s", strerror(errno) )
  1549. else
  1550. Warning( "Given brightness value (%d) may be out-of-range", p_brightness )
  1551. }
  1552. //Info( "Brightness 3 %d", vid_control.value );
  1553. }
  1554. return( vid_control.value );
  1555. }
  1556. #endif // ZM_HAS_V4L2
  1557. #if ZM_HAS_V4L1
  1558. if ( v4l_version == 1 )
  1559. {
  1560. struct video_picture vid_pic;
  1561. memset( &vid_pic, 0, sizeof(video_picture) );
  1562. if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
  1563. {
  1564. Error( "Failed to get picture attributes: %s", strerror(errno) );
  1565. return( -1 );
  1566. }
  1567.  
  1568. if ( p_brightness >= 0 )
  1569. {
  1570. vid_pic.brightness = p_brightness;
  1571. if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 )
  1572. {
  1573. Error( "Failed to set picture attributes: %s", strerror(errno) );
  1574. return( -1 );
  1575. }
  1576. }
  1577. return( vid_pic.brightness );
  1578. }
  1579. #endif // ZM_HAS_V4L1
  1580. return( -1 );
  1581. }
  1582.  
  1583. int LocalCamera::Hue( int p_hue )
  1584. {
  1585. #if ZM_HAS_V4L2
  1586. if ( v4l_version == 2 )
  1587. {
  1588. struct v4l2_control vid_control;
  1589.  
  1590. memset( &vid_control, 0, sizeof(vid_control) );
  1591. vid_control.id = V4L2_CID_HUE;
  1592.  
  1593. if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 )
  1594. {
  1595. if ( errno != EINVAL )
  1596. Error( "Unable to query hue: %s", strerror(errno) )
  1597. else
  1598. Warning( "Hue control is not suppported" )
  1599. }
  1600. else if ( p_hue >= 0 )
  1601. {
  1602. vid_control.value = p_hue;
  1603.  
  1604. /* The driver may clamp the value or return ERANGE, ignored here */
  1605. if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 )
  1606. {
  1607. if ( errno != ERANGE )
  1608. Error( "Unable to set hue: %s", strerror(errno) )
  1609. else
  1610. Warning( "Given hue value (%d) may be out-of-range", p_hue )
  1611. }
  1612. }
  1613. return( vid_control.value );
  1614. }
  1615. #endif // ZM_HAS_V4L2
  1616. #if ZM_HAS_V4L1
  1617. if ( v4l_version == 1 )
  1618. {
  1619. struct video_picture vid_pic;
  1620. memset( &vid_pic, 0, sizeof(video_picture) );
  1621. if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
  1622. {
  1623. Error( "Failed to get picture attributes: %s", strerror(errno) );
  1624. return( -1 );
  1625. }
  1626.  
  1627. if ( p_hue >= 0 )
  1628. {
  1629. vid_pic.hue = p_hue;
  1630. if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 )
  1631. {
  1632. Error( "Failed to set picture attributes: %s", strerror(errno) );
  1633. return( -1 );
  1634. }
  1635. }
  1636. return( vid_pic.hue );
  1637. }
  1638. #endif // ZM_HAS_V4L1
  1639. return( -1 );
  1640. }
  1641.  
  1642. int LocalCamera::Colour( int p_colour )
  1643. {
  1644. #if ZM_HAS_V4L2
  1645. if ( v4l_version == 2 )
  1646. {
  1647. struct v4l2_control vid_control;
  1648.  
  1649. memset( &vid_control, 0, sizeof(vid_control) );
  1650. vid_control.id = V4L2_CID_SATURATION;
  1651.  
  1652. if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 )
  1653. {
  1654. if ( errno != EINVAL )
  1655. Error( "Unable to query saturation: %s", strerror(errno) )
  1656. else
  1657. Warning( "Saturation control is not suppported" )
  1658. }
  1659. else if ( p_colour >= 0 )
  1660. {
  1661. vid_control.value = p_colour;
  1662.  
  1663. /* The driver may clamp the value or return ERANGE, ignored here */
  1664. if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) < 0 )
  1665. {
  1666. if ( errno != ERANGE )
  1667. Error( "Unable to set saturation: %s", strerror(errno) )
  1668. else
  1669. Warning( "Given saturation value (%d) may be out-of-range", p_colour )
  1670. }
  1671. }
  1672. return( vid_control.value );
  1673. }
  1674. #endif // ZM_HAS_V4L2
  1675. #if ZM_HAS_V4L1
  1676. if ( v4l_version == 1 )
  1677. {
  1678. struct video_picture vid_pic;
  1679. memset( &vid_pic, 0, sizeof(video_picture) );
  1680. if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
  1681. {
  1682. Error( "Failed to get picture attributes: %s", strerror(errno) );
  1683. return( -1 );
  1684. }
  1685.  
  1686. if ( p_colour >= 0 )
  1687. {
  1688. vid_pic.colour = p_colour;
  1689. if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 )
  1690. {
  1691. Error( "Failed to set picture attributes: %s", strerror(errno) );
  1692. return( -1 );
  1693. }
  1694. }
  1695. return( vid_pic.colour );
  1696. }
  1697. #endif // ZM_HAS_V4L1
  1698. return( -1 );
  1699. }
  1700.  
  1701. int LocalCamera::Contrast( int p_contrast )
  1702. {
  1703. #if ZM_HAS_V4L2
  1704. if ( v4l_version == 2 )
  1705. {
  1706. struct v4l2_control vid_control;
  1707.  
  1708. memset( &vid_control, 0, sizeof(vid_control) );
  1709. vid_control.id = V4L2_CID_CONTRAST;
  1710.  
  1711. if ( vidioctl( vid_fd, VIDIOC_G_CTRL, &vid_control ) < 0 )
  1712. {
  1713. if ( errno != EINVAL )
  1714. Error( "Unable to query contrast: %s", strerror(errno) )
  1715. else
  1716. Warning( "Contrast control is not suppported" )
  1717. }
  1718. else if ( p_contrast >= 0 )
  1719. {
  1720. vid_control.value = p_contrast;
  1721.  
  1722. /* The driver may clamp the value or return ERANGE, ignored here */
  1723. if ( vidioctl ( vid_fd, VIDIOC_S_CTRL, &vid_control ) )
  1724. {
  1725. if ( errno != ERANGE )
  1726. Error( "Unable to set contrast: %s", strerror(errno) )
  1727. else
  1728. Warning( "Given contrast value (%d) may be out-of-range", p_contrast )
  1729. }
  1730. }
  1731. return( vid_control.value );
  1732. }
  1733. #endif // ZM_HAS_V4L2
  1734. #if ZM_HAS_V4L1
  1735. if ( v4l_version == 1 )
  1736. {
  1737. struct video_picture vid_pic;
  1738. memset( &vid_pic, 0, sizeof(video_picture) );
  1739. if ( ioctl( vid_fd, VIDIOCGPICT, &vid_pic) < 0 )
  1740. {
  1741. Error( "Failed to get picture attributes: %s", strerror(errno) );
  1742. return( -1 );
  1743. }
  1744.  
  1745. if ( p_contrast >= 0 )
  1746. {
  1747. vid_pic.contrast = p_contrast;
  1748. if ( ioctl( vid_fd, VIDIOCSPICT, &vid_pic ) < 0 )
  1749. {
  1750. Error( "Failed to set picture attributes: %s", strerror(errno) );
  1751. return( -1 );
  1752. }
  1753. }
  1754. return( vid_pic.contrast );
  1755. }
  1756. #endif // ZM_HAS_V4L1
  1757. return( -1 );
  1758. }
  1759.  
  1760. int LocalCamera::PrimeCapture()
  1761. {
  1762. Initialise();
  1763.  
  1764. Debug( 2, "Priming capture" );
  1765. #if ZM_HAS_V4L2
  1766. if ( v4l_version == 2 )
  1767. {
  1768. Debug( 3, "Queueing buffers" );
  1769. for ( int frame = 0; frame < v4l2_data.reqbufs.count; frame++ )
  1770. {
  1771. struct v4l2_buffer vid_buf;
  1772.  
  1773. memset( &vid_buf, 0, sizeof(vid_buf) );
  1774.  
  1775. vid_buf.type = v4l2_data.fmt.type;
  1776. vid_buf.memory = v4l2_data.reqbufs.memory;
  1777. vid_buf.index = frame;
  1778.  
  1779. if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 )
  1780. Fatal( "Failed to queue buffer %d: %s", frame, strerror(errno) );
  1781. }
  1782. v4l2_data.bufptr = NULL;
  1783.  
  1784. Debug( 3, "Starting video stream" );
  1785. //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  1786. enum v4l2_buf_type type = v4l2_data.fmt.type;
  1787. if ( vidioctl( vid_fd, VIDIOC_STREAMON, &type ) < 0 )
  1788. Fatal( "Failed to start capture stream: %s", strerror(errno) );
  1789. }
  1790. #endif // ZM_HAS_V4L2
  1791. #if ZM_HAS_V4L1
  1792. if ( v4l_version == 1 )
  1793. {
  1794. for ( int frame = 0; frame < v4l1_data.frames.frames; frame++ )
  1795. {
  1796. Debug( 3, "Queueing frame %d", frame );
  1797. if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[frame] ) < 0 )
  1798. {
  1799. Error( "Capture failure for frame %d: %s", frame, strerror(errno) );
  1800. return( -1 );
  1801. }
  1802. }
  1803. }
  1804. #endif // ZM_HAS_V4L1
  1805.  
  1806. return( 0 );
  1807. }
  1808.  
  1809. int LocalCamera::PreCapture()
  1810. {
  1811. Debug( 2, "Pre-capturing" );
  1812. return( 0 );
  1813. }
  1814.  
  1815. int LocalCamera::Capture( Image &image )
  1816. {
  1817. Debug( 3, "Capturing" );
  1818. static uint8_t* buffer = NULL;
  1819. static uint8_t* directbuffer = NULL;
  1820. static int capture_frame = -1;
  1821.  
  1822. int captures_per_frame = 1;
  1823. if ( channel_count > 1 )
  1824. captures_per_frame = config.captures_per_frame;
  1825.  
  1826.  
  1827. // Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer
  1828. if ( channel_prime )
  1829. {
  1830. #if ZM_HAS_V4L2
  1831. if ( v4l_version == 2 )
  1832. {
  1833. static struct v4l2_buffer vid_buf;
  1834.  
  1835. memset( &vid_buf, 0, sizeof(vid_buf) );
  1836.  
  1837. vid_buf.type = v4l2_data.fmt.type;
  1838. //vid_buf.memory = V4L2_MEMORY_MMAP;
  1839. vid_buf.memory = v4l2_data.reqbufs.memory;
  1840.  
  1841. Debug( 3, "Capturing %d frames", captures_per_frame );
  1842. while ( captures_per_frame )
  1843. {
  1844. if ( vidioctl( vid_fd, VIDIOC_DQBUF, &vid_buf ) < 0 )
  1845. {
  1846. if ( errno == EIO )
  1847. Warning( "Capture failure, possible signal loss?: %s", strerror(errno) )
  1848. else
  1849. Error( "Unable to capture frame %d: %s", vid_buf.index, strerror(errno) )
  1850. return( -1 );
  1851. }
  1852.  
  1853. v4l2_data.bufptr = &vid_buf;
  1854. capture_frame = v4l2_data.bufptr->index;
  1855. if ( --captures_per_frame )
  1856. {
  1857. if ( vidioctl( vid_fd, VIDIOC_QBUF, &vid_buf ) < 0 )
  1858. {
  1859. Error( "Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno) );
  1860. return( -1 );
  1861. }
  1862. }
  1863. }
  1864.  
  1865. Debug( 3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel );
  1866.  
  1867. buffer = (unsigned char *)v4l2_data.buffers[v4l2_data.bufptr->index].start;
  1868.  
  1869. if(v4l2_data.fmt.fmt.pix.width != width && v4l2_data.fmt.fmt.pix.height != height) {
  1870. Fatal("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d",v4l2_data.fmt.fmt.pix.width,v4l2_data.fmt.fmt.pix.height,width,height);
  1871. }
  1872.  
  1873. }
  1874. #endif // ZM_HAS_V4L2
  1875. #if ZM_HAS_V4L1
  1876. if ( v4l_version == 1 )
  1877. {
  1878. Debug( 3, "Capturing %d frames", captures_per_frame );
  1879. while ( captures_per_frame )
  1880. {
  1881. Debug( 3, "Syncing frame %d", v4l1_data.active_frame );
  1882. if ( ioctl( vid_fd, VIDIOCSYNC, &v4l1_data.active_frame ) < 0 )
  1883. {
  1884. Error( "Sync failure for frame %d buffer %d: %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) );
  1885. return( -1 );
  1886. }
  1887. captures_per_frame--;
  1888. if ( captures_per_frame )
  1889. {
  1890. Debug( 3, "Capturing frame %d", v4l1_data.active_frame );
  1891. if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 )
  1892. {
  1893. Error( "Capture failure for buffer %d (%d): %s", v4l1_data.active_frame, captures_per_frame, strerror(errno) );
  1894. return( -1 );
  1895. }
  1896. }
  1897. }
  1898. capture_frame = v4l1_data.active_frame;
  1899. Debug( 3, "Captured %d for channel %d", capture_frame, channel );
  1900.  
  1901. buffer = v4l1_data.bufptr+v4l1_data.frames.offsets[capture_frame];
  1902. }
  1903. #endif // ZM_HAS_V4L1
  1904. } /* prime capture */
  1905.  
  1906. if(conversion_type != 0) {
  1907.  
  1908. Debug( 3, "Performing format conversion" );
  1909.  
  1910. /* Request a writeable buffer of the target image */
  1911. directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
  1912. if(directbuffer == NULL) {
  1913. Error("Failed requesting writeable buffer for the captured image.");
  1914. return (-1);
  1915. }
  1916. #if HAVE_LIBSWSCALE
  1917. if(conversion_type == 1) {
  1918. /* Use swscale to convert the image directly into the shared memory */
  1919.  
  1920. avpicture_fill( (AVPicture *)tmpPicture, directbuffer, imagePixFormat, width, height );
  1921.  
  1922. sws_scale( imgConversionContext, capturePictures[capture_frame]->data, capturePictures[capture_frame]->linesize, 0, height, tmpPicture->data, tmpPicture->linesize );
  1923. }
  1924. #endif
  1925. if(conversion_type == 2) {
  1926.  
  1927. /* Call the image conversion function and convert directly into the shared memory */
  1928. (*conversion_fptr)(buffer, directbuffer, pixels);
  1929. }
  1930.  
  1931. } else {
  1932. Debug( 3, "No format conversion performed. Assigning the image" );
  1933.  
  1934. /* No conversion was performed, the image is in the V4L buffers and needs to be copied into the shared memory */
  1935. image.Assign( width, height, colours, subpixelorder, buffer, imagesize);
  1936.  
  1937. }
  1938.  
  1939. return( 0 );
  1940. }
  1941.  
  1942. int LocalCamera::PostCapture()
  1943. {
  1944. Debug( 2, "Post-capturing" );
  1945. // Requeue the buffer unless we need to switch or are a duplicate camera on a channel
  1946. if ( channel_count > 1 || channel_prime )
  1947. {
  1948. #if ZM_HAS_V4L2
  1949. if ( v4l_version == 2 )
  1950. {
  1951. if ( channel_count > 1 )
  1952. {
  1953. int next_channel = (channel_index+1)%channel_count;
  1954. Debug( 3, "Switching video source to %d", channels[next_channel] );
  1955. if ( vidioctl( vid_fd, VIDIOC_S_INPUT, &channels[next_channel] ) < 0 )
  1956. {
  1957. Error( "Failed to set camera source %d: %s", channels[next_channel], strerror(errno) );
  1958. return( -1 );
  1959. }
  1960.  
  1961. v4l2_std_id stdId = standards[next_channel];
  1962. if ( vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 )
  1963. {
  1964. Error( "Failed to set video format %d: %s", standards[next_channel], strerror(errno) );
  1965. return( -1 );
  1966. }
  1967. }
  1968. Debug( 3, "Requeueing buffer %d", v4l2_data.bufptr->index );
  1969. if ( vidioctl( vid_fd, VIDIOC_QBUF, v4l2_data.bufptr ) < 0 )
  1970. {
  1971. Error( "Unable to requeue buffer %d: %s", v4l2_data.bufptr->index, strerror(errno) )
  1972. return( -1 );
  1973. }
  1974. }
  1975. #endif // ZM_HAS_V4L2
  1976. #if ZM_HAS_V4L1
  1977. if ( v4l_version == 1 )
  1978. {
  1979. if ( channel_count > 1 )
  1980. {
  1981. Debug( 3, "Switching video source" );
  1982. int next_channel = (channel_index+1)%channel_count;
  1983. struct video_channel vid_src;
  1984. memset( &vid_src, 0, sizeof(vid_src) );
  1985. vid_src.channel = channel;
  1986. if ( ioctl( vid_fd, VIDIOCGCHAN, &vid_src) < 0 )
  1987. {
  1988. Error( "Failed to get camera source %d: %s", channel, strerror(errno) );
  1989. return(-1);
  1990. }
  1991.  
  1992. vid_src.channel = channels[next_channel];
  1993. vid_src.norm = standards[next_channel];
  1994. vid_src.flags = 0;
  1995. vid_src.type = VIDEO_TYPE_CAMERA;
  1996. if ( ioctl( vid_fd, VIDIOCSCHAN, &vid_src ) < 0 )
  1997. {
  1998. Error( "Failed to set camera source %d: %s", channel, strerror(errno) );
  1999. return( -1 );
  2000. }
  2001. }
  2002. Debug( 3, "Requeueing frame %d", v4l1_data.active_frame );
  2003. if ( ioctl( vid_fd, VIDIOCMCAPTURE, &v4l1_data.buffers[v4l1_data.active_frame] ) < 0 )
  2004. {
  2005. Error( "Capture failure for frame %d: %s", v4l1_data.active_frame, strerror(errno) );
  2006. return( -1 );
  2007. }
  2008. v4l1_data.active_frame = (v4l1_data.active_frame+1)%v4l1_data.frames.frames;
  2009. }
  2010. #endif // ZM_HAS_V4L1
  2011. }
  2012. return( 0 );
  2013. }
  2014.  
  2015. #endif // ZM_HAS_V4L
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement