Ejemplo n.º 1
0
static int Audio_OnNewBlock(decoder_t *p_dec, block_t *p_block)
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED))
    {
        if (DecodeFlush(p_dec) != VLC_SUCCESS)
            return -1;
        date_Set(&p_sys->u.audio.i_end_date, VLC_TS_INVALID);
        return 0;
    }

    /* We've just started the stream, wait for the first PTS. */
    if (!date_Get(&p_sys->u.audio.i_end_date))
    {
        if (p_block->i_pts <= VLC_TS_INVALID)
            return 0;
        date_Set(&p_sys->u.audio.i_end_date, p_block->i_pts);
    }

    /* try delayed opening if there is a new extra data */
    if (!p_sys->api->b_started)
    {
        bool b_delayed_start = false;

        switch (p_dec->fmt_in.i_codec)
        {
        case VLC_CODEC_VORBIS:
        case VLC_CODEC_MP4A:
            if (p_dec->fmt_in.i_extra)
                b_delayed_start = true;
        default:
            break;
        }
        if (!p_dec->p_sys->u.audio.i_channels && p_dec->fmt_in.audio.i_channels)
        {
            p_dec->p_sys->u.audio.i_channels = p_dec->fmt_in.audio.i_channels;
            b_delayed_start = true;
        }

        if (b_delayed_start && !p_dec->p_sys->u.audio.i_channels
         && p_sys->u.audio.b_need_channels)
            b_delayed_start = false;

        if (b_delayed_start && StartMediaCodec(p_dec) != VLC_SUCCESS)
            return -1;
        if (!p_sys->api->b_started)
            return 0;
    }
    return 1;
}
Ejemplo n.º 2
0
/*****************************************************************************
 * OpenDecoder: Create the decoder instance
 *****************************************************************************/
