Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (21)
......@@ -77,7 +77,7 @@ static void rtp_process (demux_t *demux, block_t *block)
/* TODO: use SDP and get rid of this hack */
if (unlikely(sys->autodetect))
{ /* Autodetect payload type, _before_ rtp_queue() */
rtp_autodetect (demux, sys->session, block);
rtp_autodetect(VLC_OBJECT(demux), sys->session, block);
sys->autodetect = false;
}
......
......@@ -32,6 +32,7 @@
#include <vlc_network.h>
#include <vlc_plugin.h>
#include <vlc_dtls.h>
#include <vlc_modules.h> /* module_exists() */
#include "rtp.h"
#ifdef HAVE_SRTP
......@@ -44,7 +45,6 @@
/*
* TODO: so much stuff
* - send RTCP-RR and RTCP-BYE
* - dynamic payload types (need SDP parser)
* - multiple medias (need SDP parser, and RTCP-SR parser for lip-sync)
* - support for stream_filter in case of chained demux (MPEG-TS)
*/
......@@ -199,13 +199,6 @@ static int OpenSDP(vlc_object_t *obj)
goto error;
}
/* Check payload type (FIXME: handle multiple, match w/ a=rtpmap) */
unsigned char pt = atoi(media->format);
if (pt >= 64 || !(UINT64_C(0x300005d09) & (UINT64_C(1) << pt))) {
msg_Dbg(obj, "unsupported payload format(s) %s", media->format);
goto error;
}
if (vlc_sdp_media_attr_value(media, "control") != NULL
|| vlc_sdp_attr_value(sdp, "control") != NULL) {
msg_Dbg(obj, "RTSP not supported");
......@@ -294,15 +287,12 @@ static int OpenSDP(vlc_object_t *obj)
}
}
vlc_sdp_free(sdp);
sdp = NULL;
sys->chained_demux = NULL;
sys->max_src = var_InheritInteger(obj, "rtp-max-src");
sys->timeout = vlc_tick_from_sec(var_InheritInteger(obj, "rtp-timeout"));
sys->max_dropout = var_InheritInteger(obj, "rtp-max-dropout");
sys->max_misorder = -var_InheritInteger(obj, "rtp-max-misorder");
sys->autodetect = true;
sys->autodetect = false;
demux->pf_demux = NULL;
demux->pf_control = Control;
......@@ -312,11 +302,22 @@ static int OpenSDP(vlc_object_t *obj)
if (sys->session == NULL)
goto error;
/* Parse payload types */
int err = vlc_rtp_add_media_types(obj, sys->session, media);
if (err < 0) {
msg_Err(obj, "SDP description parse error");
goto error;
}
if (err > 0 && module_exists("live555")) /* Bail out to live555 */
goto error;
if (vlc_clone(&sys->thread, rtp_dgram_thread, demux,
VLC_THREAD_PRIORITY_INPUT)) {
rtp_session_destroy(demux, sys->session);
goto error;
}
vlc_sdp_free(sdp);
return VLC_SUCCESS;
error:
......@@ -324,8 +325,7 @@ error:
vlc_dtls_Close(sys->rtcp_sock);
if (sys->rtp_sock != NULL)
vlc_dtls_Close(sys->rtp_sock);
if (sdp != NULL)
vlc_sdp_free(sdp);
vlc_sdp_free(sdp);
return VLC_EGENERIC;
}
......@@ -532,16 +532,6 @@ error:
"RTP packets will be discarded if they are too far behind (i.e. in the " \
"past) by this many packets from the last received packet." )
#define RTP_DYNAMIC_PT_TEXT N_("RTP payload format assumed for dynamic " \
"payloads")
#define RTP_DYNAMIC_PT_LONGTEXT N_( \
"This payload format will be assumed for dynamic payload types " \
"(between 96 and 127) if it can't be determined otherwise with " \
"out-of-band mappings (SDP)" )
static const char *const dynamic_pt_list[] = { "", "theora" };
static const char *const dynamic_pt_list_text[] = { N_( "Unset" ), N_( "Theora Encoded Video" ) };
/*
* Module descriptor
*/
......@@ -580,9 +570,7 @@ vlc_module_begin()
add_integer("rtp-max-misorder", 100, RTP_MAX_MISORDER_TEXT,
RTP_MAX_MISORDER_LONGTEXT)
change_integer_range (0, 32767)
add_string("rtp-dynamic-pt", "", RTP_DYNAMIC_PT_TEXT,
RTP_DYNAMIC_PT_LONGTEXT)
change_string_list(dynamic_pt_list, dynamic_pt_list_text)
add_obsolete_string("rtp-dynamic-pt") /* since 4.0.0 */
/*add_shortcut ("sctp")*/
add_shortcut("dccp", "rtp", "udplite")
......
......@@ -20,22 +20,90 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
typedef struct rtp_pt_t rtp_pt_t;
typedef struct vlc_rtp_pt rtp_pt_t;
typedef struct rtp_session_t rtp_session_t;
struct vlc_demux_chained_t;
struct vlc_sdp_media;
/** @section RTP payload format */
struct rtp_pt_t
struct vlc_sdp_pt {
const struct vlc_sdp_media *media;
char name[16];
unsigned int clock_rate;
unsigned char channel_count;
const char *parameters;
};
struct vlc_rtp_pt_operations {
void *(*init)(struct vlc_rtp_pt *, demux_t *);
void (*destroy)(demux_t *, void *);
void (*decode)(demux_t *, void *, block_t *);
};
struct vlc_rtp_pt
{
void *(*init) (demux_t *);
void (*destroy) (demux_t *, void *);
void (*header) (demux_t *, void *, block_t *);
void (*decode) (demux_t *, void *, block_t *);
const struct vlc_rtp_pt_operations *ops;
uint32_t frequency; /* RTP clock rate (Hz) */
uint8_t number;
uint8_t channel_count;
};
void rtp_autodetect (demux_t *, rtp_session_t *, const block_t *);
/**
* Destroys a payload type parameter set.
*/
void vlc_rtp_pt_release(struct vlc_rtp_pt *pt);
/**
* Instantiates a payload type from a set of parameters.
*
* A given SDP media can have multiple alternative payload types, each with
* their set of parameters. The RTP session can then have multiple concurrent
* RTP sources (SSRC). This function creates an instance of a given payload
* type for use by an unique RTP source.
*
* @param pt RTP payload type to instantiate
* @param demux demux object for output
* @return private data for the instance
*/
static inline void *vlc_rtp_pt_begin(struct vlc_rtp_pt *pt, demux_t *demux)
{
assert(pt->ops->init != NULL);
return pt->ops->init(pt, demux);
}
/**
* Deinstantiates a payload type.
*
* This destroys an instance of a payload type created by vlc_rtp_pt_begin().
*
* @param pt RTP payload type to deinstantiate
* @param demux demux object that was used by the instance
* @param data instance private data as returned by vlc_rtp_pt_begin()
*/
static inline void vlc_rtp_pt_end(struct vlc_rtp_pt *pt, demux_t *demux,
void *data)
{
if (pt->ops->destroy != NULL)
pt->ops->destroy(demux, data);
}
/**
* Processes an payload packet.
*
* This passes a data payload of an RTP packet to the instance of the
* payload type specified in the packet (PT and SSRC fields).
*/
static inline void vlc_rtp_pt_decode(const struct vlc_rtp_pt *pt,
demux_t *demux,
void *data, block_t *pkt)
{
assert(pt->ops->decode != NULL);
pt->ops->decode(demux, data, pkt);
}
void rtp_autodetect(vlc_object_t *, rtp_session_t *, const block_t *);
static inline uint8_t rtp_ptype (const block_t *block)
{
......@@ -46,16 +114,16 @@ void *codec_init (demux_t *demux, es_format_t *fmt);
void codec_destroy (demux_t *demux, void *data);
void codec_decode (demux_t *demux, void *data, block_t *block);
void *theora_init (demux_t *demux);
void xiph_destroy (demux_t *demux, void *data);
void xiph_decode (demux_t *demux, void *data, block_t *block);
extern const struct vlc_rtp_pt_operations rtp_video_theora;
/** @section RTP session */
rtp_session_t *rtp_session_create (demux_t *);
void rtp_session_destroy (demux_t *, rtp_session_t *);
void rtp_queue (demux_t *, rtp_session_t *, block_t *);
bool rtp_dequeue (demux_t *, const rtp_session_t *, vlc_tick_t *);
int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt);
int rtp_add_type(rtp_session_t *ses, rtp_pt_t *pt);
int vlc_rtp_add_media_types(vlc_object_t *obj, rtp_session_t *ses,
const struct vlc_sdp_media *media);
void *rtp_dgram_thread (void *data);
......
......@@ -25,6 +25,7 @@
#endif
#include <stdlib.h>
#include <errno.h>
#include <vlc_common.h>
#include <vlc_demux.h>
......@@ -32,6 +33,7 @@
#include <vlc_aout.h> /* aout_FormatPrepare() */
#include "rtp.h"
#include "sdp.h"
/*
* Generic packet handlers
......@@ -85,16 +87,6 @@ static void stream_destroy (demux_t *demux, void *data)
}
}
static void stream_header (demux_t *demux, void *data, block_t *block)
{
VLC_UNUSED(demux);
VLC_UNUSED(data);
if(block->p_buffer[1] & 0x80) /* TS M-bit == discontinuity (RFC 2250, 2.1) */
{
block->i_flags |= BLOCK_FLAG_DISCONTINUITY;
}
}
/* Send a packet to a chained demuxer */
static void stream_decode (demux_t *demux, void *data, block_t *block)
{
......@@ -112,88 +104,101 @@ static void stream_decode (demux_t *demux, void *data, block_t *block)
/* PT=0
* PCMU: G.711 µ-law (RFC3551)
*/
static void *pcmu_init (demux_t *demux)
static void *pcmu_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MULAW);
fmt.audio.i_rate = 8000;
fmt.audio.i_rate = pt->frequency;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
return codec_init (demux, &fmt);
}
static const struct vlc_rtp_pt_operations rtp_audio_pcmu = {
pcmu_init, codec_destroy, codec_decode,
};
/* PT=3
* GSM
*/
static void *gsm_init (demux_t *demux)
static void *gsm_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_GSM);
fmt.audio.i_rate = 8000;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
(void) pt;
return codec_init (demux, &fmt);
}
static const struct vlc_rtp_pt_operations rtp_audio_gsm = {
gsm_init, codec_destroy, codec_decode,
};
/* PT=8
* PCMA: G.711 A-law (RFC3551)
*/
static void *pcma_init (demux_t *demux)
static void *pcma_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_ALAW);
fmt.audio.i_rate = 8000;
fmt.audio.i_rate = pt->frequency;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
return codec_init (demux, &fmt);
}
static const struct vlc_rtp_pt_operations rtp_audio_pcma = {
pcma_init, codec_destroy, codec_decode,
};
/* PT=10,11
* L16: 16-bits (network byte order) PCM
*/
static void *l16s_init (demux_t *demux)
static void *l16_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16B);
fmt.audio.i_rate = 44100;
fmt.audio.i_physical_channels = AOUT_CHANS_STEREO;
fmt.audio.i_rate = pt->frequency;
fmt.audio.i_channels = pt->channel_count ? pt->channel_count : 1;
return codec_init (demux, &fmt);
}
static void *l16m_init (demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16B);
fmt.audio.i_rate = 44100;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
return codec_init (demux, &fmt);
}
static const struct vlc_rtp_pt_operations rtp_audio_l16 = {
l16_init, codec_destroy, codec_decode,
};
/* PT=12
* QCELP
*/
static void *qcelp_init (demux_t *demux)
static void *qcelp_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_QCELP);
fmt.audio.i_rate = 8000;
fmt.audio.i_physical_channels = AOUT_CHAN_CENTER;
(void) pt;
return codec_init (demux, &fmt);
}
static const struct vlc_rtp_pt_operations rtp_audio_qcelp = {
qcelp_init, codec_destroy, codec_decode,
};
/* PT=14
* MPA: MPEG Audio (RFC2250, §3.4)
*/
static void *mpa_init (demux_t *demux)
static void *mpa_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MPGA);
fmt.audio.i_physical_channels = AOUT_CHANS_STEREO;
fmt.b_packetized = false;
(void) pt;
return codec_init (demux, &fmt);
}
......@@ -211,16 +216,20 @@ static void mpa_decode (demux_t *demux, void *data, block_t *block)
codec_decode (demux, data, block);
}
static const struct vlc_rtp_pt_operations rtp_audio_mpa = {
mpa_init, codec_destroy, mpa_decode,
};
/* PT=32
* MPV: MPEG Video (RFC2250, §3.5)
*/
static void *mpv_init (demux_t *demux)
static void *mpv_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, VIDEO_ES, VLC_CODEC_MPGV);
fmt.b_packetized = false;
(void) pt;
return codec_init (demux, &fmt);
}
......@@ -244,128 +253,254 @@ static void mpv_decode (demux_t *demux, void *data, block_t *block)
codec_decode (demux, data, block);
}
static const struct vlc_rtp_pt_operations rtp_video_mpv = {
mpv_init, codec_destroy, mpv_decode,
};
/* PT=33
* MP2: MPEG TS (RFC2250, §2)
*/
static void *ts_init (demux_t *demux)
static void *ts_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
(void) pt;
return stream_init (demux, "ts");
}
static const struct vlc_rtp_pt_operations rtp_av_ts = {
ts_init, stream_destroy, stream_decode,
};
/* Not using SDP, we need to guess the payload format used */
/* see http://www.iana.org/assignments/rtp-parameters */
void rtp_autodetect (demux_t *demux, rtp_session_t *session,
const block_t *block)
void rtp_autodetect(vlc_object_t *obj, rtp_session_t *session,
const block_t *block)
{
uint8_t ptype = rtp_ptype (block);
rtp_pt_t pt = {
.init = NULL,
.destroy = codec_destroy,
.header = NULL,
.decode = codec_decode,
.frequency = 0,
.number = ptype,
char type[6], proto[] = "RTP/AVP", numstr[4];
struct vlc_sdp_media media = {
.type = type, .port_count = 1, .proto = proto, .format = numstr
};
/* Remember to keep this in sync with modules/services_discovery/sap.c */
switch (ptype)
{
case 0:
msg_Dbg (demux, "detected G.711 mu-law");
pt.init = pcmu_init;
pt.frequency = 8000;
break;
case 3:
msg_Dbg (demux, "detected GSM");
pt.init = gsm_init;
pt.frequency = 8000;
break;
case 8:
msg_Dbg (demux, "detected G.711 A-law");
pt.init = pcma_init;
pt.frequency = 8000;
break;
case 10:
msg_Dbg (demux, "detected stereo PCM");
pt.init = l16s_init;
pt.frequency = 44100;
break;
case 11:
msg_Dbg (demux, "detected mono PCM");
pt.init = l16m_init;
pt.frequency = 44100;
break;
case 12:
msg_Dbg (demux, "detected QCELP");
pt.init = qcelp_init;
pt.frequency = 8000;
break;
case 14:
msg_Dbg (demux, "detected MPEG Audio");
pt.init = mpa_init;
pt.decode = mpa_decode;
pt.frequency = 90000;
break;
case 32:
msg_Dbg (demux, "detected MPEG Video");
pt.init = mpv_init;
pt.decode = mpv_decode;
pt.frequency = 90000;
break;
case 33:
msg_Dbg (demux, "detected MPEG2 TS");
pt.init = ts_init;
pt.destroy = stream_destroy;
pt.header = stream_header;
pt.decode = stream_decode;
pt.frequency = 90000;
break;
default:
if (ptype >= 96)
{
char *dynamic = var_InheritString(demux, "rtp-dynamic-pt");
if (dynamic == NULL)
;
else if (!strcmp(dynamic, "theora"))
{
msg_Dbg (demux, "assuming Theora Encoded Video");
pt.init = theora_init;
pt.destroy = xiph_destroy;
pt.decode = xiph_decode;
pt.frequency = 90000;
free (dynamic);
break;
}
else
msg_Err (demux, "unknown dynamic payload format `%s' "
"specified", dynamic);
free (dynamic);
}
/* We only support static audio subtypes except MPV (PT=32).
* MP2T (PT=33) can be treated as either audio or video. */
memcpy(type, (ptype == 32) ? "video" : "audio", 6);
snprintf(numstr, sizeof (numstr), "%hhu", ptype);
msg_Err (demux, "unspecified payload format (type %"PRIu8")", ptype);
msg_Info (demux, "A valid SDP is needed to parse this RTP stream.");
vlc_dialog_display_error (demux, N_("SDP required"),
if (vlc_rtp_add_media_types(obj, session, &media)) {
msg_Err(obj, "unspecified payload format (type %"PRIu8")", ptype);
msg_Info(obj, "A valid SDP is needed to parse this RTP stream.");
vlc_dialog_display_error(obj, N_("SDP required"),
N_("A description in SDP format is required to receive the RTP "
"stream. Note that rtp:// URIs cannot work with dynamic "
"RTP payload format (%"PRIu8")."), ptype);
return;
}
rtp_add_type (demux, session, &pt);
}
/*
* Dynamic payload type handlers
* Hmm, none implemented yet apart from Xiph ones.
*/
static struct vlc_rtp_pt *vlc_rtp_pt_create(vlc_object_t *obj,
const struct vlc_sdp_pt *desc)
{
if (desc->clock_rate == 0) {
/* Dynamic payload type not defined in the SDP */
errno = EINVAL;
return NULL;
}
struct vlc_rtp_pt *pt = malloc(sizeof (*pt));
if (unlikely(pt == NULL))
return NULL;
pt->frequency = desc->clock_rate;
pt->channel_count = desc->channel_count;
pt->ops = NULL;
/* TODO: introduce module (capabilities) for payload types */
if (strcmp(desc->media->type, "audio") == 0) {
if (strcmp(desc->name, "PCMU") == 0)
pt->ops = &rtp_audio_pcmu;
else if (strcmp(desc->name, "GSM") == 0)
pt->ops = &rtp_audio_gsm;
else if (strcmp(desc->name, "PCMA") == 0)
pt->ops = &rtp_audio_pcma;
else if (strcmp(desc->name, "L16") == 0)
pt->ops = &rtp_audio_l16;
else if (strcmp(desc->name, "QCLEP") == 0)
pt->ops = &rtp_audio_qcelp;
else if (strcmp(desc->name, "MPA") == 0)
pt->ops = &rtp_audio_mpa;
} else if (strcmp(desc->media->type, "video") == 0) {
if (strcmp(desc->name, "MPV") == 0)
pt->ops = &rtp_video_mpv;
}
if (strcmp(desc->name, "MP2T") == 0)
pt->ops = &rtp_av_ts;
if (pt->ops == NULL) {
msg_Err(obj, "unsupported media type %s/%s", desc->media->type,
desc->name);
free(pt);
errno = ENOTSUP;
pt = NULL;
}
return pt;
}
void vlc_rtp_pt_release(struct vlc_rtp_pt *pt)
{
free(pt);
}
struct vlc_sdp_pt_default {
unsigned char number;
char subtype[6];
unsigned char channel_count;
unsigned int clock_rate;
};
/**
* Sets the static payload types.
*/
static void vlc_rtp_set_default_types(struct vlc_sdp_pt *restrict types,
const struct vlc_sdp_media *media)
{
/* Implicit payload type mappings (RFC3551 section 6) */
static const struct vlc_sdp_pt_default audio_defaults[] = {
{ 0, "PCMU", 1, 8000, },
{ 3, "GSM", 1, 8000, },
{ 4, "G723", 1, 8000, },
{ 5, "DIV4", 1, 8000, },
{ 6, "DIV4", 1, 16000, },
{ 7, "LPC", 1, 8000, },
{ 8, "PCMA", 1, 8000, },
{ 9, "G722", 1, 8000, },
{ 10, "L16", 2, 44100, },
{ 11, "L16", 1, 44100, },
{ 12, "QCELP", 1, 8000, },
{ 13, "CN", 1, 8000, },
{ 14, "MPA", 0, 90000 },
{ 15, "G728", 1, 8000, },
{ 16, "DIV4", 1, 11025, },
{ 17, "DIV4", 1, 22050, },
{ 18, "G729", 1, 8000, },
{ 33, "MP2T", 0, 90000, },
};
static const struct vlc_sdp_pt_default video_defaults[] = {
{ 25, "CelB", 0, 90000, },
{ 26, "JPEG", 0, 90000, },
{ 28, "nv", 0, 90000, },
{ 31, "H261", 0, 90000, },
{ 32, "MPV", 0, 90000, },
{ 33, "MP2T", 0, 90000, },
{ 34, "H263", 0, 90000, },
};
const struct vlc_sdp_pt_default *defs = NULL;
size_t def_size = 0;
if (strcmp(media->type, "audio") == 0) {
defs = audio_defaults;
def_size = ARRAY_SIZE(audio_defaults);
} else if (strcmp(media->type, "video") == 0) {
defs = video_defaults;
def_size = ARRAY_SIZE(video_defaults);
}
for (size_t i = 0; i < def_size; i++) {
const struct vlc_sdp_pt_default *def = defs + i;
struct vlc_sdp_pt *pt = types + def->number;
pt->media = media;
strcpy(pt->name, def->subtype);
pt->clock_rate = def->clock_rate;
pt->channel_count = def->channel_count;
}
}
/**
* Registers all payload types declared in an SDP media.
*/
int vlc_rtp_add_media_types(vlc_object_t *obj, rtp_session_t *session,
const struct vlc_sdp_media *media)
{
struct vlc_sdp_pt types[128] = { };
vlc_rtp_set_default_types(types, media);
/* Parse the a=rtpmap and extract a=fmtp lines */
for (const struct vlc_sdp_attr *a = media->attrs; a != NULL; a = a->next) {
if (strcmp(a->name, "rtpmap") == 0) {
unsigned char number, channels;
char name[16];
unsigned int frequency;
switch (sscanf(a->value, "%hhu %15[^/]/%u/%hhu", &number, name,
&frequency, &channels)) {
case 3:
channels = 0;
/* fall through */
case 4:
if (number < ARRAY_SIZE(types)) {
strcpy(types[number].name, name);
types[number].clock_rate = frequency;
types[number].channel_count = channels;
}
break;
}
} else if (strcmp(a->name, "fmtp") == 0) {
unsigned char number;
int offset;
if (sscanf(a->value, "%hhu %n", &number, &offset) == 1
&& number < ARRAY_SIZE(types))
types[number].parameters = a->value + offset;
}
}
const char *numbers = media->format; /* space-separated list of PTs */
char *end;
int errors = 0;
for (;;) {
unsigned long number = strtoul(numbers, &end, 10);
if (end == numbers) {
if (*end != '\0')
return -EINVAL;
break; /* garbage or end of the line */
}
numbers = end + strspn(end, " "); /* next PT number */
if (number >= ARRAY_SIZE(types))
continue;
struct vlc_sdp_pt *const type = types + number;
if (type->media == NULL) /* not defined or already used */
continue;
msg_Dbg(obj, "payload type %lu: %s/%s, %u Hz", number,
media->type, type->name, type->clock_rate);
if (type->channel_count > 0)
msg_Dbg(obj, " - %hhu channel(s)", type->channel_count);
if (type->parameters != NULL)
msg_Dbg(obj, " - parameters: %s", type->parameters);
struct vlc_rtp_pt *pt = vlc_rtp_pt_create(obj, type);
if (pt != NULL) {
pt->number = number;
if (rtp_add_type(session, pt))
vlc_rtp_pt_release(pt);
} else
errors++;
type->media = NULL; /* Prevent duplicate PT numbers. */
}
return errors;
}
......@@ -41,7 +41,7 @@ struct rtp_session_t
rtp_source_t **srcv;
unsigned srcc;
uint8_t ptc;
rtp_pt_t *ptv;
rtp_pt_t **ptv;
};
static rtp_source_t *
......@@ -79,58 +79,31 @@ void rtp_session_destroy (demux_t *demux, rtp_session_t *session)
for (unsigned i = 0; i < session->srcc; i++)
rtp_source_destroy (demux, session, session->srcv[i]);
for (uint_fast8_t i = 0; i < session->ptc; i++)
vlc_rtp_pt_release(session->ptv[i]);
free (session->srcv);
free (session->ptv);
free (session);
(void)demux;
}
static void *no_init (demux_t *demux)
{
(void)demux;
return NULL;
}
static void no_destroy (demux_t *demux, void *opaque)
{
(void)demux; (void)opaque;
}
static void no_decode (demux_t *demux, void *opaque, block_t *block)
{
(void)demux; (void)opaque;
block_Release (block);
}
/**
* Adds a payload type to an RTP session.
*/
int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt)
int rtp_add_type(rtp_session_t *ses, rtp_pt_t *pt)
{
assert(pt->frequency > 0); /* SIGFPE! */
if (ses->srcc > 0)
{
msg_Err (demux, "cannot change RTP payload formats during session");
return EINVAL;
}
return EBUSY;
rtp_pt_t *ppt = realloc (ses->ptv, (ses->ptc + 1) * sizeof (rtp_pt_t));
rtp_pt_t **ppt = realloc(ses->ptv, (ses->ptc + 1) * sizeof (pt));
if (ppt == NULL)
return ENOMEM;
ses->ptv = ppt;
ppt += ses->ptc++;
ppt->init = pt->init ? pt->init : no_init;
ppt->destroy = pt->destroy ? pt->destroy : no_destroy;
ppt->decode = pt->decode ? pt->decode : no_decode;
ppt->header = NULL;
ppt->frequency = pt->frequency;
ppt->number = pt->number;
msg_Dbg (demux, "added payload type %"PRIu8" (f = %"PRIu32" Hz)",
ppt->number, ppt->frequency);
assert (ppt->frequency > 0); /* SIGFPE! */
(void)demux;
ses->ptv[ses->ptc++] = pt;
return 0;
}
......@@ -176,7 +149,7 @@ rtp_source_create (demux_t *demux, const rtp_session_t *session,
/* Initializes all payload */
for (unsigned i = 0; i < session->ptc; i++)
source->opaque[i] = session->ptv[i].init (demux);
source->opaque[i] = vlc_rtp_pt_begin(session->ptv[i], demux);
msg_Dbg (demux, "added RTP source (%08x)", ssrc);
return source;
......@@ -193,7 +166,7 @@ rtp_source_destroy (demux_t *demux, const rtp_session_t *session,
msg_Dbg (demux, "removing RTP source (%08x)", source->ssrc);
for (unsigned i = 0; i < session->ptc; i++)
session->ptv[i].destroy (demux, source->opaque[i]);
vlc_rtp_pt_end(session->ptv[i], demux, source->opaque[i]);
block_ChainRelease (source->blocks);
free (source);
}
......@@ -210,7 +183,7 @@ static inline uint32_t rtp_timestamp (const block_t *block)
return GetDWBE (block->p_buffer + 4);
}
static const struct rtp_pt_t *
static const struct vlc_rtp_pt *
rtp_find_ptype (const rtp_session_t *session, rtp_source_t *source,
const block_t *block, void **pt_data)
{
......@@ -218,11 +191,13 @@ rtp_find_ptype (const rtp_session_t *session, rtp_source_t *source,
for (unsigned i = 0; i < session->ptc; i++)
{
if (session->ptv[i].number == ptype)
struct vlc_rtp_pt *pt = session->ptv[i];
if (pt->number == ptype)
{
if (pt_data != NULL)
*pt_data = source->opaque[i];
return &session->ptv[i];
return pt;
}
}
return NULL;
......@@ -502,9 +477,6 @@ rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
goto drop;
}
if(pt->header)
pt->header(demux, pt_data, block);
/* Computes the PTS from the RTP timestamp and payload RTP frequency.
* DTS is unknown. Also, while the clock frequency depends on the payload
* format, a single source MUST only use payloads of a chosen frequency.
......@@ -540,7 +512,7 @@ rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
block->p_buffer += skip;
block->i_buffer -= skip;
pt->decode (demux, pt_data, block);
vlc_rtp_pt_decode(pt, demux, pt_data, block);
return;
drop:
......
......@@ -71,13 +71,13 @@ static void *vorbis_init (demux_t *demux)
/* PT=dynamic
* vorbis: Xiph Theora video
*/
void *theora_init (demux_t *demux)
static void *theora_init(struct vlc_rtp_pt *pt, demux_t *demux)
{
(void)demux;
(void) pt; (void) demux;
return xiph_init (false);
}
void xiph_destroy (demux_t *demux, void *data)
static void xiph_destroy(demux_t *demux, void *data)
{
rtp_xiph_t *self = data;
......@@ -142,8 +142,7 @@ static ssize_t xiph_header (void **pextra, const uint8_t *buf, size_t len)
return extra_size;
}
void xiph_decode (demux_t *demux, void *data, block_t *block)
static void xiph_decode(demux_t *demux, void *data, block_t *block)
{
rtp_xiph_t *self = data;
......@@ -286,3 +285,7 @@ void xiph_decode (demux_t *demux, void *data, block_t *block)
drop:
block_Release (block);
}
const struct vlc_rtp_pt_operations rtp_video_theora = {
theora_init, xiph_destroy, xiph_decode,
};