[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