Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
33f87566
Commit
33f87566
authored
Oct 29, 2008
by
Rémi Denis-Courmont
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Remove never used RTCP code (fixes #2254)
parent
05492281
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
0 additions
and
1377 deletions
+0
-1377
modules/mux/rtp/Modules.am
modules/mux/rtp/Modules.am
+0
-1
modules/mux/rtp/rtcp.c
modules/mux/rtp/rtcp.c
+0
-1040
modules/mux/rtp/rtcp.h
modules/mux/rtp/rtcp.h
+0
-282
modules/mux/rtp/rtp.h
modules/mux/rtp/rtp.h
+0
-54
No files found.
modules/mux/rtp/Modules.am
deleted
100644 → 0
View file @
05492281
SOURCES_rtcp = rtcp.c rtcp.h rtp.h
modules/mux/rtp/rtcp.c
deleted
100644 → 0
View file @
05492281
/*****************************************************************************
* rtcp.c: RTP/RTCP source file
*****************************************************************************
* Copyright (C) 2005-2007 M2X
*
* $Id$
*
* Authors: Jean-Paul Saman <jpsaman #_at_# videolan dot org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#include <netinet/in.h>
#include <sys/time.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_bits.h>
#include <vlc_block.h>
#include "rtp.h"
#include "rtcp.h"
void
send_RTCP
(
vlc_object_t
*
p_this
,
rtcp_event_t
);
void
rtcp_schedule
(
vlc_object_t
*
p_this
,
mtime_t
,
rtcp_event_t
);
/* SDES support functions */
static
int
SDES_client_item_add
(
rtcp_client_t
*
p_client
,
int
i_item
,
char
*
psz_name
)
{
rtcp_SDES_item_t
*
p_item
=
NULL
;
p_item
=
(
rtcp_SDES_item_t
*
)
malloc
(
sizeof
(
rtcp_SDES_item_t
)
);
if
(
!
p_item
)
return
VLC_ENOMEM
;
p_item
->
u_type
=
i_item
;
p_item
->
psz_data
=
strdup
(
psz_name
);
p_item
->
i_index
=
p_client
->
i_items
+
1
;;
INSERT_ELEM
(
p_client
->
pp_sdes
,
p_client
->
i_items
,
p_item
->
i_index
,
p_item
);
return
VLC_EGENERIC
;
}
static
int
SDES_client_item_del
(
rtcp_client_t
*
p_client
)
{
uint32_t
i
=
0
;
for
(
i
=
0
;
i
<
p_client
->
i_items
;
i
++
)
{
rtcp_SDES_item_t
*
p_old
=
p_client
->
pp_sdes
[
i
];
REMOVE_ELEM
(
p_client
->
pp_sdes
,
p_client
->
i_items
,
i
);
p_client
->
i_items
--
;
free
(
p_old
->
psz_data
);
free
(
p_old
);
}
return
VLC_SUCCESS
;
}
int
rtcp_add_client
(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
,
uint32_t
*
i_pos
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
rtcp_client_t
*
p_client
=
NULL
;
vlc_object_lock
(
p_rtcp
);
p_client
=
(
rtcp_client_t
*
)
malloc
(
sizeof
(
rtcp_client_t
)
);
if
(
!
p_client
)
return
VLC_ENOMEM
;
p_client
->
i_index
=
p_rtcp
->
i_clients
+
1
;
p_client
->
b_deleted
=
false
;
*
i_pos
=
p_client
->
i_index
;
INSERT_ELEM
(
p_rtcp
->
pp_clients
,
p_rtcp
->
i_clients
,
p_client
->
i_index
,
p_client
);
p_rtcp
->
i_clients
++
;
p_rtcp
->
u_clients
++
;
vlc_object_unlock
(
p_rtcp
);
return
VLC_SUCCESS
;
}
int
rtcp_del_client
(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
uint32_t
i_pos
=
0
;
vlc_object_lock
(
p_rtcp
);
if
(
p_rtcp
->
pf_find_client
(
p_this
,
u_ssrc
,
&
i_pos
)
==
VLC_SUCCESS
)
{
rtcp_client_t
*
p_old
=
p_rtcp
->
pp_clients
[
i_pos
];
p_old
->
b_deleted
=
true
;
p_old
->
i_timeout
=
5
*
(
p_rtcp
->
i_date
-
p_rtcp
->
i_last_date
)
+
p_rtcp
->
i_next_date
;
p_rtcp
->
u_clients
--
;
/* BYE message is sent by rtcp_destroy_client() */
}
vlc_object_unlock
(
p_rtcp
);
return
VLC_SUCCESS
;
}
/* rtcp_cleanup_clients should not be called too often */
int
rtcp_cleanup_clients
(
vlc_object_t
*
p_this
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
uint32_t
i
=
0
;
vlc_object_lock
(
p_rtcp
);
for
(
i
=
0
;
i
<
p_rtcp
->
i_clients
;
i
++
)
{
rtcp_client_t
*
p_old
=
p_rtcp
->
pp_clients
[
i
];
if
(
p_old
->
b_deleted
&&
(
p_old
->
i_timeout
>
mdate
())
)
{
REMOVE_ELEM
(
p_rtcp
->
pp_clients
,
p_rtcp
->
i_clients
,
i
);
p_rtcp
->
i_clients
--
;
SDES_client_item_del
(
p_old
);
free
(
p_old
);
}
}
vlc_object_unlock
(
p_rtcp
);
return
VLC_SUCCESS
;
}
/* Close communication with clients and release allocated objects */
int
rtcp_destroy_clients
(
vlc_object_t
*
p_this
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
uint32_t
i
=
0
;
for
(
i
=
0
;
i
<
p_rtcp
->
i_clients
;
i
++
)
{
rtcp_pkt_t
*
pkt
=
NULL
;
rtcp_client_t
*
p_old
=
p_rtcp
->
pp_clients
[
i
];
p_rtcp
->
pf_del_client
(
p_this
,
p_old
->
u_ssrc
);
pkt
=
rtcp_pkt_new
(
p_this
,
RTCP_BYE
);
if
(
pkt
)
{
block_t
*
p_block
=
NULL
;
p_block
=
rtcp_encode_BYE
(
p_this
,
pkt
,
strdup
(
"server is leaving"
)
);
/* FIXME:
* if( p_block )
* send_RTCP( p_this, p_block );
*/
}
}
/* wait till all clients have been signalled */
while
(
p_rtcp
->
i_clients
!=
0
)
{
p_rtcp
->
pf_cleanup_clients
(
p_this
);
msleep
(
500
);
}
return
VLC_SUCCESS
;
}
/* rtcp_find_client should be called with the object lock held.
* vlc_mutex_lock( &p_rtcp->obj_lock );
*/
int
rtcp_find_client
(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
,
uint32_t
*
i_pos
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
uint32_t
i
=
0
;
for
(
i
=
0
;
i
<
p_rtcp
->
i_clients
;
i
++
)
{
if
(
p_rtcp
->
pp_clients
[
i
]
->
u_ssrc
==
u_ssrc
)
{
*
i_pos
=
i
;
return
VLC_SUCCESS
;
}
}
*
i_pos
=
-
1
;
return
VLC_EGENERIC
;
}
/*--------------------------------------------------------------------------
* rtcp_interval - Calculate the interval in seconds for sending RTCP packets.
*--------------------------------------------------------------------------
*/
uint64_t
rtcp_interval
(
vlc_object_t
*
p_this
,
uint64_t
u_bandwidth
,
uint32_t
u_ssrc
,
bool
b_sender
,
bool
b_first
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
rtcp_client_t
*
p_client
=
NULL
;
uint32_t
i_rtcp_min
=
5
;
/* seconds */
uint32_t
i_pos
=
0
;
double
i_bandwidth
=
u_bandwidth
;
const
double
i_compensation
=
2
.
71828
-
1
.
5
;
double
i_interval
=
0
;
int
n
=
p_rtcp
->
i_clients
;
if
(
b_first
)
i_rtcp_min
=
(
i_rtcp_min
>>
1
);
if
(
(
double
)(
p_rtcp
->
u_active
)
<=
(
double
)(
p_rtcp
->
u_clients
*
0
.
25
)
)
{
if
(
b_sender
)
{
i_bandwidth
=
i_bandwidth
*
0
.
25
;
n
=
p_rtcp
->
u_active
;
}
else
{
i_bandwidth
=
i_bandwidth
*
(
1
-
0
.
25
);
n
=
n
-
p_rtcp
->
u_active
;
}
}
/* calculate average time between reports */
p_client
=
p_rtcp
->
pf_find_client
(
p_this
,
u_ssrc
,
&
i_pos
);
if
(
!
p_client
)
return
-
1
;
i_interval
=
p_client
->
p_stats
->
u_avg_pkt_size
*
(
n
/
i_bandwidth
);
if
(
i_interval
<
i_rtcp_min
)
i_interval
=
i_rtcp_min
;
i_interval
=
i_interval
*
(
drand48
()
+
0
.
5
);
i_interval
=
(
double
)
(
i_interval
/
i_compensation
);
return
(
uint64_t
)
i_interval
;
}
/*--------------------------------------------------------------------------
* rtcp_expire - decides to sent an RTCP report or a BYE record
*--------------------------------------------------------------------------
*/
void
rtcp_expire
(
vlc_object_t
*
p_this
,
rtcp_event_t
rtcp_event
,
uint64_t
u_bandwidth
,
uint32_t
u_ssrc
,
bool
b_sender
,
bool
*
b_first
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
rtcp_client_t
*
p_client
=
NULL
;
rtcp_stats_t
*
p_stats
=
NULL
;
mtime_t
i_interval
=
0
;
uint32_t
i_pos
=
0
;
p_client
=
p_rtcp
->
pf_find_client
(
p_this
,
u_ssrc
,
&
i_pos
);
if
(
!
p_client
)
return
;
p_stats
=
(
rtcp_stats_t
*
)
p_client
->
p_stats
;
i_interval
=
(
mtime_t
)
rtcp_interval
(
p_this
,
u_bandwidth
,
u_ssrc
,
b_sender
,
*
b_first
);
p_rtcp
->
i_next_date
=
p_rtcp
->
i_last_date
+
i_interval
;
switch
(
rtcp_event
)
{
case
EVENT_BYE
:
if
(
p_rtcp
->
i_next_date
<=
p_rtcp
->
i_date
)
send_RTCP
(
p_this
,
rtcp_event
);
else
rtcp_schedule
(
p_this
,
p_rtcp
->
i_next_date
,
rtcp_event
);
break
;
case
EVENT_REPORT
:
if
(
p_rtcp
->
i_next_date
<=
p_rtcp
->
i_date
)
{
send_RTCP
(
p_this
,
rtcp_event
);
/* Magic numbers are from RFC 3550 page 92
* 1.0/16.0 = 0.0625 and
* 15.0/16.0 = 0.9375
*/
p_stats
->
u_avg_pkt_size
=
(
uint64_t
)
(
(
double
)
(
(
double
)
p_stats
->
u_sent_pkt_size
/
((
double
)
0
.
0625
)
)
+
(
((
double
)
0
.
9357
)
*
p_stats
->
u_avg_pkt_size
)
);
/* recalculate */
p_rtcp
->
i_last_date
=
p_rtcp
->
i_date
;
i_interval
=
rtcp_interval
(
p_this
,
u_bandwidth
,
u_ssrc
,
b_sender
,
*
b_first
);
rtcp_schedule
(
p_this
,
p_rtcp
->
i_next_date
+
i_interval
,
rtcp_event
);
*
b_first
=
false
;
}
else
{
rtcp_schedule
(
p_this
,
p_rtcp
->
i_next_date
,
rtcp_event
);
}
break
;
}
p_rtcp
->
i_date
=
p_rtcp
->
i_next_date
;
}
/*--------------------------------------------------------------------------
* Local functions prototoypes
*--------------------------------------------------------------------------
*/
static
int
rtcp_decode_SR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
static
int
rtcp_decode_RR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
static
int
rtcp_decode_SR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
static
int
rtcp_decode_SDES
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
static
int
rtcp_decode_BYE
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
static
int
rtcp_decode_APP
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
/*--------------------------------------------------------------------------
* Local functions
*--------------------------------------------------------------------------
*/
static
int
rtcp_decode_SR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
unsigned
int
i
=
0
;
if
(
!
p_pkt
)
return
VLC_EGENERIC
;
msg_Dbg
(
p_this
,
"decoding record: SR"
);
/* parse sender info */
p_pkt
->
u_payload_type
=
RTCP_SR
;
p_pkt
->
report
.
sr
.
ntp_timestampH
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_pkt
->
report
.
sr
.
ntp_timestampL
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_pkt
->
report
.
sr
.
rtp_timestamp
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_pkt
->
report
.
sr
.
u_pkt_count
=
bs_read
(
p_rtcp
->
bs
,
32
);
/*sender*/
p_pkt
->
report
.
sr
.
u_octet_count
=
bs_read
(
p_rtcp
->
bs
,
32
);
/*sender*/
/* parse report block */
for
(
i
=
0
;
i
<
p_pkt
->
u_report
;
i
++
)
{
rtcp_client_t
*
p_client
=
NULL
;
uint32_t
i_pos
=
0
;
uint32_t
u_ssrc
=
0
;
u_ssrc
=
bs_read
(
p_rtcp
->
bs
,
32
);
if
(
p_rtcp
->
pf_find_client
(
p_this
,
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
{
if
(
p_rtcp
->
pf_add_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
return
VLC_ENOMEM
;
}
vlc_object_lock
(
p_rtcp
);
p_client
=
p_rtcp
->
pp_clients
[
i_pos
];
p_client
->
p_stats
->
u_SR_received
++
;
p_client
->
p_stats
->
u_pkt_count
++
;
p_client
->
p_stats
->
u_octet_count
++
;
msg_Dbg
(
p_this
,
"SR received %d, packet count %d, octect count %d, SSRC count %d"
,
p_client
->
p_stats
->
u_SR_received
,
p_client
->
p_stats
->
u_pkt_count
,
p_client
->
p_stats
->
u_octet_count
,
p_pkt
->
u_ssrc
);
p_client
->
p_stats
->
u_fraction_lost
=
bs_read
(
p_rtcp
->
bs
,
8
);
p_client
->
p_stats
->
u_pkt_lost
=
bs_read
(
p_rtcp
->
bs
,
24
);
p_client
->
p_stats
->
u_highest_seq_no
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_client
->
p_stats
->
u_jitter
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_client
->
p_stats
->
u_last_SR
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_client
->
p_stats
->
u_delay_since_last_SR
=
(
mtime_t
)
bs_read
(
p_rtcp
->
bs
,
32
);
/* Magic numbers are from RFC 3550 page 92
* 1.0/16.0 = 0.0625 and
* 15.0/16.0 = 0.9375
*/
p_client
->
p_stats
->
u_avg_pkt_size
=
(
uint64_t
)
(
(
double
)((
double
)
p_client
->
p_stats
->
u_sent_pkt_size
*
(
double
)(
0
.
0625
))
+
((
double
)(
0
.
9375
)
*
p_client
->
p_stats
->
u_avg_pkt_size
)
);
msg_Dbg
(
p_this
,
"fract lost %d, packet lost %d, highest seqno %d, "
"jitter %d, last SR %d, delay %lld"
,
p_client
->
p_stats
->
u_fraction_lost
,
p_client
->
p_stats
->
u_pkt_lost
,
p_client
->
p_stats
->
u_highest_seq_no
,
p_client
->
p_stats
->
u_jitter
,
p_client
->
p_stats
->
u_last_SR
,
p_client
->
p_stats
->
u_delay_since_last_SR
);
p_client
=
NULL
;
vlc_object_unlock
(
p_rtcp
);
}
return
VLC_SUCCESS
;
}
static
int
rtcp_decode_RR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
unsigned
int
i
=
0
;
if
(
!
p_pkt
)
return
VLC_EGENERIC
;
msg_Dbg
(
p_this
,
"decoding record: RR"
);
for
(
i
=
0
;
i
<
p_pkt
->
u_report
;
i
++
)
{
rtcp_client_t
*
p_client
=
NULL
;
uint32_t
i_pos
=
0
;
uint32_t
u_ssrc
=
0
;
u_ssrc
=
bs_read
(
p_rtcp
->
bs
,
32
);
if
(
p_rtcp
->
pf_find_client
(
p_this
,
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
{
if
(
p_rtcp
->
pf_add_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
return
VLC_ENOMEM
;
}
vlc_object_lock
(
p_rtcp
);
p_client
=
p_rtcp
->
pp_clients
[
i_pos
];
p_client
->
p_stats
->
u_RR_received
++
;
msg_Dbg
(
p_this
,
"RR received %d, SSRC %d"
,
p_client
->
p_stats
->
u_RR_received
,
u_ssrc
);
p_client
->
p_stats
->
u_fraction_lost
=
bs_read
(
p_rtcp
->
bs
,
8
);
p_client
->
p_stats
->
u_pkt_lost
=
bs_read
(
p_rtcp
->
bs
,
24
);
p_client
->
p_stats
->
u_highest_seq_no
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_client
->
p_stats
->
u_jitter
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_client
->
p_stats
->
u_last_SR
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_client
->
p_stats
->
u_delay_since_last_SR
=
(
mtime_t
)
bs_read
(
p_rtcp
->
bs
,
32
);
/* Magic numbers are from RFC 3550 page 92
* 1.0/16.0 = 0.0625 and
* 15.0/16.0 = 0.9375
*/
p_client
->
p_stats
->
u_avg_pkt_size
=
(
uint64_t
)
(
(
double
)((
double
)
p_client
->
p_stats
->
u_sent_pkt_size
*
(
double
)(
0
.
0625
))
+
((
double
)(
0
.
9375
)
*
p_client
->
p_stats
->
u_avg_pkt_size
)
);
msg_Dbg
(
p_this
,
"fract lost %d, packet lost %d, highest seqno %d, "
"jitter %d, last SR %d, delay %lld"
,
p_client
->
p_stats
->
u_fraction_lost
,
p_client
->
p_stats
->
u_pkt_lost
,
p_client
->
p_stats
->
u_highest_seq_no
,
p_client
->
p_stats
->
u_jitter
,
p_client
->
p_stats
->
u_last_SR
,
p_client
->
p_stats
->
u_delay_since_last_SR
);
p_client
=
NULL
;
vlc_object_unlock
(
p_rtcp
);
}
return
VLC_SUCCESS
;
}
static
int
rtcp_decode_SDES
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
unsigned
int
i
=
0
;
if
(
!
p_pkt
)
return
VLC_EGENERIC
;
msg_Dbg
(
p_this
,
"decoding record: SDES"
);
for
(
i
=
0
;
i
<
p_pkt
->
u_report
;
i
++
)
{
rtcp_client_t
*
p_client
=
NULL
;
uint32_t
i_pos
=
0
;
uint32_t
u_ssrc
=
0
;
uint8_t
u_item
=
0
;
uint8_t
u_length
=
0
;
int
i
=
0
;
u_ssrc
=
bs_read
(
p_rtcp
->
bs
,
32
);
if
(
p_rtcp
->
pf_find_client
(
p_this
,
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
{
if
(
p_rtcp
->
pf_add_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
return
VLC_ENOMEM
;
}
vlc_object_lock
(
p_rtcp
);
p_client
=
p_rtcp
->
pp_clients
[
i_pos
];
u_item
=
bs_read
(
p_rtcp
->
bs
,
8
);
switch
(
u_item
)
{
case
RTCP_SDES_CNAME
:
case
RTCP_SDES_NAME
:
case
RTCP_SDES_EMAIL
:
case
RTCP_SDES_PHONE
:
case
RTCP_SDES_LOC
:
case
RTCP_SDES_TOOL
:
case
RTCP_SDES_NOTE
:
{
char
psz_name
[
255
];
u_length
=
bs_read
(
p_rtcp
->
bs
,
8
);
for
(
i
=
0
;
i
<
u_length
;
i
++
)
{
psz_name
[
i
]
=
bs_read
(
p_rtcp
->
bs
,
8
);
}
SDES_client_item_add
(
p_client
,
u_item
,
psz_name
);
}
break
;
case
RTCP_SDES_PRIV
:
/* ignoring these */
{
uint8_t
u_prefix_len
=
0
;
uint8_t
u_length
=
0
;
char
psz_prefix_name
[
255
];
char
psz_name
[
255
];
u_length
=
bs_read
(
p_rtcp
->
bs
,
8
);
u_prefix_len
=
bs_read
(
p_rtcp
->
bs
,
8
);
if
(
u_prefix_len
>
254
)
u_prefix_len
=
254
;
for
(
i
=
0
;
i
<
u_prefix_len
;
i
++
)
{
psz_prefix_name
[
i
]
=
bs_read
(
p_rtcp
->
bs
,
8
);
}
psz_prefix_name
[
255
]
=
'\0'
;
SDES_client_item_add
(
p_client
,
u_item
,
psz_prefix_name
);
for
(
i
=
0
;
i
<
u_length
;
i
++
)
{
psz_name
[
i
]
=
bs_read
(
p_rtcp
->
bs
,
8
);
}
psz_name
[
255
]
=
'\0'
;
SDES_client_item_add
(
p_client
,
u_item
,
psz_name
);
}
break
;
default:
return
VLC_EGENERIC
;
}
/* Magic numbers are from RFC 3550 page 92
* 1.0/16.0 = 0.0625 and
* 15.0/16.0 = 0.9375
*/
p_client
->
p_stats
->
u_avg_pkt_size
=
(
uint64_t
)
(
(
double
)((
double
)
p_client
->
p_stats
->
u_sent_pkt_size
*
(
double
)(
0
.
0625
))
+
((
double
)(
0
.
9375
)
*
p_client
->
p_stats
->
u_avg_pkt_size
)
);
p_client
=
NULL
;
vlc_object_unlock
(
p_rtcp
);
}
return
VLC_SUCCESS
;
}
static
int
rtcp_decode_BYE
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
uint32_t
u_ssrc
=
0
;
uint8_t
u_length
=
0
;
int
i
=
0
;
if
(
!
p_pkt
)
return
VLC_EGENERIC
;
msg_Dbg
(
p_this
,
"decoding record: BYE"
);
u_ssrc
=
bs_read
(
p_rtcp
->
bs
,
32
);
p_rtcp
->
pf_del_client
(
p_this
,
u_ssrc
);
u_length
=
p_pkt
->
u_length
-
1
;
for
(
i
=
0
;
i
<
u_length
;
i
++
)
{
u_ssrc
=
bs_read
(
p_rtcp
->
bs
,
8
);
p_rtcp
->
pf_del_client
(
p_this
,
u_ssrc
);
}
return
VLC_SUCCESS
;
}
static
int
rtcp_decode_APP
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
rtcp_client_t
*
p_client
=
NULL
;
char
psz_name
[
4
];
char
*
psz_data
=
NULL
;
uint32_t
u_ssrc
=
0
;
uint32_t
i_pos
=
0
;
uint32_t
i
=
0
;
if
(
!
p_pkt
)
return
VLC_EGENERIC
;
msg_Dbg
(
p_this
,
"decoding record: APP"
);
u_ssrc
=
bs_read
(
p_rtcp
->
bs
,
32
);
if
(
p_rtcp
->
pf_find_client
(
p_this
,
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
{
if
(
p_rtcp
->
pf_add_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
return
VLC_ENOMEM
;
}
vlc_object_lock
(
p_rtcp
);
p_client
=
p_rtcp
->
pp_clients
[
i_pos
];
for
(
i
=
0
;
i
<
4
;
i
++
)
{
psz_name
[
i
]
=
bs_read
(
p_rtcp
->
bs
,
8
);
}
psz_name
[
4
]
=
'\0'
;
p_pkt
->
u_payload_type
=
RTCP_APP
;
p_pkt
->
report
.
app
.
psz_prefix
=
strdup
(
psz_name
);
p_pkt
->
report
.
app
.
u_prefix_len
=
4
;
p_pkt
->
u_length
-=
4
;
psz_data
=
(
char
*
)
malloc
(
p_pkt
->
u_length
);
if
(
!
psz_data
)
{
vlc_object_unlock
(
p_rtcp
);
return
VLC_EGENERIC
;
}
for
(
i
=
0
;
i
<
p_pkt
->
u_length
;
i
--
)
{
psz_data
[
i
]
=
bs_read
(
p_rtcp
->
bs
,
8
);
}
psz_data
[
p_pkt
->
u_length
]
=
'\0'
;
p_pkt
->
report
.
app
.
psz_data
=
strdup
(
psz_data
);
p_pkt
->
report
.
app
.
u_length
=
p_pkt
->
u_length
;
p_client
=
NULL
;
vlc_object_unlock
(
p_rtcp
);
/* Just ignore this packet */
return
VLC_SUCCESS
;
}
/* Decode RTCP packet
* Decode incoming RTCP packet and inspect the records types.
*/
int
rtcp_pkt_decode
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
,
block_t
*
p_block
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
if
(
!
p_pkt
&&
!
p_block
)
return
VLC_EGENERIC
;
bs_init
(
p_rtcp
->
bs
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
p_pkt
->
u_version
=
bs_read
(
p_rtcp
->
bs
,
2
);
p_pkt
->
b_padding
=
bs_read
(
p_rtcp
->
bs
,
1
)
?
true
:
false
;
p_pkt
->
u_report
=
bs_read
(
p_rtcp
->
bs
,
5
);
p_pkt
->
u_payload_type
=
bs_read
(
p_rtcp
->
bs
,
8
);
p_pkt
->
u_length
=
bs_read
(
p_rtcp
->
bs
,
16
);
if
(
p_pkt
->
u_payload_type
!=
RTCP_SDES
)
p_pkt
->
u_ssrc
=
bs_read
(
p_rtcp
->
bs
,
32
);
msg_Dbg
(
p_this
,
"New RTCP packet: version %d, padding %s, count %d, "
"type %d, length %d, SSRC %d"
,
p_pkt
->
u_version
,
p_pkt
->
b_padding
?
"true"
:
"false"
,
p_pkt
->
u_report
,
p_pkt
->
u_payload_type
,
p_pkt
->
u_length
,
p_pkt
->
u_ssrc
);
while
(
!
bs_eof
(
p_rtcp
->
bs
)
)
{
uint32_t
i_pos
=
0
;
switch
(
p_pkt
->
u_payload_type
)
{
case
RTCP_SR
:
if
(
p_rtcp
->
pf_find_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
p_rtcp
->
pf_add_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
);
rtcp_decode_SR
(
p_this
,
p_pkt
);
break
;
case
RTCP_RR
:
if
(
p_rtcp
->
pf_find_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
p_rtcp
->
pf_add_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
);
rtcp_decode_RR
(
p_this
,
p_pkt
);
break
;
case
RTCP_SDES
:
if
(
p_rtcp
->
pf_find_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
p_rtcp
->
pf_add_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
);
rtcp_decode_SDES
(
p_this
,
p_pkt
);
break
;
case
RTCP_BYE
:
rtcp_decode_BYE
(
p_this
,
p_pkt
);
#if 0
if( p_rtcp->pf_find_sender( p_this, pkt->u_ssrc, &i_pos ) == VLC_EGENERIC )
p_rtcp->pf_del_sender( p_this, p_pkt->u_ssrc );
#endif
if
(
p_rtcp
->
pf_find_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
p_rtcp
->
pf_del_client
(
p_this
,
p_pkt
->
u_ssrc
);
if
(
p_rtcp
->
u_active
<
p_rtcp
->
u_members
)
{
rtcp_event_t
event
=
EVENT_BYE
;
p_rtcp
->
i_next_date
=
p_rtcp
->
i_date
+
(
mtime_t
)
(
(
p_rtcp
->
u_active
/
p_rtcp
->
u_members
)
*
(
p_rtcp
->
i_next_date
-
p_rtcp
->
i_date
)
);
p_rtcp
->
i_last_date
=
p_rtcp
->
i_date
-
(
mtime_t
)
(
(
mtime_t
)(
p_rtcp
->
u_active
/
p_rtcp
->
u_members
)
*
(
p_rtcp
->
i_date
-
p_rtcp
->
i_last_date
)
);
/* schedule for next period */
rtcp_schedule
(
VLC_OBJECT
(
p_rtcp
),
p_rtcp
->
i_next_date
,
event
);
p_rtcp
->
u_members
=
p_rtcp
->
u_active
;
}
else
p_rtcp
->
u_members
++
;
break
;
case
RTCP_APP
:
if
(
p_rtcp
->
pf_find_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
p_rtcp
->
pf_add_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
);
rtcp_decode_APP
(
p_this
,
p_pkt
);
break
;
default:
return
VLC_EGENERIC
;
}
}
return
VLC_SUCCESS
;
}
/*
* Create RTCP records for reporting to server.
*/
rtcp_pkt_t
*
rtcp_pkt_new
(
vlc_object_t
*
p_this
,
int
type
)
{
rtcp_pkt_t
*
p_pkt
=
NULL
;
p_pkt
=
(
rtcp_pkt_t
*
)
malloc
(
sizeof
(
rtcp_pkt_t
)
);
if
(
!
p_pkt
)
return
NULL
;
memset
(
p_pkt
,
0
,
sizeof
(
rtcp_pkt_t
)
);
p_pkt
->
u_version
=
2
;
p_pkt
->
u_payload_type
=
type
;
p_pkt
->
u_length
=
RTCP_HEADER_LEN
;
switch
(
type
)
{
case
RTCP_SR
:
p_pkt
->
u_length
+=
sizeof
(
rtcp_SR_t
);
break
;
case
RTCP_RR
:
p_pkt
->
u_length
+=
sizeof
(
rtcp_RR_t
);
break
;
case
RTCP_SDES
:
p_pkt
->
u_length
+=
sizeof
(
rtcp_SDES_t
);
if
(
p_pkt
->
report
.
sdes
.
pp_items
)
p_pkt
->
u_length
+=
p_pkt
->
report
.
sdes
.
u_items
;
break
;
case
RTCP_BYE
:
p_pkt
->
u_length
+=
sizeof
(
rtcp_BYE_t
);
break
;
case
RTCP_APP
:
p_pkt
->
u_length
+=
sizeof
(
rtcp_APP_t
);
break
;
default:
free
(
p_pkt
);
return
NULL
;
}
return
p_pkt
;
}
void
rtcp_pkt_del
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
if
(
!
p_pkt
)
return
;
switch
(
p_pkt
->
u_payload_type
)
{
case
RTCP_SR
:
case
RTCP_RR
:
break
;
case
RTCP_SDES
:
if
(
p_pkt
->
report
.
sdes
.
pp_items
)
{
uint32_t
i
=
0
;
for
(
i
=
0
;
i
<
p_pkt
->
report
.
sdes
.
u_items
;
i
++
)
{
rtcp_SDES_item_t
*
p_old
=
p_pkt
->
report
.
sdes
.
pp_items
[
i
];
REMOVE_ELEM
(
p_pkt
->
report
.
sdes
.
pp_items
,
p_pkt
->
report
.
sdes
.
u_items
,
i
);
p_pkt
->
report
.
sdes
.
u_items
--
;
if
(
p_old
->
psz_data
)
free
(
p_old
->
psz_data
);
free
(
p_old
);
}
}
break
;
case
RTCP_BYE
:
break
;
case
RTCP_APP
:
if
(
p_pkt
->
report
.
app
.
psz_prefix
)
free
(
p_pkt
->
report
.
app
.
psz_prefix
);
if
(
p_pkt
->
report
.
app
.
psz_data
)
free
(
p_pkt
->
report
.
app
.
psz_data
);
break
;
default:
msg_Err
(
p_this
,
"unknown RTCP packet type %d: "
"possible leaking of memory."
,
p_pkt
->
u_payload_type
);
break
;
}
free
(
p_pkt
);
}
block_t
*
rtcp_encode_SR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
mtime_t
ntp_time
;
bs_t
bits
,
*
s
=
&
bits
;
block_t
*
p_block
=
NULL
;
rtcp_stats_t
*
p_stats
=
NULL
;
rtcp_client_t
*
p_client
=
NULL
;
uint32_t
i_pos
=
0
;
if
(
p_pkt
->
u_payload_type
!=
RTCP_SR
)
return
NULL
;
/* FIXME: Maybe this should be a buffer pool instead */
p_block
=
block_New
(
p_this
,
p_pkt
->
u_length
);
if
(
!
p_block
)
return
NULL
;
bs_init
(
s
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
/* Fill in header */
bs_write
(
s
,
2
,
p_pkt
->
u_version
);
bs_write
(
s
,
1
,
0
);
/* padding */
bs_write
(
s
,
5
,
p_pkt
->
u_report
);
bs_write
(
s
,
8
,
p_pkt
->
u_payload_type
);
bs_write
(
s
,
16
,
p_pkt
->
u_length
);
bs_write
(
s
,
32
,
p_pkt
->
u_ssrc
);
/* sender info */
ntp_time
=
mdate
();
bs_write
(
s
,
32
,
((
unsigned
int
)(
ntp_time
>>
32
))
);
/* ntp_timestampH */
bs_write
(
s
,
32
,
((
unsigned
int
)
ntp_time
)
);
/* ntp_timestampL */
/* FIXME: Make sure to generate a good RTP server timestamp.
p_pkt->report.sr.rtp_timestamp = htonl(
(unsigned int) ((double)ntp_time.tv_sec +
(double)ntp_time.tv_usec/1000000.) * p_mux->rate
+ session->start_rtptime ); */
bs_write
(
s
,
32
,
p_pkt
->
report
.
sr
.
rtp_timestamp
);
bs_write
(
s
,
32
,
p_pkt
->
report
.
sr
.
u_pkt_count
);
bs_write
(
s
,
32
,
p_pkt
->
report
.
sr
.
u_octet_count
);
/* report block */
if
(
p_rtcp
->
pf_find_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
{
msg_Err
(
p_this
,
"SR: SSRC identifier doesn't exists"
,
p_pkt
->
u_ssrc
);
free
(
p_block
);
return
NULL
;
}
vlc_object_lock
(
p_rtcp
);
p_client
=
p_rtcp
->
pp_clients
[
i_pos
];
p_stats
=
p_client
->
p_stats
;
if
(
!
p_stats
)
{
msg_Err
(
p_this
,
"SR: SSRC identifier doesn't exists"
,
p_pkt
->
u_ssrc
);
free
(
p_block
);
return
NULL
;
}
bs_write
(
s
,
32
,
p_stats
->
l_dest_SSRC
);
bs_write
(
s
,
8
,
p_stats
->
u_fraction_lost
);
bs_write
(
s
,
24
,
p_stats
->
u_pkt_lost
);
bs_write
(
s
,
32
,
p_stats
->
u_highest_seq_no
);
bs_write
(
s
,
32
,
p_stats
->
u_jitter
);
bs_write
(
s
,
32
,
p_stats
->
u_last_SR
);
bs_write
(
s
,
32
,
p_stats
->
u_delay_since_last_SR
);
p_client
=
NULL
;
vlc_object_unlock
(
p_rtcp
);
/* possible SR extension */
return
p_block
;
}
block_t
*
rtcp_encode_RR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
rtcp_t
*
p_rtcp
=
(
rtcp_t
*
)
p_this
;
bs_t
bits
,
*
s
=
&
bits
;
block_t
*
p_block
=
NULL
;
rtcp_stats_t
*
p_stats
=
NULL
;
rtcp_client_t
*
p_client
=
NULL
;
uint32_t
i_pos
=
0
;
if
(
p_pkt
->
u_payload_type
!=
RTCP_RR
)
return
NULL
;
/* FIXME: Maybe this should be a buffer pool instead */
p_block
=
block_New
(
p_this
,
p_pkt
->
u_length
);
if
(
!
p_block
)
return
NULL
;
bs_init
(
s
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
/* Fill in header */
bs_write
(
s
,
2
,
p_pkt
->
u_version
);
bs_write
(
s
,
1
,
0
);
/* padding */
bs_write
(
s
,
5
,
p_pkt
->
u_report
);
bs_write
(
s
,
8
,
p_pkt
->
u_payload_type
);
bs_write
(
s
,
16
,
p_pkt
->
u_length
);
bs_write
(
s
,
32
,
p_pkt
->
u_ssrc
);
/* report block */
if
(
p_rtcp
->
pf_find_client
(
p_this
,
p_pkt
->
u_ssrc
,
&
i_pos
)
==
VLC_EGENERIC
)
{
msg_Err
(
p_this
,
"RR: SSRC identifier doesn't exists"
,
p_pkt
->
u_ssrc
);
free
(
p_block
);
return
NULL
;
}
vlc_object_lock
(
p_rtcp
);
p_client
=
p_rtcp
->
pp_clients
[
i_pos
];
p_stats
=
p_client
->
p_stats
;
if
(
!
p_stats
)
{
msg_Err
(
p_this
,
"RR: SSRC identifier doesn't exists"
,
p_pkt
->
u_ssrc
);
free
(
p_block
);
return
NULL
;
}
bs_write
(
s
,
32
,
p_stats
->
l_dest_SSRC
);
bs_write
(
s
,
8
,
p_stats
->
u_fraction_lost
);
bs_write
(
s
,
24
,
p_stats
->
u_pkt_lost
);
bs_write
(
s
,
32
,
p_stats
->
u_highest_seq_no
);
bs_write
(
s
,
32
,
p_stats
->
u_jitter
);
bs_write
(
s
,
32
,
p_stats
->
u_last_RR
);
bs_write
(
s
,
32
,
p_stats
->
u_delay_since_last_RR
);
p_client
=
NULL
;
vlc_object_unlock
(
p_rtcp
);
/* possible RR extension */
return
p_block
;
}
block_t
*
rtcp_encode_SDES
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
)
{
bs_t
bits
,
*
s
=
&
bits
;
block_t
*
p_block
=
NULL
;
uint32_t
i_chunks
;
if
(
p_pkt
->
u_payload_type
!=
RTCP_SDES
)
return
NULL
;
/* FIXME: Maybe this should be a buffer pool instead */
p_block
=
block_New
(
p_this
,
p_pkt
->
u_length
);
if
(
!
p_block
)
return
NULL
;
bs_init
(
s
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
/* Fill in header */
bs_write
(
s
,
2
,
p_pkt
->
u_version
);
bs_write
(
s
,
1
,
0
);
/* padding */
bs_write
(
s
,
5
,
p_pkt
->
u_report
);
/* Number of SSRC/CSRC chunks */
bs_write
(
s
,
8
,
p_pkt
->
u_payload_type
);
bs_write
(
s
,
16
,
p_pkt
->
u_length
);
bs_write
(
s
,
32
,
p_pkt
->
u_ssrc
);
/* fill in record */
for
(
i_chunks
=
0
;
i_chunks
<
p_pkt
->
u_report
;
i_chunks
++
)
{
uint32_t
i_item
;
for
(
i_item
=
0
;
i_item
<
p_pkt
->
report
.
sdes
.
u_items
;
i_item
++
)
{
uint32_t
i_count
=
strlen
(
p_pkt
->
report
.
sdes
.
pp_items
[
i_item
]
->
psz_data
);
uint8_t
u_octet
=
i_count
/
8
;
/* Octect count ??*/
rtcp_SDES_item_t
*
p_item
=
p_pkt
->
report
.
sdes
.
pp_items
[
i_item
];
uint32_t
i_pos
,
i_pad
,
i_padding
;
bs_write
(
s
,
8
,
p_item
->
u_type
);
bs_write
(
s
,
8
,
u_octet
);
for
(
i_pos
=
0
;
i_pos
<
i_count
;
i_pos
++
)
{
/* FIXME: must be UTF 8 encoded */
bs_write
(
s
,
8
,
p_item
->
psz_data
[
i_pos
]
);
}
/* do we need padding to 32 bit boundary? */
i_padding
=
0
;
if
(
((
i_count
+
2
)
%
4
)
!=
0
)
i_padding
=
(
i_count
+
2
)
-
(((
i_count
+
2
)
%
4
)
<<
2
);
for
(
i_pad
=
0
;
i_pad
<
i_padding
;
i_pad
++
)
{
bs_write
(
s
,
8
,
0
);
}
}
}
return
p_block
;
}
block_t
*
rtcp_encode_BYE
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
,
char
*
psz_reason
)
{
bs_t
bits
,
*
s
=
&
bits
;
block_t
*
p_block
=
NULL
;
uint32_t
i_count
=
strlen
(
psz_reason
);
uint8_t
u_octet
=
i_count
/
8
;
/* Octect count ??*/
int32_t
i_pos
,
i_pad
,
i_padding
;
if
(
p_pkt
->
u_payload_type
!=
RTCP_BYE
)
return
NULL
;
/* FIXME: Maybe this should be a buffer pool instead */
p_block
=
block_New
(
p_this
,
p_pkt
->
u_length
);
if
(
!
p_block
)
return
NULL
;
bs_init
(
s
,
p_block
->
p_buffer
,
p_block
->
i_buffer
);
/* Fill in header */
bs_write
(
s
,
2
,
p_pkt
->
u_version
);
bs_write
(
s
,
1
,
0
);
/* padding */
bs_write
(
s
,
5
,
p_pkt
->
u_report
);
/* Number of SSRC/CSRC chunks */
bs_write
(
s
,
8
,
p_pkt
->
u_payload_type
);
bs_write
(
s
,
16
,
p_pkt
->
u_length
);
bs_write
(
s
,
32
,
p_pkt
->
u_ssrc
);
/* Give reason for leaving */
//FIXME: bs_write( s, 8, p_item->u_type );
bs_write
(
s
,
8
,
u_octet
);
for
(
i_pos
=
0
;
i_pos
<
i_count
;
i_pos
++
)
{
/* FIXME: must be UTF 8 encoded */
bs_write
(
s
,
8
,
psz_reason
[
i_pos
]
);
}
/* do we need padding to 32 bit boundary? */
i_padding
=
0
;
if
(
((
i_count
+
2
)
%
4
)
!=
0
)
i_padding
=
(
i_count
+
2
)
-
(((
i_count
+
2
)
%
4
)
<<
2
);
for
(
i_pad
=
0
;
i_pad
<
i_padding
;
i_pad
++
)
{
bs_write
(
s
,
8
,
0
);
}
return
p_block
;
}
modules/mux/rtp/rtcp.h
deleted
100644 → 0
View file @
05492281
/*****************************************************************************
* rtcp.h: RTP/RTCP headerfile
*****************************************************************************
* Copyright (C) 2005-2007 M2X
*
* $Id$
*
* Authors: Jean-Paul Saman <jpsaman #_at_# videolan dot org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef _RTCP_H
#define _RTCP_H 1
/* RTCP packet types */
#define RTCP_SR 200
#define RTCP_RR 201
#define RTCP_SDES 202
#define RTCP_BYE 203
#define RTCP_APP 204
/* End of RTCP packet types */
/* SDES type */
#define RTCP_SDES_CNAME 1
#define RTCP_SDES_NAME 2
#define RTCP_SDES_EMAIL 3
#define RTCP_SDES_PHONE 4
#define RTCP_SDES_LOC 5
#define RTCP_SDES_TOOL 6
#define RTCP_SDES_NOTE 7
#define RTCP_SDES_PRIV 8
/* End of SDES type */
#define RTCP_HEADER_LEN 3
typedef
enum
rtcp_event_enum
{
EVENT_BYE
,
EVENT_REPORT
}
rtcp_event_t
;
typedef
struct
{
uint32_t
ntp_timestampH
;
uint32_t
ntp_timestampL
;
uint32_t
rtp_timestamp
;
uint32_t
u_pkt_count
;
uint32_t
u_octet_count
;
}
rtcp_SR_t
;
typedef
struct
{
}
rtcp_RR_t
;
typedef
struct
SDES_item_t
{
uint32_t
i_index
;
/*< index */
uint8_t
u_type
;
/*< type field */
char
*
psz_data
;
/*< null terminated string */
}
rtcp_SDES_item_t
;
typedef
struct
{
uint32_t
u_length
;
/*< length of packet */
uint32_t
u_items
;
/*< number of SDES_items */
rtcp_SDES_item_t
**
pp_items
;
/*< list of SDES_items */
}
rtcp_SDES_t
;
typedef
struct
{
uint32_t
u_length
;
/*< length of packet */
}
rtcp_BYE_t
;
typedef
struct
{
uint32_t
u_length
;
/*< length of packet */
uint32_t
u_prefix_len
;
/*< length of prefix data */
unsigned
char
*
psz_prefix
;
/*< prefix string (null terminated) */
unsigned
char
*
psz_data
;
/*< data string (null terminated) */
}
rtcp_APP_t
;
/**
* structure rtcp_stats_t
*/
typedef
struct
{
uint32_t
u_RR_received
;
/*< RR records received */
uint32_t
u_SR_received
;
/*< SR records received */
uint64_t
l_dest_SSRC
;
/*< SSRC of first source */
uint32_t
u_pkt_count
;
/*< count of packets received */
uint32_t
u_octet_count
;
/*< ? */
uint32_t
u_pkt_lost
;
/*< cumulative count of packets lost */
uint8_t
u_fraction_lost
;
/*< count of fractional packets lost */
uint32_t
u_highest_seq_no
;
/*< highest sequence number found */
uint32_t
u_jitter
;
/*< inter arrival jitter calculated */
uint32_t
u_last_SR
;
/*< last SR record received */
uint32_t
u_last_RR
;
/*< last RR record received */
mtime_t
u_delay_since_last_SR
;
/*< delay since last SR record received */
mtime_t
u_delay_since_last_RR
;
/*< delay since last RR record received */
uint64_t
u_avg_pkt_size
;
/*< average RTCP packet size */
uint64_t
u_sent_pkt_size
;
/*< RTCP packet size sent */
}
rtcp_stats_t
;
typedef
struct
{
uint32_t
u_version
;
/*< RTCP version number */
bool
b_padding
;
/*< indicates if packets has padding */
uint32_t
u_report
;
/*< reception packet count */
uint32_t
u_payload_type
;
/*< type of RTCP payload */
uint32_t
u_length
;
/*< length of packet */
uint32_t
u_ssrc
;
/*< channel name this packet belongs to */
union
{
rtcp_SR_t
sr
;
/*< SR record */
rtcp_RR_t
rr
;
/*< RR record */
rtcp_SDES_t
sdes
;
/*< SDES record */
rtcp_BYE_t
bye
;
/*< BYE record */
rtcp_APP_t
app
;
/*< APP record */
}
report
;
}
rtcp_pkt_t
;
typedef
struct
rtcp_client_t
{
int
fd
;
/*< socket descriptor of rtcp stream */
uint32_t
i_index
;
uint32_t
u_ssrc
;
/*< channel name */
bool
b_deleted
;
/*< channel deleted ? */
mtime_t
i_timeout
;
/*< remove timeout before real deletion,
* this is recommended by RFC 3550 at
* page 27 to ignore out-of-order packets.
*/
rtcp_stats_t
*
p_stats
;
/*< RTCP statistics */
uint32_t
i_items
;
/*< count of SDES item structures */
rtcp_SDES_item_t
**
pp_sdes
;
/*< SDES client items */
}
rtcp_client_t
;
/**
* structure rtcp_t
* This structure is a VLC_OBJECT and holds RTCP statistical information.
*/
typedef
struct
rtcp_t
{
VLC_COMMON_MEMBERS
uint32_t
u_clients
;
/*< number of clients connected */
uint32_t
u_active
;
/*< number of active senders */
uint32_t
u_members
;
/*< number of clients in previous interval */
mtime_t
i_date
;
/*< current RTCP packet interval */
mtime_t
i_last_date
;
/*< previous RTCP packet interval */
mtime_t
i_next_date
;
/*< next scheduled transmision time
of RTCP packet */
uint32_t
i_clients
;
/*< count of clients structures */
rtcp_client_t
**
pp_clients
;
/*< RTCP clients */
/* bitstream data pointer used for decoding */
bs_t
*
bs
;
/*< bitstream decoding data pointer */
/* functions */
int
(
*
pf_add_client
)(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
,
uint32_t
*
i_pos
);
int
(
*
pf_del_client
)(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
);
int
(
*
pf_find_client
)(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
,
uint32_t
*
i_pos
);
int
(
*
pf_cleanup_clients
)(
vlc_object_t
*
p_this
);
int
(
*
pf_destroy_clients
)(
vlc_object_t
*
p_this
);
}
rtcp_t
;
int
rtcp_add_client
(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
,
uint32_t
*
i_pos
);
int
rtcp_del_client
(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
);
/* Should be called with vlc_mutex_lock( &p_this->objec_lock ) held */
int
rtcp_find_client
(
vlc_object_t
*
p_this
,
uint32_t
u_ssrc
,
uint32_t
*
i_pos
);
int
rtcp_cleanup_clients
(
vlc_object_t
*
p_this
);
int
rtcp_destroy_clients
(
vlc_object_t
*
p_this
);
/**
* rtcp_cleanup_clients - Permanently remove clients from the list
* Permanently delete struct rtcp_client_t from member list when it is there
* time to be removed. RFC 3550 recommends a grace period of five times the
* RTCP packet send/receive interval before permanent removal of session. This
* is to ignore out of order packets for the same SSRC that arrive after the
* BYE report for that SSRC has been received.
* Arguments:
* \param p_this VLC_OBJECT_T of type rtcp_t
*/
int
rtcp_cleanup_clients
(
vlc_object_t
*
p_this
);
//VLC_EXPORT( int, rtcp_cleanup_clients, ( vlc_object_t * ) );
/**
* rtcp_pkt_decode - Decode RTCP packet
* Decode incoming RTCP packet and inspect the records types.
* Arguments:
* \param p_this
* \param p_pkt
* \param p_block
*/
int
rtcp_pkt_decode
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
,
block_t
*
p_block
);
//VLC_EXPORT( int, rtcp_decode, ( rtcp_pkt_t *, block_t * ) );
/**
* rtcp_pkt_new - Encode RTCP packet
* Create a new RTCP packet of type 'type'
* Arguments:
* \param type type of RTCP packet @see
*/
rtcp_pkt_t
*
rtcp_pkt_new
(
vlc_object_t
*
p_this
,
int
type
);
//VLC_EXPORT( block_t* , rtcp_encode, ( vlc_object_t *, int ) );
void
rtcp_pkt_del
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
pkt
);
block_t
*
rtcp_encode_SR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
block_t
*
rtcp_encode_RR
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
block_t
*
rtcp_encode_SDES
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
);
block_t
*
rtcp_encode_BYE
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
p_pkt
,
char
*
psz_reason
);
/**
* rtcp_interval
* Calculate the interval at which RTCP compound packets are going to be
* sent or received.
* Arguments:
* \param p_this VLC_OBJECT of type rtcp_t
* \param u_bandwith bandwidth of RTP connection
* \param u_ssrc client to sent or receive from
* \param b_sender are we the sender or the receiver
* \param b_first the first time this function is called use only half
* of the initial waiting time
*/
uint64_t
rtcp_interval
(
vlc_object_t
*
p_this
,
uint64_t
u_bandwidth
,
uint32_t
u_ssrc
,
bool
b_sender
,
bool
b_first
);
/**
* rtcp_expire
* Decides to sent an RTCP report or a BYE record
* Arguments:
* \param p_this VLC_OBJECT of type rtcp_t
* \param u_bandwith bandwidth of RTP connection
* \param u_ssrc client to sent or receive from
* \param rtcp_event type of event received
* \param b_sender are we the sender or the receiver
* \param *b_first the first time this function is called use only half
* of the initial waiting time. If b_first is true, then
* it will return *b_first = false;
*/
void
rtcp_expire
(
vlc_object_t
*
p_this
,
rtcp_event_t
rtcp_event
,
uint64_t
u_bandwidth
,
uint32_t
u_ssrc
,
bool
b_sender
,
bool
*
b_first
);
/**
* rtcp_received
* Determine what to do on the received Sender Report, decode it
* or leave the channel (BYE record).
* Arguments:
* \param p_this VLC_OBJECT of type rtcp_t
* \param p_pkt RTCP packet that was received
* \param rtcp_event type of event received
*/
void
rtcp_received
(
vlc_object_t
*
p_this
,
rtcp_pkt_t
*
pkt
,
rtcp_event_t
rtcp_event
);
#endif
/* RTCP_H */
modules/mux/rtp/rtp.h
deleted
100644 → 0
View file @
05492281
/*****************************************************************************
* rtp.h: RTP/RTCP headerfile
*****************************************************************************
* Copyright (C) 2005 M2X
*
* $Id$
*
* Authors: Jean-Paul Saman <jpsaman #_at_# videolan dot org>
*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef _RTP_H
#define _RTP_H 1
#define RTP_HEADER_LEN 12
#define RTP_SEQ_NUM_SIZE 65536
/*
* See RFC 1889 & RFC 2250.
*/
typedef
struct
{
int
fd
;
/*< socket descriptor of rtp stream */
unsigned
int
u_version
;
/*< rtp version number */
unsigned
int
u_CSRC_count
;
/*< CSRC count */
unsigned
int
u_payload_type
;
/*< type of RTP payload stream */
bool
b_extension
;
/*< The header is followed by exactly one header extension */
unsigned
int
u_marker
;
/*< marker field expect 1 */
unsigned
int
u_seq_no
;
/*< sequence number of RTP stream */
uint32_t
i_timestamp
;
/*< timestamp of stream */
unsigned
int
ssrc
;
/*< stream number is used here. */
unsigned
int
u_ext_length
;
/*< lenght of extension field */
/*int (*pf_connect)( void *p_userdata, char *p_server, int i_port );
int (*pf_disconnect)( void *p_userdata );
int (*pf_read)( void *p_userdata, uint8_t *p_buffer, int i_buffer );
int (*pf_write)( void *p_userdata, uint8_t *p_buffer, int i_buffer );*/
}
rtp_t
;
#endif
/* RTP_H */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment