Commit 91f7b6f5 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

RTP: add support for MPA and MPV static payload formats

parent b8b6f0b0
...@@ -145,7 +145,7 @@ static int Open (vlc_object_t *obj) ...@@ -145,7 +145,7 @@ static int Open (vlc_object_t *obj)
if (p_sys == NULL) if (p_sys == NULL)
goto error; goto error;
var_Create (obj, "rtp-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); p_sys->caching = var_CreateGetInteger (obj, "rtp-caching");
p_sys->max_src = var_CreateGetInteger (obj, "rtp-max-src"); p_sys->max_src = var_CreateGetInteger (obj, "rtp-max-src");
p_sys->timeout = var_CreateGetInteger (obj, "rtp-timeout"); p_sys->timeout = var_CreateGetInteger (obj, "rtp-timeout");
p_sys->max_dropout = var_CreateGetInteger (obj, "rtp-max-dropout"); p_sys->max_dropout = var_CreateGetInteger (obj, "rtp-max-dropout");
...@@ -166,7 +166,7 @@ static int Open (vlc_object_t *obj) ...@@ -166,7 +166,7 @@ static int Open (vlc_object_t *obj)
error: error:
net_Close (fd); net_Close (fd);
free (p_sys); free (p_sys);
return VLC_SUCCESS; return VLC_EGENERIC;
} }
...@@ -217,8 +217,7 @@ static int extract_port (char **phost) ...@@ -217,8 +217,7 @@ static int extract_port (char **phost)
*/ */
static int Control (demux_t *demux, int i_query, va_list args) static int Control (demux_t *demux, int i_query, va_list args)
{ {
/*demux_sys_t *p_sys = demux->p_sys;*/ demux_sys_t *p_sys = demux->p_sys;
(void)demux;
switch (i_query) switch (i_query)
{ {
...@@ -240,7 +239,7 @@ static int Control (demux_t *demux, int i_query, va_list args) ...@@ -240,7 +239,7 @@ static int Control (demux_t *demux, int i_query, va_list args)
case DEMUX_GET_PTS_DELAY: case DEMUX_GET_PTS_DELAY:
{ {
int64_t *v = va_arg (args, int64_t *); int64_t *v = va_arg (args, int64_t *);
*v = var_GetInteger (demux, "rtp-caching"); *v = p_sys->caching;
return 0; return 0;
} }
} }
...@@ -270,6 +269,33 @@ static block_t *rtp_dgram_recv (demux_t *demux, int fd) ...@@ -270,6 +269,33 @@ static block_t *rtp_dgram_recv (demux_t *demux, int fd)
/* /*
* Generic packet handlers * Generic packet handlers
*/ */
static void *codec_init (demux_t *demux, es_format_t *fmt)
{
return es_out_Add (demux->out, fmt);
}
static void codec_destroy (demux_t *demux, void *data)
{
if (data)
es_out_Del (demux->out, (es_out_id_t *)data);
}
/* Send a packet to decoder */
static void codec_decode (demux_t *demux, void *data, block_t *block)
{
if (data)
{
block->i_dts = 0; /* RTP does not specify this */
es_out_Control (demux->out, ES_OUT_SET_PCR,
block->i_pts - demux->p_sys->caching * 1000);
es_out_Send (demux->out, (es_out_id_t *)data, block);
}
else
block_Release (block);
}
static void *stream_init (demux_t *demux, const char *name) static void *stream_init (demux_t *demux, const char *name)
{ {
return stream_DemuxNew (demux, name, demux->out); return stream_DemuxNew (demux, name, demux->out);
...@@ -287,9 +313,74 @@ static void stream_decode (demux_t *demux, void *data, block_t *block) ...@@ -287,9 +313,74 @@ static void stream_decode (demux_t *demux, void *data, block_t *block)
{ {
if (data) if (data)
stream_DemuxSend ((stream_t *)data, block); stream_DemuxSend ((stream_t *)data, block);
else
block_Release (block);
(void)demux; (void)demux;
} }
/*
* Static payload types handler
*/
/* PT=14
* MPA: MPEG Audio (RFC2250, §3.4)
*/
static void *mpa_init (demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('m', 'p', 'g', 'a'));
fmt.audio.i_channels = 2;
return codec_init (demux, &fmt);
}
static void mpa_decode (demux_t *demux, void *data, block_t *block)
{
if (block->i_buffer < 4)
{
block_Release (block);
return;
}
block->i_buffer -= 4; /* 32-bits RTP/MPA header */
block->p_buffer += 4;
codec_decode (demux, data, block);
}
/* PT=32
* MPV: MPEG Video (RFC2250, §3.5)
*/
static void *mpv_init (demux_t *demux)
{
es_format_t fmt;
es_format_Init (&fmt, VIDEO_ES, VLC_FOURCC ('m', 'p', 'g', 'v'));
return codec_init (demux, &fmt);
}
static void mpv_decode (demux_t *demux, void *data, block_t *block)
{
if (block->i_buffer < 4)
{
block_Release (block);
return;
}
block->i_buffer -= 4; /* 32-bits RTP/MPV header */
block->p_buffer += 4;
#if 0
if (block->p_buffer[-3] & 0x4)
{
/* MPEG2 Video extension header */
/* TODO: shouldn't we skip this too ? */
}
#endif
codec_decode (demux, data, block);
}
/* PT=33 /* PT=33
* MP2: MPEG TS (RFC2250, §2) * MP2: MPEG TS (RFC2250, §2)
*/ */
...@@ -299,6 +390,11 @@ static void *ts_init (demux_t *demux) ...@@ -299,6 +390,11 @@ static void *ts_init (demux_t *demux)
} }
/*
* Dynamic payload type handlers
* Hmm, none implemented yet.
*/
/** /**
* Processing callback * Processing callback
*/ */
...@@ -313,17 +409,27 @@ static int Demux (demux_t *demux) ...@@ -313,17 +409,27 @@ static int Demux (demux_t *demux)
/* Not using SDP, we need to guess the payload format used */ /* Not using SDP, we need to guess the payload format used */
if (p_sys->autodetect && block->i_buffer >= 2) if (p_sys->autodetect && block->i_buffer >= 2)
{ {
rtp_pt_t pt = { .init = NULL, }; rtp_pt_t pt = {
.init = NULL,
switch (pt.number = (block->p_buffer[1] & 0x7f)) .destroy = codec_destroy,
.decode = codec_decode,
.frequency = 0,
.number = block->p_buffer[1] & 0x7f,
};
switch (pt.number)
{ {
case 14: case 14:
msg_Dbg (demux, "detected MPEG Audio over RTP"); msg_Dbg (demux, "detected MPEG Audio over RTP");
pt.init = mpa_init;
pt.decode = mpa_decode;
pt.frequency = 44100; pt.frequency = 44100;
break; break;
case 32: case 32:
msg_Dbg (demux, "detected MPEG Video over RTP"); msg_Dbg (demux, "detected MPEG Video over RTP");
pt.init = mpv_init;
pt.decode = mpv_decode;
pt.frequency = 90000; pt.frequency = 90000;
break; break;
...@@ -344,64 +450,3 @@ static int Demux (demux_t *demux) ...@@ -344,64 +450,3 @@ static int Demux (demux_t *demux)
return 1; return 1;
} }
/* Send a packet to decoder */
#if 0
static void pt_decode (demux_t *obj, block_t *block, rtp_pt_t *self)
{
p_block->i_pts = p_block->i_dts = date_... (...);
es_out_Control (obj->out, ES_OUT_SET_PCR, p_block->i_pts);
es_out_Send (obj->out, (es_out_id_t *)*p_id, block);
return 0;
}
#endif
#if 0
/*
* Static payload types handler
*/
/* PT=14
* MPA: MPEG Audio (RFC2250, §3.4)
*/
static int pt_mpa (demux_t *obj, block_t *block, rtp_pt_t *self)
{
if (block->i_buffer < 4)
return VLC_EGENERIC;
block->i_buffer -= 4; // 32 bits RTP/MPA header
block->p_buffer += 4;
return pt_demux (obj, block, self, "mpga");
}
/* PT=32
* MPV: MPEG Video (RFC2250, §3.5)
*/
static int pt_mpv (demux_t *obj, block_t *block, rtp_pt_t *self)
{
if (block->i_buffer < 4)
return VLC_EGENERIC;
block->i_buffer -= 4; // 32 bits RTP/MPV header
block->p_buffer += 4;
if (block->p_buffer[-3] & 0x4)
{
/* MPEG2 Video extension header */
/* TODO: shouldn't we skip this too ? */
}
return pt_demux (obj, block, self, "mpgv");
}
#endif
/*
* Dynamic payload type handlers
* Hmm, none implemented yet.
*/
...@@ -45,6 +45,7 @@ struct demux_sys_t ...@@ -45,6 +45,7 @@ struct demux_sys_t
rtp_session_t *session; rtp_session_t *session;
int fd; int fd;
unsigned caching;
unsigned timeout; unsigned timeout;
uint8_t max_src; uint8_t max_src;
uint16_t max_dropout; uint16_t max_dropout;
......
...@@ -87,7 +87,8 @@ void rtp_session_destroy (demux_t *demux, rtp_session_t *session) ...@@ -87,7 +87,8 @@ void rtp_session_destroy (demux_t *demux, rtp_session_t *session)
static void *no_init (demux_t *demux) static void *no_init (demux_t *demux)
{ {
return demux; (void)demux;
return NULL;
} }
static void no_destroy (demux_t *demux, void *opaque) static void no_destroy (demux_t *demux, void *opaque)
...@@ -124,6 +125,8 @@ int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt) ...@@ -124,6 +125,8 @@ int rtp_add_type (demux_t *demux, rtp_session_t *ses, const rtp_pt_t *pt)
ppt->decode = pt->decode ? pt->decode : no_decode; ppt->decode = pt->decode ? pt->decode : no_decode;
ppt->frequency = pt->frequency; ppt->frequency = pt->frequency;
ppt->number = pt->number; ppt->number = pt->number;
msg_Dbg (demux, "added payload type %"PRIu8" (f = %"PRIu32" Hz)",
ppt->number, ppt->frequency);
assert (ppt->frequency > 0); /* SIGFPE! */ assert (ppt->frequency > 0); /* SIGFPE! */
(void)demux; (void)demux;
...@@ -139,7 +142,7 @@ struct rtp_source_t ...@@ -139,7 +142,7 @@ struct rtp_source_t
uint16_t max_seq; /* next expected sequence */ uint16_t max_seq; /* next expected sequence */
block_t *blocks; /* re-ordered blocks queue */ block_t *blocks; /* re-ordered blocks queue */
void *opaque[0]; /* Per-source prviate payload data */ void *opaque[0]; /* Per-source private payload data */
}; };
/** /**
...@@ -347,7 +350,6 @@ rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src) ...@@ -347,7 +350,6 @@ rtp_decode (demux_t *demux, const rtp_session_t *session, rtp_source_t *src)
/* TODO: sync multiple sources sanely... */ /* TODO: sync multiple sources sanely... */
const uint32_t timestamp = GetDWBE (block->p_buffer + 4); const uint32_t timestamp = GetDWBE (block->p_buffer + 4);
block->i_pts = UINT64_C(1) * CLOCK_FREQ * timestamp / pt->frequency; block->i_pts = UINT64_C(1) * CLOCK_FREQ * timestamp / pt->frequency;
//msg_Dbg (demux, "pts = %"PRIu64, block->i_pts);
/* CSRC count */ /* CSRC count */
size_t skip = 12u + (block->p_buffer[0] & 0x0F) * 4; size_t skip = 12u + (block->p_buffer[0] & 0x0F) * 4;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment