CTR Streaming Server 3DS

From GameBrew

CTR Streaming Server
Last Updated2014/11/21
Type3DS Streaming
Source Only Download

This is a 3DS homebrew audio/video playback server, listening on TCP port 8334. This uses ctrulib.

User guide

Compiling: make MEDIAMODE=<val> CODEC=<val> HIDREPORT=<val>

  • MEDIAMODE must be either value 0 for video, or value 1 for audio.
  • CODEC must be either value 0 for raw video/audio, or value 1 for encoded video/audio.
  • HIDREPORT is optional, when the value is non-zero and MEDIAMODE is 0, the server will send a 0x10c-byte block to the client every >= ~1/60 of a second. The first 0x108-bytes are from hidSharedMem+0, the last word is from here. The app will only send the HID block while video data is being received.

Besides ctrulib, the following libraries are required: libvpx, libvorbisfile, libvorbis, and libogg.

  • Configuring libvpx building: CROSS=arm-none-eabi- ./configure --target=generic-gnu "--extra-cflags=-march=armv6 -mtune=mpcore -mfpu=vfp" --disable-multithread --disable-vp8-encoder --disable-vp9-encoder
  • Configuring libogg building: ./configure --host=arm-none-eabi --prefix=/opt/devkitpro/devkitARM/portlibs/arm/armv6

Audio and color format:

  • The audio is 44100Hz pcm_s16le mono-channel, when CODEC is non-zero the data sent to the app must be .ogg.
  • When CODEC is non-zero, the video data sent to the app must be VP8 IVF.
  • The color-format of the video frame is the same as the LCD framebuffer, the width must be 240.
  • For raw video, the color-format is RGB565.

Screen image size:

  • The height must be at least 320 (sub-screen) or 400 (main-screen).
  • For encoded video, larger height values allows more than one LCD framebuffer to be used in each video frame.
  • 320+400 = main-screen image (400 height) + sub-screen image (320 height), 800 = two main-screen images (height 400 for each image), for 3D left and 3D right.
  • 800+320 = same as 800, except this has a 320-height sub-screen image following the main-screen images.

The VP8 video framerate from the client should be only ~20-25fps (this depends on the video dimensions), this is due to single-threaded decoding (higher framerates can't be used due to this not decoding fast enough).

Example terminal commands for streaming to this server:

  • Ogg streaming: avconv -i <inputfile> -f s16le -acodec libvorbis -ac 1 -vn -f ogg - | nc <serveraddr> 8334
  • Raw audio streaming: avconv -i <inputfile> -f s16le -acodec pcm_s16le -ac 1 - | nc <serveraddr> 8334
  • VP8 IVF, for just sub-screen: avconv -i <video input path> -s 320x240 -vf transpose=1 -r 30 -f ivf - | nc <serveraddr> 8334

Note: This app handles certain errors by triggering crashes. This includes service initialization failure (such as CSND), like when the app doesn't have access to a required service.

Known issues

This has various bugs, including:

  • Return-to-homemenu(which includes power-button handling) does not work, returning to hbmenu is broken too.
  • Audio playback starting when the initial connection is closed then another connection opened, is broken. The app does not hang/crash(closing the connection + opening the connection again still works), however no audio is played.
  • Ogg handling is broken, this doesn't work very well compared to raw audio playback. Unlike raw audio playback, the app will quickly hang without crashing, when playing ogg audio.
  • This app only waits for just one audio chunk(1-second block), then immediately plays that. This results in audio playback briefly stopping while the app waits for the next chunk when playback of the previous chunk already finished.


The yuv2rgb code used by this app is from here.

External links