Как известно, Astra не умеет воспроизводить TS-файлы EIT, т.к. в них отсутствуют временные метки. Получить же такие eit.ts можно на сайте DVB.BY после регистрации. Пример как сделать EPG у себя в сети.
Первый вариант на Perl — ничего нового нет — это упрощённый ringelspiel.pl как у CherryEPG.
#!/usr/bin/perl use Socket; use Time::HiRes qw(usleep); use POSIX qw(ceil); my $hash = "e50d0fXXX913c12"; # hash in the dvb.by acc. my $host = "239.1.1.50"; # route add -host 239.1.1.50 gw 192.168.1.20 my $port = 5500; my $filename = "eit.ts"; socket( my $target, PF_INET, SOCK_DGRAM, getprotobyname('udp')) or die( "Error opening udp socket: $!"); my $ipaddr = inet_aton( $host); my $portaddr = sockaddr_in( $port, $ipaddr); # ссылка показана как пример # с недавнего времени dvb.by стал передавать ts в GZIP # т.е. после скачки надо его распаковать gunzip-ом system( "wget https://dvb.by/epg/my/$hash.ts -O $filename"); my $size = -s "$filename"; my $mtsCount = $size / 188; my $gap = ceil( 4170 / $mtsCount * 7000); while( 1){ my $buffer; open my $file, '<', $filename or die "Cannot open file $!\n"; while(read $file, $buffer, 188) { send( $target, $buffer, 0, $portaddr); usleep( $gap); } close $file; }
Второй вариант для гиков на Си… Заметка скорее для себя, как работать с сокетами…
#define MULTICAST #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <sys/time.h> #include <arpa/inet.h> #include <unistd.h> #include <time.h> #define TS_PACKET_SIZE 188 long long int usecDiff(struct timespec* time_stop, struct timespec* time_start) { long long int temp = 0; long long int utemp = 0; if (time_stop && time_start) { if (time_stop->tv_nsec >= time_start->tv_nsec) { utemp = time_stop->tv_nsec - time_start->tv_nsec; temp = time_stop->tv_sec - time_start->tv_sec; } else { utemp = time_stop->tv_nsec + 1000000000 - time_start->tv_nsec; temp = time_stop->tv_sec - 1 - time_start->tv_sec; } if (temp >= 0 && utemp >= 0) { temp = (temp * 1000000000) + utemp; } else { fprintf(stderr, "start time %ld.%ld is after stop time %ld.%ld\n", time_start->tv_sec, time_start->tv_nsec, time_stop->tv_sec, time_stop->tv_nsec); temp = -1; } } else { fprintf(stderr, "memory is garbaged?\n"); temp = -1; } return temp / 1000; } int main (int argc, char *argv[]) { int sockfd; int len; int sent; int ret; int is_multicast; int transport_fd; unsigned char option_ttl; char start_addr[4]; struct sockaddr_in addr; struct ip_mreq mreq; unsigned long int packet_size; char tsfile[20]; unsigned char* send_buf; unsigned int bitrate; unsigned long long int packet_time; unsigned long long int real_time; struct timespec time_start; struct timespec time_stop; struct timespec nano_sleep_packet; char wget[100]; memset(&addr, 0, sizeof(addr)); memset(&time_start, 0, sizeof(time_start)); memset(&time_stop, 0, sizeof(time_stop)); memset(&nano_sleep_packet, 0, sizeof(nano_sleep_packet)); fprintf(stderr, "\033[1m ************************************************************\n"); fprintf(stderr, "\033[1m * This program is designed for use with the service EPG.BY *\n"); fprintf(stderr, "\033[1m * Copyright 2017 Vitaly Tumashevsky *\n"); fprintf(stderr, "\033[1m * Email: unidiag@tut.by *\n"); fprintf(stderr, "\033[1m ************************************************************\033[0m\n\n"); if(argc < 4 ) { fprintf(stderr, " Usage: \033[1m%s hash ifaddr ipaddr\033[0m [port] [bitrate] [ttl]\n\n", argv[0]); fprintf(stderr, " \033[32mhash\033[0m - code stream on service DVB.BY (ex. \033[0;36m129c688adf47f2c0\033[0m)\n"); fprintf(stderr, " \033[32mifaddr\033[0m - network interface (ex. \033[0;36m127.0.0.1\033[0m)\n"); fprintf(stderr, " \033[32mipaddr\033[0m - address multicast group (ex. \033[0;36m239.0.100.1\033[0m)\n"); fprintf(stderr, " \033[32mport\033[0m - port multicast group (default \033[0;36m1234\033[0m)\n"); fprintf(stderr, " \033[32mbitrate\033[0m - bitrate stream (default \033[0;36m250000\033[0m bps)\n"); fprintf(stderr, " \033[32mttl\033[0m - time to live packets (default \033[0;36m3\033[0m)\n\n"); return 0; } else { strcat(strcat(strcat(strcat(strcpy(wget, "wget https://dvb.by/epg/my/"), argv[1]), ".ts -b -o /dev/null -O "), argv[1]), ".ts"); system(wget); strcat(strcpy(tsfile, argv[1]), ".ts"); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(argv[3]); // 239.0.100.1 addr.sin_port = htons(atoi(argv[4])); // 1234 ------------ bitrate = atoi(argv[5]); // 250000 bps ---------- if (bitrate <= 0) { bitrate = 100000000; // 100 Mbps } } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd < 0) { perror("\033[0;31msocket(): error\033[0m "); return 0; } if (argc >= 7){ option_ttl = atoi(argv[6]); is_multicast = 0; memcpy(start_addr, argv[3], 3); start_addr[3] = 0; is_multicast = atoi(start_addr); is_multicast = (is_multicast >= 224) || (is_multicast <= 239); if (is_multicast) { ret = setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &option_ttl, sizeof(option_ttl)); } else { ret = setsockopt(sockfd, IPPROTO_IP, IP_TTL, &option_ttl, sizeof(option_ttl)); } if(ret < 0) { perror("\033[0;31mttl configuration fail\033[0m"); } } // выберем необходимый интерфейс mreq.imr_interface.s_addr = inet_addr(argv[2]); if(setsockopt( sockfd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)) < 0){ perror("\033[0;31mIfaddr not found\033[0m"); } start: packet_size = 7 * TS_PACKET_SIZE; transport_fd = open(tsfile, O_RDONLY); if(transport_fd < 0) { fprintf(stderr, "\033[0;31mcan't open file %s\033[0m\n", tsfile); close(sockfd); return 0; } int completed = 0; send_buf = malloc(packet_size); packet_time = 0; real_time = 0; nano_sleep_packet.tv_nsec = 665778; /* 1 packet at 100mbps*/ clock_gettime(CLOCK_MONOTONIC, &time_start); while (!completed) { clock_gettime(CLOCK_MONOTONIC, &time_stop); real_time = usecDiff(&time_stop, &time_start); while (real_time * bitrate > packet_time * 1000000 && !completed) { /* theorical bits against sent bits */ len = read(transport_fd, send_buf, packet_size); if(len < 0) { fprintf(stderr, "\033[0;31mts file read error\033[0m \n"); completed = 1; } else if (len == 0) { //fprintf(stderr, "."); //completed = 1; close(transport_fd); goto start; } else { sent = sendto(sockfd, send_buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if(sent <= 0) { perror("\033[0;31msend(): error\033[0m "); completed = 1; } else { packet_time += packet_size * 8; } } } nanosleep(&nano_sleep_packet, 0); } close(transport_fd); close(sockfd); free(send_buf); return 0; }
—-
Третий вариант для виндовских нубов. В разных источниках прога называется по-разному (автор в хелпе не указан). Это TSstreaming.exe и EPGstreaming.exe.
Скачать это изделие можно тут epgstreaming.