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 = \
include/vlc_playlist.h \
include/vlc_threads.h \
include/vlc_threads_funcs.h \
include/vout_synchro.h \
include/win32_specific.h \
include/osd.h \
$(NULL)
......@@ -387,6 +388,7 @@ SOURCES_libvlc_common = \
src/video_output/video_text.c \
src/video_output/video_text.h \
src/video_output/vout_subpictures.c \
src/video_output/vout_synchro.c \
src/audio_output/common.c \
src/audio_output/dec.c \
src/audio_output/filters.c \
......
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* 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>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -242,6 +242,7 @@ typedef struct picture_sys_t picture_sys_t;
typedef struct picture_heap_t picture_heap_t;
typedef struct subpicture_t subpicture_t;
typedef struct subpicture_sys_t subpicture_sys_t;
typedef struct vout_synchro_t vout_synchro_t;
/* Stream output */
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 @@
* libmpeg2.c: mpeg2 video decoder module making use of libmpeg2.
*****************************************************************************
* 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>
*
......@@ -34,6 +34,8 @@
#include <mpeg2dec/mpeg2.h>
#include "vout_synchro.h"
/* Aspect ratio (ISO/IEC 13818-2 section 6.3.3, table 6-3) */
#define AR_SQUARE_PICTURE 1 /* square pixels */
#define AR_3_4_PICTURE 2 /* 3:4 picture (TV) */
......@@ -60,11 +62,14 @@ typedef struct dec_thread_t
mtime_t i_previous_pts;
mtime_t i_current_pts;
mtime_t i_period_remainder;
int i_current_rate;
picture_t * p_picture_to_destroy;
/*
* Output properties
*/
vout_thread_t *p_vout;
vout_synchro_t *p_synchro;
} dec_thread_t;
......@@ -102,6 +107,7 @@ static int OpenDecoder( vlc_object_t *p_this )
p_fifo->pf_run = RunDecoder;
return VLC_SUCCESS;
}
/*****************************************************************************
* RunDecoder: the libmpeg2 decoder
*****************************************************************************/
......@@ -132,6 +138,7 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
p_dec->i_current_pts = 0;
p_dec->i_previous_pts = 0;
p_dec->i_period_remainder = 0;
p_dec->p_picture_to_destroy = NULL;
/* Initialize decoder */
p_dec->p_mpeg2dec = mpeg2_init();
......@@ -163,6 +170,14 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
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 )
{
mpeg2_pts( p_dec->p_mpeg2dec,
......@@ -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_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;
}
......@@ -187,6 +204,7 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
{
/* Initialize video output */
uint8_t *buf[3];
buf[0] = buf[1] = buf[2] = NULL;
/* Check whether the input gives a particular aspect ratio */
if( p_dec->p_fifo->p_demux_data
......@@ -231,76 +249,86 @@ static int RunDecoder( decoder_fifo_t *p_fifo )
mpeg2_custom_fbuf( p_dec->p_mpeg2dec, 1 );
/* Set the first 2 reference frames */
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic );
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic );
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, NULL );
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, NULL );
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;
case STATE_PICTURE:
{
uint8_t *buf[3];
if( (p_pic = GetNewPicture( p_dec, buf )) == NULL ) break;
mpeg2_set_buf( p_dec->p_mpeg2dec, buf, p_pic );
/* Store the date for the picture */
if( p_dec->p_info->current_picture->flags & PIC_FLAG_PTS )
buf[0] = buf[1] = buf[2] = NULL;
vout_SynchroNewPicture( p_dec->p_synchro,
p_dec->p_info->current_picture->flags & PIC_MASK_CODING_TYPE,
p_dec->p_info->current_picture->nb_fields,
(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 ==
(uint32_t)p_dec->i_current_pts ) ?
p_dec->i_current_pts : p_dec->i_previous_pts;
mpeg2_skip( p_dec->p_mpeg2dec, 0 );
vout_SynchroDecode( p_dec->p_synchro );
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_SLICE:
if( p_dec->p_info->display_fbuf
&& p_dec->p_info->display_fbuf->id )
{
p_pic = (picture_t *)p_dec->p_info->display_fbuf->id;
/* Date the new picture */
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
if ( p_pic != NULL )
{
p_dec->i_pts += ( (p_dec->p_info->sequence->frame_period +
p_dec->i_period_remainder) / 27 );
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 * 27;
if ( p_dec->p_picture_to_destroy != p_pic )
{
vout_SynchroEnd( p_dec->p_synchro,
p_dec->p_info->display_picture->flags
& PIC_MASK_CODING_TYPE,
0 );
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 );
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 )
if( p_dec->p_info->discard_fbuf &&
p_dec->p_info->discard_fbuf->id )
{
int i_repeat_fields =
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;
vout_UnlinkPicture( p_dec->p_vout, p_pic );
}
}
break;
case STATE_INVALID:
msg_Warn( p_dec->p_fifo, "Received STATE_INVALID" );
break;
default:
break;
}
......@@ -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 );
}
if( p_dec->p_synchro )
vout_SynchroRelease( p_dec->p_synchro );
if( p_dec->p_mpeg2dec ) mpeg2_close( p_dec->p_mpeg2dec );
free( p_dec );
......@@ -380,6 +411,7 @@ static picture_t *GetNewPicture( dec_thread_t *p_dec, uint8_t **pp_buf )
}
if( p_pic == NULL )
return NULL;
vout_LinkPicture( p_dec->p_vout, p_pic );
pp_buf[0] = p_pic->p[0].p_pixels;
pp_buf[1] = p_pic->p[1].p_pixels;
......
......@@ -2,7 +2,7 @@
* modules.c : Builtin and plugin modules management functions
*****************************************************************************
* 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>
* Ethan C. Baldridge <BaldridgeE@cadmus.com>
......@@ -81,6 +81,7 @@
#include "video.h"
#include "video_output.h"
#include "vout_synchro.h"
#include "audio_output.h"
#include "aout_internal.h"
......
......@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* 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>
*
......@@ -638,7 +638,7 @@ static void RunThread( vout_thread_t *p_vout)
display_date = 0;
current_date = mdate();
#ifdef STATS
#if 0
p_vout->c_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