[FFmpeg-devel] [PATCH 12/13] avcodec/omx: Check initializing mutexes/conditions

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Fri Sep 3 10:03:43 EEST 2021


Steve Lhomme:
> On 2021-09-02 17:41, Andreas Rheinhardt wrote:
>> The earlier code did not properly check these initializations:
>> It only recorded whether the part of init where these initializations
>> are has been reached, but it did not check whether the initializations
>> were successful, although destroying them would be undefined behaviour
>> if they had not been initialized successfully.
>> Furthermore cleanup() always locked a mutex regardless of whether there
>> was any attempt to initialize these mutexes at all.
>>
>> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
>> ---
>> This is mostly untested: I only tested whether it compiles.
>>
>>   libavcodec/omx.c | 34 +++++++++++++++++-----------------
>>   1 file changed, 17 insertions(+), 17 deletions(-)
>>
>> diff --git a/libavcodec/omx.c b/libavcodec/omx.c
>> index 9597c60057..7086ddd3a4 100644
>> --- a/libavcodec/omx.c
>> +++ b/libavcodec/omx.c
>> @@ -43,6 +43,7 @@
>>   #include "avcodec.h"
>>   #include "h264.h"
>>   #include "internal.h"
>> +#include "pthread_internal.h"
>>     #ifdef OMX_SKIP64BIT
>>   static OMX_TICKS to_omx_ticks(int64_t value)
>> @@ -218,7 +219,7 @@ typedef struct OMXCodecContext {
>>       OMX_STATETYPE state;
>>       OMX_ERRORTYPE error;
>>   -    int mutex_cond_inited;
>> +    unsigned mutex_cond_inited_cnt;
>>         int eos_sent, got_eos;
>>   @@ -229,6 +230,12 @@ typedef struct OMXCodecContext {
>>       int profile;
>>   } OMXCodecContext;
>>   +#define NB_MUTEX_CONDS 6
>> +#define OFF(field) offsetof(OMXCodecContext, field)
>> +DEFINE_OFFSET_ARRAY(OMXCodecContext, omx_codec_context,
>> mutex_cond_inited_cnt,
>> +                    (OFF(input_mutex), OFF(output_mutex),
>> OFF(state_mutex)),
>> +                    (OFF(input_cond),  OFF(output_cond), 
>> OFF(state_cond)));
>> +
>>   static void append_buffer(pthread_mutex_t *mutex, pthread_cond_t *cond,
>>                             int* array_size, OMX_BUFFERHEADERTYPE
>> **array,
>>                             OMX_BUFFERHEADERTYPE *buffer)
>> @@ -591,6 +598,9 @@ static av_cold void cleanup(OMXCodecContext *s)
>>   {
>>       int i, executing;
>>   +    /* If the mutexes/condition variables have not been properly
>> initialized,
>> +     * nothing has been initialized and locking the mutex might be
>> unsafe. */
>> +    if (s->mutex_cond_inited_cnt == NB_MUTEX_CONDS) {
>>       pthread_mutex_lock(&s->state_mutex);
>>       executing = s->state == OMX_StateExecuting;
>>       pthread_mutex_unlock(&s->state_mutex);
>> @@ -620,20 +630,13 @@ static av_cold void cleanup(OMXCodecContext *s)
>>         omx_deinit(s->omx_context);
>>       s->omx_context = NULL;
>> -    if (s->mutex_cond_inited) {
>> -        pthread_cond_destroy(&s->state_cond);
>> -        pthread_mutex_destroy(&s->state_mutex);
>> -        pthread_cond_destroy(&s->input_cond);
>> -        pthread_mutex_destroy(&s->input_mutex);
>> -        pthread_cond_destroy(&s->output_cond);
>> -        pthread_mutex_destroy(&s->output_mutex);
>> -        s->mutex_cond_inited = 0;
>> -    }
>>       av_freep(&s->in_buffer_headers);
>>       av_freep(&s->out_buffer_headers);
>>       av_freep(&s->free_in_buffers);
>>       av_freep(&s->done_out_buffers);
>>       av_freep(&s->output_buf);
>> +    }
>> +    ff_pthread_free(s, omx_codec_context_offsets);
>>   }
>>     static av_cold int omx_encode_init(AVCodecContext *avctx)
>> @@ -644,17 +647,14 @@ static av_cold int
>> omx_encode_init(AVCodecContext *avctx)
>>       OMX_BUFFERHEADERTYPE *buffer;
>>       OMX_ERRORTYPE err;
>>   +    /* cleanup relies on the mutexes/conditions being initialized
>> first. */
>> +    ret = ff_pthread_init(s, omx_codec_context_offsets);
>> +    if (ret < 0)
>> +        return ret;
>>       s->omx_context = omx_init(avctx, s->libname, s->libprefix);
>>       if (!s->omx_context)
> 
> Shouldn't you call ff_pthread_free() here ?
> 
These encoders have the FF_CODEC_CAP_INIT_CLEANUP set which means that
omx_encode_end() will be called automatically if omx_encode_init()
fails. (This is why the current code always locked the state_mutex
regardless of whether its initialization has ever been reached.)

- Andreas


More information about the ffmpeg-devel mailing list