Skip to content

Commit

Permalink
Merge pull request #126 from smasherprog/AppleWork
Browse files Browse the repository at this point in the history
Example fix and permission checks
  • Loading branch information
smasherprog authored Nov 27, 2021
2 parents 3e3e391 + 3343eea commit d2660f9
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 235 deletions.
109 changes: 57 additions & 52 deletions Example_CPP/Screen_Capture_Example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,30 +30,28 @@ void TestCopyContiguous()

std::vector<SL::Screen_Capture::ImageBGRA> strided;

for (unsigned row(0); row < HEIGHT; ++row)
{
for (unsigned col(0); col < WIDTH; ++col)
{
for (unsigned row(0); row < HEIGHT; ++row) {
for (unsigned col(0); col < WIDTH; ++col) {
strided.push_back(SL::Screen_Capture::ImageBGRA{VALID, VALID, VALID, VALID});
}
}

auto bytes = strided.size() * PIXEL_DEPTH;
std::vector<unsigned char> contiguous(bytes, static_cast<unsigned char>(0));
auto image = SL::Screen_Capture::Image{{ 0, 0, WIDTH, HEIGHT }, 0, true, strided.data() };
auto image = SL::Screen_Capture::Image{{0, 0, WIDTH, HEIGHT}, 0, true, strided.data()};

auto result = SCL_Utility_CopyToContiguous(contiguous.data(), &image);
auto distance = std::distance(contiguous.data(), static_cast<unsigned char*>(result));
auto distance = std::distance(contiguous.data(), static_cast<unsigned char *>(result));

if (distance != (WIDTH * HEIGHT * PIXEL_DEPTH)) std::abort();
if (distance != (WIDTH * HEIGHT * PIXEL_DEPTH))
std::abort();

auto const begin(contiguous.begin()), end(contiguous.end());

for (auto current(begin); current != end; ++current)
{
if (*current != VALID) std::abort();
for (auto current(begin); current != end; ++current) {
if (*current != VALID)
std::abort();
}

}

void TestCopyNonContiguous()
Expand All @@ -66,68 +64,59 @@ void TestCopyNonContiguous()

std::vector<SL::Screen_Capture::ImageBGRA> strided;

for (unsigned row(0); row < HEIGHT; ++row)
{
for (unsigned row(0); row < HEIGHT; ++row) {

for (unsigned col(0); col < WIDTH; ++col)
{
for (unsigned col(0); col < WIDTH; ++col) {
strided.push_back(SL::Screen_Capture::ImageBGRA{VALID, VALID, VALID, VALID});
}

for (unsigned pad(0); pad < PADDING; ++pad)
{
for (unsigned pad(0); pad < PADDING; ++pad) {
strided.push_back(SL::Screen_Capture::ImageBGRA{INVALID, INVALID, INVALID, INVALID});
}

}

auto bytes = strided.size() * PIXEL_DEPTH;
std::vector<unsigned char> contiguous(bytes, static_cast<unsigned char>(0));
auto image = SL::Screen_Capture::Image{{ 0, 0, WIDTH, HEIGHT }, STRIDE_IN_BYTES, false, strided.data() };
auto image = SL::Screen_Capture::Image{{0, 0, WIDTH, HEIGHT}, STRIDE_IN_BYTES, false, strided.data()};

auto result = SCL_Utility_CopyToContiguous(contiguous.data(), &image);
auto distance = std::distance(contiguous.data(), static_cast<unsigned char*>(result));
auto distance = std::distance(contiguous.data(), static_cast<unsigned char *>(result));

// Ensures that the pointer incremented by only the amount written.
if (distance != (WIDTH * HEIGHT * PIXEL_DEPTH)) std::abort();
if (distance != (WIDTH * HEIGHT * PIXEL_DEPTH))
std::abort();

auto const begin(contiguous.begin());
auto contiguousEnd(begin), absoluteEnd(contiguous.end());

std::advance(contiguousEnd, WIDTH * HEIGHT * PIXEL_DEPTH);

for (auto current(begin); current != contiguousEnd; ++current)
{
if (*current != VALID) std::abort();
for (auto current(begin); current != contiguousEnd; ++current) {
if (*current != VALID)
std::abort();
}

for (auto current(contiguousEnd); current != absoluteEnd; ++current)
{
if (*current != 0) std::abort();
for (auto current(contiguousEnd); current != absoluteEnd; ++current) {
if (*current != 0)
std::abort();
}

}

void ExtractAndConvertToRGBA(const SL::Screen_Capture::Image &img, unsigned char *dst, size_t dst_size)
{
assert(dst_size >= static_cast<size_t>(SL::Screen_Capture::Width(img) * SL::Screen_Capture::Height(img) * sizeof(SL::Screen_Capture::ImageBGRA)));
auto imgsrc = StartSrc(img);
auto imgdist = dst;
if (img.isContiguous) {
memcpy(imgdist, imgsrc, dst_size);
}
else {
for (auto h = 0; h < Height(img); h++) {
auto startimgsrc = imgsrc;
for (auto w = 0; w < Width(img); w++) {
*imgdist++ = imgsrc->R;
*imgdist++ = imgsrc->G;
*imgdist++ = imgsrc->B;
*imgdist++ = 0; // alpha should be zero
imgsrc++;
}
imgsrc = SL::Screen_Capture::GotoNextRow(img, startimgsrc);
auto imgdist = dst;
for (auto h = 0; h < Height(img); h++) {
auto startimgsrc = imgsrc;
for (auto w = 0; w < Width(img); w++) {
*imgdist++ = imgsrc->R;
*imgdist++ = imgsrc->G;
*imgdist++ = imgsrc->B;
*imgdist++ = 0; // alpha should be zero
imgsrc++;
}
imgsrc = SL::Screen_Capture::GotoNextRow(img, startimgsrc);
}
}

Expand Down Expand Up @@ -175,15 +164,14 @@ void createframegrabber()
})
->onNewFrame([&](const SL::Screen_Capture::Image &img, const SL::Screen_Capture::Monitor &monitor) {
// Uncomment the below code to write the image to disk for debugging
/*
auto r = realcounter.fetch_add(1);
auto s = std::to_string(r) + std::string("MONITORNEW_") + std::string(".jpg");
auto size = Width(img) * Height(img) * sizeof(SL::Screen_Capture::ImageBGRA);
auto imgbuffer(std::make_unique<unsigned char[]>(size));
ExtractAndConvertToRGBA(img, imgbuffer.get(), size);
tje_encode_to_file(s.c_str(), Width(img), Height(img), 4, (const unsigned char *)imgbuffer.get());
tje_encode_to_file(s.c_str(), Width(img), Height(img), 4, (const unsigned char *)imgbuffer.get());
*/

//auto r = realcounter.fetch_add(1);
//auto s = std::to_string(r) + std::string("MONITORNEW_") + std::string(".jpg");
//auto size = Width(img) * Height(img) * sizeof(SL::Screen_Capture::ImageBGRA);
//auto imgbuffer(std::make_unique<unsigned char[]>(size));
//ExtractAndConvertToRGBA(img, imgbuffer.get(), size);
//tje_encode_to_file(s.c_str(), Width(img), Height(img), 4, (const unsigned char *)imgbuffer.get());

if (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - onNewFramestart).count() >=
1000) {
std::cout << "onNewFrame fps" << onNewFramecounter << std::endl;
Expand Down Expand Up @@ -370,6 +358,23 @@ int main()
TestCopyContiguous();
TestCopyNonContiguous();

std::cout << "Checking for Permission to capture the screen" << std::endl;
if (SL::Screen_Capture::IsScreenCaptureEnabled()) {
std::cout << "Application Allowed to Capture the screen!" << std::endl;
}
else if (SL::Screen_Capture::CanRequestScreenCapture()) {
std::cout << "Application Not Allowed to Capture the screen. Waiting for permission " << std::endl;
while (!SL::Screen_Capture::IsScreenCaptureEnabled()) {
SL::Screen_Capture::RequestScreenCapture();
std::cout << " . ";
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
else {
std::cout << "Cannot Capture the screen due to permission issues. Exiting" << std::endl;
return 0;
}

auto goodmonitors = SL::Screen_Capture::GetMonitors();
for (auto &m : goodmonitors) {
std::cout << m << std::endl;
Expand Down
9 changes: 9 additions & 0 deletions include/ScreenCapture.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,15 @@ namespace Screen_Capture {
SC_LITE_EXTERN std::vector<Monitor> GetMonitors();
// will return all windows
SC_LITE_EXTERN std::vector<Window> GetWindows();
// MAC, permission can be requested, but the app still needs to be restarted after permission is given.
// Linux/windows You cannot request permissions, You either have it or not!
SC_LITE_EXTERN bool IsScreenCaptureEnabled();
// MAC, permission can be requested, but the app still needs to be restarted after permission is given.
// Linux/windows You cannot request permissions, You either have it or not!
SC_LITE_EXTERN void RequestScreenCapture();
//MAC, permission can be requested, but the app still needs to be restarted after permission is given.
//Linux/windows You cannot request permissions, You either have it or not!
SC_LITE_EXTERN bool CanRequestScreenCapture();

SC_LITE_EXTERN bool isMonitorInsideBounds(const std::vector<Monitor> &monitors, const Monitor &monitor);
typedef std::function<void(const SL::Screen_Capture::Image &img, const Window &window)> WindowCaptureCallback;
Expand Down
16 changes: 9 additions & 7 deletions include/internal/SCCommon.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once
#include "ScreenCapture.h"
#include <assert.h>
#include <atomic>
#include <thread>
#include <assert.h>
// this is INTERNAL DO NOT USE!
namespace SL {
namespace Screen_Capture {
Expand All @@ -13,7 +13,7 @@ namespace Screen_Capture {
std::shared_ptr<Timer> MouseTimer;
M OnMouseChanged;
W getThingsToWatch;
};
};
struct CommonData {
// Used to indicate abnormal error condition
std::atomic<bool> UnexpectedErrorEvent;
Expand Down Expand Up @@ -49,13 +49,13 @@ namespace Screen_Capture {

enum DUPL_RETURN { DUPL_RETURN_SUCCESS = 0, DUPL_RETURN_ERROR_EXPECTED = 1, DUPL_RETURN_ERROR_UNEXPECTED = 2 };
Monitor CreateMonitor(int index, int id, int h, int w, int ox, int oy, const std::string &n, float scale);
Monitor CreateMonitor(int index, int id, int adapter, int h, int w, int ox, int oy, const std::string &n, float scale);
Monitor CreateMonitor(int index, int id, int adapter, int h, int w, int ox, int oy, const std::string &n, float scale);
SC_LITE_EXTERN Image CreateImage(const ImageRect &imgrect, int rowStrideInBytes, const ImageBGRA *data);
// this function will copy data from the src into the dst. The only requirement is that src must not be larger than dst, but it can be smaller
// void Copy(const Image& dst, const Image& src);

SC_LITE_EXTERN std::vector<ImageRect> GetDifs(const Image &oldimg, const Image &newimg);
template <class F, class C>
template <class F, class C>
void ProcessCapture(const F &data, BaseFrameProcessor &base, const C &mointor, const unsigned char *startsrc, int srcrowstride)
{
ImageRect imageract;
Expand Down Expand Up @@ -100,13 +100,15 @@ namespace Screen_Capture {
memcpy(startdst, startsrc, dstrowstride * Height(mointor));
}
else {
auto monheight = std::max(Height(mointor) -1, 0); ///just in case height is 0
assert(base.ImageBufferSize >= (monheight * srcrowstride) + dstrowstride);///the last row is all I care about, the inbetween rows will be moved up in chunk sizez of srcrowstride. This is a bounds assert
auto monheight = std::max(Height(mointor) - 1, 0); /// just in case height is 0
assert(base.ImageBufferSize >=
(monheight * srcrowstride) + dstrowstride); /// the last row is all I care about, the inbetween rows will be moved up in chunk
/// sizez of srcrowstride. This is a bounds assert
for (auto i = 0; i < Height(mointor); i++) {
memcpy(startdst + (i * dstrowstride), startsrc + (i * srcrowstride), dstrowstride);
}
}
}
}
} // namespace Screen_Captures
} // namespace Screen_Capture
} // namespace SL
4 changes: 2 additions & 2 deletions include/ios/NSFrameProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ namespace SL {
void setMinFrameDuration(NSFrameProcessorImpl*, const std::chrono::microseconds& );
void Pause_(NSFrameProcessorImpl*);
void Resume_(NSFrameProcessorImpl*);
DUPL_RETURN Init(NSFrameProcessorImpl* createdimpl, NSFrameProcessor* parent, const std::chrono::microseconds& );

DUPL_RETURN Init(NSFrameProcessorImpl* createdimpl, NSFrameProcessor* parent, const std::chrono::microseconds& );

class NSFrameProcessor : public BaseFrameProcessor {
NSFrameProcessorImpl* NSFrameProcessorImpl_ = nullptr;
Expand Down
3 changes: 2 additions & 1 deletion releasenotes.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Added OpenGL example
Fixed Example Code Extract to RGB code
Added functions to check if application has permission to capture the screen, Request permission, and can request permission
Loading

0 comments on commit d2660f9

Please sign in to comment.