static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
{
    decoder_t *p_dec = (decoder_t *)p_this;
    decoder_sys_t *p_sys;
    mc_api *api;
    const char *mime = NULL;

    /* Video or Audio if "mediacodec-audio" bool is true */
    if (p_dec->fmt_in.i_cat != VIDEO_ES && (p_dec->fmt_in.i_cat != AUDIO_ES
     || !var_InheritBool(p_dec, CFG_PREFIX "audio")))
        return VLC_EGENERIC;

    if (p_dec->fmt_in.i_cat == VIDEO_ES)
    {
        if (!p_dec->fmt_in.video.i_width || !p_dec->fmt_in.video.i_height)
        {
            /* We can handle h264 without a valid video size */
            if (p_dec->fmt_in.i_codec != VLC_CODEC_H264)
            {
                msg_Dbg(p_dec, "resolution (%dx%d) not supported",
                        p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height);
                return VLC_EGENERIC;
            }
        }

        switch (p_dec->fmt_in.i_codec) {
        case VLC_CODEC_HEVC: mime = "video/hevc"; break;
        case VLC_CODEC_H264: mime = "video/avc"; break;
        case VLC_CODEC_H263: mime = "video/3gpp"; break;
        case VLC_CODEC_MP4V: mime = "video/mp4v-es"; break;
        case VLC_CODEC_WMV3: mime = "video/x-ms-wmv"; break;
        case VLC_CODEC_VC1:  mime = "video/wvc1"; break;
        case VLC_CODEC_VP8:  mime = "video/x-vnd.on2.vp8"; break;
        case VLC_CODEC_VP9:  mime = "video/x-vnd.on2.vp9"; break;
        /* case VLC_CODEC_MPGV: mime = "video/mpeg2"; break; */
        }
    }
    else
    {
        switch (p_dec->fmt_in.i_codec) {
        case VLC_CODEC_AMR_NB: mime = "audio/3gpp"; break;
        case VLC_CODEC_AMR_WB: mime = "audio/amr-wb"; break;
        case VLC_CODEC_MPGA:
        case VLC_CODEC_MP3:    mime = "audio/mpeg"; break;
        case VLC_CODEC_MP2:    mime = "audio/mpeg-L2"; break;
        case VLC_CODEC_MP4A:   mime = "audio/mp4a-latm"; break;
        case VLC_CODEC_QCELP:  mime = "audio/qcelp"; break;
        case VLC_CODEC_VORBIS: mime = "audio/vorbis"; break;
        case VLC_CODEC_OPUS:   mime = "audio/opus"; break;
        case VLC_CODEC_ALAW:   mime = "audio/g711-alaw"; break;
        case VLC_CODEC_MULAW:  mime = "audio/g711-mlaw"; break;
        case VLC_CODEC_FLAC:   mime = "audio/flac"; break;
        case VLC_CODEC_GSM:    mime = "audio/gsm"; break;
        case VLC_CODEC_A52:    mime = "audio/ac3"; break;
        case VLC_CODEC_EAC3:   mime = "audio/eac3"; break;
        case VLC_CODEC_ALAC:   mime = "audio/alac"; break;
        case VLC_CODEC_DTS:    mime = "audio/vnd.dts"; break;
        /* case VLC_CODEC_: mime = "audio/mpeg-L1"; break; */
        /* case VLC_CODEC_: mime = "audio/aac-adts"; break; */
        }
    }
    if (!mime)
    {
        msg_Dbg(p_dec, "codec %4.4s not supported",
                (char *)&p_dec->fmt_in.i_codec);
        return VLC_EGENERIC;
    }

    api = calloc(1, sizeof(mc_api));
    if (!api)
        return VLC_ENOMEM;
    api->p_obj = p_this;
    api->b_video = p_dec->fmt_in.i_cat == VIDEO_ES;
    if (pf_init(api) != VLC_SUCCESS)
    {
        free(api);
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if ((p_sys = calloc(1, sizeof(*p_sys))) == NULL)
    {
        api->clean(api);
        free(api);
        return VLC_ENOMEM;
    }
    p_sys->api = api;
    p_dec->p_sys = p_sys;

    p_dec->pf_decode_video = DecodeVideo;
    p_dec->pf_decode_audio = DecodeAudio;

    p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
    p_dec->fmt_out.video = p_dec->fmt_in.video;
    p_dec->fmt_out.audio = p_dec->fmt_in.audio;
    p_dec->b_need_packetized = true;
    p_sys->mime = mime;
    p_sys->b_new_block = true;

    if (p_dec->fmt_in.i_cat == VIDEO_ES)
    {
        p_sys->u.video.i_width = p_dec->fmt_in.video.i_width;
        p_sys->u.video.i_height = p_dec->fmt_in.video.i_height;

        p_sys->u.video.timestamp_fifo = timestamp_FifoNew(32);
        if (!p_sys->u.video.timestamp_fifo)
        {
            CloseDecoder(p_this);
            return VLC_ENOMEM;
        }

        if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
            h264_get_profile_level(&p_dec->fmt_in,
                                   &p_sys->u.video.i_h264_profile, NULL, NULL);

        p_sys->psz_name = MediaCodec_GetName(VLC_OBJECT(p_dec), p_sys->mime,
                                              p_sys->u.video.i_h264_profile);
        if (!p_sys->psz_name)
        {
            CloseDecoder(p_this);
            return VLC_EGENERIC;
        }

        /* Check if we need late opening */
        switch (p_dec->fmt_in.i_codec)
        {
        case VLC_CODEC_H264:
            if (!p_sys->u.video.i_width || !p_sys->u.video.i_height)
            {
                msg_Warn(p_dec, "waiting for sps/pps for codec %4.4s",
                         (const char *)&p_dec->fmt_in.i_codec);
                return VLC_SUCCESS;
            }
        case VLC_CODEC_VC1:
            if (!p_dec->fmt_in.i_extra)
            {
                msg_Warn(p_dec, "waiting for extra data for codec %4.4s",
                         (const char *)&p_dec->fmt_in.i_codec);
                return VLC_SUCCESS;
            }
            break;
        }
    }
    else
    {
        p_sys->u.audio.i_channels = p_dec->fmt_in.audio.i_channels;

        p_sys->psz_name = MediaCodec_GetName(VLC_OBJECT(p_dec), p_sys->mime, 0);
        if (!p_sys->psz_name)
        {
            CloseDecoder(p_this);
            return VLC_EGENERIC;
        }

        /* Marvel ACodec assert if channel count is 0 */
        if (!strncmp(p_sys->psz_name, "OMX.Marvell",
                     __MIN(strlen(p_sys->psz_name), strlen("OMX.Marvell"))))
            p_sys->u.audio.b_need_channels = true;

        /* Check if we need late opening */
        switch (p_dec->fmt_in.i_codec)
        {
        case VLC_CODEC_VORBIS:
        case VLC_CODEC_MP4A:
            if (!p_dec->fmt_in.i_extra)
            {
                msg_Warn(p_dec, "waiting for extra data for codec %4.4s",
                         (const char *)&p_dec->fmt_in.i_codec);
                return VLC_SUCCESS;
            }
            break;
        }
        if (!p_sys->u.audio.i_channels && p_sys->u.audio.b_need_channels)
        {
            msg_Warn(p_dec, "waiting for valid channel count");
            return VLC_SUCCESS;
        }
    }

    return StartMediaCodec(p_dec);
}
Ejemplo n.º 3
0
/*****************************************************************************
 * OpenDecoder: Create the decoder instance
 *****************************************************************************/
static int OpenDecoder(vlc_object_t *p_this, pf_MediaCodecApi_init pf_init)
{
    decoder_t *p_dec = (decoder_t *)p_this;
    decoder_sys_t *p_sys;
    mc_api *api;
    const char *mime = NULL;

    /* Video or Audio if "mediacodec-audio" bool is true */
    if (p_dec->fmt_in.i_cat != VIDEO_ES && (p_dec->fmt_in.i_cat != AUDIO_ES
     || !var_InheritBool(p_dec, CFG_PREFIX "audio")))
        return VLC_EGENERIC;

    if (p_dec->fmt_in.i_cat == VIDEO_ES)
    {
        if (!p_dec->fmt_in.video.i_width || !p_dec->fmt_in.video.i_height)
        {
            /* We can handle h264 without a valid video size */
            if (p_dec->fmt_in.i_codec != VLC_CODEC_H264)
            {
                msg_Dbg(p_dec, "resolution (%dx%d) not supported",
                        p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height);
                return VLC_EGENERIC;
            }
        }

        switch (p_dec->fmt_in.i_codec) {
        case VLC_CODEC_HEVC: mime = "video/hevc"; break;
        case VLC_CODEC_H264: mime = "video/avc"; break;
        case VLC_CODEC_H263: mime = "video/3gpp"; break;
        case VLC_CODEC_MP4V: mime = "video/mp4v-es"; break;
        case VLC_CODEC_WMV3: mime = "video/x-ms-wmv"; break;
        case VLC_CODEC_VC1:  mime = "video/wvc1"; break;
        case VLC_CODEC_VP8:  mime = "video/x-vnd.on2.vp8"; break;
        case VLC_CODEC_VP9:  mime = "video/x-vnd.on2.vp9"; break;
        /* case VLC_CODEC_MPGV: mime = "video/mpeg2"; break; */
        }
    }
    else
    {
        switch (p_dec->fmt_in.i_codec) {
        case VLC_CODEC_AMR_NB: mime = "audio/3gpp"; break;
        case VLC_CODEC_AMR_WB: mime = "audio/amr-wb"; break;
        case VLC_CODEC_MPGA:
        case VLC_CODEC_MP3:    mime = "audio/mpeg"; break;
        case VLC_CODEC_MP2:    mime = "audio/mpeg-L2"; break;
        case VLC_CODEC_MP4A:   mime = "audio/mp4a-latm"; break;
        case VLC_CODEC_QCELP:  mime = "audio/qcelp"; break;
        case VLC_CODEC_VORBIS: mime = "audio/vorbis"; break;
        case VLC_CODEC_OPUS:   mime = "audio/opus"; break;
        case VLC_CODEC_ALAW:   mime = "audio/g711-alaw"; break;
        case VLC_CODEC_MULAW:  mime = "audio/g711-mlaw"; break;
        case VLC_CODEC_FLAC:   mime = "audio/flac"; break;
        case VLC_CODEC_GSM:    mime = "audio/gsm"; break;
        case VLC_CODEC_A52:    mime = "audio/ac3"; break;
        case VLC_CODEC_EAC3:   mime = "audio/eac3"; break;
        case VLC_CODEC_ALAC:   mime = "audio/alac"; break;
        case VLC_CODEC_DTS:    mime = "audio/vnd.dts"; break;
        /* case VLC_CODEC_: mime = "audio/mpeg-L1"; break; */
        /* case VLC_CODEC_: mime = "audio/aac-adts"; break; */
        }
    }
    if (!mime)
    {
        msg_Dbg(p_dec, "codec %4.4s not supported",
                (char *)&p_dec->fmt_in.i_codec);
        return VLC_EGENERIC;
    }

    api = calloc(1, sizeof(mc_api));
    if (!api)
        return VLC_ENOMEM;
    api->p_obj = p_this;
    api->b_video = p_dec->fmt_in.i_cat == VIDEO_ES;
    if (pf_init(api) != VLC_SUCCESS)
    {
        free(api);
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    if ((p_sys = calloc(1, sizeof(*p_sys))) == NULL)
    {
        api->clean(api);
        free(api);
        return VLC_ENOMEM;
    }
    p_sys->api = api;
    p_dec->p_sys = p_sys;

    p_dec->pf_decode_video = DecodeVideo;
    p_dec->pf_decode_audio = DecodeAudio;

    p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
    p_dec->fmt_out.video = p_dec->fmt_in.video;
    p_dec->fmt_out.audio = p_dec->fmt_in.audio;
    p_dec->b_need_packetized = true;
    p_sys->mime = mime;
    p_sys->b_new_block = true;

    if (p_dec->fmt_in.i_cat == VIDEO_ES)
    {
        p_sys->pf_on_new_block = Video_OnNewBlock;
        p_sys->pf_on_flush = Video_OnFlush;
        p_sys->pf_process_output = Video_ProcessOutput;
        p_sys->u.video.i_width = p_dec->fmt_in.video.i_width;
        p_sys->u.video.i_height = p_dec->fmt_in.video.i_height;

        p_sys->u.video.timestamp_fifo = timestamp_FifoNew(32);
        if (!p_sys->u.video.timestamp_fifo)
            goto bailout;

        if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
            h264_get_profile_level(&p_dec->fmt_in,
                                   &p_sys->u.video.i_h264_profile, NULL, NULL);

        p_sys->psz_name = MediaCodec_GetName(VLC_OBJECT(p_dec), p_sys->mime,
                                              p_sys->u.video.i_h264_profile);
        if (!p_sys->psz_name)
            goto bailout;

        p_sys->i_quirks = OMXCodec_GetQuirks( VIDEO_ES,
                                              p_dec->fmt_in.i_codec,
                                              p_sys->psz_name,
                                              strlen(p_sys->psz_name) );

        if ((p_sys->i_quirks & OMXCODEC_VIDEO_QUIRKS_NEED_SIZE)
         && (!p_sys->u.video.i_width || !p_sys->u.video.i_height))
        {
            msg_Warn(p_dec, "waiting for a valid video size for codec %4.4s",
                     (const char *)&p_dec->fmt_in.i_codec);
            return VLC_SUCCESS;
        }
    }
    else
    {
        p_sys->pf_on_new_block = Audio_OnNewBlock;
        p_sys->pf_on_flush = Audio_OnFlush;
        p_sys->pf_process_output = Audio_ProcessOutput;
        p_sys->u.audio.i_channels = p_dec->fmt_in.audio.i_channels;

        p_sys->psz_name = MediaCodec_GetName(VLC_OBJECT(p_dec), p_sys->mime, 0);
        if (!p_sys->psz_name)
            goto bailout;

        p_sys->i_quirks = OMXCodec_GetQuirks( AUDIO_ES,
                                              p_dec->fmt_in.i_codec,
                                              p_sys->psz_name,
                                              strlen(p_sys->psz_name) );
        if ((p_sys->i_quirks & OMXCODEC_AUDIO_QUIRKS_NEED_CHANNELS)
         && !p_sys->u.audio.i_channels)
        {
            msg_Warn(p_dec, "waiting for valid channel count");
            return VLC_SUCCESS;
        }
    }
    if ((p_sys->i_quirks & OMXCODEC_QUIRKS_NEED_CSD)
     && !p_dec->fmt_in.i_extra)
    {
        msg_Warn(p_dec, "waiting for extra data for codec %4.4s",
                 (const char *)&p_dec->fmt_in.i_codec);
        if (p_dec->fmt_in.i_codec == VLC_CODEC_MP4V)
        {
            msg_Warn(p_dec, "late opening with MPEG4 not handled"); /* TODO */
            goto bailout;
        }
        return VLC_SUCCESS;
    }

    if (StartMediaCodec(p_dec) == VLC_SUCCESS)
        return VLC_SUCCESS;
    else
        msg_Err(p_dec, "StartMediaCodec failed");
bailout:
    CloseDecoder(p_this);
    return VLC_EGENERIC;
}
Ejemplo n.º 4
0
static int Video_OnNewBlock(decoder_t *p_dec, block_t *p_block)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    bool b_csd_changed = false, b_size_changed = false;
    bool b_delayed_start = false;

    if (p_block->i_flags & BLOCK_FLAG_INTERLACED_MASK
        && !p_sys->api->b_support_interlaced)
        return -1;

    if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED))
    {
        if (p_sys->decoded)
        {
            timestamp_FifoEmpty(p_sys->u.video.timestamp_fifo);
            /* Invalidate all pictures that are currently in flight
             * since flushing make all previous indices returned by
             * MediaCodec invalid. */
            if (p_sys->api->b_direct_rendering)
                InvalidateAllPictures(p_dec);
        }

        if (DecodeFlush(p_dec) != VLC_SUCCESS)
            return -1;
        return 0;
    }

    if (p_dec->fmt_in.i_codec == VLC_CODEC_H264)
        H264ProcessBlock(p_dec, p_block, &b_csd_changed, &b_size_changed);
    else if (p_dec->fmt_in.i_codec == VLC_CODEC_HEVC)
        HEVCProcessBlock(p_dec, p_block, &b_csd_changed, &b_size_changed);

    if (p_sys->api->b_started && b_csd_changed)
    {
        if (b_size_changed)
        {
            msg_Err(p_dec, "SPS/PPS changed during playback and "
                    "video size are different. Restart it !");
            StopMediaCodec(p_dec);
        } else
        {
            msg_Err(p_dec, "SPS/PPS changed during playback. Flush it");
            if (DecodeFlush(p_dec) != VLC_SUCCESS)
                return -1;
        }
    }

    if (b_csd_changed)
        b_delayed_start = true;

    /* try delayed opening if there is a new extra data */
    if (!p_sys->api->b_started)
    {
        switch (p_dec->fmt_in.i_codec)
        {
        case VLC_CODEC_VC1:
            if (p_dec->fmt_in.i_extra)
                b_delayed_start = true;
        default:
            break;
        }
        if (b_delayed_start && StartMediaCodec(p_dec) != VLC_SUCCESS)
            return -1;
        if (!p_sys->api->b_started)
            return 0;
    }

    timestamp_FifoPut(p_sys->u.video.timestamp_fifo,
                      p_block->i_pts ? VLC_TS_INVALID : p_block->i_dts);
    return 1;
}
Ejemplo n.º 5
0
/**
 * DecodeCommon called from DecodeVideo or DecodeAudio.
 * It returns -1 in case of error, 0 otherwise. The output buffer is returned
 * in pp_out_pic for Video, and pp_out_block for Audio.
 */
