/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * inputstreamer.cc * * Sat Sep 20 10:15:51 CEST 2014 * Copyright 2014 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of SimpleRTP. * * SimpleRTP 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. * * SimpleRTP 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 SimpleRTP; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "inputstreamer.h" #include #include #define CSRC_V 42 #define CSRC_A 43 InputStreamer::InputStreamer(int peer, QString peer_name, QHostAddress addr, quint16 port, QString key, unsigned int ssrc) // : socket(this) { this->peer = peer; this->peer_name = peer_name; this->key = key; this->ssrc = ssrc; this->addr = addr; this->port = port; total = 0; name.sin_family = AF_INET; sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(sock < 0) { perror("socket()"); return; } name.sin_port = htons(port); //name.sin_addr.s_addr = inet_addr(addr.toString().toStdString().c_str()); name.sin_addr.s_addr = inet_addr("0.0.0.0"); // Listen on all interfaces if(INADDR_NONE == name.sin_addr.s_addr) { printf("Could not parse IP address: %s\n", addr.toString().toStdString().c_str()); return; } if(bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) { close(sock); perror("bind()"); return; } running = true; start(); } int interrupted; void handle_int(int num) { interrupted = 1; } InputStreamer::~InputStreamer() { running = false; wait(); close(sock); } #include void InputStreamer::run() { lrtp_status_t status; char ckey[61]; strcpy(ckey, key.toStdString().c_str()); lrtp = lrtp_init(&status, ckey, ssrc); if(status != LRTP_OK) printf("I:lrtp_init err: %d\n", status); int res; res = lrtp_create_profile(lrtp, PROFILE_JPEG, CSRC_V, OPTION_END); if(res != 0) printf("I:lrtp_create_profile (v) err: %d\n", res); res = lrtp_create_profile(lrtp, PROFILE_OPUS, CSRC_A, OPTION_END); if(res != 0) printf("I:lrtp_create_profile (a) err: %d\n", res); char packet[64*1024]; while(running) { ssize_t packetsize; { int fd = sock; fd_set fds; struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 1000; FD_ZERO(&fds); FD_SET(fd, &fds); if(select(fd + 1, &fds, NULL, NULL, &timeout) > 0) { packetsize = recv(sock, (char*)packet, sizeof(packet), 0); } else { // timeout continue; } } if(packetsize == -1) { perror("recv()"); usleep(1000); continue; } if(packetsize == 0) { usleep(1000); continue; } total += packetsize; // Now decode the sucker.... lrtp_unpack(lrtp, packet, packetsize); int n = 0; int ret; char frame[512 * 1024]; // 512kbyte should be enough for even the larges // JPEG frames... unsigned int csrc; unsigned int ts; while((ret = lrtp_dequeue_frame(lrtp, frame, sizeof(frame), &csrc, &ts)) != 0) { if(ret < 0) printf("I:lrtp_dequeue_frame: %d\n", ret); if(csrc == CSRC_V) { // Video frame Frame f(frame, ret); f.ts = ts; emit newImage(peer, f); //printf("v"); fflush(stdout); } else if(csrc == CSRC_A) { // Audio frame Frame f(frame, ret); f.ts = ts; emit newAudio(peer, f); //printf("a"); fflush(stdout); } else { printf("Unknown stream: CSRC: %d\n", csrc); } } } printf("done\n"); status = lrtp_destroy_profile(lrtp, CSRC_V); if(status != LRTP_OK) printf("I:lrtp_destroy_profile (v) err: %d\n", status); status = lrtp_destroy_profile(lrtp, CSRC_A); if(status != LRTP_OK) printf("I:lrtp_destroy_profile (a) err: %d\n", status); status = lrtp_close(lrtp); if(status != LRTP_OK) printf("I:lrtp_close err: %d\n", status); } size_t InputStreamer::getTotal() { size_t t = total; total = 0; return t; } QString InputStreamer::getName() { return peer_name; }