[vlc-commits] packetizer: h264: use POC for computing missing pts
Francois Cartegnie
git at videolan.org
Fri Mar 17 19:46:35 CET 2017
vlc | branch: master | Francois Cartegnie <fcvlcdev at free.fr> | Fri Mar 17 18:57:35 2017 +0100| [508452ae3e47c079ccc6fca4275a6ca0e812195e] | committer: Francois Cartegnie
packetizer: h264: use POC for computing missing pts
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=508452ae3e47c079ccc6fca4275a6ca0e812195e
---
modules/packetizer/h264.c | 82 +++++++++++++++++++++++++++++++++++------------
1 file changed, 62 insertions(+), 20 deletions(-)
diff --git a/modules/packetizer/h264.c b/modules/packetizer/h264.c
index 2849dea..5c5d397 100644
--- a/modules/packetizer/h264.c
+++ b/modules/packetizer/h264.c
@@ -113,9 +113,16 @@ struct decoder_sys_t
bool b_even_frame;
bool b_discontinuity;
+ /* POC */
+ poc_context_t pocctx;
+ struct
+ {
+ mtime_t pts;
+ int num;
+ } prevdatedpoc;
+
mtime_t i_frame_pts;
mtime_t i_frame_dts;
- mtime_t i_prev_pts;
date_t dts;
@@ -315,9 +322,12 @@ static int Open( vlc_object_t *p_this )
p_sys->b_discontinuity = false;
p_sys->i_frame_dts = VLC_TS_INVALID;
p_sys->i_frame_pts = VLC_TS_INVALID;
- p_sys->i_prev_pts = VLC_TS_INVALID;
p_sys->i_dpb_output_delay = 0;
+ /* POC */
+ h264_poc_context_init( &p_sys->pocctx );
+ p_sys->prevdatedpoc.pts = VLC_TS_INVALID;
+
date_Init( &p_sys->dts, 1, 1 );
date_Set( &p_sys->dts, VLC_TS_INVALID );
@@ -490,10 +500,12 @@ static void PacketizeReset( void *p_private, bool b_broken )
p_sys->p_active_sps = NULL;
p_sys->i_frame_pts = VLC_TS_INVALID;
p_sys->i_frame_dts = VLC_TS_INVALID;
- p_sys->i_prev_pts = VLC_TS_INVALID;
p_sys->b_even_frame = false;
p_sys->slice.i_frame_type = 0;
p_sys->b_slice = false;
+ /* POC */
+ h264_poc_context_init( &p_sys->pocctx );
+ p_sys->prevdatedpoc.pts = VLC_TS_INVALID;
/* From SEI */
p_sys->i_dpb_output_delay = 0;
p_sys->i_pic_struct = 0;
@@ -757,7 +769,6 @@ static block_t *OutputPicture( decoder_t *p_dec )
p_sps->vui.i_num_units_in_tick / p_sps->vui.i_time_scale;
}
- mtime_t i_field_pts_diff = -1;
if( p_sps->frame_mbs_only_flag == 0 && p_sps->vui.b_pic_struct_present_flag )
{
switch( p_sys->i_pic_struct )
@@ -770,13 +781,6 @@ static block_t *OutputPicture( decoder_t *p_dec )
p_pic->i_flags |= (p_sys->i_pic_struct == 1) ? BLOCK_FLAG_TOP_FIELD_FIRST
: BLOCK_FLAG_BOTTOM_FIELD_FIRST;
}
- else if( p_pic->i_pts <= VLC_TS_INVALID &&
- date_Get( &p_sys->dts ) > VLC_TS_INVALID && p_pic->i_length )
- {
- /* interpolate from even frame */
- i_field_pts_diff = p_pic->i_length;
- }
-
p_sys->b_even_frame = !p_sys->b_even_frame;
break;
/* Each of the following slices contains multiple fields */
@@ -809,26 +813,64 @@ static block_t *OutputPicture( decoder_t *p_dec )
p_pic->i_dts = date_Get( &p_sys->dts );
/* PTS Fixup, interlaced fields (multiple AU/block) */
- if( p_pic->i_pts <= VLC_TS_INVALID && p_sps->vui.i_time_scale &&
- p_sps->vui.b_valid && p_sps->vui.b_hrd_parameters_present_flag )
+ int tFOC = 0, bFOC = 0, PictureOrderCount = 0;
+ h264_compute_poc( p_sps, &p_sys->slice, &p_sys->pocctx, &PictureOrderCount, &tFOC, &bFOC );
+
+ if( p_sys->slice.i_frame_type & BLOCK_FLAG_TYPE_I )
+ p_sys->prevdatedpoc.pts = VLC_TS_INVALID;
+
+ if( p_pic->i_pts == VLC_TS_INVALID )
{
- mtime_t i_pts_delay = CLOCK_FREQ * p_sys->i_dpb_output_delay *
- p_sps->vui.i_num_units_in_tick / p_sps->vui.i_time_scale;
- p_pic->i_pts = p_pic->i_dts + i_pts_delay;
- if( i_field_pts_diff >= 0 )
- p_pic->i_pts += i_field_pts_diff;
+ if( p_sys->prevdatedpoc.pts > VLC_TS_INVALID )
+ {
+ date_t pts = p_sys->dts;
+ date_Set( &pts, p_sys->prevdatedpoc.pts );
+
+ int diff = tFOC - p_sys->prevdatedpoc.num;
+ if( diff > 0 )
+ date_Increment( &pts, diff );
+ else
+ date_Decrement( &pts, -diff );
+
+ p_pic->i_pts = date_Get( &pts );
+ }
+ /* In case there's no PTS at all */
+ else if( p_sys->slice.i_nal_ref_idc == 0 &&
+ p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_B )
+ {
+ p_pic->i_pts = p_pic->i_dts;
+ }
+ else if( p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I )
+ {
+ /* Hell no PTS on IDR. We're totally blind */
+ date_t pts = p_sys->dts;
+ date_Increment( &pts, 2 );
+ p_pic->i_pts = date_Get( &pts );
+ }
}
+ if( p_pic->i_pts > VLC_TS_INVALID )
+ {
+ p_sys->prevdatedpoc.pts = p_pic->i_pts;
+ p_sys->prevdatedpoc.num = PictureOrderCount;
+ }
+
+#if 0
+ msg_Err(p_dec, "F/BOC %d/%d POC %d %s ref%d fn %d fp %d %d pts %ld",
+ tFOC, bFOC, PictureOrderCount,
+ (p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_I) ? "I" : (p_sys->slice.i_frame_type == BLOCK_FLAG_TYPE_P ? "P": "B"),
+ p_sys->slice.i_nal_ref_idc, p_sys->slice.i_frame_num, p_sys->slice.i_field_pic_flag,
+ p_pic->i_pts - p_pic->i_dts, p_pic->i_pts % (100*CLOCK_FREQ));
+#endif
+
if( !p_sys->b_discontinuity )
{
/* save for next pic fixups */
date_Increment( &p_sys->dts, i_num_clock_ts );
- p_sys->i_prev_pts = p_pic->i_pts;
}
else
{
p_sys->b_discontinuity = false;
- p_sys->i_prev_pts = VLC_TS_INVALID;
date_Set( &p_sys->dts, VLC_TS_INVALID );
if( p_pic )
p_pic->i_flags |= BLOCK_FLAG_DISCONTINUITY;
More information about the vlc-commits
mailing list