* dvbiscovery.sh: NIT can take longer than 15s. * dvbiscovery_dvb-s.conf: Change...
[dvblast.git] / output.c
blobd7f3f27c56b3805e3fa740ed63564acd68b4c9c9
1 /*****************************************************************************
2 * output.c
3 *****************************************************************************
4 * Copyright (C) 2004, 2008-2010 VideoLAN
5 * $Id$
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8 * Andy Gatward <a.j.gatward@reading.ac.uk>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <stdint.h>
28 #include <stdbool.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/uio.h>
37 #include <errno.h>
39 #include "dvblast.h"
41 #include <bitstream/mpeg/ts.h>
42 #include <bitstream/ietf/rtp.h>
44 /*****************************************************************************
45 * Local prototypes
46 *****************************************************************************/
47 struct packet_t
49 struct packet_t *p_next;
50 mtime_t i_dts;
51 int i_depth;
52 block_t **pp_blocks;
53 /* PRIVATE - this MUST be at the end of the structure: */
54 block_t *p_blocks; /* actually an array of pointers */
57 static uint8_t p_pad_ts[TS_SIZE] = {
58 0x47, 0x1f, 0xff, 0x10, 0xff, 0xff, 0xff, 0xff,
59 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
60 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
61 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
62 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
63 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
64 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
73 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
76 /*****************************************************************************
77 * output_Create : create and insert the output_t structure
78 *****************************************************************************/
79 output_t *output_Create( const output_config_t *p_config )
81 int i;
82 output_t *p_output = NULL;
84 for ( i = 0; i < i_nb_outputs; i++ )
86 if ( !( pp_outputs[i]->config.i_config & OUTPUT_VALID ) )
88 p_output = pp_outputs[i];
89 break;
93 if ( p_output == NULL )
95 p_output = malloc( sizeof(output_t) );
96 i_nb_outputs++;
97 pp_outputs = realloc( pp_outputs, i_nb_outputs * sizeof(output_t *) );
98 pp_outputs[i] = p_output;
101 if ( output_Init( p_output, p_config ) < 0 )
102 return NULL;
104 return p_output;
107 /*****************************************************************************
108 * output_Init : set up the output initial config
109 *****************************************************************************/
110 int output_Init( output_t *p_output, const output_config_t *p_config )
112 socklen_t i_sockaddr_len = (p_config->i_family == AF_INET) ?
113 sizeof(struct sockaddr_in) :
114 sizeof(struct sockaddr_in6);
116 memset( p_output, 0, sizeof(output_t) );
117 config_Init( &p_output->config );
119 /* Init run-time values */
120 p_output->p_packets = p_output->p_last_packet = NULL;
121 p_output->i_cc = rand() & 0xffff;
122 p_output->i_pat_cc = rand() & 0xf;
123 p_output->i_pmt_cc = rand() & 0xf;
124 p_output->i_nit_cc = rand() & 0xf;
125 p_output->i_sdt_cc = rand() & 0xf;
126 p_output->i_eit_cc = rand() & 0xf;
127 p_output->i_pat_version = rand() & 0xff;
128 p_output->i_pmt_version = rand() & 0xff;
129 p_output->i_nit_version = rand() & 0xff;
130 p_output->i_sdt_version = rand() & 0xff;
131 p_output->p_pat_section = NULL;
132 p_output->p_pmt_section = NULL;
133 p_output->p_nit_section = NULL;
134 p_output->p_sdt_section = NULL;
135 p_output->p_eit_ts_buffer = NULL;
136 if ( b_random_tsid )
137 p_output->i_tsid = rand() & 0xffff;
139 /* Init socket-related fields */
140 p_output->config.i_family = p_config->i_family;
141 memcpy( &p_output->config.connect_addr, &p_config->connect_addr,
142 sizeof(struct sockaddr_storage) );
143 memcpy( &p_output->config.bind_addr, &p_config->bind_addr,
144 sizeof(struct sockaddr_storage) );
145 p_output->config.i_if_index_v6 = p_config->i_if_index_v6;
147 p_output->i_handle = socket( p_config->i_family, SOCK_DGRAM, IPPROTO_UDP );
148 if ( p_output->i_handle < 0 )
150 msg_Err( NULL, "couldn't create socket (%s)", strerror(errno) );
151 p_output->config.i_config &= ~OUTPUT_VALID;
152 return -errno;
155 if ( p_config->bind_addr.ss_family != AF_UNSPEC )
157 if ( bind( p_output->i_handle, (struct sockaddr *)&p_config->bind_addr,
158 i_sockaddr_len ) < 0 )
159 msg_Warn( NULL, "couldn't bind socket (%s)", strerror(errno) );
161 if ( p_config->i_family == AF_INET )
163 struct sockaddr_in *p_connect_addr =
164 (struct sockaddr_in *)&p_output->config.connect_addr;
165 struct sockaddr_in *p_bind_addr =
166 (struct sockaddr_in *)&p_output->config.bind_addr;
168 if ( IN_MULTICAST( ntohl( p_connect_addr->sin_addr.s_addr ) ) )
169 setsockopt( p_output->i_handle, IPPROTO_IP, IP_MULTICAST_IF,
170 (void *)&p_bind_addr->sin_addr.s_addr,
171 sizeof(p_bind_addr->sin_addr.s_addr) );
175 if ( p_config->i_family == AF_INET6 && p_config->i_if_index_v6 != -1 )
177 struct sockaddr_in6 *p_addr =
178 (struct sockaddr_in6 *)&p_output->config.connect_addr;
179 if ( IN6_IS_ADDR_MULTICAST( p_addr->sin6_addr.s6_addr ) )
180 setsockopt( p_output->i_handle, IPPROTO_IPV6,
181 IPV6_MULTICAST_IF, (void *)&p_config->i_if_index_v6,
182 sizeof(p_config->i_if_index_v6) );
185 if ( connect( p_output->i_handle,
186 (struct sockaddr *)&p_output->config.connect_addr,
187 i_sockaddr_len ) < 0 )
189 msg_Err( NULL, "couldn't connect socket (%s)", strerror(errno) );
190 close( p_output->i_handle );
191 p_output->config.i_config &= ~OUTPUT_VALID;
192 return -errno;
195 p_output->config.i_config |= OUTPUT_VALID;
197 return 0;
200 /*****************************************************************************
201 * output_Close
202 *****************************************************************************/
203 void output_Close( output_t *p_output )
205 packet_t *p_packet = p_output->p_packets;
206 while ( p_packet != NULL )
208 int i;
210 for ( i = 0; i < p_packet->i_depth; i++ )
212 p_packet->pp_blocks[i]->i_refcount--;
213 if ( !p_packet->pp_blocks[i]->i_refcount )
214 block_Delete( p_packet->pp_blocks[i] );
216 p_output->p_packets = p_packet->p_next;
217 free( p_packet );
218 p_packet = p_output->p_packets;
221 p_output->p_packets = p_output->p_last_packet = NULL;
222 free( p_output->p_pat_section );
223 free( p_output->p_pmt_section );
224 free( p_output->p_nit_section );
225 free( p_output->p_sdt_section );
226 free( p_output->p_eit_ts_buffer );
227 p_output->config.i_config &= ~OUTPUT_VALID;
229 close( p_output->i_handle );
231 config_Free( &p_output->config );
234 /*****************************************************************************
235 * output_BlockCount
236 *****************************************************************************/
237 static int output_BlockCount( output_t *p_output )
239 int i_mtu = p_output->config.i_mtu;
240 if ( !(p_output->config.i_config & OUTPUT_UDP) )
241 i_mtu -= RTP_HEADER_SIZE;
242 return i_mtu / TS_SIZE;
245 /*****************************************************************************
246 * output_Flush
247 *****************************************************************************/
248 static void output_Flush( output_t *p_output )
250 packet_t *p_packet = p_output->p_packets;
251 int i_block_cnt = output_BlockCount( p_output );
252 struct iovec p_iov[i_block_cnt + 1];
253 uint8_t p_rtp_hdr[RTP_HEADER_SIZE];
254 int i_iov, i_block;
256 if ( !(p_output->config.i_config & OUTPUT_UDP) )
258 p_iov[0].iov_base = p_rtp_hdr;
259 p_iov[0].iov_len = sizeof(p_rtp_hdr);
261 rtp_set_hdr( p_rtp_hdr );
262 rtp_set_type( p_rtp_hdr, RTP_TYPE_TS );
263 rtp_set_cc( p_rtp_hdr, p_output->i_cc++ );
264 rtp_set_timestamp( p_rtp_hdr,
265 p_output->i_ref_timestamp
266 + (p_packet->i_dts - p_output->i_ref_wallclock)
267 * 9 / 100 );
268 rtp_set_ssrc( p_rtp_hdr, p_output->config.pi_ssrc );
270 i_iov = 1;
272 else
273 i_iov = 0;
275 for ( i_block = 0; i_block < p_packet->i_depth; i_block++ )
277 p_iov[i_iov].iov_base = p_packet->pp_blocks[i_block]->p_ts;
278 p_iov[i_iov].iov_len = TS_SIZE;
279 i_iov++;
282 for ( ; i_block < i_block_cnt; i_block++ )
284 p_iov[i_iov].iov_base = p_pad_ts;
285 p_iov[i_iov].iov_len = TS_SIZE;
286 i_iov++;
289 if ( writev( p_output->i_handle, p_iov, i_iov ) < 0 )
291 msg_Err( NULL, "couldn't writev to %s (%s)",
292 p_output->config.psz_displayname, strerror(errno) );
294 /* Update the wallclock because writev() can take some time. */
295 i_wallclock = mdate();
297 for ( i_block = 0; i_block < p_packet->i_depth; i_block++ )
299 p_packet->pp_blocks[i_block]->i_refcount--;
300 if ( !p_packet->pp_blocks[i_block]->i_refcount )
301 block_Delete( p_packet->pp_blocks[i_block] );
303 p_output->p_packets = p_packet->p_next;
304 free( p_packet );
305 if ( p_output->p_packets == NULL )
306 p_output->p_last_packet = NULL;
309 /*****************************************************************************
310 * output_Put : called from demux
311 *****************************************************************************/
312 void output_Put( output_t *p_output, block_t *p_block )
314 int i_block_cnt = output_BlockCount( p_output );
315 packet_t *p_packet;
317 p_block->i_refcount++;
319 if ( p_output->p_last_packet != NULL
320 && p_output->p_last_packet->i_depth < i_block_cnt
321 && p_output->p_last_packet->i_dts + p_output->config.i_max_retention
322 > p_block->i_dts )
324 p_packet = p_output->p_last_packet;
325 if ( ts_has_adaptation( p_block->p_ts )
326 && ts_get_adaptation( p_block->p_ts )
327 && tsaf_has_pcr( p_block->p_ts ) )
328 p_packet->i_dts = p_block->i_dts;
330 else
332 /* This isn't the cleanest allocation of the world. */
333 p_packet = malloc( sizeof(packet_t)
334 + (i_block_cnt - 1) * sizeof(block_t *) );
335 p_packet->pp_blocks = &p_packet->p_blocks;
336 p_packet->i_depth = 0;
337 p_packet->p_next = NULL;
338 p_packet->i_dts = p_block->i_dts;
339 if ( p_output->p_last_packet != NULL )
340 p_output->p_last_packet->p_next = p_packet;
341 else
342 p_output->p_packets = p_packet;
343 p_output->p_last_packet = p_packet;
346 p_packet->pp_blocks[p_packet->i_depth] = p_block;
347 p_packet->i_depth++;
350 /*****************************************************************************
351 * output_Send : called from main to flush the queues when needed
352 *****************************************************************************/
353 mtime_t output_Send( void )
355 mtime_t i_earliest_dts = -1;
356 int i;
358 if ( output_dup.config.i_config & OUTPUT_VALID )
360 while ( output_dup.p_packets != NULL
361 && output_dup.p_packets->i_dts
362 + output_dup.config.i_output_latency <= i_wallclock )
363 output_Flush( &output_dup );
365 if ( output_dup.p_packets != NULL )
366 i_earliest_dts = output_dup.p_packets->i_dts;
369 for ( i = 0; i < i_nb_outputs; i++ )
371 output_t *p_output = pp_outputs[i];
372 if ( !( p_output->config.i_config & OUTPUT_VALID ) )
373 continue;
375 while ( p_output->p_packets != NULL
376 && p_output->p_packets->i_dts
377 + p_output->config.i_output_latency <= i_wallclock )
378 output_Flush( p_output );
380 if ( p_output->p_packets != NULL
381 && (p_output->p_packets->i_dts
382 + p_output->config.i_output_latency < i_earliest_dts
383 || i_earliest_dts == -1) )
384 i_earliest_dts = p_output->p_packets->i_dts
385 + p_output->config.i_output_latency;
388 return i_earliest_dts == -1 ? -1 : i_earliest_dts - i_wallclock;
391 /*****************************************************************************
392 * output_Find : find an existing output from a given output_config_t
393 *****************************************************************************/
394 output_t *output_Find( const output_config_t *p_config )
396 socklen_t i_sockaddr_len = (p_config->i_family == AF_INET) ?
397 sizeof(struct sockaddr_in) :
398 sizeof(struct sockaddr_in6);
399 int i;
401 for ( i = 0; i < i_nb_outputs; i++ )
403 output_t *p_output = pp_outputs[i];
405 if ( !(p_output->config.i_config & OUTPUT_VALID) ) continue;
407 if ( p_config->i_family != p_output->config.i_family ||
408 memcmp( &p_config->connect_addr, &p_output->config.connect_addr,
409 i_sockaddr_len ) ||
410 memcmp( &p_config->bind_addr, &p_output->config.bind_addr,
411 i_sockaddr_len ) )
412 continue;
414 if ( p_config->i_family == AF_INET6 &&
415 p_config->i_if_index_v6 != p_output->config.i_if_index_v6 )
416 continue;
418 return p_output;
421 return NULL;
424 /*****************************************************************************
425 * output_Change : get changes from a new output_config_t
426 *****************************************************************************/
427 void output_Change( output_t *p_output, const output_config_t *p_config )
429 memcpy( p_output->config.pi_ssrc, p_config->pi_ssrc, 4 * sizeof(uint8_t) );
430 p_output->config.i_output_latency = p_config->i_output_latency;
431 p_output->config.i_max_retention = p_config->i_max_retention;
433 if ( p_output->config.i_ttl != p_config->i_ttl )
435 if ( p_output->config.i_family == AF_INET6 )
437 struct sockaddr_in6 *p_addr =
438 (struct sockaddr_in6 *)&p_output->config.connect_addr;
439 if ( IN6_IS_ADDR_MULTICAST( p_addr->sin6_addr.s6_addr ) )
440 setsockopt( p_output->i_handle, IPPROTO_IPV6,
441 IPV6_MULTICAST_HOPS, (void *)&p_config->i_ttl,
442 sizeof(p_config->i_ttl) );
444 else
446 struct sockaddr_in *p_addr =
447 (struct sockaddr_in *)&p_output->config.connect_addr;
448 if ( IN_MULTICAST( ntohl( p_addr->sin_addr.s_addr ) ) )
449 setsockopt( p_output->i_handle, IPPROTO_IP, IP_MULTICAST_TTL,
450 (void *)&p_config->i_ttl, sizeof(p_config->i_ttl) );
452 p_output->config.i_ttl = p_config->i_ttl;
455 if ( p_output->config.i_tos != p_config->i_tos )
457 if ( p_output->config.i_family == AF_INET )
458 setsockopt( p_output->i_handle, IPPROTO_IP, IP_TOS,
459 (void *)&p_config->i_tos, sizeof(p_config->i_tos) );
460 p_output->config.i_tos = p_config->i_tos;
463 if ( p_output->config.i_mtu != p_config->i_mtu
464 || ((p_output->config.i_config ^ p_config->i_config) & OUTPUT_UDP) )
466 int i_block_cnt;
467 packet_t *p_packet = p_output->p_last_packet;
468 p_output->config.i_config &= ~OUTPUT_UDP;
469 p_output->config.i_config |= p_config->i_config & OUTPUT_UDP;
470 p_output->config.i_mtu = p_config->i_mtu;
472 i_block_cnt = output_BlockCount( p_output );
473 if ( p_packet != NULL && p_packet->i_depth < i_block_cnt )
475 p_packet = realloc( p_packet, sizeof(packet_t *)
476 + (i_block_cnt - 1) * sizeof(block_t *) );
477 p_packet->pp_blocks = &p_packet->p_blocks;