static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)

{

    MMALDecodeContext *ctx = avctx->priv_data;

    MMAL_BUFFER_HEADER_T *buffer = NULL;

    MMAL_STATUS_T status = 0;

    int ret = 0;



    if (ctx->eos_received)

        goto done;



    while (1) {

        // To ensure decoding in lockstep with a constant delay between fed packets

        // and output frames, we always wait until an output buffer is available.

        // Except during start we don't know after how many input packets the decoder

        // is going to return the first buffer, and we can't distinguish decoder

        // being busy from decoder waiting for input. So just poll at the start and

        // keep feeding new data to the buffer.

        // We are pretty sure the decoder will produce output if we sent more input

        // frames than what a h264 decoder could logically delay. This avoids too

        // excessive buffering.

        // We also wait if we sent eos, but didn't receive it yet (think of decoding

        // stream with a very low number of frames).

        if (ctx->frames_output || ctx->packets_sent > MAX_DELAYED_FRAMES || ctx->eos_sent) {

            buffer = mmal_queue_wait(ctx->queue_decoded_frames);

        } else {

            buffer = mmal_queue_get(ctx->queue_decoded_frames);

        }

        if (!buffer)

            goto done;



        ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS);

        if (ctx->eos_received)

            goto done;



        if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {

            MMAL_COMPONENT_T *decoder = ctx->decoder;

            MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer);

            MMAL_BUFFER_HEADER_T *stale_buffer;



            av_log(avctx, AV_LOG_INFO, "Changing output format.\n");



            if ((status = mmal_port_disable(decoder->output[0])))

                goto done;



            while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames)))

                mmal_buffer_header_release(stale_buffer);



            mmal_format_copy(decoder->output[0]->format, ev->format);



            if ((ret = ffmal_update_format(avctx)) < 0)

                goto done;



            if ((status = mmal_port_enable(decoder->output[0], output_callback)))

                goto done;



            if ((ret = ffmmal_fill_output_port(avctx)) < 0)

                goto done;



            if ((ret = ffmmal_fill_input_port(avctx)) < 0)

                goto done;



            mmal_buffer_header_release(buffer);

            continue;

        } else if (buffer->cmd) {

            char s[20];

            av_get_codec_tag_string(s, sizeof(s), buffer->cmd);

            av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on output port\n", s);

            goto done;

        } else if (buffer->length == 0) {

            // Unused output buffer that got drained after format change.

            mmal_buffer_header_release(buffer);

            continue;

        }



        ctx->frames_output++;



        if ((ret = ffmal_copy_frame(avctx, frame, buffer)) < 0)

            goto done;



        *got_frame = 1;

        break;

    }



done:

    if (buffer)

        mmal_buffer_header_release(buffer);

    if (status && ret >= 0)

        ret = AVERROR_UNKNOWN;

    return ret;

}

static int ffmmal_read_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame)

{

    MMALDecodeContext *ctx = avctx->priv_data;

    MMAL_BUFFER_HEADER_T *buffer = NULL;

    MMAL_STATUS_T status = 0;

    int ret = 0;



    if (ctx->eos_received)

        goto done;



    while (1) {

        

        

        

        

        

        

        

        

        

        

        

        if (ctx->frames_output || ctx->packets_sent > MAX_DELAYED_FRAMES || ctx->eos_sent) {

            buffer = mmal_queue_wait(ctx->queue_decoded_frames);

        } else {

            buffer = mmal_queue_get(ctx->queue_decoded_frames);

        }

        if (!buffer)

            goto done;



        ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS);

        if (ctx->eos_received)

            goto done;



        if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {

            MMAL_COMPONENT_T *decoder = ctx->decoder;

            MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer);

            MMAL_BUFFER_HEADER_T *stale_buffer;



            av_log(avctx, AV_LOG_INFO, "Changing output format.\n");



            if ((status = mmal_port_disable(decoder->output[0])))

                goto done;



            while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames)))

                mmal_buffer_header_release(stale_buffer);



            mmal_format_copy(decoder->output[0]->format, ev->format);



            if ((ret = ffmal_update_format(avctx)) < 0)

                goto done;



            if ((status = mmal_port_enable(decoder->output[0], output_callback)))

                goto done;



            if ((ret = ffmmal_fill_output_port(avctx)) < 0)

                goto done;



            if ((ret = ffmmal_fill_input_port(avctx)) < 0)

                goto done;



            mmal_buffer_header_release(buffer);

            continue;

        } else if (buffer->cmd) {

            char s[20];

            av_get_codec_tag_string(s, sizeof(s), buffer->cmd);

            av_log(avctx, AV_LOG_WARNING, "Unknown MMAL event %s on output port\n", s);

            goto done;

        } else if (buffer->length == 0) {

            

            mmal_buffer_header_release(buffer);

            continue;

        }



        ctx->frames_output++;



        if ((ret = ffmal_copy_frame(avctx, frame, buffer)) < 0)

            goto done;



        *got_frame = 1;

        break;

    }



done:

    if (buffer)

        mmal_buffer_header_release(buffer);

    if (status && ret >= 0)

        ret = AVERROR_UNKNOWN;

    return ret;

}

