📄 rtp.c
字号:
return VLC_EGENERIC;}/** * Checks if a file descriptor is hung up. */static bool fd_dead (int fd){ struct pollfd ufd = { .fd = fd, }; return (poll (&ufd, 1, 0) == 1) && (ufd.revents & POLLHUP);}/** * Gets a datagram from the network, or NULL in case of fatal error. */static block_t *rtp_dgram_recv (demux_t *demux, int fd){ block_t *block = block_Alloc (0xffff); ssize_t len; do { len = net_Read (VLC_OBJECT (demux), fd, NULL, block->p_buffer, block->i_buffer, false); if (((len <= 0) && fd_dead (fd)) || !vlc_object_alive (demux)) { block_Release (block); return NULL; } } while (len == -1); return block_Realloc (block, 0, len);}/** * Gets a framed RTP packet, or NULL in case of fatal error. */static block_t *rtp_stream_recv (demux_t *demux, int fd){ ssize_t len = 0; uint8_t hdr[2]; /* frame header */ /* Receives the RTP frame header */ do { ssize_t val = net_Read (VLC_OBJECT (demux), fd, NULL, hdr + len, 2 - len, false); if (val <= 0) return NULL; len += val; } while (len < 2); block_t *block = block_Alloc (GetWBE (hdr)); /* Receives the RTP packet */ for (ssize_t i = 0; i < len;) { ssize_t val; val = net_Read (VLC_OBJECT (demux), fd, NULL, block->p_buffer + i, block->i_buffer - i, false); if (val <= 0) { block_Release (block); return NULL; } i += val; } return block;}/* * 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 ); 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){ return stream_DemuxNew (demux, name, demux->out);}static void stream_destroy (demux_t *demux, void *data){ if (data) stream_DemuxDelete ((stream_t *)data); (void)demux;}/* Send a packet to a chained demuxer */static void stream_decode (demux_t *demux, void *data, block_t *block){ if (data) stream_DemuxSend ((stream_t *)data, block); else block_Release (block); (void)demux;}/* * Static payload types handler *//* PT=0 * PCMU: G.711 µ-law (RFC3551) */static void *pcmu_init (demux_t *demux){ es_format_t fmt; es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('u', 'l', 'a', 'w')); fmt.audio.i_rate = 8000; fmt.audio.i_channels = 1; return codec_init (demux, &fmt);}/* PT=8 * PCMA: G.711 A-law (RFC3551) */static void *pcma_init (demux_t *demux){ es_format_t fmt; es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('a', 'l', 'a', 'w')); fmt.audio.i_rate = 8000; fmt.audio.i_channels = 1; return codec_init (demux, &fmt);}/* PT=10,11 * L16: 16-bits (network byte order) PCM */static void *l16s_init (demux_t *demux){ es_format_t fmt; es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('s', '1', '6', 'b')); fmt.audio.i_rate = 44100; fmt.audio.i_channels = 2; return codec_init (demux, &fmt);}static void *l16m_init (demux_t *demux){ es_format_t fmt; es_format_Init (&fmt, AUDIO_ES, VLC_FOURCC ('s', '1', '6', 'b')); fmt.audio.i_rate = 44100; fmt.audio.i_channels = 1; return codec_init (demux, &fmt);}/* 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 * MP2: MPEG TS (RFC2250, §2) */static void *ts_init (demux_t *demux){ return stream_init (demux, "ts");}/* * Dynamic payload type handlers * Hmm, none implemented yet. *//** * Processing callback */static int Demux (demux_t *demux){ demux_sys_t *p_sys = demux->p_sys; block_t *block; block = p_sys->framed_rtp ? rtp_stream_recv (demux, p_sys->fd) : rtp_dgram_recv (demux, p_sys->fd); if (!block) return 0; if (block->i_buffer < 2) goto drop; const uint8_t ptype = block->p_buffer[1] & 0x7F; if (ptype >= 72 && ptype <= 76) goto drop; /* Muxed RTCP, ignore for now */ if (p_sys->srtp) { size_t len = block->i_buffer; if (srtp_recv (p_sys->srtp, block->p_buffer, &len)) { msg_Dbg (demux, "SRTP authentication/decryption failed"); goto drop; } block->i_buffer = len; } /* Not using SDP, we need to guess the payload format used */ /* see http://www.iana.org/assignments/rtp-parameters */ if (p_sys->autodetect) { rtp_pt_t pt = { .init = NULL, .destroy = codec_destroy, .decode = codec_decode, .frequency = 0, .number = ptype, }; switch (ptype) { case 0: msg_Dbg (demux, "detected G.711 mu-law"); pt.init = pcmu_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 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.decode = stream_decode; pt.frequency = 90000; break; default: goto drop; } rtp_add_type (demux, p_sys->session, &pt); p_sys->autodetect = false; } rtp_receive (demux, p_sys->session, block); return 1;drop: block_Release (block); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -