Skip to content

Commit

Permalink
Implement screen capturer for macos (based on WebRTC source code).
Browse files Browse the repository at this point in the history
  • Loading branch information
dchapyshev committed Nov 8, 2023
1 parent ded1833 commit cee00da
Show file tree
Hide file tree
Showing 6 changed files with 693 additions and 21 deletions.
28 changes: 28 additions & 0 deletions source/base/desktop/frame.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@

namespace base {

//--------------------------------------------------------------------------------------------------
// static
const float Frame::kStandardDPI = 96.0;

//--------------------------------------------------------------------------------------------------
Frame::Frame(const Size& size,
const PixelFormat& format,
Expand Down Expand Up @@ -68,6 +72,30 @@ void Frame::copyPixelsFrom(const Frame& src_frame, const Point& src_pos, const R
copyPixelsFrom(src_frame.frameDataAtPos(src_pos), src_frame.stride(), dest_rect);
}

//--------------------------------------------------------------------------------------------------
float Frame::scaleFactor() const
{
float scale = 1.0f;

#if defined(OS_MAC)
// At least on Windows the logical and physical pixel are the same
// See http://crbug.com/948362.
if (dpi() != Point(0, 0) && dpi().x() == dpi().y())
scale = dpi().x() / kStandardDPI;
#endif

return scale;
}

//--------------------------------------------------------------------------------------------------
Rect Frame::rect() const
{
const float scale = scaleFactor();
// Only scale the size.
return Rect::makeXYWH(topLeft().x(), topLeft().y(),
size().width() / scale, size().height() / scale);
}

//--------------------------------------------------------------------------------------------------
uint8_t* Frame::frameDataAtPos(const Point& pos) const
{
Expand Down
8 changes: 8 additions & 0 deletions source/base/desktop/frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class SharedMemoryBase;
class Frame
{
public:
static const float kStandardDPI;

virtual ~Frame() = default;

SharedMemoryBase* sharedMemory() const { return shared_memory_; }
Expand All @@ -51,6 +53,12 @@ class Frame
void setTopLeft(const Point& top_left) { top_left_ = top_left; }
const Point& topLeft() const { return top_left_; }

void setDpi(const Point& dpi) { dpi_ = dpi; }
const Point& dpi() const { return dpi_; }

float scaleFactor() const;
Rect rect() const;

void setCapturerType(uint32_t capturer_type) { capturer_type_ = capturer_type; }
uint32_t capturerType() const { return capturer_type_; }

Expand Down
3 changes: 3 additions & 0 deletions source/base/desktop/mac/desktop_configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ struct MacDisplayConfiguration

// Display type, built-in or external.
bool is_builtin = false;

// Display primary or not.
bool is_primary_ = false;
};

typedef std::vector<MacDisplayConfiguration> MacDisplayConfigurations;
Expand Down
1 change: 1 addition & 0 deletions source/base/desktop/mac/desktop_configuration.mm
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ MacDisplayConfiguration getConfigurationForScreen(NSScreen* screen)

// Determine if the display is built-in or external.
display_config.is_builtin = CGDisplayIsBuiltin(display_config.id);
display_config.is_primary_ = CGDisplayIsMain(display_config.id);

return display_config;
}
Expand Down
68 changes: 68 additions & 0 deletions source/base/desktop/screen_capturer_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@

#include "base/desktop/screen_capturer.h"

#include "base/desktop/mouse_cursor.h"
#include "base/desktop/screen_capturer_helper.h"
#include "base/desktop/shared_frame.h"
#include "base/desktop/mac/frame_provider.h"
#include "base/desktop/mac/desktop_configuration.h"
#include "base/desktop/mac/desktop_configuration_monitor.h"
#include "base/threading/thread_checker.h"

#include <vector>

#include <AppKit/NSImage.h>

namespace base {

class ScreenCapturerMac : public ScreenCapturer
Expand All @@ -43,6 +55,62 @@ class ScreenCapturerMac : public ScreenCapturer
void reset() override;

private:
// Returns false if the selected screen is no longer valid.
bool cgBlit(const Frame& frame, const Region& region);

// Called when the screen configuration is changed.
void screenConfigurationChanged();

bool registerRefreshAndMoveHandlers();
void unregisterRefreshAndMoveHandlers();

void screenRefresh(CGDirectDisplayID display_id, CGRectCount count, const CGRect* rect_array,
const Point& display_origin, IOSurfaceRef io_surface);
void releaseBuffers();

std::unique_ptr<Frame> createFrame();

const bool detect_updated_region_;

// Queue of the frames buffers.
FrameQueue<SharedFrame> queue_;

// Current display configuration.
MacDesktopConfiguration desktop_config_;

// Currently selected display, or 0 if the full desktop is selected. On OS X
// 10.6 and before, this is always 0.
CGDirectDisplayID current_display_ = 0;

// The physical pixel bounds of the current screen.
Rect screen_pixel_bounds_;

// The dip to physical pixel scale of the current screen.
float dip_to_pixel_scale_ = 1.0f;

// A thread-safe list of invalid rectangles, and the size of the most
// recently captured screen.
ScreenCapturerHelper helper_;

// Contains an invalid region from the previous capture.
Region last_invalid_region_;

// Monitoring display reconfiguration.
std::shared_ptr<DesktopConfigurationMonitor> desktop_config_monitor_;

// List of streams, one per screen.
std::vector<CGDisplayStreamRef> display_streams_;

// Container holding latest state of the snapshot per displays.
FrameProvider desktop_frame_provider_;

ScreenId current_screen_id_ = kFullDesktopScreenId;

__strong NSImage* last_ns_cursor_ = nullptr;
std::unique_ptr<MouseCursor> last_cursor_;

THREAD_CHECKER(thread_checker_);

DISALLOW_COPY_AND_ASSIGN(ScreenCapturerMac);
};

Expand Down
Loading

0 comments on commit cee00da

Please sign in to comment.