go_image_streaming

package module
v0.0.0-...-697a2cd Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2024 License: MIT Imports: 14 Imported by: 0

README

GO Image Streaming over UDP

This repository exists to make my personal UDP streaming library available to whoever wants to use it and also importable.

Features

A coherent RUDP protocol at the most baseline level for transmitting image data across the internet.

The ability to specify size and dimensions of the screenshot

Usage

I've found and tested that this module works well for web-based streaming at lower resolutions. My tests involved just making a socket between the 'server' and a javascript socket for dynamic refreshing.

In most tests anything less than 1200, 1200 pixels streams basically in real-time, while higher resolutions particularly in the 2000+ range end up chugging (I'm not sure of the principals behind fixing this, though I'd imagine big streaming studios and applications would settle for crunchy jpegs or highly optimized custom encoders)

To leverage this library just invoke the:

Listen_for_UDP_stream(port string, mute_io ...interface{})

port -> string: our port for listening to.

mute_io -> ...interface{}: a conditonal flag for logging, leave it to 0 if you don't want logs.

function, which is used to await our special UDP packet from the sender.

Then transmit data to the Listener via a sender application of sorts - or the same application, do what you must I guess.

func Screenshot_and_encode_jpeg_compressed(
	buffer *bytes.Buffer, // Our image buffer
	capture_Region interface{}, // the region interface which anticipates a rect-style object. x,y,w,h
	quality int, // quality in percents. I typically go with 6 for real-time but there's different permutations
	resizer int, // another quality reducer, I keep this at 2 as it divides the resolution and then blows it back up.
) bool

buffer -> *bytes.buffer: This is the buffer we leverage for an image buffer.

capture_Region -> interface{}: This anticipates an object with x,y,w,h parameters in its structure. I'm pretty sure this allows for plug-in-play rects but I could be incorrect, since my only actual tests are manually feeding structs to it.

quality -> int: Takes in quality as a percent, with 100 being the best and 0 being the absolute worst.

resizer -> int: Takes in a resizer factor, which I then under-the-hood resize back to its proper resolution, giving a 'fuzzier/blurrier' image but resulting in less packets which means better speed. I keep this at 2.

Additionally, there's a few other functions included that follow the same style as the one above for sending. Including a PNG counterpart to the example

Examples

Sender Example:

package main

import (
    "bytes"
    "fmt"
    "math"
    "net"

    "github.com/actes2/go_image_streaming"
)

func main() {
    // Resolve the string address to a UDP address
    udpAddr, err := net.ResolveUDPAddr("udp", "localhost:4470")

    if err != nil {
        fmt.Println("We've failed to resolve the udp address")
        return
    }

    img_buff := new(bytes.Buffer)

    conn, _ := net.DialUDP("udp", nil, udpAddr)
    defer conn.Close()

    for {

        // This is gross as I just threw in an in-line struct, but you should be able to feed it any interface motif.
        go_image_streaming.Screenshot_and_encode_jpeg_compressed(img_buff, struct {
            x int
            y int
            w int
            h int
        }{
            x: 0,
            y: 0,
            w: 1000,
            h: 1000,
        },
            50,
            4)
        
        // The reasoning for this portion is because UDP is limited at 65,535 Bytes, forcing us to wrap around our buff
        buff_Max := len(img_buff.Bytes())
        packet_Max := int(math.Ceil((float64(buff_Max) / float64(go_image_streaming.PACKET_SIZE))))


        go_image_streaming.Transmit_UDP(packet_Max, conn, img_buff) // Sends off our packet header and body upon ack.


    }
}

Receiver Example:

package main

import (
    "bytes"
    "image"
    "image/jpeg"
    "log"
    "os"
    "github.com/actes2/go_image_streaming"
)

func main() {
    
    // This hard exits, usually you'd wrap this with a goroutine
    img := go_image_streaming.Listen_for_UDP_stream("4470") 

    // Create a new file to save the PNG
    outFile, err := os.Create("output.jpeg")
    if err != nil {
        log.Fatalf("failed to create output file: %v", err)
    }
    defer outFile.Close()

    // Encode the image to PNG and write it to the file
    if err := jpeg.Encode(outFile, img); err != nil {
        log.Fatalf("failed to encode image to jpeg: %v", err)
    }

    log.Println("PNG image successfully created")
}

Documentation

Index

Constants

View Source
const PACKET_SIZE = 65000

Variables

This section is empty.

Functions

func Listen_for_UDP_stream

func Listen_for_UDP_stream(
	port string,
	mute_io ...interface{},
) image.Image

Listens for a header and payload with our image data.

func Screenshot_and_encode_jpeg

func Screenshot_and_encode_jpeg(buffer *bytes.Buffer, quality ...int) bool

This function captures the whole display.

func Screenshot_and_encode_jpeg_compressed

func Screenshot_and_encode_jpeg_compressed(
	buffer *bytes.Buffer,
	capture_Region interface{},
	quality int,
	resizer int,
) bool

Screenshot and encode as a jpeg to a buffer.

Parameters:

Buffer -> *bytes.buffer - this is the image buffer.

capture_Region -> interface{} - this is a struct for a rect

quality -> int - this is our quality modifier for the jpeg.

resizer -> ...int - this is an optional parameter that allows for us to scale the image by a factor. 4 is basically real-time with a grosser quality.

Output:

This entire function returns true if it succeededs and false if it failes.

func Screenshot_and_encode_png

func Screenshot_and_encode_png(buffer *bytes.Buffer) bool

This function captures the whole display.

func Screenshot_and_encode_png_compressed

func Screenshot_and_encode_png_compressed(
	buffer *bytes.Buffer,
	capture_Region interface{},
	resizer ...int,
) bool

Screenshot and encode as a jpeg to a buffer.

Parameters:

Buffer -> *bytes.buffer - this is the image buffer.

capture_Region -> interface{} - this is a struct for a rect

resizer -> ...int - this is an optional parameter that allows for us to scale the image by a factor. 4 is basically real-time with a grosser quality.

Output:

This entire function returns true if it succeededs and false if it failes.

func Transmit_UDP

func Transmit_UDP(packet_Max int, connection *net.UDPConn, img_Buffer *bytes.Buffer) bool

Summary:

This function is responsible for using our internal RUDP protcol to stream data

Parameters:

packet_Max -> int: Maximum amount of bits we'll be sending

connection -> *net.UDPConn: The UDP Connection object

img_Buffer -> *bytes.Buffer: The Buffer we'll be sending across our protcol

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL