[vlc-devel] [PATCH] demux: mjpeg: rework using packetizer

Francois Cartegnie fcvlcdev at free.fr
Wed Jun 13 17:45:57 CEST 2018


Unsure if we really want to do this 
or still match EOI (no packetizer delay when set)

---
 modules/demux/mjpeg.c | 155 ++++++++++++++++++++++++++++----------------------
 1 file changed, 88 insertions(+), 67 deletions(-)

diff --git a/modules/demux/mjpeg.c b/modules/demux/mjpeg.c
index d0355f35ea..ce0c3b3db3 100644
--- a/modules/demux/mjpeg.c
+++ b/modules/demux/mjpeg.c
@@ -35,12 +35,14 @@
 #include <vlc_common.h>
 #include <vlc_plugin.h>
 #include <vlc_demux.h>
+#include <vlc_codec.h>
 #include "mxpeg_helper.h"
 
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
 static int  Open ( vlc_object_t * );
+static void Close( vlc_object_t * );
 
 #define FPS_TEXT N_("Frames per Second")
 #define FPS_LONGTEXT N_("This is the desired frame rate when " \
@@ -51,7 +53,7 @@ vlc_module_begin ()
     set_shortname( "MJPEG")
     set_description( N_("M-JPEG camera demuxer") )
     set_capability( "demux", 5 )
-    set_callbacks( Open, NULL )
+    set_callbacks( Open, Close )
     set_category( CAT_INPUT )
     set_subcategory( SUBCAT_INPUT_DEMUX )
     add_float( "mjpeg-fps", 0.0, FPS_TEXT, FPS_LONGTEXT, false )
@@ -78,6 +80,8 @@ typedef struct
     const uint8_t   *p_peek;
     int             i_data_peeked;
     int             i_level;
+
+    decoder_t      *p_packetizer;
 } demux_sys_t;
 
 /*****************************************************************************
@@ -256,31 +260,32 @@ static bool CheckMimeHeader( demux_t *p_demux, int *p_header_size )
     return b_jpeg;
 }
 
-static int SendBlock( demux_t *p_demux, int i )
+static void DateAndSendBlock( demux_t *p_demux, block_t *p_block )
 {
     demux_sys_t *p_sys = p_demux->p_sys;
-    block_t     *p_block;
-
-    if( ( p_block = vlc_stream_Block( p_demux->s, i ) ) == NULL )
-    {
-        msg_Warn( p_demux, "cannot read data" );
-        return VLC_DEMUXER_EOF;
-    }
 
+    mtime_t i_dts;
     if( p_sys->i_frame_length )
     {
-        p_block->i_pts = p_sys->i_time;
-        p_sys->i_time += p_sys->i_frame_length;
+        i_dts = (p_sys->i_time != VLC_TS_INVALID) ? p_sys->i_time : VLC_TS_0;
+        p_block->i_length = p_sys->i_frame_length;
     }
     else
     {
-        p_block->i_pts = mdate();
+        i_dts = mdate();
+        p_block->i_length = 0;
     }
-    p_block->i_dts = p_block->i_pts;
+    p_block->i_pts = p_block->i_dts = i_dts;
+
+    /* Set clock before sending */
+    if( p_sys->i_time == VLC_TS_INVALID )
+        es_out_SetPCR( p_demux->out, i_dts );
 
-    es_out_SetPCR( p_demux->out, p_block->i_pts );
     es_out_Send( p_demux->out, p_sys->p_es, p_block );
 
+    p_sys->i_time = i_dts + p_sys->i_frame_length;
+    es_out_SetPCR( p_demux->out, p_sys->i_time );
+
     if( p_sys->b_still )
         p_sys->i_still_end = mdate() + p_sys->i_frame_length;
 
@@ -300,15 +305,16 @@ static int Open( vlc_object_t * p_this )
         // let avformat handle this case
         return VLC_EGENERIC;
 
-    demux_sys_t *p_sys = vlc_obj_malloc( p_this, sizeof (*p_sys) );
+    demux_sys_t *p_sys = malloc( sizeof( demux_sys_t ) );
     if( unlikely(p_sys == NULL) )
         return VLC_ENOMEM;
 
     p_demux->p_sys      = p_sys;
     p_sys->p_es         = NULL;
-    p_sys->i_time       = VLC_TS_0;
+    p_sys->i_time       = VLC_TS_INVALID;
     p_sys->i_level      = 0;
 
+    p_sys->p_packetizer  = NULL;
     p_sys->psz_separator = NULL;
     p_sys->i_frame_size_estimate = 15 * 1024;
 
@@ -327,11 +333,11 @@ static int Open( vlc_object_t * p_this )
                 boundary[len-1] = '\0';
                 boundary++;
             }
-            p_sys->psz_separator = vlc_obj_strdup( p_this, boundary );
+            p_sys->psz_separator = strdup( boundary );
             if( !p_sys->psz_separator )
             {
                 free( content_type );
-                return VLC_ENOMEM;
+                goto error;
             }
         }
         free( content_type );
@@ -342,7 +348,7 @@ static int Open( vlc_object_t * p_this )
     {
         p_demux->pf_demux = MimeDemux;
         if( vlc_stream_Read( p_demux->s, NULL, i_size ) < i_size )
-            return VLC_EGENERIC;
+            goto error;
     }
     else if( i_size == 0 )
     {
@@ -355,12 +361,12 @@ static int Open( vlc_object_t * p_this )
         }
         else
         {
-            return VLC_EGENERIC;
+            goto error;
         }
     }
     else
     {
-        return VLC_EGENERIC;
+        goto error;
     }
 
     /* Frame rate */
