Introduction

gputranscoder is an application that utilizes the Rasperry Pi GPU for transcoding transport stream media files.

Design Decisions

Basic Usage

gputranscoder needs an input_filename and output_filename to operate at minimum.

Important!!!: Make sure your output filename ends with a “ts” extension. The output container is guessed by the filename.

Extra config arguments are optional. Default values are 2Mbit for bitrate, false for deinterlacing , info for log level and size is copied from the input stream.

Basic usage is printed by the app itself as follows

Usage: 
  ./gputranscoder [-s WxH] [-b target_bitrate] [-d] [-L log_level]  <infile> <outfile>

    -s size        Resize output.  'size'  format is WidthxHeight
    -b bitrate     Target bitrate in bits/second. Low bitrates may result in frame drops
    -f framerate   Frame Rate Per Second : fps
    -g gopsize     Sets the intra refresh period : GoP size. H264 video uses a complete frame (I-frame) every intra refresh period
                   This option specifies the numbers of frames between each I-frame.
    -d        Deinterlace
    -p        AVC profile  string. Possible values: "main" "baseline" "extended" "high"
    -L        Debug Level: 1:error 2:warn 3:info 4:debug-
    -q        Initial Quanitization Level. Initial video quality at the beginning of encoding. Generally a value between 10 and 40.
              Lower Value = Better Initial Quality
    -P        Comma seperated Blocked PID list. i.e. -P 257,278
              After PID filtering, there must be still be a video stream for transcoder to operate.

Output container is guessed based on outfile name.  Use '.ts' for transport stream output.

Input file must contain one of MPEG 2 or H.264 video.
Make sure You have installed necessary codecs in your RasPi

Sample usage:

# Sample usage for 3Mbit/sec target bitrate and Log Level only printing error messages.
gputranscoder -b 3000000 -L 1 input.ts output.ts

# Sample usage for main profile with framerate 30 fps
gputranscoder -p "main" -f 30 input.ts output.ts

# Sample usage for filtering audio stream with PID 257 and text stream with PID 278
gputranscoder -P 257,258  input.ts output.ts

Note that size and deinterlacing options are not enabled in the first binary

Library Dependencies

There are three major chunk of dependencies 1. OpenMAX api related dependencies. If these are not installed yet, you must build them on the Raspberry Pi under /opt/ folder

  libGLESv2.so => /opt/vc/lib/libGLESv2.so (0x76378000)
  libEGL.so => /opt/vc/lib/libEGL.so (0x7634f000)
    libopenmaxil.so => /opt/vc/lib/libopenmaxil.so (0x76340000)
    libbcm_host.so => /opt/vc/lib/libbcm_host.so (0x76322000)
    libvcos.so => /opt/vc/lib/libvcos.so (0x76310000)
    libvchiq_arm.so => /opt/vc/lib/libvchiq_arm.so (0x76302000)

2. FFmpeg related dependencies. For demuxing main lib is libavformat which depends on libavcodec which in turn brings in many dependencies. Although none of the soft codecs here are needed, the default ffmpeg on RasPi repository has them enabled so they will all be listed as a dependency.

