From d3c8e6da4eb7970ccef7c53a9c31c7f1dfbdc467 Mon Sep 17 00:00:00 2001 From: LordGrey <48840279+Lord-Grey@users.noreply.github.com> Date: Sat, 31 Jul 2021 20:56:45 +0200 Subject: [PATCH] Amlogic updates (#1285) * Limit Amlogic grabber to 30fps * Exclude FB Grabber on Amlogic platform, as FB is included in Amlogic Grabber * Amlogic Grabber - Have continuous feed even when paused. Have no delay when pausing/unpausing * Revert back to CAP_FLAG_AT_END capture method * Clarification on Capture Frequency --- assets/webconfig/i18n/en.json | 2 +- libsrc/api/JsonAPI.cpp | 4 ++- libsrc/grabber/amlogic/AmlogicGrabber.cpp | 43 ++++++++++------------- libsrc/grabber/amlogic/Amvideocap.h | 19 +++++----- 4 files changed, 31 insertions(+), 37 deletions(-) diff --git a/assets/webconfig/i18n/en.json b/assets/webconfig/i18n/en.json index 2cb042c5..b1a3ed1d 100644 --- a/assets/webconfig/i18n/en.json +++ b/assets/webconfig/i18n/en.json @@ -327,7 +327,7 @@ "edt_conf_fbs_timeout_title": "Timeout", "edt_conf_fg_display_expl": "Select which desktop should be captured (multi monitor setup)", "edt_conf_fg_display_title": "Display", - "edt_conf_fg_frequency_Hz_expl": "How fast new pictures are captured", + "edt_conf_fg_frequency_Hz_expl": "How fast new pictures are captured, i.e. it is the sampling rate. Note: The video might be played at a higher or lower frame rate.", "edt_conf_fg_frequency_Hz_title": "Capture frequency", "edt_conf_fg_heading_title": "Screen Capture", "edt_conf_fg_height_expl": "Shrink picture to this height, as raw picture needs a lot of CPU time.", diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp index 1c1ee6e7..f35533bd 100644 --- a/libsrc/api/JsonAPI.cpp +++ b/libsrc/api/JsonAPI.cpp @@ -1541,7 +1541,9 @@ void JsonAPI::handleInputSourceCommand(const QJsonObject& message, const QString delete xcbGrabber; #endif - #ifdef ENABLE_FB + //Ignore FB for Amlogic, as it is embedded in the Amlogic grabber itself + #if defined(ENABLE_FB) && !defined(ENABLE_AMLOGIC) + FramebufferFrameGrabber* fbGrabber = new FramebufferFrameGrabber(); device = fbGrabber->discover(params); if (!device.isEmpty() ) diff --git a/libsrc/grabber/amlogic/AmlogicGrabber.cpp b/libsrc/grabber/amlogic/AmlogicGrabber.cpp index 97185129..f016be60 100644 --- a/libsrc/grabber/amlogic/AmlogicGrabber.cpp +++ b/libsrc/grabber/amlogic/AmlogicGrabber.cpp @@ -30,8 +30,8 @@ const bool verbose = false; const char DEFAULT_FB_DEVICE[] = "/dev/fb0"; const char DEFAULT_VIDEO_DEVICE[] = "/dev/amvideo"; const char DEFAULT_CAPTURE_DEVICE[] = "/dev/amvideocap0"; - -const int AMVIDEOCAP_WAIT_MAX_MS = 50; +const int AMVIDEOCAP_WAIT_MAX_MS = 40; +const int AMVIDEOCAP_DEFAULT_RATE_HZ = 25; } //End of constants @@ -44,7 +44,6 @@ AmlogicGrabber::AmlogicGrabber() , _grabbingModeNotification(0) { _image_ptr = _image_bgr.memptr(); - _useImageResampler = true; } @@ -71,11 +70,16 @@ bool AmlogicGrabber::setupScreen() bool AmlogicGrabber::openDevice(int &fd, const char* dev) { + bool rc = true; if (fd<0) { fd = ::open(dev, O_RDWR); + if ( fd < 0) + { + rc = false; + } } - return fd >= 0; + return rc; } void AmlogicGrabber::closeDevice(int &fd) @@ -92,7 +96,6 @@ bool AmlogicGrabber::isVideoPlaying() bool rc = false; if(QFile::exists(DEFAULT_VIDEO_DEVICE)) { - int videoDisabled = 1; if (!openDevice(_videoDev, DEFAULT_VIDEO_DEVICE)) { @@ -148,8 +151,6 @@ int AmlogicGrabber::grabFrame(Image & image) _lastError = 0; } rc = _fbGrabber.grabFrame(image); - - //usleep(50 * 1000); } } return rc; @@ -189,25 +190,16 @@ int AmlogicGrabber::grabFrame_amvideocap(Image & image) // Read the snapshot into the memory ssize_t bytesRead = pread(_captureDev, _image_ptr, _bytesToRead, 0); - if (bytesRead < 0) + + if ( bytesRead < 0 && !EAGAIN && errno > 0 ) { - int state; - ioctl(_captureDev, AMVIDEOCAP_IOR_GET_STATE, &state); - if (state == AMVIDEOCAP_STATE_ON_CAPTURE) - { - DebugIf(_lastError != 5, _log,"Video playback has been paused"); - _lastError = 5; - } - else - { - ErrorIf(_lastError != 3, _log,"Read of device failed: %d - %s", errno, strerror(errno)); - _lastError = 3; - } + ErrorIf(_lastError != 3, _log,"Capture frame failed failed - Retrying. Error [%d] - %s", errno, strerror(errno)); + _lastError = 3; rc = -1; } else { - if (static_cast(_bytesToRead) != bytesRead) + if (bytesRead != -1 && static_cast(_bytesToRead) != bytesRead) { // Read of snapshot failed ErrorIf(_lastError != 4, _log,"Capture failed to grab entire image [bytesToRead(%d) != bytesRead(%d)]", _bytesToRead, bytesRead); @@ -215,6 +207,9 @@ int AmlogicGrabber::grabFrame_amvideocap(Image & image) rc = -1; } else { + //If bytesRead = -1 but no error or EAGAIN or ENODATA, return last image to cover video pausing scenario + // EAGAIN : // 11 - Resource temporarily unavailable + // ENODATA: // 61 - No data available _imageResampler.processImage(static_cast(_image_ptr), _width, _height, @@ -244,7 +239,7 @@ QJsonObject AmlogicGrabber::discover(const QJsonObject& params) int fbIdx = _fbGrabber.getPath().rightRef(1).toInt(); DebugIf(verbose, _log, "FB device [%s] found with resolution: %dx%d", QSTRING_CSTR(_fbGrabber.getPath()), screenSize.width(), screenSize.height()); - QJsonArray fps = { 1, 5, 10, 15, 20, 25, 30, 40, 50, 60 }; + QJsonArray fps = { 1, 5, 10, 15, 20, 25, 30}; QJsonObject in; @@ -282,7 +277,7 @@ QJsonObject AmlogicGrabber::discover(const QJsonObject& params) inputsDiscovered["video_inputs"] = video_inputs; QJsonObject defaults, video_inputs_default, resolution_default; - resolution_default["fps"] = _fps; + resolution_default["fps"] = AMVIDEOCAP_DEFAULT_RATE_HZ; video_inputs_default["resolution"] = resolution_default; video_inputs_default["inputIdx"] = 0; defaults["video_input"] = video_inputs_default; @@ -328,7 +323,7 @@ bool AmlogicGrabber::setWidthHeight(int width, int height) _height = height; _bytesToRead = _image_bgr.size(); _image_ptr = _image_bgr.memptr(); - rc = _fbGrabber.setWidthHeight(width, height); + rc = _fbGrabber.setWidthHeight(width, height); } return rc; } diff --git a/libsrc/grabber/amlogic/Amvideocap.h b/libsrc/grabber/amlogic/Amvideocap.h index f90b9714..4a0896cd 100644 --- a/libsrc/grabber/amlogic/Amvideocap.h +++ b/libsrc/grabber/amlogic/Amvideocap.h @@ -31,15 +31,12 @@ #define AMVIDEOCAP_IOW_SET_START_CAPTURE _IOW(AMVIDEOCAP_IOC_MAGIC, 0x32, int) #define AMVIDEOCAP_IOW_SET_CANCEL_CAPTURE _IOW(AMVIDEOCAP_IOC_MAGIC, 0x33, int) -#define _A_M 'S' -#define AMSTREAM_IOC_GET_VIDEO_DISABLE _IOR((_A_M), 0x48, int) +#define AMSTREAM_IOC_MAGIC 'S' +#define AMSTREAM_IOC_GET_VIDEO_DISABLE _IOR((AMSTREAM_IOC_MAGIC), 0x48, int) -#define AMVIDEOCAP_IOC_MAGIC 'V' -#define AMVIDEOCAP_IOW_SET_START_CAPTURE _IOW(AMVIDEOCAP_IOC_MAGIC, 0x32, int) - - enum amvideocap_state{ - AMVIDEOCAP_STATE_INIT=0, - AMVIDEOCAP_STATE_ON_CAPTURE=200, - AMVIDEOCAP_STATE_FINISHED_CAPTURE=300, - AMVIDEOCAP_STATE_ERROR=0xffff, - }; +enum amvideocap_state{ + AMVIDEOCAP_STATE_INIT=0, + AMVIDEOCAP_STATE_ON_CAPTURE=200, + AMVIDEOCAP_STATE_FINISHED_CAPTURE=300, + AMVIDEOCAP_STATE_ERROR=0xffff, + };