Commit 21144a3a authored by Thomas Guillem's avatar Thomas Guillem

decoder: add VLCDEC_ECRITICAL status

This replaces the decoder_t->b_error boolean.

For now, only decoders that were setting b_error return VLCDEC_ECRITICAL, but a
lot more decoders should use this value since critical errors are often ignored.
parent a8b249bc
......@@ -68,6 +68,7 @@ struct decoder_t
bool b_frame_drop_allowed;
# define VLCDEC_SUCCESS VLC_SUCCESS
# define VLCDEC_ECRITICAL VLC_EGENERIC
/* This function is called to decode one packetized block.
*
* The module implementation will own the input block (p_block) and should
......@@ -78,6 +79,11 @@ struct decoder_t
* If p_block is NULL, the decoder asks the module to drain itself. The
* module should return all available output frames/block via the queue
* functions.
*
* Return values can be:
* VLCDEC_SUCCESS: pf_decode will be called again
* VLCDEC_ECRITICAL: in case of critical error, pf_decode won't be called
* again.
*/
int ( * pf_decode ) ( decoder_t *, block_t *p_block );
......@@ -171,8 +177,6 @@ struct decoder_t
/* Private structure for the owner of the decoder */
decoder_owner_sys_t *p_owner;
bool b_error;
};
/**
......
......@@ -301,7 +301,7 @@ static void Flush( decoder_t *p_dec )
/*****************************************************************************
* DecodeBlock: Called to decode one frame
*****************************************************************************/
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error )
{
decoder_sys_t *p_sys = p_dec->p_sys;
AVCodecContext *ctx = p_sys->p_context;
......@@ -452,7 +452,7 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
return ( p_sys->p_decoded ) ? DequeueOneDecodedFrame( p_sys ) : NULL;
end:
p_dec->b_error = true;
*error = true;
if( pp_block )
{
assert( *pp_block == p_block );
......@@ -468,10 +468,11 @@ drop:
static int DecodeAudio( decoder_t *p_dec, block_t *p_block )
{
bool error = false;
block_t **pp_block = p_block ? &p_block : NULL, *p_out;
while( ( p_out = DecodeBlock( p_dec, pp_block ) ) != NULL )
while( ( p_out = DecodeBlock( p_dec, pp_block, &error ) ) != NULL )
decoder_QueueAudio( p_dec, p_out );
return VLCDEC_SUCCESS;
return error ? VLCDEC_ECRITICAL : VLCDEC_SUCCESS;
}
static block_t * ConvertAVFrame( decoder_t *p_dec, AVFrame *frame )
......
......@@ -305,7 +305,7 @@ static int lavc_UpdateVideoFormat(decoder_t *dec, AVCodecContext *ctx,
* Copies a picture from the libavcodec-allocate buffer to a picture_t.
* This is used when not in direct rendering mode.
*/
static void lavc_CopyPicture(decoder_t *dec, picture_t *pic, AVFrame *frame)
static int lavc_CopyPicture(decoder_t *dec, picture_t *pic, AVFrame *frame)
{
decoder_sys_t *sys = dec->p_sys;
......@@ -315,8 +315,7 @@ static void lavc_CopyPicture(decoder_t *dec, picture_t *pic, AVFrame *frame)
msg_Err(dec, "Unsupported decoded output format %d (%s)",
sys->p_context->pix_fmt, (name != NULL) ? name : "unknown");
dec->b_error = true;
return;
return VLC_EGENERIC;
}
for (int plane = 0; plane < pic->i_planes; plane++)
......@@ -334,6 +333,7 @@ static void lavc_CopyPicture(decoder_t *dec, picture_t *pic, AVFrame *frame)
dst += dst_stride;
}
}
return VLC_SUCCESS;
}
static int OpenVideoCodec( decoder_t *p_dec )
......@@ -708,7 +708,7 @@ static void update_late_frame_count( decoder_t *p_dec, block_t *p_block, mtime_t
/*****************************************************************************
* DecodeBlock: Called to decode one or more frames
*****************************************************************************/
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block, bool *error )
{
decoder_sys_t *p_sys = p_dec->p_sys;
AVCodecContext *p_context = p_sys->p_context;
......@@ -846,7 +846,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if (ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL))
{
msg_Err(p_dec, "avcodec_send_packet critical error");
p_dec->b_error = true;
*error = true;
}
av_packet_unref( &pkt );
break;
......@@ -857,7 +857,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
AVFrame *frame = av_frame_alloc();
if (unlikely(frame == NULL))
{
p_dec->b_error = true;
*error = true;
break;
}
......@@ -867,7 +867,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
if (ret == AVERROR(ENOMEM) || ret == AVERROR(EINVAL))
{
msg_Err(p_dec, "avcodec_receive_frame critical error");
p_dec->b_error = true;
*error = true;
}
av_frame_free(&frame);
break;
......@@ -936,7 +936,7 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
= malloc( sizeof(video_palette_t) );
if( !p_palette )
{
p_dec->b_error = true;
*error = true;
av_frame_free(&frame);
break;
}
......@@ -970,7 +970,13 @@ static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
}
/* Fill picture_t from AVFrame */
lavc_CopyPicture(p_dec, p_pic, frame);
if( lavc_CopyPicture( p_dec, p_pic, frame ) != VLC_SUCCESS )
{
*error = true;
av_frame_free(&frame);
picture_Release( p_pic );
break;
}
}
else
{
......@@ -1022,9 +1028,10 @@ static int DecodeVideo( decoder_t *p_dec, block_t *p_block )
{
block_t **pp_block = p_block ? &p_block : NULL;
picture_t *p_pic;
while( ( p_pic = DecodeBlock( p_dec, pp_block ) ) != NULL )
bool error = false;
while( ( p_pic = DecodeBlock( p_dec, pp_block, &error ) ) != NULL )
decoder_QueueVideo( p_dec, p_pic );
return VLCDEC_SUCCESS;
return error ? VLCDEC_ECRITICAL : VLCDEC_SUCCESS;
}
/*****************************************************************************
......
......@@ -680,9 +680,8 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
if( unlikely( p_buf == NULL ) )
{
msg_Err( p_dec, "failed to create input gstbuffer" );
p_dec->b_error = true;
block_Release( p_block );
goto done;
return VLCDEC_ECRITICAL;
}
if( p_block->i_dts > VLC_TS_INVALID )
......@@ -722,9 +721,8 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
{
/* block will be released internally,
* when gst_buffer_unref() is called */
p_dec->b_error = true;
msg_Err( p_dec, "failed to push buffer" );
goto done;
return VLCDEC_ECRITICAL;
}
}
else
......@@ -749,11 +747,10 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
msg_Dbg( p_dec, "Pipeline is prerolled" );
break;
default:
p_dec->b_error = default_msg_handler( p_dec, p_msg );
if( p_dec->b_error )
if( default_msg_handler( p_dec, p_msg ) )
{
gst_message_unref( p_msg );
goto done;
return VLCDEC_ECRITICAL;
}
break;
}
......@@ -788,8 +785,7 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
{
msg_Err( p_dec, "failed to map gst video frame" );
gst_buffer_unref( p_buf );
p_dec->b_error = true;
goto done;
return VLCDEC_ECRITICAL;
}
gst_CopyPicture( p_pic, &frame );
......@@ -841,9 +837,11 @@ static void CloseDecoder( vlc_object_t *p_this )
msg_Dbg( p_dec, "got eos" );
break;
default:
p_dec->b_error = default_msg_handler( p_dec, p_msg );
if( p_dec->b_error )
if( default_msg_handler( p_dec, p_msg ) )
{
msg_Err( p_dec, "pipeline may not close gracefully" );
return VLCDEC_ECRITICAL;
}
break;
}
......
......@@ -55,6 +55,7 @@ struct decoder_sys_t
mpg123_handle * p_handle;
date_t end_date;
block_t * p_out;
bool b_opened;
};
/*****************************************************************************
......@@ -120,6 +121,7 @@ static int MPG123Open( decoder_t *p_dec )
return VLC_EGENERIC;
}
p_sys->b_opened = true;
return VLC_SUCCESS;
}
......@@ -133,8 +135,8 @@ static void Flush( decoder_t *p_dec )
date_Set( &p_sys->end_date, 0 );
mpg123_close( p_sys->p_handle );
if( MPG123Open( p_dec ) )
p_dec->b_error = true;
p_sys->b_opened = false;
MPG123Open( p_dec );
}
static int UpdateAudioFormat( decoder_t *p_dec )
......@@ -196,6 +198,13 @@ static int DecodeBlock( decoder_t *p_dec, block_t *p_block )
decoder_sys_t *p_sys = p_dec->p_sys;
block_t *p_out = NULL;
if( !p_sys->b_opened )
{
if( p_block )
block_Release( p_block );
return VLCDEC_ECRITICAL;
}
/* Feed input block */
if( p_block != NULL )
{
......
......@@ -1581,11 +1581,14 @@ end:
if (var_Create(p_dec, "mediacodec-failed", VLC_VAR_VOID)
== VLC_SUCCESS)
decoder_RequestReload(p_dec);
vlc_mutex_unlock(&p_sys->lock);
return VLCDEC_SUCCESS;
}
else
p_dec->b_error = true;
vlc_mutex_unlock(&p_sys->lock);
return VLCDEC_SUCCESS;
{
vlc_mutex_unlock(&p_sys->lock);
return VLCDEC_ECRITICAL;
}
}
else
{
......
......@@ -1136,13 +1136,13 @@ skip:
return VLCDEC_SUCCESS;
reload:
block_Release(p_block);
/* Add an empty variable so that videotoolbox won't be loaded again for
* this ES */
if (var_Create(p_dec, "videotoolbox-failed", VLC_VAR_VOID) == VLC_SUCCESS)
if (var_Create(p_dec, "videotoolbox-failed", VLC_VAR_VOID) == VLC_SUCCESS)
decoder_RequestReload(p_dec);
else
p_dec->b_error = true;
block_Release(p_block);
return VLCDEC_ECRITICAL;
return VLCDEC_SUCCESS;
}
......
......@@ -189,8 +189,9 @@ static int Decode(decoder_t *dec, block_t *block)
free(pkt_pts);
VPX_ERR(dec, ctx, "Failed to decode frame");
if (err == VPX_CODEC_UNSUP_BITSTREAM)
dec->b_error = true;
return VLCDEC_SUCCESS;
return VLCDEC_ECRITICAL;
else
return VLCDEC_SUCCESS;
}
const void *iter = NULL;
......
......@@ -265,7 +265,6 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
case STATE_SEND_DATA:
if( !(p_out_buffer = GetOutBuffer( p_dec )) )
{
//p_dec->b_error = true;
return NULL;
}
......
......@@ -283,7 +283,6 @@ static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
case STATE_SEND_DATA:
if( !(p_out_buffer = GetOutBuffer( p_dec )) )
{
//p_dec->b_error = true;
return NULL;
}
......
......@@ -1123,7 +1123,6 @@ static block_t *PacketizeStreamBlock(decoder_t *p_dec, block_t **pp_block)
p_out_buffer = block_Alloc(p_sys->i_frame_size);
if (!p_out_buffer) {
//p_dec->b_error = true;
return NULL;
}
p_buf = p_out_buffer->p_buffer;
......
......@@ -535,7 +535,6 @@ static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
case STATE_SEND_DATA:
if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
{
//p_dec->b_error = true;
return NULL;
}
......
......@@ -117,6 +117,8 @@ struct decoder_owner_sys_t
unsigned frames_countdown;
bool paused;
bool error;
/* Waiting */
bool b_waiting;
bool b_first;
......@@ -198,7 +200,6 @@ static void UnloadDecoder( decoder_t *p_dec )
es_format_Clean( &p_dec->fmt_in );
es_format_Clean( &p_dec->fmt_out );
p_dec->b_error = false;
}
static int ReloadDecoder( decoder_t *p_dec, bool b_packetizer,
......@@ -209,12 +210,13 @@ static int ReloadDecoder( decoder_t *p_dec, bool b_packetizer,
es_format_Init( &fmt_in, UNKNOWN_ES, 0 );
if( es_format_Copy( &fmt_in, p_fmt ) != VLC_SUCCESS )
{
p_dec->b_error = true;
p_dec->p_owner->error = true;
return VLC_EGENERIC;
}
/* Restart the decoder module */
UnloadDecoder( p_dec );
p_dec->p_owner->error = false;
if( reload == RELOAD_DECODER_AOUT )
{
......@@ -234,7 +236,7 @@ static int ReloadDecoder( decoder_t *p_dec, bool b_packetizer,
if( LoadDecoder( p_dec, b_packetizer, &fmt_in ) )
{
p_dec->b_error = true;
p_dec->p_owner->error = true;
es_format_Clean( &fmt_in );
return VLC_EGENERIC;
}
......@@ -513,7 +515,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
while( i_attempts-- )
{
if( p_dec->b_error )
if( p_owner->error )
break;
p_vout = input_resource_HoldVout( p_owner->p_resource );
......@@ -817,7 +819,7 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
{
msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
(char *)&p_owner->fmt.i_codec );
p_dec->b_error = true;
p_owner->error = true;
if(p_block)
block_Release(p_block);
......@@ -837,7 +839,7 @@ static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
{
msg_Err( p_dec, "cannot continue streaming due to errors" );
p_dec->b_error = true;
p_owner->error = true;
/* Cleanup */
......@@ -1253,6 +1255,9 @@ static void DecoderDecode( decoder_t *p_dec, block_t *p_block )
case VLCDEC_SUCCESS:
p_owner->pf_update_stat( p_owner, 1, 0 );
break;
case VLCDEC_ECRITICAL:
p_owner->error = true;
break;
default:
vlc_assert_unreachable();
}
......@@ -1268,7 +1273,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
{
decoder_owner_sys_t *p_owner = p_dec->p_owner;
if( p_dec->b_error )
if( p_owner->error )
goto error;
/* Here, the atomic doesn't prevent to miss a reload request.
......@@ -1336,7 +1341,7 @@ static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
p_packetized_block->p_next = NULL;
DecoderDecode( p_dec, p_packetized_block );
if( p_dec->b_error )
if( p_owner->error )
{
block_ChainRelease( p_next );
return;
......@@ -1363,7 +1368,7 @@ static void DecoderProcessFlush( decoder_t *p_dec )
decoder_owner_sys_t *p_owner = p_dec->p_owner;
decoder_t *p_packetizer = p_owner->p_packetizer;
if( p_dec->b_error )
if( p_owner->error )
return;
if( p_packetizer != NULL && p_packetizer->pf_flush != NULL )
......@@ -1569,6 +1574,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_owner->b_first = true;
p_owner->b_has_data = false;
p_owner->error = false;
p_owner->flushing = false;
p_owner->b_draining = false;
atomic_init( &p_owner->drained, false );
......
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