If you do not have ffmpeg installed you must install it. sudo apt-get install ffmpeg. For future development, you will also need the development versions of libavutil libavformat and libavcodec

  /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0x76fc9000)
    libavformat.so.54 => /usr/lib/arm-linux-gnueabihf/neon/vfp/libavformat.so.54 (0x76ec3000)
    libavcodec.so.54 => /usr/lib/arm-linux-gnueabihf/neon/vfp/libavcodec.so.54 (0x763be000)
    libavutil.so.52 => /usr/lib/arm-linux-gnueabihf/neon/vfp/libavutil.so.52 (0x76395000)
    librtmp.so.0 => /usr/lib/arm-linux-gnueabihf/librtmp.so.0 (0x76113000)
    libxvidcore.so.4 => /usr/lib/arm-linux-gnueabihf/libxvidcore.so.4 (0x75ee9000)
    libx264.so.130 => /usr/lib/arm-linux-gnueabihf/neon/vfp/libx264.so.130 (0x75d85000)
    libvpx.so.1 => /usr/lib/arm-linux-gnueabihf/libvpx.so.1 (0x75d2b000)
    libvorbisenc.so.2 => /usr/lib/arm-linux-gnueabihf/libvorbisenc.so.2 (0x75bbd000)
    libvorbis.so.0 => /usr/lib/arm-linux-gnueabihf/libvorbis.so.0 (0x75b8d000)
    libvo-amrwbenc.so.0 => /usr/lib/arm-linux-gnueabihf/libvo-amrwbenc.so.0 (0x75b6d000)
    libvo-aacenc.so.0 => /usr/lib/arm-linux-gnueabihf/libvo-aacenc.so.0 (0x75b4a000)
    libtheoraenc.so.1 => /usr/lib/arm-linux-gnueabihf/libtheoraenc.so.1 (0x75b09000)
    libtheoradec.so.1 => /usr/lib/arm-linux-gnueabihf/libtheoradec.so.1 (0x75aea000)
    libspeex.so.1 => /usr/lib/arm-linux-gnueabihf/libspeex.so.1 (0x75acc000)
    libschroedinger-1.0.so.0 => /usr/lib/arm-linux-gnueabihf/libschroedinger-1.0.so.0 (0x75a14000)
    libopus.so.0 => /usr/lib/libopus.so.0 (0x759d0000)
    libopenjpeg.so.2 => /usr/lib/arm-linux-gnueabihf/libopenjpeg.so.2 (0x759ae000)
    libopencore-amrwb.so.0 => /usr/lib/arm-linux-gnueabihf/libopencore-amrwb.so.0 (0x75994000)
    libopencore-amrnb.so.0 => /usr/lib/arm-linux-gnueabihf/libopencore-amrnb.so.0 (0x75969000)
    libmp3lame.so.0 => /usr/lib/arm-linux-gnueabihf/libmp3lame.so.0 (0x758ec000)
    libgsm.so.1 => /usr/lib/arm-linux-gnueabihf/libgsm.so.1 (0x758da000)
    libva.so.1 => /usr/lib/arm-linux-gnueabihf/libva.so.1 (0x758be000)
    libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0x758b2000)
    libgcrypt.so.11 => /lib/arm-linux-gnueabihf/libgcrypt.so.11 (0x75832000)
    libtasn1.so.3 => /usr/lib/arm-linux-gnueabihf/libtasn1.so.3 (0x7581c000)
    libp11-kit.so.0 => /usr/lib/arm-linux-gnueabihf/libp11-kit.so.0 (0x75805000)
    libogg.so.0 => /usr/lib/arm-linux-gnueabihf/libogg.so.0 (0x757f8000)
    liborc-0.4.so.0 => /usr/lib/arm-linux-gnueabihf/liborc-0.4.so.0 (0x7577d000)
    libgpg-error.so.0 => /lib/arm-linux-gnueabihf/libgpg-error.so.0 (0x75772000)

3. Arm libc and generic libraries only listed as information

  libz.so.1 => /lib/arm-linux-gnueabihf/libz.so.1 (0x760f5000)
    libgnutls.so.26 => /usr/lib/arm-linux-gnueabihf/libgnutls.so.26 (0x7603b000)
    libbz2.so.1.0 => /lib/arm-linux-gnueabihf/libbz2.so.1.0 (0x76021000)
    libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0x75ff9000)
    /lib/ld-linux-armhf.so.3 (0x76fd6000)
  libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0x762e3000)
  librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0x762d3000)
    libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76262000)
    libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76131000)

Codec Dependencies

H.264 is installed by default. Make sure you have purchased and installed MPEG-2 license from the Raspberry Pi store. [http://www.raspberrypi.com/license-keys/]

Conclusions and Next Steps

Known Issues

  • At 1080p 30fps content if resizing is enabled, encoder outputs two frames with the same PTS. It may be related to salling in the encoder so that one of the frames would get a late STC. Currently investigating whether there is a workaround or if this is due to platform limitation.

Version History


Version 1.0:

  • ffmpeg demuxing and GPU transcoding support for H264 and MPEG2 content
  • -b target_bitrate option
  • -L loglevel option

Version 1.1:

  • deinterlacing support added
  • resizing support added
  • selecting h.264 profile added
  • Bug fix related to content that has missing framerate information in the container

Version 1.2:

  • Bug fix : While consuming the final frames from the encoder output buffer, frames that do not fit into default read_size were not being handled properly. This would result in feeding the same frame in to parts with the same dts. This release fixes that.

Version 1.3:

  • Bug fix : When a new encoding begins the first frames are encoded in a lower quality than the average bitrate. The RasPi GPU only supports Variable Bitrate - VBR rate setting and it seems to increase the quality gradually. In order start at a better quality initially, this release sets Initial Quantization Parameter for a better quality.

Version 1.4:

  • framerate support added
  • gopsize (keyframe interval) added
  • selecting initial quantization level added
  • selecting h.264 profile added

Version 1.5:

  • PID filtering support added
  • BugFix: If deinterlacing was enabled 1080p progressive content transcoder was hanging.
  • Generally improved cases when the program would hang due to encoder hangs.

Version 1.6:

  • Slowed down feeding input to the transcoder to avoid missed frames.
  • BugFix: If default initial quantization level is low (meaning high quality) there was “ZERO LEN BUF” outputs with skipped frames. Removed default initial quantization level.