From edc3ad1c8e079a96a985d60a800a56918186b9e3 Mon Sep 17 00:00:00 2001 From: schmirl Date: Tue, 20 Jul 2010 06:23:32 +0000 Subject: [PATCH] - set externremux.sh executable in distribution archive - externremux quality value should be wlan54, not wlan45 --- CONTRIBUTORS | 8 + HISTORY | 26 ++++ streamdev-server/externremux.sh | 267 ++++++++++++++++++++++++++++++++ 3 files changed, 301 insertions(+) create mode 100755 streamdev-server/externremux.sh diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 5ccccc6..5f8ef8d 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -37,6 +37,7 @@ Rolf Ahrenberg for improving LIMIKUUTIO and PARENTALRATING patch detection for suggesting to include the charset in HTTP replies for requesting replacement of asprintf calls + for suggesting to change the URL path from EXTERN to EXT Rantanen Teemu for providing vdr-incompletesections.diff @@ -146,3 +147,10 @@ lhanisch Eric Valette for adding support for EnhancedAC3 + +carel + for reporting "plugin doesn't honor APIVERSION" error in new Makefile + for helping to find a way to cleanly shutdown externremux with mencoder + +wolfi.m + for reporting a typo in externermux quality parameter value diff --git a/HISTORY b/HISTORY index 252a171..95fb1c7 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,32 @@ VDR Plugin 'streamdev' Revision History --------------------------------------- + +2010-07-20: Version 0.5.0a +- set externremux.sh executable in distribution archive +- externremux quality value should be wlan54, not wlan45 + +2010-07-19: Version 0.5.0 + +- using SIGINT in externremux to kill mencoder works better than SIGTERM; + especially x264 still needs a SIGKILL sometimes +- added --remove-destination to cp commands installing plugins +- fixed "plugin doesn't honor APIVERSION" (reported by carel@vdrportal) +- updated Italian translation (thanks to Diego Pierotto) +- config option "client may suspend" hidden if not applicable +- updated and enhanced README +- separated language resources of client and server +- restructured build process +- added support for HTTP method HEAD +- rewrite of externremux.sh, including support for various URL parameters, + logging and improved shutdown +- start externremux script in a separate process group +- changed HTTP URL path for externremux from EXTERN to EXT (suggested by + Rolf Ahrenberg) +- HTTP headers now have to be emitted by externremux script +- pass channel related information and URL parameters to externremux script + through environment +- implement CGI like interface for externremux script - dropped "Synchronize EPG" feature. Please use epgsync-plugin instead (available from http://vdr.schmirler.de) - proper tsplay-0.2 patch detection. tsplay-0.1 is no longer recognized diff --git a/streamdev-server/externremux.sh b/streamdev-server/externremux.sh new file mode 100755 index 0000000..21cc60d --- /dev/null +++ b/streamdev-server/externremux.sh @@ -0,0 +1,267 @@ +#!/bin/bash +# +# externremux.sh - sample remux script using mencoder for remuxing. +# +# Install this script as VDRCONFDIR/plugins/streamdev-server/externremux.sh +# +# The parameter QUALITY selects the default remux parameters. Adjust +# to your needs and point your web browser to http://servername:3000/ext/ +# To select different remux parameters on the fly, insert a semicolon +# followed by the name and value of the requested parameter, e.g: +# e.g. http://servername:3000/ext;QUALITY=WLAN11;VBR=512/ +# The following parameters are recognized: +# +# PROG actual remux program +# VC video codec +# VBR video bitrate (kbit) +# VOPTS custom video options +# WIDTH scale video to width +# AC audio codec +# ABR audio bitrate (kbit) +# AOPTS custom audio options +# + +########################################################################## + +### GENERAL CONFIG START +### +# Pick one of DSL1000/DSL2000/DSL3000/DSL6000/DSL16000/LAN10/WLAN11/WLAN54 +QUALITY='DSL1000' +# Program used for logging (logging disabled if empty) +LOGGER=logger +# Path and name of FIFO +FIFO=/tmp/externremux-${RANDOM:-$$} +# Default remux program (cat/mencoder/ogg) +PROG=mencoder +# Use mono if $ABR is lower than this value +ABR_MONO=64 +### +### GENERAL CONFIG END + +### MENCODER CONFIG START +### +# mencoder binary +MENCODER=mencoder +# Default video codec (e.g. lavc/x264/copy) +MENCODER_VC=lavc +# Default audio codec (e.g. lavc/mp3lame/faac/copy) +MENCODER_AC=mp3lame +# Default video codec if lavc is used (-ovc lavc -lavcopts vcodec=) +MENCODER_LAVC_VC=mpeg4 +# Default audio codec if lavc is used (-oac lavc -lavcopts acodec=) +MENCODER_LAVC_AC=mp2 +### +### MENCODER CONFIG END + +### OGG CONFIG START +### +# ffmpeg2theora binary +OGG=ffmpeg2theora +# speedlevel - lower value gives better quality but is slower (0..2) +OGG_SPEED=1 +# videoquality - higher value gives better quality but is slower (0..10) +OGG_VQUALITY=0 +# audioquality - higher value gives better quality but is slower (0..10) +OGG_AQUALITY=0 +### +### OGG CONFIG END + +########################################################################## + +function hasOpt { echo "$1" | grep -q "\b${2}\b"; } + +function isNumeric() { echo "$@" | grep -q '^[0-9]\{1,\}$'; } + +function remux_cat +{ + startReply + exec 3<&0 + cat 0<&3 >"$FIFO" & +} + +function remux_mencoder +{ + # lavc may be used for video and audio + LAVCOPTS=() + + # Assemble video options + VC=${REMUX_PARAM_VC:-$MENCODER_VC} + VOPTS=${REMUX_PARAM_VOPTS} + WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH} + case "$VC" in + lavc) + LAVCOPTS=( + ${VOPTS} + $(hasOpt "$VOPTS" vcodec || echo "vcodec=$MENCODER_LAVC_VC") + ${VBR:+vbitrate=$VBR} + ) + [ ${#LAVCOPTS[*]} -gt 0 ] && VOPTS=$(IFS=:; echo -lavcopts "${LAVCOPTS[*]}") + ;; + x264) + X264OPTS=( + ${VOPTS} + $(hasOpt "$VOPTS" threads || echo "threads=auto") + ${VBR:+bitrate=$ABR} + ) + [ ${#X264OPTS[*]} -gt 0 ] && VOPTS=$(IFS=:; echo -x264encopts "${X264OPTS[*]}") + ;; + copy) + VOPTS= + ;; + *) + error "Unknown video codec '$VC'" + ;; + esac + + # Assemble audio options + AC=${REMUX_PARAM_AC:-$MENCODER_AC} + AOPTS=${REMUX_PARAM_AOPTS} + case "$AC" in + lavc) + LAVCOPTS=( + ${LAVCOPTS[*]} + ${AOPTS} + $(hasOpt "$AOPTS" acodec || echo "acodec=$MENCODER_LAVC_AC") + ${ABR:+abitrate=$ABR} + ) + + [ ${#LAVCOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -lavcopts "${LAVCOPTS[*]}") + # lavc used for video and audio decoding - wipe out VOPTS as video options became part of AOPTS + [ "$VC" = lavc ] && VOPTS= + ;; + mp3lame) + LAMEOPTS=( + ${AOPTS} + $(isNumeric "${ABR}" && [ "${ABR}" -lt "$ABR_MONO" ] && ! hasOpt "${AOPTS}" mode ] && echo 'mode=3') + ${ABR:+preset=$ABR} + ) + [ ${#LAMEOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -lameopts "${LAMEOPTS[*]}") + ;; + faac) + FAACOPTS=( + ${AOPTS} + ${ABR:+br=$ABR} + ) + [ ${#FAACOPTS[*]} -gt 0 ] && AOPTS=$(IFS=:; echo -faacopts "${FAACOPTS[*]}") + ;; + copy) + AOPTS= + ;; + *) + error "Unknown audio codec '$AC'" + ;; + esac + + + startReply + exec 3<&0 + echo "$MENCODER" \ + -ovc $VC $VOPTS \ + -oac $AC $AOPTS \ + ${WIDTH:+-vf scale -zoom -xy $WIDTH} \ + -o "$FIFO" -- - >&2 + "$MENCODER" \ + -ovc $VC $VOPTS \ + -oac $AC $AOPTS \ + ${WIDTH:+-vf scale -zoom -xy $WIDTH} \ + -o "$FIFO" -- - 0<&3 >/dev/null & +} + +function remux_ogg +{ + VOPTS=${REMUX_PARAM_VOPTS//[:=]/ } + AOPTS=${REMUX_PARAM_AOPTS//[:=]/ } + WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH} + + OGGOPTS=( + ${VOPTS} + ${VBR:+--videobitrate $VBR} + $(hasOpt "${VOPTS}" videoquality || echo "--videoquality $OGG_VQUALITY") + $(hasOpt "${VOPTS}" speedlevel || echo "--speedlevel $OGG_SPEED") + ${AOPTS} + ${ABR:+--audiobitrate $ABR} + $(isNumeric "${ABR}" && [ "${ABR}" -lt "$ABR_MONO" ] && ! hasOpt "${AOPTS}" channels ] && echo '--channels 1') + $(hasOpt "${AOPTS}" audioquality || echo "--audioquality $OGG_AQUALITY") + $(hasOpt "${AOPTS}" audiostream || echo '--audiostream 1') + ) + + startReply + exec 3<&0 + echo "$OGG" --format ts \ + ${OGGOPTS[*]} \ + ${WIDTH:+--width $WIDTH --height $(($WIDTH * 3 / 4 / 8 * 8))} \ + --title "VDR Streamdev: ${REMUX_CHANNEL_NAME}" \ + --output "$FIFO" -- - 0<&3 >&2 + "$OGG" --format ts \ + ${OGGOPTS[*]} \ + ${WIDTH:+--width $WIDTH --height $(($WIDTH * 3 / 4 / 8 * 8))} \ + --title "VDR Streamdev: ${REMUX_CHANNEL_NAME}" \ + --output "$FIFO" -- - 0<&3 >/dev/null & +} + +function error +{ + if [ "$SERVER_PROTOCOL" = HTTP ]; then + echo -ne "Content-type: text/plain\r\n" + echo -ne '\r\n' + echo "$*" + fi + + echo "$*" >&2 + exit 1 +} + +function startReply +{ + if [ "$SERVER_PROTOCOL" = HTTP ]; then + # send content-type and custom headers + echo -ne "Content-type: ${CONTENTTYPE}\r\n" + for header in "${HEADER[@]}"; do echo -ne "$header\r\n"; done + echo -ne '\r\n' + + # abort after headers + [ "$REQUEST_METHOD" = HEAD ] && exit 0 + fi + + # create FIFO and read from it in the background + mkfifo "$FIFO" + trap "trap '' EXIT HUP INT TERM ABRT PIPE CHLD; kill -INT 0; sleep 1; fuser -k '$FIFO'; rm '$FIFO'" EXIT HUP INT TERM ABRT PIPE CHLD + cat "$FIFO" <&- & +} + +HEADER=() + +[ "$LOGGER" ] && exec 2> >($LOGGER -t "vdr: [$$] ${0##*/}" 2>&-) + +# set default content-types +case "$REMUX_VPID" in + ''|0|1) CONTENTTYPE='audio/mpeg';; + *) CONTENTTYPE='video/mpeg';; +esac + +QUALITY=${REMUX_PARAM_QUALITY:-$QUALITY} +case "$QUALITY" in + DSL1000|dsl1000) VBR=96; ABR=16; WIDTH=160;; + DSL2000|dsl2000) VBR=128; ABR=16; WIDTH=160;; + DSL3000|dsl3000) VBR=256; ABR=16; WIDTH=320;; + DSL6000|dsl6000) VBR=378; ABR=32; WIDTH=320;; + DSL16000|dsl16000) VBR=512; ABR=32; WIDTH=480;; + WLAN11|wlan11) VBR=768; ABR=64; WIDTH=640;; + WLAN54|wlan54) VBR=2048; ABR=128; WIDTH=;; + LAN10|lan10) VBR=4096; ABR=; WIDTH=;; + *) error "Unknown quality '$QUALITY'";; +esac +ABR=${REMUX_PARAM_ABR:-$ABR} +VBR=${REMUX_PARAM_VBR:-$VBR} +WIDTH=${REMUX_PARAM_WIDTH:-$WIDTH} +PROG=${REMUX_PARAM_PROG:-$PROG} + +case "$PROG" in + cat) remux_cat;; + mencoder) remux_mencoder;; + ogg) remux_ogg;; + *) error "Unknown remuxer '$PROG'";; +esac + +set -o monitor +wait