<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 27, 2015 at 5:32 PM, Rémi Denis-Courmont <span dir="ltr"><<a href="mailto:remi@remlab.net" target="_blank">remi@remlab.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Le mardi 27 janvier 2015, 16:49:31 Tristan Matthews a écrit :<br>
<span class="">> Supports RGB24 and I420, should be trivial to add other formats.<br>
> ---<br>
>  modules/stream_out/rtp.c    |  19 +++++<br>
>  modules/stream_out/rtp.h    |   4 +<br>
>  modules/stream_out/rtpfmt.c | 196<br>
> ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 219<br>
> insertions(+)<br>
><br>
> diff --git a/modules/stream_out/rtp.c b/modules/stream_out/rtp.c<br>
> index 98c5fb4..4762d47 100644<br>
> --- a/modules/stream_out/rtp.c<br>
> +++ b/modules/stream_out/rtp.c<br>
> @@ -361,6 +361,9 @@ struct sout_stream_id_sys_t<br>
>      uint32_t    i_ts_offset;<br>
>      uint8_t     ssrc[4];<br>
><br>
> +    /* For RFC 4175, seqnum is extended to 32-bits */<br>
> +    uint16_t    i_extended_sequence;<br>
> +<br>
<br>
</span>This is needlessly complicated. Just make the seq 32-bits.<br>
<div><div class="h5"><br>
>      /* for rtsp */<br>
>      uint16_t    i_seq_sent_next;<br>
><br>
> @@ -984,6 +987,7 @@ static sout_stream_id_sys_t *Add( sout_stream_t<br>
> *p_stream, es_format_t *p_fmt ) (int64_t)1000 * var_GetInteger( p_stream,<br>
> SOUT_CFG_PREFIX "caching");<br>
><br>
>      vlc_rand_bytes (&id->i_sequence, sizeof (id->i_sequence));<br>
> +    vlc_rand_bytes (&id->i_extended_sequence, sizeof<br>
> (id->i_extended_sequence)); vlc_rand_bytes (id->ssrc, sizeof (id->ssrc));<br>
><br>
>      bool format = false;<br>
> @@ -1002,6 +1006,7 @@ static sout_stream_id_sys_t *Add( sout_stream_t<br>
> *p_stream, es_format_t *p_fmt ) * initialized inside vod_init_id() to avoid<br>
> race<br>
>               * conditions. */<br>
>              id->i_sequence = id->i_seq_sent_next;<br>
> +            id->i_extended_sequence = 0;<br>
>          }<br>
>          /* vod_init_id() may fail either because the ES wasn't found in<br>
>           * the VoD media, or because the RTSP session is gone. In the<br>
> @@ -1045,6 +1050,7 @@ static sout_stream_id_sys_t *Add( sout_stream_t<br>
> *p_stream, es_format_t *p_fmt ) goto error;<br>
>          }<br>
>          id->i_sequence = 0; /* FIXME: awful hack for libvlc_srtp */<br>
> +        id->i_extended_sequence = 0;<br>
>      }<br>
>  #endif<br>
><br>
> @@ -1650,6 +1656,14 @@ void rtp_packetize_common( sout_stream_id_sys_t *id,<br>
> block_t *out, memcpy( out->p_buffer + 8, id->ssrc, 4 );<br>
><br>
>      id->i_sequence++;<br>
> +    /* Wrap-around to 0 just occured */<br>
> +    if (!id->i_sequence)<br>
> +        id->i_extended_sequence++;<br>
> +}<br>
> +<br>
> +uint16_t rtp_get_extended_sequence( sout_stream_id_sys_t *id )<br>
> +{<br>
> +    return id->i_extended_sequence;<br>
>  }<br>
><br>
>  void rtp_packetize_send( sout_stream_id_sys_t *id, block_t *out )<br>
> @@ -1797,3 +1811,8 @@ static sout_access_out_t *GrabberCreate( sout_stream_t<br>
> *p_stream ) p_grab->pf_write    = AccessOutGrabberWrite;<br>
>      return p_grab;<br>
>  }<br>
> +<br>
> +void rtp_get_video_geometry( sout_stream_id_sys_t *id, int *width, int<br>
> *height ) +{<br>
> +    sscanf( id->rtp_fmt.fmtp, "%*s width=%d; height=%d; ", width, height );<br>
> +}<br>
> diff --git a/modules/stream_out/rtp.h b/modules/stream_out/rtp.h<br>
> index ff26c69..01d6b61 100644<br>
> --- a/modules/stream_out/rtp.h<br>
> +++ b/modules/stream_out/rtp.h<br>
> @@ -89,6 +89,10 @@ typedef struct rtp_format_t<br>
>  int rtp_get_fmt( vlc_object_t *obj, es_format_t *p_fmt, const char *mux,<br>
>                   rtp_format_t *p_rtp_fmt );<br>
><br>
> +/* Only used by rtp_packetize_rawvideo */<br>
> +void rtp_get_video_geometry( sout_stream_id_sys_t *id, int *width, int<br>
> *height ); +uint16_t rtp_get_extended_sequence( sout_stream_id_sys_t *id );<br>
> +<br>
>  /* VoD */<br>
>  int  OpenVoD ( vlc_object_t * );<br>
>  void CloseVoD( vlc_object_t * );<br>
> diff --git a/modules/stream_out/rtpfmt.c b/modules/stream_out/rtpfmt.c<br>
> index d8c8621..1759c6a 100644<br>
> --- a/modules/stream_out/rtpfmt.c<br>
> +++ b/modules/stream_out/rtpfmt.c<br>
> @@ -6,6 +6,8 @@<br>
>   * $Id$<br>
>   *<br>
>   * Authors: Laurent Aimar <<a href="mailto:fenrir@via.ecp.fr">fenrir@via.ecp.fr</a>><br>
> + * RFC 4175 support based on gstrtpvrawpay.c (LGPL 2) by:<br>
> + * Wim Taymans <<a href="mailto:wim.taymans@gmail.com">wim.taymans@gmail.com</a>><br>
>   *<br>
>   * This program is free software; you can redistribute it and/or modify it<br>
>   * under the terms of the GNU Lesser General Public License as published by<br>
> @@ -57,6 +59,8 @@ static int rtp_packetize_g726_40 (sout_stream_id_sys_t *,<br>
> block_t *); static int rtp_packetize_xiph (sout_stream_id_sys_t *, block_t<br>
> *); static int rtp_packetize_vp8 (sout_stream_id_sys_t *, block_t *);<br>
> static int rtp_packetize_jpeg (sout_stream_id_sys_t *, block_t *); +static<br>
> int rtp_packetize_i420 (sout_stream_id_sys_t *, block_t *); +static int<br>
> rtp_packetize_rgb24 (sout_stream_id_sys_t *, block_t *);<br>
><br>
>  #define XIPH_IDENT (0)<br>
><br>
> @@ -524,6 +528,31 @@ int rtp_get_fmt( vlc_object_t *obj, es_format_t *p_fmt,<br>
> const char *mux, rtp_fmt->ptname = "VP8";<br>
>              rtp_fmt->pf_packetize = rtp_packetize_vp8;<br>
>              break;<br>
> +        case VLC_CODEC_I420:<br>
> +            rtp_fmt->ptname = "RAW";<br>
> +            rtp_fmt->pf_packetize = rtp_packetize_i420;<br>
> +            if( asprintf( &rtp_fmt->fmtp,<br>
> +                    "sampling=YCbCr-4:2:0; width=%d; height=%d; "<br>
> +                    "depth=8; colorimetry=BT%s",<br>
> +                    p_fmt->video.i_width, p_fmt->video.i_height,<br>
> +                    p_fmt->video.i_height > 576 ? "709-2" : "601-5") == -1<br>
> )<br>
<br>
</div></div>This won't work where visible dimensions are smaller.<br></blockquote><div><br></div><div>Would simply using i_visible_{width,height} do the trick or am I missing something?<br> <br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div class="h5"><br>
> +            {<br>
> +                rtp_fmt->fmtp = NULL;<br>
> +                return VLC_ENOMEM;<br>
> +            }<br>
> +            break;<br>
> +        case VLC_CODEC_RGB24:<br>
> +            rtp_fmt->ptname = "RAW";<br>
> +            rtp_fmt->pf_packetize = rtp_packetize_rgb24;<br>
> +            if( asprintf( &rtp_fmt->fmtp,<br>
> +                    "sampling=RGB; width=%d; height=%d; "<br>
> +                    "depth=8; colorimetry=SMPTE240M",<br>
> +                    p_fmt->video.i_width, p_fmt->video.i_height) == -1 )<br>
> +            {<br>
> +                rtp_fmt->fmtp = NULL;<br>
> +                return VLC_ENOMEM;<br>
> +            }<br>
> +            break;<br>
>          case VLC_CODEC_MJPG:<br>
>          case VLC_CODEC_JPEG:<br>
>              rtp_fmt->ptname = "JPEG";<br>
> @@ -1502,6 +1531,173 @@ static int rtp_packetize_vp8( sout_stream_id_sys_t<br>
> *id, block_t *in ) return VLC_SUCCESS;<br>
>  }<br>
><br>
> +<br>
> +/* See RFC 4175 */<br>
> +static int rtp_packetize_rawvideo( sout_stream_id_sys_t *id, block_t *in,<br>
> vlc_fourcc_t i_format  ) +{<br>
> +    int i_width, i_height;<br>
> +    rtp_get_video_geometry( id, &i_width, &i_height );<br>
> +    int i_pgroup; /* Size of a group of pixels */<br>
> +    int i_xdec, i_ydec; /* sub-sampling factor in x and y */<br>
> +    switch( i_format )<br>
> +    {<br>
> +        case VLC_CODEC_RGB24:<br>
> +            i_pgroup = 3;<br>
> +            i_xdec = i_ydec = 1;<br>
> +            break;<br>
> +        case VLC_CODEC_I420:<br>
> +            i_pgroup = 6;<br>
> +            i_xdec = i_ydec = 2;<br>
> +            break;<br>
> +        default:<br>
> +            assert(0);<br>
> +    }<br>
> +<br>
> +    static const int RTP_HEADER_LEN = 12;<br>
> +    /* each partial or complete line needs a 6 byte header */<br>
> +    const int i_line_header_size = 6;<br>
> +    const int i_min_line_size = i_line_header_size + i_pgroup;<br>
> +    uint8_t *p_data = in->p_buffer;<br>
> +<br>
> +    for( uint16_t i_line_number = 0, i_column = 0; i_line_number <<br>
> i_height; ) +    {<br>
> +        /* Allocate a packet */<br>
> +        int i_payload = (int)(rtp_mtu (id) - RTP_HEADER_LEN);<br>
> +        if( i_payload <= 0 )<br>
> +        {<br>
> +            block_Release( in );<br>
> +            return VLC_EGENERIC;<br>
> +        }<br>
> +<br>
> +        block_t *out = block_Alloc( RTP_HEADER_LEN + i_payload );<br>
> +        if( unlikely( out == NULL ) )<br>
> +        {<br>
> +            block_Release( in );<br>
> +            return VLC_ENOMEM;<br>
> +        }<br>
> +<br>
> +        /* Do headers first... */<br>
> +<br>
> +        /* Write extended seqnum */<br>
> +        uint8_t *p_outdata = out->p_buffer + RTP_HEADER_LEN;<br>
> +        SetWBE( p_outdata, rtp_get_extended_sequence( id ) );<br>
> +        p_outdata += 2;<br>
> +        i_payload -= 2;<br>
> +<br>
> +        uint8_t *p_headers = p_outdata;<br>
> +<br>
> +        for( uint8_t i_cont = 0x80; i_cont && i_payload > i_min_line_size;<br>
> ) +        {<br>
> +            i_payload -= i_line_header_size;<br>
> +<br>
> +            int i_pixels = i_width - i_column;<br>
> +            int i_length = (i_pixels * i_pgroup) / i_xdec;<br>
> +<br>
> +            const bool b_next_line = i_payload >= i_length;<br>
> +            if( !b_next_line )<br>
> +            {<br>
> +                i_pixels = (i_payload / i_pgroup) * i_xdec;<br>
> +                i_length = (i_pixels * i_pgroup) / i_xdec;<br>
> +            }<br>
> +<br>
> +            i_payload -= i_length;<br>
> +<br>
> +            /* write length */<br>
> +            SetWBE( p_outdata, i_length );<br>
> +            p_outdata += 2;<br>
> +<br>
> +            /* write line number */<br>
> +            /* TODO: support interlaced */<br>
> +            const uint8_t i_field = 0;<br>
> +            SetWBE( p_outdata, i_line_number );<br>
> +            *p_outdata |= i_field << 7;<br>
> +            p_outdata += 2;<br>
> +<br>
> +            /* continue if there's still room in the packet and we have<br>
> more lines */ +            i_cont = (i_payload > i_min_line_size &&<br>
> i_line_number < (i_height - i_ydec)) ? 0x80 : 0x00; +<br>
> +            /* write offset and continuation marker */<br>
> +            SetWBE( p_outdata, i_column );<br>
> +            *p_outdata |= i_cont;<br>
> +            p_outdata += 2;<br>
> +<br>
> +            if( b_next_line )<br>
> +            {<br>
> +                i_column = 0;<br>
> +                i_line_number += i_ydec;<br>
> +            }<br>
> +            else<br>
> +            {<br>
> +                i_column += i_pixels;<br>
> +            }<br>
> +        }<br>
> +<br>
> +        /* write the actual video data here */<br>
> +        for( uint8_t i_cont = 0x80; i_cont; p_headers += i_line_header_size<br>
> ) +        {<br>
> +            const uint16_t i_length = GetWBE( p_headers );<br>
> +            const uint16_t i_lin = GetWBE( p_headers + 2 ) & 0x7fff;<br>
> +            uint16_t i_offs = GetWBE( p_headers + 4 ) & 0x7fff;<br>
> +            i_cont = p_headers[4] & 0x80;<br>
> +<br>
> +            if( i_format == VLC_CODEC_RGB24 )<br>
> +            {<br>
> +                const int i_ystride = i_width * i_pgroup;<br>
> +                i_offs /= i_xdec;<br>
> +                memcpy( p_outdata, p_data + (i_lin * i_ystride) + (i_offs *<br>
> i_pgroup), i_length ); +                p_outdata += i_length;<br>
> +            }<br>
> +            else if( i_format == VLC_CODEC_I420 )<br>
> +            {<br>
> +                const int i_ystride = i_width;<br>
> +                const uint8_t *p_u = p_data + i_width * i_height;<br>
> +                const uint8_t *p_v = p_u + (i_width * i_height) / (i_xdec *<br>
> i_ydec); +                const int i_uvstride = i_width / i_xdec;<br>
> +<br>
> +                const uint8_t *p_yd1 = p_data + (i_lin * i_ystride) +<br>
> i_offs; +                const uint8_t *p_yd2 = p_yd1 + i_ystride;<br>
> +                const unsigned i_uvoff = (i_lin / i_ydec * i_uvstride) +<br>
> (i_offs / i_xdec); +                const uint8_t *p_ud = p_u + i_uvoff;<br>
> +                const uint8_t *p_vd = p_v + i_uvoff;<br>
> +<br>
> +                unsigned i_pixels = i_length / i_pgroup;<br>
> +                while( i_pixels-- )<br>
> +                {<br>
> +                    *p_outdata++ = *p_yd1++;<br>
> +                    *p_outdata++ = *p_yd1++;<br>
> +                    *p_outdata++ = *p_yd2++;<br>
> +                    *p_outdata++ = *p_yd2++;<br>
> +                    *p_outdata++ = *p_ud++;<br>
> +                    *p_outdata++ = *p_vd++;<br>
> +                }<br>
> +            }<br>
> +            else assert(0);<br>
> +        }<br>
> +<br>
> +        /* rtp common header */<br>
> +        rtp_packetize_common( id, out, i_line_number >= i_height,<br>
> +                (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );<br>
> +<br>
> +        out->i_dts    = in->i_dts;<br>
> +        out->i_length = in->i_length;<br>
> +<br>
> +        rtp_packetize_send( id, out );<br>
> +    }<br>
> +<br>
> +    block_Release( in );<br>
> +    return VLC_SUCCESS;<br>
> +}<br>
> +<br>
> +static int rtp_packetize_i420( sout_stream_id_sys_t *id, block_t *in )<br>
> +{<br>
> +    return rtp_packetize_rawvideo( id, in, VLC_CODEC_I420 );<br>
> +}<br>
> +<br>
> +static int rtp_packetize_rgb24( sout_stream_id_sys_t *id, block_t *in )<br>
> +{<br>
> +    return rtp_packetize_rawvideo( id, in, VLC_CODEC_RGB24 );<br>
> +}<br>
> +<br>
>  static int rtp_packetize_jpeg( sout_stream_id_sys_t *id, block_t *in )<br>
>  {<br>
>      uint8_t *p_data = in->p_buffer;<br>
<br>
--<br>
</div></div>Rémi Denis-Courmont<br>
<a href="http://www.remlab.net/" target="_blank">http://www.remlab.net/</a><br>
<br>
_______________________________________________<br>
vlc-devel mailing list<br>
To unsubscribe or modify your subscription options:<br>
<a href="https://mailman.videolan.org/listinfo/vlc-devel" target="_blank">https://mailman.videolan.org/listinfo/vlc-devel</a><br>
</blockquote></div><br></div></div>