Statistics
| Branch: | Tag: | Revision:

dvbd / src / dvbrtp.cpp @ 81094b1d

History | View | Annotate | Download (5.95 KB)

1
/*
2
  Copyright 2003 John Knottenbelt
3
  RTP Modifications by Federico Simoncelli
4
  
5
  This program is free software; you can redistribute it and/or modify
6
  it under the terms of the GNU General Public License as published by
7
  the Free Software Foundation; either version 2 of the License, or
8
  (at your option) any later version.
9
 
10
  This program is distributed in the hope that it will be useful,
11
  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
  GNU General Public License for more details.
14
 
15
  You should have received a copy of the GNU General Public License
16
  along with this program; if not, write to the Free Software
17
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
18
*/
19

    
20
#include "config.h"
21
#include "dvbd.h"
22
#include "utils.h"
23
#include "stringutil.h"
24
#include "select.h"
25
#include "clientconnection.h"
26
#include "unixclientsocket.h"
27
#include "rtp.h"
28

    
29
#include <string>
30
#include <iostream>
31
#include <time.h>
32
#include <getopt.h>
33
#include <cerrno>
34
#include <fstream>
35
#include <fcntl.h>
36

    
37
/* Network Include Files */
38
#include <sys/time.h>
39
#include <sys/socket.h>
40
#include <netinet/in.h>
41
#include <netdb.h>
42
#include <arpa/inet.h>
43

    
44
/* Thanks to Giancarlo Baracchino for this fix */
45
#define MTU 1500
46
#define IP_HEADER_SIZE 20
47
#define UDP_HEADER_SIZE 8
48
#define RTP_HEADER_SIZE 12
49

    
50
#define MAX_RTP_SIZE (MTU - IP_HEADER_SIZE - UDP_HEADER_SIZE - RTP_HEADER_SIZE)
51

    
52
void usage(const char *progname);
53
long getmsec(void);
54
char* getIpHost(const char *host);
55

    
56

    
57
int main(int argc, char *argv[])
58
{
59
  // improve iostream performance
60
  std::ios::sync_with_stdio(false);
61

    
62
  std::string socketFile = DEFAULT_SOCKET_FILE;
63
  bool durationSpecified = false;
64
  unsigned duration = 0;
65
  int priority = 10;
66
  bool convertToPS = false;
67

    
68
  while (true) {
69
    static struct option long_options[] = {
70
      {"duration", 1, 0, 'd'},
71
      {"priority", 1, 0, 'p'},
72
      {"socket", 1, 0, 's'},
73
      {"ps", 0, 0, 'P'},
74
      {0, 0, 0, 0}
75
    };
76
 
77
    int option_index = 0;
78
    int c = getopt_long(argc, argv, "Pd:p:o:s:", long_options, &option_index);
79
    if (c == -1)
80
      break;
81
    switch (c) {
82
    case 'd':
83
      durationSpecified = true;
84
      duration = toInt(optarg);
85
      break;
86
    case 'p':
87
      priority = toInt(optarg);
88
      break;
89
    case 's':
90
      socketFile = optarg;
91
      break;
92
    case 'P':
93
      convertToPS = true;
94
      break;
95
    default:
96
      usage(argv[0]);
97
      return 1;
98
    }
99
  }
100

    
101
  if (argc - optind != 3) {
102
    if (argc - optind != 0)
103
      std::cerr << "Incorrect number of arguments passed (expected 2, got " 
104
                << argc - optind << ")\n\n";
105

    
106
    usage(argv[0]);
107
    return 1;
108
  }
109

    
110
  // Parse the command line arguments
111
  std::string type(argv[optind++]);
112
  std::string channel(argv[optind++]);
113
  std::string host(argv[optind++]);
114

    
115
  ClientConnection client(socketFile);
116
  if (!client) {
117
    std::cerr << "Fatal error: failed to connect to server on socket " << socketFile << std::endl;
118
    return 1;
119
  }
120

    
121
  char *destAddress = getIpHost(host.substr(0, host.find(":")).c_str());
122
  if(destAddress == NULL) {
123
    std::cerr << "Destination host not found!" << std::endl;
124
    return 1;
125
  }
126

    
127
  int destPort = atoi(host.substr(host.find(":") + 1, host.rfind(":")).c_str());
128
  if(destPort == 0) destPort = 5004;
129

    
130
  int ttl = 2;
131
  struct sockaddr_in sOut;
132
  struct rtpheader hdr;
133

    
134
  int socketOut = makesocket(destAddress, destPort, ttl, &sOut);
135
  initrtp(&hdr, (convertToPS) ? 34 : 33 /* 33 for RTP_TS, 34 for RTP_PS */);
136

    
137
  // Tune the channel
138
  if (!client.tune(type, channel, convertToPS, priority)) {
139
    std::cerr << "Failed to tune channel. Response from server was:\n"
140
              << client.getError() << "\n";
141
    return 1;
142
  }
143

    
144
  UnixClientSocket &control = client.control();
145
  UnixClientSocket &data = client.data();
146

    
147
  control.setBlocking(false);
148
  data.setBlocking(false);
149

    
150
  time_t start = time(NULL);
151
  Select s;
152
  do {
153
    s.clearFDs();
154
    control.addSelectFDs(s);
155
    data.addSelectFDs(s);
156

    
157
    if (durationSpecified) {
158
      unsigned elapsed = time(NULL) - start;
159
      if (elapsed >= duration*60) {
160
        std::cerr << "Duration elapsed" << std::endl;
161
        break;
162
      }
163
      s.addAlarm(duration * 60 - elapsed, 0);
164
    }
165

    
166
    s.wait();
167

    
168
    if (data.isReady(s)) {
169
      if (!data.processReady(s)) {
170
        std::cerr << "Server closed data connection" << std::endl;
171
        break;
172
      }
173

    
174
      char buffer[MAX_RTP_SIZE];
175
      int bytesRead = data.read(buffer, MAX_RTP_SIZE);
176

    
177
      if (bytesRead > 0)
178
      {
179
        hdr.timestamp = getmsec() * 90;
180
        int bytesWritten = sendrtp2(socketOut, &sOut, &hdr, buffer, bytesRead);
181

    
182
        if (bytesWritten < 0 && errno == EPIPE)
183
          break;
184
      }
185
    }
186
    else if (control.isReady(s)) {
187
      if (!control.processReady(s)) {
188
        std::cerr << "Server closed control connection" << std::endl;
189
        break;
190
      }
191

    
192
      std::string line;
193
      if (control.readLine(line)) 
194
        std::cerr << line;
195
    }
196
  } while (true);
197

    
198
  return 0;
199
}
200

    
201
void usage(const char *progname) {
202
  std::cerr << "Usage: " << progname << " [OPTION] TYPE CHANNEL HOST:PORT\n"
203
            << "Receive DVB broadcast for channel CHANNEL, using DVB-card\n"
204
            << "Broadcast RTP stream to HOST:PORT\n"
205
            << "\n"
206
            << "TYPE can be dvb-t, dvb-s or dvb-c.\n"
207
            << "\n"
208
            << "  -d, --duration         Time to stream for in minutes.\n"
209
            << "  -p, --priority         Priority of stream (default is 10\n"
210
            << "                         higher priorities may dislodge lower\n"
211
            << "                         ones).\n"
212
            << "  -s, --socket           Specify socket to connect to\n"
213
            << "                         (default is " << DEFAULT_SOCKET_FILE << ")\n"
214
            << "  -P, --ps               Convert stream to program stream\n";
215
}
216

    
217
long getmsec()
218
{
219
  struct timeval tv;
220
  gettimeofday(&tv, (struct timezone*) NULL);
221
  return (tv.tv_sec % 1000000) * 1000 + tv.tv_usec / 1000;
222
}
223

    
224
char *getIpHost(const char *host)
225
{
226
  struct hostent *h = gethostbyname(host);
227
  if (h == NULL) return NULL;
228
  return inet_ntoa(*(reinterpret_cast<in_addr*>(h->h_addr_list[0])));
229
}
230