static int DecodeCommon(decoder_t *p_dec, block_t **pp_block,
                        picture_t **pp_out_pic, block_t **pp_out_block)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block = pp_block ? *pp_block : NULL;
    unsigned int i_attempts = 0;
    jlong timeout = 0;
    int i_output_ret = 0;
    int i_input_ret = 0;
    bool b_abort = false;
    bool b_error = false;
    bool b_new_block = p_block ? p_sys->b_new_block : false;

    if (p_sys->error_state)
        goto endclean;

    if (b_new_block)
    {
        int i_ret, i_flags = 0;

        p_sys->b_new_block = false;

        if (p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED))
        {
            if (DecodeFlush(p_dec) != VLC_SUCCESS)
                b_error = true;
            goto endclean;
        }

        i_ret = p_sys->pf_on_new_block(p_dec, p_block, &i_flags);
        if (i_ret != 1)
        {
            if (i_ret == -1)
                b_error = true;
            goto endclean;
        }
        if (i_flags & NEWBLOCK_FLAG_FLUSH)
        {
            if (DecodeFlush(p_dec) != VLC_SUCCESS)
            {
                b_error = true;
                goto endclean;
            }
        }

        if (i_flags & NEWBLOCK_FLAG_RESTART)
        {
            StopMediaCodec(p_dec);
            if (StartMediaCodec(p_dec) != VLC_SUCCESS)
            {
                b_error = true;
                goto endclean;
            }
        }
    }
    if (!p_sys->api->b_started)
        goto endclean;

    do
    {
        if ((p_sys->i_csd_send < p_sys->i_csd_count || p_block)
         && i_input_ret == 0)
        {
            int i_index = p_sys->api->dequeue_in(p_sys->api, timeout);

            if (i_index >= 0)
            {
                block_t *p_in_block;
                mtime_t i_ts;

                if (p_sys->i_csd_send < p_sys->i_csd_count)
                {
                    p_in_block = p_sys->pp_csd[p_sys->i_csd_send];
                    i_ts = 0;
                }
                else
                {
                    p_in_block = p_block;
                    i_ts = p_block->i_pts;
                    if (!i_ts && p_block->i_dts)
                        i_ts = p_block->i_dts;
                }
                i_input_ret = p_sys->api->queue_in(p_sys->api, i_index,
                                                   p_in_block->p_buffer,
                                                   p_in_block->i_buffer, i_ts,
                                                   p_in_block->i_flags & BLOCK_FLAG_CSD) == 0 ? 1 : -1;
                if (i_input_ret == 1)
                {
                    if (p_sys->i_csd_send < p_sys->i_csd_count)
                    {
                        p_sys->i_csd_send++;
                        i_input_ret = 0;
                    }
                    else
                    {
                        p_sys->decoded = true;
                        if (p_block->i_flags & BLOCK_FLAG_PREROLL )
                            p_sys->i_preroll_end = i_ts;
                    }
                }
            }
            else if (i_index == MC_API_INFO_TRYAGAIN)
                i_input_ret = 0;
            else
                i_input_ret = -1;

            /* No need to try output if no input buffer is decoded */
            if (!p_sys->decoded)
                continue;
        }

        if (i_input_ret != -1 && p_sys->decoded && i_output_ret == 0)
        {
            i_output_ret = GetAndProcessOutput(p_dec, pp_out_pic, pp_out_block,
                                               timeout);

            if (i_output_ret == 0 && i_input_ret == 0)
            {
                if (++i_attempts == 20)
                {
                    /* HACK: When direct rendering is enabled, there is a
                     * possible deadlock between the Decoder and the Vout. It
                     * happens when the Vout is paused and when the Decoder is
                     * flushing. In that case, the Vout won't release any
                     * output buffers, therefore MediaCodec won't dequeue any
                     * input buffers. To work around this issue, release all
                     * output buffers if DecodeCommon is waiting more than 400
                     * msec for a new input buffer. */ 
                    msg_Warn(p_dec, "Decoder stuck: invalidate all buffers");
                    InvalidateAllPictures(p_dec);
                }
                if (!p_sys->b_has_format && ++i_attempts > 100)
                {
                    /* No output and no format, thereforce mediacodec didn't
                     * produce any output or events yet. Don't wait
                     * indefinitely and abort after 2seconds (100 * 2 * 10ms)
                     * without any data.  Indeed, MediaCodec can fail without
                     * throwing any exception or error returns... */
                    msg_Err(p_dec, "No output/input for %lld ms, abort",
                                    i_attempts * timeout);
                    b_error = true;
                    break;
                }
            }
        }
        timeout = 10 * 1000; // 10 ms
        /* loop until either the input or the output are processed (i_input_ret
         * or i_output_ret == 1 ) or caused an error (i_input_ret or
         * i_output_ret == -1 )*/
    } while (p_block && i_input_ret == 0 && i_output_ret == 0 && !b_abort);

    if (i_input_ret == -1 || i_output_ret == -1)
    {
        msg_Err(p_dec, "%s failed",
                i_input_ret == -1 ? "PutInput" : "GetOutput");
        b_error = true;
    }

endclean:

    /* If pf_decode returns NULL, we'll get a new p_block from the next
     * pf_decode call. Therefore we need to release the current one even if we
     * couldn't process it (it happens in case or error or if MediaCodec is
     * still not opened). We also must release the current p_block if we were
     * able to process it. */
    if (p_block && (i_output_ret != 1 || i_input_ret != 0))
    {
        block_Release(p_block);
        *pp_block = NULL;
        p_sys->b_new_block = true;
    }
    if (b_error && !p_sys->error_state) {
        /* Signal the error to the Java. */
        jni_EventHardwareAccelerationError();
        p_sys->error_state = true;
    }

    return b_error ? -1 : 0;
}