├── armv7 ├── pi-time.txt ├── build.sh └── files │ ├── 10-adduser │ ├── tvheadend43.patch │ ├── libdvbcsa.patch │ └── docker ├── x64 ├── build.sh └── files │ ├── metric_heartbeat.sh │ ├── tvheadend43.patch │ ├── 10-adduser │ ├── libdvbcsa.patch │ └── docker ├── aarch64 ├── build.sh └── files │ ├── metric_heartbeat.sh │ ├── 10-adduser │ ├── tvheadend43.patch │ ├── libdvbcsa.patch │ └── docker └── README.md /armv7/pi-time.txt: -------------------------------------------------------------------------------- 1 | https://docs.linuxserver.io/faq#my-host-is-incompatible-with-images-based-on-ubuntu-focal-and-alpine-3-13 2 | 3 | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 04EE7237B7D453EC 648ACFD622F3D138 4 | echo "deb http://deb.debian.org/debian buster-backports main" | sudo tee -a /etc/apt/sources.list.d/buster-backports.list 5 | sudo apt update 6 | sudo apt install -t buster-backports libseccomp2 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /x64/build.sh: -------------------------------------------------------------------------------- 1 | rm -rf docker-tvheadend 2 | git clone https://github.com/linuxserver/docker-tvheadend.git 3 | mkdir docker-tvheadend/patches/argtable 4 | mkdir docker-tvheadend/patches/libdvbcsa 5 | mkdir docker-tvheadend/patches/tvheadend 6 | mv docker-tvheadend/patches/config.guess docker-tvheadend/patches/argtable/ 7 | mv docker-tvheadend/patches/config.sub docker-tvheadend/patches/argtable/ 8 | cp files/libdvbcsa.patch docker-tvheadend/patches/libdvbcsa/ 9 | #cp files/tvheadend43.patch docker-tvheadend/patches/tvheadend/ 10 | cp files/10-adduser docker-tvheadend/ 11 | cat files/docker > docker-tvheadend/Dockerfile 12 | cat files/metric_heartbeat.sh > docker-tvheadend/metric_heartbeat.sh 13 | cd docker-tvheadend/ 14 | docker build -t thealhu/tvheadend-x64 --network host --no-cache . 15 | -------------------------------------------------------------------------------- /aarch64/build.sh: -------------------------------------------------------------------------------- 1 | rm -rf docker-tvheadend 2 | git clone https://github.com/linuxserver/docker-tvheadend.git 3 | mkdir docker-tvheadend/patches/argtable 4 | mkdir docker-tvheadend/patches/libdvbcsa 5 | mkdir docker-tvheadend/patches/tvheadend 6 | mv docker-tvheadend/patches/config.guess docker-tvheadend/patches/argtable/ 7 | mv docker-tvheadend/patches/config.sub docker-tvheadend/patches/argtable/ 8 | cp files/libdvbcsa.patch docker-tvheadend/patches/libdvbcsa/ 9 | #cp files/tvheadend43.patch docker-tvheadend/patches/tvheadend/ 10 | cp files/10-adduser docker-tvheadend/ 11 | cat files/docker > docker-tvheadend/Dockerfile 12 | cat files/metric_heartbeat.sh > docker-tvheadend/metric_heartbeat.sh 13 | cd docker-tvheadend/ 14 | docker build --platform linux/arm64 -t thealhu/tvheadend-aarch64 --network host --no-cache . 15 | -------------------------------------------------------------------------------- /armv7/build.sh: -------------------------------------------------------------------------------- 1 | rm -rf docker-tvheadend 2 | git clone https://github.com/linuxserver/docker-tvheadend.git 3 | mkdir docker-tvheadend/patches/argtable 4 | mkdir docker-tvheadend/patches/cpan 5 | mkdir docker-tvheadend/patches/libdvbcsa 6 | mkdir docker-tvheadend/patches/tvheadend 7 | mv docker-tvheadend/patches/config.guess docker-tvheadend/patches/argtable/ 8 | mv docker-tvheadend/patches/config.sub docker-tvheadend/patches/argtable/ 9 | mv docker-tvheadend/patches/cpanfile docker-tvheadend/patches/cpan 10 | cp files/libdvbcsa.patch docker-tvheadend/patches/libdvbcsa/ 11 | cp files/tvheadend43.patch docker-tvheadend/patches/tvheadend/ 12 | cp files/cpanm docker-tvheadend/ 13 | cp files/10-adduser docker-tvheadend/ 14 | cat files/docker > docker-tvheadend/Dockerfile 15 | cd docker-tvheadend/ 16 | docker build -t thealhu/tvheadend-armv7 --network host --no-cache . 17 | -------------------------------------------------------------------------------- /x64/files/metric_heartbeat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ $heartbeat_alive == "false" ]]; then 4 | exit 0 5 | else 6 | API_KEY=619269e542c207099e02a64106697e4c 7 | EVENT_TYPE="heartbeat" 8 | URL=https://api2.amplitude.com/2/httpapi 9 | UUID_FILE="/config/.thealhu_amplitude_uuid" 10 | 11 | # Check if UUID file exists and read from it, otherwise create a new one 12 | if [ -f "$UUID_FILE" ]; then 13 | HOSTNAME=$(cat "$UUID_FILE") 14 | else 15 | HOSTNAME=$(cat /proc/sys/kernel/random/uuid) 16 | echo "$HOSTNAME" > "$UUID_FILE" 17 | fi 18 | 19 | # Create the JSON data 20 | JSON_DATA=$(printf '{"api_key": "%s", "events": [{"device_id": "%s", "event_type": "%s"}]}' "$API_KEY" "$HOSTNAME" "$EVENT_TYPE") 21 | 22 | while true 23 | do 24 | # Make the POST request 25 | curl -X POST $URL -H 'Content-Type: application/json' -H 'Accept: */*' --data "$JSON_DATA" > /dev/null 2>&1 26 | 27 | # Wait for 1 hour before next execution 28 | sleep 3600 29 | done 30 | fi -------------------------------------------------------------------------------- /aarch64/files/metric_heartbeat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [[ $heartbeat_alive == "false" ]]; then 4 | exit 0 5 | else 6 | API_KEY=619269e542c207099e02a64106697e4c 7 | EVENT_TYPE="heartbeat" 8 | URL=https://api2.amplitude.com/2/httpapi 9 | UUID_FILE="/config/.thealhu_amplitude_uuid" 10 | 11 | # Check if UUID file exists and read from it, otherwise create a new one 12 | if [ -f "$UUID_FILE" ]; then 13 | HOSTNAME=$(cat "$UUID_FILE") 14 | else 15 | HOSTNAME=$(cat /proc/sys/kernel/random/uuid) 16 | echo "$HOSTNAME" > "$UUID_FILE" 17 | fi 18 | 19 | # Create the JSON data 20 | JSON_DATA=$(printf '{"api_key": "%s", "events": [{"device_id": "%s", "event_type": "%s"}]}' "$API_KEY" "$HOSTNAME" "$EVENT_TYPE") 21 | 22 | while true 23 | do 24 | # Make the POST request 25 | curl -X POST $URL -H 'Content-Type: application/json' -H 'Accept: */*' --data "$JSON_DATA" > /dev/null 2>&1 26 | 27 | # Wait for 1 hour before next execution 28 | sleep 3600 29 | done 30 | fi -------------------------------------------------------------------------------- /x64/files/tvheadend43.patch: -------------------------------------------------------------------------------- 1 | --- a/configure 2 | +++ b/configure 3 | @@ -714,6 +714,14 @@ if enabled_or_auto tvhcsa; then 4 | check_cc_lib dvbcsa dvbcsa_l) ||\ 5 | die "Failed to find dvbcsa library" 6 | LDFLAGS="$LDFLAGS -ldvbcsa" 7 | + check_cc ' 8 | + #include 9 | + int test(void) 10 | + { 11 | + dvbcsa_bs_key_set_ecm; 12 | + return 0; 13 | + } 14 | + ' && CFLAGS="$CFLAGS -DDVBCSA_KEY_ECM=1" && printf " ^ dvbcsa icam\n" 15 | fi 16 | else 17 | disable tvhcsa 18 | --- a/src/descrambler/tvhcsa.h 19 | +++ b/src/descrambler/tvhcsa.h 20 | @@ -26,6 +26,9 @@ struct elementary_stream; 21 | #include "build.h" 22 | #if ENABLE_DVBCSA 23 | #include 24 | +#if DVBCSA_KEY_ECM > 0 25 | +#define dvbcsa_bs_key_set(a,b) dvbcsa_bs_key_set_ecm(csa->csa_ecm,a,b) 26 | +#endif 27 | #endif 28 | #include "tvhlog.h" 29 | 30 | @@ -47,6 +50,7 @@ typedef struct tvhcsa 31 | uint8_t *csa_tsbcluster; 32 | int csa_fill; 33 | int csa_fill_size; 34 | + uint8_t csa_ecm; 35 | 36 | #if ENABLE_DVBCSA 37 | struct dvbcsa_bs_batch_s *csa_tsbbatch_even; -------------------------------------------------------------------------------- /armv7/files/10-adduser: -------------------------------------------------------------------------------- 1 | #!/usr/bin/with-contenv bash 2 | 3 | PUID=${PUID:-911} 4 | PGID=${PGID:-911} 5 | 6 | groupmod -o -g "$PGID" abc 7 | usermod -o -u "$PUID" abc 8 | 9 | echo ' 10 | ------------------------------------- 11 | 12 | ████████╗██╗ ██╗███████╗ █████╗ ██╗ ██╗ ██╗██╗ ██╗ ▄█╗ ███████╗ 13 | ╚══██╔══╝██║ ██║██╔════╝██╔══██╗██║ ██║ ██║██║ ██║ ╚═╝ ██╔════╝ 14 | ██║ ███████║█████╗ ███████║██║ ███████║██║ ██║ ███████╗ 15 | ██║ ██╔══██║██╔══╝ ██╔══██║██║ ██╔══██║██║ ██║ ╚════██║ 16 | ██║ ██║ ██║███████╗██║ ██║███████╗██║ ██║╚██████╔╝ ███████║ 17 | ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ 18 | 19 | ███████╗██╗ █████╗ ██╗ ██╗ ██████╗ ██████╗ 20 | ██╔════╝██║ ██╔══██╗██║ ██║██╔═══██╗██╔══██╗ 21 | █████╗ ██║ ███████║██║ ██║██║ ██║██████╔╝ 22 | ██╔══╝ ██║ ██╔══██║╚██╗ ██╔╝██║ ██║██╔══██╗ 23 | ██║ ███████╗██║ ██║ ╚████╔╝ ╚██████╔╝██║ ██║ 24 | ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ 25 | 26 | ██████╗ ███████╗ 27 | ██╔═══██╗██╔════╝ 28 | ██║ ██║█████╗ 29 | ██║ ██║██╔══╝ 30 | ╚██████╔╝██║ 31 | ╚═════╝ ╚═╝ 32 | 33 | ████████╗██╗ ██╗██╗ ██╗███████╗ █████╗ ██████╗ ███████╗███╗ ██╗██████╗ 34 | ╚══██╔══╝██║ ██║██║ ██║██╔════╝██╔══██╗██╔══██╗██╔════╝████╗ ██║██╔══██╗ 35 | ██║ ██║ ██║███████║█████╗ ███████║██║ ██║█████╗ ██╔██╗ ██║██║ ██║ 36 | ██║ ╚██╗ ██╔╝██╔══██║██╔══╝ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║██║ ██║ 37 | ██║ ╚████╔╝ ██║ ██║███████╗██║ ██║██████╔╝███████╗██║ ╚████║██████╔╝ 38 | ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚═╝ ╚═══╝╚═════╝ 39 | 40 | -------------------------------------' 41 | 42 | echo ' 43 | GID/UID 44 | -------------------------------------' 45 | echo " 46 | User uid: $(id -u abc) 47 | User gid: $(id -g abc) 48 | ------------------------------------- 49 | " 50 | 51 | time32="$(date +%Y)" 52 | 53 | if [[ "${time32}" == "1970" || "${time32}" == "1969" ]] && [ "$(uname -m)" == "armv7l" ]; then 54 | echo ' 55 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 56 | 57 | Your DockerHost is running an outdated version of libseccomp 58 | 59 | To fix this, please visit https://docs.linuxserver.io/faq#libseccomp 60 | 61 | Apps will not behave correctly without this 62 | 63 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 64 | ' 65 | sleep infinity 66 | fi 67 | 68 | chown abc:abc /app 69 | chown abc:abc /config 70 | chown abc:abc /defaults 71 | -------------------------------------------------------------------------------- /aarch64/files/10-adduser: -------------------------------------------------------------------------------- 1 | #!/usr/bin/with-contenv bash 2 | 3 | /usr/bin/metric_heartbeat.sh & 4 | 5 | PUID=${PUID:-911} 6 | PGID=${PGID:-911} 7 | 8 | groupmod -o -g "$PGID" abc 9 | usermod -o -u "$PUID" abc 10 | 11 | echo ' 12 | ------------------------------------- 13 | 14 | ████████╗██╗ ██╗███████╗ █████╗ ██╗ ██╗ ██╗██╗ ██╗ ▄█╗ ███████╗ 15 | ╚══██╔══╝██║ ██║██╔════╝██╔══██╗██║ ██║ ██║██║ ██║ ╚═╝ ██╔════╝ 16 | ██║ ███████║█████╗ ███████║██║ ███████║██║ ██║ ███████╗ 17 | ██║ ██╔══██║██╔══╝ ██╔══██║██║ ██╔══██║██║ ██║ ╚════██║ 18 | ██║ ██║ ██║███████╗██║ ██║███████╗██║ ██║╚██████╔╝ ███████║ 19 | ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ 20 | 21 | ███████╗██╗ █████╗ ██╗ ██╗ ██████╗ ██████╗ 22 | ██╔════╝██║ ██╔══██╗██║ ██║██╔═══██╗██╔══██╗ 23 | █████╗ ██║ ███████║██║ ██║██║ ██║██████╔╝ 24 | ██╔══╝ ██║ ██╔══██║╚██╗ ██╔╝██║ ██║██╔══██╗ 25 | ██║ ███████╗██║ ██║ ╚████╔╝ ╚██████╔╝██║ ██║ 26 | ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ 27 | 28 | ██████╗ ███████╗ 29 | ██╔═══██╗██╔════╝ 30 | ██║ ██║█████╗ 31 | ██║ ██║██╔══╝ 32 | ╚██████╔╝██║ 33 | ╚═════╝ ╚═╝ 34 | 35 | ████████╗██╗ ██╗██╗ ██╗███████╗ █████╗ ██████╗ ███████╗███╗ ██╗██████╗ 36 | ╚══██╔══╝██║ ██║██║ ██║██╔════╝██╔══██╗██╔══██╗██╔════╝████╗ ██║██╔══██╗ 37 | ██║ ██║ ██║███████║█████╗ ███████║██║ ██║█████╗ ██╔██╗ ██║██║ ██║ 38 | ██║ ╚██╗ ██╔╝██╔══██║██╔══╝ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║██║ ██║ 39 | ██║ ╚████╔╝ ██║ ██║███████╗██║ ██║██████╔╝███████╗██║ ╚████║██████╔╝ 40 | ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚═╝ ╚═══╝╚═════╝ 41 | 42 | -------------------------------------' 43 | 44 | echo ' 45 | GID/UID 46 | -------------------------------------' 47 | echo " 48 | User uid: $(id -u abc) 49 | User gid: $(id -g abc) 50 | ------------------------------------- 51 | " 52 | 53 | time32="$(date +%Y)" 54 | 55 | if [[ "${time32}" == "1970" || "${time32}" == "1969" ]] && [ "$(uname -m)" == "armv7l" ]; then 56 | echo ' 57 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 58 | 59 | Your DockerHost is running an outdated version of libseccomp 60 | 61 | To fix this, please visit https://docs.linuxserver.io/faq#libseccomp 62 | 63 | Apps will not behave correctly without this 64 | 65 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 66 | ' 67 | sleep infinity 68 | fi 69 | 70 | chown abc:abc /app 71 | chown abc:abc /config 72 | chown abc:abc /defaults 73 | -------------------------------------------------------------------------------- /x64/files/10-adduser: -------------------------------------------------------------------------------- 1 | #!/usr/bin/with-contenv bash 2 | 3 | /usr/bin/metric_heartbeat.sh & 4 | 5 | PUID=${PUID:-911} 6 | PGID=${PGID:-911} 7 | 8 | groupmod -o -g "$PGID" abc 9 | usermod -o -u "$PUID" abc 10 | 11 | echo ' 12 | ------------------------------------- 13 | 14 | ████████╗██╗ ██╗███████╗ █████╗ ██╗ ██╗ ██╗██╗ ██╗ ▄█╗ ███████╗ 15 | ╚══██╔══╝██║ ██║██╔════╝██╔══██╗██║ ██║ ██║██║ ██║ ╚═╝ ██╔════╝ 16 | ██║ ███████║█████╗ ███████║██║ ███████║██║ ██║ ███████╗ 17 | ██║ ██╔══██║██╔══╝ ██╔══██║██║ ██╔══██║██║ ██║ ╚════██║ 18 | ██║ ██║ ██║███████╗██║ ██║███████╗██║ ██║╚██████╔╝ ███████║ 19 | ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ 20 | 21 | ███████╗██╗ █████╗ ██╗ ██╗ ██████╗ ██████╗ 22 | ██╔════╝██║ ██╔══██╗██║ ██║██╔═══██╗██╔══██╗ 23 | █████╗ ██║ ███████║██║ ██║██║ ██║██████╔╝ 24 | ██╔══╝ ██║ ██╔══██║╚██╗ ██╔╝██║ ██║██╔══██╗ 25 | ██║ ███████╗██║ ██║ ╚████╔╝ ╚██████╔╝██║ ██║ 26 | ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ 27 | 28 | ██████╗ ███████╗ 29 | ██╔═══██╗██╔════╝ 30 | ██║ ██║█████╗ 31 | ██║ ██║██╔══╝ 32 | ╚██████╔╝██║ 33 | ╚═════╝ ╚═╝ 34 | 35 | ████████╗██╗ ██╗██╗ ██╗███████╗ █████╗ ██████╗ ███████╗███╗ ██╗██████╗ 36 | ╚══██╔══╝██║ ██║██║ ██║██╔════╝██╔══██╗██╔══██╗██╔════╝████╗ ██║██╔══██╗ 37 | ██║ ██║ ██║███████║█████╗ ███████║██║ ██║█████╗ ██╔██╗ ██║██║ ██║ 38 | ██║ ╚██╗ ██╔╝██╔══██║██╔══╝ ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║██║ ██║ 39 | ██║ ╚████╔╝ ██║ ██║███████╗██║ ██║██████╔╝███████╗██║ ╚████║██████╔╝ 40 | ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚═╝ ╚═══╝╚═════╝ 41 | 42 | -------------------------------------' 43 | 44 | echo ' 45 | GID/UID 46 | -------------------------------------' 47 | echo " 48 | User uid: $(id -u abc) 49 | User gid: $(id -g abc) 50 | ------------------------------------- 51 | " 52 | 53 | time32="$(date +%Y)" 54 | 55 | if [[ "${time32}" == "1970" || "${time32}" == "1969" ]] && [ "$(uname -m)" == "armv7l" ]; then 56 | echo ' 57 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 58 | 59 | Your DockerHost is running an outdated version of libseccomp 60 | 61 | To fix this, please visit https://docs.linuxserver.io/faq#libseccomp 62 | 63 | Apps will not behave correctly without this 64 | 65 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 66 | ' 67 | sleep infinity 68 | fi 69 | 70 | chown abc:abc /app 71 | chown abc:abc /config 72 | chown abc:abc /defaults 73 | -------------------------------------------------------------------------------- /aarch64/files/tvheadend43.patch: -------------------------------------------------------------------------------- 1 | --- a/configure 2 | +++ b/configure 3 | @@ -714,6 +714,14 @@ if enabled_or_auto tvhcsa; then 4 | check_cc_lib dvbcsa dvbcsa_l) ||\ 5 | die "Failed to find dvbcsa library" 6 | LDFLAGS="$LDFLAGS -ldvbcsa" 7 | + check_cc ' 8 | + #include 9 | + int test(void) 10 | + { 11 | + dvbcsa_bs_key_set_ecm; 12 | + return 0; 13 | + } 14 | + ' && CFLAGS="$CFLAGS -DDVBCSA_KEY_ECM=1" && printf " ^ dvbcsa icam\n" 15 | fi 16 | else 17 | disable tvhcsa 18 | --- a/src/descrambler/caid.h 19 | +++ b/src/descrambler/caid.h 20 | @@ -46,6 +46,7 @@ uint16_t name2caid(const char *str); 21 | card_type_t detect_card_type(const uint16_t caid); 22 | 23 | static inline int caid_is_irdeto(uint16_t caid) { return (caid >> 8) == 0x06; } 24 | +static inline int caid_is_videoguard(uint16_t caid) { return (caid >> 8) == 0x09; } 25 | static inline int caid_is_powervu(uint16_t caid) { return (caid >> 8) == 0x0e; } 26 | static inline int caid_is_betacrypt(uint16_t caid) { return (caid >> 8) == 0x17; } 27 | static inline int caid_is_dvn(uint16_t caid) { return caid == 0x4a30; } 28 | --- a/src/descrambler/descrambler.c 29 | +++ b/src/descrambler/descrambler.c 30 | @@ -1301,6 +1301,8 @@ descrambler_table_callback 31 | int64_t clk, clk2, clk3; 32 | uint8_t ki; 33 | int i, j; 34 | + caid_t *ca; 35 | + elementary_stream_t *st; 36 | 37 | if (len < 6) 38 | return 0; 39 | @@ -1362,13 +1364,20 @@ descrambler_table_callback 40 | if (dr->dr_ecm_parity == ECM_PARITY_81EVEN_80ODD) 41 | j ^= 1; 42 | dr->dr_ecm_start[j] = clk; 43 | - if (dr->dr_quick_ecm) { 44 | - ki = 1 << (j + 6); /* 0x40 = even, 0x80 = odd */ 45 | - for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) { 46 | - tk = &dr->dr_keys[i]; 47 | + ki = 1 << (j + 6); /* 0x40 = even, 0x80 = odd */ 48 | + for (i = 0; i < DESCRAMBLER_MAX_KEYS; i++) { 49 | + tk = &dr->dr_keys[i]; 50 | + if (dr->dr_quick_ecm) 51 | tk->key_valid &= ~ki; 52 | - if (tk->key_pid == 0) break; 53 | + TAILQ_FOREACH(st, &mt->mt_service->s_components.set_filter, es_filter_link) { 54 | + if (st->es_pid != mt->mt_pid) continue; 55 | + LIST_FOREACH(ca, &st->es_caids, link) { 56 | + if (ca->use == 0) continue; 57 | + tk->key_csa.csa_ecm = (caid_is_videoguard(ca->caid) && (ptr[4] != 0 && (ptr[2] - ptr[4]) == 4)) ? ptr[21] : 0; 58 | + tvhtrace(LS_DESCRAMBLER, "key ecm=%X (caid=%04X)", tk->key_csa.csa_ecm, ca->caid); 59 | + } 60 | } 61 | + if (tk->key_pid == 0) break; 62 | } 63 | } 64 | tvhtrace(LS_DESCRAMBLER, "ECM message %02x:%02x (section %d, len %d, pid %d) for service \"%s\"", 65 | --- a/src/descrambler/tvhcsa.h 66 | +++ b/src/descrambler/tvhcsa.h 67 | @@ -26,6 +26,9 @@ struct elementary_stream; 68 | #include "build.h" 69 | #if ENABLE_DVBCSA 70 | #include 71 | +#if DVBCSA_KEY_ECM > 0 72 | +#define dvbcsa_bs_key_set(a,b) dvbcsa_bs_key_set_ecm(csa->csa_ecm,a,b) 73 | +#endif 74 | #endif 75 | #include "tvhlog.h" 76 | 77 | @@ -47,6 +50,7 @@ typedef struct tvhcsa 78 | uint8_t *csa_tsbcluster; 79 | int csa_fill; 80 | int csa_fill_size; 81 | + uint8_t csa_ecm; 82 | 83 | #if ENABLE_DVBCSA 84 | struct dvbcsa_bs_batch_s *csa_tsbbatch_even; 85 | -------------------------------------------------------------------------------- /armv7/files/tvheadend43.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/descrambler/descrambler.c b/src/descrambler/descrambler.c 2 | index 71cc9ebd6..b5c46e329 100644 3 | --- a/src/descrambler/descrambler.c 4 | +++ b/src/descrambler/descrambler.c 5 | @@ -966,12 +966,12 @@ key_flush( th_descrambler_runtime_t *dr, th_descrambler_key_t *tk, uint8_t chang 6 | /* update the keys */ 7 | if (changed & 1) { 8 | debug2("%p: even key[%d] set for decoder", dr, tk->key_pid); 9 | - tvhcsa_set_key_even(&tk->key_csa, tk->key_data[0]); 10 | + tvhcsa_set_key_even(&tk->key_csa, tk->key_data[0], dr->dr_ecm); 11 | tk->key_valid |= 0x40; 12 | } 13 | if (changed & 2) { 14 | debug2("%p: odd key[%d] set for decoder", dr, tk->key_pid); 15 | - tvhcsa_set_key_odd(&tk->key_csa, tk->key_data[1]); 16 | + tvhcsa_set_key_odd(&tk->key_csa, tk->key_data[1], dr->dr_ecm); 17 | tk->key_valid |= 0x80; 18 | } 19 | } 20 | @@ -1371,6 +1371,7 @@ descrambler_table_callback 21 | } 22 | } 23 | } 24 | + dr->dr_ecm = (ptr[2] - ptr[4]) == 4 ? ptr[0x15] : 0; 25 | tvhtrace(LS_DESCRAMBLER, "ECM message %02x:%02x (section %d, len %d, pid %d) for service \"%s\"", 26 | ptr[0], ptr[1], des->number, len, mt->mt_pid, t->s_dvb_svcname); 27 | } 28 | diff --git a/src/descrambler/descrambler.h b/src/descrambler/descrambler.h 29 | index ac5ff312c..697adfe04 100644 30 | --- a/src/descrambler/descrambler.h 31 | +++ b/src/descrambler/descrambler.h 32 | @@ -103,6 +103,7 @@ typedef struct th_descrambler_runtime { 33 | int64_t dr_ecm_start[2]; 34 | int64_t dr_ecm_last_key_time; 35 | int64_t dr_ecm_key_margin; 36 | + uint8_t dr_ecm; 37 | int64_t dr_last_err; 38 | int64_t dr_force_skip; 39 | th_descrambler_key_t dr_keys[DESCRAMBLER_MAX_KEYS]; 40 | diff --git a/src/descrambler/tvhcsa.c b/src/descrambler/tvhcsa.c 41 | index 942ce92b5..664523665 100644 42 | --- a/src/descrambler/tvhcsa.c 43 | +++ b/src/descrambler/tvhcsa.c 44 | @@ -220,12 +220,12 @@ tvhcsa_set_type( tvhcsa_t *csa, struct mpegts_service *s, int type ) 45 | } 46 | 47 | 48 | -void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even ) 49 | +void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even, const uint8_t ecm) 50 | { 51 | switch (csa->csa_type) { 52 | case DESCRAMBLER_CSA_CBC: 53 | #if ENABLE_DVBCSA 54 | - dvbcsa_bs_key_set(even, csa->csa_key_even); 55 | + dvbcsa_bs_key_set_ecm(ecm, even, csa->csa_key_even); 56 | #endif 57 | break; 58 | case DESCRAMBLER_DES_NCB: 59 | @@ -241,13 +241,13 @@ void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even ) 60 | } 61 | } 62 | 63 | -void tvhcsa_set_key_odd( tvhcsa_t *csa, const uint8_t *odd ) 64 | +void tvhcsa_set_key_odd( tvhcsa_t *csa, const uint8_t *odd, const uint8_t ecm ) 65 | { 66 | assert(csa->csa_type); 67 | switch (csa->csa_type) { 68 | case DESCRAMBLER_CSA_CBC: 69 | #if ENABLE_DVBCSA 70 | - dvbcsa_bs_key_set(odd, csa->csa_key_odd); 71 | + dvbcsa_bs_key_set_ecm(ecm, odd, csa->csa_key_odd); 72 | #endif 73 | break; 74 | case DESCRAMBLER_DES_NCB: 75 | diff --git a/src/descrambler/tvhcsa.h b/src/descrambler/tvhcsa.h 76 | index 855de5acc..24eb729cb 100644 77 | --- a/src/descrambler/tvhcsa.h 78 | +++ b/src/descrambler/tvhcsa.h 79 | @@ -66,8 +66,8 @@ typedef struct tvhcsa 80 | 81 | int tvhcsa_set_type( tvhcsa_t *csa, struct mpegts_service *s, int type ); 82 | 83 | -void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even ); 84 | -void tvhcsa_set_key_odd ( tvhcsa_t *csa, const uint8_t *odd ); 85 | +void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even, const uint8_t ecm ); 86 | +void tvhcsa_set_key_odd ( tvhcsa_t *csa, const uint8_t *odd, const uint8_t ecm ); 87 | 88 | void tvhcsa_init ( tvhcsa_t *csa ); 89 | void tvhcsa_destroy ( tvhcsa_t *csa ); 90 | @@ -76,8 +76,8 @@ void tvhcsa_destroy ( tvhcsa_t *csa ); 91 | 92 | static inline int tvhcsa_set_type( tvhcsa_t *csa, struct mpegts_service *s, int type ) { return -1; } 93 | 94 | -static inline void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even ) { }; 95 | -static inline void tvhcsa_set_key_odd ( tvhcsa_t *csa, const uint8_t *odd ) { }; 96 | +static inline void tvhcsa_set_key_even( tvhcsa_t *csa, const uint8_t *even, const uint8_t ecm ) { }; 97 | +static inline void tvhcsa_set_key_odd ( tvhcsa_t *csa, const uint8_t *odd, const uint8_t ecm ) { }; 98 | 99 | static inline void tvhcsa_init ( tvhcsa_t *csa ) { }; 100 | static inline void tvhcsa_destroy ( tvhcsa_t *csa ) { }; 101 | -------------------------------------------------------------------------------- /armv7/files/libdvbcsa.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/dvbcsa/dvbcsa.h b/src/dvbcsa/dvbcsa.h 2 | index c7e9c59..b63fb7d 100644 3 | --- a/src/dvbcsa/dvbcsa.h 4 | +++ b/src/dvbcsa/dvbcsa.h 5 | @@ -93,6 +93,8 @@ void dvbcsa_bs_key_free(struct dvbcsa_bs_key_s *key); 6 | 7 | void dvbcsa_bs_key_set(const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key); 8 | 9 | +void dvbcsa_bs_key_set_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key); 10 | + 11 | /** get maximum number of packet per batch */ 12 | 13 | unsigned int dvbcsa_bs_batch_size(void); 14 | diff --git a/src/dvbcsa_bs_key.c b/src/dvbcsa_bs_key.c 15 | index e2fcf55..d703325 100644 16 | --- a/src/dvbcsa_bs_key.c 17 | +++ b/src/dvbcsa_bs_key.c 18 | @@ -63,3 +63,39 @@ dvbcsa_bs_key_set (const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key) 19 | } 20 | } 21 | 22 | +void 23 | +dvbcsa_bs_key_set_ecm (const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key) 24 | +{ 25 | + dvbcsa_keys_t kk; 26 | + int i; 27 | + 28 | + /* precalculations for stream */ 29 | + 30 | + uint64_t ck = dvbcsa_load_le64(cw); 31 | + 32 | + for (i = 0; i < DVBCSA_CWBITS_SIZE; i++) 33 | + key->stream[i] = (ck >> (i^4)) & 1 ? BS_VAL8(ff) : BS_VAL8(00); 34 | + 35 | + /* precalculations for block */ 36 | + 37 | + dvbcsa_key_schedule_block_ecm(ecm, cw, kk); 38 | + 39 | + for (i = 0; i < DVBCSA_KEYSBUFF_SIZE; i++) 40 | + { 41 | +#if BS_BATCH_SIZE == 32 42 | + *(dvbcsa_u32_aliasing_t *)(key->block + i) = kk[i] * 0x01010101; 43 | + 44 | +#elif BS_BATCH_SIZE == 64 45 | + *(dvbcsa_u64_aliasing_t *)(key->block + i) = kk[i] * 0x0101010101010101ULL; 46 | + 47 | +#elif BS_BATCH_SIZE > 64 && BS_BATCH_SIZE % 64 == 0 48 | + uint64_t v = kk[i] * 0x0101010101010101ULL; 49 | + int j; 50 | + 51 | + for (j = 0; j < BS_BATCH_BYTES / 8; j++) 52 | + *((dvbcsa_u64_aliasing_t *)(key->block + i) + j) = v; 53 | +#else 54 | +# error 55 | +#endif 56 | + } 57 | +} 58 | diff --git a/src/dvbcsa_key.c b/src/dvbcsa_key.c 59 | index 1ff17e0..bd2a2c1 100644 60 | --- a/src/dvbcsa_key.c 61 | +++ b/src/dvbcsa_key.c 62 | @@ -585,3 +585,18 @@ dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk) 63 | kk[i*8+j] = (k[i]>>(j*8)) ^ i; 64 | } 65 | 66 | +void 67 | +dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk) 68 | +{ 69 | + uint64_t k[7]; 70 | + int i, j; 71 | + 72 | + k[6] = dvbcsa_load_le64_ecm(ecm, cw); 73 | + for (i = 6; i > 0; i--) 74 | + k[i - 1] = dvbcsa_key_permute_block(k[i]); 75 | + 76 | + for (i = 0; i < 7; i++) 77 | + for (j = 0; j < 8; j++) 78 | + kk[i*8+j] = (k[i]>>(j*8)) ^ i; 79 | +} 80 | + 81 | diff --git a/src/dvbcsa_pv.h b/src/dvbcsa_pv.h 82 | index 83753b1..e59a70d 100644 83 | --- a/src/dvbcsa_pv.h 84 | +++ b/src/dvbcsa_pv.h 85 | @@ -88,6 +88,26 @@ struct dvbcsa_key_s 86 | 87 | extern const uint8_t dvbcsa_block_sbox[256]; 88 | 89 | +static const uint8_t csa_block_perm_ecm[256] = 90 | + { 91 | + 0x00,0x02,0x80,0x82,0x20,0x22,0xa0,0xa2, 0x04,0x06,0x84,0x86,0x24,0x26,0xa4,0xa6, 92 | + 0x40,0x42,0xc0,0xc2,0x60,0x62,0xe0,0xe2, 0x44,0x46,0xc4,0xc6,0x64,0x66,0xe4,0xe6, 93 | + 0x01,0x03,0x81,0x83,0x21,0x23,0xa1,0xa3, 0x05,0x07,0x85,0x87,0x25,0x27,0xa5,0xa7, 94 | + 0x41,0x43,0xc1,0xc3,0x61,0x63,0xe1,0xe3, 0x45,0x47,0xc5,0xc7,0x65,0x67,0xe5,0xe7, 95 | + 0x08,0x0a,0x88,0x8a,0x28,0x2a,0xa8,0xaa, 0x0c,0x0e,0x8c,0x8e,0x2c,0x2e,0xac,0xae, 96 | + 0x48,0x4a,0xc8,0xca,0x68,0x6a,0xe8,0xea, 0x4c,0x4e,0xcc,0xce,0x6c,0x6e,0xec,0xee, 97 | + 0x09,0x0b,0x89,0x8b,0x29,0x2b,0xa9,0xab, 0x0d,0x0f,0x8d,0x8f,0x2d,0x2f,0xad,0xaf, 98 | + 0x49,0x4b,0xc9,0xcb,0x69,0x6b,0xe9,0xeb, 0x4d,0x4f,0xcd,0xcf,0x6d,0x6f,0xed,0xef, 99 | + 0x10,0x12,0x90,0x92,0x30,0x32,0xb0,0xb2, 0x14,0x16,0x94,0x96,0x34,0x36,0xb4,0xb6, 100 | + 0x50,0x52,0xd0,0xd2,0x70,0x72,0xf0,0xf2, 0x54,0x56,0xd4,0xd6,0x74,0x76,0xf4,0xf6, 101 | + 0x11,0x13,0x91,0x93,0x31,0x33,0xb1,0xb3, 0x15,0x17,0x95,0x97,0x35,0x37,0xb5,0xb7, 102 | + 0x51,0x53,0xd1,0xd3,0x71,0x73,0xf1,0xf3, 0x55,0x57,0xd5,0xd7,0x75,0x77,0xf5,0xf7, 103 | + 0x18,0x1a,0x98,0x9a,0x38,0x3a,0xb8,0xba, 0x1c,0x1e,0x9c,0x9e,0x3c,0x3e,0xbc,0xbe, 104 | + 0x58,0x5a,0xd8,0xda,0x78,0x7a,0xf8,0xfa, 0x5c,0x5e,0xdc,0xde,0x7c,0x7e,0xfc,0xfe, 105 | + 0x19,0x1b,0x99,0x9b,0x39,0x3b,0xb9,0xbb, 0x1d,0x1f,0x9d,0x9f,0x3d,0x3f,0xbd,0xbf, 106 | + 0x59,0x5b,0xd9,0xdb,0x79,0x7b,0xf9,0xfb, 0x5d,0x5f,0xdd,0xdf,0x7d,0x7f,0xfd,0xff 107 | +}; 108 | + 109 | void dvbcsa_block_decrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out); 110 | void dvbcsa_block_encrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out); 111 | 112 | @@ -95,6 +115,7 @@ void dvbcsa_stream_xor (const dvbcsa_cw_t cw, const dvbcsa_block_t iv, 113 | uint8_t *stream, unsigned int len); 114 | 115 | void dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk); 116 | +void dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk); 117 | 118 | DVBCSA_INLINE static inline void 119 | dvbcsa_xor_64 (uint8_t *b, const uint8_t *a) 120 | @@ -141,6 +162,33 @@ dvbcsa_load_le64(const uint8_t *p) 121 | #endif 122 | } 123 | 124 | +DVBCSA_INLINE static inline uint64_t 125 | +dvbcsa_load_le64_ecm(const unsigned char ecm, const uint8_t *p) 126 | +{ 127 | + dvbcsa_block_t W; 128 | + memcpy(W, p, sizeof(W)); 129 | + if (ecm == 4) 130 | + { 131 | + W[0] = csa_block_perm_ecm[p[0]]; 132 | + W[4] = csa_block_perm_ecm[p[4]]; 133 | + } 134 | +#if defined(DVBCSA_ENDIAN_LITTLE) 135 | + uint64_t i; 136 | + memcpy(&i, W, 8); 137 | + return i; 138 | +#else 139 | + return (uint64_t)( ((uint64_t)W[7] << 56) | 140 | + ((uint64_t)W[6] << 48) | 141 | + ((uint64_t)W[5] << 40) | 142 | + ((uint64_t)W[4] << 32) | 143 | + ((uint64_t)W[3] << 24) | 144 | + ((uint64_t)W[2] << 16) | 145 | + ((uint64_t)W[1] << 8 ) | 146 | + (uint64_t)W[0] 147 | + ); 148 | +#endif 149 | +} 150 | + 151 | DVBCSA_INLINE static inline void 152 | dvbcsa_store_le64(uint8_t *p, const uint64_t w) 153 | { 154 | -------------------------------------------------------------------------------- /x64/files/libdvbcsa.patch: -------------------------------------------------------------------------------- 1 | --- a/README 2 | +++ b/README 3 | @@ -135,6 +135,12 @@ Example: 4 | dvbcsa_bs_encrypt(key, b, 184); 5 | 6 | 7 | + DVBCSA_KEY_ECM 8 | + 9 | + unsigned char ecm = (ecm_caid >> 8 == 0x09 && (ecm_data[2] - ecm_data[4]) == 4) ? ecm_data[21] : 0; 10 | + dvbcsa_bs_key_set_ecm(ecm, cw, key); 11 | + 12 | + 13 | Portability 14 | =========== 15 | 16 | --- a/src/dvbcsa/dvbcsa.h 17 | +++ b/src/dvbcsa/dvbcsa.h 18 | @@ -93,6 +93,11 @@ void dvbcsa_bs_key_free(struct dvbcsa_bs_key_s *key); 19 | 20 | void dvbcsa_bs_key_set(const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key); 21 | 22 | +#ifndef DVBCSA_KEY_ECM 23 | +#define DVBCSA_KEY_ECM 1 24 | +#endif 25 | +void dvbcsa_bs_key_set_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key); 26 | + 27 | /** get maximum number of packet per batch */ 28 | 29 | unsigned int dvbcsa_bs_batch_size(void); 30 | --- a/src/dvbcsa_bs_key.c 31 | +++ b/src/dvbcsa_bs_key.c 32 | @@ -63,3 +63,40 @@ dvbcsa_bs_key_set (const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key) 33 | } 34 | } 35 | 36 | +void 37 | +dvbcsa_bs_key_set_ecm (const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key) 38 | +{ 39 | + dvbcsa_keys_t kk; 40 | + int i; 41 | + 42 | + /* precalculations for stream */ 43 | + 44 | + uint64_t ck = dvbcsa_load_le64(cw); 45 | + 46 | + for (i = 0; i < DVBCSA_CWBITS_SIZE; i++) 47 | + key->stream[i] = (ck >> (i^4)) & 1 ? BS_VAL8(ff) : BS_VAL8(00); 48 | + 49 | + /* precalculations for block */ 50 | + 51 | + dvbcsa_key_schedule_block_ecm(ecm, cw, kk); 52 | + 53 | + for (i = 0; i < DVBCSA_KEYSBUFF_SIZE; i++) 54 | + { 55 | +#if BS_BATCH_SIZE == 32 56 | + *(dvbcsa_u32_aliasing_t *)(key->block + i) = kk[i] * 0x01010101; 57 | + 58 | +#elif BS_BATCH_SIZE == 64 59 | + *(dvbcsa_u64_aliasing_t *)(key->block + i) = kk[i] * 0x0101010101010101ULL; 60 | + 61 | +#elif BS_BATCH_SIZE > 64 && BS_BATCH_SIZE % 64 == 0 62 | + uint64_t v = kk[i] * 0x0101010101010101ULL; 63 | + int j; 64 | + 65 | + for (j = 0; j < BS_BATCH_BYTES / 8; j++) 66 | + *((dvbcsa_u64_aliasing_t *)(key->block + i) + j) = v; 67 | +#else 68 | +# error 69 | +#endif 70 | + } 71 | +} 72 | + 73 | --- a/src/dvbcsa_key.c 74 | +++ b/src/dvbcsa_key.c 75 | @@ -585,3 +585,18 @@ dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk) 76 | kk[i*8+j] = (k[i]>>(j*8)) ^ i; 77 | } 78 | 79 | +void 80 | +dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk) 81 | +{ 82 | + uint64_t k[7]; 83 | + int i, j; 84 | + 85 | + k[6] = dvbcsa_load_le64_ecm(ecm, cw); 86 | + for (i = 6; i > 0; i--) 87 | + k[i - 1] = dvbcsa_key_permute_block(k[i]); 88 | + 89 | + for (i = 0; i < 7; i++) 90 | + for (j = 0; j < 8; j++) 91 | + kk[i*8+j] = (k[i]>>(j*8)) ^ i; 92 | +} 93 | + 94 | --- a/src/dvbcsa_pv.h 95 | +++ b/src/dvbcsa_pv.h 96 | @@ -87,6 +87,25 @@ struct dvbcsa_key_s 97 | }; 98 | 99 | extern const uint8_t dvbcsa_block_sbox[256]; 100 | +static const uint8_t csa_block_perm_ecm[256] = 101 | +{ 102 | + 0x00, 0x02, 0x80, 0x82, 0x20, 0x22, 0xa0, 0xa2, 0x04, 0x06, 0x84, 0x86, 0x24, 0x26, 0xa4, 0xa6, 103 | + 0x40, 0x42, 0xc0, 0xc2, 0x60, 0x62, 0xe0, 0xe2, 0x44, 0x46, 0xc4, 0xc6, 0x64, 0x66, 0xe4, 0xe6, 104 | + 0x01, 0x03, 0x81, 0x83, 0x21, 0x23, 0xa1, 0xa3, 0x05, 0x07, 0x85, 0x87, 0x25, 0x27, 0xa5, 0xa7, 105 | + 0x41, 0x43, 0xc1, 0xc3, 0x61, 0x63, 0xe1, 0xe3, 0x45, 0x47, 0xc5, 0xc7, 0x65, 0x67, 0xe5, 0xe7, 106 | + 0x08, 0x0a, 0x88, 0x8a, 0x28, 0x2a, 0xa8, 0xaa, 0x0c, 0x0e, 0x8c, 0x8e, 0x2c, 0x2e, 0xac, 0xae, 107 | + 0x48, 0x4a, 0xc8, 0xca, 0x68, 0x6a, 0xe8, 0xea, 0x4c, 0x4e, 0xcc, 0xce, 0x6c, 0x6e, 0xec, 0xee, 108 | + 0x09, 0x0b, 0x89, 0x8b, 0x29, 0x2b, 0xa9, 0xab, 0x0d, 0x0f, 0x8d, 0x8f, 0x2d, 0x2f, 0xad, 0xaf, 109 | + 0x49, 0x4b, 0xc9, 0xcb, 0x69, 0x6b, 0xe9, 0xeb, 0x4d, 0x4f, 0xcd, 0xcf, 0x6d, 0x6f, 0xed, 0xef, 110 | + 0x10, 0x12, 0x90, 0x92, 0x30, 0x32, 0xb0, 0xb2, 0x14, 0x16, 0x94, 0x96, 0x34, 0x36, 0xb4, 0xb6, 111 | + 0x50, 0x52, 0xd0, 0xd2, 0x70, 0x72, 0xf0, 0xf2, 0x54, 0x56, 0xd4, 0xd6, 0x74, 0x76, 0xf4, 0xf6, 112 | + 0x11, 0x13, 0x91, 0x93, 0x31, 0x33, 0xb1, 0xb3, 0x15, 0x17, 0x95, 0x97, 0x35, 0x37, 0xb5, 0xb7, 113 | + 0x51, 0x53, 0xd1, 0xd3, 0x71, 0x73, 0xf1, 0xf3, 0x55, 0x57, 0xd5, 0xd7, 0x75, 0x77, 0xf5, 0xf7, 114 | + 0x18, 0x1a, 0x98, 0x9a, 0x38, 0x3a, 0xb8, 0xba, 0x1c, 0x1e, 0x9c, 0x9e, 0x3c, 0x3e, 0xbc, 0xbe, 115 | + 0x58, 0x5a, 0xd8, 0xda, 0x78, 0x7a, 0xf8, 0xfa, 0x5c, 0x5e, 0xdc, 0xde, 0x7c, 0x7e, 0xfc, 0xfe, 116 | + 0x19, 0x1b, 0x99, 0x9b, 0x39, 0x3b, 0xb9, 0xbb, 0x1d, 0x1f, 0x9d, 0x9f, 0x3d, 0x3f, 0xbd, 0xbf, 117 | + 0x59, 0x5b, 0xd9, 0xdb, 0x79, 0x7b, 0xf9, 0xfb, 0x5d, 0x5f, 0xdd, 0xdf, 0x7d, 0x7f, 0xfd, 0xff 118 | +}; 119 | 120 | void dvbcsa_block_decrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out); 121 | void dvbcsa_block_encrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out); 122 | @@ -95,6 +114,7 @@ void dvbcsa_stream_xor (const dvbcsa_cw_t cw, const dvbcsa_block_t iv, 123 | uint8_t *stream, unsigned int len); 124 | 125 | void dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk); 126 | +void dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk); 127 | 128 | DVBCSA_INLINE static inline void 129 | dvbcsa_xor_64 (uint8_t *b, const uint8_t *a) 130 | @@ -141,6 +161,33 @@ dvbcsa_load_le64(const uint8_t *p) 131 | #endif 132 | } 133 | 134 | +DVBCSA_INLINE static inline uint64_t 135 | +dvbcsa_load_le64_ecm(const unsigned char ecm, const uint8_t *p) 136 | +{ 137 | + dvbcsa_block_t W; 138 | + memcpy(W, p, sizeof(W)); 139 | + if (ecm == 4) 140 | + { 141 | + W[0] = csa_block_perm_ecm[p[0]]; 142 | + W[4] = csa_block_perm_ecm[p[4]]; 143 | + } 144 | +#if defined(DVBCSA_ENDIAN_LITTLE) 145 | + uint64_t i; 146 | + memcpy(&i, W, 8); 147 | + return i; 148 | +#else 149 | + return (uint64_t)( ((uint64_t)W[7] << 56) | 150 | + ((uint64_t)W[6] << 48) | 151 | + ((uint64_t)W[5] << 40) | 152 | + ((uint64_t)W[4] << 32) | 153 | + ((uint64_t)W[3] << 24) | 154 | + ((uint64_t)W[2] << 16) | 155 | + ((uint64_t)W[1] << 8 ) | 156 | + (uint64_t)W[0] 157 | + ); 158 | +#endif 159 | +} 160 | + 161 | DVBCSA_INLINE static inline void 162 | dvbcsa_store_le64(uint8_t *p, const uint64_t w) 163 | { 164 | -------------------------------------------------------------------------------- /aarch64/files/libdvbcsa.patch: -------------------------------------------------------------------------------- 1 | --- a/README 2 | +++ b/README 3 | @@ -135,6 +135,12 @@ Example: 4 | dvbcsa_bs_encrypt(key, b, 184); 5 | 6 | 7 | + DVBCSA_KEY_ECM 8 | + 9 | + unsigned char ecm = (ecm_caid >> 8 == 0x09 && (ecm_data[2] - ecm_data[4]) == 4) ? ecm_data[21] : 0; 10 | + dvbcsa_bs_key_set_ecm(ecm, cw, key); 11 | + 12 | + 13 | Portability 14 | =========== 15 | 16 | --- a/src/dvbcsa/dvbcsa.h 17 | +++ b/src/dvbcsa/dvbcsa.h 18 | @@ -93,6 +93,11 @@ void dvbcsa_bs_key_free(struct dvbcsa_bs_key_s *key); 19 | 20 | void dvbcsa_bs_key_set(const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key); 21 | 22 | +#ifndef DVBCSA_KEY_ECM 23 | +#define DVBCSA_KEY_ECM 1 24 | +#endif 25 | +void dvbcsa_bs_key_set_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key); 26 | + 27 | /** get maximum number of packet per batch */ 28 | 29 | unsigned int dvbcsa_bs_batch_size(void); 30 | --- a/src/dvbcsa_bs_key.c 31 | +++ b/src/dvbcsa_bs_key.c 32 | @@ -63,3 +63,40 @@ dvbcsa_bs_key_set (const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key) 33 | } 34 | } 35 | 36 | +void 37 | +dvbcsa_bs_key_set_ecm (const unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key) 38 | +{ 39 | + dvbcsa_keys_t kk; 40 | + int i; 41 | + 42 | + /* precalculations for stream */ 43 | + 44 | + uint64_t ck = dvbcsa_load_le64(cw); 45 | + 46 | + for (i = 0; i < DVBCSA_CWBITS_SIZE; i++) 47 | + key->stream[i] = (ck >> (i^4)) & 1 ? BS_VAL8(ff) : BS_VAL8(00); 48 | + 49 | + /* precalculations for block */ 50 | + 51 | + dvbcsa_key_schedule_block_ecm(ecm, cw, kk); 52 | + 53 | + for (i = 0; i < DVBCSA_KEYSBUFF_SIZE; i++) 54 | + { 55 | +#if BS_BATCH_SIZE == 32 56 | + *(dvbcsa_u32_aliasing_t *)(key->block + i) = kk[i] * 0x01010101; 57 | + 58 | +#elif BS_BATCH_SIZE == 64 59 | + *(dvbcsa_u64_aliasing_t *)(key->block + i) = kk[i] * 0x0101010101010101ULL; 60 | + 61 | +#elif BS_BATCH_SIZE > 64 && BS_BATCH_SIZE % 64 == 0 62 | + uint64_t v = kk[i] * 0x0101010101010101ULL; 63 | + int j; 64 | + 65 | + for (j = 0; j < BS_BATCH_BYTES / 8; j++) 66 | + *((dvbcsa_u64_aliasing_t *)(key->block + i) + j) = v; 67 | +#else 68 | +# error 69 | +#endif 70 | + } 71 | +} 72 | + 73 | --- a/src/dvbcsa_key.c 74 | +++ b/src/dvbcsa_key.c 75 | @@ -585,3 +585,18 @@ dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk) 76 | kk[i*8+j] = (k[i]>>(j*8)) ^ i; 77 | } 78 | 79 | +void 80 | +dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk) 81 | +{ 82 | + uint64_t k[7]; 83 | + int i, j; 84 | + 85 | + k[6] = dvbcsa_load_le64_ecm(ecm, cw); 86 | + for (i = 6; i > 0; i--) 87 | + k[i - 1] = dvbcsa_key_permute_block(k[i]); 88 | + 89 | + for (i = 0; i < 7; i++) 90 | + for (j = 0; j < 8; j++) 91 | + kk[i*8+j] = (k[i]>>(j*8)) ^ i; 92 | +} 93 | + 94 | --- a/src/dvbcsa_pv.h 95 | +++ b/src/dvbcsa_pv.h 96 | @@ -87,6 +87,25 @@ struct dvbcsa_key_s 97 | }; 98 | 99 | extern const uint8_t dvbcsa_block_sbox[256]; 100 | +static const uint8_t csa_block_perm_ecm[256] = 101 | +{ 102 | + 0x00, 0x02, 0x80, 0x82, 0x20, 0x22, 0xa0, 0xa2, 0x04, 0x06, 0x84, 0x86, 0x24, 0x26, 0xa4, 0xa6, 103 | + 0x40, 0x42, 0xc0, 0xc2, 0x60, 0x62, 0xe0, 0xe2, 0x44, 0x46, 0xc4, 0xc6, 0x64, 0x66, 0xe4, 0xe6, 104 | + 0x01, 0x03, 0x81, 0x83, 0x21, 0x23, 0xa1, 0xa3, 0x05, 0x07, 0x85, 0x87, 0x25, 0x27, 0xa5, 0xa7, 105 | + 0x41, 0x43, 0xc1, 0xc3, 0x61, 0x63, 0xe1, 0xe3, 0x45, 0x47, 0xc5, 0xc7, 0x65, 0x67, 0xe5, 0xe7, 106 | + 0x08, 0x0a, 0x88, 0x8a, 0x28, 0x2a, 0xa8, 0xaa, 0x0c, 0x0e, 0x8c, 0x8e, 0x2c, 0x2e, 0xac, 0xae, 107 | + 0x48, 0x4a, 0xc8, 0xca, 0x68, 0x6a, 0xe8, 0xea, 0x4c, 0x4e, 0xcc, 0xce, 0x6c, 0x6e, 0xec, 0xee, 108 | + 0x09, 0x0b, 0x89, 0x8b, 0x29, 0x2b, 0xa9, 0xab, 0x0d, 0x0f, 0x8d, 0x8f, 0x2d, 0x2f, 0xad, 0xaf, 109 | + 0x49, 0x4b, 0xc9, 0xcb, 0x69, 0x6b, 0xe9, 0xeb, 0x4d, 0x4f, 0xcd, 0xcf, 0x6d, 0x6f, 0xed, 0xef, 110 | + 0x10, 0x12, 0x90, 0x92, 0x30, 0x32, 0xb0, 0xb2, 0x14, 0x16, 0x94, 0x96, 0x34, 0x36, 0xb4, 0xb6, 111 | + 0x50, 0x52, 0xd0, 0xd2, 0x70, 0x72, 0xf0, 0xf2, 0x54, 0x56, 0xd4, 0xd6, 0x74, 0x76, 0xf4, 0xf6, 112 | + 0x11, 0x13, 0x91, 0x93, 0x31, 0x33, 0xb1, 0xb3, 0x15, 0x17, 0x95, 0x97, 0x35, 0x37, 0xb5, 0xb7, 113 | + 0x51, 0x53, 0xd1, 0xd3, 0x71, 0x73, 0xf1, 0xf3, 0x55, 0x57, 0xd5, 0xd7, 0x75, 0x77, 0xf5, 0xf7, 114 | + 0x18, 0x1a, 0x98, 0x9a, 0x38, 0x3a, 0xb8, 0xba, 0x1c, 0x1e, 0x9c, 0x9e, 0x3c, 0x3e, 0xbc, 0xbe, 115 | + 0x58, 0x5a, 0xd8, 0xda, 0x78, 0x7a, 0xf8, 0xfa, 0x5c, 0x5e, 0xdc, 0xde, 0x7c, 0x7e, 0xfc, 0xfe, 116 | + 0x19, 0x1b, 0x99, 0x9b, 0x39, 0x3b, 0xb9, 0xbb, 0x1d, 0x1f, 0x9d, 0x9f, 0x3d, 0x3f, 0xbd, 0xbf, 117 | + 0x59, 0x5b, 0xd9, 0xdb, 0x79, 0x7b, 0xf9, 0xfb, 0x5d, 0x5f, 0xdd, 0xdf, 0x7d, 0x7f, 0xfd, 0xff 118 | +}; 119 | 120 | void dvbcsa_block_decrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out); 121 | void dvbcsa_block_encrypt (const dvbcsa_keys_t key, const dvbcsa_block_t in, dvbcsa_block_t out); 122 | @@ -95,6 +114,7 @@ void dvbcsa_stream_xor (const dvbcsa_cw_t cw, const dvbcsa_block_t iv, 123 | uint8_t *stream, unsigned int len); 124 | 125 | void dvbcsa_key_schedule_block(const dvbcsa_cw_t cw, uint8_t * kk); 126 | +void dvbcsa_key_schedule_block_ecm(const unsigned char ecm, const dvbcsa_cw_t cw, uint8_t * kk); 127 | 128 | DVBCSA_INLINE static inline void 129 | dvbcsa_xor_64 (uint8_t *b, const uint8_t *a) 130 | @@ -141,6 +161,33 @@ dvbcsa_load_le64(const uint8_t *p) 131 | #endif 132 | } 133 | 134 | +DVBCSA_INLINE static inline uint64_t 135 | +dvbcsa_load_le64_ecm(const unsigned char ecm, const uint8_t *p) 136 | +{ 137 | + dvbcsa_block_t W; 138 | + memcpy(W, p, sizeof(W)); 139 | + if (ecm == 4) 140 | + { 141 | + W[0] = csa_block_perm_ecm[p[0]]; 142 | + W[4] = csa_block_perm_ecm[p[4]]; 143 | + } 144 | +#if defined(DVBCSA_ENDIAN_LITTLE) 145 | + uint64_t i; 146 | + memcpy(&i, W, 8); 147 | + return i; 148 | +#else 149 | + return (uint64_t)( ((uint64_t)W[7] << 56) | 150 | + ((uint64_t)W[6] << 48) | 151 | + ((uint64_t)W[5] << 40) | 152 | + ((uint64_t)W[4] << 32) | 153 | + ((uint64_t)W[3] << 24) | 154 | + ((uint64_t)W[2] << 16) | 155 | + ((uint64_t)W[1] << 8 ) | 156 | + (uint64_t)W[0] 157 | + ); 158 | +#endif 159 | +} 160 | + 161 | DVBCSA_INLINE static inline void 162 | dvbcsa_store_le64(uint8_t *p, const uint64_t w) 163 | { 164 | -------------------------------------------------------------------------------- /aarch64/files/docker: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | ############## picons stage ############## 4 | # built by https://github.com/linuxserver/picons-builder 5 | FROM ghcr.io/linuxserver/picons-builder as piconsstage 6 | 7 | 8 | FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.21 as buildstage 9 | ############## build stage ############## 10 | 11 | # package versions 12 | ARG ARGTABLE_VER="2.13" 13 | 14 | # environment settings 15 | ARG TZ="Europe/Vienna" 16 | ARG TVHEADEND_COMMIT 17 | ENV HOME="/config" 18 | 19 | # copy patches and picons 20 | COPY patches/ /tmp/patches/ 21 | COPY --from=piconsstage /picons.tar.bz2 /picons.tar.bz2 22 | 23 | RUN \ 24 | echo "**** install build packages ****" && \ 25 | apk add --no-cache \ 26 | autoconf \ 27 | automake \ 28 | bsd-compat-headers \ 29 | build-base \ 30 | cmake \ 31 | ffmpeg4-dev \ 32 | file \ 33 | findutils \ 34 | gettext-dev \ 35 | git \ 36 | gnu-libiconv-dev \ 37 | libdvbcsa-dev \ 38 | libgcrypt-dev \ 39 | libhdhomerun-dev \ 40 | libtool \ 41 | libva-dev \ 42 | libvpx-dev \ 43 | libxml2-dev \ 44 | libxslt-dev \ 45 | linux-headers \ 46 | openssl-dev \ 47 | opus-dev \ 48 | patch \ 49 | pcre2-dev \ 50 | pkgconf \ 51 | pngquant \ 52 | python3 \ 53 | sdl2-dev \ 54 | uriparser-dev \ 55 | x264-dev \ 56 | x265-dev \ 57 | zlib-dev 58 | 59 | RUN \ 60 | echo "**** remove musl iconv.h and replace with gnu-iconv.h ****" && \ 61 | rm -rf /usr/include/iconv.h && \ 62 | cp /usr/include/gnu-libiconv/iconv.h /usr/include/iconv.h 63 | 64 | RUN \ 65 | echo "**** build libdvbcsa ****" && \ 66 | git clone https://github.com/glenvt18/libdvbcsa.git /tmp/libdvbcsa && \ 67 | cd /tmp/libdvbcsa && \ 68 | git apply /tmp/patches/libdvbcsa/libdvbcsa.patch && \ 69 | ./bootstrap && \ 70 | ./configure \ 71 | --prefix=/usr \ 72 | --sysconfdir=/etc \ 73 | --mandir=/usr/share/man \ 74 | --infodir=/usr/share/info \ 75 | --localstatedir=/var && \ 76 | make -j 2 && \ 77 | make check && \ 78 | make DESTDIR=/tmp/libdvbcsa-build install && \ 79 | echo "**** copy to /usr for tvheadend dependency ****" && \ 80 | cp -pr /tmp/libdvbcsa-build/usr/* /usr/ 81 | 82 | RUN \ 83 | echo "**** build tvheadend ****" && \ 84 | if [ -z ${TVHEADEND_COMMIT+x} ]; then \ 85 | TVHEADEND_COMMIT=$(curl -sX GET https://api.github.com/repos/tvheadend/tvheadend/commits/master \ 86 | | jq -r '. | .sha'); \ 87 | fi && \ 88 | mkdir -p \ 89 | /tmp/tvheadend && \ 90 | git clone https://github.com/tvheadend/tvheadend.git /tmp/tvheadend && \ 91 | cd /tmp/tvheadend && \ 92 | git checkout ${TVHEADEND_COMMIT} && \ 93 | echo "**** configure tvheadend ****" && \ 94 | ./configure \ 95 | `#Encoding` \ 96 | --disable-ffmpeg_static \ 97 | --disable-libfdkaac_static \ 98 | --disable-libtheora_static \ 99 | --disable-libopus_static \ 100 | --disable-libvorbis_static \ 101 | --disable-libvpx_static \ 102 | --disable-libx264_static \ 103 | --disable-libx265_static \ 104 | --disable-libfdkaac \ 105 | --enable-libopus \ 106 | --enable-libvorbis \ 107 | --enable-libvpx \ 108 | --enable-libx264 \ 109 | --enable-libx265 \ 110 | \ 111 | `#Options` \ 112 | --disable-avahi \ 113 | --disable-dbus_1 \ 114 | --disable-bintray_cache \ 115 | --disable-execinfo \ 116 | --disable-hdhomerun_static \ 117 | --enable-hdhomerun_client \ 118 | --enable-libav \ 119 | --enable-pngquant \ 120 | --enable-trace \ 121 | --enable-vaapi \ 122 | --infodir=/usr/share/info \ 123 | --localstatedir=/var \ 124 | --nowerror \ 125 | --mandir=/usr/share/man \ 126 | --prefix=/usr \ 127 | --python=python3 \ 128 | --sysconfdir=/config && \ 129 | echo "**** compile tvheadend ****" && \ 130 | make -j 2 && \ 131 | make DESTDIR=/tmp/tvheadend-build install 132 | 133 | RUN \ 134 | echo "**** compile argtable2 ****" && \ 135 | ARGTABLE_VER1="${ARGTABLE_VER//./-}" && \ 136 | mkdir -p \ 137 | /tmp/argtable && \ 138 | curl -s -o \ 139 | /tmp/argtable-src.tar.gz -L \ 140 | "https://sourceforge.net/projects/argtable/files/argtable/argtable-${ARGTABLE_VER}/argtable${ARGTABLE_VER1}.tar.gz" && \ 141 | tar xf \ 142 | /tmp/argtable-src.tar.gz -C \ 143 | /tmp/argtable --strip-components=1 && \ 144 | cp /tmp/patches/argtable/config.* /tmp/argtable && \ 145 | cd /tmp/argtable && \ 146 | CFLAGS="-include ctype.h -include string.h" ./configure \ 147 | --prefix=/usr && \ 148 | make -j 2 && \ 149 | make check && \ 150 | make DESTDIR=/tmp/argtable-build install && \ 151 | echo "**** copy to /usr for comskip dependency ****" && \ 152 | cp -pr /tmp/argtable-build/usr/* /usr/ 153 | 154 | RUN \ 155 | echo "***** compile comskip ****" && \ 156 | git clone https://github.com/erikkaashoek/Comskip /tmp/comskip && \ 157 | cd /tmp/comskip && \ 158 | ./autogen.sh && \ 159 | ./configure \ 160 | --bindir=/usr/bin \ 161 | --sysconfdir=/config/comskip && \ 162 | make -j 2 && \ 163 | make DESTDIR=/tmp/comskip-build install 164 | 165 | RUN \ 166 | echo "***** extract picons ****" && \ 167 | mkdir -p /picons && \ 168 | tar xf \ 169 | /picons.tar.bz2 -C \ 170 | /picons 171 | 172 | 173 | ############## runtime stage ############## 174 | FROM ghcr.io/linuxserver/baseimage-alpine:arm64v8-3.21 175 | 176 | # set version label 177 | ARG BUILD_DATE 178 | ARG VERSION 179 | LABEL build_version="version:- ${VERSION} Build-date:- ${BUILD_DATE}" 180 | LABEL maintainer="thealhu" 181 | 182 | # environment settings 183 | ENV HOME="/config" 184 | 185 | RUN \ 186 | echo "**** install runtime packages ****" && \ 187 | apk add --no-cache \ 188 | bsd-compat-headers \ 189 | ffmpeg \ 190 | ffmpeg4-libavcodec \ 191 | ffmpeg4-libavdevice \ 192 | ffmpeg4-libavfilter \ 193 | ffmpeg4-libavformat \ 194 | ffmpeg4-libavutil \ 195 | ffmpeg4-libpostproc \ 196 | ffmpeg4-libswresample \ 197 | ffmpeg4-libswscale \ 198 | gnu-libiconv \ 199 | libdvbcsa \ 200 | libhdhomerun-libs \ 201 | libva \ 202 | mesa-va-gallium \ 203 | libvpx \ 204 | libxml2 \ 205 | libxslt \ 206 | linux-headers \ 207 | opus \ 208 | pcre2 \ 209 | perl \ 210 | perl-datetime-format-strptime \ 211 | perl-json \ 212 | py3-requests \ 213 | python3 \ 214 | uriparser \ 215 | x264 \ 216 | x265 \ 217 | xmltv \ 218 | zlib && \ 219 | printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version 220 | 221 | # copy local files and buildstage artifacts 222 | COPY --from=buildstage /tmp/libdvbcsa-build/usr/ /usr/ 223 | COPY --from=buildstage /tmp/argtable-build/usr/ /usr/ 224 | COPY --from=buildstage /tmp/comskip-build/usr/ /usr/ 225 | COPY --from=buildstage /tmp/tvheadend-build/usr/ /usr/ 226 | COPY --from=buildstage /picons /picons 227 | COPY root/ / 228 | 229 | RUN rm -rf /usr/bin/tv_grab_file && wget https://raw.githubusercontent.com/b-jesch/tv_grab_file/master/tv_grab_file -O /usr/bin/tv_grab_file && chmod +x /usr/bin/tv_grab_file 230 | 231 | RUN rm -rf /etc/cont-init.d/10-adduser 232 | ADD 10-adduser /etc/cont-init.d/10-adduser 233 | RUN chmod +x /etc/cont-init.d/10-adduser 234 | 235 | ADD metric_heartbeat.sh /usr/bin/metric_heartbeat.sh 236 | RUN chmod +x /usr/bin/metric_heartbeat.sh 237 | 238 | # ports and volumes 239 | EXPOSE 9981 9982 240 | VOLUME /config 241 | -------------------------------------------------------------------------------- /x64/files/docker: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | ############## picons stage ############## 4 | # built by https://github.com/linuxserver/picons-builder 5 | FROM ghcr.io/linuxserver/picons-builder as piconsstage 6 | 7 | 8 | FROM ghcr.io/linuxserver/baseimage-alpine:3.21 as buildstage 9 | ############## build stage ############## 10 | 11 | # package versions 12 | ARG ARGTABLE_VER="2.13" 13 | 14 | # environment settings 15 | ARG TZ="Europe/Vienna" 16 | ARG TVHEADEND_COMMIT 17 | ENV HOME="/config" 18 | 19 | # copy patches and picons 20 | COPY patches/ /tmp/patches/ 21 | COPY --from=piconsstage /picons.tar.bz2 /picons.tar.bz2 22 | 23 | RUN \ 24 | echo "**** install build packages ****" && \ 25 | apk add --no-cache \ 26 | autoconf \ 27 | automake \ 28 | bsd-compat-headers \ 29 | build-base \ 30 | cmake \ 31 | ffmpeg4-dev \ 32 | file \ 33 | findutils \ 34 | gettext-dev \ 35 | git \ 36 | gnu-libiconv-dev \ 37 | libdvbcsa-dev \ 38 | libgcrypt-dev \ 39 | libhdhomerun-dev \ 40 | libtool \ 41 | libva-dev \ 42 | libvpx-dev \ 43 | libxml2-dev \ 44 | libxslt-dev \ 45 | linux-headers \ 46 | openssl-dev \ 47 | opus-dev \ 48 | patch \ 49 | pcre2-dev \ 50 | pkgconf \ 51 | pngquant \ 52 | python3 \ 53 | sdl2-dev \ 54 | uriparser-dev \ 55 | x264-dev \ 56 | x265-dev \ 57 | zlib-dev 58 | 59 | RUN \ 60 | echo "**** remove musl iconv.h and replace with gnu-iconv.h ****" && \ 61 | rm -rf /usr/include/iconv.h && \ 62 | cp /usr/include/gnu-libiconv/iconv.h /usr/include/iconv.h 63 | 64 | RUN \ 65 | echo "**** build libdvbcsa ****" && \ 66 | git clone https://github.com/glenvt18/libdvbcsa.git /tmp/libdvbcsa && \ 67 | cd /tmp/libdvbcsa && \ 68 | git apply /tmp/patches/libdvbcsa/libdvbcsa.patch && \ 69 | ./bootstrap && \ 70 | ./configure \ 71 | --prefix=/usr \ 72 | --sysconfdir=/etc \ 73 | --mandir=/usr/share/man \ 74 | --infodir=/usr/share/info \ 75 | --localstatedir=/var && \ 76 | make -j 2 && \ 77 | make check && \ 78 | make DESTDIR=/tmp/libdvbcsa-build install && \ 79 | echo "**** copy to /usr for tvheadend dependency ****" && \ 80 | cp -pr /tmp/libdvbcsa-build/usr/* /usr/ 81 | 82 | RUN \ 83 | echo "**** build tvheadend ****" && \ 84 | if [ -z ${TVHEADEND_COMMIT+x} ]; then \ 85 | TVHEADEND_COMMIT=$(curl -sX GET https://api.github.com/repos/tvheadend/tvheadend/commits/master \ 86 | | jq -r '. | .sha'); \ 87 | fi && \ 88 | mkdir -p \ 89 | /tmp/tvheadend && \ 90 | git clone https://github.com/tvheadend/tvheadend.git /tmp/tvheadend && \ 91 | cd /tmp/tvheadend && \ 92 | git checkout ${TVHEADEND_COMMIT} && \ 93 | echo "**** configure tvheadend ****" && \ 94 | ./configure \ 95 | `#Encoding` \ 96 | --disable-ffmpeg_static \ 97 | --disable-libfdkaac_static \ 98 | --disable-libtheora_static \ 99 | --disable-libopus_static \ 100 | --disable-libvorbis_static \ 101 | --disable-libvpx_static \ 102 | --disable-libx264_static \ 103 | --disable-libx265_static \ 104 | --disable-libfdkaac \ 105 | --enable-libopus \ 106 | --enable-libvorbis \ 107 | --enable-libvpx \ 108 | --enable-libx264 \ 109 | --enable-libx265 \ 110 | \ 111 | `#Options` \ 112 | --disable-avahi \ 113 | --disable-dbus_1 \ 114 | --disable-bintray_cache \ 115 | --disable-execinfo \ 116 | --disable-hdhomerun_static \ 117 | --enable-hdhomerun_client \ 118 | --enable-libav \ 119 | --enable-pngquant \ 120 | --enable-trace \ 121 | --enable-vaapi \ 122 | --infodir=/usr/share/info \ 123 | --localstatedir=/var \ 124 | --mandir=/usr/share/man \ 125 | --prefix=/usr \ 126 | --python=python3 \ 127 | --sysconfdir=/config && \ 128 | echo "**** compile tvheadend ****" && \ 129 | make -j 2 && \ 130 | make DESTDIR=/tmp/tvheadend-build install 131 | 132 | RUN \ 133 | echo "**** compile argtable2 ****" && \ 134 | ARGTABLE_VER1="${ARGTABLE_VER//./-}" && \ 135 | mkdir -p \ 136 | /tmp/argtable && \ 137 | curl -s -o \ 138 | /tmp/argtable-src.tar.gz -L \ 139 | "https://sourceforge.net/projects/argtable/files/argtable/argtable-${ARGTABLE_VER}/argtable${ARGTABLE_VER1}.tar.gz" && \ 140 | tar xf \ 141 | /tmp/argtable-src.tar.gz -C \ 142 | /tmp/argtable --strip-components=1 && \ 143 | cp /tmp/patches/argtable/config.* /tmp/argtable && \ 144 | cd /tmp/argtable && \ 145 | CFLAGS="-include ctype.h -include string.h" ./configure \ 146 | --prefix=/usr && \ 147 | make -j 2 && \ 148 | make check && \ 149 | make DESTDIR=/tmp/argtable-build install && \ 150 | echo "**** copy to /usr for comskip dependency ****" && \ 151 | cp -pr /tmp/argtable-build/usr/* /usr/ 152 | 153 | RUN \ 154 | echo "***** compile comskip ****" && \ 155 | git clone https://github.com/erikkaashoek/Comskip /tmp/comskip && \ 156 | cd /tmp/comskip && \ 157 | ./autogen.sh && \ 158 | ./configure \ 159 | --bindir=/usr/bin \ 160 | --sysconfdir=/config/comskip && \ 161 | make -j 2 && \ 162 | make DESTDIR=/tmp/comskip-build install 163 | 164 | RUN \ 165 | echo "***** extract picons ****" && \ 166 | mkdir -p /picons && \ 167 | tar xf \ 168 | /picons.tar.bz2 -C \ 169 | /picons 170 | 171 | 172 | ############## runtime stage ############## 173 | FROM ghcr.io/linuxserver/baseimage-alpine:3.21 174 | 175 | # set version label 176 | ARG BUILD_DATE 177 | ARG VERSION 178 | LABEL build_version="version:- ${VERSION} Build-date:- ${BUILD_DATE}" 179 | LABEL maintainer="thealhu" 180 | 181 | # environment settings 182 | ENV HOME="/config" 183 | 184 | RUN \ 185 | echo "**** install runtime packages ****" && \ 186 | apk add --no-cache \ 187 | bsd-compat-headers \ 188 | ffmpeg \ 189 | ffmpeg4-libavcodec \ 190 | ffmpeg4-libavdevice \ 191 | ffmpeg4-libavfilter \ 192 | ffmpeg4-libavformat \ 193 | ffmpeg4-libavutil \ 194 | ffmpeg4-libpostproc \ 195 | ffmpeg4-libswresample \ 196 | ffmpeg4-libswscale \ 197 | gnu-libiconv \ 198 | libdvbcsa \ 199 | libhdhomerun-libs \ 200 | libva \ 201 | libva-intel-driver \ 202 | intel-media-driver \ 203 | mesa-va-gallium \ 204 | libvpx \ 205 | libxml2 \ 206 | libxslt \ 207 | linux-headers \ 208 | opus \ 209 | pcre2 \ 210 | perl \ 211 | perl-datetime-format-strptime \ 212 | perl-json \ 213 | py3-requests \ 214 | python3 \ 215 | uriparser \ 216 | x264 \ 217 | x265 \ 218 | xmltv \ 219 | zlib && \ 220 | printf "Linuxserver.io version: ${VERSION}\nBuild-date: ${BUILD_DATE}" > /build_version 221 | 222 | # copy local files and buildstage artifacts 223 | COPY --from=buildstage /tmp/libdvbcsa-build/usr/ /usr/ 224 | COPY --from=buildstage /tmp/argtable-build/usr/ /usr/ 225 | COPY --from=buildstage /tmp/comskip-build/usr/ /usr/ 226 | COPY --from=buildstage /tmp/tvheadend-build/usr/ /usr/ 227 | COPY --from=buildstage /picons /picons 228 | COPY root/ / 229 | 230 | RUN rm -rf /usr/bin/tv_grab_file && wget https://raw.githubusercontent.com/b-jesch/tv_grab_file/master/tv_grab_file -O /usr/bin/tv_grab_file && chmod +x /usr/bin/tv_grab_file 231 | 232 | RUN rm -rf /etc/cont-init.d/10-adduser 233 | ADD 10-adduser /etc/cont-init.d/10-adduser 234 | RUN chmod +x /etc/cont-init.d/10-adduser 235 | 236 | ADD metric_heartbeat.sh /usr/bin/metric_heartbeat.sh 237 | RUN chmod +x /usr/bin/metric_heartbeat.sh 238 | 239 | # ports and volumes 240 | EXPOSE 9981 9982 241 | VOLUME /config 242 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ## **thealhu´s flavor of TVHeadend** 5 | ![](https://i.ibb.co/b20nP39/TVHeadend-Docker-Image-new.png) 6 | 7 | - **ICAM support** 8 | > In these TVHeadend docker images, icam support is built-in. 9 | 10 | **The architectures supported by this image are:** 11 | | Architectures | Status | Tag |Additional information | 12 | |--|--|--|--| 13 | | amd64 | ✅ | thealhu/tvheadend:latest | | 14 | | aarch64 | ✅ | thealhu/tvheadend:aarch64-latest | `for raspberry pi & other single board computers on aarch64` for example: PI 3 & PI 4 with 64 bit OS| 15 | | armv7 | ❌ | thealhu/tvheadend:armv7-latest | **Deprecated! - [linuxserver alpine linux no longer offers support for armv7](https://github.com/linuxserver/docker-tvheadend/commit/79481854219e79fc5770799797b3b426bb5c4a98)**| 16 | 17 | *This image was built on the basis of [linuxserver/docker-tvheadend](https://github.com/linuxserver/docker-tvheadend) and is always kept and updated to the same version.* 18 | 19 | **The container images are automatically built through a Jenkins pipeline as soon as a commit is checked into the [TVHeadend git repository](https://github.com/tvheadend/tvheadend) or [Linuxserver docker-TVHeadend git repository](https://github.com/linuxserver/docker-tvheadend)** 20 | 21 | If you want to build the image yourself, everything you need can be found [here](https://github.com/upchui/tvheadend-docker-icam). 22 | 23 | ## ICAM 24 | ### What is ICAM? 25 | 26 | ICAM stands for "Integrated Conditional Access Module". It is a security module that can be built into some digital satellite receivers or set-top boxes. It is used to access encrypted channels that require separate activation. The ICAM is used to perform the decryption of the encrypted signals being broadcast by the satellite. It contains a security chip that enables authentication and access to the encrypted channels. The receiver must be equipped with a valid smart card or other security module in order to access the encrypted channels. 27 | 28 | **In these TVHeadend docker images, icam support is built-in.** 29 | 30 | ## Usage 31 | ### docker-compose (recommended) 32 | 33 | ```yaml 34 | --- 35 | version: "2.1" 36 | services: 37 | tvheadend: 38 | image: thealhu/tvheadend:latest #or thealhu/tvheadend:aarch64-latest depending on the architecture of your CPU 39 | container_name: tvheadend 40 | environment: 41 | - PUID=1000 42 | - PGID=1000 43 | - TZ=Europe/Vienna 44 | - RUN_OPTS= #optional 45 | volumes: 46 | - /path/to/data:/config 47 | - /path/to/recordings:/recordings 48 | ports: 49 | - 9981:9981 50 | - 9982:9982 51 | devices: 52 | - /dev/dri:/dev/dri #optional 53 | - /dev/dvb:/dev/dvb #optional 54 | restart: unless-stopped 55 | 56 | ``` 57 | ### docker cli 58 | 59 | ```bash 60 | docker run -d \ 61 | --name=tvheadend \ 62 | -e PUID=1000 \ 63 | -e PGID=1000 \ 64 | -e TZ=Europe/Vienna \ 65 | -e RUN_OPTS= `#optional` \ 66 | -p 9981:9981 \ 67 | -p 9982:9982 \ 68 | -v /path/to/data:/config \ 69 | -v /path/to/recordings:/recordings \ 70 | --device /dev/dri:/dev/dri `#optional` \ 71 | --device /dev/dvb:/dev/dvb `#optional` \ 72 | --restart unless-stopped \ 73 | thealhu/tvheadend:latest #or thealhu/tvheadend:aarch64-latest depending on the architecture of your CPU 74 | 75 | ``` 76 | #### Host vs. Bridge 77 | 78 | If you use IPTV, SAT>IP or HDHomeRun, you need to create the container with --net=host and remove the -p flags. This is because to work with these services Tvheadend requires a multicast address of `239.255.255.250` and a UDP port of `1900` which at this time is not possible with docker bridge mode. If you have other host services which also use multicast such as SSDP/DLNA/Emby you may experience stabilty problems. These can be solved by giving tvheadend its own IP using macvlan. 79 | 80 | ## Parameters 81 | 82 | Container images are configured using parameters passed at runtime (such as those above). These parameters are separated by a colon and indicate `:` respectively. For example, `-p 8080:80` would expose port `80` from inside the container to be accessible from the host's IP on port `8080` outside the container. 83 | 84 | Parameter 85 | 86 | Function 87 | 88 | `-p 9981` 89 | 90 | WebUI 91 | 92 | `-p 9982` 93 | 94 | HTSP server port. 95 | 96 | `-e PUID=1000` 97 | 98 | for UserID - see below for explanation 99 | 100 | `-e PGID=1000` 101 | 102 | for GroupID - see below for explanation 103 | 104 | `-e TZ=Europe/London` 105 | 106 | Specify a timezone to use EG Europe/London. 107 | 108 | `-e RUN_OPTS=` 109 | 110 | Optionally specify additional arguments to be passed. See Additional runtime parameters. 111 | 112 | `-v /config` 113 | 114 | Where TVHeadend show store it's config files. 115 | 116 | `-v /recordings` 117 | 118 | Where you want the PVR to store recordings. 119 | 120 | `--device /dev/dri` 121 | 122 | Only needed if you want to use your AMD/Intel GPU for hardware accelerated video encoding (vaapi). 123 | 124 | `--device /dev/dvb` 125 | 126 | Only needed if you want to pass through a DVB card to the container. If you use IPTV or HDHomeRun you can leave it out. 127 | 128 | `-e heartbeat_alive=false` 129 | 130 | Do not send heartbeat packets to amplitude.com, this is used to determine how many are using this docker image 131 | 132 | ## Environment variables from files (Docker secrets) 133 | 134 | You can set any environment variable from a file by using a special prepend `FILE__`. 135 | 136 | As an example: 137 | 138 | ```bash 139 | -e FILE__PASSWORD=/run/secrets/mysecretpassword 140 | 141 | ``` 142 | 143 | Will set the environment variable `PASSWORD` based on the contents of the `/run/secrets/mysecretpassword` file. 144 | 145 | ## Umask for running applications 146 | 147 | For all of our images we provide the ability to override the default umask settings for services started within the containers using the optional `-e UMASK=022` setting. Keep in mind umask is not chmod it subtracts from permissions based on it's value it does not add. Please read up [here](https://en.wikipedia.org/wiki/Umask) 148 | 149 | ## User / Group Identifiers 150 | 151 | When using volumes (`-v` flags) permissions issues can arise between the host OS and the container, we avoid this issue by allowing you to specify the user `PUID` and group `PGID`. 152 | 153 | Ensure any volume directories on the host are owned by the same user you specify and any permissions issues will vanish like magic. 154 | 155 | In this instance `PUID=1000` and `PGID=1000`, to find yours use `id user` as below: 156 | 157 | ```bash 158 | $ id username 159 | uid=1000(dockeruser) gid=1000(dockergroup) groups=1000(dockergroup) 160 | 161 | ``` 162 | 163 | ## Updating Info 164 | 165 | ### Via Docker Compose 166 | 167 | - Update all images: `docker-compose pull` 168 | - or update a single image: `docker-compose pull tvheadend` 169 | - Let compose update all containers as necessary: `docker-compose up -d` 170 | - or update a single container: `docker-compose up -d tvheadend` 171 | - You can also remove the old dangling images: `docker image prune` 172 | 173 | ### Via Docker Run 174 | 175 | - Update the image: `docker pull thealhu/tvheadend:latest` 176 | - Stop the running container: `docker stop tvheadend` 177 | - Delete the container: `docker rm tvheadend` 178 | - Recreate a new container with the same docker run parameters as instructed above (if mapped correctly to a host folder, your `/config` folder and settings will be preserved) 179 | - You can also remove the old dangling images: `docker image prune` 180 | 181 | ### Via Watchtower auto-updater (only use if you don't remember the original parameters) 182 | 183 | - Pull the latest image at its tag and replace it with the same env variables in one run: 184 | 185 | ```bash 186 | docker run --rm \ 187 | -v /var/run/docker.sock:/var/run/docker.sock \ 188 | containrrr/watchtower \ 189 | --run-once tvheadend 190 | 191 | ``` 192 | 193 | - You can also remove the old dangling images: `docker image prune` 194 | 195 | 196 | **Note:** We do not endorse the use of Watchtower as a solution to automated updates of existing Docker containers. In fact we generally discourage automated updates. However, this is a useful tool for one-time manual updates of containers where you have forgotten the original parameters. In the long term, we highly recommend using [Docker Compose](https://docs.linuxserver.io/general/docker-compose). 197 | 198 | ## Thanks for support to 199 | | Contributor | | 200 | |--|--| 201 | | [Serbus](https://www.kodinerds.net/index.php/User/23768-Serbus/) | for the help in fixing the [simple EPG file grabber](https://github.com/b-jesch/tv_grab_file) | 202 | | [PvD](https://www.kodinerds.net/index.php/User/20365-PvD/) | for the providing and developing of the [simple EPG file grabber](https://github.com/b-jesch/tv_grab_file) | 203 | 204 | 205 | 206 | ## AUTOMATICALLY NEW IMAGES 207 | 208 | **Container images will now be automatically built through Jenkins pipeline as soon as a commit is checked in on the [TVHeadend git repository](https://github.com/tvheadend/tvheadend) or [Linuxserver docker-TVHeadend git repository](https://github.com/linuxserver/docker-tvheadend).** 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /armv7/files/docker: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/linuxserver/baseimage-alpine:3.15 as buildstage 2 | ############## build stage ############## 3 | 4 | # package versions 5 | ARG ARGTABLE_VER="2.13" 6 | ARG XMLTV_VER="v1.0.0" 7 | 8 | # environment settings 9 | ARG TZ="Europe/Vienna" 10 | ARG TVHEADEND_COMMIT 11 | ENV HOME="/config" 12 | 13 | # copy patches 14 | COPY patches/ /tmp/patches/ 15 | 16 | RUN \ 17 | echo "**** install build packages ****" && \ 18 | apk add --no-cache \ 19 | autoconf \ 20 | automake \ 21 | bsd-compat-headers \ 22 | bzip2 \ 23 | cmake \ 24 | curl \ 25 | ffmpeg-dev \ 26 | file \ 27 | findutils \ 28 | g++ \ 29 | gcc \ 30 | gettext-dev \ 31 | git \ 32 | gnu-libiconv-dev \ 33 | gzip \ 34 | jq \ 35 | libcurl \ 36 | libgcrypt-dev \ 37 | libhdhomerun-dev \ 38 | libtool \ 39 | libva-dev \ 40 | libvpx-dev \ 41 | libxml2-dev \ 42 | libxslt-dev \ 43 | linux-headers \ 44 | make \ 45 | openssl-dev \ 46 | opus-dev \ 47 | patch \ 48 | pcre2-dev \ 49 | perl-archive-zip \ 50 | perl-boolean \ 51 | perl-capture-tiny \ 52 | perl-cgi \ 53 | perl-compress-raw-zlib \ 54 | perl-date-manip \ 55 | perl-datetime \ 56 | perl-datetime-format-strptime \ 57 | perl-datetime-timezone \ 58 | perl-dbd-sqlite \ 59 | perl-dbi \ 60 | perl-dev \ 61 | perl-digest-sha1 \ 62 | perl-doc \ 63 | perl-file-slurp \ 64 | perl-file-temp \ 65 | perl-file-which \ 66 | perl-getopt-long \ 67 | perl-html-parser \ 68 | perl-html-tree \ 69 | perl-http-cookies \ 70 | perl-io \ 71 | perl-io-html \ 72 | perl-io-socket-ssl \ 73 | perl-io-stringy \ 74 | perl-json \ 75 | perl-json-xs \ 76 | perl-libwww \ 77 | perl-lingua-en-numbers-ordinate \ 78 | perl-lingua-preferred \ 79 | perl-list-moreutils \ 80 | perl-lwp-useragent-determined \ 81 | perl-module-build \ 82 | perl-module-pluggable \ 83 | perl-net-ssleay \ 84 | perl-parse-recdescent \ 85 | perl-path-class \ 86 | perl-scalar-list-utils \ 87 | perl-term-progressbar \ 88 | perl-term-readkey \ 89 | perl-test-exception \ 90 | perl-test-requires \ 91 | perl-timedate \ 92 | perl-try-tiny \ 93 | perl-unicode-string \ 94 | perl-xml-libxml \ 95 | perl-xml-libxslt \ 96 | perl-xml-parser \ 97 | perl-xml-sax \ 98 | perl-xml-treepp \ 99 | perl-xml-twig \ 100 | perl-xml-writer \ 101 | pkgconf \ 102 | pngquant \ 103 | python3 \ 104 | sdl-dev \ 105 | tar \ 106 | uriparser-dev \ 107 | wget \ 108 | x264-dev \ 109 | x265-dev \ 110 | zlib-dev 111 | 112 | RUN \ 113 | echo "**** remove musl iconv.h and replace with gnu-iconv.h ****" && \ 114 | rm -rf /usr/include/iconv.h && \ 115 | cp /usr/include/gnu-libiconv/iconv.h /usr/include/iconv.h 116 | 117 | ADD cpanm /usr/local/bin/cpanm 118 | RUN chmod +x /usr/local/bin/cpanm 119 | 120 | RUN \ 121 | echo "**** install perl modules for xmltv ****" && \ 122 | curl -s -L https://cpanmin.us | perl - App::cpanminus && \ 123 | /usr/local/bin/cpanm --installdeps /tmp/patches/cpan 124 | 125 | RUN \ 126 | echo "**** compile XMLTV ****" && \ 127 | git clone https://github.com/XMLTV/xmltv.git /tmp/xmltv && \ 128 | cd /tmp/xmltv && \ 129 | git checkout ${XMLTV_VER} && \ 130 | echo "**** Perl 5.26 fixes for XMTLV ****" && \ 131 | sed "s/use POSIX 'tmpnam';//" -i filter/tv_to_latex && \ 132 | sed "s/use POSIX 'tmpnam';//" -i filter/tv_to_text && \ 133 | sed "s/\(lib\/set_share_dir.pl';\)/.\/\1/" -i grab/it/tv_grab_it.PL && \ 134 | sed "s/\(filter\/Grep.pm';\)/.\/\1/" -i filter/tv_grep.PL && \ 135 | sed "s/\(lib\/XMLTV.pm.in';\)/.\/\1/" -i lib/XMLTV.pm.PL && \ 136 | sed "s/\(lib\/Ask\/Term.pm';\)/.\/\1/" -i Makefile.PL && \ 137 | PERL5LIB=`pwd` && \ 138 | echo -e "yes" | perl Makefile.PL PREFIX=/usr/ INSTALLDIRS=vendor && \ 139 | make -j 2 && \ 140 | make test && \ 141 | make DESTDIR=/tmp/xmltv-build install 142 | 143 | RUN \ 144 | echo "**** build libdvbcsa ****" && \ 145 | git clone https://github.com/glenvt18/libdvbcsa.git /tmp/libdvbcsa && \ 146 | cd /tmp/libdvbcsa && \ 147 | git apply /tmp/patches/libdvbcsa/libdvbcsa.patch && \ 148 | ./bootstrap && \ 149 | ./configure \ 150 | --prefix=/usr \ 151 | --sysconfdir=/etc \ 152 | --mandir=/usr/share/man \ 153 | --infodir=/usr/share/info \ 154 | --localstatedir=/var && \ 155 | make -j 2 && \ 156 | make check && \ 157 | make DESTDIR=/tmp/libdvbcsa-build install && \ 158 | echo "**** copy to /usr for tvheadend dependency ****" && \ 159 | cp -pr /tmp/libdvbcsa-build/usr/* /usr/ 160 | 161 | RUN \ 162 | echo "**** build tvheadend ****" && \ 163 | if [ -z ${TVHEADEND_COMMIT+x} ]; then \ 164 | TVHEADEND_COMMIT=$(curl -sX GET https://api.github.com/repos/tvheadend/tvheadend/commits/master \ 165 | | jq -r '. | .sha'); \ 166 | fi && \ 167 | mkdir -p \ 168 | /tmp/tvheadend && \ 169 | git clone https://github.com/tvheadend/tvheadend.git /tmp/tvheadend && \ 170 | cd /tmp/tvheadend && \ 171 | git checkout ${TVHEADEND_COMMIT} && \ 172 | echo "**** patch tvheadend ****" && \ 173 | git apply /tmp/patches/tvheadend/tvheadend43.patch && \ 174 | echo "**** configure tvheadend ****" && \ 175 | ./configure \ 176 | `#Encoding` \ 177 | --disable-ffmpeg_static \ 178 | --disable-libfdkaac_static \ 179 | --disable-libtheora_static \ 180 | --disable-libopus_static \ 181 | --disable-libvorbis_static \ 182 | --disable-libvpx_static \ 183 | --disable-libx264_static \ 184 | --disable-libx265_static \ 185 | --disable-libfdkaac \ 186 | --enable-libopus \ 187 | --enable-libvorbis \ 188 | --enable-libvpx \ 189 | --enable-libx264 \ 190 | --enable-libx265 \ 191 | \ 192 | `#Options` \ 193 | --disable-avahi \ 194 | --disable-dbus_1 \ 195 | --disable-bintray_cache \ 196 | --disable-execinfo \ 197 | --disable-hdhomerun_static \ 198 | --enable-hdhomerun_client \ 199 | --enable-libav \ 200 | --enable-pngquant \ 201 | --enable-trace \ 202 | --enable-vaapi \ 203 | --infodir=/usr/share/info \ 204 | --localstatedir=/var \ 205 | --nowerror \ 206 | --mandir=/usr/share/man \ 207 | --prefix=/usr \ 208 | --python=python3 \ 209 | --sysconfdir=/config && \ 210 | echo "**** compile tvheadend ****" && \ 211 | make -j 2 && \ 212 | make DESTDIR=/tmp/tvheadend-build install 213 | 214 | RUN \ 215 | echo "**** compile argtable2 ****" && \ 216 | ARGTABLE_VER1="${ARGTABLE_VER//./-}" && \ 217 | mkdir -p \ 218 | /tmp/argtable && \ 219 | curl -s -o \ 220 | /tmp/argtable-src.tar.gz -L \ 221 | "https://sourceforge.net/projects/argtable/files/argtable/argtable-${ARGTABLE_VER}/argtable${ARGTABLE_VER1}.tar.gz" && \ 222 | tar xf \ 223 | /tmp/argtable-src.tar.gz -C \ 224 | /tmp/argtable --strip-components=1 && \ 225 | cp /tmp/patches/argtable/config.* /tmp/argtable && \ 226 | cd /tmp/argtable && \ 227 | ./configure \ 228 | --prefix=/usr && \ 229 | make -j 2 && \ 230 | make check && \ 231 | make DESTDIR=/tmp/argtable-build install && \ 232 | echo "**** copy to /usr for comskip dependency ****" && \ 233 | cp -pr /tmp/argtable-build/usr/* /usr/ 234 | 235 | RUN \ 236 | echo "***** compile comskip ****" && \ 237 | git clone https://github.com/erikkaashoek/Comskip /tmp/comskip && \ 238 | cd /tmp/comskip && \ 239 | ./autogen.sh && \ 240 | ./configure \ 241 | --bindir=/usr/bin \ 242 | --sysconfdir=/config/comskip && \ 243 | make -j 2 && \ 244 | make DESTDIR=/tmp/comskip-build install 245 | 246 | ############## picons stage ############## 247 | # built by https://github.com/linuxserver/picons-builder 248 | FROM ghcr.io/linuxserver/picons-builder as piconsstage 249 | 250 | 251 | ############## runtime stage ############## 252 | FROM ghcr.io/linuxserver/baseimage-alpine:3.15 253 | 254 | # set version label 255 | ARG BUILD_DATE 256 | ARG VERSION 257 | LABEL build_version="version:- ${VERSION} Build-date:- ${BUILD_DATE}" 258 | LABEL maintainer="thealhu" 259 | 260 | # environment settings 261 | ENV HOME="/config" 262 | 263 | RUN \ 264 | echo "**** install runtime packages ****" && \ 265 | apk add --no-cache \ 266 | bsd-compat-headers \ 267 | bzip2 \ 268 | curl \ 269 | ffmpeg \ 270 | ffmpeg-libs \ 271 | gnu-libiconv \ 272 | gzip \ 273 | libcrypto1.1 \ 274 | libcurl \ 275 | libdvbcsa \ 276 | libhdhomerun-libs \ 277 | libssl1.1 \ 278 | libvpx \ 279 | libxml2 \ 280 | libxslt \ 281 | linux-headers \ 282 | openssl \ 283 | opus \ 284 | pcre2 \ 285 | perl \ 286 | perl-archive-zip \ 287 | perl-boolean \ 288 | perl-capture-tiny \ 289 | perl-cgi \ 290 | perl-compress-raw-zlib \ 291 | perl-date-manip \ 292 | perl-datetime \ 293 | perl-datetime-format-strptime \ 294 | perl-datetime-timezone \ 295 | perl-dbd-sqlite \ 296 | perl-dbi \ 297 | perl-digest-sha1 \ 298 | perl-doc \ 299 | perl-file-slurp \ 300 | perl-file-temp \ 301 | perl-file-which \ 302 | perl-getopt-long \ 303 | perl-html-parser \ 304 | perl-html-tree \ 305 | perl-http-cookies \ 306 | perl-io \ 307 | perl-io-html \ 308 | perl-io-socket-ssl \ 309 | perl-io-stringy \ 310 | perl-json \ 311 | perl-json-xs \ 312 | perl-libwww \ 313 | perl-lingua-en-numbers-ordinate \ 314 | perl-lingua-preferred \ 315 | perl-list-moreutils \ 316 | perl-lwp-useragent-determined \ 317 | perl-module-build \ 318 | perl-module-pluggable \ 319 | perl-net-ssleay \ 320 | perl-parse-recdescent \ 321 | perl-path-class \ 322 | perl-scalar-list-utils \ 323 | perl-term-progressbar \ 324 | perl-term-readkey \ 325 | perl-test-exception \ 326 | perl-test-requires \ 327 | perl-timedate \ 328 | perl-try-tiny \ 329 | perl-unicode-string \ 330 | perl-xml-libxml \ 331 | perl-xml-libxslt \ 332 | perl-xml-parser \ 333 | perl-xml-sax \ 334 | perl-xml-treepp \ 335 | perl-xml-twig \ 336 | perl-xml-writer \ 337 | py3-requests \ 338 | python3 \ 339 | tar \ 340 | uriparser \ 341 | wget \ 342 | x264 \ 343 | x265 \ 344 | zlib 345 | 346 | # copy local files and buildstage artifacts 347 | COPY --from=buildstage /tmp/libdvbcsa-build/usr/ /usr/ 348 | COPY --from=buildstage /tmp/argtable-build/usr/ /usr/ 349 | COPY --from=buildstage /tmp/comskip-build/usr/ /usr/ 350 | COPY --from=buildstage /tmp/tvheadend-build/usr/ /usr/ 351 | COPY --from=buildstage /tmp/xmltv-build/usr/ /usr/ 352 | COPY --from=buildstage /usr/local/share/man/ /usr/local/share/man/ 353 | COPY --from=buildstage /usr/local/share/perl5/ /usr/local/share/perl5/ 354 | COPY --from=piconsstage /picons.tar.bz2 /picons.tar.bz2 355 | COPY root/ / 356 | 357 | RUN rm -rf /usr/bin/tv_grab_file && wget https://raw.githubusercontent.com/b-jesch/tv_grab_file/master/tv_grab_file -O /usr/bin/tv_grab_file && chmod +x /usr/bin/tv_grab_file 358 | 359 | RUN rm -rf /etc/cont-init.d/10-adduser 360 | ADD 10-adduser /etc/cont-init.d/10-adduser 361 | RUN chmod +x /etc/cont-init.d/10-adduser 362 | 363 | # ports and volumes 364 | EXPOSE 9981 9982 365 | VOLUME /config 366 | --------------------------------------------------------------------------------