Metadata-Version: 2.4
Name: mirror-space
Version: 0.1.0
Summary: LAN screen broadcasting with adaptive UDP streaming and diff-frame encoding
Author: Mirror-Space Contributors
License: MIT License
        
        Copyright (c) 2026 Mirror-Space Contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/your-username/mirror-space
Project-URL: Repository, https://github.com/your-username/mirror-space
Project-URL: Bug Tracker, https://github.com/your-username/mirror-space/issues
Keywords: screen-sharing,screen-broadcast,lan,udp,streaming,diff-encoding,remote-desktop,opencv
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Video :: Display
Classifier: Topic :: System :: Networking
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mss==9.0.1
Requires-Dist: opencv-python>=4.8.0
Requires-Dist: numpy>=1.24.0
Requires-Dist: pillow>=10.0.0
Requires-Dist: zeroconf>=0.130.0
Provides-Extra: windows
Requires-Dist: pygetwindow>=0.0.9; extra == "windows"
Requires-Dist: pywin32>=306; extra == "windows"
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Requires-Dist: pytest>=7.0; extra == "dev"
Dynamic: license-file

# mirror-space

**LAN screen broadcasting with adaptive UDP streaming and diff-frame encoding.**

mirror-space lets you share your screen to any machine on the same local network with minimal latency. It uses block-based differential compression — sending only the pixels that changed — to keep bandwidth low even at 30 fps, and automatically adapts quality when the network gets congested.

---

## Features

- **Diff-frame encoding** — only changed screen regions are transmitted each frame
- **Adaptive streaming** — FPS, resolution, and JPEG quality adjust in real time based on receiver feedback
- **Zero-config LAN discovery** — mDNS (Zeroconf), UDP beacon, and subnet-scan discovery run in parallel so receivers find broadcasters automatically
- **HWND-based window capture** (Windows) — lock capture to a specific window handle so tab switches never affect the stream
- **Secure session handshake** — six-character access ID prevents accidental cross-session connections
- **Cross-platform receiver** — the receiver runs on Windows, Linux, and macOS

---

## Requirements

| Component | Minimum version |
|-----------|----------------|
| Python    | 3.10           |
| OpenCV    | 4.8.0          |
| NumPy     | 1.24.0         |
| mss       | 9.0.1          |
| Pillow    | 10.0.0         |
| zeroconf  | 0.130.0        |

Windows users who want HWND-based window capture (recommended) also need:

```
pygetwindow>=0.0.9
pywin32>=306
```

---

## Installation

### From PyPI

```bash
pip install mirror-space
```

### With Windows extras (HWND capture + window enumeration)

```bash
pip install "mirror-space[windows]"
```

### From source (development)

```bash
git clone https://github.com/your-username/mirror-space.git
cd mirror-space
pip install -e ".[dev,windows]"
```

---

## Quick Start

### Step 1 — Start the broadcaster (on the machine you want to share)

```bash
mirror-broadcast
```

The broadcaster will:
1. Prompt you to choose a capture region (full screen, specific window, or custom area)
2. Print a **Session Access ID** (e.g. `A1B2C3`)
3. Wait for a receiver to connect

### Step 2 — Start the receiver (on the other machine)

```bash
mirror-receive
```

The receiver will discover broadcasters on the LAN automatically. Select the broadcaster by number and enter the Session Access ID when prompted.

### Manual IP (if auto-discovery fails)

```bash
# broadcaster side — already running, noting its IP
mirror-broadcast

# receiver side — pass broadcaster IP directly
mirror-receive 192.168.1.42
```

### Custom port

```bash
mirror-broadcast 192.168.1.255 8888
mirror-receive 8888 192.168.1.42
```

---

## CLI Reference

### `mirror-broadcast [target_ip [port]]`

| Argument    | Default           | Description                              |
|-------------|-------------------|------------------------------------------|
| `target_ip` | `255.255.255.255` | Receiver IP or broadcast address         |
| `port`      | `9999`            | UDP stream port (feedback on `port + 1`) |

### `mirror-receive [port [broadcaster_ip]]`

| Argument         | Default | Description                              |
|------------------|---------|------------------------------------------|
| `port`           | `9999`  | UDP listen port                          |
| `broadcaster_ip` | _(auto)_ | Skip discovery and connect directly     |

**Receiver keyboard shortcuts** (inside the OpenCV display window):

| Key | Action |
|-----|--------|
| `1`–`9` | Select discovered stream |
| `q` / `ESC` | Quit |

---

## Library API

You can use the encoder and decoder directly in your own code:

```python
import cv2
import numpy as np
from mirror_space import DiffFrameEncoder, DiffFrameDecoder

encoder = DiffFrameEncoder(
    block_size=8,
    threshold=1,
    max_changed_block_ratio=0.45,
    jpeg_quality=95,
)

decoder = DiffFrameDecoder()

# Encode a frame captured by any means
frame = cv2.imread("screenshot.png")
payload = encoder.encode(frame, frame_number=0)

# Decode on the receiver side
reconstructed = decoder.decode(payload)
```

### `DiffFrameEncoder` parameters

| Parameter                | Default | Description |
|--------------------------|---------|-------------|
| `block_size`             | `32`    | Pixel block size for dirty-region detection |
| `threshold`              | `10`    | Per-pixel diff threshold to count a block as changed |
| `max_changed_block_ratio`| `0.30`  | Changed-area ratio above which a key frame is sent |
| `max_diff_payload_ratio` | `0.12`  | Payload-size ratio above which a key frame is sent |
| `jpeg_quality`           | `75`    | JPEG quality for full/key frames (30–95) |
| `enable_motion_detection`| `True`  | Enable Lucas-Kanade optical flow motion frames |

---

## How It Works

```
Broadcaster                          Receiver
──────────                           ────────
ScreenCapture                        UDPReceiver
    │                                    │
    ▼                                    │
DiffFrameEncoder ──UDP fragments──► Reassemble
    │                                    │
    │   KEY_FRAME  (PNG, full res)       ▼
    │   DIFF_FRAME (PNG patches)    DiffFrameDecoder
    │   MOTION_FRAME (residuals)         │
    │                                    ▼
    ◄──STREAM_STATS / KEYFRAME_REQ──  cv2.imshow
AdaptiveController
```

- **KEY_FRAME / FULL_FRAME** — complete PNG-compressed frame; sent on startup, resolution change, or high-motion scenes
- **DIFF_FRAME** — only the changed rectangular regions, each individually PNG-compressed
- **MOTION_FRAME** — Lucas-Kanade optical flow vectors + residual blocks (experimental)
- **Fragmentation** — frames larger than 1400 bytes are split into MTU-safe UDP fragments with a 20-byte header (`total | index | frame_number | send_time_ns`)

---

## Project Structure

```
mirror-space/
├── src/
│   └── mirror_space/
│       ├── __init__.py          # Public API
│       ├── broadcaster.py       # CLI entry point + stream logic
│       ├── receiver.py          # CLI entry point + display loop
│       ├── diff_encoder.py      # DiffFrameEncoder / DiffFrameDecoder
│       └── region_selector.py   # Capture region / window picker
├── docs/
├── pyproject.toml
├── setup.py
├── README.md
├── LICENSE
└── .gitignore
```

---

## Building and Publishing

See [PUBLISHING.md](docs/PUBLISHING.md) for full step-by-step instructions.

---

## License

MIT — see [LICENSE](LICENSE) for details.
