[vlc-devel] [PATCH 3/3] [WIP] JPEG RTP packetization

Andrey Utkin andrey.krieger.utkin at gmail.com
Sun Dec 8 03:25:31 CET 2013


---
 modules/stream_out/rtpfmt.c | 127 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 127 insertions(+)

diff --git a/modules/stream_out/rtpfmt.c b/modules/stream_out/rtpfmt.c
index 014d2dc..50ffef2 100644
--- a/modules/stream_out/rtpfmt.c
+++ b/modules/stream_out/rtpfmt.c
@@ -54,6 +54,7 @@ static int rtp_packetize_g726_32 (sout_stream_id_t *, block_t *);
 static int rtp_packetize_g726_40 (sout_stream_id_t *, block_t *);
 static int rtp_packetize_xiph (sout_stream_id_t *, block_t *);
 static int rtp_packetize_vp8 (sout_stream_id_t *, block_t *);
+static int rtp_packetize_jpeg (sout_stream_id_t *, block_t *);
 
 #define XIPH_IDENT (0)
 
@@ -521,6 +522,12 @@ int rtp_get_fmt( vlc_object_t *obj, es_format_t *p_fmt, const char *mux,
             rtp_fmt->ptname = "VP8";
             rtp_fmt->pf_packetize = rtp_packetize_vp8;
             break;
+        case VLC_CODEC_MJPG:
+        case VLC_CODEC_JPEG:
+            rtp_fmt->ptname = "JPEG";
+            rtp_fmt->payload_type = 26;
+            rtp_fmt->pf_packetize = rtp_packetize_jpeg;
+            break;
 
         default:
             msg_Err( obj, "cannot add this stream (unsupported "
@@ -1421,3 +1428,123 @@ static int rtp_packetize_vp8( sout_stream_id_t *id, block_t *in )
 
     return VLC_SUCCESS;
 }
+
+static int rtp_packetize_jpeg( sout_stream_id_t *id, block_t *in )
+{
+    uint8_t *p_data = in->p_buffer;
+    int     i_data  = in->i_buffer;
+
+    const uint8_t *qtables = NULL;
+    int nb_qtables = 0;
+    int off  = 0; // fragment offset in frame
+    // TODO Set by pixel format:
+    // 0 for yuvj422p
+    // 1 for yuvj420p
+    int type = 1; // FIXME HARDCODE
+    int w = 0; // Width in multiples of 8
+    int h = 0; // Height in multiples of 8
+
+    uint8_t *buf = p_data;
+    int size = i_data;
+    /* preparse the header for getting some infos */
+    int i;
+    for (i = 0; i < size; i++) {
+        if (buf[i] != 0xff)
+            continue;
+
+        if (buf[i + 1] == 0xdb /* DQT */) {
+            if (buf[i + 4])
+                assert(0);
+                //av_log(s1, AV_LOG_WARNING,
+                  //     "Only 8-bit precision is supported.\n");
+
+            /* a quantization table is 64 bytes long */
+            nb_qtables = /*AV_RB16*/GetWBE(&buf[i + 2]) / 65;
+            if (i + 4 + nb_qtables * 65 > size) {
+                assert(0);
+                //av_log(s1, AV_LOG_ERROR, "Too short JPEG header. Aborted!\n");
+                return VLC_EGENERIC;
+            }
+
+            qtables = &buf[i + 4];
+        } else if (buf[i + 1] == 0xc0 /*SOF0*/) {
+            int height = GetWBE(&buf[i + 1 + 4]);
+            int width = GetWBE(&buf[i + 1 + 6]);
+            w = width >> 3;
+            h = height >> 3;
+
+
+            if (buf[i + 14] != 17 || buf[i + 17] != 17) {
+                assert(0);
+                //av_log(s1, AV_LOG_ERROR,
+                  //     "Only 1x1 chroma blocks are supported. Aborted!\n");
+                return VLC_EGENERIC;
+            }
+        } else if (buf[i + 1] == 0xda /*SOS*/) {
+            /* SOS is last marker in the header */
+            i += /*AV_RB16*/GetWBE(&buf[i + 2]) + 2;
+            break;
+        }
+    }
+    assert (w);
+    assert (h);
+    //fprintf(stderr, "width %d, height %d x8\n", w, h);
+
+    /* skip JPEG header */
+    buf  += i;
+    size -= i;
+
+    i_data = size;
+    p_data = buf;
+
+    while ( i_data )
+    {
+        int hdr_size = 8;
+        if (off == 0 && nb_qtables)
+            hdr_size += 4 + 64 * nb_qtables;
+
+        int i_payload = __MIN( i_data, rtp_mtu (id) - hdr_size );
+
+        block_t *out = block_Alloc( 12 + hdr_size + i_payload );
+
+        uint8_t *p = out->p_buffer + 12;
+        /* set main header */
+        /* set type-specific=0, set offset in following 24 bits: */
+        SetDWBE (p, off & 0x00ffffff);
+        p += 4;
+        *p++ = type;
+        *p++ = 255;
+        *p++ = w;
+        *p++ = h;
+        if (off == 0 && nb_qtables)
+        {
+            /* set quantization tables header */
+            *p++ = 0;
+            *p++ = 0;
+            SetWBE (p, 64 * nb_qtables);
+            p += 2;
+            for (int i = 0; i < nb_qtables; i++)
+            {
+                memcpy (p, &qtables[65 * i + 1], 64);
+                p += 64;
+            }
+        }
+
+        /* rtp common header */
+        rtp_packetize_common( id, out, (i_payload == i_data),
+                      (in->i_pts > VLC_TS_INVALID ? in->i_pts : in->i_dts) );
+        memcpy( p, p_data, i_payload );
+
+        out->i_buffer = 12 + hdr_size + i_payload;
+        out->i_dts    = in->i_dts + in->i_length * off / in->i_buffer;
+        out->i_length = in->i_length * i_payload / in->i_buffer;
+
+        rtp_packetize_send( id, out );
+
+        p_data += i_payload;
+        i_data -= i_payload;
+        off    += i_payload;
+    }
+
+    return VLC_SUCCESS;
+}
-- 
1.8.1.5




More information about the vlc-devel mailing list