📄 plaympeg.c
字号:
/* plaympeg - Sample MPEG player using the SMPEG library Copyright (C) 1999 Loki Entertainment Software This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#ifdef unix#include <unistd.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <sys/time.h>#define NET_SUPPORT /* General network support */#define RAW_SUPPORT /* Raw data transport support */#define HTTP_SUPPORT /* HTTP support */#define FTP_SUPPORT /* FTP support */#ifdef linux#define VCD_SUPPORT /* Video CD support */#endif#endif#ifdef NET_SUPPORT#include <netinet/in.h>#include <netdb.h>#include <sys/socket.h>#include <arpa/inet.h>#endif#ifdef VCD_SUPPORT#include <signal.h>#include <fcntl.h>#include <sys/stat.h>#include <linux/cdrom.h>#endif#include "smpeg.h"void usage(char *argv0){ printf("Usage: %s [options] file ...\n""Where the options are one of:\n"" --noaudio Don't play audio stream\n"" --novideo Don't play video stream\n"" --fullscreen Play MPEG in fullscreen mode\n"" --double or -2 Play MPEG at double size\n"" --loop or -l Play MPEG over and over\n"" --bilinear Use software bilinear filtering\n"" --volume N or -v N Set audio volume to N (0-100)\n"" --scale wxh or -s wxh Play MPEG at given resolution\n"" --seek N or -S N Skip N bytes\n"#ifdef USE_SYSTEM_TIMESTAMP" --skip N or -k N Skip N seconds\n"#endif" --help or -h\n"" --version or -V\n""Specifying - as filename will use stdin for input\n", argv0);}#ifdef NET_SUPPORTint is_address_multicast(unsigned long address){ if((address & 255) >= 224 && (address & 255) <= 239) return(1); return(0);}int tcp_open(char * address, int port){ struct sockaddr_in stAddr; struct hostent * host; int sock; struct linger l; memset(&stAddr,0,sizeof(stAddr)); stAddr.sin_family = AF_INET ; stAddr.sin_port = htons(port); if((host = gethostbyname(address)) == NULL) return(0); stAddr.sin_addr = *((struct in_addr *) host->h_addr_list[0]) ; if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) return(0); l.l_onoff = 1; l.l_linger = 5; if(setsockopt(sock, SOL_SOCKET, SO_LINGER, (char*) &l, sizeof(l)) < 0) return(0); if(connect(sock, (struct sockaddr *) &stAddr, sizeof(stAddr)) < 0) return(0); return(sock);}int udp_open(char * address, int port){ int enable = 1L; struct sockaddr_in stAddr; struct sockaddr_in stLclAddr; struct ip_mreq stMreq; struct hostent * host; int sock; stAddr.sin_family = AF_INET; stAddr.sin_port = htons(port); if((host = gethostbyname(address)) == NULL) return(0); stAddr.sin_addr = *((struct in_addr *) host->h_addr_list[0]) ; /* Create a UDP socket */ if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return(0); /* Allow multiple instance of the client to share the same address and port */ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(unsigned long int)) < 0) return(0); /* If the address is multicast, register to the multicast group */ if(is_address_multicast(stAddr.sin_addr.s_addr)) { /* Bind the socket to port */ stLclAddr.sin_family = AF_INET; stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); stLclAddr.sin_port = stAddr.sin_port; if(bind(sock, (struct sockaddr*) & stLclAddr, sizeof(stLclAddr)) < 0) return(0); /* Register to a multicast address */ stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr; stMreq.imr_interface.s_addr = INADDR_ANY; if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) & stMreq, sizeof(stMreq)) < 0) return(0); } else { /* Bind the socket to port */ stLclAddr.sin_family = AF_INET; stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); stLclAddr.sin_port = htons(0); if(bind(sock, (struct sockaddr*) & stLclAddr, sizeof(stLclAddr)) < 0) return(0); } return(sock);}#ifdef RAW_SUPPORTint raw_open(char * arg){ char * host; int port; int sock; /* Check for URL syntax */ if(strncmp(arg, "raw://", strlen("raw://"))) return(0); /* Parse URL */ port = 0; host = arg + strlen("raw://"); if(strchr(host, ':') != NULL) /* port is specified */ { port = atoi(strchr(host, ':') + 1); *strchr(host, ':') = 0; } /* Open a UDP socket */ if(!(sock = udp_open(host, port))) perror("raw_open"); return(sock);}#endif#ifdef HTTP_SUPPORTint http_open(char * arg){ char * host; int port; char * request; int tcp_sock; char http_request[1024]; char c; /* Check for URL syntax */ if(strncmp(arg, "http://", strlen("http://"))) return(0); /* Parse URL */ port = 80; host = arg + strlen("http://"); if((request = strchr(host, '/')) == NULL) return(0); *request++ = 0; if(strchr(host, ':') != NULL) /* port is specified */ { port = atoi(strchr(host, ':') + 1); *strchr(host, ':') = 0; } /* Open a TCP socket */ if(!(tcp_sock = tcp_open(host, port))) { perror("http_open"); return(0); } /* Send HTTP GET request */ sprintf(http_request, "GET /%s HTTP/1.0\r\n" "User-Agent: Mozilla/2.0 (Win95; I)\r\n" "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", request, host); send(tcp_sock, http_request, strlen(http_request), 0); /* Parse server reply */ do read(tcp_sock, &c, sizeof(char)); while(c != ' '); read(tcp_sock, http_request, 4*sizeof(char)); http_request[4] = 0; if(strcmp(http_request, "200 ")) { fprintf(stderr, "http_open: "); do { read(tcp_sock, &c, sizeof(char)); fprintf(stderr, "%c", c); } while(c != '\r'); fprintf(stderr, "\n"); return(0); } return(tcp_sock);}#endif#ifdef FTP_SUPPORTint ftp_get_reply(int tcp_sock){ int i; char c; char answer[1024]; do { /* Read a line */ for(i = 0, c = 0; i < 1024 && c != '\n'; i++) { read(tcp_sock, &c, sizeof(char)); answer[i] = c; } answer[i] = 0; fprintf(stderr, answer + 4); } while(answer[3] == '-'); answer[3] = 0; return(atoi(answer));}int ftp_open(char * arg){ char * host; int port; char * dir; char * file; int tcp_sock; int data_sock; char ftp_request[1024]; struct sockaddr_in stLclAddr; socklen_t namelen; int i; /* Check for URL syntax */ if(strncmp(arg, "ftp://", strlen("ftp://"))) return(0); /* Parse URL */ port = 21; host = arg + strlen("ftp://"); if((dir = strchr(host, '/')) == NULL) return(0); *dir++ = 0; if((file = strrchr(dir, '/')) == NULL) { file = dir; dir = NULL; } else *file++ = 0; if(strchr(host, ':') != NULL) /* port is specified */ { port = atoi(strchr(host, ':') + 1); *strchr(host, ':') = 0; } /* Open a TCP socket */ if(!(tcp_sock = tcp_open(host, port))) { perror("ftp_open"); return(0); } /* Send FTP USER and PASS request */ ftp_get_reply(tcp_sock); sprintf(ftp_request, "USER anonymous\r\n"); send(tcp_sock, ftp_request, strlen(ftp_request), 0); if(ftp_get_reply(tcp_sock) != 331) return(0); sprintf(ftp_request, "PASS smpeguser@\r\n"); send(tcp_sock, ftp_request, strlen(ftp_request), 0); if(ftp_get_reply(tcp_sock) != 230) return(0); sprintf(ftp_request, "TYPE I\r\n"); send(tcp_sock, ftp_request, strlen(ftp_request), 0); if(ftp_get_reply(tcp_sock) != 200) return(0); if(dir != NULL) { sprintf(ftp_request, "CWD %s\r\n", dir); send(tcp_sock, ftp_request, strlen(ftp_request), 0); if(ftp_get_reply(tcp_sock) != 250) return(0); } /* Get interface address */ namelen = sizeof(stLclAddr); if(getsockname(tcp_sock, (struct sockaddr *) &stLclAddr, &namelen) < 0) return(0); /* Open data socket */ if ((data_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) return(0); stLclAddr.sin_family = AF_INET; /* Get the first free port */ for(i = 0; i < 0xC000; i++) { stLclAddr.sin_port = htons(0x4000 + i); if(bind(data_sock, (struct sockaddr *) &stLclAddr, sizeof(stLclAddr)) >= 0) break; } port = 0x4000 + i; if(listen(data_sock, 1) < 0) return(0); i = ntohl(stLclAddr.sin_addr.s_addr); sprintf(ftp_request, "PORT %d,%d,%d,%d,%d,%d\r\n", (i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF, (port >> 8) & 0xFF, port & 0xFF); send(tcp_sock, ftp_request, strlen(ftp_request), 0); if(ftp_get_reply(tcp_sock) != 200) return(0); sprintf(ftp_request, "RETR %s\r\n", file); send(tcp_sock, ftp_request, strlen(ftp_request), 0); if(ftp_get_reply(tcp_sock) != 150) return(0); return(accept(data_sock, NULL, NULL));}#endif#endif#ifdef VCD_SUPPORTint vcd_read(int fd, int lba, unsigned char *buf){ struct cdrom_msf *msf; msf = (struct cdrom_msf*) buf; msf->cdmsf_min0 = (lba + CD_MSF_OFFSET) / CD_FRAMES / CD_SECS; msf->cdmsf_sec0 = (lba + CD_MSF_OFFSET) / CD_FRAMES % CD_SECS; msf->cdmsf_frame0 = (lba + CD_MSF_OFFSET) % CD_FRAMES; return(ioctl(fd, CDROMREADMODE2, buf));}int vcd_open(char * arg){ struct stat buf; struct cdrom_tocentry toc; char *pip; int track; int pipe_fd[2]; int fd; int pid, parent; unsigned char * buffer; /* Track defaults to 02, unless requested otherwise */ track = 02; pip = strrchr(arg, ':'); if ( pip ) { *pip = '\0'; track = atoi(pip+1) + 1; } /* See if the CD-ROM device file exists */ if ( (stat(arg, &buf) < 0) || !S_ISBLK(buf.st_mode) ) { if ( pip ) { *pip = ':'; } return(0); } fd = open(arg, O_RDONLY, 0); if ( fd < 0 ) { if ( pip ) { *pip = ':'; } return(0); } /* Track 02 (changed to 'track') contains MPEG data */ if ( track < 2 ) { printf("Warning: VCD data normally starts on track 2\n"); } toc.cdte_track = track; toc.cdte_format = CDROM_LBA; if(ioctl(fd, CDROMREADTOCENTRY, &toc) < 0) return(0); if(pipe(pipe_fd) < 0) return(0); parent = getpid(); pid = fork(); if(pid < 0) return(0); if(!pid) { /* Child process fills the pipe */ int pos; struct timeval timeout; fd_set fdset; buffer = (unsigned char *) malloc(CD_FRAMESIZE_RAW0); for(pos = toc.cdte_addr.lba; vcd_read(fd, pos, buffer) >= 0; pos ++) { if(kill(parent, 0) < 0) break; FD_ZERO(&fdset); FD_SET(pipe_fd[1], &fdset); timeout.tv_sec = 10; timeout.tv_usec = 0; if(select(pipe_fd[1]+1, NULL, &fdset, NULL, &timeout) <= 0) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -