Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
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
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
Show 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 = \
...
@@ -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
\
...
...
include/vlc_common.h
View file @
dd521c46
...
@@ -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.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>
* 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
;
...
...
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 @@
...
@@ -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
;
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
{
mpeg2_skip
(
p_dec
->
p_mpeg2dec
,
0
);
vout_SynchroDecode
(
p_dec
->
p_synchro
);
if
(
(
p_pic
=
GetNewPicture
(
p_dec
,
buf
))
==
NULL
)
break
;
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
,
p_pic
);
/* Store the date for the picture */
if
(
p_dec
->
p_info
->
current_picture
->
flags
&
PIC_FLAG_PTS
)
{
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
;
}
}
}
}
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
;
if
(
p_dec
->
p_picture_to_destroy
!=
p_pic
)
p_dec
->
i_period_remainder
=
0
;
{
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
else
{
{
p_dec
->
i_pts
+=
(
(
p_dec
->
p_info
->
sequence
->
frame_period
+
p_dec
->
p_picture_to_destroy
=
NULL
;
p_dec
->
i_period_remainder
)
/
27
);
vout_SynchroEnd
(
p_dec
->
p_synchro
,
p_dec
->
i_period_remainder
=
p_dec
->
p_info
->
display_picture
->
flags
p_dec
->
p_info
->
sequence
->
frame_period
+
&
PIC_MASK_CODING_TYPE
,
p_dec
->
i_period_remainder
-
1
);
(
p_dec
->
p_info
->
sequence
->
frame_period
+
vout_DestroyPicture
(
p_dec
->
p_vout
,
p_pic
);
p_dec
->
i_period_remainder
)
/
27
*
27
;
}
}
vout_DatePicture
(
p_dec
->
p_vout
,
p_pic
,
p_dec
->
i_pts
);
}
if
(
p_dec
->
p_info
->
discard_fbuf
&&
vout_DisplayPicture
(
p_dec
->
p_vout
,
p_pic
);
p_dec
->
p_info
->
discard_fbuf
->
id
)
/* 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
;
...
...
src/misc/modules.c
View file @
dd521c46
...
@@ -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.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>
* 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"
...
...
src/video_output/video_output.c
View file @
dd521c46
...
@@ -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.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>
* 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
();
#if
def 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) )
{
{
...
...
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