First commit, have fun!

This commit is contained in:
Maschell 2018-07-03 20:23:12 +02:00
commit 89f4361f52
24 changed files with 4717 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
build/*
*.mod

66
.travis.yml Normal file
View File

@ -0,0 +1,66 @@
language: cpp
os: linux
sudo: false
dist: trusty
branches:
only:
- master
env:
global:
- DEVKITPRO=/opt/devkitpro
- WUT_ROOT=/opt/devkitpro/wut
- DEVKITPPC=/opt/devkitpro/devkitPPC
- PORTLIBREPOS=$HOME/portlibrepos
cache:
directories:
- "$HOME/.local"
- "$DEVKITPRO"
addons:
apt:
packages:
- p7zip-full
before_install:
- mkdir -p "${PORTLIBREPOS}"
- mkdir -p "${DEVKITPRO}"
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget https://github.com/devkitPro/pacman/releases/download/devkitpro-pacman-1.0.1/devkitpro-pacman.deb
-O /tmp/devkitpro-pacman.deb; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo dpkg -i /tmp/devkitpro-pacman.deb;
fi
- yes | sudo dkp-pacman -Syu devkitPPC --needed
- yes | sudo dkp-pacman -Syu general-tools --needed
- wget https://github.com/decaf-emu/wut/releases/download/1.0.0-beta2/wut.linux64.7z
install:
- 7z x -y $(ls | grep "linux") -o${WUT_ROOT}
- cd $PORTLIBREPOS
- git clone https://github.com/Maschell/WiiUPluginSystem.git
- git clone https://github.com/Maschell/libutils.git -b wut
- cd WiiUPluginSystem
- make && make install
- cd $PORTLIBREPOS
- cd libutils
- mkdir build && cd build
- cmake -DCMAKE_TOOLCHAIN_FILE=$WUT_ROOT/share/wut.toolchain.cmake -DCMAKE_INSTALL_PREFIX=$WUT_ROOT
../
- make install
- cd $PORTLIBREPOS
before_script:
- cd $TRAVIS_BUILD_DIR/
script:
- make -j8
before_deploy:
- cd $TRAVIS_BUILD_DIR/
- mkdir -p "wiiu/plugins"
- commit="$(git rev-parse --short=7 HEAD)"
- find -type f -name "*.mod" | xargs -i cp {} wiiu/plugins
- zip -r screenstreamer_wups_nightly_$commit.zip wiiu
- git config --local user.name "Maschell"
- git config --local user.email "Maschell@gmx.de"
- git tag "ScreenshotWUPS-$(date +'%Y%m%d%H%M%S')-$(git log --format=%h -1)"
deploy:
provider: releases
skip_cleanup: true
api_key:
secure: H3sXW8voP9WWwK9PpSD1BXTFmNwss3z6FjX9UVZUOEga7Yu4Na4yUvDtmpEKOxLvFDjAOkS6tyB1UM0Ft9GNi1Qd2cPpSgsJZx5NiYDkiSc7A1UNEbYuMgS+deILnT3qNrTaXMjLeedyMZSTLTt2iThJVP31bwvOTs2nM08PuSrFO8sa0uuLpFyx9uCcznctZsRmSzaTbey/P2rSvTBSOtFHMkfTPLsBndSF1hEn/UUIoOguLUfuq/ovgTr1i6Bm+OMt35oLaaCnSs0JiglUYyXSHP53/14h4CVvQiq69EjHSSrsF46U60j3HA+05eJaxBnr1FZUWfHc/m245G4oSFjvKKCN0hXeRhcLQg1texz1TcI5PIzEgg50UAl6W1LdZVIksGSySojfH/P9FFUkRxtTzzDAgDz/UWNfnx9N9JEZbRsV0hp6goJSnHj/gpu2wxVdYSAVae3NTe7zYT5Le0l0vgpnVhcSVFaZQiy70xb26JPRa0msxFd3BXzYcGV/c+GsxVXoo0yTMpWae4CbWSonkCuNyPTdVQ05+TAP6KjJO9mEWRj+8XuFkRRUELiM7Oe5rHY0nIyQwECbF3yoQP3FDaw+WNhrs+d8ETbZ+uM9UcsCy9h9eGJCgbTU96mVylf9tXCUoVEEUBjXOYgs/joQy83hjCDCS96KVJNLI8g=
file: screenstreamer_wups_nightly_$commit.zip
on:
repo: Maschell/StreamingPluginWiiU

300
Makefile Normal file
View File

@ -0,0 +1,300 @@
# You probably never need to adjust this Makefile.
# All changes can be done in the makefile.mk
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPRO")
endif
export PATH := $(DEVKITPPC)/bin:$(PORTLIBS)/bin:$(PATH)
export PORTLIBS := $(DEVKITPRO)/portlibs/ppc
export WUPSDIR := $(DEVKITPRO)/wups
export GCC_VER := $(shell $(DEVKITPPC)/bin/powerpc-eabi-gcc -dumpversion)
PREFIX := powerpc-eabi-
export AS := $(PREFIX)as
export CC := $(PREFIX)gcc
export CXX := $(PREFIX)g++
export LD := $(PREFIX)ld
export AR := $(PREFIX)ar
export OBJCOPY := $(PREFIX)objcopy
#---------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
ifeq ($(notdir $(CURDIR)),$(BUILD))
include ../makefile.mk
else
include makefile.mk
endif
include $(WUPSDIR)/plugin_makefile.mk
#MAP ?= $(TARGET:.mod=.map)
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
# -Os: optimise size
# -Wall: generate lots of warnings
# -D__wiiu__: define the symbol __wiiu__ (used in some headers)
# -mcpu=750: enable processor specific compilation
# -meabi: enable eabi specific compilation
# -mhard-float: enable hardware floating point instructions
# -nostartfiles: Do not use the standard system startup files when linking
# -ffunction-sections: split up functions so linker can garbage collect
# -fdata-sections: split up data so linker can garbage collect
COMMON_CFLAGS := -Os -Wall -mcpu=750 -meabi -mhard-float -D__WIIU__ -nostartfiles -ffunction-sections -fdata-sections -Wl,-q $(COMMON_CFLAGS)
# -x c: compile as c code
# -std=c11: use the c11 standard
CFLAGS := $(COMMON_CFLAGS) -x c -std=gnu11 $(CFLAGS)
# -x c: compile as c++ code
# -std=gnu++11: use the c++11 standard
CXXFLAGS := $(COMMON_CFLAGS) -x c++ -std=gnu++11 $(CXXFLAGS)
ifeq ($(DO_LOGGING), 1)
CFLAGS += -D__LOGGING__
CXXFLAGS += -D__LOGGING__
endif
#---------------------------------------------------------------------------------
# any extra ld flags
#--------------------------------------------------------------------------------
# --gc-sections: remove unneeded symbols
# -Map: generate a map file
LDFLAGS += -Wl,-Map,$(notdir $@).map,--gc-sections
#---------------------------------------------------------------------------------
Q := @
MAKEFLAGS += --no-print-directory
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS +=
#
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS +=
NEEDS_WUT := 0
ifeq ($(WUT_ENABLE_CPP), 1)
WUT_ENABLE_NEWLIB := 1
LDFLAGS += -Wl,-whole-archive,-lwutstdc++,-no-whole-archive
NEEDS_WUT := 1
endif
ifeq ($(WUT_ENABLE_NEWLIB), 1)
LDFLAGS += -Wl,-whole-archive,-lwutnewlib,-no-whole-archive
NEEDS_WUT := 1
endif
ifeq ($(WUT_DEFAULT_MALLOC), 1)
LDFLAGS += -Wl,-whole-archive,-lwutmalloc,-no-whole-archive
NEEDS_WUT := 1
endif
ifeq ($(NEEDS_WUT), 1)
ifeq ($(strip $(WUT_ROOT)),)
$(error "Please set WUT_ROOT in your environment. export WUT_ROOT=<path to>wut)
endif
CFLAGS += -D__WUT__
CXXFLAGS += -D__WUT__
endif
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export PROJECTDIR := $(CURDIR)
export OUTPUT := $(CURDIR)/$(TARGETDIR)/$(TARGET)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
#---------------------------------------------------------------------------------
# automatically build a list of object files for our project
#---------------------------------------------------------------------------------
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
TTFFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.ttf)))
PNGFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.png)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
export REAL_LD := $(CC)
else
export REAL_LD := $(CXX)
endif
export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \
$(sFILES:.s=.o) $(SFILES:.S=.o) \
$(PNGFILES:.png=.png.o) $(addsuffix .o,$(BINFILES))
#---------------------------------------------------------------------------------
# build a list of include paths
#---------------------------------------------------------------------------------
export INCLUDE_FULL += $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
$(EXTERNAL_INCLUDE)
#---------------------------------------------------------------------------------
# build a list of library paths
#---------------------------------------------------------------------------------
export LIBPATHS_FULL += $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
$(EXTERNAL_LIBPATHS)
export OUTPUT := $(CURDIR)/$(TARGET)
.PHONY: $(BUILD) clean install
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(OUTPUT).mod $(OUTPUT)
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
THIS_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
###############################################################################
# Rule to make everything.
PHONY += all
all : $(OUTPUT)
###############################################################################
# Special build rules
# Rule to make the module file.
$(OUTPUT) : $(OFILES)
@echo "linking ... " $@
@$(REAL_LD) $(OFILES) $(LDFLAGS) $(LIBS) $(LIBPATHS_FULL) -o $@
###############################################################################
# Standard build rules
#---------------------------------------------------------------------------------
%.a:
#---------------------------------------------------------------------------------
@echo $(notdir $@)
@rm -f $@
@$(AR) -rc $@ $^
#---------------------------------------------------------------------------------
%.o: %.cpp
@echo $(notdir $<)
@$(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.c
@echo $(notdir $<)
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.o: %.S
@echo $(notdir $<)
@$(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(INCLUDE_FULL) -c $< -o $@ $(ERROR_FILTER)
#---------------------------------------------------------------------------------
%.png.o : %.png
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.jpg.o : %.jpg
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.ttf.o : %.ttf
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.bin.o : %.bin
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.wav.o : %.wav
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.mp3.o : %.mp3
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
#---------------------------------------------------------------------------------
%.ogg.o : %.ogg
@echo $(notdir $<)
@bin2s -a 32 $< | $(AS) -o $(@)
###############################################################################
# Assembly listing rules
# Rule to make assembly listing.
PHONY += list
list : $(LIST)
# Rule to make the listing file.
%.list : $(TARGET)
$(LOG)
-$Qmkdir -p $(dir $@)
$Q$(OBJDUMP) -d $< > $@
###############################################################################
# Clean rule
# Rule to clean files.
PHONY += clean
clean :
$Qrm -rf $(wildcard $(BUILD) $(BIN))
###############################################################################
# Phony targets
.PHONY : $(PHONY)
-include $(DEPENDS)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------

46
README.md Normal file
View File

@ -0,0 +1,46 @@
# ScreenStreaming for the Wii U [![Build Status](https://api.travis-ci.org/Maschell/StreamingPluginWiiU.svg?branch=master)](https://travis-ci.org/Maschell/StreamingPluginWiiU)
## Still an early PROOF OF CONCEPT. DON'T EXCEPT MAGIC.
This is just a simple plugin that allows you to stream the content of the DRC to any browser.
Currently no configuration without recompiling is supported. It streams in a resolution of 428x240 and tries to achieve 20 fps. This numbers might improve in the future.
But general notes:
- This is still an early PoC
- Encoding is done in software note hardware
- It probably affects gameplay. Loading times are increased, the games could lag. I wouldn't recommend you to play Online.
- All settings are hard coded in the code. In the future it will (hopefully) be possible to choose the screen to stream (TV or DRC), at which resolution and which quality.
- No streaming of the home menu.
- Probably unstable.
- Some games might be too dark some might be too bright or doesn't work at all.
- Currently streaming is achieved via "MJPEG via HTTP", this might change in the future to improve performance.
# Usage
Simply load the plugin with the plugin loader. When the system menu is loaded, you can open `http://<ip of your ip>:8080" on your browser an should see the stream. Whenever you switch the application (e.g. load a game), you need to refresh the site in your browser.
Example when the IP of your IP is 192.168.0.44.
```
http:/192.168.0.44:8080
```
If you don't know the IP of your Wii U, you can start for example [ftpii](https://github.com/dimok789/ftpiiu) which shows the IP when running.
## Wii U Plugin System
This is a plugin for the [Wii U Plugin System (WUPS)](https://github.com/Maschell/WiiUPluginSystem/). To be able to use this plugin you have to place the resulting `.mod` file into the following folder:
```
sd:/wiiu/plugins
```
When the file is placed on the SDCard you can load it with [plugin loader](https://github.com/Maschell/WiiUPluginSystem/).
## Building
For building you need:
- [wups](https://github.com/Maschell/WiiUPluginSystem)
- [dynamic_libs](https://github.com/Maschell/dynamic_libs/tree/lib) for access to the functions.
- [libutils](https://github.com/Maschell/libutils) for common functions.
Install them (in this order) according to their README's. Don't forget the dependencies of the libs itself.
Other external libraries are already located in the `libs` folder.
- libjpeg
- libturbojpeg

74
libs/include/jconfig.h Normal file
View File

@ -0,0 +1,74 @@
/* jconfig.h. Generated from jconfig.h.in by configure. */
/* Version ID for the JPEG library.
* Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
*/
#define JPEG_LIB_VERSION 62
/* libjpeg-turbo version */
#define LIBJPEG_TURBO_VERSION 1.5.3
/* libjpeg-turbo version in integer form */
#define LIBJPEG_TURBO_VERSION_NUMBER 1005003
/* Support arithmetic encoding */
#define C_ARITH_CODING_SUPPORTED 1
/* Support arithmetic decoding */
#define D_ARITH_CODING_SUPPORTED 1
/*
* Define BITS_IN_JSAMPLE as either
* 8 for 8-bit sample values (the usual setting)
* 12 for 12-bit sample values
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
* JPEG standard, and the IJG code does not support anything else!
* We do not support run-time selection of data precision, sorry.
*/
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if the system has the type `unsigned char'. */
#define HAVE_UNSIGNED_CHAR 1
/* Define to 1 if the system has the type `unsigned short'. */
#define HAVE_UNSIGNED_SHORT 1
/* Compiler does not support pointers to undefined structures. */
/* #undef INCOMPLETE_TYPES_BROKEN */
/* Support in-memory source/destination managers */
#define MEM_SRCDST_SUPPORTED 1
/* Define if you have BSD-like bzero and bcopy in <strings.h> rather than
memset/memcpy in <string.h>. */
/* #undef NEED_BSD_STRINGS */
/* Define if you need to include <sys/types.h> to get size_t. */
#define NEED_SYS_TYPES_H 1
/* Define if your (broken) compiler shifts signed values as if they were
unsigned. */
/* #undef RIGHT_SHIFT_IS_UNSIGNED */
/* Use accelerated SIMD routines. */
/* #undef WITH_SIMD */
/* Define to 1 if type `char' is unsigned and you are not using gcc. */
#ifndef __CHAR_UNSIGNED__
/* # undef __CHAR_UNSIGNED__ */
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `unsigned int' if <sys/types.h> does not define. */
/* #undef size_t */

317
libs/include/jerror.h Normal file
View File

@ -0,0 +1,317 @@
/*
* jerror.h
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1994-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2014, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* This file defines the error and message codes for the JPEG library.
* Edit this file to add new codes, or to translate the message strings to
* some other language.
* A set of error-reporting macros are defined too. Some applications using
* the JPEG library may wish to include this file to get the error codes
* and/or the macros.
*/
/*
* To define the enum list of message codes, include this file without
* defining macro JMESSAGE. To create a message string table, include it
* again with a suitable JMESSAGE definition (see jerror.c for an example).
*/
#ifndef JMESSAGE
#ifndef JERROR_H
/* First time through, define the enum list */
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
#define JMESSAGE(code,string)
#endif /* JERROR_H */
#endif /* JMESSAGE */
#ifdef JMAKE_ENUM_LIST
typedef enum {
#define JMESSAGE(code,string) code ,
#endif /* JMAKE_ENUM_LIST */
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
/* For maintenance convenience, list is alphabetical by message code name */
#if JPEG_LIB_VERSION < 70
JMESSAGE(JERR_ARITH_NOTIMPL,
"Sorry, arithmetic coding is not implemented")
#endif
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
#if JPEG_LIB_VERSION >= 70
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
#endif
JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
#if JPEG_LIB_VERSION >= 70
JMESSAGE(JERR_BAD_DROP_SAMPLING,
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
#endif
JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
JMESSAGE(JERR_BAD_LIB_VERSION,
"Wrong JPEG library version: library is %d, caller expects %d")
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
JMESSAGE(JERR_BAD_PROGRESSION,
"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
JMESSAGE(JERR_BAD_PROG_SCRIPT,
"Invalid progressive parameters at scan script entry %d")
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
JMESSAGE(JERR_BAD_STRUCT_SIZE,
"JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
JMESSAGE(JERR_FILE_READ, "Input file read error")
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
"Cannot transcode due to multiple use of quantization table %d")
JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
#if JPEG_LIB_VERSION >= 70
JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
#endif
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
JMESSAGE(JERR_QUANT_COMPONENTS,
"Cannot quantize more than %d color components")
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
JMESSAGE(JERR_TFILE_WRITE,
"Write failed on temporary file --- out of disk space?")
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT_SHORT)
JMESSAGE(JMSG_VERSION, JVERSION)
JMESSAGE(JTRC_16BIT_TABLES,
"Caution: quantization tables are too coarse for baseline JPEG")
JMESSAGE(JTRC_ADOBE,
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
JMESSAGE(JTRC_EOI, "End Of Image")
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
"Warning: thumbnail image size does not match data length %u")
JMESSAGE(JTRC_JFIF_EXTENSION,
"JFIF extension marker: type 0x%02x, length %u")
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
JMESSAGE(JTRC_RST, "RST%d")
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
"Smoothing not supported with nonstandard sampling ratios")
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
JMESSAGE(JTRC_SOI, "Start of Image")
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
JMESSAGE(JTRC_THUMB_JPEG,
"JFIF extension marker: JPEG-compressed thumbnail image, length %u")
JMESSAGE(JTRC_THUMB_PALETTE,
"JFIF extension marker: palette thumbnail image, length %u")
JMESSAGE(JTRC_THUMB_RGB,
"JFIF extension marker: RGB thumbnail image, length %u")
JMESSAGE(JTRC_UNKNOWN_IDS,
"Unrecognized component IDs %d %d %d, assuming YCbCr")
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
#if JPEG_LIB_VERSION >= 70
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
#endif
JMESSAGE(JWRN_BOGUS_PROGRESSION,
"Inconsistent progression sequence for component %d coefficient %d")
JMESSAGE(JWRN_EXTRANEOUS_DATA,
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
JMESSAGE(JWRN_MUST_RESYNC,
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
#if JPEG_LIB_VERSION < 70
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
#if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED)
JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
#endif
#endif
#ifdef JMAKE_ENUM_LIST
JMSG_LASTMSGCODE
} J_MESSAGE_CODE;
#undef JMAKE_ENUM_LIST
#endif /* JMAKE_ENUM_LIST */
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
#undef JMESSAGE
#ifndef JERROR_H
#define JERROR_H
/* Macros to simplify using the error and trace message stuff */
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
#define ERREXIT(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT3(cinfo,code,p1,p2,p3) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXITS(cinfo,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
#define WARNMS(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
/* Informational/debugging messages */
#define TRACEMS(cinfo,lvl,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS1(cinfo,lvl,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMSS(cinfo,lvl,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#endif /* JERROR_H */

421
libs/include/jmorecfg.h Normal file
View File

@ -0,0 +1,421 @@
/*
* jmorecfg.h
*
* This file was part of the Independent JPEG Group's software:
* Copyright (C) 1991-1997, Thomas G. Lane.
* Modified 1997-2009 by Guido Vollbeding.
* libjpeg-turbo Modifications:
* Copyright (C) 2009, 2011, 2014-2015, D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg
* file.
*
* This file contains additional configuration options that customize the
* JPEG software for special applications or support machine-dependent
* optimizations. Most users will not need to touch this file.
*/
/*
* Maximum number of components (color channels) allowed in JPEG image.
* To meet the letter of the JPEG spec, set this to 255. However, darn
* few applications need more than 4 channels (maybe 5 for CMYK + alpha
* mask). We recommend 10 as a reasonable compromise; use 4 if you are
* really short on memory. (Each allowed component costs a hundred or so
* bytes of storage, whether actually used in an image or not.)
*/
#define MAX_COMPONENTS 10 /* maximum number of image components */
/*
* Basic data types.
* You may need to change these if you have a machine with unusual data
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
* but it had better be at least 16.
*/
/* Representation of a single sample (pixel element value).
* We frequently allocate large arrays of these, so it's important to keep
* them small. But if you have memory to burn and access to char or short
* arrays is very slow on your hardware, you might want to change these.
*/
#if BITS_IN_JSAMPLE == 8
/* JSAMPLE should be the smallest type that will hold the values 0..255.
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef __CHAR_UNSIGNED__
#define GETJSAMPLE(value) ((int) (value))
#else
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
#endif /* BITS_IN_JSAMPLE == 8 */
#if BITS_IN_JSAMPLE == 12
/* JSAMPLE should be the smallest type that will hold the values 0..4095.
* On nearly all machines "short" will do nicely.
*/
typedef short JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
#endif /* BITS_IN_JSAMPLE == 12 */
/* Representation of a DCT frequency coefficient.
* This should be a signed value of at least 16 bits; "short" is usually OK.
* Again, we allocate large arrays of these, but you can change to int
* if you have memory to burn and "short" is really slow.
*/
typedef short JCOEF;
/* Compressed datastreams are represented as arrays of JOCTET.
* These must be EXACTLY 8 bits wide, at least once they are written to
* external storage. Note that when using the stdio data source/destination
* managers, this is also the data type passed to fread/fwrite.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JOCTET;
#define GETJOCTET(value) (value)
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JOCTET;
#ifdef __CHAR_UNSIGNED__
#define GETJOCTET(value) (value)
#else
#define GETJOCTET(value) ((value) & 0xFF)
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
/* These typedefs are used for various table entries and so forth.
* They must be at least as wide as specified; but making them too big
* won't cost a huge amount of memory, so we don't provide special
* extraction code like we did for JSAMPLE. (In other words, these
* typedefs live at a different point on the speed/space tradeoff curve.)
*/
/* UINT8 must hold at least the values 0..255. */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char UINT8;
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef __CHAR_UNSIGNED__
typedef char UINT8;
#else /* not __CHAR_UNSIGNED__ */
typedef short UINT8;
#endif /* __CHAR_UNSIGNED__ */
#endif /* HAVE_UNSIGNED_CHAR */
/* UINT16 must hold at least the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short UINT16;
#else /* not HAVE_UNSIGNED_SHORT */
typedef unsigned int UINT16;
#endif /* HAVE_UNSIGNED_SHORT */
/* INT16 must hold at least the values -32768..32767. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
typedef short INT16;
#endif
/* INT32 must hold at least signed 32-bit values.
*
* NOTE: The INT32 typedef dates back to libjpeg v5 (1994.) Integers were
* sometimes 16-bit back then (MS-DOS), which is why INT32 is typedef'd to
* long. It also wasn't common (or at least as common) in 1994 for INT32 to be
* defined by platform headers. Since then, however, INT32 is defined in
* several other common places:
*
* Xmd.h (X11 header) typedefs INT32 to int on 64-bit platforms and long on
* 32-bit platforms (i.e always a 32-bit signed type.)
*
* basetsd.h (Win32 header) typedefs INT32 to int (always a 32-bit signed type
* on modern platforms.)
*
* qglobal.h (Qt header) typedefs INT32 to int (always a 32-bit signed type on
* modern platforms.)
*
* This is a recipe for conflict, since "long" and "int" aren't always
* compatible types. Since the definition of INT32 has technically been part
* of the libjpeg API for more than 20 years, we can't remove it, but we do not
* use it internally any longer. We instead define a separate type (JLONG)
* for internal use, which ensures that internal behavior will always be the
* same regardless of any external headers that may be included.
*/
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
#ifndef _BASETSD_H /* MinGW is slightly different */
#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
typedef long INT32;
#endif
#endif
#endif
#endif
/* Datatype used for image dimensions. The JPEG standard only supports
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
* "unsigned int" is sufficient on all machines. However, if you need to
* handle larger images and you don't mind deviating from the spec, you
* can change this datatype. (Note that changing this datatype will
* potentially require modifying the SIMD code. The x86-64 SIMD extensions,
* in particular, assume a 32-bit JDIMENSION.)
*/
typedef unsigned int JDIMENSION;
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
/* These macros are used in all function definitions and extern declarations.
* You could modify them if you need to change function linkage conventions;
* in particular, you'll need to do that to make the library a Windows DLL.
* Another application is to make all functions global for use with debuggers
* or code profilers that require it.
*/
/* a function called through method pointers: */
#define METHODDEF(type) static type
/* a function used only in its module: */
#define LOCAL(type) static type
/* a function referenced thru EXTERNs: */
#define GLOBAL(type) type
/* a reference to a GLOBAL function: */
#define EXTERN(type) extern type
/* Originally, this macro was used as a way of defining function prototypes
* for both modern compilers as well as older compilers that did not support
* prototype parameters. libjpeg-turbo has never supported these older,
* non-ANSI compilers, but the macro is still included because there is some
* software out there that uses it.
*/
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS),
* but again, some software relies on this macro.
*/
#undef FAR
#define FAR
/*
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
* in standard header files. Or you may have conflicts with application-
* specific header files that you want to include together with these files.
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
*/
#ifndef HAVE_BOOLEAN
typedef int boolean;
#endif
#ifndef FALSE /* in case these macros already exist */
#define FALSE 0 /* values of boolean */
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
* The remaining options affect code selection within the JPEG library,
* but they don't need to be visible to most applications using the library.
* To minimize application namespace pollution, the symbols won't be
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
*/
#ifdef JPEG_INTERNALS
#define JPEG_INTERNAL_OPTIONS
#endif
#ifdef JPEG_INTERNAL_OPTIONS
/*
* These defines indicate whether to include various optional functions.
* Undefining some of these symbols will produce a smaller but less capable
* library. Note that you can leave certain source files out of the
* compilation/linking process if you've #undef'd the corresponding symbols.
* (You may HAVE to do that if your compiler doesn't like null source files.)
*/
/* Capability options common to encoder and decoder: */
#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
/* Encoder capability options: */
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
* precision, so jchuff.c normally uses entropy optimization to compute
* usable tables for higher precision. If you don't want to do optimization,
* you'll have to supply different default Huffman tables.
* The exact same statements apply for progressive JPEG: the default tables
* don't work for progressive mode. (This may get fixed, however.)
*/
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
/* Decoder capability options: */
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
/* more capability options later, no doubt */
/*
* The RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros are a vestigial
* feature of libjpeg. The idea was that, if an application developer needed
* to compress from/decompress to a BGR/BGRX/RGBX/XBGR/XRGB buffer, they could
* change these macros, rebuild libjpeg, and link their application statically
* with it. In reality, few people ever did this, because there were some
* severe restrictions involved (cjpeg and djpeg no longer worked properly,
* compressing/decompressing RGB JPEGs no longer worked properly, and the color
* quantizer wouldn't work with pixel sizes other than 3.) Further, since all
* of the O/S-supplied versions of libjpeg were built with the default values
* of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications have
* come to regard these values as immutable.
*
* The libjpeg-turbo colorspace extensions provide a much cleaner way of
* compressing from/decompressing to buffers with arbitrary component orders
* and pixel sizes. Thus, we do not support changing the values of RGB_RED,
* RGB_GREEN, RGB_BLUE, or RGB_PIXELSIZE. In addition to the restrictions
* listed above, changing these values will also break the SIMD extensions and
* the regression tests.
*/
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
#define RGB_GREEN 1 /* Offset of Green */
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
#define JPEG_NUMCS 17
#define EXT_RGB_RED 0
#define EXT_RGB_GREEN 1
#define EXT_RGB_BLUE 2
#define EXT_RGB_PIXELSIZE 3
#define EXT_RGBX_RED 0
#define EXT_RGBX_GREEN 1
#define EXT_RGBX_BLUE 2
#define EXT_RGBX_PIXELSIZE 4
#define EXT_BGR_RED 2
#define EXT_BGR_GREEN 1
#define EXT_BGR_BLUE 0
#define EXT_BGR_PIXELSIZE 3
#define EXT_BGRX_RED 2
#define EXT_BGRX_GREEN 1
#define EXT_BGRX_BLUE 0
#define EXT_BGRX_PIXELSIZE 4
#define EXT_XBGR_RED 3
#define EXT_XBGR_GREEN 2
#define EXT_XBGR_BLUE 1
#define EXT_XBGR_PIXELSIZE 4
#define EXT_XRGB_RED 1
#define EXT_XRGB_GREEN 2
#define EXT_XRGB_BLUE 3
#define EXT_XRGB_PIXELSIZE 4
static const int rgb_red[JPEG_NUMCS] = {
-1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED,
EXT_BGR_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED,
EXT_RGBX_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED,
-1
};
static const int rgb_green[JPEG_NUMCS] = {
-1, -1, RGB_GREEN, -1, -1, -1, EXT_RGB_GREEN, EXT_RGBX_GREEN,
EXT_BGR_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN,
EXT_RGBX_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN,
-1
};
static const int rgb_blue[JPEG_NUMCS] = {
-1, -1, RGB_BLUE, -1, -1, -1, EXT_RGB_BLUE, EXT_RGBX_BLUE,
EXT_BGR_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE,
EXT_RGBX_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE,
-1
};
static const int rgb_pixelsize[JPEG_NUMCS] = {
-1, -1, RGB_PIXELSIZE, -1, -1, -1, EXT_RGB_PIXELSIZE, EXT_RGBX_PIXELSIZE,
EXT_BGR_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE,
EXT_RGBX_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE,
-1
};
/* Definitions for speed-related optimizations. */
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
*/
#ifndef MULTIPLIER
#ifndef WITH_SIMD
#define MULTIPLIER int /* type for fastest integer multiply */
#else
#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
#endif
#endif
/* FAST_FLOAT should be either float or double, whichever is done faster
* by your compiler. (Note that this type is only used in the floating point
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
*/
#ifndef FAST_FLOAT
#define FAST_FLOAT float
#endif
#endif /* JPEG_INTERNAL_OPTIONS */

1122
libs/include/jpeglib.h Normal file

File diff suppressed because it is too large Load Diff

1545
libs/include/turbojpeg.h Normal file

File diff suppressed because it is too large Load Diff

BIN
libs/lib/libjpeg.a Normal file

Binary file not shown.

BIN
libs/lib/libturbojpeg.a Normal file

Binary file not shown.

64
makefile.mk Normal file
View File

@ -0,0 +1,64 @@
# Compiling the projects with libutils logging code?
DO_LOGGING := 1
# Links against the wut implementation of newlib, this is useful for using any function
# from the C standard library
WUT_ENABLE_NEWLIB := 0
# Links against the wut implementation of stdcpp, this is useful for using any function
# from the C++ standard library. This will enable WUT_ENABLE_NEWLIB if you have not already done so.
WUT_ENABLE_CPP := 0
# By default newlib will allocate 90% of the default heap for use with sbrk & malloc,
# if this is unacceptable to you then you should use this as it replaces the newlib
# malloc functions which ones which redirect to the CafeOS default heap functions
# such as MEMAllocFromDefaultHeap.
WUT_DEFAULT_MALLOC := 1
# Target filename
TARGET := screenstreamer.mod
# Source directories
SOURCES := src/
# Data directories
DATA :=
# Include directories
INCLUDES := src
#---------------------------------------------------------------------------------
# options for code generation and linking
#---------------------------------------------------------------------------------
# Extra C AND C++ compiler flags
COMMON_CFLAGS :=
# Extra C compiler flags
CFLAGS :=
# Extra C++ compiler flags
CXXFLAGS :=
# Extra linking flags for all linking steps
LDFLAGS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(WUPSDIR) $(WUT_ROOT) $(CURDIR)/libs
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS := -lwups -lutilswut -lcoreinit -lturbojpeg -lgx2 -lvpad -lnsysnet
#---------------------------------------------------------------------------------
# Will be added to the final lib paths
# example:
# -L$C:/library1/lib
#---------------------------------------------------------------------------------
EXTERNAL_LIBPATHS :=
#---------------------------------------------------------------------------------
# Will be added to the final include paths
# -IC:/library1/include
#---------------------------------------------------------------------------------
EXTERNAL_INCLUDE := -I$(WUT_ROOT)/include/libutilswut

134
src/EncodingHelper.cpp Normal file
View File

@ -0,0 +1,134 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include <vector>
#include "EncodingHelper.h"
#include "MJPEGStreamServer.hpp"
#include "stream_utils.h"
#include "JpegInformation.h"
#include <gx2/event.h>
#include <gx2/surface.h>
#include <gx2/mem.h>
EncodingHelper *EncodingHelper::instance = NULL;
OSMessageQueue encodeQueue __attribute__((section(".data")));
OSMessage encodeQueueMessages[ENCODE_QUEUE_MESSAGE_COUNT] __attribute__((section(".data")));
void EncodingHelper::StartAsyncThread() {
int32_t priority = 17;
this->pThread = CThread::create(DoAsyncThread, this, CThread::eAttributeAffCore0, priority,0x40000);
this->pThread->resumeThread();
}
void EncodingHelper::DoAsyncThread(CThread *thread, void *arg) {
EncodingHelper * arg_instance = (EncodingHelper *) arg;
return arg_instance->DoAsyncThreadInternal(thread);
}
JpegInformation * convertToJpeg(uint8_t * sourceBuffer, uint32_t width, uint32_t height, uint32_t pitch, uint32_t format, int quality) {
if(sourceBuffer == NULL) {
DEBUG_FUNCTION_LINE("path or buffer NULL\n");
return NULL;
}
if(( format != GX2_SURFACE_FORMAT_SRGB_R8_G8_B8_A8 &&
format != GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8)) {
DEBUG_FUNCTION_LINE("Format not supported\n");
return NULL;
}
tjhandle handle = tjInitCompress();
if(handle == NULL) {
const char *err = (const char *) tjGetErrorStr();
DEBUG_FUNCTION_LINE("TJ Error: %s UNABLE TO INIT TJ Compressor Object\n",err);
return NULL;
}
int jpegQual = quality;
int nbands = 4;
int flags = 0;
unsigned char* jpegBuf = NULL;
int pixelFormat = TJPF_GRAY;
int jpegSubsamp = TJSAMP_GRAY;
if(nbands == 4) {
pixelFormat = TJPF_RGBA;
jpegSubsamp = TJSAMP_411;
}
unsigned long jpegSize = 0;
int tj_stat = tjCompress2( handle, sourceBuffer, width, pitch * nbands, height, pixelFormat, &(jpegBuf), &jpegSize, jpegSubsamp, jpegQual, flags);
if(tj_stat != 0) {
const char *err = (const char *) tjGetErrorStr();
DEBUG_FUNCTION_LINE("TurboJPEG Error: %s UNABLE TO COMPRESS JPEG IMAGE\n", err);
tjDestroy(handle);
} else {
return new JpegInformation(handle, jpegBuf, jpegSize);
}
return NULL;
}
void EncodingHelper::DoAsyncThreadInternal(CThread *thread) {
serverRunning = true;
OSMessage message;
GX2ColorBuffer * colorBuffer = NULL;
shouldExit = false;
while(true) {
//DEBUG_FUNCTION_LINE("Waiting for message in EncoderHelper\n");
if(!OSReceiveMessage(&encodeQueue,&message,OS_MESSAGE_FLAGS_NONE)) {
//DEBUG_FUNCTION_LINE("... %08X\n",this->shouldExit);
if(this->shouldExit) {
DEBUG_FUNCTION_LINE("We should stop\n");
break;
}
OSSleepTicks(OSMicrosecondsToTicks(5000));
continue;
}
DCFlushRange(&message,sizeof(OSMessage));
//DEBUG_FUNCTION_LINE("Received message %08X: data1 %08X\n",message.message,message.args[1]);
if((uint32_t) message.message == 0xDEADBEEF) {
//DEBUG_FUNCTION_LINE("We should stop the server\n");
break;
}
colorBuffer = (GX2ColorBuffer *) message.args[1];
JpegInformation * info = convertToJpeg((uint8_t*) colorBuffer->surface.image,colorBuffer->surface.width,colorBuffer->surface.height,colorBuffer->surface.pitch,colorBuffer->surface.format,85);
if(info != NULL ) {
MJPEGStreamServer::getInstance()->streamJPEG(info);
}
//DEBUG_FUNCTION_LINE("We can now kill the colorBuffer\n",colorBuffer);
if(colorBuffer->surface.image != NULL) {
free(colorBuffer->surface.image);
colorBuffer->surface.image = NULL;
//DEBUG_FUNCTION_LINE("Free image data for %08X\n",colorBuffer);
}
free(colorBuffer);
colorBuffer = NULL;
//DEBUG_FUNCTION_LINE("Encoding Done.\n");
}
DEBUG_FUNCTION_LINE("Server not running anymore\n");
serverRunning = false;
DCFlushRange((void*)&serverRunning,sizeof(serverRunning));
}

94
src/EncodingHelper.h Normal file
View File

@ -0,0 +1,94 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef __ENCODING_HELPER_H_
#define __ENCODING_HELPER_H_
#include <vector>
#include <algorithm>
#include <system/CThread.h>
#include <coreinit/messagequeue.h>
#include <utils/logger.h>
#include <MJPEGStreamServer.hpp>
#define ENCODE_QUEUE_MESSAGE_COUNT 1
extern OSMessageQueue encodeQueue;
extern OSMessage encodeQueueMessages[ENCODE_QUEUE_MESSAGE_COUNT];
class EncodingHelper {
public:
static EncodingHelper * getInstance() {
if(!instance) {
instance = new EncodingHelper();
}
return instance;
}
static void destroyInstance() {
if(instance) {
instance->StopAsyncThread();
while(instance->serverRunning) {
OSSleepTicks(OSMicrosecondsToTicks(1000));
}
OSSleepTicks(OSMillisecondsToTicks(500));
delete instance;
instance = NULL;
}
MJPEGStreamServer::destroyInstance();
}
static bool addFSQueueMSG(OSMessage message) {
if(!OSSendMessage(&encodeQueue,&message,OS_MESSAGE_FLAGS_NONE)) {
//DEBUG_FUNCTION_LINE("Dropping frame\n");
return false;
};
return true;
}
void StartAsyncThread();
void StopAsyncThread() {
DEBUG_FUNCTION_LINE("StopAsyncThread\n");
shouldExit = true;
DCFlushRange((void*) &shouldExit,sizeof(shouldExit));
}
private:
EncodingHelper() {
OSInitMessageQueue(&encodeQueue, encodeQueueMessages, ENCODE_QUEUE_MESSAGE_COUNT);
DEBUG_FUNCTION_LINE("Init queue done! \n");
}
static void DoAsyncThread(CThread *thread, void *arg);
void DoAsyncThreadInternal(CThread *thread);
CThread *pThread;
volatile bool serverRunning = false;
volatile bool shouldExit = false;
static EncodingHelper * instance;
};
#endif // __ENCODING_HELPER_H_

15
src/JpegInformation.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "JpegInformation.h"
#include <malloc.h>
JpegInformation::JpegInformation(tjhandle handle, uint8_t* jpegBuf, uint64_t jpegSize) {
this->buffer = jpegBuf;
this->size = jpegSize;
this->handle = handle;
}
JpegInformation::~JpegInformation() {
if(this->buffer) {
free(this->buffer);
}
tjDestroy(this->handle);
}

26
src/JpegInformation.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef JPEGINFORMATION_H
#define JPEGINFORMATION_H
#include <stdint.h>
#include <turbojpeg.h>
class JpegInformation {
public:
JpegInformation(tjhandle handle, uint8_t* jpegBuf, uint64_t jpegSize);
virtual ~JpegInformation();
uint8_t * getBuffer() {
return buffer;
};
uint64_t getSize() {
return size;
};
private:
uint8_t* buffer;
uint64_t size;
tjhandle handle;
};
#endif // JPEGINFORMATION_H

130
src/MJPEGStreamServer.cpp Normal file
View File

@ -0,0 +1,130 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "MJPEGStreamServer.hpp"
#include "turbojpeg.h"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <utils/logger.h>
#include <utils/StringTools.h>
#include <coreinit/thread.h>
#include <coreinit/time.h>
OSMessageQueue streamSendQueue __attribute__((section(".data")));
OSMessage streamSendQueueMessages[STREAM_SEND_QUEUE_MESSAGE_COUNT] __attribute__((section(".data")));
MJPEGStreamServer * MJPEGStreamServer::instance = NULL;
MJPEGStreamServer::MJPEGStreamServer(int32_t port): TCPServer(port,MJPEGStreamServer::getPriority()) {
OSInitMessageQueue(&streamSendQueue, streamSendQueueMessages, STREAM_SEND_QUEUE_MESSAGE_COUNT);
}
MJPEGStreamServer::~MJPEGStreamServer() {
}
/**
The sendwait from <network/net.h> is reaaally slow.
**/
int32_t mysendwait(int32_t sock, const void *buffer, int32_t len) {
int32_t ret;
while (len > 0) {
ret = send(sock, buffer, len, 0);
if(ret < 0) {
return ret;
}
len -= ret;
buffer = (void *)(((char *) buffer) + ret);
}
return 0;
}
void MJPEGStreamServer::sendJPEG(uint8_t * buffer, uint64_t size) {
int32_t clientfd = getClientFD();
char str[90];
snprintf(str, 90, "\r\n--boundary\r\nContent-Type: image/jpeg\r\nContent-Length: %llu \r\n\r\n", size);
mysendwait(clientfd, str, strlen(str));
mysendwait(clientfd, buffer, size);
//DEBUG_FUNCTION_LINE("Send frame\n");
}
BOOL MJPEGStreamServer::whileLoop() {
int32_t ret;
int32_t clientfd = getClientFD();
OSMessage message;
while (1) {
ret = checkbyte(clientfd);
if (ret < 0) {
if(socketlasterr() != 6) {
// Ending Server on error.
return false;
}
}
//DEBUG_FUNCTION_LINE("Waiting\n",message.message,message.data1);
while(!OSReceiveMessage(&streamSendQueue,&message,OS_MESSAGE_FLAGS_NONE)) {
if(shouldExit()) {
break;
}
OSSleepTicks(OSMicrosecondsToTicks(500));
}
if((uint32_t) message.message == 0x1234) {
continue;
}
if((uint32_t) message.message == 0xDEADBEEF) {
DEBUG_FUNCTION_LINE("We should exit\n");
break;
}
DCFlushRange(&message,sizeof(OSMessage));
JpegInformation * info = (JpegInformation *) message.args[0];
if(info != NULL) {
DCFlushRange(info,sizeof(JpegInformation));
sendJPEG(info->getBuffer(),info->getSize());
delete info;
}
}
return true;
}
const char * headerHTTP = "HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace; boundary=--boundary\r\n";
BOOL MJPEGStreamServer::acceptConnection() {
int32_t clientfd = getClientFD();
DEBUG_FUNCTION_LINE("TCP Connection accepted! \n");
mysendwait(clientfd, headerHTTP, strlen(headerHTTP));
// Consume the first response of the browser.
while(checkbyte(clientfd) > 0);
DEBUG_FUNCTION_LINE("Handshake done! Success!\n");
return true;
}
void MJPEGStreamServer::onConnectionClosed() {
DEBUG_FUNCTION_LINE("disconnected\n");
}

104
src/MJPEGStreamServer.hpp Normal file
View File

@ -0,0 +1,104 @@
/****************************************************************************
* Copyright (C) 2018 Maschell
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _MJPEG_STREAM_SERVER_H_
#define _MJPEG_STREAM_SERVER_H_
#include <utils/TCPServer.hpp>
#include <network/net.h>
#include <coreinit/messagequeue.h>
#include "turbojpeg.h"
#include "JpegInformation.h"
#define STREAM_SEND_QUEUE_MESSAGE_COUNT 1
extern OSMessageQueue streamSendQueue;
extern OSMessage streamSendQueueMessages[STREAM_SEND_QUEUE_MESSAGE_COUNT];
class MJPEGStreamServer: TCPServer {
public:
static MJPEGStreamServer *getInstance() {
if(!instance) {
instance = new MJPEGStreamServer(8080);
}
return instance;
}
static void destroyInstance() {
if(instance) {
instance->StopAsyncThread();
while(instance->isConnected()) {
OSSleepTicks(OSMicrosecondsToTicks(1000));
}
OSSleepTicks(OSMillisecondsToTicks(500));
delete instance;
instance = NULL;
}
}
void StopAsyncThread() {
DEBUG_FUNCTION_LINE("StopAsyncThread\n");
OSMessage message;
message.message = (void *)0xDEADBEEF;
OSSendMessage(&streamSendQueue,&message,OS_MESSAGE_FLAGS_BLOCKING);
}
static int32_t getPriority() {
return 10;
}
static volatile bool isInstanceConnected() {
if(instance) {
return instance->isConnected();
}
return false;
}
MJPEGStreamServer(int32_t port);
void sendJPEG(uint8_t * buffer, uint64_t size);
virtual bool streamJPEG(JpegInformation * info) {
if(this->isConnected()) {
OSMessage message;
message.message = (void *) 0x11111;
message.args[0] = (uint32_t) info;
if(!OSSendMessage(&streamSendQueue,&message,OS_MESSAGE_FLAGS_BLOCKING)) {
DEBUG_FUNCTION_LINE("Dropping frame\n");
delete info;
return false;
};
} else {
delete info;
}
return true;
}
virtual ~MJPEGStreamServer();
virtual BOOL whileLoop();
virtual BOOL acceptConnection();
virtual void onConnectionClosed();
static MJPEGStreamServer * instance;
};
#endif //_MJPEG_STREAM_SERVER_H_

22
src/function_patcher.cpp Normal file
View File

@ -0,0 +1,22 @@
#include <wups.h>
#include <utils/logger.h>
#include <gx2/surface.h>
#include <utils/StringTools.h>
#include <fs/FSUtils.h>
#include "stream_utils.h"
#include "retain_vars.hpp"
uint32_t count = 0;
DECL_FUNCTION(void, GX2CopyColorBufferToScanBuffer, const GX2ColorBuffer *colorBuffer, int32_t scan_target) {
if(gAppStatus == WUPS_APP_STATUS_FOREGROUND) {
// Stream every 4th frame of the Gamepad (targetting 20fps)
if(scan_target == 4 && (count++ % 4 == 0) && colorBuffer != NULL ) {
count = 0;
streamVideo((GX2ColorBuffer *)colorBuffer);
}
}
real_GX2CopyColorBufferToScanBuffer(colorBuffer,scan_target);
}
WUPS_MUST_REPLACE(GX2CopyColorBufferToScanBuffer, WUPS_LOADER_LIBRARY_GX2, GX2CopyColorBufferToScanBuffer);

43
src/main.cpp Normal file
View File

@ -0,0 +1,43 @@
#include <wups.h>
#include <utils/logger.h>
#include "retain_vars.hpp"
#include "EncodingHelper.h"
#include "MJPEGStreamServer.hpp"
// Mandatory plugin information.
WUPS_PLUGIN_NAME("Gamepad streaming tool. Open http://<ip of your wii u>:8000 on a browser in the same network.");
WUPS_PLUGIN_DESCRIPTION("");
WUPS_PLUGIN_VERSION("v0.1");
WUPS_PLUGIN_AUTHOR("Maschell");
WUPS_PLUGIN_LICENSE("GPL");
// Something is using "write"...
WUPS_FS_ACCESS()
// Gets called once the loader exists.
INITIALIZE_PLUGIN() {
socket_lib_init();
log_init();
}
// Called whenever an application was started.
ON_APPLICATION_START(my_args) {
socket_lib_init();
log_init();
gAppStatus = WUPS_APP_STATUS_FOREGROUND;
EncodingHelper::getInstance()->StartAsyncThread();
MJPEGStreamServer::getInstance();
log_init();
}
ON_APP_STATUS_CHANGED(status) {
gAppStatus = status;
if(status == WUPS_APP_STATUS_CLOSED) {
EncodingHelper::destroyInstance();
MJPEGStreamServer::destroyInstance();
}
}

2
src/retain_vars.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "retain_vars.hpp"
wups_loader_app_status_t gAppStatus __attribute__((section(".data"))) = WUPS_APP_STATUS_UNKNOWN;

8
src/retain_vars.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef _RETAINS_VARS_H_
#define _RETAINS_VARS_H_
#include <wups.h>
extern wups_loader_app_status_t gAppStatus;
#endif // _RETAINS_VARS_H_

171
src/stream_utils.cpp Normal file
View File

@ -0,0 +1,171 @@
#include "stream_utils.h"
#include "EncodingHelper.h"
#include "MJPEGStreamServer.hpp"
#include <fs/FSUtils.h>
#include <malloc.h>
#include <gx2/event.h>
#include <gx2/surface.h>
#include <gx2/mem.h>
#ifdef __cplusplus
extern "C" {
#endif
void
GX2ResolveAAColorBuffer(const GX2ColorBuffer * srcColorBuffer,
GX2Surface * dstSurface,
uint32_t dstMip,
uint32_t dstSlice);
#ifdef __cplusplus
}
#endif
bool copyBuffer(GX2ColorBuffer * sourceBuffer, GX2ColorBuffer * targetBuffer, uint32_t targetWidth, uint32_t targetHeight) {
// Making sure the buffers are not NULL
if (sourceBuffer != NULL && targetBuffer != NULL) {
targetBuffer->surface.use = (GX2SurfaceUse) (GX2_SURFACE_USE_COLOR_BUFFER | GX2_SURFACE_USE_TEXTURE);
targetBuffer->surface.dim = GX2_SURFACE_DIM_TEXTURE_2D;
targetBuffer->surface.width = targetWidth;
targetBuffer->surface.height = targetHeight;
targetBuffer->surface.depth = 1;
targetBuffer->surface.mipLevels = 1;
targetBuffer->surface.format = GX2_SURFACE_FORMAT_UNORM_R8_G8_B8_A8;
targetBuffer->surface.aa = GX2_AA_MODE1X;
targetBuffer->surface.tileMode = GX2_TILE_MODE_LINEAR_ALIGNED;
targetBuffer->viewMip = 0;
targetBuffer->viewFirstSlice = 0;
targetBuffer->viewNumSlices = 1;
GX2CalcSurfaceSizeAndAlignment(&targetBuffer->surface);
GX2InitColorBufferRegs(targetBuffer);
// Let's allocate the memory.
targetBuffer->surface.image = memalign(targetBuffer->surface.alignment,targetBuffer->surface.imageSize);
if(targetBuffer->surface.image == NULL) {
DEBUG_FUNCTION_LINE("failed to allocate memory.\n");
return false;
}
//DEBUG_FUNCTION_LINE("Allocated image data buffer. data %08X size %08X \n",targetBuffer->surface.image,targetBuffer->surface.imageSize);
GX2Invalidate(GX2_INVALIDATE_MODE_CPU, targetBuffer->surface.image, targetBuffer->surface.imageSize);
if (sourceBuffer->surface.aa == GX2_AA_MODE1X) {
// If AA is disabled, we can simply use GX2CopySurface.
GX2CopySurface(&sourceBuffer->surface,
sourceBuffer->viewMip,
sourceBuffer->viewFirstSlice,
&targetBuffer->surface, 0, 0);
} else {
// If AA is enabled, we need to resolve the AA buffer.
GX2Surface tempSurface;
tempSurface = sourceBuffer->surface;
tempSurface.aa = GX2_AA_MODE1X;
GX2CalcSurfaceSizeAndAlignment(&tempSurface);
tempSurface.image = memalign(tempSurface.alignment,tempSurface.imageSize);
if(tempSurface.image == NULL) {
DEBUG_FUNCTION_LINE("failed to allocate data AA.\n");
if(targetBuffer->surface.image != NULL) {
free(targetBuffer->surface.image);
targetBuffer->surface.image = NULL;
}
return false;
}
GX2ResolveAAColorBuffer(sourceBuffer,&tempSurface, 0, 0);
GX2CopySurface(&tempSurface, 0, 0,&targetBuffer->surface, 0, 0);
// Sync CPU and GPU
GX2DrawDone();
if(tempSurface.image != NULL) {
free(tempSurface.image);
tempSurface.image = NULL;
}
}
return true;
} else {
DEBUG_FUNCTION_LINE("Couldn't copy buffer, pointer was NULL\n");
return false;
}
}
uint32_t frame_counter = 0;
uint32_t frame_counter_skipped = 0;
bool streamVideo(GX2ColorBuffer *srcBuffer) {
if(srcBuffer == NULL) {
return false;
}
if(!MJPEGStreamServer::isInstanceConnected()) {
return false;
}
GX2ColorBuffer* colorBuffer = (GX2ColorBuffer*) memalign(0x40,sizeof(GX2ColorBuffer));
if(colorBuffer == NULL) {
DEBUG_FUNCTION_LINE("Failed to allocate color buffer\n");
return false;
}
//DEBUG_FUNCTION_LINE("allocated at %08X\n",colorBuffer);
memset(colorBuffer,0,sizeof(GX2ColorBuffer));
// keep dimensions
//uint32_t width = srcBuffer->surface.width;
//uint32_t height = srcBuffer->surface.height;
//uint32_t width = 640;
//uint32_t height = 360;
uint32_t width = 428;
uint32_t height = 240;
bool valid = copyBuffer(srcBuffer,colorBuffer,width,height);
if(!valid) {
DEBUG_FUNCTION_LINE("Copy buffer failed.\n");
if(colorBuffer->surface.image != NULL) {
free(colorBuffer->surface.image);
colorBuffer->surface.image = NULL;
}
if(colorBuffer != NULL) {
free(colorBuffer);
colorBuffer = NULL;
}
return false;
}
//DEBUG_FUNCTION_LINE("Copy buffer was successful.\n");
// Flush out destinations caches
GX2Invalidate(GX2_INVALIDATE_MODE_COLOR_BUFFER, colorBuffer->surface.image,colorBuffer->surface.imageSize);
// Wait for GPU to finish
GX2DrawDone();
DCFlushRange(colorBuffer,sizeof(GX2ColorBuffer));
DCFlushRange(&(colorBuffer->surface),sizeof(GX2Surface));
OSMessage message;
message.message = (void *) 0x1337;
message.args[1] = (uint32_t) colorBuffer;
frame_counter++;
bool result = true;
if(!EncodingHelper::addFSQueueMSG(message)) {
frame_counter_skipped++;
//DEBUG_FUNCTION_LINE("Adding to queue failed, free memory\n");
if(colorBuffer->surface.image != NULL) {
free(colorBuffer->surface.image);
colorBuffer->surface.image = NULL;
}
if(colorBuffer != NULL) {
free(colorBuffer);
colorBuffer = NULL;
}
result = false;
}
if(frame_counter % 120 == 0) {
DEBUG_FUNCTION_LINE("Send %d frames, skipped %d. %.2f\n",frame_counter-frame_counter_skipped,frame_counter_skipped,100.f * (frame_counter_skipped*1.0f/frame_counter));
}
return result;
}

11
src/stream_utils.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef _STREAM_UTILS_H_
#define _STREAM_UTILS_H_
#include <gx2/surface.h>
#include <utils/logger.h>
bool copyBuffer(GX2ColorBuffer * sourceBuffer, GX2ColorBuffer * targetBuffer, uint32_t targetWidth, uint32_t targetHeight);
bool streamVideo(GX2ColorBuffer *srcBuffer);
#endif