@@ -384,10 +390,27 @@ static int Open( vlc_object_t * p_this )
 
     p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt );
     if( unlikely(p_sys->p_es == NULL) )
-        return VLC_ENOMEM;
+        goto error;
+
+    /* Load the mpegvideo packetizer */
+    if( p_demux->pf_demux == MjpgDemux )
+    {
+        es_format_t fmt;
+        es_format_Copy( &fmt, &p_sys->fmt );
+        fmt.video.i_frame_rate = f_fps * 10000;
+        fmt.video.i_frame_rate_base = 10000;
+        p_sys->p_packetizer = demux_PacketizerNew( p_demux, &fmt, "mjpeg" );
+        if( !p_sys->p_packetizer )
+            goto error;
+    }
 
     p_demux->pf_control = Control;
     return VLC_SUCCESS;
+
+error:
+    free( p_sys->psz_separator );
+    free( p_sys );
+    return VLC_EGENERIC;
 }
 
 /*****************************************************************************
@@ -395,58 +418,33 @@ static int Open( vlc_object_t * p_this )
  *****************************************************************************
  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  *****************************************************************************/
-static int MjpgDemux( demux_t *p_demux )
+static int MjpgDemux( demux_t *p_demux)
 {
     demux_sys_t *p_sys = p_demux->p_sys;
-    int i;
+    block_t *p_block_in, *p_block_out;
+    bool b_eof = false;
 
-    if( p_sys->b_still && p_sys->i_still_end )
-    {
-        /* Still frame, wait until the pause delay is gone */
-        mwait( p_sys->i_still_end );
-        p_sys->i_still_end = 0;
-        return VLC_DEMUXER_SUCCESS;
-    }
+    p_block_in = vlc_stream_Block( p_demux->s, p_sys->i_frame_size_estimate );
+    if( p_block_in == NULL )
+        b_eof = true;
 
-    if( !Peek( p_demux, true ) )
-    {
-        msg_Warn( p_demux, "cannot peek data" );
-        return VLC_DEMUXER_EOF;
-    }
-    if( p_sys->i_data_peeked < 4 )
-    {
-        msg_Warn( p_demux, "data shortage" );
-        return VLC_DEMUXER_EOF;
-    }
-    i = 3;
-FIND_NEXT_EOI:
-    while( !( p_sys->p_peek[i-1] == 0xFF && p_sys->p_peek[i] == 0xD9 ) )
+    while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer,
+                                                             p_block_in ? &p_block_in : NULL )) )
     {
-        if( p_sys->p_peek[i-1] == 0xFF && p_sys->p_peek[i] == 0xD9  )
+        while( p_block_out )
         {
-            p_sys->i_level++;
-            msg_Dbg( p_demux, "we found another JPEG SOI at %d", i );
-        }
-        i++;
-        if( i >= p_sys->i_data_peeked )
-        {
-            msg_Dbg( p_demux, "did not find JPEG EOI in %d bytes",
-                     p_sys->i_data_peeked );
-            if( !Peek( p_demux, false ) )
-            {
-                msg_Warn( p_demux, "no more data is available at the moment" );
-                return VLC_DEMUXER_EOF;
-            }
-        }
-    }
-    i++;
+            if( p_block_out->i_buffer > p_sys->i_frame_size_estimate )
+                p_sys->i_frame_size_estimate = p_block_out->i_buffer;
+
+            block_t *p_next = p_block_out->p_next;
+            p_block_out->p_next = NULL;
 
-    msg_Dbg( p_demux, "JPEG EOI detected at %d", i );
-    p_sys->i_level--;
+            DateAndSendBlock( p_demux, p_block_out );
 
-    if( p_sys->i_level > 0 )
-        goto FIND_NEXT_EOI;
-    return SendBlock( p_demux, i );
+            p_block_out = p_next;
+        }
+    }
+    return (b_eof) ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS;
 }
 
 static int MimeDemux( demux_t *p_demux )
@@ -526,7 +524,30 @@ static int MimeDemux( demux_t *p_demux )
         return VLC_DEMUXER_EOF;
     }
 
-    return SendBlock( p_demux, i );
+    block_t *p_block;
+    if( ( p_block = vlc_stream_Block( p_demux->s, i ) ) == NULL )
+    {
+        msg_Warn( p_demux, "cannot read data" );
+        return VLC_DEMUXER_EOF;
+    }
+
+    DateAndSendBlock( p_demux, p_block );
+
+    return VLC_DEMUXER_SUCCESS;
+}
+
+/*****************************************************************************
+ * Close: frees unused data
+ *****************************************************************************/
+static void Close ( vlc_object_t * p_this )
+{
+    demux_t     *p_demux = (demux_t*)p_this;
+    demux_sys_t *p_sys  = p_demux->p_sys;
+
+    if( p_sys->p_packetizer )
+        demux_PacketizerDestroy( p_sys->p_packetizer );
+    free( p_sys->psz_separator );
+    free( p_sys );
 }
 
 /*****************************************************************************
-- 
2.14.4



More information about the vlc-devel mailing list