From: michael Date: Sat, 1 Jul 2006 17:02:54 +0000 (+0000) Subject: record a stream (for example from getstream) X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/record-dvb/commitdiff_plain/5c2e3e4489486a30d8f14338277de093b4d94cf0 record a stream (for example from getstream) --- 5c2e3e4489486a30d8f14338277de093b4d94cf0 diff --git a/.cvsignore b/.cvsignore new file mode 100644 index 0000000..5a75ec1 --- /dev/null +++ b/.cvsignore @@ -0,0 +1,2 @@ +record-dvb +*.d diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f3306ce --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +CFLAGS =-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -Wall -g + +OBJS = record-dvb.o http.o mcast.o common.o + +all: record-dvb + +DEPEND=$(OBJS:.o=.d) +-include $(DEPEND) + +record-dvb: $(OBJS) + +clean: + rm -f record-dvb $(OBJS) $(DEPEND) + +%.o: %.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + $(COMPILE.c) -MM $< > $*.d + +.PHONY: all clean diff --git a/common.c b/common.c new file mode 100644 index 0000000..97ec807 --- /dev/null +++ b/common.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include + +#include "common.h" + +struct dvb_host *parse(char *urlpart, char *defport) +{ + struct dvb_host *dvbhost; + char *pos; + + if (!(dvbhost = malloc(sizeof(struct dvb_host)))) { + perror("malloc"); + exit(EXIT_FAILURE); + } + + bzero(dvbhost, sizeof(struct dvb_host)); + + if (!(dvbhost->hostname = strdup(urlpart))) { + perror("strdup"); + exit(EXIT_FAILURE); + } + + /* Unneded, but better readablity: */ + dvbhost->location = NULL; + dvbhost->port = NULL; + + pos = dvbhost->hostname; + + while(*pos != '\0' && *pos != ':' && *pos != '/') + pos++; + + if (*pos == '/') + dvbhost->location = pos + 1; + + if (*pos == ':') + dvbhost->port = pos + 1; + + *pos = 0; + + if (dvbhost->port) { + pos++; + + while(*pos != '\0' && *pos != '/') + pos ++; + + if(*pos == '/') + dvbhost->location = pos + 1; + + *pos = 0; + } + + if (!dvbhost->port) + dvbhost->port = strdup(defport); + + if (!dvbhost->location) + if(!(dvbhost->location = strdup(""))) { + perror("strdup"); + exit(EXIT_FAILURE); + } + + return dvbhost; +} diff --git a/common.h b/common.h new file mode 100644 index 0000000..5f7b1f8 --- /dev/null +++ b/common.h @@ -0,0 +1,7 @@ +struct dvb_host { + char *hostname; + char *port; + char *location; +}; + +struct dvb_host *parse(char *urlpart, char *defport); diff --git a/http.c b/http.c new file mode 100644 index 0000000..a4f4c91 --- /dev/null +++ b/http.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "http.h" + +#define BUFFSIZE 1024 + +int is_http(char *url) +{ + if (strlen(url) < 8) + return 0; + + if (!strncasecmp("http://",url,7)) + return 1; + + return 0; +} + +int open_http(char *url) +{ + int fd; + struct sockaddr_in server; + struct dvb_host *dvbhost; + struct addrinfo *s_addrinfo, addrhints; + char buffer[BUFFSIZE]; + int i; + + if(!is_http(url)) + return -1; + + dvbhost = parse(&(url[7]), "80"); + + bzero(&addrhints, sizeof(struct addrinfo)); + addrhints.ai_family = PF_INET; + addrhints.ai_socktype = SOCK_STREAM; + + if ((i=getaddrinfo(dvbhost->hostname, dvbhost->port, &addrhints, &s_addrinfo))) { + fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(i)); + return -1; + } + + if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + perror("socket"); + return -1; + } + + bzero(&server, sizeof(struct sockaddr_in)); + server.sin_family = AF_INET; + server.sin_addr.s_addr = ((struct sockaddr_in*)(s_addrinfo->ai_addr))->sin_addr.s_addr; + server.sin_port = ((struct sockaddr_in*)(s_addrinfo->ai_addr))->sin_port; + + if (connect(fd, (struct sockaddr*) &server, sizeof(server)) < 0) { + perror("connect"); + return -1; + } + + freeaddrinfo(s_addrinfo); + + + snprintf(buffer, BUFFSIZE-1, "GET /%s HTTP/1.0\n\n",dvbhost->location); + buffer[BUFFSIZE-1] = 0; + send(fd, buffer, strlen(buffer), 0); + i = 0; + while(i < 2) { + if (recv(fd, buffer, 1, 0) < 1) { + perror("recv"); + exit(EXIT_FAILURE); + } + printf("%c",buffer[0]); + if (buffer[0] == 0x0a) + i++; + else + if (buffer[0] != 0x0d) + i = 0; + } + + return fd; +} diff --git a/http.h b/http.h new file mode 100644 index 0000000..f5f5cb1 --- /dev/null +++ b/http.h @@ -0,0 +1,2 @@ +int is_http(char *url); +int open_http(char *url); diff --git a/mcast.c b/mcast.c new file mode 100644 index 0000000..a8be22f --- /dev/null +++ b/mcast.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include "mcast.h" + +int is_mcast(char *url) +{ + if (strlen(url) < 7) + return 0; + + if (!strncasecmp("udp://",url,6)) + return 1; + + return 0; +} + +int open_mcast(char *url) +{ + fprintf(stderr,"multicast currently unimplemented!\n"); + + exit(EXIT_FAILURE); +} diff --git a/mcast.h b/mcast.h new file mode 100644 index 0000000..e60cc90 --- /dev/null +++ b/mcast.h @@ -0,0 +1,2 @@ +int is_mcast(char *url); +int open_mcast(char *url); diff --git a/record-dvb.c b/record-dvb.c new file mode 100644 index 0000000..aa48bb4 --- /dev/null +++ b/record-dvb.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "http.h" +#include "mcast.h" + +#define CHUNKSIZE 8192 + +void record(int(*open_fn)(char *), char *url, char *outfile, int duration) +{ + struct timeval start, curr; + int bytes, written; + char buffer[CHUNKSIZE]; + int i; + int in, out; + + if ((out = open(outfile, O_CREAT|O_TRUNC|O_WRONLY|O_LARGEFILE, 00644)) < 0) { + perror("open"); + exit(EXIT_FAILURE); + } + + if ((in = (*open_fn)(url)) < 0) { + fprintf(stderr,"Can't open url %s!\n",url); + exit(EXIT_FAILURE); + } + + printf("Recording from %s for %d seconds...\n", url, duration); + + gettimeofday(&start, NULL); + + do { + if ((bytes = recv(in, buffer, CHUNKSIZE, 0)) < 1) { + perror("recv"); + exit(EXIT_FAILURE); + } + + written = 0; + do { + if ((i = write(out, buffer, bytes-written)) < 0) { + perror("write"); + exit(EXIT_FAILURE); + } + written += i; + } while(written < bytes); + + gettimeofday(&curr, NULL); + } while (curr.tv_sec < start.tv_sec+duration); + + close(out); + close(in); + shutdown(in, SHUT_RDWR); +} + +int main(int argc, char **argv) +{ + int duration; + char *url; + char *outfile; + int(*open_fn)(char *); + + if (argc == 4) { + url = argv[1]; + duration = atol(argv[2])*60; + outfile = argv[3]; + } else { + fprintf(stderr,"Syntax: %s URL duration outfile\n", argv[0]); + exit(EXIT_FAILURE); + } + + if (is_http(url)) { + open_fn = &open_http; + } else if (is_mcast(url)) { + open_fn = &open_mcast; + } else { + printf("URL %s not supported!\n", url); + exit(EXIT_FAILURE); + } + + record(open_fn, url, outfile, duration); + + return EXIT_SUCCESS; +}