Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Steve Lhomme
VLC
Commits
dd521c46
Commit
dd521c46
authored
Apr 14, 2003
by
Christophe Massiot
Browse files
* Implementation of a frame-dropping algorithm for the libmpeg2 plug-in
(incomplete).
parent
899ac5e2
Changes
7
Hide whitespace changes
Inline
Side-by-side
Makefile.am
View file @
dd521c46
...
...
@@ -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
\
...
...
include/vlc_common.h
View file @
dd521c46
...
...
@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.6
0
2003/04/1
3
2
0:00:20 fenrir
Exp $
* $Id: vlc_common.h,v 1.6
1
2003/04/1
4
2
2: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
;
...
...
include/vout_synchro.h
0 → 100644
View file @
dd521c46
/*****************************************************************************
* 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
)
);
modules/codec/libmpeg2.c
View file @
dd521c46
...
...
@@ -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
;
...
...
src/misc/modules.c
View file @
dd521c46
...
...
@@ -2,7 +2,7 @@
* modules.c : Builtin and plugin modules management functions
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: modules.c,v 1.11
7
2003/0
3/25 15:38:14 gbazin
Exp $
* $Id: modules.c,v 1.11
8
2003/0
4/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"
...
...
src/video_output/video_output.c
View file @
dd521c46
...
...
@@ -5,7 +5,7 @@
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: video_output.c,v 1.21
7
2003/0
3/28 17:02:25 gbazin
Exp $
* $Id: video_output.c,v 1.21
8
2003/0
4/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
();
#if
def STATS
#if
0
p_vout->c_loops++;
if( !(p_vout->c_loops % VOUT_STATS_NB_LOOPS) )
{
...
...
src/video_output/vout_synchro.c
0 → 100644
View file @
dd521c46
/*****************************************************************************
* vout_synchro.c : frame dropping routines
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: vout_synchro.c,v 1.1 2003/04/14 22:22:32 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Samuel Hocevar <sam@via.ecp.fr>
* Jean-Marc Dressler <polux@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.
*****************************************************************************/
/*
* DISCUSSION : How to Write an efficient Frame-Dropping Algorithm
* ==========
*
* This implementation is based on mathematical and statistical
* developments. Older implementations used an enslavement, considering
* that if we're late when reading an I picture, we will decode one frame
* less. It had a tendancy to derive, and wasn't responsive enough, which
* would have caused trouble with the stream control stuff.
*
* 1. Structure of a picture stream
* =============================
* Between 2 I's, we have for instance :
* I B P B P B P B P B P B I
* t0 t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12
* Please bear in mind that B's and IP's will be inverted when displaying
* (decoding order != presentation order). Thus, t1 < t0.
*
* 2. Definitions
* ===========
* t[0..12] : Presentation timestamps of pictures 0..12.
* t : Current timestamp, at the moment of the decoding.
* T : Picture period, T = 1/frame_rate.
* tau[I,P,B] : Mean time to decode an [I,P,B] picture.
* tauYUV : Mean time to render a picture (given by the video_output).
* tau[I,P,B] = 2 * tau[I,P,B] + tauYUV
* : Mean time + typical difference (estimated to tau/2, that
* needs to be confirmed) + render time.
* DELTA : A given error margin.
*
* 3. General considerations
* ======================
* We define three types of machines :
* 14T > tauI : machines capable of decoding all I pictures
* 2T > tauP : machines capable of decoding all P pictures
* T > tauB : machines capable of decoding all B pictures
*
* 4. Decoding of an I picture
* ========================
* On fast machines, we decode all I's.
* Otherwise :
* We can decode an I picture if we simply have enough time to decode it
* before displaying :
* t0 - t > tauI + DELTA
*
* 5. Decoding of a P picture
* =======================
* On fast machines, we decode all P's.
* Otherwise :
* First criterion : have time to decode it.
* t2 - t > tauP + DELTA
*
* Second criterion : it shouldn't prevent us from displaying the forthcoming
* I picture, which is more important.
* t12 - t > tauP + tauI + DELTA
*
* 6. Decoding of a B picture
* =======================
* On fast machines, we decode all B's. Otherwise :
* t1 - t > tauB + DELTA
* Since the next displayed I or P is already decoded, we don't have to
* worry about it.
*
* I hope you will have a pleasant flight and do not forget your life
* jacket.
* --Meuuh (2000-12-29)
*/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
/* free() */
#include <string.h>
/* memcpy(), memset() */
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include "vout_synchro.h"
#include "stream_control.h"
/*
* Local prototypes
*/
/* Error margins */
#define DELTA (int)(0.075*CLOCK_FREQ)
#define DEFAULT_NB_P 5
#define DEFAULT_NB_B 1
/*****************************************************************************
* vout_SynchroInit : You know what ?
*****************************************************************************/
vout_synchro_t
*
__vout_SynchroInit
(
vlc_object_t
*
p_object
,
vout_thread_t
*
p_vout
,
int
i_frame_rate
)
{
vout_synchro_t
*
p_synchro
=
vlc_object_create
(
p_object
,
sizeof
(
vout_synchro_t
)
);
if
(
p_synchro
==
NULL
)
{
msg_Err
(
p_object
,
"out of memory"
);
return
NULL
;
}
vlc_object_attach
(
p_synchro
,
p_vout
);
/* We use a fake stream pattern, which is often right. */
p_synchro
->
i_n_p
=
p_synchro
->
i_eta_p
=
DEFAULT_NB_P
;
p_synchro
->
i_n_b
=
p_synchro
->
i_eta_b
=
DEFAULT_NB_B
;
memset
(
p_synchro
->
p_tau
,
0
,
4
*
sizeof
(
mtime_t
)
);
memset
(
p_synchro
->
pi_meaningful
,
0
,
4
*
sizeof
(
unsigned
int
)
);
p_synchro
->
i_nb_ref
=
0
;
p_synchro
->
current_pts
=
mdate
()
+
DEFAULT_PTS_DELAY
;
p_synchro
->
backward_pts
=
0
;
p_synchro
->
i_current_period
=
p_synchro
->
i_backward_period
=
0
;
p_synchro
->
i_trashed_pic
=
p_synchro
->
i_not_chosen_pic
=
p_synchro
->
i_pic
=
0
;
p_synchro
->
i_frame_rate
=
i_frame_rate
;
p_synchro
->
p_vout
=
p_vout
;
return
p_synchro
;
}
/*****************************************************************************
* vout_SynchroRelease : You know what ?
*****************************************************************************/
void
vout_SynchroRelease
(
vout_synchro_t
*
p_synchro
)
{
vlc_object_detach
(
p_synchro
);
vlc_object_destroy
(
p_synchro
);
}
/*****************************************************************************
* vout_SynchroReset : Reset the reference picture counter
*****************************************************************************/
void
vout_SynchroReset
(
vout_synchro_t
*
p_synchro
)
{
p_synchro
->
i_nb_ref
=
0
;
}
/*****************************************************************************
* vout_SynchroChoose : Decide whether we will decode a picture or not
*****************************************************************************/
vlc_bool_t
vout_SynchroChoose
(
vout_synchro_t
*
p_synchro
,
int
i_coding_type
)
{
#define TAU_PRIME( coding_type ) (p_synchro->p_tau[(coding_type)] \
+ (p_synchro->p_tau[(coding_type)] >> 1) \
+ tau_yuv)
#define S (*p_synchro)
/* VPAR_SYNCHRO_DEFAULT */
mtime_t
now
,
period
,
tau_yuv
;
mtime_t
pts
=
0
;
vlc_bool_t
b_decode
=
0
;
now
=
mdate
();
period
=
1000000
*
1001
/
p_synchro
->
i_frame_rate
*
p_synchro
->
i_current_rate
/
DEFAULT_RATE
;
vlc_mutex_lock
(
&
p_synchro
->
p_vout
->
change_lock
);
tau_yuv
=
p_synchro
->
p_vout
->
render_time
;
vlc_mutex_unlock
(
&
p_synchro
->
p_vout
->
change_lock
);
switch
(
i_coding_type
)
{
case
I_CODING_TYPE
:
if
(
S
.
backward_pts
)
{
pts
=
S
.
backward_pts
;
}
else
{
/* displaying order : B B P B B I
* ^ ^
* | +- current picture
* +- current PTS
*/
pts
=
S
.
current_pts
+
period
*
(
S
.
i_n_b
+
2
);
}
if
(
(
1
+
S
.
i_n_p
*
(
S
.
i_n_b
+
1
))
*
period
>
S
.
p_tau
[
I_CODING_TYPE
]
)
{
b_decode
=
1
;
}
else
{
b_decode
=
(
pts
-
now
)
>
(
TAU_PRIME
(
I_CODING_TYPE
)
+
DELTA
);
}
if
(
!
b_decode
)
{
msg_Warn
(
p_synchro
,
"synchro trashing I ("
I64Fd
")"
,
pts
-
now
);
p_synchro
->
i_nb_ref
=
0
;
}
else
if
(
p_synchro
->
i_nb_ref
<
2
)
p_synchro
->
i_nb_ref
++
;
break
;
case
P_CODING_TYPE
:
if
(
S
.
backward_pts
)
{
pts
=
S
.
backward_pts
;
}
else
{
pts
=
S
.
current_pts
+
period
*
(
S
.
i_n_b
+
1
);
}
if
(
p_synchro
->
i_nb_ref
<
1
)
{
b_decode
=
0
;
}
else
if
(
(
1
+
S
.
i_n_p
*
(
S
.
i_n_b
+
1
))
*
period
>
S
.
p_tau
[
I_CODING_TYPE
]
)