Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc-1.1
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc-1.1
Commits
dd521c46
Commit
dd521c46
authored
Apr 14, 2003
by
Christophe Massiot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
* Implementation of a frame-dropping algorithm for the libmpeg2 plug-in
(incomplete).
parent
899ac5e2
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
699 additions
and
52 deletions
+699
-52
Makefile.am
Makefile.am
+2
-0
include/vlc_common.h
include/vlc_common.h
+2
-1
include/vout_synchro.h
include/vout_synchro.h
+89
-0
modules/codec/libmpeg2.c
modules/codec/libmpeg2.c
+80
-48
src/misc/modules.c
src/misc/modules.c
+2
-1
src/video_output/video_output.c
src/video_output/video_output.c
+2
-2
src/video_output/vout_synchro.c
src/video_output/vout_synchro.c
+522
-0
No files found.
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/13 20:00:20 fenrir
Exp $
* $Id: vlc_common.h,v 1.6
1 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
;
...
...
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/03/25 15:38:14 gbazin
Exp $
* $Id: modules.c,v 1.11
8 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"
...
...
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/03/28 17:02:25 gbazin
Exp $
* $Id: video_output.c,v 1.21
8 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
();
#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
]
)
{
if
(
(
S
.
i_n_b
+
1
)
*
period
>
S
.
p_tau
[
P_CODING_TYPE
]
)
{
/* Security in case we're _really_ late */
b_decode
=
(
pts
-
now
>
0
);
}
else
{
b_decode
=
(
pts
-
now
)
>
(
TAU_PRIME
(
P_CODING_TYPE
)
+
DELTA
);
/* next I */
b_decode
&=
(
pts
-
now
+
period
*
(
(
S
.
i_n_p
-
S
.
i_eta_p
)
*
(
1
+
S
.
i_n_b
)
-
1
))
>
(
TAU_PRIME
(
P_CODING_TYPE
)
+
TAU_PRIME
(
I_CODING_TYPE
)
+
DELTA
);
}
}
else
{
b_decode
=
0
;
}
if
(
b_decode
)
p_synchro
->
i_nb_ref
=
2
;
else
p_synchro
->
i_nb_ref
=
0
;
break
;
case
B_CODING_TYPE
:
pts
=
S
.
current_pts
;
if
(
p_synchro
->
i_nb_ref
<
2
)
{
b_decode
=
0
;
}
else
if
(
(
S
.
i_n_b
+
1
)
*
period
>
S
.
p_tau
[
P_CODING_TYPE
]
)
{
b_decode
=
(
pts
-
now
)
>
(
TAU_PRIME
(
B_CODING_TYPE
)
+
DELTA
);
}
else
{
b_decode
=
0
;
}
}
if
(
!
b_decode
)
{
S
.
i_not_chosen_pic
++
;
}
return
(
b_decode
);
#undef S
#undef TAU_PRIME
}
/*****************************************************************************
* vout_SynchroTrash : Update counters when we trash a picture
*****************************************************************************/
void
vout_SynchroTrash
(
vout_synchro_t
*
p_synchro
)
{
p_synchro
->
i_trashed_pic
++
;
}
/*****************************************************************************
* vout_SynchroDecode : Update timers when we decide to decode a picture
*****************************************************************************/
void
vout_SynchroDecode
(
vout_synchro_t
*
p_synchro
)
{
p_synchro
->
decoding_start
=
mdate
();
}
/*****************************************************************************
* vout_SynchroEnd : Called when the image is totally decoded
*****************************************************************************/
void
vout_SynchroEnd
(
vout_synchro_t
*
p_synchro
,
int
i_coding_type
,
vlc_bool_t
b_garbage
)
{
mtime_t
tau
;
if
(
!
b_garbage
)
{
tau
=
mdate
()
-
p_synchro
->
decoding_start
;
/* If duration too high, something happened (pause ?), so don't
* take it into account. */
if
(
tau
<
3
*
p_synchro
->
p_tau
[
i_coding_type
]
||
!
p_synchro
->
pi_meaningful
[
i_coding_type
]
)
{
/* Mean with average tau, to ensure stability. */
p_synchro
->
p_tau
[
i_coding_type
]
=
(
p_synchro
->
pi_meaningful
[
i_coding_type
]
*
p_synchro
->
p_tau
[
i_coding_type
]
+
tau
)
/
(
p_synchro
->
pi_meaningful
[
i_coding_type
]
+
1
);
if
(
p_synchro
->
pi_meaningful
[
i_coding_type
]
<
MAX_PIC_AVERAGE
)
{
p_synchro
->
pi_meaningful
[
i_coding_type
]
++
;
}
}
}
}
/*****************************************************************************
* vout_SynchroDate : When an image has been decoded, ask for its date
*****************************************************************************/
mtime_t
vout_SynchroDate
(
vout_synchro_t
*
p_synchro
)
{
/* No need to lock, since PTS are only used by the video parser. */
return
p_synchro
->
current_pts
;
}
/*****************************************************************************
* vout_SynchroNewPicture: Update stream structure and PTS
*****************************************************************************/
void
vout_SynchroNewPicture
(
vout_synchro_t
*
p_synchro
,
int
i_coding_type
,
int
i_repeat_field
,
mtime_t
next_pts
,
mtime_t
next_dts
,
int
i_current_rate
)
{
mtime_t
period
=
1000000
*
1001
/
p_synchro
->
i_frame_rate
*
i_current_rate
/
DEFAULT_RATE
;
#if 0
mtime_t now = mdate();
#endif
p_synchro
->
i_current_rate
=
i_current_rate
;
switch
(
i_coding_type
)
{
case
I_CODING_TYPE
:
if
(
p_synchro
->
i_eta_p
&&
p_synchro
->
i_eta_p
!=
p_synchro
->
i_n_p
)
{
#if 0
msg_Dbg( p_synchro,
"stream periodicity changed from P[%d] to P[%d]",
p_synchro->i_n_p, p_synchro->i_eta_p );
#endif
p_synchro
->
i_n_p
=
p_synchro
->
i_eta_p
;
}
p_synchro
->
i_eta_p
=
p_synchro
->
i_eta_b
=
0
;
#if 0
msg_Dbg( p_synchro, "I("I64Fd") P("I64Fd")[%d] B("I64Fd")"
"[%d] YUV("I64Fd") : trashed %d:%d/%d",
p_synchro->p_tau[I_CODING_TYPE],
p_synchro->p_tau[P_CODING_TYPE],
p_synchro->i_n_p,
p_synchro->p_tau[B_CODING_TYPE],
p_synchro->i_n_b,
p_synchro->p_vout->render_time,
p_synchro->i_not_chosen_pic,
p_synchro->i_trashed_pic -
p_synchro->i_not_chosen_pic,
p_synchro->i_pic );
p_synchro->i_trashed_pic = p_synchro->i_not_chosen_pic
= p_synchro->i_pic = 0;
#else
if
(
p_synchro
->
i_pic
>=
100
)
{
msg_Dbg
(
p_synchro
,
"decoded %d/%d pictures"
,
p_synchro
->
i_pic
-
p_synchro
->
i_trashed_pic
,
p_synchro
->
i_pic
);
p_synchro
->
i_trashed_pic
=
p_synchro
->
i_not_chosen_pic
=
p_synchro
->
i_pic
=
0
;
}
#endif
break
;
case
P_CODING_TYPE
:
p_synchro
->
i_eta_p
++
;
if
(
p_synchro
->
i_eta_b
&&
p_synchro
->
i_eta_b
!=
p_synchro
->
i_n_b
)
{
msg_Warn
(
p_synchro
,
"stream periodicity changed from B[%d] to B[%d]"
,
p_synchro
->
i_n_b
,
p_synchro
->
i_eta_b
);
p_synchro
->
i_n_b
=
p_synchro
->
i_eta_b
;
}
p_synchro
->
i_eta_b
=
0
;
break
;
case
B_CODING_TYPE
:
p_synchro
->
i_eta_b
++
;
break
;
}
p_synchro
->
current_pts
+=
p_synchro
->
i_current_period
*
(
period
>>
1
);
#define PTS_THRESHOLD (period >> 2)
if
(
i_coding_type
==
B_CODING_TYPE
)
{
/* A video frame can be displayed 1, 2 or 3 times, according to
* repeat_first_field, top_field_first, progressive_sequence and
* progressive_frame. */
p_synchro
->
i_current_period
=
i_repeat_field
;
if
(
next_pts
)
{
if
(
next_pts
-
p_synchro
->
current_pts
>
PTS_THRESHOLD
||
p_synchro
->
current_pts
-
next_pts
>
PTS_THRESHOLD
)
{
msg_Warn
(
p_synchro
,
"vout synchro warning: pts != "
"current_date ("
I64Fd
")"
,
p_synchro
->
current_pts
-
next_pts
);
}
p_synchro
->
current_pts
=
next_pts
;
}
}
else
{
p_synchro
->
i_current_period
=
p_synchro
->
i_backward_period
;
p_synchro
->
i_backward_period
=
i_repeat_field
;
if
(
p_synchro
->
backward_pts
)
{
if
(
next_dts
&&
(
next_dts
-
p_synchro
->
backward_pts
>
PTS_THRESHOLD
||
p_synchro
->
backward_pts
-
next_dts
>
PTS_THRESHOLD
)
)
{
msg_Warn
(
p_synchro
,
"backward_pts != dts ("
I64Fd
")"
,
next_dts
-
p_synchro
->
backward_pts
);
}
if
(
p_synchro
->
backward_pts
-
p_synchro
->
current_pts
>
PTS_THRESHOLD
||
p_synchro
->
current_pts
-
p_synchro
->
backward_pts
>
PTS_THRESHOLD
)
{
msg_Warn
(
p_synchro
,
"backward_pts != current_pts ("
I64Fd
")"
,
p_synchro
->
current_pts
-
p_synchro
->
backward_pts
);
}
p_synchro
->
current_pts
=
p_synchro
->
backward_pts
;
p_synchro
->
backward_pts
=
0
;
}
else
if
(
next_dts
)
{
if
(
next_dts
-
p_synchro
->
current_pts
>
PTS_THRESHOLD
||
p_synchro
->
current_pts
-
next_dts
>
PTS_THRESHOLD
)
{
msg_Warn
(
p_synchro
,
"dts != current_pts ("
I64Fd
")"
,
p_synchro
->
current_pts
-
next_dts
);
}
/* By definition of a DTS. */
p_synchro
->
current_pts
=
next_dts
;
next_dts
=
0
;
}
if
(
next_pts
)
{
/* Store the PTS for the next time we have to date an I picture. */
p_synchro
->
backward_pts
=
next_pts
;
next_pts
=
0
;
}
}
#undef PTS_THRESHOLD
#if 0
/* Removed for incompatibility with slow motion */
if( p_synchro->current_pts + DEFAULT_PTS_DELAY < now )
{
/* We cannot be _that_ late, something must have happened, reinit
* the dates. */
msg_Warn( p_synchro, "PTS << now ("I64Fd"), resetting",
now - p_synchro->current_pts - DEFAULT_PTS_DELAY );
p_synchro->current_pts = now + DEFAULT_PTS_DELAY;
}
if( p_synchro->backward_pts
&& p_synchro->backward_pts + DEFAULT_PTS_DELAY < now )
{
/* The same. */
p_synchro->backward_pts = 0;
}
#endif
p_synchro
->
i_pic
++
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment