Commit dd521c46 authored by Christophe Massiot's avatar Christophe Massiot

* Implementation of a frame-dropping algorithm for the libmpeg2 plug-in

  (incomplete).
parent 899ac5e2
...@@ -203,6 +203,7 @@ HEADERS_include = \ ...@@ -203,6 +203,7 @@ HEADERS_include = \
include/vlc_playlist.h \ include/vlc_playlist.h \
include/vlc_threads.h \ include/vlc_threads.h \
include/vlc_threads_funcs.h \ include/vlc_threads_funcs.h \
include/vout_synchro.h \
include/win32_specific.h \ include/win32_specific.h \
include/osd.h \ include/osd.h \
$(NULL) $(NULL)
...@@ -387,6 +388,7 @@ SOURCES_libvlc_common = \ ...@@ -387,6 +388,7 @@ SOURCES_libvlc_common = \
src/video_output/video_text.c \ src/video_output/video_text.c \
src/video_output/video_text.h \ src/video_output/video_text.h \
src/video_output/vout_subpictures.c \ src/video_output/vout_subpictures.c \
src/video_output/vout_synchro.c \
src/audio_output/common.c \ src/audio_output/common.c \
src/audio_output/dec.c \ src/audio_output/dec.c \
src/audio_output/filters.c \ src/audio_output/filters.c \
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions * Collection of useful common types and macros definitions
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.60 2003/04/13 20:00:20 fenrir Exp $ * $Id: vlc_common.h,v 1.61 2003/04/14 22:22:32 massiot Exp $
* *
* Authors: Samuel Hocevar <sam@via.ecp.fr> * Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr> * Vincent Seguin <seguin@via.ecp.fr>
...@@ -242,6 +242,7 @@ typedef struct picture_sys_t picture_sys_t; ...@@ -242,6 +242,7 @@ typedef struct picture_sys_t picture_sys_t;
typedef struct picture_heap_t picture_heap_t; typedef struct picture_heap_t picture_heap_t;
typedef struct subpicture_t subpicture_t; typedef struct subpicture_t subpicture_t;
typedef struct subpicture_sys_t subpicture_sys_t; typedef struct subpicture_sys_t subpicture_sys_t;
typedef struct vout_synchro_t vout_synchro_t;
/* Stream output */ /* Stream output */
typedef struct sout_instance_t sout_instance_t; typedef struct sout_instance_t sout_instance_t;
......
/*****************************************************************************
* vout_synchro.h: frame-dropping structures
*****************************************************************************
* Copyright (C) 1999-2003 VideoLAN
* $Id: vout_synchro.h,v 1.1 2003/04/14 22:22:32 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Jean-Marc Dressler <polux@via.ecp.fr>
* Stphane Borel <stef@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* vout_synchro_t : timers for the video synchro
*****************************************************************************/
#define MAX_PIC_AVERAGE 8
/* Read the discussion on top of vout_synchro.c for more information. */
struct vout_synchro_t
{
VLC_COMMON_MEMBERS
vout_thread_t * p_vout;
int i_frame_rate;
int i_current_rate;
/* date of the beginning of the decoding of the current picture */
mtime_t decoding_start;
/* stream properties */
unsigned int i_n_p, i_n_b;
/* decoding values */
mtime_t p_tau[4]; /* average decoding durations */
unsigned int pi_meaningful[4]; /* number of durations read */
/* and p_vout->render_time (read with p_vout->change_lock) */
/* stream context */
vlc_bool_t i_nb_ref; /* Number of reference pictures */
unsigned int i_eta_p, i_eta_b;
mtime_t backward_pts, current_pts;
int i_current_period; /* period to add to the next picture */
int i_backward_period; /* period to add after the next
* reference picture
* (backward_period * period / 2) */
/* statistics */
unsigned int i_trashed_pic, i_not_chosen_pic, i_pic;
};
/* Pictures types */
#define I_CODING_TYPE 1
#define P_CODING_TYPE 2
#define B_CODING_TYPE 3
#define D_CODING_TYPE 4 /* MPEG-1 ONLY */
/* other values are reserved */
/* Structures */
#define TOP_FIELD 1
#define BOTTOM_FIELD 2
#define FRAME_STRUCTURE 3
/*****************************************************************************
* Prototypes
*****************************************************************************/
#define vout_SynchroInit(a,b,c) __vout_SynchroInit(VLC_OBJECT(a),b,c)
VLC_EXPORT( vout_synchro_t *, __vout_SynchroInit, ( vlc_object_t *, vout_thread_t *, int ) );
VLC_EXPORT( void, vout_SynchroRelease, ( vout_synchro_t * ) );
VLC_EXPORT( void, vout_SynchroReset, ( vout_synchro_t * ) );
VLC_EXPORT( vlc_bool_t, vout_SynchroChoose, ( vout_synchro_t *, int ) );
VLC_EXPORT( void, vout_SynchroTrash, ( vout_synchro_t * ) );
VLC_EXPORT( void, vout_SynchroDecode, ( vout_synchro_t * ) );
VLC_EXPORT( void, vout_SynchroEnd, ( vout_synchro_t *, int, vlc_bool_t ) );
VLC_EXPORT( mtime_t, vout_SynchroDate, ( vout_synchro_t * ) );
VLC_EXPORT( void, vout_SynchroNewPicture, ( vout_synchro_t *, int, int, mtime_t, mtime_t, int ) );
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* libmpeg2.c: mpeg2 video decoder module making use of libmpeg2. * libmpeg2.c: mpeg2 video decoder module making use of libmpeg2.
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: libmpeg2.c,v 1.8 2003/04/07 17:35:01 gbazin Exp $ * $Id: libmpeg2.c,v 1.9 2003/04/14 22:22:32 massiot Exp $
* *
* Authors: Gildas Bazin <gbazin@netcourrier.com> * Authors: Gildas Bazin <gbazin@netcourrier.com>
* *
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include <mpeg2dec/mpeg2.h> #include <mpeg2dec/mpeg2.h>
#include "vout_synchro.h"
/* Aspect ratio (ISO/IEC 13818-2 section 6.3.3, table 6-3) */ /* Aspect ratio (ISO/IEC 13818-2 section 6.3.3, table 6-3) */
#define AR_SQUARE_PICTURE 1 /* square pixels */ #define AR_SQUARE_PICTURE 1 /* square pixels */
#define AR_3_4_PICTURE 2 /* 3:4 picture (TV) */ #define AR_3_4_PICTURE 2 /* 3:4 picture (TV) */
...@@ -60,11 +62,14 @@ typedef struct dec_thread_t ...@@ -60,11 +62,14 @@ typedef struct dec_thread_t
mtime_t i_previous_pts; mtime_t i_previous_pts;
mtime_t i_current_pts; mtime_t i_current_pts;
mtime_t i_period_remainder; mtime_t i_period_remainder;
int i_current_rate;
picture_t * p_picture_to_destroy;
/* /*
* Output properties * Output properties
*/ */
vout_thread_t *p_vout; vout_thread_t *p_vout;
vout_synchro_t *p_synchro;
} dec_thread_t; } dec_thread_t;
...@@ -102,6 +107,7 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -102,6 +107,7 @@ static int OpenDecoder( vlc_object_t *p_this )
p_fifo->pf_run = RunDecoder; p_fifo->pf_run = RunDecoder;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
* RunDecoder: the libmpeg2 decoder * RunDecoder: the libmpeg2 decoder
*****************************************************************************/ *****************************************************************************/
...@@ -132,6 +138,7 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -132,6 +138,7 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
p_dec->i_current_pts = 0; p_dec->i_current_pts = 0;
p_dec->i_previous_pts = 0; p_dec->i_previous_pts = 0;
p_dec->i_period_remainder = 0; p_dec->i_period_remainder = 0;
p_dec->p_picture_to_destroy = NULL;
/* Initialize decoder */ /* Initialize decoder */
p_dec->p_mpeg2dec = mpeg2_init(); p_dec->p_mpeg2dec = mpeg2_init();
...@@ -163,6 +170,14 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -163,6 +170,14 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
break; break;
} }
if( p_dec->p_pes->b_discontinuity )
{
vout_SynchroReset( p_dec->p_synchro );
if ( p_dec->p_info->current_fbuf != NULL )
p_dec->p_picture_to_destroy
= p_dec->p_info->current_fbuf->id;
}
if( p_dec->p_pes->i_pts ) if( p_dec->p_pes->i_pts )
{ {
mpeg2_pts( p_dec->p_mpeg2dec, mpeg2_pts( p_dec->p_mpeg2dec,
...@@ -170,6 +185,8 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -170,6 +185,8 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
p_dec->i_previous_pts = p_dec->i_current_pts; p_dec->i_previous_pts = p_dec->i_current_pts;
p_dec->i_current_pts = p_dec->p_pes->i_pts; p_dec->i_current_pts = p_dec->p_pes->i_pts;
} }
p_dec->i_current_rate = p_dec->p_pes->i_rate;
p_data = p_dec->p_pes->p_first; p_data = p_dec->p_pes->p_first;
} }
...@@ -187,6 +204,7 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -187,6 +204,7 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
{ {
/* Initialize video output */ /* Initialize video output */
uint8_t *buf[3]; uint8_t *buf[3];
buf[0] = buf[1] = buf[2] = NULL;
/* Check whether the input gives a particular aspect ratio */ /* Check whether the input gives a particular aspect ratio */
if( p_dec->p_fifo->p_demux_data if( p_dec->p_fifo->p_demux_data
...@@ -231,76 +249,86 @@ static int RunDecoder( decoder_fifo_t *p_fifo ) ...@@ -231,76 +249,86 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
mpeg2_custom_fbuf( p_dec->p_mpeg2dec, 1 ); mpeg2_custom_fbuf( p_dec->p_mpeg2dec, 1 );
/* Set the first 2 reference frames */ /* Set the first 2 reference frames */
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break; mpeg2_set_buf( p_dec->p_mpeg2dec, buf, NULL );
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic ); mpeg2_set_buf( p_dec->p_mpeg2dec, buf, NULL );
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic ); p_dec->p_synchro = vout_SynchroInit( p_dec->p_fifo, p_dec->p_vout,
1000000 * 27 / p_dec->p_info->sequence->frame_period * 1001 );
} }
break; break;
case STATE_PICTURE: case STATE_PICTURE:
{ {
uint8_t *buf[3]; uint8_t *buf[3];
buf[0] = buf[1] = buf[2] = NULL;
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic ); vout_SynchroNewPicture( p_dec->p_synchro,
p_dec->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
/* Store the date for the picture */ p_dec->p_info->current_picture->nb_fields,
if( p_dec->p_info->current_picture->flags & PIC_FLAG_PTS ) (p_dec->p_info->current_picture->flags & PIC_FLAG_PTS) ?
( (p_dec->p_info->current_picture->pts ==
(uint32_t)p_dec->i_current_pts) ?
p_dec->i_current_pts : p_dec->i_previous_pts ) : 0,
0,
p_dec->i_current_rate );
if ( !vout_SynchroChoose( p_dec->p_synchro,
p_dec->p_info->current_picture->flags & PIC_MASK_CODING_TYPE ) )
{
mpeg2_skip( p_dec->p_mpeg2dec, 1 );
vout_SynchroTrash( p_dec->p_synchro );
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, NULL );
}
else
{ {
p_pic->date = ( p_dec->p_info->current_picture->pts == mpeg2_skip( p_dec->p_mpeg2dec, 0 );
(uint32_t)p_dec->i_current_pts ) ? vout_SynchroDecode( p_dec->p_synchro );
p_dec->i_current_pts : p_dec->i_previous_pts; if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic );
} }
} }
break; /* pass-through */
case STATE_END: case STATE_END:
case STATE_SLICE:
if( p_dec->p_info->display_fbuf if( p_dec->p_info->display_fbuf
&& p_dec->p_info->display_fbuf->id ) && p_dec->p_info->display_fbuf->id )
{ {
p_pic = (picture_t *)p_dec->p_info->display_fbuf->id; p_pic = (picture_t *)p_dec->p_info->display_fbuf->id;
/* Date the new picture */ if ( p_pic != NULL )
if( p_dec->p_info->display_picture->flags & PIC_FLAG_PTS )
{
p_dec->i_pts = p_pic->date;
p_dec->i_period_remainder = 0;
}
else
{ {
p_dec->i_pts += ( (p_dec->p_info->sequence->frame_period + if ( p_dec->p_picture_to_destroy != p_pic )
p_dec->i_period_remainder) / 27 ); {
p_dec->i_period_remainder = vout_SynchroEnd( p_dec->p_synchro,
p_dec->p_info->sequence->frame_period + p_dec->p_info->display_picture->flags
p_dec->i_period_remainder - & PIC_MASK_CODING_TYPE,
( p_dec->p_info->sequence->frame_period + 0 );
p_dec->i_period_remainder ) / 27 * 27; vout_DatePicture( p_dec->p_vout, p_pic,
vout_SynchroDate( p_dec->p_synchro ) );
vout_DisplayPicture( p_dec->p_vout, p_pic );
}
else
{
p_dec->p_picture_to_destroy = NULL;
vout_SynchroEnd( p_dec->p_synchro,
p_dec->p_info->display_picture->flags
& PIC_MASK_CODING_TYPE,
1 );
vout_DestroyPicture( p_dec->p_vout, p_pic );
}
} }
vout_DatePicture( p_dec->p_vout, p_pic, p_dec->i_pts ); if( p_dec->p_info->discard_fbuf &&
p_dec->p_info->discard_fbuf->id )
vout_DisplayPicture( p_dec->p_vout, p_pic );
/* Handle pulldown by adding some delay to the pts of the next
* picture. */
if( p_dec->p_info->display_picture->nb_fields > 2 )
{ {
int i_repeat_fields = vout_UnlinkPicture( p_dec->p_vout, p_pic );
p_dec->p_info->display_picture->nb_fields - 2;
p_dec->i_pts += ( (p_dec->p_info->sequence->frame_period +
p_dec->i_period_remainder)
/ 27 / 2 * i_repeat_fields );
p_dec->i_period_remainder =
p_dec->p_info->sequence->frame_period +
p_dec->i_period_remainder -
( p_dec->p_info->sequence->frame_period +
p_dec->i_period_remainder ) / 27 / 2 * 27 * 2;
} }
} }
break; break;
case STATE_INVALID:
msg_Warn( p_dec->p_fifo, "Received STATE_INVALID" );
break;
default: default:
break; break;
} }
...@@ -357,6 +385,9 @@ static void CloseDecoder( dec_thread_t * p_dec ) ...@@ -357,6 +385,9 @@ static void CloseDecoder( dec_thread_t * p_dec )
vout_Request( p_dec->p_fifo, p_dec->p_vout, 0, 0, 0, 0 ); vout_Request( p_dec->p_fifo, p_dec->p_vout, 0, 0, 0, 0 );
} }
if( p_dec->p_synchro )
vout_SynchroRelease( p_dec->p_synchro );
if( p_dec->p_mpeg2dec ) mpeg2_close( p_dec->p_mpeg2dec ); if( p_dec->p_mpeg2dec ) mpeg2_close( p_dec->p_mpeg2dec );
free( p_dec ); free( p_dec );
...@@ -380,6 +411,7 @@ static picture_t *GetNewPicture( dec_thread_t *p_dec, uint8_t **pp_buf ) ...@@ -380,6 +411,7 @@ static picture_t *GetNewPicture( dec_thread_t *p_dec, uint8_t **pp_buf )
} }
if( p_pic == NULL ) if( p_pic == NULL )
return NULL; return NULL;
vout_LinkPicture( p_dec->p_vout, p_pic );
pp_buf[0] = p_pic->p[0].p_pixels; pp_buf[0] = p_pic->p[0].p_pixels;
pp_buf[1] = p_pic->p[1].p_pixels; pp_buf[1] = p_pic->p[1].p_pixels;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* modules.c : Builtin and plugin modules management functions * modules.c : Builtin and plugin modules management functions
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: modules.c,v 1.117 2003/03/25 15:38:14 gbazin Exp $ * $Id: modules.c,v 1.118 2003/04/14 22:22:32 massiot Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* Ethan C. Baldridge <BaldridgeE@cadmus.com> * Ethan C. Baldridge <BaldridgeE@cadmus.com>
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
#include "video.h" #include "video.h"
#include "video_output.h" #include "video_output.h"
#include "vout_synchro.h"
#include "audio_output.h" #include "audio_output.h"
#include "aout_internal.h" #include "aout_internal.h"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread. * thread, and destroy a previously oppened video output thread.
***************************************************************************** *****************************************************************************
* Copyright (C) 2000-2001 VideoLAN * Copyright (C) 2000-2001 VideoLAN
* $Id: video_output.c,v 1.217 2003/03/28 17:02:25 gbazin Exp $ * $Id: video_output.c,v 1.218 2003/04/14 22:22:32 massiot Exp $
* *
* Authors: Vincent Seguin <seguin@via.ecp.fr> * Authors: Vincent Seguin <seguin@via.ecp.fr>
* *
...@@ -638,7 +638,7 @@ static void RunThread( vout_thread_t *p_vout) ...@@ -638,7 +638,7 @@ static void RunThread( vout_thread_t *p_vout)
display_date = 0; display_date = 0;
current_date = mdate(); current_date = mdate();
#ifdef STATS #if 0
p_vout->c_loops++; p_vout->c_loops++;
if( !(p_vout->c_loops % VOUT_STATS_NB_LOOPS) ) if( !(p_vout->c_loops % VOUT_STATS_NB_LOOPS) )
{ {
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment