recpt1のオプションで --http と言うモノを見つけたので取り込んだ.
recpt1がそのままHTTP接続を受け付ける.
VLCからHTTPでアクセスするだけ。
VLCからチャンネル指定できる.
Bon_DriverのHTTPとも組み合わせられる.
httpつけると
VLCなどでHTTPのアドレス+ファイル名(チャンネル)を指定すれば、PT2から直接ストリームが降ってきて便利。
コードとか
>:新参者 :2010/04/29(木) 01:05:03 ID:3hyiY+PL
> とりあえずhttpサーバー版の暫定版をアップしてみました。
> makeの方法は最近のrecpt1と同じでいけると思います。
>
> (driveとarib25をインストールした後)
> --
> ./autogen.sh
> ./configure --enable-b25
> ./make
> --
>
> recpt1 --b25 --strip --http 8888
>
> みたいにすると8888番ポートでデーモン起動し、
> VLCなどで
>http://hostname:8888/25
>
> などするとUHF25チャンネルが視聴できるはずです。
>
>http://2sen.dip.jp/cgi-bin/pt1up/source/up0280.gz
>
> ログをちゃんと吐かないとか、家にBSアンテナがないので試していないとか
> 色々問題がありますが・・
>
> 動作報告等ありましたら嬉しいです。
> (サポートできるかどうかは不明ですが・・)
>
> (当方は32bit ubuntu 8.10でテストしました)
使い方
ちょっと古いのでパッチを作って置いた
あがってるrecpt1のベースのコードがちょっと古いので最新版の差分パッチをあてて差分作っておいた.
差分はこれ
diff -urN .//diff.txt /home/takuya/PT1.http/pt1-http-rc1/recpt1//diff.txt --- .//diff.txt 2011-05-13 22:18:13.800738559 +0900 +++ /home/takuya/PT1.http/pt1-http-rc1/recpt1//diff.txt 1970-01-01 09:00:00.000000000 +0900 @@ -1,12 +0,0 @@ -diff -urN .//config.status /home/takuya/PT1.http/pt1-http-rc1/recpt1//config.status ---- .//config.status 2011-05-08 03:40:12.748538598 +0900 -+++ /home/takuya/PT1.http/pt1-http-rc1/recpt1//config.status 2011-05-13 21:53:55.631548303 +0900 -@@ -444,7 +444,7 @@ - This config.status script is free software; the Free Software Foundation - gives unlimited permission to copy, distribute and modify it." - --ac_pwd='/home/takuya/PT1.2011-03-08/pt1/recpt1' -+ac_pwd='/home/takuya/PT1.http/pt1-http-rc1/recpt1' - srcdir='.' - test -n "$AWK" || AWK=awk - # The default lists apply if the user does not specify any file. diff -urN .//recpt1.c /home/takuya/PT1.http/pt1-http-rc1/recpt1//recpt1.c --- .//recpt1.c 2011-03-08 02:50:50.604306966 +0900 +++ /home/takuya/PT1.http/pt1-http-rc1/recpt1//recpt1.c 2010-04-29 00:50:21.000000000 +0900 @@ -21,6 +21,8 @@ #include <netinet/in.h> #include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/uio.h> #include "pt1_ioctl.h" #include "config.h" @@ -78,6 +80,30 @@ int tune(char *channel, thread_data *tdata, char *device); int close_tuner(thread_data *tdata); +//read 1st line from socket +int read_line(int socket, char *p){ + int len = 0; + while (1){ + int ret; + ret = read(socket, p, 1); + if ( ret == -1 ){ + perror("read"); + exit(1); + } else if ( ret == 0 ){ + break; + } + if ( *p == '\n' ){ + p++; + len++; + break; + } + p++; + len++; + } + *p = '\0'; + return len; +} + /* ipc message receive */ void * @@ -486,7 +512,7 @@ show_usage(char *cmd) { #ifdef HAVE_LIBARIB25 - fprintf(stderr, "Usage: \n%s [--b25 [--round N] [--strip] [--EMM]] [--udp [--addr hostname --port portnumber]] [--device devicefile] [--lnb voltage] [--sid SID1,SID2] channel rectime destfile\n", cmd); + fprintf(stderr, "Usage: \n%s [--b25 [--round N] [--strip] [--EMM]] [--udp [--addr hostname --port portnumber]] [--http portnumber] [--device devicefile] [--lnb voltage] [--sid SID1,SID2] channel rectime destfile\n", cmd); #else fprintf(stderr, "Usage: \n%s [--strip] [--EMM]] [--udp [--addr hostname --port portnumber]] [--device devicefile] [--lnb voltage] [--sid SID1,SID2] channel rectime destfile\n", cmd); #endif @@ -509,6 +535,7 @@ fprintf(stderr, "--udp: Turn on udp broadcasting\n"); fprintf(stderr, " --addr hostname: Hostname or address to connect\n"); fprintf(stderr, " --port portnumber: Port number to connect\n"); + fprintf(stderr, "--http portnumber: Turn on http broadcasting (run as a daemon)\n"); fprintf(stderr, "--device devicefile: Specify devicefile to use\n"); fprintf(stderr, "--lnb voltage: Specify LNB voltage (0, 11, 15)\n"); fprintf(stderr, "--sid SID1,SID2,...: Specify SID number in CSV format (101,102,...)\n"); @@ -893,6 +920,7 @@ { "udp", 0, NULL, 'u'}, { "addr", 1, NULL, 'a'}, { "port", 1, NULL, 'p'}, + { "http", 1, NULL, 'H'}, { "device", 1, NULL, 'd'}, { "help", 0, NULL, 'h'}, { "version", 0, NULL, 'v'}, @@ -903,18 +931,20 @@ boolean use_b25 = FALSE; boolean use_udp = FALSE; + boolean use_http = FALSE; boolean fileless = FALSE; boolean use_stdout = FALSE; boolean use_splitter = FALSE; char *host_to = NULL; int port_to = 1234; + int port_http = 12345; sock_data *sockdata = NULL; char *device = NULL; int val; char *voltage[] = {"0V", "11V", "15V"}; char *sid_list = NULL; - while((result = getopt_long(argc, argv, "br:smn:ua:p:d:hvli:", + while((result = getopt_long(argc, argv, "br:smn:ua:H:p:d:hvli:", long_options, &option_index)) != -1) { switch(result) { case 'b': @@ -934,6 +964,11 @@ host_to = "localhost"; fprintf(stderr, "enable UDP broadcasting\n"); break; + case 'H': + use_http = TRUE; + port_http = atoi(optarg); + fprintf(stderr, "creating a http daemon\n"); + break; case 'h': fprintf(stderr, "\n"); show_usage(argv[0]); @@ -993,6 +1028,214 @@ } } + //http broadcasting + if(use_http){ + fprintf(stderr, "run as a daemon..\n"); + if(daemon(1,1)){ + perror("failed to start"); + exit(1); + } + fprintf(stderr, "pid = %d\n", getpid()); + + int connected_socket, listening_socket; + struct sockaddr_in sin; + unsigned int len; + int ret; + int sock_optval = 1; + + listening_socket = socket(AF_INET, SOCK_STREAM, 0); + if ( listening_socket == -1 ){ + perror("socket"); + exit(1); + } + + if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, + &sock_optval, sizeof(sock_optval)) == -1 ){ + perror("setsockopt"); + exit(1); + } + + sin.sin_family = AF_INET; + sin.sin_port = htons(port_http); + sin.sin_addr.s_addr = htonl(INADDR_ANY); + + + if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){ + perror("bind"); + exit(1); + } + + ret = listen(listening_socket, SOMAXCONN); + if ( ret == -1 ){ + perror("listen"); + exit(1); + } + fprintf(stderr,"listening at port %d\n", port_http); + + /* initialize decoder */ + if(use_b25) { + dec = b25_startup(&dopt); + if(!dec) { + fprintf(stderr, "Cannot start b25 decoder\n"); + fprintf(stderr, "Fall back to encrypted recording\n"); + use_b25 = FALSE; + } + } + /* initialize splitter */ + if(use_splitter) { + splitter = split_startup(sid_list); + if(splitter->sid_list == NULL) { + fprintf(stderr, "Cannot start TS splitter\n"); + return 1; + } + } + //set rectime to the infinite + if(parse_time("-",&tdata) != 0){ + return 1; + } + + while(1){ + struct hostent *peer_host; + struct sockaddr_in peer_sin; + + len = sizeof(peer_sin); + + connected_socket = accept(listening_socket, (struct sockaddr *)&peer_sin, &len); + if ( connected_socket == -1 ){ + perror("accept"); + exit(1); + } + + peer_host = gethostbyaddr((char *)&peer_sin.sin_addr.s_addr, + sizeof(peer_sin.sin_addr), AF_INET); + if ( peer_host == NULL ){ + fprintf(stderr, "gethostbyname failed\n"); + exit(1); + } + + fprintf(stderr,"connect from: %s [%s] port %d\n", peer_host->h_name, inet_ntoa(peer_sin.sin_addr), ntohs(peer_sin.sin_port)); + + int read_size; + + char buf[256]; + read_size = read_line(connected_socket, buf); + char s0[10],s1[10],s2[10]; + sscanf(buf,"%s %s %s",s0,s1,s2); + char *channel = &s1[1]; + fprintf(stderr,"channel is %s\n",channel); + char header[] = "HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream\r\nCache-Control: no-cache\r\n\r\n"; + ret = write(connected_socket, header, strlen(header)); + + //set write target to http + tdata.wfd = connected_socket; + + //tune + if(tune(channel, &tdata, device) != 0){ + fprintf(stderr, "Tuner cannot start recording\n"); + continue; + } + /* prepare thread data */ + tdata.queue = p_queue; + tdata.decoder = dec; + tdata.splitter = splitter; + tdata.sock_data = sockdata; + + /* spawn signal handler thread */ + init_signal_handlers(&signal_thread, &tdata); + + /* spawn reader thread */ + tdata.signal_thread = signal_thread; + pthread_create(&reader_thread, NULL, reader_func, &tdata); + + /* spawn ipc thread */ + key_t key; + key = (key_t)(getpid()); + + if ((tdata.msqid = msgget(key, IPC_CREAT | 0666)) < 0) { + perror("msgget"); + } + pthread_create(&ipc_thread, NULL, mq_recv, &tdata); + + /* start recording */ + if(ioctl(tdata.tfd, START_REC, 0) < 0) { + fprintf(stderr, "Tuner cannot start recording\n"); + exit(1); + } + + fprintf(stderr, "Broadcasting...\n"); + + time(&tdata.start_time); + + /* read from tuner */ + while(1) { + if(f_exit) + break; + + time(&cur_time); + bufptr = malloc(sizeof(BUFSZ)); + if(!bufptr) { + f_exit = TRUE; + break; + } + bufptr->size = read(tdata.tfd, bufptr->buffer, MAX_READ_SIZE); + if(bufptr->size <= 0) { + if((cur_time - tdata.start_time) >= tdata.recsec && !tdata.indefinite) { + f_exit = TRUE; + enqueue(p_queue, NULL); + break; + } + else { + continue; + } + } + enqueue(p_queue, bufptr); + + /* stop recording */ + time(&cur_time); + if((cur_time - tdata.start_time) >= tdata.recsec && !tdata.indefinite) { + ioctl(tdata.tfd, STOP_REC, 0); + // read remaining data + while(1) { + bufptr = malloc(sizeof(BUFSZ)); + if(!bufptr) { + f_exit = TRUE; + break; + } + bufptr->size = read(tdata.tfd, bufptr->buffer, MAX_READ_SIZE); + if(bufptr->size <= 0) { + f_exit = TRUE; + enqueue(p_queue, NULL); + break; + } + enqueue(p_queue, bufptr); + } + break; + } + } + + /* delete message queue*/ + msgctl(tdata.msqid, IPC_RMID, NULL); + + pthread_kill(signal_thread, SIGUSR1); + + /* wait for threads */ + pthread_join(reader_thread, NULL); + pthread_join(signal_thread, NULL); + pthread_join(ipc_thread, NULL); + + + /* close tuner */ + if(close_tuner(&tdata) != 0) + return 1; + + /* close http socket */ + close(tdata.wfd); + + fprintf(stderr,"connection closed. still listening at port %d\n",port_http); + f_exit = FALSE; + } + } + if(argc - optind < 3) { if(argc - optind == 2 && use_udp) { fprintf(stderr, "Fileless UDP broadcasting\n"); @@ -1120,6 +1363,7 @@ time(&tdata.start_time); + /* read from tuner */ while(1) { if(f_exit)
参考資料
http://otu.sakura.ne.jp/2ch/_bin/view.cgi?host=pc11.2ch.net&board=linux&thread=1269999876&delete=1
http://pc11.2ch.net/test/read.cgi/linux/1230616112/769
当方って古くさいよね
どうでもいいけど当方・小生とか小職という文字見ると加齢臭がするって誰かに言われたので。僕も時々使ってたけど自重することにします.