Commit a3d9fc2e authored by Laurent Aimar's avatar Laurent Aimar

Workaround libmpeg2 DPB bugs (#2883).

It should work as the vout never deletes the pictures used by a decoder.
parent 946a8e91
...@@ -110,12 +110,14 @@ static void PutPicture( decoder_t *, picture_t * ); ...@@ -110,12 +110,14 @@ static void PutPicture( decoder_t *, picture_t * );
static void GetAR( decoder_t *p_dec ); static void GetAR( decoder_t *p_dec );
static void Reset( decoder_t *p_dec );
/* */ /* */
static void DpbInit( decoder_t * ); static void DpbInit( decoder_t * );
static void DpbClean( decoder_t * ); static void DpbClean( decoder_t * );
static picture_t *DpbNewPicture( decoder_t * ); static picture_t *DpbNewPicture( decoder_t * );
static void DpbUnlinkPicture( decoder_t *, picture_t * ); static void DpbUnlinkPicture( decoder_t *, picture_t * );
static void DpbDisplayPicture( decoder_t *, picture_t * ); static int DpbDisplayPicture( decoder_t *, picture_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -250,11 +252,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -250,11 +252,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
p_block = *pp_block; p_block = *pp_block;
if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) ) if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
{ Reset( p_dec );
cc_Flush( &p_sys->cc );
mpeg2_reset( p_sys->p_mpeg2dec, p_sys->p_info->sequence != NULL );
DpbClean( p_dec );
}
while( 1 ) while( 1 )
{ {
...@@ -389,7 +387,15 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -389,7 +387,15 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
p_pic = NULL; p_pic = NULL;
if( !b_skip ) if( !b_skip )
{
p_pic = DpbNewPicture( p_dec ); p_pic = DpbNewPicture( p_dec );
if( !p_pic )
{
Reset( p_dec );
block_Release( p_block );
return NULL;
}
}
if( b_skip || !p_pic ) if( b_skip || !p_pic )
{ {
...@@ -524,16 +530,20 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -524,16 +530,20 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
p_sys->p_info->display_fbuf->id ) p_sys->p_info->display_fbuf->id )
{ {
p_pic = p_sys->p_info->display_fbuf->id; p_pic = p_sys->p_info->display_fbuf->id;
DpbDisplayPicture( p_dec, p_pic ); if( DpbDisplayPicture( p_dec, p_pic ) )
p_pic = NULL;
decoder_SynchroEnd( p_sys->p_synchro, decoder_SynchroEnd( p_sys->p_synchro,
p_sys->p_info->display_picture->flags & PIC_MASK_CODING_TYPE, p_sys->p_info->display_picture->flags & PIC_MASK_CODING_TYPE,
p_sys->b_garbage_pic ); p_sys->b_garbage_pic );
p_pic->date = decoder_SynchroDate( p_sys->p_synchro ); if( p_pic )
if( p_sys->b_garbage_pic ) {
p_pic->date = 0; /* ??? */ p_pic->date = decoder_SynchroDate( p_sys->p_synchro );
p_sys->b_garbage_pic = false; if( p_sys->b_garbage_pic )
p_pic->date = 0; /* ??? */
p_sys->b_garbage_pic = false;
}
} }
if( p_sys->p_info->discard_fbuf && if( p_sys->p_info->discard_fbuf &&
...@@ -593,6 +603,18 @@ static void CloseDecoder( vlc_object_t *p_this ) ...@@ -593,6 +603,18 @@ static void CloseDecoder( vlc_object_t *p_this )
free( p_sys ); free( p_sys );
} }
/*****************************************************************************
* Reset: reset the decoder state
*****************************************************************************/
static void Reset( decoder_t *p_dec )
{
decoder_sys_t *p_sys = p_dec->p_sys;
cc_Flush( &p_sys->cc );
mpeg2_reset( p_sys->p_mpeg2dec, p_sys->p_info->sequence != NULL );
DpbClean( p_dec );
}
/***************************************************************************** /*****************************************************************************
* GetNewPicture: Get a new picture from the vout and set the buf struct * GetNewPicture: Get a new picture from the vout and set the buf struct
*****************************************************************************/ *****************************************************************************/
...@@ -819,6 +841,14 @@ static picture_dpb_t *DpbFindPicture( decoder_t *p_dec, picture_t *p_picture ) ...@@ -819,6 +841,14 @@ static picture_dpb_t *DpbFindPicture( decoder_t *p_dec, picture_t *p_picture )
static void DpbUnlinkPicture( decoder_t *p_dec, picture_t *p_picture ) static void DpbUnlinkPicture( decoder_t *p_dec, picture_t *p_picture )
{ {
picture_dpb_t *p = DpbFindPicture( p_dec, p_picture ); picture_dpb_t *p = DpbFindPicture( p_dec, p_picture );
/* XXX it is needed to workaround libmpeg2 bugs */
if( !p || !p->b_linked )
{
msg_Err( p_dec, "DpbUnlinkPicture called on an invalid picture" );
return;
}
assert( p && p->b_linked ); assert( p && p->b_linked );
decoder_UnlinkPicture( p_dec, p->p_picture ); decoder_UnlinkPicture( p_dec, p->p_picture );
...@@ -831,12 +861,21 @@ static void DpbUnlinkPicture( decoder_t *p_dec, picture_t *p_picture ) ...@@ -831,12 +861,21 @@ static void DpbUnlinkPicture( decoder_t *p_dec, picture_t *p_picture )
/** /**
* Mark the provided picture as displayed. * Mark the provided picture as displayed.
*/ */
static void DpbDisplayPicture( decoder_t *p_dec, picture_t *p_picture ) static int DpbDisplayPicture( decoder_t *p_dec, picture_t *p_picture )
{ {
picture_dpb_t *p = DpbFindPicture( p_dec, p_picture ); picture_dpb_t *p = DpbFindPicture( p_dec, p_picture );
/* XXX it is needed to workaround libmpeg2 bugs */
if( !p || p->b_displayed || !p->b_linked )
{
msg_Err( p_dec, "DpbDisplayPicture called on an invalid picture" );
return VLC_EGENERIC;
}
assert( p && !p->b_displayed && p->b_linked ); assert( p && !p->b_displayed && p->b_linked );
p->b_displayed = true; p->b_displayed = true;
return VLC_SUCCESS;
} }
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