Плееры EIT ts-файлов для EPG

kiss_200kb.1510924712Как известно, Astra не умеет воспроизводить TS-файлы EIT, т.к. в них отсутствуют временные метки.

Первый вариант на Perl — ничего нового нет — это упрощённый ringelspiel.pl как у CherryEPG.

#!/usr/bin/perl

use Socket;
use Time::HiRes qw(usleep);
use POSIX qw(ceil);

my $hash = "e50d0fXXX913c12"; # hash in the epg.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);

system( "wget https://epg.by/$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 2018 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 EPG.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://epg.by/"), 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.
EPG streaming.exeСкачать это изделие можно тут epgstreaming.

Запись опубликована в рубрике Программирование, Телевидение с метками , . Добавьте в закладки постоянную ссылку.

Добавить комментарий