From e6b67dcdc2d50605092f5dfe50d8f2c130f00277 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 15 Jun 2021 13:42:55 -0400 Subject: [PATCH 001/101] We cannot delete from the queue when capturing. Just do the waiting. Reduce severity of logs. Make more use of auto. Realise that no other iterators can be pointing into the queue. --- src/zm_packetqueue.cpp | 74 +++++++++--------------------------------- 1 file changed, 15 insertions(+), 59 deletions(-) diff --git a/src/zm_packetqueue.cpp b/src/zm_packetqueue.cpp index b18fdc266..9d0168ab7 100644 --- a/src/zm_packetqueue.cpp +++ b/src/zm_packetqueue.cpp @@ -92,48 +92,9 @@ bool PacketQueue::queuePacket(std::shared_ptr add_packet) { Warning("You have set the max video packets in the queue to %u." " The queue is full. Either Analysis is not keeping up or" " your camera's keyframe interval is larger than this setting." - " We are dropping packets.", max_video_packet_count); - if (add_packet->keyframe) { - // Have a new keyframe, so delete everything - while ((*pktQueue.begin() != add_packet) and (packet_counts[video_stream_id] > max_video_packet_count)) { - std::shared_ptr zm_packet = *pktQueue.begin(); - ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); - if (!lp->trylock()) { - Debug(1, "Found locked packet when trying to free up video packets. Can't continue"); - delete lp; - break; - } - delete lp; - - for ( - std::list::iterator iterators_it = iterators.begin(); - iterators_it != iterators.end(); - ++iterators_it - ) { - packetqueue_iterator *iterator_it = *iterators_it; - // Have to check each iterator and make sure it doesn't point to the packet we are about to delete - if ( *(*iterator_it) == zm_packet ) { - Debug(1, "Bumping IT because it is at the front that we are deleting"); - ++(*iterators_it); - } - } // end foreach iterator - - pktQueue.pop_front(); - packet_counts[zm_packet->packet.stream_index] -= 1; - Debug(1, - "Deleting a packet with stream index:%d image_index:%d with keyframe:%d, video frames in queue:%d max: %d, queuesize:%zu", - zm_packet->packet.stream_index, - zm_packet->image_index, - zm_packet->keyframe, - packet_counts[video_stream_id], - max_video_packet_count, - pktQueue.size()); - } // end while - } - } // end if too many video packets - if (max_video_packet_count > 0) { + , max_video_packet_count); while (packet_counts[video_stream_id] > max_video_packet_count) { - Error("Unable to free up older packets. Waiting."); + Debug(1, "Capture waiting for room in the queue."); condition.wait(lck); if (deleting or zm_terminate) return false; @@ -148,16 +109,13 @@ bool PacketQueue::queuePacket(std::shared_ptr add_packet) { packet_counts[add_packet->packet.stream_index]); for ( - std::list::iterator iterators_it = iterators.begin(); + auto iterators_it = iterators.begin(); iterators_it != iterators.end(); ++iterators_it ) { packetqueue_iterator *iterator_it = *iterators_it; if (*iterator_it == pktQueue.end()) { - Debug(4, "pointing it %p to back", iterator_it); --(*iterator_it); - } else { - Debug(4, "it %p not at end", iterator_it); } } // end foreach iterator } // end lock scope @@ -166,7 +124,7 @@ bool PacketQueue::queuePacket(std::shared_ptr add_packet) { condition.notify_all(); return true; -} // end bool PacketQueue::queuePacket(ZMPacket* zm_packet) +} // end bool PacketQueue::queuePacket(ZMPacket* zm_packet) void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { // Only do queueCleaning if we are adding a video keyframe, so that we guarantee that there is one. @@ -240,8 +198,8 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { return; } - packetqueue_iterator it = pktQueue.begin(); - packetqueue_iterator next_front = pktQueue.begin(); + auto it = pktQueue.begin(); + auto next_front = pktQueue.begin(); // First packet is special because we know it is a video keyframe and only need to check for lock std::shared_ptr zm_packet = *it; @@ -249,18 +207,13 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { return; } - Debug(1, "trying lock on first packet"); ZMLockedPacket *lp = new ZMLockedPacket(zm_packet); if (lp->trylock()) { int video_packets_to_delete = 0; // This is a count of how many packets we will delete so we know when to stop looking - Debug(1, "Have lock on first packet"); + Debug(4, "Have lock on first packet"); ++it; delete lp; - if (it == pktQueue.end()) { - Debug(1, "Hit end already"); - it = pktQueue.begin(); - } else { // Since we have many packets in the queue, we should NOT be pointing at end so don't need to test for that while (*it != add_packet) { zm_packet = *it; @@ -271,10 +224,14 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { } delete lp; - if (is_there_an_iterator_pointing_to_packet(zm_packet) and (pktQueue.begin() == next_front)) { - Warning("Found iterator at beginning of queue. Some thread isn't keeping up"); +#if 0 + // There are no threads that follow analysis thread. So there cannot be an it pointing here + if (is_there_an_iterator_pointing_to_packet(zm_packet)) { + if (pktQueue.begin() == next_front) + Warning("Found iterator at beginning of queue. Some thread isn't keeping up"); break; } +#endif if (zm_packet->packet.stream_index == video_stream_id) { if (zm_packet->keyframe) { @@ -282,15 +239,14 @@ void PacketQueue::clearPackets(const std::shared_ptr &add_packet) { next_front = it; } ++video_packets_to_delete; - Debug(4, "Counted %d video packets. Which would leave %d in packetqueue tail count is %d", - video_packets_to_delete, packet_counts[video_stream_id]-video_packets_to_delete, tail_count); + Debug(4, "Counted %d video packets. Which would leave %d in packetqueue tail count is %d", + video_packets_to_delete, packet_counts[video_stream_id]-video_packets_to_delete, tail_count); if (packet_counts[video_stream_id] - video_packets_to_delete <= pre_event_video_packet_count + tail_count) { break; } } ++it; } // end while - } } // end if first packet not locked Debug(1, "Resulting pointing at latest packet? %d, next front points to begin? %d", ( *it == add_packet ), From 8554ccd64982c8ff6ed101f7bc3182690565588c Mon Sep 17 00:00:00 2001 From: criadoperez Date: Wed, 29 Sep 2021 12:26:15 +0200 Subject: [PATCH 002/101] Added Debian 11 (bullseye) installation --- docs/installationguide/debian.rst | 86 +++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/docs/installationguide/debian.rst b/docs/installationguide/debian.rst index c6e0cebcf..15cc9660d 100644 --- a/docs/installationguide/debian.rst +++ b/docs/installationguide/debian.rst @@ -3,6 +3,92 @@ Debian .. contents:: +Easy Way: Debian 11 (Bullseye) +------------------------ + +This procedure will guide you through the installation of ZoneMinder on Debian 11 (Bullseye). + +**Step 1:** Setup Sudo (optional but recommended) + +By default Debian does not come with sudo, so you have to install it and configure it manually. +This step is optional but recommended and the following instructions assume that you have setup sudo. +If you prefer to setup ZoneMinder as root, do it at your own risk and adapt the following instructions accordingly. + +:: + + apt install sudo + usermod -a -G sudo + exit + +Now your terminal session is back under your normal user. You can check that +you are now part of the sudo group with the command ``groups``, "sudo" should +appear in the list. If not, run ``newgrp sudo`` and check again with ``groups``. + +**Step 2:** Update system and install zoneminder + +Run the following commands. + +:: + + sudo apt update + sudo apt upgrade + sudo apt install zoneminder + +**Step 3:** Initialize database + +Run the following commands. + +:: + + cat /usr/share/zoneminder/db/zm_create.sql | sudo mysql --defaults-file=/etc/mysql/debian.cnf + echo 'grant lock tables,alter,create,select,insert,update,delete,index on zm.* to 'zmuser'@localhost identified by "zmpass";' | sudo mysql --defaults-file=/etc/mysql/debian.cnf mysql + +**Step 4:** Setup permissions for zm.conf + +To make sure zoneminder can read the configuration file, run the following command. + +:: + + sudo chgrp -c www-data /etc/zm/zm.conf + +**Step 5:** Edit Timezone in PHP + +Automated way: +:: + + sudo sed -i "s/;date.timezone =/date.timezone = $(sed 's/\//\\\//' /etc/timezone)/g" /etc/php/7.*/apache2/php.ini + +Manual way +:: + + sudo nano /etc/php/7.*/apache2/php.ini + +Search for [Date] (Ctrl + w then type Date and press Enter) and change +date.timezone for your time zone. Don't forget to remove the ; from in front +of date.timezone. + +:: + + [Date] + ; Defines the default timezone used by the date functions + ; http://php.net/date.timezone + date.timezone = America/New_York + +CTRL+o then [Enter] to save + +CTRL+x to exit + +**Step 6:** Reload Apache and start zoneminder + +Run the following commands. + +:: + + sudo systemctl reload apache2 + sudo systectl start zoneminder + +Congratulations! You should now be able to access zoneminder at ``http://yourhostname/zm`` + Easy Way: Debian Buster ------------------------ From 9f683c0c91f7c5f37d10f1bf502d499016a7bb84 Mon Sep 17 00:00:00 2001 From: criadoperez Date: Wed, 29 Sep 2021 14:14:25 +0200 Subject: [PATCH 003/101] Removed default-file parameter that is deprecated --- docs/installationguide/debian.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/installationguide/debian.rst b/docs/installationguide/debian.rst index 15cc9660d..50173928f 100644 --- a/docs/installationguide/debian.rst +++ b/docs/installationguide/debian.rst @@ -40,8 +40,8 @@ Run the following commands. :: - cat /usr/share/zoneminder/db/zm_create.sql | sudo mysql --defaults-file=/etc/mysql/debian.cnf - echo 'grant lock tables,alter,create,select,insert,update,delete,index on zm.* to 'zmuser'@localhost identified by "zmpass";' | sudo mysql --defaults-file=/etc/mysql/debian.cnf mysql + cat /usr/share/zoneminder/db/zm_create.sql | sudo mariadb + echo 'grant lock tables,alter,create,select,insert,update,delete,index on zm.* to 'zmuser'@localhost identified by "zmpass";' | sudo mariadb **Step 4:** Setup permissions for zm.conf From e462c231151ecb6044d747e3a1ad29ef948af3dd Mon Sep 17 00:00:00 2001 From: criadoperez Date: Wed, 29 Sep 2021 16:46:04 +0200 Subject: [PATCH 004/101] updated dlandon repository name --- docs/installationguide/easydocker.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installationguide/easydocker.rst b/docs/installationguide/easydocker.rst index 899ce0e5d..a7d37a9e5 100644 --- a/docs/installationguide/easydocker.rst +++ b/docs/installationguide/easydocker.rst @@ -2,7 +2,7 @@ An Easy To Use Docker Image =========================== If you are interested in trying out ZoneMinder quickly, user Dan Landon maintains an easy to use docker image for ZoneMinder. With a few simple configuration changes, it also provides complete Event Notification Server and Machine Learning hook support. Please follow instructions in his repostory. He maintains two repositories: -* If you want to run the latest stable release, please use his `zoneminder repository `__. +* If you want to run the latest stable release, please use his `zoneminder machine learning repository `__. * If you want to run the latest zoneminder master, please use his `zoneminder master repository `__. In both cases, instructions are provided in the repo README files. From 1e71300a3bee9cf8844c4cee6a75f4e0b2d130bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Criado-P=C3=A9rez?= Date: Thu, 30 Sep 2021 01:15:45 +0200 Subject: [PATCH 005/101] added Debian installation instructions --- docs/installationguide/debian.rst | 48 ++----------------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/docs/installationguide/debian.rst b/docs/installationguide/debian.rst index 50173928f..f7325fe1f 100644 --- a/docs/installationguide/debian.rst +++ b/docs/installationguide/debian.rst @@ -32,18 +32,12 @@ Run the following commands. sudo apt update sudo apt upgrade + sudo apt install mariadb-server sudo apt install zoneminder -**Step 3:** Initialize database +When mariadb is installed for the first time, it doesn't add a password to the root user. Therefore, for security, it is recommended to run ``mysql secure installation``. -Run the following commands. - -:: - - cat /usr/share/zoneminder/db/zm_create.sql | sudo mariadb - echo 'grant lock tables,alter,create,select,insert,update,delete,index on zm.* to 'zmuser'@localhost identified by "zmpass";' | sudo mariadb - -**Step 4:** Setup permissions for zm.conf +**Step 3:** Setup permissions for zm.conf To make sure zoneminder can read the configuration file, run the following command. @@ -51,42 +45,6 @@ To make sure zoneminder can read the configuration file, run the following comma sudo chgrp -c www-data /etc/zm/zm.conf -**Step 5:** Edit Timezone in PHP - -Automated way: -:: - - sudo sed -i "s/;date.timezone =/date.timezone = $(sed 's/\//\\\//' /etc/timezone)/g" /etc/php/7.*/apache2/php.ini - -Manual way -:: - - sudo nano /etc/php/7.*/apache2/php.ini - -Search for [Date] (Ctrl + w then type Date and press Enter) and change -date.timezone for your time zone. Don't forget to remove the ; from in front -of date.timezone. - -:: - - [Date] - ; Defines the default timezone used by the date functions - ; http://php.net/date.timezone - date.timezone = America/New_York - -CTRL+o then [Enter] to save - -CTRL+x to exit - -**Step 6:** Reload Apache and start zoneminder - -Run the following commands. - -:: - - sudo systemctl reload apache2 - sudo systectl start zoneminder - Congratulations! You should now be able to access zoneminder at ``http://yourhostname/zm`` Easy Way: Debian Buster From ca293eb288a4be0cb4ba2c5b66d3acd302047ee8 Mon Sep 17 00:00:00 2001 From: TheRealJiffy <55252594+TheRealJiffy@users.noreply.github.com> Date: Sat, 2 Oct 2021 23:42:08 -0400 Subject: [PATCH 006/101] Update mobile.rst fix broken link --- docs/userguide/mobile.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/userguide/mobile.rst b/docs/userguide/mobile.rst index c6da91642..7f000bea3 100644 --- a/docs/userguide/mobile.rst +++ b/docs/userguide/mobile.rst @@ -6,7 +6,7 @@ Here are some options for using ZoneMinder on Mobile devices: Third party mobile clients ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * zmNinja (`source code `__, needs APIs to be installed to work) - * Available in App Store, Play Store and for Desktops - `website `__ + * Available in App Store, Play Store and for Desktops - `website `__ Using the existing web console ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,4 +17,4 @@ Discontinued clients The following are a list of clients that do not work and have not been updated: * eyeZM -* zmView \ No newline at end of file +* zmView From a0142d38967c0ae4ec13cafde3ec9afbcb2c3326 Mon Sep 17 00:00:00 2001 From: haade <76404800+haade-administrator@users.noreply.github.com> Date: Tue, 5 Oct 2021 08:15:39 +0200 Subject: [PATCH 007/101] Update translation --- web/lang/fr_fr.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/lang/fr_fr.php b/web/lang/fr_fr.php index b244145b5..303eb8100 100644 --- a/web/lang/fr_fr.php +++ b/web/lang/fr_fr.php @@ -348,16 +348,16 @@ $SLANG = array( 'Ffmpeg' => 'Ffmpeg', // Added - 2009-02-08 'File' => 'Fichier', 'Filter' => 'Filtre', // Added - 2015-04-18 - 'FilterArchiveEvents' => 'Archiver', - 'FilterDeleteEvents' => 'Effacer', - 'FilterEmailEvents' => 'Envoyer les détails par email', + 'FilterArchiveEvents' => 'Archiver les évènements', + 'FilterDeleteEvents' => 'Effacer les évènements', + 'FilterEmailEvents' => 'Envoyer les évènements par email', 'FilterExecuteEvents' => 'Exécuter une commande', 'FilterLog' => 'Filtre', // Added - 2015-04-18 - 'FilterMessageEvents' => 'Envoyer les détails par message', + 'FilterMessageEvents' => 'Envoyer les évènements par message', 'FilterMoveEvents' => 'Move all matches', // Added - 2018-08-30 'FilterPx' => 'Filtre Px', 'FilterUnset' => 'Vous devez spécifier une largeur et une hauteur de filtre', - 'FilterUpdateDiskSpace'=> 'Update used disk space', // Added - 2018-08-30 + 'FilterUpdateDiskSpace'=> 'Mies à jour de l\'espace disque utilisé', // Added - 2018-08-30 'FilterUploadEvents' => 'Transférer', 'FilterVideoEvents' => 'Créer vidéo', 'Filters' => 'Filtres', From 1f04723f3a8bc421d8bb13d6762ec963d259d73f Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 29 Sep 2021 09:31:16 -0400 Subject: [PATCH 008/101] dbError is supposed to take the sql that caused the error. So pass something to satisfy php --- web/includes/actions/monitor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/includes/actions/monitor.php b/web/includes/actions/monitor.php index 1c6e1f72f..ee041967c 100644 --- a/web/includes/actions/monitor.php +++ b/web/includes/actions/monitor.php @@ -205,7 +205,7 @@ if ( $action == 'save' ) { } // end if changes in width or height } else { global $error_message; - $error_message = dbError(); + $error_message = dbError('unknown'); } // end if successful save $restart = true; } else { // new monitor From 75a014321ef9f30e5d8026188a396db0dff583c9 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 5 Oct 2021 13:50:41 -0400 Subject: [PATCH 009/101] Spacing, remove tests for v4l2, move control setting/getting code to a single function. --- src/zm_local_camera.cpp | 785 ++++++++++++++++++---------------------- src/zm_local_camera.h | 1 + 2 files changed, 351 insertions(+), 435 deletions(-) diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index 8f38b4d99..795aaab7c 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -259,12 +259,12 @@ LocalCamera::LocalCamera( v4l_multi_buffer = p_v4l_multi_buffer; v4l_captures_per_frame = p_v4l_captures_per_frame; - if ( capture ) { - if ( device_prime ) { + if (capture) { + if (device_prime) { Debug(2, "V4L support enabled, using V4L%d api", v4l_version); } - if ( (!last_camera) || (channel != last_camera->channel) ) { + if ((!last_camera) || (channel != last_camera->channel)) { // We are the first, or only, input that uses this channel channel_prime = true; channel_index = channel_count++; @@ -278,10 +278,10 @@ LocalCamera::LocalCamera( /* The V4L1 API doesn't care about endianness, we need to check the endianness of the machine */ uint32_t checkval = 0xAABBCCDD; - if ( *(unsigned char*)&checkval == 0xDD ) { + if (*(unsigned char*)&checkval == 0xDD) { BigEndian = 0; Debug(2, "little-endian processor detected"); - } else if ( *(unsigned char*)&checkval == 0xAA ) { + } else if (*(unsigned char*)&checkval == 0xAA) { BigEndian = 1; Debug(2, "Big-endian processor detected"); } else { @@ -289,15 +289,15 @@ LocalCamera::LocalCamera( BigEndian = 0; } - if ( v4l_version == 2 && palette == 0 ) { + if (v4l_version == 2 && palette == 0) { /* Use automatic format selection */ Debug(2,"Using automatic format selection"); palette = AutoSelectFormat(colours); - if ( palette == 0 ) { + if (palette == 0) { Error("Automatic format selection failed. Falling back to YUYV"); palette = V4L2_PIX_FMT_YUYV; } else { - if ( capture ) { + if (capture) { Info("Selected capture palette: %s (0x%02hhx%02hhx%02hhx%02hhx)", palette_desc, static_cast((palette >> 24) & 0xff), @@ -328,130 +328,127 @@ LocalCamera::LocalCamera( imagePixFormat = AV_PIX_FMT_NONE; } - /* V4L2 format matching */ - if ( v4l_version == 2 ) { - /* Try to find a match for the selected palette and target colourspace */ + /* Try to find a match for the selected palette and target colourspace */ - /* RGB32 palette and 32bit target colourspace */ - if ( palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_RGB32 ) { - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_ARGB; + /* RGB32 palette and 32bit target colourspace */ + if (palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_RGB32) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_ARGB; - /* BGR32 palette and 32bit target colourspace */ - } else if ( palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_RGB32 ) { - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_BGRA; + /* BGR32 palette and 32bit target colourspace */ + } else if (palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_RGB32) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_BGRA; - /* RGB24 palette and 24bit target colourspace */ - } else if ( palette == V4L2_PIX_FMT_RGB24 && colours == ZM_COLOUR_RGB24 ) { - conversion_type = 0; - conversion_type = 0; - subpixelorder = ZM_SUBPIX_ORDER_BGR; + /* RGB24 palette and 24bit target colourspace */ + } else if (palette == V4L2_PIX_FMT_RGB24 && colours == ZM_COLOUR_RGB24) { + conversion_type = 0; + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_BGR; - /* Grayscale palette and grayscale target colourspace */ - } else if ( palette == V4L2_PIX_FMT_GREY && colours == ZM_COLOUR_GRAY8 ) { - conversion_type = 0; + /* Grayscale palette and grayscale target colourspace */ + } else if (palette == V4L2_PIX_FMT_GREY && colours == ZM_COLOUR_GRAY8) { + conversion_type = 0; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */ + } else { + if (capture) { + Info( + "No direct match for the selected palette (%d) and target colorspace (%02u). Format conversion is required, performance penalty expected", + capturePixFormat, + colours); + } + /* Try using swscale for the conversion */ + conversion_type = 1; + Debug(2, "Using swscale for image conversion"); + if (colours == ZM_COLOUR_RGB32) { + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + imagePixFormat = AV_PIX_FMT_RGBA; + } else if (colours == ZM_COLOUR_RGB24) { + subpixelorder = ZM_SUBPIX_ORDER_RGB; + imagePixFormat = AV_PIX_FMT_RGB24; + } else if (colours == ZM_COLOUR_GRAY8) { subpixelorder = ZM_SUBPIX_ORDER_NONE; - /* Unable to find a solution for the selected palette and target colourspace. Conversion required. Notify the user of performance penalty */ + imagePixFormat = AV_PIX_FMT_GRAY8; } else { - if ( capture ) { - Info( - "No direct match for the selected palette (%d) and target colorspace (%02u). Format conversion is required, performance penalty expected", - capturePixFormat, - colours); + Panic("Unexpected colours: %u",colours); + } + if (capture) { + if (!sws_isSupportedInput(capturePixFormat)) { + Error("swscale does not support the used capture format: %d", capturePixFormat); + conversion_type = 2; /* Try ZM format conversions */ } - /* Try using swscale for the conversion */ - conversion_type = 1; - Debug(2, "Using swscale for image conversion"); - if ( colours == ZM_COLOUR_RGB32 ) { - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - imagePixFormat = AV_PIX_FMT_RGBA; - } else if ( colours == ZM_COLOUR_RGB24 ) { - subpixelorder = ZM_SUBPIX_ORDER_RGB; - imagePixFormat = AV_PIX_FMT_RGB24; - } else if ( colours == ZM_COLOUR_GRAY8 ) { + if (!sws_isSupportedOutput(imagePixFormat)) { + Error("swscale does not support the target format: 0x%d", imagePixFormat); + conversion_type = 2; /* Try ZM format conversions */ + } + } + /* Our YUYV->Grayscale conversion is a lot faster than swscale's */ + if (colours == ZM_COLOUR_GRAY8 && palette == V4L2_PIX_FMT_YUYV) { + conversion_type = 2; + } + + /* JPEG */ + if (palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) { + Debug(2,"Using JPEG image decoding"); + conversion_type = 3; + } + + if (conversion_type == 2) { + Debug(2,"Using ZM for image conversion"); + if ( palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_GRAY8 ) { + conversion_fptr = &std_convert_argb_gray8; subpixelorder = ZM_SUBPIX_ORDER_NONE; - imagePixFormat = AV_PIX_FMT_GRAY8; - } else { - Panic("Unexpected colours: %u",colours); - } - if ( capture ) { - if ( !sws_isSupportedInput(capturePixFormat) ) { - Error("swscale does not support the used capture format: %d", capturePixFormat); - conversion_type = 2; /* Try ZM format conversions */ - } - if ( !sws_isSupportedOutput(imagePixFormat) ) { - Error("swscale does not support the target format: 0x%d", imagePixFormat); - conversion_type = 2; /* Try ZM format conversions */ - } - } - /* Our YUYV->Grayscale conversion is a lot faster than swscale's */ - if ( colours == ZM_COLOUR_GRAY8 && palette == V4L2_PIX_FMT_YUYV ) { - conversion_type = 2; - } - - /* JPEG */ - if ( palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG ) { - Debug(2,"Using JPEG image decoding"); - conversion_type = 3; - } - - if ( conversion_type == 2 ) { - Debug(2,"Using ZM for image conversion"); - if ( palette == V4L2_PIX_FMT_RGB32 && colours == ZM_COLOUR_GRAY8 ) { - conversion_fptr = &std_convert_argb_gray8; - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } else if ( palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_GRAY8 ) { - conversion_fptr = &std_convert_bgra_gray8; - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8 ) { - /* Fast YUYV->Grayscale conversion by extracting the Y channel */ - if ( config.cpu_extensions && sse_version >= 35 ) { - conversion_fptr = &ssse3_convert_yuyv_gray8; - Debug(2,"Using SSSE3 YUYV->grayscale fast conversion"); - } else { - conversion_fptr = &std_convert_yuyv_gray8; - Debug(2,"Using standard YUYV->grayscale fast conversion"); - } - subpixelorder = ZM_SUBPIX_ORDER_NONE; - } else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB24 ) { - conversion_fptr = &zm_convert_yuyv_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if ( palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB32 ) { - conversion_fptr = &zm_convert_yuyv_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } else if ( palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB24 ) { - conversion_fptr = &zm_convert_rgb555_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if ( palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB32 ) { - conversion_fptr = &zm_convert_rgb555_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; - } else if ( palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB24 ) { - conversion_fptr = &zm_convert_rgb565_rgb; - subpixelorder = ZM_SUBPIX_ORDER_RGB; - } else if ( palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB32 ) { - conversion_fptr = &zm_convert_rgb565_rgba; - subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if (palette == V4L2_PIX_FMT_BGR32 && colours == ZM_COLOUR_GRAY8) { + conversion_fptr = &std_convert_bgra_gray8; + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if (palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_GRAY8) { + /* Fast YUYV->Grayscale conversion by extracting the Y channel */ + if (config.cpu_extensions && sse_version >= 35) { + conversion_fptr = &ssse3_convert_yuyv_gray8; + Debug(2,"Using SSSE3 YUYV->grayscale fast conversion"); } else { - Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace."); + conversion_fptr = &std_convert_yuyv_gray8; + Debug(2,"Using standard YUYV->grayscale fast conversion"); } - } // end if conversion_type == 2 - } // end if needs conversion - } // end if v4l2 + subpixelorder = ZM_SUBPIX_ORDER_NONE; + } else if (palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_yuyv_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if (palette == V4L2_PIX_FMT_YUYV && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_yuyv_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if (palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb555_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if (palette == V4L2_PIX_FMT_RGB555 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb555_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else if (palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB24) { + conversion_fptr = &zm_convert_rgb565_rgb; + subpixelorder = ZM_SUBPIX_ORDER_RGB; + } else if (palette == V4L2_PIX_FMT_RGB565 && colours == ZM_COLOUR_RGB32) { + conversion_fptr = &zm_convert_rgb565_rgba; + subpixelorder = ZM_SUBPIX_ORDER_RGBA; + } else { + Fatal("Unable to find a suitable format conversion for the selected palette and target colorspace."); + } + } // end if conversion_type == 2 + } // end if needs conversion last_camera = this; Debug(3, "Selected subpixelorder: %u", subpixelorder); /* Initialize swscale stuff */ - if ( capture and (conversion_type == 1) ) { + if (capture and (conversion_type == 1)) { tmpPicture = av_frame_alloc(); - if ( !tmpPicture ) + if (!tmpPicture) Fatal("Could not allocate temporary picture"); unsigned int pSize = av_image_get_buffer_size(imagePixFormat, width, height, 1); - if ( pSize != imagesize ) { + if (pSize != imagesize) { Fatal("Image size mismatch. Required: %d Available: %llu", pSize, imagesize); } @@ -460,23 +457,23 @@ LocalCamera::LocalCamera( width, height, imagePixFormat, SWS_BICUBIC, nullptr, nullptr, nullptr); - if ( !imgConversionContext ) { + if (!imgConversionContext) { Fatal("Unable to initialise image scaling context"); } } else { tmpPicture = nullptr; imgConversionContext = nullptr; } // end if capture and conversion_tye == swscale - if ( capture and device_prime ) + if (capture and device_prime) Initialise(); } // end LocalCamera::LocalCamera LocalCamera::~LocalCamera() { - if ( device_prime && capture ) + if (device_prime && capture) Terminate(); /* Clean up swscale stuff */ - if ( capture && (conversion_type == 1) ) { + if (capture && (conversion_type == 1)) { sws_freeContext(imgConversionContext); imgConversionContext = nullptr; @@ -492,251 +489,248 @@ int LocalCamera::Close() { void LocalCamera::Initialise() { Debug(3, "Opening video device %s", device.c_str()); - //if ( (vid_fd = open( device.c_str(), O_RDWR|O_NONBLOCK, 0 )) < 0 ) - if ( (vid_fd = open(device.c_str(), O_RDWR, 0)) < 0 ) + if ((vid_fd = open(device.c_str(), O_RDWR, 0)) < 0) Fatal("Failed to open video device %s: %s", device.c_str(), strerror(errno)); struct stat st; - if ( stat(device.c_str(), &st) < 0 ) + if (stat(device.c_str(), &st) < 0) Fatal("Failed to stat video device %s: %s", device.c_str(), strerror(errno)); - if ( !S_ISCHR(st.st_mode) ) + if (!S_ISCHR(st.st_mode)) Fatal("File %s is not device file: %s", device.c_str(), strerror(errno)); Debug(2, "V4L2 support enabled, using V4L%d api", v4l_version); - if ( v4l_version == 2 ) { - struct v4l2_capability vid_cap; + struct v4l2_capability vid_cap; - Debug(3, "Checking video device capabilities"); - if ( vidioctl(vid_fd, VIDIOC_QUERYCAP, &vid_cap) < 0 ) - Fatal("Failed to query video device: %s", strerror(errno)); + Debug(3, "Checking video device capabilities"); + if ( vidioctl(vid_fd, VIDIOC_QUERYCAP, &vid_cap) < 0 ) + Fatal("Failed to query video device: %s", strerror(errno)); - if ( !(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ) - Fatal("Video device is not video capture device"); + if ( !(vid_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) ) + Fatal("Video device is not video capture device"); - if ( !(vid_cap.capabilities & V4L2_CAP_STREAMING) ) - Fatal("Video device does not support streaming i/o"); + if ( !(vid_cap.capabilities & V4L2_CAP_STREAMING) ) + Fatal("Video device does not support streaming i/o"); - Debug(3, "Setting up video format"); + Debug(3, "Setting up video format"); - memset(&v4l2_data.fmt, 0, sizeof(v4l2_data.fmt)); - v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + memset(&v4l2_data.fmt, 0, sizeof(v4l2_data.fmt)); + v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if ( vidioctl( vid_fd, VIDIOC_G_FMT, &v4l2_data.fmt ) < 0 ) - Fatal("Failed to get video format: %s", strerror(errno)); + if ( vidioctl( vid_fd, VIDIOC_G_FMT, &v4l2_data.fmt ) < 0 ) + Fatal("Failed to get video format: %s", strerror(errno)); - Debug(4, - " v4l2_data.fmt.type = %08x\n" - " v4l2_data.fmt.fmt.pix.width = %d\n" - " v4l2_data.fmt.fmt.pix.height = %d\n" - " v4l2_data.fmt.fmt.pix.pixelformat = %08x\n" - " v4l2_data.fmt.fmt.pix.field = %08x\n" - " v4l2_data.fmt.fmt.pix.bytesperline = %d\n" - " v4l2_data.fmt.fmt.pix.sizeimage = %d\n" - " v4l2_data.fmt.fmt.pix.colorspace = %08x\n" - " v4l2_data.fmt.fmt.pix.priv = %08x\n" - , v4l2_data.fmt.type - , v4l2_data.fmt.fmt.pix.width - , v4l2_data.fmt.fmt.pix.height - , v4l2_data.fmt.fmt.pix.pixelformat - , v4l2_data.fmt.fmt.pix.field - , v4l2_data.fmt.fmt.pix.bytesperline - , v4l2_data.fmt.fmt.pix.sizeimage - , v4l2_data.fmt.fmt.pix.colorspace - , v4l2_data.fmt.fmt.pix.priv - ); + Debug(4, + " v4l2_data.fmt.type = %08x\n" + " v4l2_data.fmt.fmt.pix.width = %d\n" + " v4l2_data.fmt.fmt.pix.height = %d\n" + " v4l2_data.fmt.fmt.pix.pixelformat = %08x\n" + " v4l2_data.fmt.fmt.pix.field = %08x\n" + " v4l2_data.fmt.fmt.pix.bytesperline = %d\n" + " v4l2_data.fmt.fmt.pix.sizeimage = %d\n" + " v4l2_data.fmt.fmt.pix.colorspace = %08x\n" + " v4l2_data.fmt.fmt.pix.priv = %08x\n" + , v4l2_data.fmt.type + , v4l2_data.fmt.fmt.pix.width + , v4l2_data.fmt.fmt.pix.height + , v4l2_data.fmt.fmt.pix.pixelformat + , v4l2_data.fmt.fmt.pix.field + , v4l2_data.fmt.fmt.pix.bytesperline + , v4l2_data.fmt.fmt.pix.sizeimage + , v4l2_data.fmt.fmt.pix.colorspace + , v4l2_data.fmt.fmt.pix.priv + ); - v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - v4l2_data.fmt.fmt.pix.width = width; - v4l2_data.fmt.fmt.pix.height = height; - v4l2_data.fmt.fmt.pix.pixelformat = palette; + v4l2_data.fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_data.fmt.fmt.pix.width = width; + v4l2_data.fmt.fmt.pix.height = height; + v4l2_data.fmt.fmt.pix.pixelformat = palette; - if ( (extras & 0xff) != 0 ) { - v4l2_data.fmt.fmt.pix.field = (v4l2_field)(extras & 0xff); + if ((extras & 0xff) != 0) { + v4l2_data.fmt.fmt.pix.field = (v4l2_field)(extras & 0xff); - if ( vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0 ) { - Warning("Failed to set V4L2 field to %d, falling back to auto", (extras & 0xff)); - v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY; - if ( vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0 ) { - Fatal("Failed to set video format: %s", strerror(errno)); - } - } - } else { - if ( vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0 ) { - Error("Failed to set video format: %s", strerror(errno)); + if (vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0) { + Warning("Failed to set V4L2 field to %d, falling back to auto", (extras & 0xff)); + v4l2_data.fmt.fmt.pix.field = V4L2_FIELD_ANY; + if (vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0) { + Fatal("Failed to set video format: %s", strerror(errno)); } } - - /* Note VIDIOC_S_FMT may change width and height. */ - Debug(4, - " v4l2_data.fmt.type = %08x\n" - " v4l2_data.fmt.fmt.pix.width = %d\n" - " v4l2_data.fmt.fmt.pix.height = %d\n" - " v4l2_data.fmt.fmt.pix.pixelformat = %08x\n" - " v4l2_data.fmt.fmt.pix.field = %08x\n" - " v4l2_data.fmt.fmt.pix.bytesperline = %d\n" - " v4l2_data.fmt.fmt.pix.sizeimage = %d\n" - " v4l2_data.fmt.fmt.pix.colorspace = %08x\n" - " v4l2_data.fmt.fmt.pix.priv = %08x\n" - , v4l2_data.fmt.type - , v4l2_data.fmt.fmt.pix.width - , v4l2_data.fmt.fmt.pix.height - , v4l2_data.fmt.fmt.pix.pixelformat - , v4l2_data.fmt.fmt.pix.field - , v4l2_data.fmt.fmt.pix.bytesperline - , v4l2_data.fmt.fmt.pix.sizeimage - , v4l2_data.fmt.fmt.pix.colorspace - , v4l2_data.fmt.fmt.pix.priv - ); - - if ( v4l2_data.fmt.fmt.pix.width != width ) { - Warning("Failed to set requested width"); - } - if ( v4l2_data.fmt.fmt.pix.height != height ) { - Warning("Failed to set requested height"); + } else { + if (vidioctl(vid_fd, VIDIOC_S_FMT, &v4l2_data.fmt) < 0) { + Error("Failed to set video format: %s", strerror(errno)); } + } - /* Buggy driver paranoia. */ - unsigned int min; - min = v4l2_data.fmt.fmt.pix.width * 2; - if ( v4l2_data.fmt.fmt.pix.bytesperline < min ) - v4l2_data.fmt.fmt.pix.bytesperline = min; - min = v4l2_data.fmt.fmt.pix.bytesperline * v4l2_data.fmt.fmt.pix.height; - if ( v4l2_data.fmt.fmt.pix.sizeimage < min ) - v4l2_data.fmt.fmt.pix.sizeimage = min; + /* Note VIDIOC_S_FMT may change width and height. */ + Debug(4, + " v4l2_data.fmt.type = %08x\n" + " v4l2_data.fmt.fmt.pix.width = %d\n" + " v4l2_data.fmt.fmt.pix.height = %d\n" + " v4l2_data.fmt.fmt.pix.pixelformat = %08x\n" + " v4l2_data.fmt.fmt.pix.field = %08x\n" + " v4l2_data.fmt.fmt.pix.bytesperline = %d\n" + " v4l2_data.fmt.fmt.pix.sizeimage = %d\n" + " v4l2_data.fmt.fmt.pix.colorspace = %08x\n" + " v4l2_data.fmt.fmt.pix.priv = %08x\n" + , v4l2_data.fmt.type + , v4l2_data.fmt.fmt.pix.width + , v4l2_data.fmt.fmt.pix.height + , v4l2_data.fmt.fmt.pix.pixelformat + , v4l2_data.fmt.fmt.pix.field + , v4l2_data.fmt.fmt.pix.bytesperline + , v4l2_data.fmt.fmt.pix.sizeimage + , v4l2_data.fmt.fmt.pix.colorspace + , v4l2_data.fmt.fmt.pix.priv + ); - if ( palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG ) { - v4l2_jpegcompression jpeg_comp; - if ( vidioctl(vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp) < 0 ) { - if ( errno == EINVAL ) { - Debug(2, "JPEG compression options are not available"); - } else { - Warning("Failed to get JPEG compression options: %s", strerror(errno)); - } + if (v4l2_data.fmt.fmt.pix.width != width) { + Warning("Failed to set requested width"); + } + if (v4l2_data.fmt.fmt.pix.height != height) { + Warning("Failed to set requested height"); + } + + /* Buggy driver paranoia. */ + unsigned int min; + min = v4l2_data.fmt.fmt.pix.width * 2; + if (v4l2_data.fmt.fmt.pix.bytesperline < min) + v4l2_data.fmt.fmt.pix.bytesperline = min; + min = v4l2_data.fmt.fmt.pix.bytesperline * v4l2_data.fmt.fmt.pix.height; + if (v4l2_data.fmt.fmt.pix.sizeimage < min) + v4l2_data.fmt.fmt.pix.sizeimage = min; + + if (palette == V4L2_PIX_FMT_JPEG || palette == V4L2_PIX_FMT_MJPEG) { + v4l2_jpegcompression jpeg_comp; + if (vidioctl(vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp) < 0) { + if (errno == EINVAL) { + Debug(2, "JPEG compression options are not available"); } else { - /* Set flags and quality. MJPEG should not have the huffman tables defined */ - if ( palette == V4L2_PIX_FMT_MJPEG ) { - jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI; - } else { - jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | V4L2_JPEG_MARKER_DHT; - } - jpeg_comp.quality = 85; - - /* Update the JPEG options */ - if ( vidioctl(vid_fd, VIDIOC_S_JPEGCOMP, &jpeg_comp) < 0 ) { - Warning("Failed to set JPEG compression options: %s", strerror(errno)); - } else { - if ( vidioctl(vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp) < 0 ) { - Debug(3,"Failed to get updated JPEG compression options: %s", strerror(errno)); - } else { - Debug(4, "JPEG quality: %d, markers: %#x", - jpeg_comp.quality, jpeg_comp.jpeg_markers); - } - } - } - } // end if JPEG/MJPEG - - Debug(3, "Setting up request buffers"); - - memset(&v4l2_data.reqbufs, 0, sizeof(v4l2_data.reqbufs)); - if ( channel_count > 1 ) { - Debug(3, "Channel count is %d", channel_count); - if ( v4l_multi_buffer ){ - v4l2_data.reqbufs.count = 2*channel_count; - } else { - v4l2_data.reqbufs.count = 1; + Warning("Failed to get JPEG compression options: %s", strerror(errno)); } } else { - v4l2_data.reqbufs.count = 8; - } - Debug(3, "Request buffers count is %d", v4l2_data.reqbufs.count); - - v4l2_data.reqbufs.type = v4l2_data.fmt.type; - v4l2_data.reqbufs.memory = V4L2_MEMORY_MMAP; - - if ( vidioctl(vid_fd, VIDIOC_REQBUFS, &v4l2_data.reqbufs) < 0 ) { - if ( errno == EINVAL ) { - Fatal("Unable to initialise memory mapping, unsupported in device"); + /* Set flags and quality. MJPEG should not have the huffman tables defined */ + if (palette == V4L2_PIX_FMT_MJPEG) { + jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI; } else { - Fatal("Unable to initialise memory mapping: %s", strerror(errno)); + jpeg_comp.jpeg_markers |= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI | V4L2_JPEG_MARKER_DHT; + } + jpeg_comp.quality = 85; + + /* Update the JPEG options */ + if (vidioctl(vid_fd, VIDIOC_S_JPEGCOMP, &jpeg_comp) < 0) { + Warning("Failed to set JPEG compression options: %s", strerror(errno)); + } else { + if (vidioctl(vid_fd, VIDIOC_G_JPEGCOMP, &jpeg_comp) < 0) { + Debug(3,"Failed to get updated JPEG compression options: %s", strerror(errno)); + } else { + Debug(4, "JPEG quality: %d, markers: %#x", + jpeg_comp.quality, jpeg_comp.jpeg_markers); + } } } + } // end if JPEG/MJPEG - if ( v4l2_data.reqbufs.count < (v4l_multi_buffer?2:1) ) - Fatal("Insufficient buffer memory %d on video device", v4l2_data.reqbufs.count); + Debug(3, "Setting up request buffers"); - Debug(3, "Setting up data buffers: Channels %d MultiBuffer %d Buffers: %d", - channel_count, v4l_multi_buffer, v4l2_data.reqbufs.count); - - v4l2_data.buffers = new V4L2MappedBuffer[v4l2_data.reqbufs.count]; - capturePictures = new AVFrame *[v4l2_data.reqbufs.count]; - - for ( unsigned int i = 0; i < v4l2_data.reqbufs.count; i++ ) { - struct v4l2_buffer vid_buf; - - memset(&vid_buf, 0, sizeof(vid_buf)); - - //vid_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - vid_buf.type = v4l2_data.fmt.type; - //vid_buf.memory = V4L2_MEMORY_MMAP; - vid_buf.memory = v4l2_data.reqbufs.memory; - vid_buf.index = i; - - if ( vidioctl(vid_fd, VIDIOC_QUERYBUF, &vid_buf) < 0 ) - Fatal("Unable to query video buffer: %s", strerror(errno)); - - v4l2_data.buffers[i].length = vid_buf.length; - v4l2_data.buffers[i].start = mmap(nullptr, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset); - - if ( v4l2_data.buffers[i].start == MAP_FAILED ) - Fatal("Can't map video buffer %u (%u bytes) to memory: %s(%d)", - i, vid_buf.length, strerror(errno), errno); - - capturePictures[i] = av_frame_alloc(); - - if ( !capturePictures[i] ) - Fatal("Could not allocate picture"); - - av_image_fill_arrays( - capturePictures[i]->data, - capturePictures[i]->linesize, - (uint8_t*)v4l2_data.buffers[i].start, - capturePixFormat, - v4l2_data.fmt.fmt.pix.width, - v4l2_data.fmt.fmt.pix.height, - 1); - } // end foreach request buf - - Debug(3, "Configuring video source"); - - if ( vidioctl(vid_fd, VIDIOC_S_INPUT, &channel) < 0 ) { - Fatal("Failed to set camera source %d: %s", channel, strerror(errno)); + memset(&v4l2_data.reqbufs, 0, sizeof(v4l2_data.reqbufs)); + if (channel_count > 1) { + Debug(3, "Channel count is %d", channel_count); + if (v4l_multi_buffer){ + v4l2_data.reqbufs.count = 2*channel_count; + } else { + v4l2_data.reqbufs.count = 1; } - - struct v4l2_input input; - v4l2_std_id stdId; - - memset(&input, 0, sizeof(input)); - input.index = channel; - - if ( vidioctl(vid_fd, VIDIOC_ENUMINPUT, &input) < 0 ) { - Fatal("Failed to enumerate input %d: %s", channel, strerror(errno)); - } - - if ( (input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN) ) { - Error("Device does not support video standard %d", standard); - } - - stdId = standard; - if ((vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0)) { - Error("Failed to set video standard %d: %d %s", standard, errno, strerror(errno)); - } - - Contrast(contrast); - Brightness(brightness); - Hue(hue); - Colour(colour); + } else { + v4l2_data.reqbufs.count = 8; } + Debug(3, "Request buffers count is %d", v4l2_data.reqbufs.count); + + v4l2_data.reqbufs.type = v4l2_data.fmt.type; + v4l2_data.reqbufs.memory = V4L2_MEMORY_MMAP; + + if (vidioctl(vid_fd, VIDIOC_REQBUFS, &v4l2_data.reqbufs) < 0) { + if (errno == EINVAL) { + Fatal("Unable to initialise memory mapping, unsupported in device"); + } else { + Fatal("Unable to initialise memory mapping: %s", strerror(errno)); + } + } + + if (v4l2_data.reqbufs.count < (v4l_multi_buffer?2:1)) + Fatal("Insufficient buffer memory %d on video device", v4l2_data.reqbufs.count); + + Debug(3, "Setting up data buffers: Channels %d MultiBuffer %d Buffers: %d", + channel_count, v4l_multi_buffer, v4l2_data.reqbufs.count); + + v4l2_data.buffers = new V4L2MappedBuffer[v4l2_data.reqbufs.count]; + capturePictures = new AVFrame *[v4l2_data.reqbufs.count]; + + for (unsigned int i = 0; i < v4l2_data.reqbufs.count; i++) { + struct v4l2_buffer vid_buf; + + memset(&vid_buf, 0, sizeof(vid_buf)); + + //vid_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vid_buf.type = v4l2_data.fmt.type; + //vid_buf.memory = V4L2_MEMORY_MMAP; + vid_buf.memory = v4l2_data.reqbufs.memory; + vid_buf.index = i; + + if (vidioctl(vid_fd, VIDIOC_QUERYBUF, &vid_buf) < 0) + Fatal("Unable to query video buffer: %s", strerror(errno)); + + v4l2_data.buffers[i].length = vid_buf.length; + v4l2_data.buffers[i].start = mmap(nullptr, vid_buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, vid_fd, vid_buf.m.offset); + + if (v4l2_data.buffers[i].start == MAP_FAILED) + Fatal("Can't map video buffer %u (%u bytes) to memory: %s(%d)", + i, vid_buf.length, strerror(errno), errno); + + capturePictures[i] = av_frame_alloc(); + + if (!capturePictures[i]) + Fatal("Could not allocate picture"); + + av_image_fill_arrays( + capturePictures[i]->data, + capturePictures[i]->linesize, + (uint8_t*)v4l2_data.buffers[i].start, + capturePixFormat, + v4l2_data.fmt.fmt.pix.width, + v4l2_data.fmt.fmt.pix.height, + 1); + } // end foreach request buf + + Debug(3, "Configuring video source"); + + if (vidioctl(vid_fd, VIDIOC_S_INPUT, &channel) < 0) { + Fatal("Failed to set camera source %d: %s", channel, strerror(errno)); + } + + struct v4l2_input input; + v4l2_std_id stdId; + + memset(&input, 0, sizeof(input)); + input.index = channel; + + if (vidioctl(vid_fd, VIDIOC_ENUMINPUT, &input) < 0) { + Fatal("Failed to enumerate input %d: %s", channel, strerror(errno)); + } + + if ((input.std != V4L2_STD_UNKNOWN) && ((input.std & standard) == V4L2_STD_UNKNOWN)) { + Error("Device does not support video standard %d", standard); + } + + stdId = standard; + if ((vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0)) { + Error("Failed to set video standard %d: %d %s", standard, errno, strerror(errno)); + } + + Contrast(contrast); + Brightness(brightness); + Hue(hue); + Colour(colour); } // end LocalCamera::Initialize void LocalCamera::Terminate() { @@ -1170,126 +1164,47 @@ bool LocalCamera::GetCurrentSettings( return true; } -int LocalCamera::Brightness(int p_brightness) { - if ( v4l_version == 2 ) { - struct v4l2_control vid_control; +int LocalCamera::Control(int vid_id, int newvalue) { + struct v4l2_control vid_control; - memset(&vid_control, 0, sizeof(vid_control)); - vid_control.id = V4L2_CID_BRIGHTNESS; + memset(&vid_control, 0, sizeof(vid_control)); + vid_control.id = vid_id; - if ( vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0 ) { - if ( errno != EINVAL ) { - Error("Unable to query brightness: %s", strerror(errno)); - } else { - Warning("Brightness control is not supported"); - } - //Info( "Brightness 1 %d", vid_control.value ); - } else if ( p_brightness >= 0 ) { - vid_control.value = p_brightness; - - //Info( "Brightness 2 %d", vid_control.value ); - /* The driver may clamp the value or return ERANGE, ignored here */ - if ( vidioctl(vid_fd, VIDIOC_S_CTRL, &vid_control) ) { - if ( errno != ERANGE ) { - Error("Unable to set brightness: %s", strerror(errno)); - } else { - Warning("Given brightness value (%d) may be out-of-range", p_brightness); - } - } - //Info( "Brightness 3 %d", vid_control.value ); + if (vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0) { + if (errno != EINVAL) { + Error("Unable to query control: %s", strerror(errno)); + } else { + Warning("Control is not supported"); + } + } else if (newvalue >= 0) { + vid_control.value = newvalue; + + /* The driver may clamp the value or return ERANGE, ignored here */ + if ( vidioctl(vid_fd, VIDIOC_S_CTRL, &vid_control) ) { + if (errno != ERANGE) { + Error("Unable to set control: %s", strerror(errno)); + } else { + Warning("Given control value (%d) may be out-of-range", newvalue); + } } - return vid_control.value; } - return -1; + return vid_control.value; +} + +int LocalCamera::Brightness(int p_brightness) { + return Control(V4L2_CID_BRIGHTNESS, p_brightness); } int LocalCamera::Hue(int p_hue) { - if ( v4l_version == 2 ) { - struct v4l2_control vid_control; - - memset( &vid_control, 0, sizeof(vid_control) ); - vid_control.id = V4L2_CID_HUE; - - if ( vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0 ) { - if ( errno != EINVAL ) - Error("Unable to query hue: %s", strerror(errno)); - else - Warning("Hue control is not supported"); - } else if ( p_hue >= 0 ) { - vid_control.value = p_hue; - - /* The driver may clamp the value or return ERANGE, ignored here */ - if ( vidioctl(vid_fd, VIDIOC_S_CTRL, &vid_control) < 0 ) { - if ( errno != ERANGE ) { - Error("Unable to set hue: %s", strerror(errno)); - } else { - Warning("Given hue value (%d) may be out-of-range", p_hue); - } - } - } - return vid_control.value; - } - return -1; + return Control(V4L2_CID_HUE, p_hue); } int LocalCamera::Colour( int p_colour ) { - if ( v4l_version == 2 ) { - struct v4l2_control vid_control; - - memset(&vid_control, 0, sizeof(vid_control)); - vid_control.id = V4L2_CID_SATURATION; - - if ( vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0 ) { - if ( errno != EINVAL ) { - Error("Unable to query saturation: %s", strerror(errno)); - } else { - Warning("Saturation control is not supported"); - } - } else if ( p_colour >= 0 ) { - vid_control.value = p_colour; - - /* The driver may clamp the value or return ERANGE, ignored here */ - if ( vidioctl(vid_fd, VIDIOC_S_CTRL, &vid_control) < 0 ) { - if ( errno != ERANGE ) { - Error("Unable to set saturation: %s", strerror(errno)); - } else { - Warning("Given saturation value (%d) may be out-of-range", p_colour); - } - } - } - return vid_control.value; - } - return -1; + return Control(V4L2_CID_SATURATION, p_colour); } -int LocalCamera::Contrast( int p_contrast ) { - if ( v4l_version == 2 ) { - struct v4l2_control vid_control; - - memset(&vid_control, 0, sizeof(vid_control)); - vid_control.id = V4L2_CID_CONTRAST; - - if ( vidioctl(vid_fd, VIDIOC_G_CTRL, &vid_control) < 0 ) { - if ( errno != EINVAL ) { - Error("Unable to query contrast: %s", strerror(errno)); - } else { - Warning("Contrast control is not supported"); - } - } else if ( p_contrast >= 0 ) { - vid_control.value = p_contrast; - - /* The driver may clamp the value or return ERANGE, ignored here */ - if ( vidioctl(vid_fd, VIDIOC_S_CTRL, &vid_control) ) { - if ( errno != ERANGE ) { - Error("Unable to set contrast: %s", strerror(errno)); - } else { - Warning("Given contrast value (%d) may be out-of-range", p_contrast); - } - } - } - return vid_control.value; - } - return -1; +int LocalCamera::Contrast(int p_contrast) { + return Control(V4L2_CID_CONTRAST, p_contrast); } int LocalCamera::PrimeCapture() { diff --git a/src/zm_local_camera.h b/src/zm_local_camera.h index f6991c5de..f702b816f 100644 --- a/src/zm_local_camera.h +++ b/src/zm_local_camera.h @@ -113,6 +113,7 @@ public: int Palette() const { return palette; } int Extras() const { return extras; } + int Control(int vid_id, int newvalue=-1 ); int Brightness( int p_brightness=-1 ) override; int Hue( int p_hue=-1 ) override; int Colour( int p_colour=-1 ) override; From c72d34f17605644fbe768a0938667c736f4d46c1 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 5 Oct 2021 17:43:48 -0400 Subject: [PATCH 010/101] fix validInt to take negative integers. Introduce validCardinal to handle positive integers --- web/includes/functions.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/includes/functions.php b/web/includes/functions.php index 60fb99571..89d2cc8ad 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -1990,6 +1990,10 @@ function requestVar($name, $default='') { // For numbers etc in javascript or tags etc function validInt($input) { + return preg_replace('/[^\-\d]/', '', $input); +} + +function validCardinal($input) { return preg_replace('/\D/', '', $input); } From ba262357634ecf651d9e195144770d54978bbb57 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 5 Oct 2021 17:44:26 -0400 Subject: [PATCH 011/101] further deprecate v4l2 tests and spacing --- src/zm_local_camera.cpp | 412 +++++++++++++++++++--------------------- 1 file changed, 199 insertions(+), 213 deletions(-) diff --git a/src/zm_local_camera.cpp b/src/zm_local_camera.cpp index 795aaab7c..68465fa21 100644 --- a/src/zm_local_camera.cpp +++ b/src/zm_local_camera.cpp @@ -49,130 +49,128 @@ static int vidioctl(int fd, int request, void *arg) { static _AVPIXELFORMAT getFfPixFormatFromV4lPalette(int v4l_version, int palette) { _AVPIXELFORMAT pixFormat = AV_PIX_FMT_NONE; - if ( v4l_version == 2 ) { - switch ( palette ) { + switch (palette) { #if defined(V4L2_PIX_FMT_RGB444) && defined(AV_PIX_FMT_RGB444) - case V4L2_PIX_FMT_RGB444 : - pixFormat = AV_PIX_FMT_RGB444; - break; + case V4L2_PIX_FMT_RGB444 : + pixFormat = AV_PIX_FMT_RGB444; + break; #endif // V4L2_PIX_FMT_RGB444 - case V4L2_PIX_FMT_RGB555 : - pixFormat = AV_PIX_FMT_RGB555; - break; - case V4L2_PIX_FMT_RGB565 : - pixFormat = AV_PIX_FMT_RGB565; - break; - case V4L2_PIX_FMT_BGR24 : - pixFormat = AV_PIX_FMT_BGR24; - break; - case V4L2_PIX_FMT_RGB24 : - pixFormat = AV_PIX_FMT_RGB24; - break; - case V4L2_PIX_FMT_BGR32 : - pixFormat = AV_PIX_FMT_BGRA; - break; - case V4L2_PIX_FMT_RGB32 : - pixFormat = AV_PIX_FMT_ARGB; - break; - case V4L2_PIX_FMT_GREY : - pixFormat = AV_PIX_FMT_GRAY8; - break; - case V4L2_PIX_FMT_YUYV : - pixFormat = AV_PIX_FMT_YUYV422; - break; - case V4L2_PIX_FMT_YUV422P : - pixFormat = AV_PIX_FMT_YUV422P; - break; - case V4L2_PIX_FMT_YUV411P : - pixFormat = AV_PIX_FMT_YUV411P; - break; + case V4L2_PIX_FMT_RGB555 : + pixFormat = AV_PIX_FMT_RGB555; + break; + case V4L2_PIX_FMT_RGB565 : + pixFormat = AV_PIX_FMT_RGB565; + break; + case V4L2_PIX_FMT_BGR24 : + pixFormat = AV_PIX_FMT_BGR24; + break; + case V4L2_PIX_FMT_RGB24 : + pixFormat = AV_PIX_FMT_RGB24; + break; + case V4L2_PIX_FMT_BGR32 : + pixFormat = AV_PIX_FMT_BGRA; + break; + case V4L2_PIX_FMT_RGB32 : + pixFormat = AV_PIX_FMT_ARGB; + break; + case V4L2_PIX_FMT_GREY : + pixFormat = AV_PIX_FMT_GRAY8; + break; + case V4L2_PIX_FMT_YUYV : + pixFormat = AV_PIX_FMT_YUYV422; + break; + case V4L2_PIX_FMT_YUV422P : + pixFormat = AV_PIX_FMT_YUV422P; + break; + case V4L2_PIX_FMT_YUV411P : + pixFormat = AV_PIX_FMT_YUV411P; + break; #ifdef V4L2_PIX_FMT_YUV444 - case V4L2_PIX_FMT_YUV444 : - pixFormat = AV_PIX_FMT_YUV444P; - break; + case V4L2_PIX_FMT_YUV444 : + pixFormat = AV_PIX_FMT_YUV444P; + break; #endif // V4L2_PIX_FMT_YUV444 - case V4L2_PIX_FMT_YUV410 : - pixFormat = AV_PIX_FMT_YUV410P; + case V4L2_PIX_FMT_YUV410 : + pixFormat = AV_PIX_FMT_YUV410P; + break; + case V4L2_PIX_FMT_YUV420 : + pixFormat = AV_PIX_FMT_YUV420P; + break; + case V4L2_PIX_FMT_JPEG : + case V4L2_PIX_FMT_MJPEG : + pixFormat = AV_PIX_FMT_YUVJ444P; + break; + case V4L2_PIX_FMT_UYVY : + pixFormat = AV_PIX_FMT_UYVY422; + break; + // These don't seem to have ffmpeg equivalents + // See if you can match any of the ones in the default clause below!? + case V4L2_PIX_FMT_RGB332 : + case V4L2_PIX_FMT_RGB555X : + case V4L2_PIX_FMT_RGB565X : + //case V4L2_PIX_FMT_Y16 : + //case V4L2_PIX_FMT_PAL8 : + case V4L2_PIX_FMT_YVU410 : + case V4L2_PIX_FMT_YVU420 : + case V4L2_PIX_FMT_Y41P : + //case V4L2_PIX_FMT_YUV555 : + //case V4L2_PIX_FMT_YUV565 : + //case V4L2_PIX_FMT_YUV32 : + case V4L2_PIX_FMT_NV12 : + case V4L2_PIX_FMT_NV21 : + case V4L2_PIX_FMT_YYUV : + case V4L2_PIX_FMT_HI240 : + case V4L2_PIX_FMT_HM12 : + //case V4L2_PIX_FMT_SBGGR8 : + //case V4L2_PIX_FMT_SGBRG8 : + //case V4L2_PIX_FMT_SBGGR16 : + case V4L2_PIX_FMT_DV : + case V4L2_PIX_FMT_MPEG : + case V4L2_PIX_FMT_WNVA : + case V4L2_PIX_FMT_SN9C10X : + case V4L2_PIX_FMT_PWC1 : + case V4L2_PIX_FMT_PWC2 : + case V4L2_PIX_FMT_ET61X251 : + //case V4L2_PIX_FMT_SPCA501 : + //case V4L2_PIX_FMT_SPCA505 : + //case V4L2_PIX_FMT_SPCA508 : + //case V4L2_PIX_FMT_SPCA561 : + //case V4L2_PIX_FMT_PAC207 : + //case V4L2_PIX_FMT_PJPG : + //case V4L2_PIX_FMT_YVYU : + default : + { + Fatal("Can't find swscale format for palette %d", palette); break; - case V4L2_PIX_FMT_YUV420 : - pixFormat = AV_PIX_FMT_YUV420P; - break; - case V4L2_PIX_FMT_JPEG : - case V4L2_PIX_FMT_MJPEG : - pixFormat = AV_PIX_FMT_YUVJ444P; - break; - case V4L2_PIX_FMT_UYVY : - pixFormat = AV_PIX_FMT_UYVY422; - break; - // These don't seem to have ffmpeg equivalents - // See if you can match any of the ones in the default clause below!? - case V4L2_PIX_FMT_RGB332 : - case V4L2_PIX_FMT_RGB555X : - case V4L2_PIX_FMT_RGB565X : - //case V4L2_PIX_FMT_Y16 : - //case V4L2_PIX_FMT_PAL8 : - case V4L2_PIX_FMT_YVU410 : - case V4L2_PIX_FMT_YVU420 : - case V4L2_PIX_FMT_Y41P : - //case V4L2_PIX_FMT_YUV555 : - //case V4L2_PIX_FMT_YUV565 : - //case V4L2_PIX_FMT_YUV32 : - case V4L2_PIX_FMT_NV12 : - case V4L2_PIX_FMT_NV21 : - case V4L2_PIX_FMT_YYUV : - case V4L2_PIX_FMT_HI240 : - case V4L2_PIX_FMT_HM12 : - //case V4L2_PIX_FMT_SBGGR8 : - //case V4L2_PIX_FMT_SGBRG8 : - //case V4L2_PIX_FMT_SBGGR16 : - case V4L2_PIX_FMT_DV : - case V4L2_PIX_FMT_MPEG : - case V4L2_PIX_FMT_WNVA : - case V4L2_PIX_FMT_SN9C10X : - case V4L2_PIX_FMT_PWC1 : - case V4L2_PIX_FMT_PWC2 : - case V4L2_PIX_FMT_ET61X251 : - //case V4L2_PIX_FMT_SPCA501 : - //case V4L2_PIX_FMT_SPCA505 : - //case V4L2_PIX_FMT_SPCA508 : - //case V4L2_PIX_FMT_SPCA561 : - //case V4L2_PIX_FMT_PAC207 : - //case V4L2_PIX_FMT_PJPG : - //case V4L2_PIX_FMT_YVYU : - default : - { - Fatal("Can't find swscale format for palette %d", palette); - break; #if 0 - // These are all spare and may match some of the above - pixFormat = AV_PIX_FMT_YUVJ420P; - pixFormat = AV_PIX_FMT_YUVJ422P; - pixFormat = AV_PIX_FMT_UYVY422; - pixFormat = AV_PIX_FMT_UYYVYY411; - pixFormat = AV_PIX_FMT_BGR565; - pixFormat = AV_PIX_FMT_BGR555; - pixFormat = AV_PIX_FMT_BGR8; - pixFormat = AV_PIX_FMT_BGR4; - pixFormat = AV_PIX_FMT_BGR4_BYTE; - pixFormat = AV_PIX_FMT_RGB8; - pixFormat = AV_PIX_FMT_RGB4; - pixFormat = AV_PIX_FMT_RGB4_BYTE; - pixFormat = AV_PIX_FMT_NV12; - pixFormat = AV_PIX_FMT_NV21; - pixFormat = AV_PIX_FMT_RGB32_1; - pixFormat = AV_PIX_FMT_BGR32_1; - pixFormat = AV_PIX_FMT_GRAY16BE; - pixFormat = AV_PIX_FMT_GRAY16LE; - pixFormat = AV_PIX_FMT_YUV440P; - pixFormat = AV_PIX_FMT_YUVJ440P; - pixFormat = AV_PIX_FMT_YUVA420P; - //pixFormat = AV_PIX_FMT_VDPAU_H264; - //pixFormat = AV_PIX_FMT_VDPAU_MPEG1; - //pixFormat = AV_PIX_FMT_VDPAU_MPEG2; + // These are all spare and may match some of the above + pixFormat = AV_PIX_FMT_YUVJ420P; + pixFormat = AV_PIX_FMT_YUVJ422P; + pixFormat = AV_PIX_FMT_UYVY422; + pixFormat = AV_PIX_FMT_UYYVYY411; + pixFormat = AV_PIX_FMT_BGR565; + pixFormat = AV_PIX_FMT_BGR555; + pixFormat = AV_PIX_FMT_BGR8; + pixFormat = AV_PIX_FMT_BGR4; + pixFormat = AV_PIX_FMT_BGR4_BYTE; + pixFormat = AV_PIX_FMT_RGB8; + pixFormat = AV_PIX_FMT_RGB4; + pixFormat = AV_PIX_FMT_RGB4_BYTE; + pixFormat = AV_PIX_FMT_NV12; + pixFormat = AV_PIX_FMT_NV21; + pixFormat = AV_PIX_FMT_RGB32_1; + pixFormat = AV_PIX_FMT_BGR32_1; + pixFormat = AV_PIX_FMT_GRAY16BE; + pixFormat = AV_PIX_FMT_GRAY16LE; + pixFormat = AV_PIX_FMT_YUV440P; + pixFormat = AV_PIX_FMT_YUVJ440P; + pixFormat = AV_PIX_FMT_YUVA420P; + //pixFormat = AV_PIX_FMT_VDPAU_H264; + //pixFormat = AV_PIX_FMT_VDPAU_MPEG1; + //pixFormat = AV_PIX_FMT_VDPAU_MPEG2; #endif - } - } // end switch palette - } // end if v4l2 + } + } // end switch palette return pixFormat; } // end getFfPixFormatFromV4lPalette @@ -289,7 +287,7 @@ LocalCamera::LocalCamera( BigEndian = 0; } - if (v4l_version == 2 && palette == 0) { + if (palette == 0) { /* Use automatic format selection */ Debug(2,"Using automatic format selection"); palette = AutoSelectFormat(colours); @@ -310,9 +308,6 @@ LocalCamera::LocalCamera( if (capture) { if (last_camera) { - if ((p_method == "v4l2" && v4l_version != 2) || (p_method == "v4l1" && v4l_version != 1)) - Fatal("Different Video For Linux version used for monitors sharing same device"); - if (standard != last_camera->standard) Warning("Different video standards defined for monitors sharing same device, results may be unpredictable or completely wrong"); @@ -324,7 +319,7 @@ LocalCamera::LocalCamera( } /* Get ffmpeg pixel format based on capture palette and endianness */ - capturePixFormat = getFfPixFormatFromV4lPalette( v4l_version, palette ); + capturePixFormat = getFfPixFormatFromV4lPalette(v4l_version, palette); imagePixFormat = AV_PIX_FMT_NONE; } @@ -499,7 +494,6 @@ void LocalCamera::Initialise() { if (!S_ISCHR(st.st_mode)) Fatal("File %s is not device file: %s", device.c_str(), strerror(errno)); - Debug(2, "V4L2 support enabled, using V4L%d api", v4l_version); struct v4l2_capability vid_cap; Debug(3, "Checking video device capabilities"); @@ -1209,46 +1203,42 @@ int LocalCamera::Contrast(int p_contrast) { int LocalCamera::PrimeCapture() { getVideoStream(); - if ( !device_prime ) + if (!device_prime) return 1; - Debug(2, "Priming capture"); - if ( v4l_version == 2 ) { - Debug(3, "Queueing (%d) buffers", v4l2_data.reqbufs.count); - for ( unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++ ) { - struct v4l2_buffer vid_buf; + Debug(3, "Queueing (%d) buffers", v4l2_data.reqbufs.count); + for (unsigned int frame = 0; frame < v4l2_data.reqbufs.count; frame++) { + struct v4l2_buffer vid_buf; - memset(&vid_buf, 0, sizeof(vid_buf)); - if ( v4l2_data.fmt.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ) { - Warning("Unknown type: (%d)", v4l2_data.fmt.type); - } - - vid_buf.type = v4l2_data.fmt.type; - vid_buf.memory = v4l2_data.reqbufs.memory; - vid_buf.index = frame; - - if (vidioctl(vid_fd, VIDIOC_QBUF, &vid_buf) < 0) { - Error("Failed to queue buffer %d: %s", frame, strerror(errno)); - return 0; - } + memset(&vid_buf, 0, sizeof(vid_buf)); + if (v4l2_data.fmt.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + Warning("Unknown type: (%d)", v4l2_data.fmt.type); } - v4l2_data.bufptr = nullptr; - Debug(3, "Starting video stream"); - //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - //enum v4l2_buf_type type = v4l2_data.fmt.type; - enum v4l2_buf_type type = (v4l2_buf_type)v4l2_data.fmt.type; - if (vidioctl(vid_fd, VIDIOC_STREAMON, &type) < 0) { - Error("Failed to start capture stream: %s", strerror(errno)); - return -1; + vid_buf.type = v4l2_data.fmt.type; + vid_buf.memory = v4l2_data.reqbufs.memory; + vid_buf.index = frame; + + if (vidioctl(vid_fd, VIDIOC_QBUF, &vid_buf) < 0) { + Error("Failed to queue buffer %d: %s", frame, strerror(errno)); + return 0; } - } // end if v4l_version == 2 + } + v4l2_data.bufptr = nullptr; + + Debug(3, "Starting video stream"); + //enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + //enum v4l2_buf_type type = v4l2_data.fmt.type; + enum v4l2_buf_type type = (v4l2_buf_type)v4l2_data.fmt.type; + if (vidioctl(vid_fd, VIDIOC_STREAMON, &type) < 0) { + Error("Failed to start capture stream: %s", strerror(errno)); + return -1; + } return 1; } // end LocalCamera::PrimeCapture int LocalCamera::PreCapture() { - //Debug(5, "Pre-capturing"); return 1; } @@ -1267,78 +1257,74 @@ int LocalCamera::Capture(std::shared_ptr &zm_packet) { } // Do the capture, unless we are the second or subsequent camera on a channel, in which case just reuse the buffer - if ( channel_prime ) { - if ( v4l_version == 2 ) { - static struct v4l2_buffer vid_buf; + if (channel_prime) { + static struct v4l2_buffer vid_buf; - memset(&vid_buf, 0, sizeof(vid_buf)); + memset(&vid_buf, 0, sizeof(vid_buf)); - vid_buf.type = v4l2_data.fmt.type; - vid_buf.memory = v4l2_data.reqbufs.memory; + vid_buf.type = v4l2_data.fmt.type; + vid_buf.memory = v4l2_data.reqbufs.memory; - Debug(3, "Capturing %d frames", captures_per_frame); - while ( captures_per_frame ) { - if ( vidioctl(vid_fd, VIDIOC_DQBUF, &vid_buf) < 0 ) { - if ( errno == EIO ) { - Warning("Capture failure, possible signal loss?: %s", strerror(errno)); - } else { - Error("Unable to capture frame %d: %s", vid_buf.index, strerror(errno)); - } + Debug(3, "Capturing %d frames", captures_per_frame); + while (captures_per_frame) { + if (vidioctl(vid_fd, VIDIOC_DQBUF, &vid_buf) < 0) { + if (errno == EIO) { + Warning("Capture failure, possible signal loss?: %s", strerror(errno)); + } else { + Error("Unable to capture frame %d: %s", vid_buf.index, strerror(errno)); + } + return -1; + } + Debug(5, "Captured a frame"); + + v4l2_data.bufptr = &vid_buf; + capture_frame = v4l2_data.bufptr->index; + bytes += vid_buf.bytesused; + + if (--captures_per_frame) { + if (vidioctl(vid_fd, VIDIOC_QBUF, &vid_buf) < 0) { + Error("Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno)); return -1; } - Debug(5, "Captured a frame"); - - v4l2_data.bufptr = &vid_buf; - capture_frame = v4l2_data.bufptr->index; - bytes += vid_buf.bytesused; - - if ( --captures_per_frame ) { - if ( vidioctl(vid_fd, VIDIOC_QBUF, &vid_buf) < 0 ) { - Error("Unable to requeue buffer %d: %s", vid_buf.index, strerror(errno)); - return -1; - } - } - } // while captures_per_frame - - Debug(3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel); - - buffer = (unsigned char *)v4l2_data.buffers[v4l2_data.bufptr->index].start; - buffer_bytesused = v4l2_data.bufptr->bytesused; - bytes += buffer_bytesused; - - if ( (v4l2_data.fmt.fmt.pix.width * v4l2_data.fmt.fmt.pix.height) > (width * height) ) { - Fatal("Captured image dimensions larger than image buffer: V4L2: %dx%d monitor: %dx%d", - v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height, width, height); - } else if ( (v4l2_data.fmt.fmt.pix.width * v4l2_data.fmt.fmt.pix.height) != (width * height) ) { - Error("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d", - v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height, width, height); } - } // end if v4l2 + } // while captures_per_frame - if ( v4l_version == 2 ) { - if ( channel_count > 1 ) { - int next_channel = (channel_index+1)%channel_count; - Debug(3, "Switching video source to %d", channels[next_channel]); - if ( vidioctl(vid_fd, VIDIOC_S_INPUT, &channels[next_channel]) < 0 ) { - Error("Failed to set camera source %d: %s", channels[next_channel], strerror(errno)); - return -1; - } + Debug(3, "Captured frame %d/%d from channel %d", capture_frame, v4l2_data.bufptr->sequence, channel); - v4l2_std_id stdId = standards[next_channel]; - if ( vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0 ) { - Error("Failed to set video format %d: %s", standards[next_channel], strerror(errno)); - } + buffer = (unsigned char *)v4l2_data.buffers[v4l2_data.bufptr->index].start; + buffer_bytesused = v4l2_data.bufptr->bytesused; + bytes += buffer_bytesused; + + if ((v4l2_data.fmt.fmt.pix.width * v4l2_data.fmt.fmt.pix.height) > (width * height)) { + Fatal("Captured image dimensions larger than image buffer: V4L2: %dx%d monitor: %dx%d", + v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height, width, height); + } else if ((v4l2_data.fmt.fmt.pix.width * v4l2_data.fmt.fmt.pix.height) != (width * height)) { + Error("Captured image dimensions differ: V4L2: %dx%d monitor: %dx%d", + v4l2_data.fmt.fmt.pix.width, v4l2_data.fmt.fmt.pix.height, width, height); + } + + if (channel_count > 1) { + int next_channel = (channel_index+1)%channel_count; + Debug(3, "Switching video source to %d", channels[next_channel]); + if (vidioctl(vid_fd, VIDIOC_S_INPUT, &channels[next_channel]) < 0) { + Error("Failed to set camera source %d: %s", channels[next_channel], strerror(errno)); + return -1; } - if ( v4l2_data.bufptr ) { - Debug(3, "Requeueing buffer %d", v4l2_data.bufptr->index); - if ( vidioctl(vid_fd, VIDIOC_QBUF, v4l2_data.bufptr) < 0 ) { - Error("Unable to requeue buffer %d: %s", v4l2_data.bufptr->index, strerror(errno)); - return -1; - } - } else { - Error("Unable to requeue buffer due to not v4l2_data"); + + v4l2_std_id stdId = standards[next_channel]; + if (vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0) { + Error("Failed to set video format %d: %s", standards[next_channel], strerror(errno)); } } + if (v4l2_data.bufptr) { + Debug(3, "Requeueing buffer %d", v4l2_data.bufptr->index); + if (vidioctl(vid_fd, VIDIOC_QBUF, v4l2_data.bufptr) < 0) { + Error("Unable to requeue buffer %d: %s", v4l2_data.bufptr->index, strerror(errno)); + return -1; + } + } else { + Error("Unable to requeue buffer due to not v4l2_data"); + } } /* prime capture */ if (!zm_packet->image) { From 52129c94ec03ddce96033b9b35fe712032235e74 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 5 Oct 2021 17:45:43 -0400 Subject: [PATCH 012/101] spacing. Use a separate boolean to tell if we have specified a new value for controls. This allows negative settings. Fix zmy outputting brightness when contrast is specified. --- src/zmu.cpp | 77 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 31 deletions(-) diff --git a/src/zmu.cpp b/src/zmu.cpp index ddf66a3dd..ec4ae7b86 100644 --- a/src/zmu.cpp +++ b/src/zmu.cpp @@ -257,9 +257,16 @@ int main(int argc, char *argv[]) { int image_idx = -1; int scale = -1; int brightness = -1; + bool have_brightness = false; + int contrast = -1; + bool have_contrast = false; + int hue = -1; + bool have_hue = false; int colour = -1; + bool have_colour = false; + char *zoneString = nullptr; char *username = nullptr; char *password = nullptr; @@ -272,13 +279,13 @@ int main(int argc, char *argv[]) { int option_index = 0; int c = getopt_long(argc, argv, "d:m:vsEDLurwei::S:t::fz::ancqhlB::C::H::O::RWU:P:A:V:T:", long_options, &option_index); - if ( c == -1 ) { + if (c == -1) { break; } switch (c) { case 'd': - if ( optarg ) + if (optarg) device = optarg; break; case 'm': @@ -292,7 +299,7 @@ int main(int argc, char *argv[]) { break; case 'i': function |= ZMU_IMAGE; - if ( optarg ) + if (optarg) image_idx = atoi(optarg); break; case 'S': @@ -300,7 +307,7 @@ int main(int argc, char *argv[]) { break; case 't': function |= ZMU_TIME; - if ( optarg ) + if (optarg) image_idx = atoi(optarg); break; case 'R': @@ -317,7 +324,7 @@ int main(int argc, char *argv[]) { break; case 'z': function |= ZMU_ZONES; - if ( optarg ) + if (optarg) zoneString = optarg; break; case 'a': @@ -349,23 +356,31 @@ int main(int argc, char *argv[]) { break; case 'B': function |= ZMU_BRIGHTNESS; - if ( optarg ) + if (optarg) { + have_brightness = true; brightness = atoi(optarg); + } break; case 'C': function |= ZMU_CONTRAST; - if ( optarg ) + if (optarg) { + have_contrast = true; contrast = atoi(optarg); + } break; case 'H': function |= ZMU_HUE; - if ( optarg ) + if (optarg) { + have_hue = true; hue = atoi(optarg); + } break; case 'O': function |= ZMU_COLOUR; - if ( optarg ) + if (optarg) { + have_colour = true; colour = atoi(optarg); + } break; case 'U': username = optarg; @@ -650,60 +665,60 @@ int main(int argc, char *argv[]) { monitor->DumpSettings(monString, verbose); printf("%s\n", monString); } - if ( function & ZMU_BRIGHTNESS ) { - if ( verbose ) { - if ( brightness >= 0 ) + if (function & ZMU_BRIGHTNESS) { + if (verbose) { + if (have_brightness) printf("New brightness: %d\n", monitor->actionBrightness(brightness)); else printf("Current brightness: %d\n", monitor->actionBrightness()); } else { - if ( have_output ) fputc(separator, stdout); - if ( brightness >= 0 ) + if (have_output) fputc(separator, stdout); + if (have_brightness) printf("%d", monitor->actionBrightness(brightness)); else printf("%d", monitor->actionBrightness()); have_output = true; } } - if ( function & ZMU_CONTRAST ) { - if ( verbose ) { - if ( contrast >= 0 ) - printf("New brightness: %d\n", monitor->actionContrast(contrast)); + if (function & ZMU_CONTRAST) { + if (verbose) { + if (have_contrast) + printf("New contrast: %d\n", monitor->actionContrast(contrast)); else printf("Current contrast: %d\n", monitor->actionContrast()); } else { - if ( have_output ) fputc(separator, stdout); - if ( contrast >= 0 ) + if (have_output) fputc(separator, stdout); + if (have_contrast) printf("%d", monitor->actionContrast(contrast)); else printf("%d", monitor->actionContrast()); have_output = true; } } - if ( function & ZMU_HUE ) { - if ( verbose ) { - if ( hue >= 0 ) + if (function & ZMU_HUE) { + if (verbose) { + if (have_hue) printf("New hue: %d\n", monitor->actionHue(hue)); else printf("Current hue: %d\n", monitor->actionHue()); } else { - if ( have_output ) fputc(separator, stdout); - if ( hue >= 0 ) + if (have_output) fputc(separator, stdout); + if (have_hue) printf("%d", monitor->actionHue(hue)); else printf("%d", monitor->actionHue()); have_output = true; } } - if ( function & ZMU_COLOUR ) { - if ( verbose ) { - if ( colour >= 0 ) + if (function & ZMU_COLOUR) { + if (verbose) { + if (have_colour) printf("New colour: %d\n", monitor->actionColour(colour)); else printf("Current colour: %d\n", monitor->actionColour()); } else { - if ( have_output ) fputc(separator, stdout); - if ( colour >= 0 ) + if (have_output) fputc(separator, stdout); + if (have_colour) printf("%d", monitor->actionColour(colour)); else printf("%d", monitor->actionColour()); @@ -711,7 +726,7 @@ int main(int argc, char *argv[]) { } } - if ( have_output ) { + if (have_output) { printf("\n"); } if ( !function ) { From 94cd3a6e69b1516c254a4d54891173f0a6308be3 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Tue, 5 Oct 2021 19:21:17 -0400 Subject: [PATCH 013/101] Use v4l2-ctrl to list the available controls and display all of them. Use range sliders where appropriate. --- web/ajax/modals/settings.php | 78 +++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 11 deletions(-) diff --git a/web/ajax/modals/settings.php b/web/ajax/modals/settings.php index 59d19ddbb..d2e27a3b4 100644 --- a/web/ajax/modals/settings.php +++ b/web/ajax/modals/settings.php @@ -1,11 +1,11 @@ $_REQUEST['mid'])); $zmuCommand = getZmuCommand(' -m '.escapeshellarg($_REQUEST['mid']).' -B -C -H -O'); $zmuOutput = exec( $zmuCommand ); -if ( $zmuOutput ) { +if ($zmuOutput) { list($brightness, $contrast, $hue, $colour) = explode(' ', $zmuOutput); $monitor->Brightness($brightness); @@ -13,7 +13,6 @@ if ( $zmuOutput ) { $monitor->Hue($hue); $monitor->Colour($colour); } - ?>