static int FUNC_0(AVCodecContext *VAR_0, AVFrame *VAR_1, int *VAR_2)

{

    MMALDecodeContext *ctx = VAR_0->priv_data;

    MMAL_BUFFER_HEADER_T *buffer = NULL;

    MMAL_STATUS_T status = 0;

    int VAR_3 = 0;



    if (ctx->eos_received)

        goto done;



    while (1) {

        

        

        

        

        

        

        

        

        

        

        

        if (ctx->frames_output || ctx->packets_sent > MAX_DELAYED_FRAMES || ctx->eos_sent) {

            buffer = mmal_queue_wait(ctx->queue_decoded_frames);

        } else {

            buffer = mmal_queue_get(ctx->queue_decoded_frames);

        }

        if (!buffer)

            goto done;



        ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS);

        if (ctx->eos_received)

            goto done;



        if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) {

            MMAL_COMPONENT_T *decoder = ctx->decoder;

            MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer);

            MMAL_BUFFER_HEADER_T *stale_buffer;



            av_log(VAR_0, AV_LOG_INFO, "Changing output format.\n");



            if ((status = mmal_port_disable(decoder->output[0])))

                goto done;



            while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames)))

                mmal_buffer_header_release(stale_buffer);



            mmal_format_copy(decoder->output[0]->format, ev->format);



            if ((VAR_3 = ffmal_update_format(VAR_0)) < 0)

                goto done;



            if ((status = mmal_port_enable(decoder->output[0], output_callback)))

                goto done;



            if ((VAR_3 = ffmmal_fill_output_port(VAR_0)) < 0)

                goto done;



            if ((VAR_3 = ffmmal_fill_input_port(VAR_0)) < 0)

                goto done;



            mmal_buffer_header_release(buffer);

            continue;

        } else if (buffer->cmd) {

            char VAR_4[20];

            av_get_codec_tag_string(VAR_4, sizeof(VAR_4), buffer->cmd);

            av_log(VAR_0, AV_LOG_WARNING, "Unknown MMAL event %VAR_4 on output port\n", VAR_4);

            goto done;

        } else if (buffer->length == 0) {

            

            mmal_buffer_header_release(buffer);

            continue;

        }



        ctx->frames_output++;



        if ((VAR_3 = ffmal_copy_frame(VAR_0, VAR_1, buffer)) < 0)

            goto done;



        *VAR_2 = 1;

        break;

    }



done:

    if (buffer)

        mmal_buffer_header_release(buffer);

    if (status && VAR_3 >= 0)

        VAR_3 = AVERROR_UNKNOWN;

    return VAR_3;

}

static int FUNC_0(AVCodecContext *VAR_0, AVFrame *VAR_1, int *VAR_2)
{ MMALDecodeContext *ctx = VAR_0->priv_data; MMAL_BUFFER_HEADER_T *buffer = NULL; MMAL_STATUS_T status = 0; int VAR_3 = 0; if (ctx->eos_received)
goto done; while (1) { if (ctx->frames_output || ctx->packets_sent > MAX_DELAYED_FRAMES || ctx->eos_sent) { buffer = mmal_queue_wait(ctx->queue_decoded_frames); } else { buffer = mmal_queue_get(ctx->queue_decoded_frames); } if (!buffer)
goto done; ctx->eos_received |= !!(buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS); if (ctx->eos_received)
goto done; if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) { MMAL_COMPONENT_T *decoder = ctx->decoder; MMAL_EVENT_FORMAT_CHANGED_T *ev = mmal_event_format_changed_get(buffer); MMAL_BUFFER_HEADER_T *stale_buffer; av_log(VAR_0, AV_LOG_INFO, "Changing output format.\n"); if ((status = mmal_port_disable(decoder->output[0])))
goto done; while ((stale_buffer = mmal_queue_get(ctx->queue_decoded_frames)))
mmal_buffer_header_release(stale_buffer); mmal_format_copy(decoder->output[0]->format, ev->format); if ((VAR_3 = ffmal_update_format(VAR_0)) < 0)
goto done; if ((status = mmal_port_enable(decoder->output[0], output_callback)))
goto done; if ((VAR_3 = ffmmal_fill_output_port(VAR_0)) < 0)
goto done; if ((VAR_3 = ffmmal_fill_input_port(VAR_0)) < 0)
goto done; mmal_buffer_header_release(buffer); continue; } else if (buffer->cmd) { char VAR_4[20]; av_get_codec_tag_string(VAR_4, sizeof(VAR_4), buffer->cmd); av_log(VAR_0, AV_LOG_WARNING, "Unknown MMAL event %VAR_4 on output port\n", VAR_4); goto done; } else if (buffer->length == 0) { mmal_buffer_header_release(buffer); continue; } ctx->frames_output++; if ((VAR_3 = ffmal_copy_frame(VAR_0, VAR_1, buffer)) < 0)
goto done; *VAR_2 = 1; break; } done:
if (buffer)
mmal_buffer_header_release(buffer); if (status && VAR_3 >= 0)
VAR_3 = AVERROR_UNKNOWN; return VAR_3; }