#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Types.h" #include "../katla/katlaStructs.h" #include "../../linux/drivers/edgeware/offs_fs.h" #include "../../linux/drivers/edgeware/exge.h" #include "../../linux/drivers/edgeware/katla.h" #include "UdpHeader.h" // 224.1.1.1 11111 eth0 /media/k streamID enum { ARG_IP=1, ARG_PORT, ARG_INTERFACE, ARG_FILENAME, ARG_STREAMID, ARG_NROF }; static inline unsigned int BitrateToPrate(unsigned int bitrate) { return bitrate == 0 ? 0 : 90000 * 188 * 8 * 7 / bitrate; } void TerminationHandler(int signal) { } int main( int argc, char *argv[] ) { int fd=-1, fdFjalar=-1, fdKatla=-1; UdpHeader* pUdpHeader = NULL; ifreq ifr; ContentInfo cInfo; in_addr destIpAddr; in_addr* pSourceIpAddr; unsigned char ttl = 128; char buffer; struct sockaddr_in saddr; memset(&saddr, 0, sizeof(struct sockaddr_in)); int status; struct sigaction action; unsigned int streamId; memset(&action, 0, sizeof action); cInfo.uTimeReq = 0; cInfo.bRelativeEnd = 0; if (argc!=ARG_NROF) { fprintf(stderr, "playout usage: IP PORT INTERFACE FILENAME STREAMID\n"); return 1; } streamId = atoi(argv[ARG_STREAMID]) + 8010; action.sa_handler = TerminationHandler; if (sigaction(SIGINT, &action, NULL) == -1) { fprintf(stderr, "sigaction(SIGTERM) failed\n"); } if (sigaction(SIGTERM, &action, NULL) == -1) { fprintf(stderr, "sigaction(SIGINT) failed\n"); } /* Open file */ if ((fd=open(argv[ARG_FILENAME], 0))<0) { fprintf(stderr, "Unable to open %s error\n", argv[3]); goto out; } /* Get content info */ if (ioctl(fd, OFFS_GET_CONTENTINFO, &cInfo)<0) { fprintf(stderr, "Unable to get start of file error\n"); goto out; } /* Open Fjalar net interface */ fdFjalar = socket(PF_INET, SOCK_DGRAM, 0/*htons(ETH_P_IP)*/); if (fdFjalar < 0) { fprintf(stderr, "Unable to open fjalar interface\n"); goto out; } memset(&ifr, 0, sizeof ifr); strncpy(ifr.ifr_name, argv[ARG_INTERFACE], sizeof (ifr.ifr_name) - 1); if (ioctl(fdFjalar, SIOCGIFFLAGS, &ifr) < 0) { fprintf(stderr, "ioctl(SIOCGIFFLAGS) failed : %m\n"); goto out; } if (!(ifr.ifr_flags & IFF_UP)) { fprintf(stderr, "Interface Is DOWN\n"); goto out; } if (ioctl(fdFjalar, SIOCGIFHWADDR, &ifr) < 0) { fprintf(stderr, "ioctl(SIOCGIFHWADDR) failed : %m\n"); goto out; } //assert(sizeof m_macAddress <= sizeof ifr.ifr_hwaddr.sa_data); u8 sourceMacAddress[ETH_ALEN]; memcpy(sourceMacAddress, (const u8*)&ifr.ifr_hwaddr.sa_data, sizeof sourceMacAddress); //assert(sizeof m_macAddress == 6); //fprintf(stdout, "Interface %s has MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", argv[ARG_INTERFACE], sourceMacAddress[0] & 0xFF, sourceMacAddress[1] & 0xFF, sourceMacAddress[2] & 0xFF, so urceMacAddress[3] & 0xFF, sourceMacAddress[4] & 0xFF, sourceMacAddress[5] & 0xFF); if (ioctl(fdFjalar, SIOCGIFADDR, &ifr) < 0) { fprintf(stderr, "ioctl(SIOCGIFADDR) failed : %m\n"); goto out; } pSourceIpAddr = &((sockaddr_in*)&ifr.ifr_addr)->sin_addr; //fprintf(stdout, "Interface %s has IP Address %s\n", argv[ARG_INTERFACE], inet_ntoa(*pSourceIpAddr)); destIpAddr.s_addr = inet_addr(argv[ARG_IP]); static u8 destMacAddress[ETH_ALEN] = { 0x01, 0x00, 0x5e, 0x80, 0x00, 0x00 }; const char* pDestIp = (const char*)&destIpAddr.s_addr; destMacAddress[3] = pDestIp[1] & 0x7f; destMacAddress[4] = pDestIp[2]; destMacAddress[5] = pDestIp[3]; // fprintf(stdout, "Interface %s has DEST MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", argv[ARG_INTERFACE], destMacAddress[0] & 0xFF, destMacAddress[1] & 0xFF, destMacAddress[2] & 0xFF, destM acAddress[3] & 0xFF, destMacAddress[4] & 0xFF, destMacAddress[5] & 0xFF); /* Enable multicast */ // Set the outgoing interface to DEFAULT setsockopt(fdFjalar, IPPROTO_IP, IP_MULTICAST_IF, pSourceIpAddr, sizeof(struct in_addr)); // Set multicast packet TTL to 3; default TTL is 1 setsockopt(fdFjalar, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(unsigned char)); // set destination multicast address saddr.sin_family = PF_INET; saddr.sin_addr.s_addr = destIpAddr.s_addr; saddr.sin_port = htons(atoi(argv[ARG_PORT])); sockaddr_in localAddress; localAddress.sin_family = AF_INET; localAddress.sin_port = htons(20000 + streamId); localAddress.sin_addr.s_addr = htonl(INADDR_ANY); bind(fdFjalar, (sockaddr*)&localAddress, sizeof localAddress); status = sendto(fdFjalar, &buffer, 0, 0, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); /* Setup sessiondata */ Sessiondata sessiondata; sessiondata.streamId = streamId; sessiondata.port = 0; sessiondata.length = sizeof (UdpHeader); pUdpHeader = new UdpHeader(sourceMacAddress, destMacAddress, *pSourceIpAddr, destIpAddr, 20000 + sessiondata.streamId, atoi(argv[ARG_PORT])); memcpy(sessiondata.UDPHeader, pUdpHeader, sessiondata.length); ifr.ifr_data = (char*)&sessiondata; if (ioctl(fdFjalar, FJALAR_SETUPSESSION, &ifr)<0) { fprintf(stderr, "ioctl(FJALAR_SETUPSESSION) failed\n"); goto out; } fdKatla = open("/dev/katla", O_RDWR); if (fdKatla < 0) { fprintf(stderr, "Unable to open /dev/katla (is katla.ko loaded?)\n"); goto kill_fjalar; } SetupSessionInfo info; memset(&info,0,sizeof (info)); info.sLM.uLength = 2048 * 8 - cInfo.uStart; info.sLM.uStart = cInfo.uStart; info.sLM.addr = cInfo.nPhysAddress; if (cInfo.uBitrate>0) info.sShaperEntry.prate = BitrateToPrate(cInfo.uBitrate); else { info.sShaperEntry.prate = 0; } info.sShaperEntry.enable = 0; info.sShaperEntry.last_pcr=0; info.sShaperEntry.count=0; info.sShaperEntry.pcr_learn=1; info.sShaperEntry.pcr_correct_off=0; info.sShaperEntry.reserved=0; info.uStreamId = sessiondata.streamId; if (ioctl(fdKatla, KATLA_SETUP_SESSION, &info) != 0) { fprintf(stderr, "ioctl(KATLA_SETUP_SESSION) failed\n"); goto kill_fjalar; } if (ioctl(fdKatla, KATLA_PLAY, &info.uStreamId) != 0) { // Play from stop or from pause fprintf(stderr, "ioctl(KATLA_PLAY) failed\n"); goto kill_fjalar; } fflush(stdout); sleep(cInfo.uLength + 1); kill_fjalar: ifr.ifr_data = (char*)info.uStreamId; if (ioctl(fdFjalar, FJALAR_KILLSESSION, &ifr) == -1) { fprintf(stderr, "ioctl(FJALAR_KILLSESSION) failed\n"); } if (ioctl(fdKatla, KATLA_KILL_SESSION, &info.uStreamId) != 0) { fprintf(stderr, "ioctl(KATLA_KILL_SESSION) failed\n"); } out: if (fdFjalar >= 0) close(fdFjalar); if (fdKatla >= 0) close(fdKatla); if (fd >= 0) close(fd); delete pUdpHeader; return 0; }