3

My overall goal is to stream my computer screen to another machine on the same local network.

I know taking a screenshot on osx with python has been asked before, specifically here, but I am not satisfied with the answers there. Namely, they are too slow. With my Retina Mac, I have at best 7fps. I currently capture the screenshot like this

def capture(path):
    _, displays, count = CG.CGGetActiveDisplayList(1, None, None)
    url = NSURL.fileURLWithPath_(path)

    dest = Quartz.CGImageDestinationCreateWithURL(
        url, LaunchServices.kUTTypeJPEG, 1, None)

    properties = {
        Quartz.kCGImagePropertyDPIWidth: 72,
        Quartz.kCGImagePropertyDPIHeight: 72,
    }

    image = CG.CGDisplayCreateImage(displays[0])
    Quartz.CGImageDestinationAddImage(dest, image, properties)
    Quartz.CGImageDestinationFinalize(dest)

Which uses Quartz to capture a screenshot at 72 dpi and saves it to a file. Then, I send the image data over a Python socket.

My main question is, is there any obvious place where this process can be sped up? My main two speedup ideas are

  1. How can I send the data from a Quartz CGImageRef directly over the socket, without writing it to a file?
  2. Is there any faster way to capture the screenshot? I don't mind it being lower resolution.
Enrico Borba
  • 1,877
  • 2
  • 14
  • 26
  • Since most of the time each subsequent image will be very similar to the previous one, the obvious way to speed things up would be to only send the parts of the image that have changed since the last time. This is what most screen-sharing programs do, with varying levels of sophistication. (and of course you want to capture the screen image into RAM and avoid writing to and reading from the hard drive, not that I know that Apple APIs well enough to say how that is accomplished) – Jeremy Friesner Dec 18 '17 at 16:57
  • 1
    1) Try just repeatedly capturing the screen and not writing it anywhere to get an idea of the maximum capture rate you are likely to achieve. 2) Try repeatedly sending the same grab (without capturing new ones in between) to see the maximum socket transfer rate. 3) Try compressing the image to JPEG before sending on socket to see if that makes it better or worse. 4) Try multithreading or using GCD to overlap capture and send. – Mark Setchell Dec 18 '17 at 17:56
  • @MarkSetchell, thank you for the suggestions. I've made some benchmarks to see where the bottlenecks really are. Capturing is pretty fast if the information isn't written to disk, so I will try to find a way to send the data over the socket without writing it to a file. Compressing the image doesn't make too much of a difference. I'll try out multithreading/grand central dispatch next. Thanks! – Enrico Borba Dec 19 '17 at 02:18

0 Answers0